Skip to content

Commit

Permalink
Merge branch 'feature/24_refactor_galist' of https://github.com/s-mar…
Browse files Browse the repository at this point in the history
…tin/galib into feature/24_refactor_galist

# Conflicts:
#	test/CMakeLists.txt
  • Loading branch information
s-martin committed Nov 9, 2023
2 parents c21c549 + 500580a commit 800662e
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 41 deletions.
2 changes: 0 additions & 2 deletions ga/GAListBASE.C
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// $Header$
/* ----------------------------------------------------------------------------
listbase.C
mbwall 10dec94
Copyright 1995 Massachusetts Institute of Technology
Expand Down
60 changes: 37 additions & 23 deletions ga/GAListBASE.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// $Header$
/* ----------------------------------------------------------------------------
listbase.h
mbwall 25nov94
Copyright 1995 Massachusetts Institute of Technology
Expand All @@ -12,8 +10,8 @@
class since those take care of memory management. BASE class has no concept of
memory management, nor does it know the best way to count what its got.
---------------------------------------------------------------------------- */
#ifndef _ga_listbase_h_
#define _ga_listbase_h_

#pragma once

#include <GANode.h>

Expand Down Expand Up @@ -130,19 +128,7 @@ class GAListBASE
/* ----------------------------------------------------------------------------
GAListIterBASE
-------------------------------------------------------------------------------
This is the base class for iterators for the list objects. We define this
class separately from the List object so that you can have multiple interators
for each list and so that you can more easily customize the traversal
algorithms within the iterator. From the object point of view, the way you
traverse a list is independent of how you represent the list.
Like the ListBASE object, this object doesn't do any memory allocation or
deallocation. All we do is provide list traversal.
Notice that we keep a 'current location' in the list - whatever your last
query was is stored as the node, so if you refer to the current member, you'll
get your last query.
If you pass a NULL node to these routines they will not break; passing a NULL
will result in a no-op, and NULL will be returned.
creation
When you create an iterator, you should pass another iterator (the new one
will copy the first) or a list (the iterator will default to the head node
Expand All @@ -153,10 +139,23 @@ current, head, tail, next, prev, warp
the iterator now points to. If current is NULL or a NULL is passed to one of
these routines, a NULL is returned and the iterator does not move.
warp
Move the iterator to the node referenced by index. The head node is node '0'
then the count increases from there.
---------------------------------------------------------------------------- */

/** This is the base class for iterators for the list objects.
*
* We define this class separately from the List object so that you can have multiple interators
* for each list and so that you can more easily customize the traversal
* algorithms within the iterator. From the object point of view, the way you
* traverse a list is independent of how you represent the list.
* Like the ListBASE object, this object doesn't do any memory allocation or
* deallocation. All we do is provide list traversal.
* Notice that we keep a 'current location' in the list - whatever your last
* query was is stored as the node, so if you refer to the current member, you'll
* get your last query.
* If you pass a NULL node to these routines they will not break; passing a NULL
* will result in a no-op, and NULL will be returned.
*
*/
class GAListIterBASE
{
public:
Expand Down Expand Up @@ -206,18 +205,33 @@ class GAListIterBASE
{
return (((list != nullptr) && (list->hd != nullptr)) ? (node = list->hd->prev) : nullptr);
}
GANodeBASE *warp(unsigned int);

/** Move the iterator to the node referenced by index.
*
* The head node is node '0' then the count increases from there.
*
* @param index
* @return GANodeBASE*
*/
GANodeBASE *warp(unsigned int);

/** Move the iterator to the node referenced by index.
*
* The head node is node '0' then the count increases from there.
*
* @param i
* @return GANodeBASE*
*/
GANodeBASE *warp(const GAListIterBASE &i)
{
list = i.list;
node = nullptr;
return (i.node != nullptr ? (node = i.node) : nullptr);
}

int size() { return (list != nullptr ? list->size() : 0); }

protected:
GANodeBASE *node;
const GAListBASE *list;
};

#endif
97 changes: 82 additions & 15 deletions test/GAListGenomeTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ BOOST_AUTO_TEST_CASE(GAListGenome_DestructiveMutator_001)
{
GAListGenome<int> genome(objective);

genome.insert(0, GAListBASE::HEAD); // the head node contains a '0'
genome.insert(0, GAListBASE::HEAD);
for (int i = 1; i < 5; i++)
genome.insert(i); // each subsequent node contains a number
genome.insert(i);

BOOST_CHECK_EQUAL(genome.size(), 5);

Expand All @@ -42,15 +42,18 @@ BOOST_AUTO_TEST_CASE(GAListGenome_DestructiveMutator_001)
BOOST_CHECK_EQUAL(*genome.head(), 2);
BOOST_CHECK_EQUAL(*genome.next(), 3);
BOOST_CHECK_EQUAL(*genome.next(), 4);

std::cout << "Destructive Mutator" << std::endl;
std::cout << "Genome: " << genome << std::endl;
}

BOOST_AUTO_TEST_CASE(GAListGenome_SwapMutator_001)
{
GAListGenome<int> genome(objective);

genome.insert(0, GAListBASE::HEAD); // the head node contains a '0'
genome.insert(0, GAListBASE::HEAD);
for (int i = 1; i < 5; i++)
genome.insert(i); // each subsequent node contains a number
genome.insert(i);

BOOST_CHECK_EQUAL(genome.size(), 5);

Expand All @@ -68,39 +71,51 @@ BOOST_AUTO_TEST_CASE(GAListGenome_SwapMutator_001)
BOOST_CHECK_EQUAL(*genome.next(), 3);
BOOST_CHECK_EQUAL(*genome.next(), 2);
BOOST_CHECK_EQUAL(*genome.next(), 1);

std::cout << "SwapMutator" << std::endl;
std::cout << "Genome: " << genome << std::endl;
}

BOOST_AUTO_TEST_CASE(GAListGenome_NodeComparator_001)
{
GAListGenome<int> genome1(objective);
genome1.insert(0, GAListBASE::HEAD); // the head node contains a '0'
genome1.insert(0, GAListBASE::HEAD);
for (int i = 1; i < 5; i++)
genome1.insert(i); // each subsequent node contains a number
genome1.insert(i);

BOOST_CHECK_EQUAL(GAListGenome<int>::NodeComparator(genome1, genome1), 0); // failure case

GAListGenome<int> genome_failure(objective);
genome_failure.insert(0, GAListBASE::HEAD); // the head node contains a '0'
genome_failure.insert(0, GAListBASE::HEAD);
BOOST_CHECK_EQUAL(GAListGenome<int>::NodeComparator(genome1, genome_failure), 4); // failure case
BOOST_CHECK_EQUAL(GAListGenome<int>::NodeComparator(genome_failure, genome1), 4); // failure case

GAListGenome<int> genome_failure2(objective);
BOOST_CHECK_EQUAL(GAListGenome<int>::NodeComparator(genome_failure2, genome_failure2), 0); // failure case

std::cout << "NodeComparator Failure Cases" << std::endl;
std::cout << "Genome 1: " << genome1 << std::endl;
std::cout << "Genome Failure 1: " << genome_failure << std::endl;
std::cout << "Genome Failure 2: " << genome_failure2 << std::endl;

GAListGenome<int> genome2(objective);
genome2.insert(3, GAListBASE::HEAD); // the head node contains a '0'
genome2.insert(3, GAListBASE::HEAD);
for (int i = 1; i < 5; i++)
genome2.insert(i+3); // each subsequent node contains a number
genome2.insert(i+3);

BOOST_CHECK_EQUAL(GAListGenome<int>::NodeComparator(genome1, genome2), 5);

std::cout << "NodeComparator" << std::endl;
std::cout << "Genome 1: " << genome1 << std::endl;
std::cout << "Genome 2: " << genome2 << std::endl;
}

BOOST_AUTO_TEST_CASE(GAListGenome_OnePointCrossover_001)
{
GAListGenome<int> genomep1(objective);
genomep1.insert(0, GAListBASE::HEAD); // the head node contains a '0'
genomep1.insert(0, GAListBASE::HEAD);
for (int i = 1; i < 5; i++)
genomep1.insert(i); // each subsequent node contains a number
genomep1.insert(i);

GAListGenome<int> genomep2(objective);
genomep2.insert(5, GAListBASE::HEAD);
Expand Down Expand Up @@ -135,17 +150,29 @@ BOOST_AUTO_TEST_CASE(GAListGenome_OnePointCrossover_001)
BOOST_CHECK_EQUAL(*genomec2.next(), 1);
BOOST_CHECK_EQUAL(*genomec2.next(), 2);

std::cout << "OnePointCrossover" << std::endl;
std::cout << "Genome P1: " << genomep1 << std::endl;
std::cout << "Genome P2: " << genomep2 << std::endl;
std::cout << "Genome C1: " << genomec1 << std::endl;
std::cout << "Genome C2: " << genomec2 << std::endl;

BOOST_CHECK_EQUAL(GAListGenome<int>::OnePointCrossover(genomep1, genomep1, nullptr, nullptr), 0);
BOOST_CHECK_EQUAL(GAListGenome<int>::OnePointCrossover(genomep1, genomep1, &genomec1, nullptr), 1);
BOOST_CHECK_EQUAL(GAListGenome<int>::OnePointCrossover(genomep1, genomep1, nullptr, &genomec2), 1);

std::cout << "OnePointCrossover Failure Cases" << std::endl;
std::cout << "Genome P1: " << genomep1 << std::endl;
std::cout << "Genome P2: " << genomep2 << std::endl;
std::cout << "Genome C1: " << genomec1 << std::endl;
std::cout << "Genome C2: " << genomec2 << std::endl;
}

BOOST_AUTO_TEST_CASE(GAListGenome_PartialMatchCrossover_001)
{
GAListGenome<int> genomep1(objective);
genomep1.insert(0, GAListBASE::HEAD); // the head node contains a '0'
genomep1.insert(0, GAListBASE::HEAD);
for (int i = 1; i < 5; i++)
genomep1.insert(i); // each subsequent node contains a number
genomep1.insert(i);

GAListGenome<int> genomep2(objective);
genomep2.insert(5, GAListBASE::HEAD);
Expand Down Expand Up @@ -180,21 +207,35 @@ BOOST_AUTO_TEST_CASE(GAListGenome_PartialMatchCrossover_001)
BOOST_CHECK_EQUAL(*genomec2.next(), 3);
BOOST_CHECK_EQUAL(*genomec2.next(), 4);

std::cout << "PartialMatchCrossover" << std::endl;
std::cout << "Genome P1: " << genomep1 << std::endl;
std::cout << "Genome P2: " << genomep2 << std::endl;
std::cout << "Genome C1: " << genomec1 << std::endl;
std::cout << "Genome C2: " << genomec2 << std::endl;


BOOST_CHECK_EQUAL(GAListGenome<int>::PartialMatchCrossover(genomep1, genomep1, nullptr, nullptr), 0);
BOOST_CHECK_EQUAL(GAListGenome<int>::PartialMatchCrossover(genomep1, genomep1, &genomec1, nullptr), 1);
BOOST_CHECK_EQUAL(GAListGenome<int>::PartialMatchCrossover(genomep1, genomep1, nullptr, &genomec2), 2);

GAListGenome<int> genome_failure(objective);
genome_failure.insert(0, GAListBASE::HEAD);
BOOST_CHECK_EQUAL(GAListGenome<int>::PartialMatchCrossover(genomep1, genome_failure, &genomec1, &genomec2), 0);

std::cout << "PartialMatchCrossover Failure Cases" << std::endl;
std::cout << "Genome P1: " << genomep1 << std::endl;
std::cout << "Genome P2: " << genomep2 << std::endl;
std::cout << "Genome C1: " << genomec1 << std::endl;
std::cout << "Genome C2: " << genomec2 << std::endl;
std::cout << "Genome Failure: " << genome_failure << std::endl;
}

BOOST_AUTO_TEST_CASE(GAListGenome_OrderCrossover_001)
{
GAListGenome<int> genomep1(objective);
genomep1.insert(0, GAListBASE::HEAD); // the head node contains a '0'
genomep1.insert(0, GAListBASE::HEAD);
for (int i = 1; i < 5; i++)
genomep1.insert(i); // each subsequent node contains a number
genomep1.insert(i);

GAListGenome<int> genomep2(objective);
genomep2.insert(5, GAListBASE::HEAD);
Expand Down Expand Up @@ -230,13 +271,26 @@ BOOST_AUTO_TEST_CASE(GAListGenome_OrderCrossover_001)
BOOST_CHECK_EQUAL(*genomec2.next(), 3);
BOOST_CHECK_EQUAL(*genomec2.next(), 4);

std::cout << "OrderCrossover" << std::endl;
std::cout << "Genome P1: " << genomep1 << std::endl;
std::cout << "Genome P2: " << genomep2 << std::endl;
std::cout << "Genome C1: " << genomec1 << std::endl;
std::cout << "Genome C2: " << genomec2 << std::endl;

BOOST_CHECK_EQUAL(GAListGenome<int>::OrderCrossover(genomep1, genomep1, nullptr, nullptr), 0);
BOOST_CHECK_EQUAL(GAListGenome<int>::OrderCrossover(genomep1, genomep1, &genomec1, nullptr), 1);
BOOST_CHECK_EQUAL(GAListGenome<int>::OrderCrossover(genomep1, genomep1, nullptr, &genomec2), 1);

GAListGenome<int> genome_failure(objective);
genome_failure.insert(0, GAListBASE::HEAD);
BOOST_CHECK_EQUAL(GAListGenome<int>::OrderCrossover(genomep1, genome_failure, &genomec1, &genomec2), 0);

std::cout << "OrderCrossover Failure Cases" << std::endl;
std::cout << "Genome P1: " << genomep1 << std::endl;
std::cout << "Genome P2: " << genomep2 << std::endl;
std::cout << "Genome C1: " << genomec1 << std::endl;
std::cout << "Genome C2: " << genomec2 << std::endl;
std::cout << "Genome Failure: " << genome_failure << std::endl;
}

BOOST_AUTO_TEST_CASE(GAListGenome_CycleCrossover_001)
Expand Down Expand Up @@ -280,13 +334,26 @@ BOOST_AUTO_TEST_CASE(GAListGenome_CycleCrossover_001)
BOOST_CHECK_EQUAL(*genomec2.next(), 3);
BOOST_CHECK_EQUAL(*genomec2.next(), 4);

std::cout << "CycleCrossover" << std::endl;
std::cout << "Genome P1: " << genomep1 << std::endl;
std::cout << "Genome P2: " << genomep2 << std::endl;
std::cout << "Genome C1: " << genomec1 << std::endl;
std::cout << "Genome C2: " << genomec2 << std::endl;

BOOST_CHECK_EQUAL(GAListGenome<int>::CycleCrossover(genomep1, genomep1, nullptr, nullptr), 0);
BOOST_CHECK_EQUAL(GAListGenome<int>::CycleCrossover(genomep1, genomep1, &genomec1, nullptr), 1);
BOOST_CHECK_EQUAL(GAListGenome<int>::CycleCrossover(genomep1, genomep1, nullptr, &genomec2), 1);

GAListGenome<int> genome_failure(objective);
genome_failure.insert(0, GAListBASE::HEAD);
BOOST_CHECK_EQUAL(GAListGenome<int>::CycleCrossover(genomep1, genome_failure, &genomec1, &genomec2), 0);

std::cout << "CycleCrossover Failure Cases" << std::endl;
std::cout << "Genome P1: " << genomep1 << std::endl;
std::cout << "Genome P2: " << genomep2 << std::endl;
std::cout << "Genome C1: " << genomec1 << std::endl;
std::cout << "Genome C2: " << genomec2 << std::endl;
std::cout << "Genome Failure: " << genome_failure << std::endl;
}

BOOST_AUTO_TEST_SUITE_END()
Loading

0 comments on commit 800662e

Please sign in to comment.