1 /* Copyright 2017-2021 PaGMO development team
2
3 This file is part of the PaGMO library.
4
5 The PaGMO library is free software; you can redistribute it and/or modify
6 it under the terms of either:
7
8 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 or
13
14 * the GNU General Public License as published by the Free Software
15 Foundation; either version 3 of the License, or (at your option) any
16 later version.
17
18 or both in parallel, as here.
19
20 The PaGMO library is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 for more details.
24
25 You should have received copies of the GNU General Public License and the
26 GNU Lesser General Public License along with the PaGMO library. If not,
27 see https://www.gnu.org/licenses/. */
28
29 #define BOOST_TEST_MODULE de1220_test
30 #define BOOST_TEST_DYN_LINK
31 #include <boost/test/unit_test.hpp>
32
33 #include <iostream>
34 #include <numeric>
35 #include <string>
36
37 #include <boost/lexical_cast.hpp>
38 #include <boost/test/tools/floating_point_comparison.hpp>
39
40 #include <pagmo/algorithm.hpp>
41 #include <pagmo/algorithms/de1220.hpp>
42 #include <pagmo/io.hpp>
43 #include <pagmo/population.hpp>
44 #include <pagmo/problems/hock_schittkowsky_71.hpp>
45 #include <pagmo/problems/inventory.hpp>
46 #include <pagmo/problems/rosenbrock.hpp>
47 #include <pagmo/problems/zdt.hpp>
48 #include <pagmo/s11n.hpp>
49 #include <pagmo/types.hpp>
50
51 using namespace pagmo;
52
BOOST_AUTO_TEST_CASE(construction_test)53 BOOST_AUTO_TEST_CASE(construction_test)
54 {
55 std::vector<unsigned> mutation_variants(18);
56 std::iota(mutation_variants.begin(), mutation_variants.end(), 1u);
57 de1220 user_algo(53u, mutation_variants, 1u, 1e-6, 1e-6, false, 23u);
58 BOOST_CHECK(user_algo.get_verbosity() == 0u);
59 BOOST_CHECK(user_algo.get_seed() == 23u);
60 BOOST_CHECK((user_algo.get_log() == de1220::log_type{}));
61
62 BOOST_CHECK_THROW((de1220{53u, {3u, 5u, 0u, 14u}, 1u, 1e-6, 1e-6, false, 23u}), std::invalid_argument);
63 BOOST_CHECK_THROW((de1220{53u, {4u, 5u, 15u, 22u, 7u}, 1u, 1e-6, 1e-6, false, 23u}), std::invalid_argument);
64 BOOST_CHECK_THROW((de1220{53u, mutation_variants, 0u, 1e-6, 1e-6, false, 23u}), std::invalid_argument);
65 BOOST_CHECK_THROW((de1220{53u, mutation_variants, 3u, 1e-6, 1e-6, false, 23u}), std::invalid_argument);
66 }
67
BOOST_AUTO_TEST_CASE(evolve_test)68 BOOST_AUTO_TEST_CASE(evolve_test)
69 {
70 // We consider all variants
71 std::vector<unsigned> mutation_variants(18);
72 std::iota(mutation_variants.begin(), mutation_variants.end(), 1u);
73 // Here we only test that evolution is deterministic if the
74 // seed is controlled for all variants
75 {
76 problem prob{rosenbrock{25u}};
77 population pop1{prob, 15u, 23u};
78 population pop2{prob, 15u, 23u};
79 population pop3{prob, 15u, 23u};
80
81 for (unsigned i = 1u; i <= 2u; ++i) {
82 de1220 user_algo1(10u, mutation_variants, i, 1e-6, 1e-6, false, 41u);
83 user_algo1.set_verbosity(1u);
84 pop1 = user_algo1.evolve(pop1);
85
86 BOOST_CHECK(user_algo1.get_log().size() > 0u);
87
88 de1220 user_algo2{10u, mutation_variants, i, 1e-6, 1e-6, false, 41u};
89 user_algo2.set_verbosity(1u);
90 pop2 = user_algo2.evolve(pop2);
91
92 BOOST_CHECK(user_algo1.get_log() == user_algo2.get_log());
93
94 user_algo2.set_seed(41u);
95 pop3 = user_algo2.evolve(pop3);
96
97 BOOST_CHECK(user_algo1.get_log() == user_algo2.get_log());
98 }
99 }
100
101 // Here we check that the exit condition of ftol and xtol actually provoke an exit within 5000 gen (rosenbrock{2} is
102 // used)
103 { // xtol
104 de1220 user_algo(300u, mutation_variants, 2, 1e-3, 1e-45, false, 41u);
105 user_algo.set_verbosity(1u);
106 problem prob{rosenbrock{2u}};
107 population pop{prob, 20u, 23u};
108 pop = user_algo.evolve(pop);
109 BOOST_CHECK(user_algo.get_log().size() < 300u);
110 }
111 { // ftol
112 de1220 user_algo(300u, mutation_variants, 1, 1e-45, 1e-3, false, 41u);
113 user_algo.set_verbosity(1u);
114 problem prob{rosenbrock{2u}};
115 population pop{prob, 20u, 23u};
116 pop = user_algo.evolve(pop);
117 BOOST_CHECK(user_algo.get_log().size() < 300u);
118 }
119
120 // We then check that the evolve throws if called on unsuitable problems
121 BOOST_CHECK_THROW(de1220{10u}.evolve(population{problem{rosenbrock{}}, 6u}), std::invalid_argument);
122 BOOST_CHECK_THROW(de1220{10u}.evolve(population{problem{zdt{}}, 15u}), std::invalid_argument);
123 BOOST_CHECK_THROW(de1220{10u}.evolve(population{problem{hock_schittkowsky_71{}}, 15u}), std::invalid_argument);
124 BOOST_CHECK_THROW(de1220{10u}.evolve(population{problem{inventory{}}, 15u}), std::invalid_argument);
125 // And a clean exit for 0 generations
126 population pop{rosenbrock{25u}, 10u};
127 BOOST_CHECK(de1220{0u}.evolve(pop).get_x()[0] == pop.get_x()[0]);
128 }
129
BOOST_AUTO_TEST_CASE(setters_getters_test)130 BOOST_AUTO_TEST_CASE(setters_getters_test)
131 {
132 // We consider all variants
133 std::vector<unsigned> mutation_variants(18);
134 std::iota(mutation_variants.begin(), mutation_variants.end(), 1u);
135 de1220 user_algo(10000u, mutation_variants, 1, 1e-6, 1e-6, false, 41u);
136 user_algo.set_verbosity(23u);
137 BOOST_CHECK(user_algo.get_verbosity() == 23u);
138 user_algo.set_seed(23u);
139 BOOST_CHECK(user_algo.get_seed() == 23u);
140 BOOST_CHECK(user_algo.get_name().find("1220") != std::string::npos);
141 BOOST_CHECK(user_algo.get_extra_info().find("Allowed variants") != std::string::npos);
142 BOOST_CHECK_NO_THROW(user_algo.get_log());
143 }
144
BOOST_AUTO_TEST_CASE(serialization_test)145 BOOST_AUTO_TEST_CASE(serialization_test)
146 {
147 // Make one evolution
148 problem prob{rosenbrock{2u}};
149 population pop{prob, 15u, 23u};
150 std::vector<unsigned> mutation_variants(18);
151 std::iota(mutation_variants.begin(), mutation_variants.end(), 1u);
152 algorithm algo(de1220{10000u, mutation_variants, 1, 1e-6, 1e-6, false, 41u});
153 algo.set_verbosity(1u);
154 pop = algo.evolve(pop);
155
156 // Store the string representation of p.
157 std::stringstream ss;
158 auto before_text = boost::lexical_cast<std::string>(algo);
159 auto before_log = algo.extract<de1220>()->get_log();
160 // Now serialize, deserialize and compare the result.
161 {
162 boost::archive::binary_oarchive oarchive(ss);
163 oarchive << algo;
164 }
165 // Change the content of p before deserializing.
166 algo = algorithm{};
167 {
168 boost::archive::binary_iarchive iarchive(ss);
169 iarchive >> algo;
170 }
171 auto after_text = boost::lexical_cast<std::string>(algo);
172 auto after_log = algo.extract<de1220>()->get_log();
173 BOOST_CHECK_EQUAL(before_text, after_text);
174 BOOST_CHECK(before_log == after_log);
175 // so we implement a close check
176 BOOST_CHECK(before_log.size() > 0u);
177 for (auto i = 0u; i < before_log.size(); ++i) {
178 BOOST_CHECK_EQUAL(std::get<0>(before_log[i]), std::get<0>(after_log[i]));
179 BOOST_CHECK_EQUAL(std::get<1>(before_log[i]), std::get<1>(after_log[i]));
180 BOOST_CHECK_CLOSE(std::get<2>(before_log[i]), std::get<2>(after_log[i]), 1e-8);
181 BOOST_CHECK_CLOSE(std::get<3>(before_log[i]), std::get<3>(after_log[i]), 1e-8);
182 BOOST_CHECK_CLOSE(std::get<4>(before_log[i]), std::get<4>(after_log[i]), 1e-8);
183 BOOST_CHECK_EQUAL(std::get<5>(before_log[i]), std::get<5>(after_log[i]));
184 BOOST_CHECK_CLOSE(std::get<6>(before_log[i]), std::get<6>(after_log[i]), 1e-8);
185 BOOST_CHECK_CLOSE(std::get<7>(before_log[i]), std::get<7>(after_log[i]), 1e-8);
186 }
187 }
188