From 431c4ec28082089969116bcdea7bd45c0fa5adda Mon Sep 17 00:00:00 2001 From: s-martin Date: Sun, 16 Apr 2023 20:11:07 +0000 Subject: [PATCH 1/4] add more tests and fix some comments --- ga/GAListBASE.C | 2 -- ga/GAListBASE.h | 60 ++++++++++++++++++++++++++++----------------- test/GAListTest.cpp | 39 +++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 25 deletions(-) diff --git a/ga/GAListBASE.C b/ga/GAListBASE.C index f800f0dc..16165d58 100644 --- a/ga/GAListBASE.C +++ b/ga/GAListBASE.C @@ -1,6 +1,4 @@ -// $Header$ /* ---------------------------------------------------------------------------- - listbase.C mbwall 10dec94 Copyright 1995 Massachusetts Institute of Technology diff --git a/ga/GAListBASE.h b/ga/GAListBASE.h index 0d47bdfa..826ea67c 100644 --- a/ga/GAListBASE.h +++ b/ga/GAListBASE.h @@ -1,6 +1,4 @@ -// $Header$ /* ---------------------------------------------------------------------------- - listbase.h mbwall 25nov94 Copyright 1995 Massachusetts Institute of Technology @@ -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 @@ -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 @@ -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: @@ -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 diff --git a/test/GAListTest.cpp b/test/GAListTest.cpp index 49969f36..f65bfbe2 100644 --- a/test/GAListTest.cpp +++ b/test/GAListTest.cpp @@ -206,7 +206,46 @@ BOOST_AUTO_TEST_CASE(remove_001) BOOST_AUTO_TEST_CASE(GAList_clone_001) { + GAList galist1; + galist1.insert(0, GAListBASE::HEAD); // the head node contains a '0' + for (int i = 1; i < 5; i++) + galist1.insert(i); // each subsequent node contains a number + + BOOST_CHECK_EQUAL(galist1.size(), 5); + + for (int i = 0; i < 5; i++) + BOOST_CHECK_EQUAL(*galist1.next(), i); + + auto galist2 = galist1.clone(); + BOOST_CHECK_EQUAL(galist2->size(), 5); + + // TODO Check why this is necessary, see also copy + BOOST_CHECK_EQUAL(*galist2->head(), 0); + for (int i = 1; i < 5; i++) + BOOST_CHECK_EQUAL(*galist2->next(), i); +} +BOOST_AUTO_TEST_CASE(GAList_warp_001) +{ + GAList galist1; + galist1.insert(0, GAListBASE::HEAD); // the head node contains a '0' + for (int i = 1; i < 5; i++) + galist1.insert(i); // each subsequent node contains a number + + BOOST_CHECK_EQUAL(galist1.size(), 5); + + for (int i = 0; i < 5; i++) + BOOST_CHECK_EQUAL(*galist1.next(), i); + + BOOST_CHECK_EQUAL(*galist1.current(), 4); + galist1.warp(2); + BOOST_CHECK_EQUAL(*galist1.current(), 2); + galist1.warp(0); + BOOST_CHECK_EQUAL(*galist1.current(), 0); + + // failure cases + BOOST_CHECK_EQUAL(galist1.warp(5), nullptr); + BOOST_CHECK_EQUAL(*galist1.current(), 0); } BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file From c58322848c44b24bc57768c527a60eedc2a7fa0a Mon Sep 17 00:00:00 2001 From: s-martin Date: Sun, 16 Apr 2023 20:29:41 +0000 Subject: [PATCH 2/4] added insert test case --- test/GAListTest.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/test/GAListTest.cpp b/test/GAListTest.cpp index f65bfbe2..15c44b50 100644 --- a/test/GAListTest.cpp +++ b/test/GAListTest.cpp @@ -36,6 +36,50 @@ BOOST_AUTO_TEST_CASE(insert_001) BOOST_CHECK_EQUAL(*galist1.next(), i); } +BOOST_AUTO_TEST_CASE(GAList_insert_002) +{ + GAList galist1; + galist1.insert(0, GAListBASE::HEAD); // the head node contains a '0' + for (int i = 1; i < 5; i++) + galist1.insert(i); // each subsequent node contains a number + + BOOST_CHECK_EQUAL(galist1.size(), 5); + + for (int i = 0; i < 5; i++) + BOOST_CHECK_EQUAL(*galist1.next(), i); + + GAList galist2; + galist2.insert(0, GAListBASE::HEAD); // the head node contains a '0' + for (int i = 1; i < 7; i++) + galist2.insert(i); // each subsequent node contains a number + + BOOST_CHECK_EQUAL(galist2.size(), 7); + + for (int i = 0; i < 7; i++) + BOOST_CHECK_EQUAL(*galist2.next(), i); + + BOOST_CHECK_EQUAL(galist1.insert(&galist2), 0); + BOOST_CHECK_EQUAL(galist1.size(), 12); + + BOOST_CHECK_EQUAL(*galist1.head(), 0); + BOOST_CHECK_EQUAL(*galist1.next(), 1); + BOOST_CHECK_EQUAL(*galist1.next(), 2); + BOOST_CHECK_EQUAL(*galist1.next(), 3); + BOOST_CHECK_EQUAL(*galist1.next(), 4); + BOOST_CHECK_EQUAL(*galist1.next(), 0); + BOOST_CHECK_EQUAL(*galist1.next(), 1); + BOOST_CHECK_EQUAL(*galist1.next(), 2); + BOOST_CHECK_EQUAL(*galist1.next(), 3); + BOOST_CHECK_EQUAL(*galist1.next(), 4); + BOOST_CHECK_EQUAL(*galist1.next(), 5); + BOOST_CHECK_EQUAL(*galist1.next(), 6); + + // failure case + BOOST_CHECK_EQUAL(galist2.insert(&galist2), -1); + BOOST_CHECK_EQUAL(galist2.size(), 7); +} + + BOOST_AUTO_TEST_CASE(GAList_copy_001) { GAList galist1; @@ -102,7 +146,6 @@ BOOST_AUTO_TEST_CASE(insertList_001) BOOST_CHECK_EQUAL(*galist1.next(), 4); } - BOOST_AUTO_TEST_CASE(GAList_swap_001) { GAList galist1; From 747aa115c1072117febb1eb71000f11364562b8c Mon Sep 17 00:00:00 2001 From: s-martin Date: Wed, 3 May 2023 20:19:38 +0000 Subject: [PATCH 3/4] add output --- test/GAListGenomeTest.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/GAListGenomeTest.cpp b/test/GAListGenomeTest.cpp index e4fbe310..fd7081c7 100644 --- a/test/GAListGenomeTest.cpp +++ b/test/GAListGenomeTest.cpp @@ -138,6 +138,12 @@ BOOST_AUTO_TEST_CASE(GAListGenome_OnePointCrossover_001) BOOST_CHECK_EQUAL(GAListGenome::OnePointCrossover(genomep1, genomep1, nullptr, nullptr), 0); BOOST_CHECK_EQUAL(GAListGenome::OnePointCrossover(genomep1, genomep1, &genomec1, nullptr), 1); BOOST_CHECK_EQUAL(GAListGenome::OnePointCrossover(genomep1, genomep1, nullptr, &genomec2), 1); + + 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_AUTO_TEST_CASE(GAListGenome_PartialMatchCrossover_001) From 500580a7c79fcc6dea249fffb4dfa116d7617336 Mon Sep 17 00:00:00 2001 From: s-martin Date: Wed, 3 May 2023 21:14:13 +0000 Subject: [PATCH 4/4] add more outputs --- test/GAListGenomeTest.cpp | 93 ++++++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 16 deletions(-) diff --git a/test/GAListGenomeTest.cpp b/test/GAListGenomeTest.cpp index fd7081c7..8616dbd6 100644 --- a/test/GAListGenomeTest.cpp +++ b/test/GAListGenomeTest.cpp @@ -22,9 +22,9 @@ BOOST_AUTO_TEST_CASE(GAListGenome_DestructiveMutator_001) { GAListGenome 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); @@ -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 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); @@ -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 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::NodeComparator(genome1, genome1), 0); // failure case GAListGenome 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::NodeComparator(genome1, genome_failure), 4); // failure case BOOST_CHECK_EQUAL(GAListGenome::NodeComparator(genome_failure, genome1), 4); // failure case GAListGenome genome_failure2(objective); BOOST_CHECK_EQUAL(GAListGenome::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 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::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 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 genomep2(objective); genomep2.insert(5, GAListBASE::HEAD); @@ -135,11 +150,17 @@ 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::OnePointCrossover(genomep1, genomep1, nullptr, nullptr), 0); BOOST_CHECK_EQUAL(GAListGenome::OnePointCrossover(genomep1, genomep1, &genomec1, nullptr), 1); BOOST_CHECK_EQUAL(GAListGenome::OnePointCrossover(genomep1, genomep1, nullptr, &genomec2), 1); - std::cout << "OnePointCrossover" << std::endl; + 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; @@ -149,9 +170,9 @@ BOOST_AUTO_TEST_CASE(GAListGenome_OnePointCrossover_001) BOOST_AUTO_TEST_CASE(GAListGenome_PartialMatchCrossover_001) { GAListGenome 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 genomep2(objective); genomep2.insert(5, GAListBASE::HEAD); @@ -186,6 +207,13 @@ 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::PartialMatchCrossover(genomep1, genomep1, nullptr, nullptr), 0); BOOST_CHECK_EQUAL(GAListGenome::PartialMatchCrossover(genomep1, genomep1, &genomec1, nullptr), 1); BOOST_CHECK_EQUAL(GAListGenome::PartialMatchCrossover(genomep1, genomep1, nullptr, &genomec2), 2); @@ -193,14 +221,21 @@ BOOST_AUTO_TEST_CASE(GAListGenome_PartialMatchCrossover_001) GAListGenome genome_failure(objective); genome_failure.insert(0, GAListBASE::HEAD); BOOST_CHECK_EQUAL(GAListGenome::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 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 genomep2(objective); genomep2.insert(5, GAListBASE::HEAD); @@ -236,6 +271,12 @@ 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::OrderCrossover(genomep1, genomep1, nullptr, nullptr), 0); BOOST_CHECK_EQUAL(GAListGenome::OrderCrossover(genomep1, genomep1, &genomec1, nullptr), 1); BOOST_CHECK_EQUAL(GAListGenome::OrderCrossover(genomep1, genomep1, nullptr, &genomec2), 1); @@ -243,6 +284,13 @@ BOOST_AUTO_TEST_CASE(GAListGenome_OrderCrossover_001) GAListGenome genome_failure(objective); genome_failure.insert(0, GAListBASE::HEAD); BOOST_CHECK_EQUAL(GAListGenome::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) @@ -286,6 +334,12 @@ 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::CycleCrossover(genomep1, genomep1, nullptr, nullptr), 0); BOOST_CHECK_EQUAL(GAListGenome::CycleCrossover(genomep1, genomep1, &genomec1, nullptr), 1); BOOST_CHECK_EQUAL(GAListGenome::CycleCrossover(genomep1, genomep1, nullptr, &genomec2), 1); @@ -293,6 +347,13 @@ BOOST_AUTO_TEST_CASE(GAListGenome_CycleCrossover_001) GAListGenome genome_failure(objective); genome_failure.insert(0, GAListBASE::HEAD); BOOST_CHECK_EQUAL(GAListGenome::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() \ No newline at end of file