1 // Copyright 2020, 2021 PaGMO development team
2 //
3 // This file is part of the pygmo library.
4 //
5 // This Source Code Form is subject to the terms of the Mozilla
6 // Public License v. 2.0. If a copy of the MPL was not distributed
7 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
9 #include <string>
10 #include <tuple>
11
12 #include <pybind11/numpy.h>
13 #include <pybind11/pybind11.h>
14
15 #include <pagmo/algorithm.hpp>
16 #include <pagmo/algorithms/gaco.hpp>
17 #include <pagmo/algorithms/gwo.hpp>
18 #include <pagmo/algorithms/ihs.hpp>
19 #include <pagmo/algorithms/maco.hpp>
20 #include <pagmo/algorithms/nsga2.hpp>
21 #include <pagmo/algorithms/nspso.hpp>
22 #include <pagmo/algorithms/null_algorithm.hpp>
23 #include <pagmo/algorithms/pso.hpp>
24 #include <pagmo/algorithms/pso_gen.hpp>
25 #include <pagmo/algorithms/sade.hpp>
26 #include <pagmo/algorithms/sea.hpp>
27 #include <pagmo/algorithms/sga.hpp>
28 #include <pagmo/algorithms/simulated_annealing.hpp>
29 #include <pagmo/config.hpp>
30
31 #if defined(PAGMO_WITH_NLOPT)
32 #include <pagmo/algorithms/nlopt.hpp>
33 #endif
34
35 #include "common_utils.hpp"
36 #include "docstrings.hpp"
37 #include "expose_algorithms.hpp"
38
39 namespace pygmo
40 {
41
42 namespace py = pybind11;
43
expose_algorithms_1(py::module & m,py::class_<pagmo::algorithm> & algo,py::module & a_module)44 void expose_algorithms_1(py::module &m, py::class_<pagmo::algorithm> &algo, py::module &a_module)
45 {
46 // Null algo.
47 auto na = expose_algorithm<pagmo::null_algorithm>(m, algo, a_module, "null_algorithm",
48 null_algorithm_docstring().c_str());
49
50 // NSGA2
51 auto nsga2_ = expose_algorithm<pagmo::nsga2>(m, algo, a_module, "nsga2", nsga2_docstring().c_str());
52 nsga2_.def(py::init<unsigned, double, double, double, double>(), py::arg("gen") = 1u, py::arg("cr") = 0.95,
53 py::arg("eta_c") = 10., py::arg("m") = 0.01, py::arg("eta_m") = 50.);
54 nsga2_.def(py::init<unsigned, double, double, double, double, unsigned>(), py::arg("gen") = 1u,
55 py::arg("cr") = 0.95, py::arg("eta_c") = 10., py::arg("m") = 0.01, py::arg("eta_m") = 50.,
56 py::arg("seed"));
57 // nsga2 needs an ad hoc exposition for the log as one entry is a vector (ideal_point)
58 nsga2_.def(
59 "get_log",
60 [](const pagmo::nsga2 &a) -> py::list {
61 py::list retval;
62 for (const auto &t : a.get_log()) {
63 retval.append(py::make_tuple(std::get<0>(t), std::get<1>(t),
64 vector_to_ndarr<py::array_t<double>>(std::get<2>(t))));
65 }
66 return retval;
67 },
68 nsga2_get_log_docstring().c_str());
69
70 nsga2_.def("get_seed", &pagmo::nsga2::get_seed, generic_uda_get_seed_docstring().c_str());
71 nsga2_.def("set_bfe", &pagmo::nsga2::set_bfe, nsga2_set_bfe_docstring().c_str(), py::arg("b"));
72
73 // GACO
74 auto gaco_ = expose_algorithm<pagmo::gaco>(m, algo, a_module, "gaco", gaco_docstring().c_str());
75 gaco_.def(
76 py::init<unsigned, unsigned, double, double, double, unsigned, unsigned, unsigned, unsigned, double, bool>(),
77 py::arg("gen") = 100u, py::arg("ker") = 63u, py::arg("q") = 1.0, py::arg("oracle") = 0., py::arg("acc") = 0.01,
78 py::arg("threshold") = 1u, py::arg("n_gen_mark") = 7u, py::arg("impstop") = 100000u,
79 py::arg("evalstop") = 100000u, py::arg("focus") = 0., py::arg("memory") = false);
80 gaco_.def(py::init<unsigned, unsigned, double, double, double, unsigned, unsigned, unsigned, unsigned, double, bool,
81 unsigned>(),
82 py::arg("gen") = 100u, py::arg("ker") = 63u, py::arg("q") = 1.0, py::arg("oracle") = 0.,
83 py::arg("acc") = 0.01, py::arg("threshold") = 1u, py::arg("n_gen_mark") = 7u,
84 py::arg("impstop") = 100000u, py::arg("evalstop") = 100000u, py::arg("focus") = 0.,
85 py::arg("memory") = false, py::arg("seed"));
86 expose_algo_log(gaco_, gaco_get_log_docstring().c_str());
87 gaco_.def("get_seed", &pagmo::gaco::get_seed, generic_uda_get_seed_docstring().c_str());
88 gaco_.def("set_bfe", &pagmo::gaco::set_bfe, gaco_set_bfe_docstring().c_str(), py::arg("b"));
89
90 // GWO
91 auto gwo_ = expose_algorithm<pagmo::gwo>(m, algo, a_module, "gwo", gwo_docstring().c_str());
92 gwo_.def(py::init<unsigned>(), py::arg("gen") = 1u);
93 gwo_.def(py::init<unsigned, unsigned>(), py::arg("gen") = 1u, py::arg("seed"));
94 expose_algo_log(gwo_, gwo_get_log_docstring().c_str());
95 gwo_.def("get_seed", &pagmo::gwo::get_seed, generic_uda_get_seed_docstring().c_str());
96
97 // SEA
98 auto sea_ = expose_algorithm<pagmo::sea>(m, algo, a_module, "sea", sea_docstring().c_str());
99 sea_.def(py::init<unsigned>(), py::arg("gen") = 1u);
100 sea_.def(py::init<unsigned, unsigned>(), py::arg("gen") = 1u, py::arg("seed"));
101 expose_algo_log(sea_, sea_get_log_docstring().c_str());
102 sea_.def("get_seed", &pagmo::sea::get_seed, generic_uda_get_seed_docstring().c_str());
103
104 // PSO
105 auto pso_ = expose_algorithm<pagmo::pso>(m, algo, a_module, "pso", pso_docstring().c_str());
106 pso_.def(py::init<unsigned, double, double, double, double, unsigned, unsigned, unsigned, bool>(),
107 py::arg("gen") = 1u, py::arg("omega") = 0.7298, py::arg("eta1") = 2.05, py::arg("eta2") = 2.05,
108 py::arg("max_vel") = 0.5, py::arg("variant") = 5u, py::arg("neighb_type") = 2u,
109 py::arg("neighb_param") = 4u, py::arg("memory") = false);
110 pso_.def(py::init<unsigned, double, double, double, double, unsigned, unsigned, unsigned, bool, unsigned>(),
111 py::arg("gen") = 1u, py::arg("omega") = 0.7298, py::arg("eta1") = 2.05, py::arg("eta2") = 2.05,
112 py::arg("max_vel") = 0.5, py::arg("variant") = 5u, py::arg("neighb_type") = 2u,
113 py::arg("neighb_param") = 4u, py::arg("memory") = false, py::arg("seed"));
114 expose_algo_log(pso_, pso_get_log_docstring().c_str());
115 pso_.def("get_seed", &pagmo::pso::get_seed, generic_uda_get_seed_docstring().c_str());
116
117 // PSO (generational)
118 auto pso_gen_ = expose_algorithm<pagmo::pso_gen>(m, algo, a_module, "pso_gen", pso_gen_docstring().c_str());
119 pso_gen_.def(py::init<unsigned, double, double, double, double, unsigned, unsigned, unsigned, bool>(),
120 py::arg("gen") = 1u, py::arg("omega") = 0.7298, py::arg("eta1") = 2.05, py::arg("eta2") = 2.05,
121 py::arg("max_vel") = 0.5, py::arg("variant") = 5u, py::arg("neighb_type") = 2u,
122 py::arg("neighb_param") = 4u, py::arg("memory") = false);
123 pso_gen_.def(py::init<unsigned, double, double, double, double, unsigned, unsigned, unsigned, bool, unsigned>(),
124 py::arg("gen") = 1u, py::arg("omega") = 0.7298, py::arg("eta1") = 2.05, py::arg("eta2") = 2.05,
125 py::arg("max_vel") = 0.5, py::arg("variant") = 5u, py::arg("neighb_type") = 2u,
126 py::arg("neighb_param") = 4u, py::arg("memory") = false, py::arg("seed"));
127 expose_algo_log(pso_gen_, pso_gen_get_log_docstring().c_str());
128 pso_gen_.def("get_seed", &pagmo::pso_gen::get_seed, generic_uda_get_seed_docstring().c_str());
129 pso_gen_.def("set_bfe", &pagmo::pso_gen::set_bfe, pso_gen_set_bfe_docstring().c_str(), py::arg("b"));
130
131 // SIMULATED ANNEALING
132 auto simulated_annealing_ = expose_algorithm<pagmo::simulated_annealing>(m, algo, a_module, "simulated_annealing",
133 simulated_annealing_docstring().c_str());
134 simulated_annealing_.def(py::init<double, double, unsigned, unsigned, unsigned, double>(), py::arg("Ts") = 10.,
135 py::arg("Tf") = 0.1, py::arg("n_T_adj") = 10u, py::arg("n_range_adj") = 1u,
136 py::arg("bin_size") = 20u, py::arg("start_range") = 1.);
137 simulated_annealing_.def(py::init<double, double, unsigned, unsigned, unsigned, double, unsigned>(),
138 py::arg("Ts") = 10., py::arg("Tf") = 0.1, py::arg("n_T_adj") = 10u,
139 py::arg("n_range_adj") = 10u, py::arg("bin_size") = 10u, py::arg("start_range") = 1.,
140 py::arg("seed"));
141 expose_algo_log(simulated_annealing_, simulated_annealing_get_log_docstring().c_str());
142 simulated_annealing_.def("get_seed", &pagmo::simulated_annealing::get_seed,
143 generic_uda_get_seed_docstring().c_str());
144 expose_not_population_based(simulated_annealing_, "simulated_annealing");
145
146 // SGA
147 auto sga_ = expose_algorithm<pagmo::sga>(m, algo, a_module, "sga", sga_docstring().c_str());
148 sga_.def(py::init<unsigned, double, double, double, double, unsigned, std::string, std::string, std::string>(),
149 py::arg("gen") = 1u, py::arg("cr") = 0.9, py::arg("eta_c") = 1., py::arg("m") = 0.02,
150 py::arg("param_m") = 1., py::arg("param_s") = 2u, py::arg("crossover") = "exponential",
151 py::arg("mutation") = "polynomial", py::arg("selection") = "tournament");
152 sga_.def(
153 py::init<unsigned, double, double, double, double, unsigned, std::string, std::string, std::string, unsigned>(),
154 py::arg("gen") = 1u, py::arg("cr") = 0.9, py::arg("eta_c") = 1., py::arg("m") = 0.02, py::arg("param_m") = 1.,
155 py::arg("param_s") = 2u, py::arg("crossover") = "exponential", py::arg("mutation") = "polynomial",
156 py::arg("selection") = "tournament", py::arg("seed"));
157 expose_algo_log(sga_, sga_get_log_docstring().c_str());
158 sga_.def("get_seed", &pagmo::sga::get_seed, generic_uda_get_seed_docstring().c_str());
159
160 // IHS
161 auto ihs_ = expose_algorithm<pagmo::ihs>(m, algo, a_module, "ihs", ihs_docstring().c_str());
162 ihs_.def(py::init<unsigned, double, double, double, double, double>(), py::arg("gen") = 1u, py::arg("phmcr") = 0.85,
163 py::arg("ppar_min") = 0.35, py::arg("ppar_max") = 0.99, py::arg("bw_min") = 1E-5, py::arg("bw_max") = 1.);
164 ihs_.def(py::init<unsigned, double, double, double, double, double, unsigned>(), py::arg("gen") = 1u,
165 py::arg("phmcr") = 0.85, py::arg("ppar_min") = 0.35, py::arg("ppar_max") = 0.99, py::arg("bw_min") = 1E-5,
166 py::arg("bw_max") = 1., py::arg("seed"));
167 // ihs needs an ad hoc exposition for the log as one entry is a vector (ideal_point)
168 ihs_.def(
169 "get_log",
170 [](const pagmo::ihs &a) -> py::list {
171 py::list retval;
172 for (const auto &t : a.get_log()) {
173 retval.append(py::make_tuple(std::get<0>(t), std::get<1>(t), std::get<2>(t), std::get<3>(t),
174 std::get<4>(t), std::get<5>(t), std::get<6>(t),
175 vector_to_ndarr<py::array_t<double>>(std::get<7>(t))));
176 }
177 return retval;
178 },
179 ihs_get_log_docstring().c_str());
180 ihs_.def("get_seed", &pagmo::ihs::get_seed, generic_uda_get_seed_docstring().c_str());
181
182 // SADE
183 auto sade_ = expose_algorithm<pagmo::sade>(m, algo, a_module, "sade", sade_docstring().c_str());
184 sade_.def(py::init<unsigned, unsigned, unsigned, double, double, bool>(), py::arg("gen") = 1u,
185 py::arg("variant") = 2u, py::arg("variant_adptv") = 1u, py::arg("ftol") = 1e-6, py::arg("xtol") = 1e-6,
186 py::arg("memory") = false);
187 sade_.def(py::init<unsigned, unsigned, unsigned, double, double, bool, unsigned>(), py::arg("gen") = 1u,
188 py::arg("variant") = 2u, py::arg("variant_adptv") = 1u, py::arg("ftol") = 1e-6, py::arg("xtol") = 1e-6,
189 py::arg("memory") = false, py::arg("seed"));
190 expose_algo_log(sade_, sade_get_log_docstring().c_str());
191 sade_.def("get_seed", &pagmo::sade::get_seed, generic_uda_get_seed_docstring().c_str());
192
193 // MACO
194 auto maco_ = expose_algorithm<pagmo::maco>(m, algo, a_module, "maco", maco_docstring().c_str());
195 maco_.def(py::init<unsigned, unsigned, double, unsigned, unsigned, unsigned, double, bool>(), py::arg("gen") = 1u,
196 py::arg("ker") = 63u, py::arg("q") = 1.0, py::arg("threshold") = 1u, py::arg("n_gen_mark") = 7u,
197 py::arg("evalstop") = 100000u, py::arg("focus") = 0., py::arg("memory") = false);
198 maco_.def(py::init<unsigned, unsigned, double, unsigned, unsigned, unsigned, double, bool, unsigned>(),
199 py::arg("gen") = 1u, py::arg("ker") = 63u, py::arg("q") = 1.0, py::arg("threshold") = 1u,
200 py::arg("n_gen_mark") = 7u, py::arg("evalstop") = 100000u, py::arg("focus") = 0.,
201 py::arg("memory") = false, py::arg("seed"));
202 // maco needs an ad hoc exposition for the log as one entry is a vector (ideal_point)
203 maco_.def(
204 "get_log",
205 [](const pagmo::maco &a) -> py::list {
206 py::list retval;
207 for (const auto &t : a.get_log()) {
208 retval.append(py::make_tuple(std::get<0>(t), std::get<1>(t),
209 vector_to_ndarr<py::array_t<double>>(std::get<2>(t))));
210 }
211 return retval;
212 },
213 maco_get_log_docstring().c_str());
214 maco_.def("get_seed", &pagmo::maco::get_seed, generic_uda_get_seed_docstring().c_str());
215 maco_.def("set_bfe", &pagmo::maco::set_bfe, maco_set_bfe_docstring().c_str(), py::arg("b"));
216
217 // NSPSO
218 auto nspso_ = expose_algorithm<pagmo::nspso>(m, algo, a_module, "nspso", nspso_docstring().c_str());
219 nspso_.def(py::init<unsigned, double, double, double, double, double, unsigned, std::string, bool>(),
220 py::arg("gen") = 1u, py::arg("omega") = 0.6, py::arg("c1") = 0.01, py::arg("c2") = 0.5,
221 py::arg("chi") = 0.5, py::arg("v_coeff") = 0.5, py::arg("leader_selection_range") = 2u,
222 py::arg("diversity_mechanism") = "crowding distance", py::arg("memory") = false);
223 nspso_.def(py::init<unsigned, double, double, double, double, double, unsigned, std::string, bool, unsigned>(),
224 py::arg("gen") = 1u, py::arg("omega") = 0.6, py::arg("c1") = 0.01, py::arg("c2") = 0.5,
225 py::arg("chi") = 0.5, py::arg("v_coeff") = 0.5, py::arg("leader_selection_range") = 2u,
226 py::arg("diversity_mechanism") = "crowding distance", py::arg("memory") = false, py::arg("seed"));
227 // nspso needs an ad hoc exposition for the log as one entry is a vector (ideal_point)
228 nspso_.def(
229 "get_log",
230 [](const pagmo::nspso &a) -> py::list {
231 py::list retval;
232 for (const auto &t : a.get_log()) {
233 retval.append(py::make_tuple(std::get<0>(t), std::get<1>(t),
234 vector_to_ndarr<py::array_t<double>>(std::get<2>(t))));
235 }
236 return retval;
237 },
238 nspso_get_log_docstring().c_str());
239 nspso_.def("get_seed", &pagmo::nspso::get_seed, generic_uda_get_seed_docstring().c_str());
240 nspso_.def("set_bfe", &pagmo::nspso::set_bfe, nspso_set_bfe_docstring().c_str(), py::arg("b"));
241
242 #if defined(PAGMO_WITH_NLOPT)
243 // NLopt.
244 auto nlopt_ = expose_algorithm<pagmo::nlopt>(m, algo, a_module, "nlopt", nlopt_docstring().c_str());
245 nlopt_
246 .def(py::init<const std::string &>(), py::arg("solver"))
247 // Properties for the stopping criteria.
248 .def_property("stopval", &pagmo::nlopt::get_stopval, &pagmo::nlopt::set_stopval,
249 nlopt_stopval_docstring().c_str())
250 .def_property("ftol_rel", &pagmo::nlopt::get_ftol_rel, &pagmo::nlopt::set_ftol_rel,
251 nlopt_ftol_rel_docstring().c_str())
252 .def_property("ftol_abs", &pagmo::nlopt::get_ftol_abs, &pagmo::nlopt::set_ftol_abs,
253 nlopt_ftol_abs_docstring().c_str())
254 .def_property("xtol_rel", &pagmo::nlopt::get_xtol_rel, &pagmo::nlopt::set_xtol_rel,
255 nlopt_xtol_rel_docstring().c_str())
256 .def_property("xtol_abs", &pagmo::nlopt::get_xtol_abs, &pagmo::nlopt::set_xtol_abs,
257 nlopt_xtol_abs_docstring().c_str())
258 .def_property("maxeval", &pagmo::nlopt::get_maxeval, &pagmo::nlopt::set_maxeval,
259 nlopt_maxeval_docstring().c_str())
260 .def_property("maxtime", &pagmo::nlopt::get_maxtime, &pagmo::nlopt::set_maxtime,
261 nlopt_maxtime_docstring().c_str());
262 expose_not_population_based(nlopt_, "nlopt");
263 expose_algo_log(nlopt_, nlopt_get_log_docstring().c_str());
264 nlopt_.def(
265 "get_last_opt_result", [](const pagmo::nlopt &n) { return static_cast<int>(n.get_last_opt_result()); },
266 nlopt_get_last_opt_result_docstring().c_str());
267 nlopt_.def("get_solver_name", &pagmo::nlopt::get_solver_name, nlopt_get_solver_name_docstring().c_str());
268 nlopt_.def_property(
269 "local_optimizer", [](pagmo::nlopt &n) { return n.get_local_optimizer(); },
270 [](pagmo::nlopt &n, const pagmo::nlopt *ptr) {
271 if (ptr) {
272 n.set_local_optimizer(*ptr);
273 } else {
274 n.unset_local_optimizer();
275 }
276 },
277 py::return_value_policy::reference_internal, nlopt_local_optimizer_docstring().c_str());
278 #endif
279 }
280
281 } // namespace pygmo
282