pymoo 0.6.1.5.dev0__cp313-cp313-macosx_11_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pymoo might be problematic. Click here for more details.

Files changed (328) hide show
  1. pymoo/__init__.py +3 -0
  2. pymoo/algorithms/__init__.py +0 -0
  3. pymoo/algorithms/base/__init__.py +0 -0
  4. pymoo/algorithms/base/bracket.py +38 -0
  5. pymoo/algorithms/base/genetic.py +109 -0
  6. pymoo/algorithms/base/line.py +62 -0
  7. pymoo/algorithms/base/local.py +39 -0
  8. pymoo/algorithms/base/meta.py +79 -0
  9. pymoo/algorithms/hyperparameters.py +89 -0
  10. pymoo/algorithms/moo/__init__.py +0 -0
  11. pymoo/algorithms/moo/age.py +310 -0
  12. pymoo/algorithms/moo/age2.py +194 -0
  13. pymoo/algorithms/moo/ctaea.py +298 -0
  14. pymoo/algorithms/moo/dnsga2.py +76 -0
  15. pymoo/algorithms/moo/kgb.py +446 -0
  16. pymoo/algorithms/moo/moead.py +183 -0
  17. pymoo/algorithms/moo/nsga2.py +113 -0
  18. pymoo/algorithms/moo/nsga3.py +358 -0
  19. pymoo/algorithms/moo/pinsga2.py +370 -0
  20. pymoo/algorithms/moo/rnsga2.py +188 -0
  21. pymoo/algorithms/moo/rnsga3.py +246 -0
  22. pymoo/algorithms/moo/rvea.py +214 -0
  23. pymoo/algorithms/moo/sms.py +195 -0
  24. pymoo/algorithms/moo/spea2.py +190 -0
  25. pymoo/algorithms/moo/unsga3.py +47 -0
  26. pymoo/algorithms/soo/__init__.py +0 -0
  27. pymoo/algorithms/soo/convex/__init__.py +0 -0
  28. pymoo/algorithms/soo/nonconvex/__init__.py +0 -0
  29. pymoo/algorithms/soo/nonconvex/brkga.py +161 -0
  30. pymoo/algorithms/soo/nonconvex/cmaes.py +554 -0
  31. pymoo/algorithms/soo/nonconvex/de.py +279 -0
  32. pymoo/algorithms/soo/nonconvex/direct.py +149 -0
  33. pymoo/algorithms/soo/nonconvex/es.py +203 -0
  34. pymoo/algorithms/soo/nonconvex/g3pcx.py +94 -0
  35. pymoo/algorithms/soo/nonconvex/ga.py +93 -0
  36. pymoo/algorithms/soo/nonconvex/ga_niching.py +223 -0
  37. pymoo/algorithms/soo/nonconvex/isres.py +74 -0
  38. pymoo/algorithms/soo/nonconvex/nelder.py +251 -0
  39. pymoo/algorithms/soo/nonconvex/optuna.py +80 -0
  40. pymoo/algorithms/soo/nonconvex/pattern.py +183 -0
  41. pymoo/algorithms/soo/nonconvex/pso.py +399 -0
  42. pymoo/algorithms/soo/nonconvex/pso_ep.py +297 -0
  43. pymoo/algorithms/soo/nonconvex/random_search.py +25 -0
  44. pymoo/algorithms/soo/nonconvex/sres.py +56 -0
  45. pymoo/algorithms/soo/univariate/__init__.py +0 -0
  46. pymoo/algorithms/soo/univariate/backtracking.py +59 -0
  47. pymoo/algorithms/soo/univariate/exp.py +46 -0
  48. pymoo/algorithms/soo/univariate/golden.py +65 -0
  49. pymoo/algorithms/soo/univariate/quadr_interp.py +81 -0
  50. pymoo/algorithms/soo/univariate/wolfe.py +163 -0
  51. pymoo/config.py +33 -0
  52. pymoo/constraints/__init__.py +3 -0
  53. pymoo/constraints/adaptive.py +62 -0
  54. pymoo/constraints/as_obj.py +56 -0
  55. pymoo/constraints/as_penalty.py +41 -0
  56. pymoo/constraints/eps.py +26 -0
  57. pymoo/constraints/from_bounds.py +36 -0
  58. pymoo/core/__init__.py +0 -0
  59. pymoo/core/algorithm.py +394 -0
  60. pymoo/core/callback.py +38 -0
  61. pymoo/core/crossover.py +77 -0
  62. pymoo/core/decision_making.py +102 -0
  63. pymoo/core/decomposition.py +76 -0
  64. pymoo/core/duplicate.py +163 -0
  65. pymoo/core/evaluator.py +116 -0
  66. pymoo/core/indicator.py +34 -0
  67. pymoo/core/individual.py +784 -0
  68. pymoo/core/infill.py +64 -0
  69. pymoo/core/initialization.py +42 -0
  70. pymoo/core/mating.py +39 -0
  71. pymoo/core/meta.py +21 -0
  72. pymoo/core/mixed.py +165 -0
  73. pymoo/core/mutation.py +44 -0
  74. pymoo/core/operator.py +40 -0
  75. pymoo/core/parameters.py +134 -0
  76. pymoo/core/plot.py +210 -0
  77. pymoo/core/population.py +180 -0
  78. pymoo/core/problem.py +460 -0
  79. pymoo/core/recorder.py +99 -0
  80. pymoo/core/repair.py +23 -0
  81. pymoo/core/replacement.py +96 -0
  82. pymoo/core/result.py +52 -0
  83. pymoo/core/sampling.py +43 -0
  84. pymoo/core/selection.py +61 -0
  85. pymoo/core/solution.py +10 -0
  86. pymoo/core/survival.py +103 -0
  87. pymoo/core/termination.py +70 -0
  88. pymoo/core/variable.py +399 -0
  89. pymoo/cython/__init__.py +0 -0
  90. pymoo/cython/calc_perpendicular_distance.cpython-313-darwin.so +0 -0
  91. pymoo/cython/calc_perpendicular_distance.pyx +67 -0
  92. pymoo/cython/decomposition.cpython-313-darwin.so +0 -0
  93. pymoo/cython/decomposition.pyx +165 -0
  94. pymoo/cython/hv.cpython-313-darwin.so +0 -0
  95. pymoo/cython/hv.pyx +18 -0
  96. pymoo/cython/info.cpython-313-darwin.so +0 -0
  97. pymoo/cython/info.pyx +5 -0
  98. pymoo/cython/mnn.cpython-313-darwin.so +0 -0
  99. pymoo/cython/mnn.pyx +273 -0
  100. pymoo/cython/non_dominated_sorting.cpython-313-darwin.so +0 -0
  101. pymoo/cython/non_dominated_sorting.pyx +645 -0
  102. pymoo/cython/pruning_cd.cpython-313-darwin.so +0 -0
  103. pymoo/cython/pruning_cd.pyx +197 -0
  104. pymoo/cython/stochastic_ranking.cpython-313-darwin.so +0 -0
  105. pymoo/cython/stochastic_ranking.pyx +49 -0
  106. pymoo/cython/utils.pxd +129 -0
  107. pymoo/cython/vendor/__init__.py +0 -0
  108. pymoo/cython/vendor/hypervolume.cpp +1621 -0
  109. pymoo/cython/vendor/hypervolume.h +63 -0
  110. pymoo/decomposition/__init__.py +0 -0
  111. pymoo/decomposition/aasf.py +24 -0
  112. pymoo/decomposition/asf.py +10 -0
  113. pymoo/decomposition/pbi.py +13 -0
  114. pymoo/decomposition/perp_dist.py +13 -0
  115. pymoo/decomposition/tchebicheff.py +11 -0
  116. pymoo/decomposition/util.py +13 -0
  117. pymoo/decomposition/weighted_sum.py +8 -0
  118. pymoo/docs.py +187 -0
  119. pymoo/experimental/__init__.py +0 -0
  120. pymoo/experimental/algorithms/__init__.py +0 -0
  121. pymoo/experimental/algorithms/gde3.py +57 -0
  122. pymoo/gradient/__init__.py +21 -0
  123. pymoo/gradient/automatic.py +57 -0
  124. pymoo/gradient/grad_autograd.py +105 -0
  125. pymoo/gradient/grad_complex.py +35 -0
  126. pymoo/gradient/grad_jax.py +51 -0
  127. pymoo/gradient/toolbox/__init__.py +6 -0
  128. pymoo/indicators/__init__.py +0 -0
  129. pymoo/indicators/distance_indicator.py +55 -0
  130. pymoo/indicators/gd.py +7 -0
  131. pymoo/indicators/gd_plus.py +7 -0
  132. pymoo/indicators/hv/__init__.py +63 -0
  133. pymoo/indicators/hv/exact.py +71 -0
  134. pymoo/indicators/hv/exact_2d.py +102 -0
  135. pymoo/indicators/hv/monte_carlo.py +74 -0
  136. pymoo/indicators/igd.py +7 -0
  137. pymoo/indicators/igd_plus.py +7 -0
  138. pymoo/indicators/kktpm.py +151 -0
  139. pymoo/indicators/migd.py +55 -0
  140. pymoo/indicators/rmetric.py +203 -0
  141. pymoo/indicators/spacing.py +52 -0
  142. pymoo/mcdm/__init__.py +0 -0
  143. pymoo/mcdm/compromise_programming.py +19 -0
  144. pymoo/mcdm/high_tradeoff.py +40 -0
  145. pymoo/mcdm/pseudo_weights.py +32 -0
  146. pymoo/operators/__init__.py +0 -0
  147. pymoo/operators/control.py +187 -0
  148. pymoo/operators/crossover/__init__.py +0 -0
  149. pymoo/operators/crossover/binx.py +45 -0
  150. pymoo/operators/crossover/dex.py +122 -0
  151. pymoo/operators/crossover/erx.py +162 -0
  152. pymoo/operators/crossover/expx.py +51 -0
  153. pymoo/operators/crossover/hux.py +37 -0
  154. pymoo/operators/crossover/nox.py +13 -0
  155. pymoo/operators/crossover/ox.py +84 -0
  156. pymoo/operators/crossover/pcx.py +82 -0
  157. pymoo/operators/crossover/pntx.py +49 -0
  158. pymoo/operators/crossover/sbx.py +125 -0
  159. pymoo/operators/crossover/spx.py +5 -0
  160. pymoo/operators/crossover/ux.py +20 -0
  161. pymoo/operators/mutation/__init__.py +0 -0
  162. pymoo/operators/mutation/bitflip.py +17 -0
  163. pymoo/operators/mutation/gauss.py +58 -0
  164. pymoo/operators/mutation/inversion.py +42 -0
  165. pymoo/operators/mutation/nom.py +7 -0
  166. pymoo/operators/mutation/pm.py +94 -0
  167. pymoo/operators/mutation/rm.py +23 -0
  168. pymoo/operators/repair/__init__.py +0 -0
  169. pymoo/operators/repair/bounce_back.py +32 -0
  170. pymoo/operators/repair/bounds_repair.py +95 -0
  171. pymoo/operators/repair/inverse_penalty.py +89 -0
  172. pymoo/operators/repair/rounding.py +18 -0
  173. pymoo/operators/repair/to_bound.py +31 -0
  174. pymoo/operators/repair/vtype.py +11 -0
  175. pymoo/operators/sampling/__init__.py +0 -0
  176. pymoo/operators/sampling/lhs.py +73 -0
  177. pymoo/operators/sampling/rnd.py +50 -0
  178. pymoo/operators/selection/__init__.py +0 -0
  179. pymoo/operators/selection/rnd.py +72 -0
  180. pymoo/operators/selection/tournament.py +76 -0
  181. pymoo/operators/survival/__init__.py +0 -0
  182. pymoo/operators/survival/rank_and_crowding/__init__.py +1 -0
  183. pymoo/operators/survival/rank_and_crowding/classes.py +209 -0
  184. pymoo/operators/survival/rank_and_crowding/metrics.py +208 -0
  185. pymoo/optimize.py +72 -0
  186. pymoo/problems/__init__.py +157 -0
  187. pymoo/problems/dyn.py +47 -0
  188. pymoo/problems/dynamic/__init__.py +0 -0
  189. pymoo/problems/dynamic/cec2015.py +108 -0
  190. pymoo/problems/dynamic/df.py +452 -0
  191. pymoo/problems/dynamic/misc.py +167 -0
  192. pymoo/problems/functional.py +48 -0
  193. pymoo/problems/many/__init__.py +5 -0
  194. pymoo/problems/many/cdtlz.py +159 -0
  195. pymoo/problems/many/dcdtlz.py +88 -0
  196. pymoo/problems/many/dtlz.py +264 -0
  197. pymoo/problems/many/wfg.py +550 -0
  198. pymoo/problems/multi/__init__.py +14 -0
  199. pymoo/problems/multi/bnh.py +34 -0
  200. pymoo/problems/multi/carside.py +48 -0
  201. pymoo/problems/multi/clutch.py +104 -0
  202. pymoo/problems/multi/csi.py +55 -0
  203. pymoo/problems/multi/ctp.py +198 -0
  204. pymoo/problems/multi/dascmop.py +213 -0
  205. pymoo/problems/multi/kursawe.py +25 -0
  206. pymoo/problems/multi/modact.py +68 -0
  207. pymoo/problems/multi/mw.py +400 -0
  208. pymoo/problems/multi/omnitest.py +48 -0
  209. pymoo/problems/multi/osy.py +32 -0
  210. pymoo/problems/multi/srn.py +28 -0
  211. pymoo/problems/multi/sympart.py +94 -0
  212. pymoo/problems/multi/tnk.py +24 -0
  213. pymoo/problems/multi/truss2d.py +83 -0
  214. pymoo/problems/multi/welded_beam.py +41 -0
  215. pymoo/problems/multi/wrm.py +36 -0
  216. pymoo/problems/multi/zdt.py +151 -0
  217. pymoo/problems/multi_to_single.py +22 -0
  218. pymoo/problems/single/__init__.py +12 -0
  219. pymoo/problems/single/ackley.py +24 -0
  220. pymoo/problems/single/cantilevered_beam.py +34 -0
  221. pymoo/problems/single/flowshop_scheduling.py +112 -0
  222. pymoo/problems/single/g.py +874 -0
  223. pymoo/problems/single/griewank.py +18 -0
  224. pymoo/problems/single/himmelblau.py +15 -0
  225. pymoo/problems/single/knapsack.py +48 -0
  226. pymoo/problems/single/mopta08.py +26 -0
  227. pymoo/problems/single/multimodal.py +20 -0
  228. pymoo/problems/single/pressure_vessel.py +30 -0
  229. pymoo/problems/single/rastrigin.py +20 -0
  230. pymoo/problems/single/rosenbrock.py +22 -0
  231. pymoo/problems/single/schwefel.py +18 -0
  232. pymoo/problems/single/simple.py +13 -0
  233. pymoo/problems/single/sphere.py +19 -0
  234. pymoo/problems/single/traveling_salesman.py +79 -0
  235. pymoo/problems/single/zakharov.py +19 -0
  236. pymoo/problems/static.py +14 -0
  237. pymoo/problems/util.py +42 -0
  238. pymoo/problems/zero_to_one.py +27 -0
  239. pymoo/termination/__init__.py +23 -0
  240. pymoo/termination/collection.py +12 -0
  241. pymoo/termination/cv.py +48 -0
  242. pymoo/termination/default.py +45 -0
  243. pymoo/termination/delta.py +64 -0
  244. pymoo/termination/fmin.py +16 -0
  245. pymoo/termination/ftol.py +144 -0
  246. pymoo/termination/indicator.py +49 -0
  247. pymoo/termination/max_eval.py +14 -0
  248. pymoo/termination/max_gen.py +15 -0
  249. pymoo/termination/max_time.py +20 -0
  250. pymoo/termination/robust.py +34 -0
  251. pymoo/termination/xtol.py +33 -0
  252. pymoo/util/__init__.py +0 -0
  253. pymoo/util/archive.py +150 -0
  254. pymoo/util/cache.py +29 -0
  255. pymoo/util/clearing.py +82 -0
  256. pymoo/util/display/__init__.py +0 -0
  257. pymoo/util/display/column.py +52 -0
  258. pymoo/util/display/display.py +34 -0
  259. pymoo/util/display/multi.py +96 -0
  260. pymoo/util/display/output.py +53 -0
  261. pymoo/util/display/progress.py +54 -0
  262. pymoo/util/display/single.py +67 -0
  263. pymoo/util/dominator.py +67 -0
  264. pymoo/util/function_loader.py +129 -0
  265. pymoo/util/hv.py +23 -0
  266. pymoo/util/matlab_engine.py +39 -0
  267. pymoo/util/misc.py +460 -0
  268. pymoo/util/mnn.py +70 -0
  269. pymoo/util/nds/__init__.py +0 -0
  270. pymoo/util/nds/dominance_degree_non_dominated_sort.py +159 -0
  271. pymoo/util/nds/efficient_non_dominated_sort.py +152 -0
  272. pymoo/util/nds/fast_non_dominated_sort.py +70 -0
  273. pymoo/util/nds/naive_non_dominated_sort.py +36 -0
  274. pymoo/util/nds/non_dominated_sorting.py +67 -0
  275. pymoo/util/nds/tree_based_non_dominated_sort.py +133 -0
  276. pymoo/util/normalization.py +312 -0
  277. pymoo/util/optimum.py +42 -0
  278. pymoo/util/plotting.py +177 -0
  279. pymoo/util/pruning_cd.py +89 -0
  280. pymoo/util/randomized_argsort.py +60 -0
  281. pymoo/util/ref_dirs/__init__.py +24 -0
  282. pymoo/util/ref_dirs/construction.py +88 -0
  283. pymoo/util/ref_dirs/das_dennis.py +52 -0
  284. pymoo/util/ref_dirs/energy.py +319 -0
  285. pymoo/util/ref_dirs/energy_layer.py +119 -0
  286. pymoo/util/ref_dirs/genetic_algorithm.py +63 -0
  287. pymoo/util/ref_dirs/incremental.py +68 -0
  288. pymoo/util/ref_dirs/misc.py +128 -0
  289. pymoo/util/ref_dirs/optimizer.py +59 -0
  290. pymoo/util/ref_dirs/performance.py +162 -0
  291. pymoo/util/ref_dirs/reduction.py +85 -0
  292. pymoo/util/ref_dirs/sample_and_map.py +24 -0
  293. pymoo/util/reference_direction.py +260 -0
  294. pymoo/util/remote.py +55 -0
  295. pymoo/util/roulette.py +27 -0
  296. pymoo/util/running_metric.py +128 -0
  297. pymoo/util/sliding_window.py +25 -0
  298. pymoo/util/stochastic_ranking.py +32 -0
  299. pymoo/util/value_functions.py +719 -0
  300. pymoo/util/vectors.py +40 -0
  301. pymoo/util/vf_dominator.py +99 -0
  302. pymoo/vendor/__init__.py +0 -0
  303. pymoo/vendor/cec2018.py +398 -0
  304. pymoo/vendor/gta.py +617 -0
  305. pymoo/vendor/hv.py +267 -0
  306. pymoo/vendor/vendor_cmaes.py +412 -0
  307. pymoo/vendor/vendor_coco.py +81 -0
  308. pymoo/vendor/vendor_scipy.py +232 -0
  309. pymoo/version.py +1 -0
  310. pymoo/visualization/__init__.py +8 -0
  311. pymoo/visualization/fitness_landscape.py +127 -0
  312. pymoo/visualization/heatmap.py +123 -0
  313. pymoo/visualization/pcp.py +120 -0
  314. pymoo/visualization/petal.py +91 -0
  315. pymoo/visualization/radar.py +108 -0
  316. pymoo/visualization/radviz.py +68 -0
  317. pymoo/visualization/scatter.py +150 -0
  318. pymoo/visualization/star_coordinate.py +75 -0
  319. pymoo/visualization/util.py +123 -0
  320. pymoo/visualization/video/__init__.py +0 -0
  321. pymoo/visualization/video/callback_video.py +82 -0
  322. pymoo/visualization/video/one_var_one_obj.py +57 -0
  323. pymoo/visualization/video/two_var_one_obj.py +62 -0
  324. pymoo-0.6.1.5.dev0.dist-info/METADATA +187 -0
  325. pymoo-0.6.1.5.dev0.dist-info/RECORD +328 -0
  326. pymoo-0.6.1.5.dev0.dist-info/WHEEL +6 -0
  327. pymoo-0.6.1.5.dev0.dist-info/licenses/LICENSE +191 -0
  328. pymoo-0.6.1.5.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,719 @@
1
+ import numpy as np
2
+ import pymoo
3
+ import scipy
4
+ from pymoo.optimize import minimize as moomin
5
+ from scipy.optimize import minimize as scimin
6
+ from pymoo.core.problem import Problem
7
+ import matplotlib.pyplot as plt
8
+ from scipy.optimize import NonlinearConstraint
9
+ from scipy.optimize import Bounds
10
+ from pymoo.algorithms.soo.nonconvex.es import ES
11
+ from pymoo.algorithms.soo.nonconvex.ga import GA
12
+ import math
13
+ from operator import mul
14
+ from functools import reduce
15
+ from pymoo.termination.default import DefaultSingleObjectiveTermination
16
+ import sys
17
+
18
+
19
+ # Input 1: A list of non-dominated points
20
+ # Input 2: The ranking of the given non-dominated points
21
+ # Input 3: constraint function for optimizing the value func
22
+ # Input 4: the skeleton utility function that we're trying to optimize
23
+ def create_vf(P, ranks, ineq_constr, vf="linear", delta=0.1, eps_max=1000, method="trust-constr", verbose=False):
24
+
25
+ if vf == "linear":
26
+ return create_linear_vf(P, ranks, delta, eps_max, method, verbose)
27
+ elif vf == "poly":
28
+ return create_poly_vf(P, ranks, delta, eps_max, method, verbose)
29
+
30
+ else:
31
+ raise ValueError("Value function '%d' not supported." % vf)
32
+
33
+ return lambda f_new: np.sum(f_new)
34
+
35
+ def create_poly_vf(P, ranks, delta=0.1, eps_max=1000, method="trust-constr", verbose=False):
36
+
37
+ if method == "trust-constr" or method == "SLSQP":
38
+ return create_vf_scipy_poly(P, ranks, delta, eps_max, method=method, verbose=verbose)
39
+ elif method == "ES":
40
+ return create_vf_pymoo_poly(P, ranks, delta, eps_max, method=method, verbose=verbose)
41
+ else:
42
+ raise ValueError("Optimization method %s not supported" % method)
43
+
44
+
45
+
46
+ def create_linear_vf(P, ranks, delta=0.1, eps_max=1000, method="trust-constr"):
47
+
48
+ if method == "trust-constr" or method == "SLSQP":
49
+ return create_vf_scipy_linear(P, ranks, delta, eps_max, method)
50
+ elif method == "ES":
51
+ return create_vf_pymoo_linear(P, ranks, delta, eps_max, method)
52
+ else:
53
+ raise ValueError("Optimization method %s not supported" % method)
54
+
55
+
56
+ def create_vf_scipy_poly(P, ranks, delta, eps_max, method="trust-constr", verbose=False):
57
+
58
+ # Gathering basic info
59
+ M = P.shape[1]
60
+
61
+ P_count = P.shape[0]
62
+
63
+ # Inequality constraints - check that each term of S in our obj is non-negative for each P
64
+ ineq_lb = [-np.inf] * (P_count*M)
65
+ ineq_ub = [0] * (P_count*M)
66
+
67
+ # Inequality constraints - check VF is monotonically increasing with user preference
68
+ ineq_lb += [-np.inf] * (P_count - 1)
69
+ ineq_ub += [0] * (P_count - 1)
70
+
71
+
72
+ # Equality constraints (Make sure all terms in VF add up to 1 per term of product)
73
+ for m in range(M):
74
+ ineq_lb.append(0)
75
+ ineq_ub.append(0)
76
+
77
+ P_sorted = _sort_P(P, ranks)
78
+ ranks.sort()
79
+
80
+ constr = NonlinearConstraint(_build_constr_poly(P_sorted, poly_vf, ranks, delta), ineq_lb, ineq_ub)
81
+
82
+ # Bounds on x
83
+ x_lb = []
84
+ x_ub = []
85
+ for m in range(M**2):
86
+ x_lb.append(0)
87
+ x_ub.append(1)
88
+
89
+ for m in range(M):
90
+ x_lb.append(-1000)
91
+ x_ub.append(1000)
92
+
93
+ x_lb.append(-1000)
94
+ x_ub.append(eps_max)
95
+
96
+ bounds = Bounds(x_lb, x_ub)
97
+
98
+ # Initial position
99
+ x0 = [1] * (M**2 + M + 1)
100
+
101
+ if method == 'trust-constr':
102
+ # The trust-constr method always finds the decision space linear
103
+ hess = lambda x: np.zeros((len(x0), len(x0)))
104
+ else:
105
+ hess = None
106
+
107
+ res = scimin(_obj_func,
108
+ x0,
109
+ constraints=constr,
110
+ bounds=bounds,
111
+ method=method,
112
+ hess=hess)
113
+
114
+ # package up results
115
+ vf = lambda P_in: poly_vf(P_in, res.x[0:-1])
116
+ params = res.x[0:-1]
117
+ epsilon = res.x[-1]
118
+
119
+ fit = _validate_vf(res, verbose)
120
+
121
+ return vfResults(vf, params, epsilon, fit)
122
+
123
+
124
+ def create_vf_scipy_linear(P, ranks, delta, eps_max, method="trust-constr", verbose=False):
125
+
126
+ # Gathering basic info
127
+ M = P.shape[1]
128
+
129
+ # Sort P
130
+ P_sorted = _sort_P(P, ranks)
131
+ ranks.sort()
132
+
133
+ # Inequality constraints
134
+ lb = [-np.inf] * (P.shape[0] - 1)
135
+ ub = [0] * (P.shape[0] - 1)
136
+
137
+ # Equality constraints
138
+ lb.append(0)
139
+ ub.append(0)
140
+
141
+ constr = NonlinearConstraint(_build_constr_linear(P_sorted, linear_vf, ranks, delta), lb, ub)
142
+
143
+ # Bounds on x
144
+ x_lb = []
145
+ x_ub = []
146
+
147
+ for m in range(M):
148
+ x_lb.append(0)
149
+ x_ub.append(1)
150
+
151
+ x_lb.append(-1000)
152
+ x_ub.append(eps_max)
153
+
154
+ bounds = Bounds(x_lb, x_ub)
155
+
156
+ # Initial position
157
+ x0 = [0.5] * (M+1)
158
+
159
+ if method == 'trust-constr':
160
+ # The trust-constr method always finds the decision space linear
161
+ hess = lambda x: np.zeros((len(x0), len(x0)))
162
+ else:
163
+ hess = None
164
+
165
+ res = scimin(_obj_func,
166
+ x0,
167
+ constraints= constr,
168
+ bounds=bounds,
169
+ method=method,
170
+ hess=hess)
171
+
172
+ # package up results
173
+ vf = lambda P_in: linear_vf(P_in, res.x[0:-1])
174
+ params = res.x[0:-1]
175
+ epsilon = res.x[-1]
176
+ fit = _validate_vf(res, verbose)
177
+
178
+ return vfResults(vf, params, epsilon, fit)
179
+
180
+ def create_vf_pymoo_linear(P, ranks, delta, eps_max, method="ES", verbose=False):
181
+
182
+ vf_prob = OptimizeLinearVF(P, ranks, delta, eps_max, linear_vf)
183
+
184
+ if method == "ES":
185
+ algorithm = ES()
186
+ elif method == "GA":
187
+ algorithm = GA()
188
+ else:
189
+ raise ValueError("Optimization method %s not supported" % method)
190
+
191
+ res = moomin(vf_prob,
192
+ algorithm,
193
+ ('n_gen', 200),
194
+ verbose=verbose,
195
+ seed=1)
196
+
197
+ vf = lambda P_in: linear_vf(P_in, res.X[0:-1])
198
+
199
+ if res.X is not None:
200
+ params = res.X[0:-1]
201
+ epsilon = res.X[-1]
202
+ else:
203
+ params = None
204
+ epsilon = -1000
205
+
206
+ fit = _validate_vf(res, verbose)
207
+
208
+ return vfResults(vf, params, epsilon, fit)
209
+
210
+
211
+ def create_vf_pymoo_poly(P, ranks, delta, eps_max, method="trust-constr", verbose=False):
212
+
213
+ vf_prob = OptimizePolyVF(P, ranks, delta, eps_max, poly_vf)
214
+
215
+ if method == "ES":
216
+ algorithm = ES()
217
+ elif method == "GA":
218
+ algorithm = GA()
219
+ else:
220
+ raise ValueError("Optimization method %s not supported" % method)
221
+
222
+ res = moomin(vf_prob,
223
+ algorithm,
224
+ ('n_gen', 100),
225
+ verbose=verbose,
226
+ seed=1)
227
+
228
+ vf = lambda P_in: poly_vf(P_in, res.X[0:-1])
229
+
230
+ if res.X is not None:
231
+ params = res.X[0:-1]
232
+ epsilon = res.X[-1]
233
+ else:
234
+ params = None
235
+ epsilon = -1000
236
+
237
+ fit = _validate_vf(res, verbose)
238
+
239
+ return vfResults(vf, params, epsilon, fit)
240
+
241
+
242
+ def linear_vf(P, x):
243
+
244
+ return np.matmul(P, x.T)
245
+
246
+ def poly_vf(P, x):
247
+
248
+ # find out M
249
+ M = P.shape[-1]
250
+
251
+ result = []
252
+
253
+ if len(x.shape) == 1:
254
+ x_len = 1
255
+ else:
256
+ x_len = x.shape[0]
257
+
258
+ # Calculate value for each row of x
259
+ for xi in range(x_len):
260
+
261
+ running_product = 1
262
+
263
+ # Get current x
264
+ if x_len == 1:
265
+ curr_x = x
266
+ else:
267
+ curr_x = x[xi, :]
268
+
269
+ S = _calc_S(P, curr_x)
270
+
271
+ # Multiply all of the S terms together along the final axis
272
+ product = np.prod(S, axis = len(np.shape(S))-1)
273
+
274
+ result.append(product)
275
+
276
+ return np.squeeze(np.array(result))
277
+
278
+
279
+ def plot_vf(P, vf, show=True):
280
+
281
+ plt.scatter(P[:,0], P[:,1], marker=".", color="red", s=200 )
282
+
283
+
284
+ for i in range(np.size(P,0)):
285
+ plt.annotate("P%d" % (i+1), (P[i,0], P[i,1]))
286
+
287
+ min_x = min(P[:,0])
288
+ min_y = min(P[:,1])
289
+ max_x = max(P[:,0])
290
+ max_y = max(P[:,1])
291
+
292
+ x,y = np.meshgrid(np.linspace(min_x, max_x, 1000), np.linspace(min_y, max_y, 1000))
293
+
294
+ z = vf(np.stack((x,y), axis=2))
295
+
296
+ values_at_P = []
297
+ for p in range(np.size(P,0)):
298
+ values_at_P.append(vf(P[p,:]))
299
+
300
+ values_at_P.sort()
301
+
302
+ plt.contour(x,y,z, levels=values_at_P)
303
+
304
+ plt.colorbar()
305
+
306
+ if show:
307
+ plt.show()
308
+
309
+ return plt
310
+
311
+
312
+
313
+ ## ---------------- Polynomial VF creation functions ------------------
314
+
315
+ def _ineq_constr_poly(x, P, vf, ranks, delta):
316
+ if len(x.shape) == 1:
317
+ return _ineq_constr_1D_poly(x, P, vf, ranks, delta)
318
+ else:
319
+ return _ineq_constr_2D_poly(x, P, vf, ranks, delta)
320
+
321
+
322
+ def _build_ineq_constr_poly(P, vf, ranks, delta):
323
+
324
+ ineq_func = lambda x : _ineq_constr_poly(x, P, vf, ranks, delta)
325
+
326
+ return ineq_func
327
+
328
+ def _eq_constr_poly(x):
329
+
330
+ M = math.floor(math.sqrt(6))
331
+
332
+ if len(x.shape) == 1:
333
+ result = []
334
+ for m in range(M):
335
+ result.append(-(sum(x[m*M:m*M+M]) - 1))
336
+
337
+ else:
338
+
339
+ pop_size = np.size(x,0)
340
+
341
+ result = []
342
+
343
+ for xi in range(pop_size):
344
+
345
+ result_for_xi = []
346
+
347
+ for m in range(M):
348
+
349
+ result_for_xi.append(-(sum(x[xi,m*M:m*M+M]) - 1))
350
+
351
+ result.append(result_for_xi)
352
+
353
+ result = np.array(result)
354
+
355
+ return result
356
+
357
+
358
+ def _build_constr_poly(P, vf, ranks, delta):
359
+
360
+ ineq_constr_func = _build_ineq_constr_poly(P, vf, ranks, delta)
361
+
362
+ return lambda x : np.append(ineq_constr_func(x), _eq_constr_poly(x))
363
+
364
+
365
+ def _ineq_constr_2D_poly(x, P, vf, ranks, delta):
366
+
367
+ pop_size = np.size(x,0)
368
+
369
+ P_count = P.shape[0]
370
+ M = P.shape[1]
371
+
372
+ S_constr_len = M * P_count
373
+ increasing_len = P_count - 1
374
+
375
+ G = np.ones((pop_size, S_constr_len + increasing_len))*-99
376
+
377
+ for xi in range(pop_size):
378
+
379
+ G[xi, :] = _ineq_constr_1D_poly(x[xi, :], P, vf, ranks, delta)
380
+
381
+ return G
382
+
383
+
384
+ def _ineq_constr_1D_poly(x, P, vf, ranks, delta):
385
+
386
+ ep = x[-1]
387
+
388
+ P_count = P.shape[0]
389
+ M = P.shape[1]
390
+
391
+ S_constr_len = M * P_count
392
+ increasing_len = P_count - 1
393
+
394
+ G = np.ones((1, S_constr_len + increasing_len))*-99
395
+
396
+ # Checking to make sure each S term in the polynomial objective function is non-negative
397
+ S = _calc_S(P, x[0:-1]) * -1
398
+
399
+ G[:, 0:S_constr_len] = S.reshape(1, S_constr_len)
400
+
401
+
402
+ # Pair-wise compare each ranked member of P, seeing if our proposed utility
403
+ # function increases monotonically as rank increases
404
+ for p in range(P_count - 1):
405
+
406
+ current_P_val = vf(P[[p],:], x[0:-1])
407
+ next_P_val = vf(P[[p+1],:], x[0:-1])
408
+
409
+ current_rank = ranks[p]
410
+ next_rank = ranks[p+1]
411
+
412
+ if current_rank == next_rank:
413
+ # Handle ties
414
+ G[:,[p + S_constr_len]] = np.abs(current_P_val - next_P_val) - delta*ep
415
+ else:
416
+ G[:,[p + S_constr_len]] = -(current_P_val - next_P_val) + ep
417
+
418
+
419
+ return G
420
+
421
+ ## ---------------- Linear VF creation functions ------------------
422
+
423
+ def _build_ineq_constr_linear(P, vf, ranks, delta):
424
+
425
+ ineq_func = lambda x : _ineq_constr_linear(x, P, vf, ranks, delta)
426
+
427
+ return ineq_func
428
+
429
+ def _build_constr_linear(P, vf, ranks, delta):
430
+
431
+ ineq_constr_func = _build_ineq_constr_linear(P, vf, ranks, delta);
432
+
433
+ return lambda x : np.append(ineq_constr_func(x), _eq_constr_linear(x))
434
+
435
+
436
+ def _ineq_constr_linear(x, P, vf, ranks, delta):
437
+ if len(x.shape) == 1:
438
+ return _ineq_constr_1D_linear(x, P, vf, ranks, delta)
439
+ else:
440
+ return _ineq_constr_2D_linear(x, P, vf, ranks, delta)
441
+
442
+
443
+ def _ineq_constr_2D_linear(x, P, vf, ranks, delta):
444
+
445
+ ep = np.column_stack([x[:,-1]])
446
+ pop_size = np.size(x,0)
447
+
448
+ G = np.ones((pop_size, np.size(P,0)-1))*-99
449
+
450
+ # Pair-wise compare each ranked member of P, seeing if our proposed utility
451
+ # function increases monotonically as rank increases
452
+ for p in range(np.size(P,0) - 1):
453
+
454
+
455
+ current_P_val = vf(P[[p],:], x[:, 0:-1])
456
+ next_P = vf(P[[p+1],:], x[:, 0:-1])
457
+
458
+ current_rank = ranks[p]
459
+ next_rank = ranks[p+1]
460
+
461
+
462
+ if current_rank == next_rank:
463
+ # Handle ties
464
+ G[:,[p]] = np.abs(current_P_val.T - next_P.T) - delta*ep
465
+ else:
466
+ # As vf returns, each column is an value of P for a given x in the population
467
+ # We transpose to make each ROW the value of P
468
+ G[:,[p]] = -(current_P_val.T - next_P.T) + ep
469
+
470
+
471
+ return G
472
+
473
+
474
+ def _ineq_constr_1D_linear(x, P, vf, ranks, delta):
475
+
476
+ ep = x[-1]
477
+
478
+ G = np.ones((1, np.size(P,0)-1))*-99
479
+
480
+ # Pair-wise compare each ranked member of P, seeing if our proposed utility
481
+ # function increases monotonically as rank increases
482
+ for p in range(np.size(P,0) - 1):
483
+
484
+ current_P_val = vf(P[[p],:], x[0:-1])
485
+ next_P = vf(P[[p+1],:], x[0:-1])
486
+
487
+ current_rank = ranks[p]
488
+ next_rank = ranks[p+1]
489
+
490
+ if current_rank == next_rank:
491
+ # Handle ties
492
+ G[:,[p]] = np.abs(current_P_val - next_P) - delta*ep
493
+ else:
494
+ G[:,[p]] = -(current_P_val - next_P) + ep
495
+
496
+
497
+
498
+ return G
499
+
500
+ def _obj_func(x):
501
+
502
+ # check if x is a 1D array or a 2D array
503
+ if len(x.shape) == 1:
504
+ ep = x[-1]
505
+ else:
506
+ ep = np.column_stack([x[:,-1]])
507
+
508
+ return -ep
509
+
510
+ def _sort_P(P, ranks):
511
+ P_with_rank = np.hstack((P, np.array([ranks]).T))
512
+
513
+ P_sorted = P[P_with_rank[:, -1].argsort()]
514
+
515
+ return P_sorted
516
+
517
+ # Can have several P instances, but assumes one x instance
518
+ def _calc_S(P, x):
519
+
520
+ M = P.shape[-1]
521
+
522
+ # reshape x into a matrix called k
523
+ k = np.array(x[0:M*M].reshape(M,M), copy=True)
524
+ k = k.T
525
+
526
+ # roll each column down to work with equation 5
527
+ for col in range(1, k.shape[1]):
528
+ k[:,[col]] = np.roll(k[:,[col]], col)
529
+
530
+
531
+ l = x[M*M:(M*M)+M].reshape(M,1)
532
+ l = l.T
533
+
534
+ # Calc S for an arbitrary dimensional space of P
535
+ S = np.matmul(P, k) + (l * 2)
536
+
537
+ return np.squeeze(S)
538
+
539
+
540
+ # Constraint that states that the x values must add up to 1
541
+ def _eq_constr_linear(x):
542
+
543
+ if len(x.shape) == 1:
544
+ eq_cons = sum(x[0:-1]) - 1
545
+ else:
546
+ eq_cons = np.sum(x[:,0:-1],1, keepdims=True) - 1
547
+
548
+ return eq_cons
549
+
550
+
551
+ # Makes a comparator for a given value function and the P that is ranked second in the
552
+ def make_vf_comparator(vf, P_rank_2):
553
+
554
+ return lambda P : vf_comparator(vf, P_rank_2, P)
555
+
556
+ def vf_comparator(vf, P_rank_2, P):
557
+
558
+ reference_value = vf(P_rank_2)
559
+
560
+ if reference_value > vf(P):
561
+ return -1
562
+ elif reference_value < vf(P):
563
+ return 1
564
+ else:
565
+ return 0
566
+
567
+
568
+ class OptimizeLinearVF(Problem):
569
+
570
+ def __init__(self, P, ranks, delta, eps_max, vf):
571
+
572
+ # One var for each dimension of the object space, plus epsilon
573
+ n_var_vf = np.size(P, 1) + 1
574
+
575
+ # it has one inequality constraints for every pair of solutions in P
576
+ n_ieq_c_vf = np.size(P,0) - 1
577
+
578
+ xl_vf = [0.0] * n_var_vf
579
+ xu_vf = [1.0] * n_var_vf
580
+
581
+ # upper/lower bound on the epsilon variable is -1000/1000
582
+ xl_vf[-1] = -1000
583
+ xu_vf[-1] = eps_max
584
+
585
+ # TODO start everything at 0.5
586
+
587
+ self.P = _sort_P(P, ranks)
588
+
589
+ self.ranks = ranks
590
+ self.ranks.sort()
591
+
592
+ self.vf = vf
593
+
594
+ self.ranks = ranks
595
+ self.delta = delta
596
+
597
+ super().__init__(n_var_vf, n_obj=1, n_ieq_constr=n_ieq_c_vf, n_eq_constr=1, xl=xl_vf, xu=xu_vf)
598
+
599
+ def _evaluate(self, x, out, *args, **kwargs):
600
+
601
+ ## Objective function:
602
+ obj = _obj_func(x)
603
+
604
+ # The objective function above returns a negated version of epsilon
605
+ ep = -obj
606
+
607
+ # maximize epsilon, or the minimum distance between each contour
608
+ out["F"] = obj
609
+
610
+ ## Inequality
611
+
612
+ ineq_func = _build_ineq_constr_linear(self.P, self.vf, self.ranks, self.delta)
613
+
614
+ out["G"] = ineq_func(x)
615
+
616
+ ## Equality constraint that keeps sum of x under 1
617
+ out["H"] = _eq_constr_linear(x)
618
+
619
+ def _validate_vf(res, verbose):
620
+
621
+ message = ""
622
+
623
+ if isinstance(res, pymoo.core.result.Result):
624
+ success = np.all(res.G <= 0)
625
+ epsilon = res.X[-1]
626
+ if not success:
627
+ message = "Constraints not met\n"
628
+ if epsilon < 0:
629
+ message = message + "Epsilon negative\n"
630
+
631
+
632
+ elif isinstance(res, scipy.optimize.optimize.OptimizeResult):
633
+ success = res.success and res.constr_violation <= 0
634
+ epsilon = res.x[-1]
635
+
636
+ if not (res.constr_violation <= 0):
637
+ message = "Constraints not met."
638
+ else:
639
+ message = res.message
640
+ else:
641
+ ValueError("Internal error: bad result objective given for validation")
642
+
643
+ if epsilon < 0 or not success:
644
+
645
+ if verbose:
646
+ sys.stderr.write("WARNING: Unable to fit value function\n")
647
+ sys.stderr.write(message + "\n")
648
+
649
+ return False
650
+ else:
651
+ return True
652
+
653
+
654
+ class OptimizePolyVF(Problem):
655
+
656
+ def __init__(self, P, ranks, delta, eps_max, vf):
657
+
658
+ M = P.shape[1]
659
+
660
+ P_count = P.shape[0]
661
+
662
+
663
+ # One var for each dimension of the object space, plus epsilon
664
+ n_var_vf = (M**2 + M + 1)
665
+
666
+ # it has one inequality constraints for every pair of solutions in P
667
+ n_ieq_c_vf = (P_count*M) + (P_count - 1)
668
+
669
+ xl_vf = [0.0] * n_var_vf
670
+ xu_vf = [1.0] * n_var_vf
671
+
672
+ # upper/lower bound on the epsilon variable is -1000/1000
673
+ xl_vf[-1] = -1000
674
+ xu_vf[-1] = eps_max
675
+
676
+ # TODO start everything at 0.5
677
+
678
+ self.P = _sort_P(P, ranks)
679
+
680
+ self.ranks = ranks
681
+ self.ranks.sort()
682
+
683
+ self.vf = vf
684
+
685
+ self.delta = delta
686
+
687
+ super().__init__(n_var_vf, n_obj=1, n_ieq_constr=n_ieq_c_vf, n_eq_constr=M, xl=xl_vf, xu=xu_vf)
688
+
689
+ def _evaluate(self, x, out, *args, **kwargs):
690
+
691
+ ## Objective function:
692
+ obj = _obj_func(x)
693
+
694
+ # The objective function above returns a negated version of epsilon
695
+ ep = -obj
696
+
697
+ # maximize epsilon, or the minimum distance between each contour
698
+ out["F"] = obj
699
+
700
+ ## Inequality
701
+ ineq_func = _build_ineq_constr_poly(self.P, self.vf, self.ranks, self.delta)
702
+
703
+ out["G"] = ineq_func(x)
704
+
705
+ ## Equality constraint that keeps sum of x under 1
706
+ out["H"] = _eq_constr_poly(x)
707
+
708
+
709
+ class vfResults():
710
+
711
+ def __init__(self, vf, params, epsilon, fit):
712
+
713
+ self.vf = vf
714
+ self.params = params
715
+ self.epsilon = epsilon
716
+ self.fit = fit
717
+
718
+
719
+