pymoo 0.6.1.5.dev0__cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.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-x86_64-linux-gnu.so +0 -0
  91. pymoo/cython/calc_perpendicular_distance.pyx +67 -0
  92. pymoo/cython/decomposition.cpython-313-x86_64-linux-gnu.so +0 -0
  93. pymoo/cython/decomposition.pyx +165 -0
  94. pymoo/cython/hv.cpython-313-x86_64-linux-gnu.so +0 -0
  95. pymoo/cython/hv.pyx +18 -0
  96. pymoo/cython/info.cpython-313-x86_64-linux-gnu.so +0 -0
  97. pymoo/cython/info.pyx +5 -0
  98. pymoo/cython/mnn.cpython-313-x86_64-linux-gnu.so +0 -0
  99. pymoo/cython/mnn.pyx +273 -0
  100. pymoo/cython/non_dominated_sorting.cpython-313-x86_64-linux-gnu.so +0 -0
  101. pymoo/cython/non_dominated_sorting.pyx +645 -0
  102. pymoo/cython/pruning_cd.cpython-313-x86_64-linux-gnu.so +0 -0
  103. pymoo/cython/pruning_cd.pyx +197 -0
  104. pymoo/cython/stochastic_ranking.cpython-313-x86_64-linux-gnu.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,1621 @@
1
+ #include "hypervolume.h"
2
+ #include <algorithm>
3
+ #include <cmath>
4
+ #include <vector>
5
+ #include <stdexcept>
6
+ #include <cstdlib>
7
+ #include <cstring>
8
+
9
+
10
+
11
+ /* Auxiliary functions and variables for the Overmars-Yap algorithm. */
12
+ static unsigned NO_OBJECTIVES;
13
+ static double SQRT_NO_DATA_POINTS;
14
+
15
+ int compare( const void * a, const void * b ) {
16
+ double * x = (double*) a;
17
+ double * y = (double*) b;
18
+
19
+ if( x[NO_OBJECTIVES-1] == y[NO_OBJECTIVES-1] )
20
+ return( 0 );
21
+
22
+ if( x[NO_OBJECTIVES-1] < y[NO_OBJECTIVES-1] )
23
+ return( -1 );
24
+
25
+ // if( x[NO_OBJECTIVES-1] > y[NO_OBJECTIVES-1] )
26
+
27
+ return( 1 );
28
+ }
29
+
30
+ int covers ( double * cuboid, double * regionLow );
31
+ int partCovers ( double * cuboid, double * regionUp );
32
+ int containsBoundary ( double * cub, double * regLow, int split );
33
+ double getMeasure ( double * regionLow, double * regionUp );
34
+ int isPile ( double * cuboid, double * regionLow, double * regionUp );
35
+ int binaryToInt ( int * bs );
36
+ void intToBinary ( int i, int * result );
37
+ double computeTrellis ( double * regLow, double * regUp, double * trellis );
38
+ double getMedian ( double * bounds, int length );
39
+
40
+ double stream ( double * regionLow, double * regionUp, double * points,
41
+ unsigned noPoints, int split, double cover );
42
+
43
+ double overmars_yap( double * points, double * referencePoint, unsigned noObjectives, unsigned noPoints ) {
44
+ NO_OBJECTIVES = noObjectives;
45
+ SQRT_NO_DATA_POINTS = sqrt( (double)noPoints );
46
+
47
+ double * regLow = new double[NO_OBJECTIVES];
48
+ std::fill( regLow, regLow + NO_OBJECTIVES, std::numeric_limits<double>::max() );
49
+
50
+ // Calculate Bounding Box
51
+ double * p = points;
52
+ for( unsigned i = 0; i < noPoints; i++ ) {
53
+ for( unsigned j = 0; j < NO_OBJECTIVES; j++ ) {
54
+ regLow[j] = std::min( regLow[j], *p );
55
+
56
+ ++p;
57
+ }
58
+ }
59
+
60
+ double d = stream( regLow, referencePoint, points, noPoints, 0, referencePoint[NO_OBJECTIVES-1] );
61
+
62
+ delete [] regLow;
63
+ return( d );
64
+ }
65
+
66
+ int covers(double * cuboid, double * regionLow)
67
+ {
68
+ unsigned i;
69
+ for (i = 0; i < NO_OBJECTIVES - 1; i++)
70
+ {
71
+ if (cuboid[i] > regionLow[i])
72
+ return (0);
73
+ }
74
+ return (1);
75
+ }
76
+
77
+ int partCovers( double * cuboid, double * regionUp ) {
78
+ unsigned i;
79
+ for (i = 0; i < NO_OBJECTIVES - 1; i++) {
80
+ if (cuboid[i] >= regionUp[i])
81
+ return (0);
82
+ }
83
+ return (1);
84
+ }
85
+
86
+ int containsBoundary(double * cub, double * regLow, int split) {
87
+ if (regLow[split] >= cub[split]) {
88
+ return -1;
89
+ } else {
90
+ int j;
91
+ for (j = 0; j < split; j++) {
92
+ if (regLow[j] < cub[j]) {
93
+ return 1;
94
+ }
95
+ }
96
+ }
97
+ return 0;
98
+ }
99
+
100
+ double getMeasure(double * regionLow, double * regionUp)
101
+ {
102
+ double volume = 1.0;
103
+ unsigned i;
104
+ for (i = 0; i < NO_OBJECTIVES - 1; i++)
105
+ {
106
+ volume *= (regionUp[i] - regionLow[i]);
107
+ }
108
+
109
+ return (volume);
110
+ }
111
+
112
+ int isPile(double * cuboid, double * regionLow, double * regionUp)
113
+ {
114
+ unsigned pile = NO_OBJECTIVES;
115
+ unsigned i;
116
+ for (i = 0; i < NO_OBJECTIVES - 1; i++)
117
+ {
118
+ if (cuboid[i] > regionLow[i])
119
+ {
120
+ if (pile != NO_OBJECTIVES)
121
+ {
122
+ return (-1);
123
+ }
124
+
125
+ pile = i;
126
+ }
127
+ }
128
+
129
+ return (pile);
130
+ }
131
+
132
+ int binaryToInt(int * bs)
133
+ {
134
+ int result = 0;
135
+ unsigned i;
136
+ for (i = 0; i < NO_OBJECTIVES - 1; i++)
137
+ {
138
+ result += bs[i] * (int) pow(2.0, (double)i);
139
+ }
140
+
141
+ return (result);
142
+ }
143
+
144
+ void intToBinary(int i, int * result)
145
+ {
146
+ unsigned j;
147
+ for (j = 0; j < NO_OBJECTIVES - 1; j++)
148
+ result[j] = 0;
149
+
150
+ int rest = i;
151
+ int idx = 0;
152
+
153
+ while (rest != 0)
154
+ {
155
+ result[idx] = (rest % 2);
156
+
157
+ rest = rest / 2;
158
+ idx++;
159
+ }
160
+ }
161
+
162
+ double computeTrellis(double * regLow, double * regUp, double * trellis)
163
+ {
164
+ unsigned i, j;
165
+ int * bs = (int*)malloc((NO_OBJECTIVES - 1) * sizeof(int));
166
+ for (i = 0; i < NO_OBJECTIVES - 1; i++) bs[i] = 1;
167
+
168
+ double result = 0;
169
+
170
+ int noSummands = binaryToInt(bs);
171
+ int oneCounter; double summand;
172
+
173
+ for (i = 1; i <= (unsigned)noSummands; i++)
174
+ {
175
+ summand = 1;
176
+ intToBinary(i, bs);
177
+ oneCounter = 0;
178
+
179
+ for (j = 0; j < NO_OBJECTIVES - 1; j++)
180
+ {
181
+ if (bs[j] == 1)
182
+ {
183
+ summand *= regUp[j] - trellis[j];
184
+ oneCounter++;
185
+ }
186
+ else
187
+ summand *= regUp[j] - regLow[j];
188
+ }
189
+
190
+ if (oneCounter % 2 == 0)
191
+ result -= summand ;
192
+ else
193
+ result += summand;
194
+ }
195
+
196
+ free(bs);
197
+
198
+ return(result);
199
+ }
200
+
201
+ int double_compare(const void *p1, const void *p2)
202
+ {
203
+ double i = *((double *)p1);
204
+ double j = *((double *)p2);
205
+
206
+ if (i > j)
207
+ return (1);
208
+ if (i < j)
209
+ return (-1);
210
+ return (0);
211
+ }
212
+
213
+ double getMedian(double * bounds, int length)
214
+ {
215
+ if (length == 1)
216
+ {
217
+ return bounds[0];
218
+ }
219
+ else if (length == 2)
220
+ {
221
+ return bounds[1];
222
+ }
223
+
224
+ qsort(bounds, length, sizeof(double), double_compare);
225
+
226
+ return(length % 2 == 1 ? bounds[length / 2] : (bounds[length / 2] + bounds[length / 2 + 1]) / 2);
227
+ }
228
+
229
+ double stream(double * regionLow,
230
+ double * regionUp,
231
+ double * points,
232
+ unsigned noPoints,
233
+ int split,
234
+ double cover ) {
235
+
236
+ using namespace std;
237
+
238
+ double coverOld;
239
+ coverOld = cover;
240
+ int coverIndex = 0;
241
+ int c;
242
+
243
+ double result = 0;
244
+
245
+ double dMeasure = getMeasure(regionLow, regionUp);
246
+ while (cover == coverOld && coverIndex < (double)noPoints)
247
+ {
248
+ if (covers(points + (coverIndex * NO_OBJECTIVES), regionLow))
249
+ {
250
+ cover = points[coverIndex * NO_OBJECTIVES + NO_OBJECTIVES - 1];
251
+ result += dMeasure * (coverOld - cover);
252
+ }
253
+ else
254
+ coverIndex++;
255
+ }
256
+
257
+ for (c = coverIndex; c > 0; c--) {
258
+ if (points[(c - 1) * NO_OBJECTIVES + NO_OBJECTIVES - 1] == cover) {
259
+ coverIndex--;
260
+ }
261
+ }
262
+
263
+ if (coverIndex == 0)
264
+ {
265
+ return (result);
266
+ }
267
+
268
+ int allPiles = 1; int i;
269
+
270
+ int * piles = (int*)malloc(coverIndex * sizeof(int));
271
+ for (i = 0; i < coverIndex; i++)
272
+ {
273
+ piles[i] = isPile(points + i * NO_OBJECTIVES, regionLow, regionUp);
274
+ if (piles[i] == -1)
275
+ {
276
+ allPiles = 0;
277
+ break;
278
+ }
279
+ }
280
+
281
+ if (allPiles)
282
+ {
283
+ double * trellis = (double*)malloc((NO_OBJECTIVES - 1) * sizeof(double));
284
+ for (c = 0; c < (int)NO_OBJECTIVES - 1; c++)
285
+ {
286
+ trellis[c] = regionUp[c];
287
+ }
288
+
289
+ double current = 0.0;
290
+ double next = 0.0;
291
+ i = 0;
292
+ do
293
+ {
294
+ current = points[i * NO_OBJECTIVES + NO_OBJECTIVES - 1];
295
+ do
296
+ {
297
+ if ( points[i * NO_OBJECTIVES + piles[i]] < trellis[piles[i]])
298
+ {
299
+ trellis[piles[i]] = points[i * NO_OBJECTIVES + piles[i]];
300
+ }
301
+ i++;
302
+ if (i < coverIndex)
303
+ {
304
+ next = points[i * NO_OBJECTIVES + NO_OBJECTIVES - 1];
305
+ }
306
+ else
307
+ {
308
+ next = cover;
309
+ break;
310
+ }
311
+
312
+ }
313
+ while (next == current);
314
+ result += computeTrellis(regionLow, regionUp, trellis)
315
+ * (next - current);
316
+ }
317
+ while (next != cover);
318
+ free(trellis);
319
+ }
320
+ else
321
+ {
322
+ double bound = -1.0;
323
+ double * boundaries = (double*) malloc(coverIndex * sizeof(double));
324
+ unsigned boundIdx = 0;
325
+ double * noBoundaries = (double*)malloc(coverIndex * sizeof(double));
326
+ unsigned noBoundIdx = 0;
327
+
328
+ do
329
+ {
330
+ for (i = 0; i < coverIndex; i++)
331
+ {
332
+ int contained = containsBoundary(points + i * NO_OBJECTIVES, regionLow, split);
333
+ if (contained == 1)
334
+ {
335
+ boundaries[boundIdx] = points[i * NO_OBJECTIVES + split];
336
+ boundIdx++;
337
+ }
338
+ else if (contained == 0)
339
+ {
340
+ noBoundaries[noBoundIdx] = points[i * NO_OBJECTIVES + split];
341
+ noBoundIdx++;
342
+ }
343
+ }
344
+
345
+ if (boundIdx > 0)
346
+ {
347
+ bound = getMedian(boundaries, boundIdx);
348
+ }
349
+ else if (noBoundIdx > SQRT_NO_DATA_POINTS)
350
+ {
351
+ bound = getMedian(noBoundaries, noBoundIdx);
352
+ }
353
+ else
354
+ {
355
+ split++;
356
+ }
357
+ }
358
+ while (bound == -1.0);
359
+
360
+ free(boundaries); free(noBoundaries);
361
+
362
+ double * pointsChild = new double[coverIndex * NO_OBJECTIVES];//(doublep*)malloc(coverIndex * sizeof(doublep*));
363
+ int pointsChildIdx = 0;
364
+
365
+ double * regionUpC = (double*)malloc(NO_OBJECTIVES * sizeof(double));
366
+ memcpy(regionUpC, regionUp, NO_OBJECTIVES * sizeof(double));
367
+ regionUpC[split] = bound;
368
+
369
+ for (i = 0; i < coverIndex; i++)
370
+ {
371
+ if (partCovers(points + i * NO_OBJECTIVES, regionUpC))
372
+ {
373
+ std::copy( points + i*NO_OBJECTIVES, points + i*NO_OBJECTIVES + NO_OBJECTIVES, pointsChild + pointsChildIdx*NO_OBJECTIVES );
374
+ //pointsChild[pointsChildIdx] = points[i * NO_OBJECTIVES];
375
+ pointsChildIdx++;
376
+ }
377
+ }
378
+
379
+ if (pointsChildIdx > 0)
380
+ {
381
+ result += stream(regionLow, regionUpC, pointsChild, pointsChildIdx, split, cover);
382
+ }
383
+
384
+ pointsChildIdx = 0;
385
+
386
+ double * regionLowC = (double*)malloc(NO_OBJECTIVES * sizeof(double));
387
+ memcpy(regionLowC, regionLow, NO_OBJECTIVES * sizeof(double));
388
+ regionLowC[split] = bound;
389
+ for (i = 0; i < coverIndex; i++)
390
+ {
391
+ if (partCovers(points + i * NO_OBJECTIVES, regionUp))
392
+ {
393
+ // pointsChild[pointsChildIdx] = points[i];
394
+ std::copy( points + i*NO_OBJECTIVES, points + i*NO_OBJECTIVES + NO_OBJECTIVES, pointsChild + pointsChildIdx*NO_OBJECTIVES );
395
+ pointsChildIdx++;
396
+ }
397
+ }
398
+ if (pointsChildIdx > 0)
399
+ {
400
+ result += stream(regionLowC, regionUp, pointsChild, pointsChildIdx, split, cover);
401
+ }
402
+
403
+ free(regionUpC);
404
+ free(regionLowC);
405
+ delete [] pointsChild;
406
+ }
407
+
408
+ free(piles);
409
+
410
+ return (result);
411
+ }
412
+
413
+ /************************************************************************
414
+ Relevant literature:
415
+
416
+ [1] C. M. Fonseca, L. Paquete, and M. Lopez-Ibanez. An
417
+ improved dimension-sweep algorithm for the hypervolume
418
+ indicator. In IEEE Congress on Evolutionary Computation,
419
+ pages 1157-1163, Vancouver, Canada, July 2006.
420
+
421
+ [2] L. Paquete, C. M. Fonseca and M. Lopez-Ibanez. An optimal
422
+ algorithm for a special case of Klee's measure problem in three
423
+ dimensions. Technical Report CSI-RT-I-01/2006, CSI, Universidade
424
+ do Algarve, 2006.
425
+
426
+ *************************************************************************/
427
+
428
+ /*****************************************************************************
429
+
430
+ avl.c & avl.h - Source code for the AVL-tree library.
431
+
432
+ Copyright (C) 1998 Michael H. Buselli <cosine@cosine.org>
433
+ Copyright (C) 2000-2002 Wessel Dankers <wsl@nl.linux.org>
434
+
435
+ This library is free software; you can redistribute it and/or
436
+ modify it under the terms of the GNU Lesser General Public
437
+ License as published by the Free Software Foundation; either
438
+ version 2.1 of the License, or (at your option) any later version.
439
+
440
+ This library is distributed in the hope that it will be useful,
441
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
442
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
443
+ Lesser General Public License for more details.
444
+
445
+ You should have received a copy of the GNU Lesser General Public
446
+ License along with this library; if not, write to the Free Software
447
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
448
+
449
+ Augmented AVL-tree. Original by Michael H. Buselli <cosine@cosine.org>.
450
+
451
+ Modified by Wessel Dankers <wsl@nl.linux.org> to add a bunch of bloat to
452
+ the sourcecode, change the interface and squash a few bugs.
453
+ Mail him if you find new bugs.
454
+
455
+ *****************************************************************************/
456
+
457
+ #define VARIANT 3
458
+
459
+ #if !defined(AVL_DEPTH) && !defined(AVL_COUNT)
460
+ #define AVL_DEPTH
461
+ #define AVL_COUNT
462
+ #endif
463
+
464
+ static const int stop_dimension = 1;
465
+ static std::vector<void*> allocated_pointers;
466
+
467
+ static void * ini_malloc( unsigned int nrBytes ) {
468
+ void * result = malloc( nrBytes );
469
+ if( result != 0 )
470
+ allocated_pointers.push_back( result );
471
+
472
+ return( result );
473
+ }
474
+
475
+ static void ini_free( void * p, bool reallyFree = false ) {
476
+ std::vector<void*>::iterator it = std::find( allocated_pointers.begin(), allocated_pointers.end(), p );
477
+ if( it == allocated_pointers.end() )
478
+ return;
479
+ allocated_pointers.erase( it );
480
+ if( reallyFree )
481
+ free( p );
482
+ }
483
+
484
+ /* User supplied function to compare two items like strcmp() does.
485
+ * For example: cmp(a,b) will return:
486
+ * -1 if a < b
487
+ * 0 if a = b
488
+ * 1 if a > b
489
+ */
490
+ typedef int (*avl_compare_t)(const void *, const void *);
491
+
492
+ /* User supplied function to delete an item when a node is free()d.
493
+ * If NULL, the item is not free()d.
494
+ */
495
+ typedef void (*avl_freeitem_t)(void *);
496
+
497
+ typedef struct avl_node_t {
498
+ struct avl_node_t *next;
499
+ struct avl_node_t *prev;
500
+ struct avl_node_t *parent;
501
+ struct avl_node_t *left;
502
+ struct avl_node_t *right;
503
+ void *item;
504
+ #ifdef AVL_COUNT
505
+ unsigned int count;
506
+ #endif
507
+ #ifdef AVL_DEPTH
508
+ unsigned char depth;
509
+ #endif
510
+ } avl_node_t;
511
+
512
+ typedef struct avl_tree_t {
513
+ avl_node_t *head;
514
+ avl_node_t *tail;
515
+ avl_node_t *top;
516
+ avl_compare_t cmp;
517
+ avl_freeitem_t freeitem;
518
+ } avl_tree_t;
519
+
520
+ /* Initializes a new tree for elements that will be ordered using
521
+ * the supplied strcmp()-like function.
522
+ * Returns the value of avltree (even if it's NULL).
523
+ * O(1) */
524
+ extern avl_tree_t *avl_init_tree(avl_tree_t *avltree, avl_compare_t, avl_freeitem_t);
525
+
526
+ /* Allocates and initializes a new tree for elements that will be
527
+ * ordered using the supplied strcmp()-like function.
528
+ * Returns NULL if memory could not be allocated.
529
+ * O(1) */
530
+ extern avl_tree_t *avl_alloc_tree(avl_compare_t, avl_freeitem_t);
531
+
532
+ /* Frees the entire tree efficiently. Nodes will be free()d.
533
+ * If the tree's freeitem is not NULL it will be invoked on every item.
534
+ * O(n) */
535
+ extern void avl_free_tree(avl_tree_t *);
536
+
537
+ /* Reinitializes the tree structure for reuse. Nothing is free()d.
538
+ * Compare and freeitem functions are left alone.
539
+ * O(1) */
540
+ extern void avl_clear_tree(avl_tree_t *);
541
+
542
+ /* Free()s all nodes in the tree but leaves the tree itself.
543
+ * If the tree's freeitem is not NULL it will be invoked on every item.
544
+ * O(n) */
545
+ extern void avl_free_nodes(avl_tree_t *);
546
+
547
+ /* Initializes memory for use as a node. Returns NULL if avlnode is NULL.
548
+ * O(1) */
549
+ extern avl_node_t *avl_init_node(avl_node_t *avlnode, void *item);
550
+
551
+ /* Insert an item into the tree and return the new node.
552
+ * Returns NULL and sets errno if memory for the new node could not be
553
+ * allocated or if the node is already in the tree (EEXIST).
554
+ * O(lg n) */
555
+ extern avl_node_t *avl_insert(avl_tree_t *, void *item);
556
+
557
+ /* Insert a node into the tree and return it.
558
+ * Returns NULL if the node is already in the tree.
559
+ * O(lg n) */
560
+ extern avl_node_t *avl_insert_node(avl_tree_t *, avl_node_t *);
561
+
562
+ /* Insert a node in an empty tree. If avlnode is NULL, the tree will be
563
+ * cleared and ready for re-use.
564
+ * If the tree is not empty, the old nodes are left dangling.
565
+ * O(1) */
566
+ extern avl_node_t *avl_insert_top(avl_tree_t *, avl_node_t *avlnode);
567
+
568
+ /* Insert a node before another node. Returns the new node.
569
+ * If old is NULL, the item is appended to the tree.
570
+ * O(lg n) */
571
+ extern avl_node_t *avl_insert_before(avl_tree_t *, avl_node_t *old, avl_node_t * newNode);
572
+
573
+ /* Insert a node after another node. Returns the new node.
574
+ * If old is NULL, the item is prepended to the tree.
575
+ * O(lg n) */
576
+ extern avl_node_t *avl_insert_after(avl_tree_t *, avl_node_t *old, avl_node_t *newNode);
577
+
578
+ /* Deletes a node from the tree. Returns immediately if the node is NULL.
579
+ * The item will not be free()d regardless of the tree's freeitem handler.
580
+ * This function comes in handy if you need to update the search key.
581
+ * O(lg n) */
582
+ extern void avl_unlink_node(avl_tree_t *, avl_node_t *);
583
+
584
+ /* Deletes a node from the tree. Returns immediately if the node is NULL.
585
+ * If the tree's freeitem is not NULL, it is invoked on the item.
586
+ * If it is, returns the item.
587
+ * O(lg n) */
588
+ extern void *avl_delete_node(avl_tree_t *, avl_node_t *);
589
+
590
+ /* Searches for an item in the tree and deletes it if found.
591
+ * If the tree's freeitem is not NULL, it is invoked on the item.
592
+ * If it is, returns the item.
593
+ * O(lg n) */
594
+ extern void *avl_delete(avl_tree_t *, const void *item);
595
+
596
+ /* If exactly one node is moved in memory, this will fix the pointers
597
+ * in the tree that refer to it. It must be an exact shallow copy.
598
+ * Returns the pointer to the old position.
599
+ * O(1) */
600
+ extern avl_node_t *avl_fixup_node(avl_tree_t *, avl_node_t *newNode);
601
+
602
+ /* Searches for a node with the key closest (or equal) to the given item.
603
+ * If avlnode is not NULL, *avlnode will be set to the node found or NULL
604
+ * if the tree is empty. Return values:
605
+ * -1 if the returned node is smaller
606
+ * 0 if the returned node is equal or if the tree is empty
607
+ * 1 if the returned node is greater
608
+ * O(lg n) */
609
+ extern int avl_search_closest(const avl_tree_t *, const void *item, avl_node_t **avlnode);
610
+
611
+ /* Searches for the item in the tree and returns a matching node if found
612
+ * or NULL if not.
613
+ * O(lg n) */
614
+ extern avl_node_t *avl_search(const avl_tree_t *, const void *item);
615
+
616
+ #ifdef AVL_COUNT
617
+ /* Returns the number of nodes in the tree.
618
+ * O(1) */
619
+ extern unsigned int avl_count(const avl_tree_t *);
620
+
621
+ /* Searches a node by its rank in the list. Counting starts at 0.
622
+ * Returns NULL if the index exceeds the number of nodes in the tree.
623
+ * O(lg n) */
624
+ extern avl_node_t *avl_at(const avl_tree_t *, unsigned int);
625
+
626
+ /* Returns the rank of a node in the list. Counting starts at 0.
627
+ * O(lg n) */
628
+ extern unsigned int avl_index(const avl_node_t *);
629
+ #endif
630
+
631
+ static void avl_rebalance(avl_tree_t *, avl_node_t *);
632
+
633
+ #ifdef AVL_COUNT
634
+ #define NODE_COUNT(n) ((n) ? (n)->count : 0)
635
+ #define L_COUNT(n) (NODE_COUNT((n)->left))
636
+ #define R_COUNT(n) (NODE_COUNT((n)->right))
637
+ #define CALC_COUNT(n) (L_COUNT(n) + R_COUNT(n) + 1)
638
+ #endif
639
+
640
+ #ifdef AVL_DEPTH
641
+ #define NODE_DEPTH(n) ((n) ? (n)->depth : 0)
642
+ #define L_DEPTH(n) (NODE_DEPTH((n)->left))
643
+ #define R_DEPTH(n) (NODE_DEPTH((n)->right))
644
+ #define CALC_DEPTH(n) ((L_DEPTH(n)>R_DEPTH(n)?L_DEPTH(n):R_DEPTH(n)) + 1)
645
+ #endif
646
+
647
+ #ifndef AVL_DEPTH
648
+ /* Also known as ffs() (from BSD) */
649
+ static int lg(unsigned int u) {
650
+ int r = 1;
651
+ if(!u) return 0;
652
+ if(u & 0xffff0000) { u >>= 16; r += 16; }
653
+ if(u & 0x0000ff00) { u >>= 8; r += 8; }
654
+ if(u & 0x000000f0) { u >>= 4; r += 4; }
655
+ if(u & 0x0000000c) { u >>= 2; r += 2; }
656
+ if(u & 0x00000002) r++;
657
+ return r;
658
+ }
659
+ #endif
660
+
661
+ static int avl_check_balance(avl_node_t *avlnode) {
662
+ #ifdef AVL_DEPTH
663
+ int d;
664
+ d = R_DEPTH(avlnode) - L_DEPTH(avlnode);
665
+ return d<-1?-1:d>1?1:0;
666
+ #else
667
+ /* int d;
668
+ * d = lg(R_COUNT(avlnode)) - lg(L_COUNT(avlnode));
669
+ * d = d<-1?-1:d>1?1:0;
670
+ */
671
+ #ifdef AVL_COUNT
672
+ int pl, r;
673
+
674
+ pl = lg(L_COUNT(avlnode));
675
+ r = R_COUNT(avlnode);
676
+
677
+ if(r>>pl+1)
678
+ return 1;
679
+ if(pl<2 || r>>pl-2)
680
+ return 0;
681
+ return -1;
682
+ #else
683
+ #error No balancing possible.
684
+ #endif
685
+ #endif
686
+ }
687
+
688
+ #ifdef AVL_COUNT
689
+ unsigned int avl_count(const avl_tree_t *avltree) {
690
+ return NODE_COUNT(avltree->top);
691
+ }
692
+
693
+ avl_node_t *avl_at(const avl_tree_t *avltree, unsigned int index) {
694
+ avl_node_t *avlnode;
695
+ unsigned int c;
696
+
697
+ avlnode = avltree->top;
698
+
699
+ while(avlnode) {
700
+ c = L_COUNT(avlnode);
701
+
702
+ if(index < c) {
703
+ avlnode = avlnode->left;
704
+ } else if(index > c) {
705
+ avlnode = avlnode->right;
706
+ index -= c+1;
707
+ } else {
708
+ return avlnode;
709
+ }
710
+ }
711
+ return NULL;
712
+ }
713
+
714
+ unsigned int avl_index(const avl_node_t *avlnode) {
715
+ avl_node_t *next;
716
+ unsigned int c;
717
+
718
+ c = L_COUNT(avlnode);
719
+
720
+ while((next = avlnode->parent)) {
721
+ if(avlnode == next->right)
722
+ c += L_COUNT(next) + 1;
723
+ avlnode = next;
724
+ }
725
+
726
+ return c;
727
+ }
728
+ #endif
729
+
730
+ int avl_search_closest(const avl_tree_t *avltree, const void *item, avl_node_t **avlnode) {
731
+ avl_node_t *node;
732
+ avl_compare_t cmp;
733
+ int c;
734
+
735
+ if(!avlnode)
736
+ avlnode = &node;
737
+
738
+ node = avltree->top;
739
+
740
+ if(!node)
741
+ return *avlnode = NULL, 0;
742
+
743
+ cmp = avltree->cmp;
744
+
745
+ for(;;) {
746
+ c = cmp(item, node->item);
747
+
748
+ if(c < 0) {
749
+ if(node->left)
750
+ node = node->left;
751
+ else
752
+ return *avlnode = node, -1;
753
+ } else if(c > 0) {
754
+ if(node->right)
755
+ node = node->right;
756
+ else
757
+ return *avlnode = node, 1;
758
+ } else {
759
+ return *avlnode = node, 0;
760
+ }
761
+ }
762
+ }
763
+
764
+ /*
765
+ * avl_search:
766
+ * Return a pointer to a node with the given item in the tree.
767
+ * If no such item is in the tree, then NULL is returned.
768
+ */
769
+ avl_node_t *avl_search(const avl_tree_t *avltree, const void *item) {
770
+ avl_node_t *node;
771
+ return avl_search_closest(avltree, item, &node) ? NULL : node;
772
+ }
773
+
774
+ avl_tree_t *avl_init_tree(avl_tree_t *rc, avl_compare_t cmp, avl_freeitem_t freeitem) {
775
+ if(rc) {
776
+ rc->head = NULL;
777
+ rc->tail = NULL;
778
+ rc->top = NULL;
779
+ rc->cmp = cmp;
780
+ rc->freeitem = freeitem;
781
+ }
782
+ return rc;
783
+ }
784
+
785
+ avl_tree_t *avl_alloc_tree(avl_compare_t cmp, avl_freeitem_t freeitem) {
786
+ return (avl_tree_t*) avl_init_tree((avl_tree_t*)ini_malloc(sizeof(avl_tree_t)), cmp, freeitem);
787
+ }
788
+
789
+ void avl_clear_tree(avl_tree_t *avltree) {
790
+ avltree->top = avltree->head = avltree->tail = NULL;
791
+ }
792
+
793
+ void avl_free_nodes(avl_tree_t *avltree) {
794
+ avl_node_t *node, *next;
795
+ avl_freeitem_t freeitem;
796
+
797
+ freeitem = avltree->freeitem;
798
+
799
+ for(node = avltree->head; node; node = next) {
800
+ next = node->next;
801
+ if(freeitem)
802
+ freeitem(node->item);
803
+ ini_free(node,true);
804
+ }
805
+ avl_clear_tree(avltree);
806
+ }
807
+
808
+ /*
809
+ * avl_free_tree:
810
+ * Free all memory used by this tree. If freeitem is not NULL, then
811
+ * it is assumed to be a destructor for the items referenced in the avl_
812
+ * tree, and they are deleted as well.
813
+ */
814
+ void avl_free_tree(avl_tree_t *avltree) {
815
+ avl_free_nodes(avltree);
816
+ ini_free(avltree, true);
817
+ }
818
+
819
+ static void avl_clear_node(avl_node_t *newnode) {
820
+ newnode->left = newnode->right = NULL;
821
+ #ifdef AVL_COUNT
822
+ newnode->count = 1;
823
+ #endif
824
+ #ifdef AVL_DEPTH
825
+ newnode->depth = 1;
826
+ #endif
827
+ }
828
+
829
+ avl_node_t *avl_init_node(avl_node_t *newnode, void *item) {
830
+ if(newnode) {
831
+ avl_clear_node(newnode);
832
+ newnode->item = item;
833
+ }
834
+ return newnode;
835
+ }
836
+
837
+ avl_node_t *avl_insert_top(avl_tree_t *avltree, avl_node_t *newnode) {
838
+ avl_clear_node(newnode);
839
+ newnode->prev = newnode->next = newnode->parent = NULL;
840
+ avltree->head = avltree->tail = avltree->top = newnode;
841
+ return newnode;
842
+ }
843
+
844
+ avl_node_t *avl_insert_before(avl_tree_t *avltree, avl_node_t *node, avl_node_t *newnode) {
845
+ if(!node)
846
+ return avltree->tail
847
+ ? avl_insert_after(avltree, avltree->tail, newnode)
848
+ : avl_insert_top(avltree, newnode);
849
+
850
+ if(node->left)
851
+ return avl_insert_after(avltree, node->prev, newnode);
852
+
853
+ avl_clear_node(newnode);
854
+
855
+ newnode->next = node;
856
+ newnode->parent = node;
857
+
858
+ newnode->prev = node->prev;
859
+ if(node->prev)
860
+ node->prev->next = newnode;
861
+ else
862
+ avltree->head = newnode;
863
+ node->prev = newnode;
864
+
865
+ node->left = newnode;
866
+ avl_rebalance(avltree, node);
867
+ return newnode;
868
+ }
869
+
870
+ avl_node_t *avl_insert_after(avl_tree_t *avltree, avl_node_t *node, avl_node_t *newnode) {
871
+ if(!node)
872
+ return avltree->head
873
+ ? avl_insert_before(avltree, avltree->head, newnode)
874
+ : avl_insert_top(avltree, newnode);
875
+
876
+ if(node->right)
877
+ return avl_insert_before(avltree, node->next, newnode);
878
+
879
+ avl_clear_node(newnode);
880
+
881
+ newnode->prev = node;
882
+ newnode->parent = node;
883
+
884
+ newnode->next = node->next;
885
+ if(node->next)
886
+ node->next->prev = newnode;
887
+ else
888
+ avltree->tail = newnode;
889
+ node->next = newnode;
890
+
891
+ node->right = newnode;
892
+ avl_rebalance(avltree, node);
893
+ return newnode;
894
+ }
895
+
896
+ avl_node_t *avl_insert_node(avl_tree_t *avltree, avl_node_t *newnode) {
897
+ avl_node_t *node;
898
+
899
+ if(!avltree->top)
900
+ return avl_insert_top(avltree, newnode);
901
+
902
+ switch(avl_search_closest(avltree, newnode->item, &node)) {
903
+ case -1:
904
+ return avl_insert_before(avltree, node, newnode);
905
+ case 1:
906
+ return avl_insert_after(avltree, node, newnode);
907
+ }
908
+
909
+ return NULL;
910
+ }
911
+
912
+ /*
913
+ * avl_insert:
914
+ * Create a new node and insert an item there.
915
+ * Returns the new node on success or NULL if no memory could be allocated.
916
+ */
917
+ avl_node_t *avl_insert(avl_tree_t *avltree, void *item) {
918
+ avl_node_t *newnode;
919
+
920
+ newnode = avl_init_node((avl_node_t*)ini_malloc(sizeof(avl_node_t)), item);
921
+ if(newnode) {
922
+ if(avl_insert_node(avltree, newnode))
923
+ return newnode;
924
+ ini_free(newnode, true);
925
+ errno = EEXIST;
926
+ }
927
+ return NULL;
928
+ }
929
+
930
+ /*
931
+ * avl_unlink_node:
932
+ * Removes the given node. Does not delete the item at that node.
933
+ * The item of the node may be freed before calling avl_unlink_node.
934
+ * (In other words, it is not referenced by this function.)
935
+ */
936
+ void avl_unlink_node(avl_tree_t *avltree, avl_node_t *avlnode) {
937
+ avl_node_t *parent;
938
+ avl_node_t **superparent;
939
+ avl_node_t *subst, *left, *right;
940
+ avl_node_t *balnode;
941
+
942
+ if(avlnode->prev)
943
+ avlnode->prev->next = avlnode->next;
944
+ else
945
+ avltree->head = avlnode->next;
946
+
947
+ if(avlnode->next)
948
+ avlnode->next->prev = avlnode->prev;
949
+ else
950
+ avltree->tail = avlnode->prev;
951
+
952
+ parent = avlnode->parent;
953
+
954
+ superparent = parent
955
+ ? avlnode == parent->left ? &parent->left : &parent->right
956
+ : &avltree->top;
957
+
958
+ left = avlnode->left;
959
+ right = avlnode->right;
960
+ if(!left) {
961
+ *superparent = right;
962
+ if(right)
963
+ right->parent = parent;
964
+ balnode = parent;
965
+ } else if(!right) {
966
+ *superparent = left;
967
+ left->parent = parent;
968
+ balnode = parent;
969
+ } else {
970
+ subst = avlnode->prev;
971
+ if(subst == left) {
972
+ balnode = subst;
973
+ } else {
974
+ balnode = subst->parent;
975
+ balnode->right = subst->left;
976
+ if(balnode->right)
977
+ balnode->right->parent = balnode;
978
+ subst->left = left;
979
+ left->parent = subst;
980
+ }
981
+ subst->right = right;
982
+ subst->parent = parent;
983
+ right->parent = subst;
984
+ *superparent = subst;
985
+ }
986
+
987
+ avl_rebalance(avltree, balnode);
988
+ }
989
+
990
+ void *avl_delete_node(avl_tree_t *avltree, avl_node_t *avlnode) {
991
+ void *item = NULL;
992
+ if(avlnode) {
993
+ item = avlnode->item;
994
+ avl_unlink_node(avltree, avlnode);
995
+ if(avltree->freeitem)
996
+ avltree->freeitem(item);
997
+ ini_free(avlnode,true);
998
+ }
999
+ return item;
1000
+ }
1001
+
1002
+ void *avl_delete(avl_tree_t *avltree, const void *item) {
1003
+ return avl_delete_node(avltree, avl_search(avltree, item));
1004
+ }
1005
+
1006
+ avl_node_t *avl_fixup_node(avl_tree_t *avltree, avl_node_t *newnode) {
1007
+ avl_node_t *oldnode = NULL, *node;
1008
+
1009
+ if(!avltree || !newnode)
1010
+ return NULL;
1011
+
1012
+ node = newnode->prev;
1013
+ if(node) {
1014
+ oldnode = node->next;
1015
+ node->next = newnode;
1016
+ } else {
1017
+ avltree->head = newnode;
1018
+ }
1019
+
1020
+ node = newnode->next;
1021
+ if(node) {
1022
+ oldnode = node->prev;
1023
+ node->prev = newnode;
1024
+ } else {
1025
+ avltree->tail = newnode;
1026
+ }
1027
+
1028
+ node = newnode->parent;
1029
+ if(node) {
1030
+ if(node->left == oldnode)
1031
+ node->left = newnode;
1032
+ else
1033
+ node->right = newnode;
1034
+ } else {
1035
+ oldnode = avltree->top;
1036
+ avltree->top = newnode;
1037
+ }
1038
+
1039
+ return oldnode;
1040
+ }
1041
+
1042
+ /*
1043
+ * avl_rebalance:
1044
+ * Rebalances the tree if one side becomes too heavy. This function
1045
+ * assumes that both subtrees are AVL-trees with consistant data. The
1046
+ * function has the additional side effect of recalculating the count of
1047
+ * the tree at this node. It should be noted that at the return of this
1048
+ * function, if a rebalance takes place, the top of this subtree is no
1049
+ * longer going to be the same node.
1050
+ */
1051
+ void avl_rebalance(avl_tree_t *avltree, avl_node_t *avlnode) {
1052
+ avl_node_t *child;
1053
+ avl_node_t *gchild;
1054
+ avl_node_t *parent;
1055
+ avl_node_t **superparent;
1056
+
1057
+ parent = avlnode;
1058
+
1059
+ while(avlnode) {
1060
+ parent = avlnode->parent;
1061
+
1062
+ superparent = parent
1063
+ ? avlnode == parent->left ? &parent->left : &parent->right
1064
+ : &avltree->top;
1065
+
1066
+ switch(avl_check_balance(avlnode)) {
1067
+ case -1:
1068
+ child = avlnode->left;
1069
+ #ifdef AVL_DEPTH
1070
+ if(L_DEPTH(child) >= R_DEPTH(child)) {
1071
+ #else
1072
+ #ifdef AVL_COUNT
1073
+ if(L_COUNT(child) >= R_COUNT(child)) {
1074
+ #else
1075
+ #error No balancing possible.
1076
+ #endif
1077
+ #endif
1078
+ avlnode->left = child->right;
1079
+ if(avlnode->left)
1080
+ avlnode->left->parent = avlnode;
1081
+ child->right = avlnode;
1082
+ avlnode->parent = child;
1083
+ *superparent = child;
1084
+ child->parent = parent;
1085
+ #ifdef AVL_COUNT
1086
+ avlnode->count = CALC_COUNT(avlnode);
1087
+ child->count = CALC_COUNT(child);
1088
+ #endif
1089
+ #ifdef AVL_DEPTH
1090
+ avlnode->depth = CALC_DEPTH(avlnode);
1091
+ child->depth = CALC_DEPTH(child);
1092
+ #endif
1093
+ } else {
1094
+ gchild = child->right;
1095
+ avlnode->left = gchild->right;
1096
+ if(avlnode->left)
1097
+ avlnode->left->parent = avlnode;
1098
+ child->right = gchild->left;
1099
+ if(child->right)
1100
+ child->right->parent = child;
1101
+ gchild->right = avlnode;
1102
+ if(gchild->right)
1103
+ gchild->right->parent = gchild;
1104
+ gchild->left = child;
1105
+ if(gchild->left)
1106
+ gchild->left->parent = gchild;
1107
+ *superparent = gchild;
1108
+ gchild->parent = parent;
1109
+ #ifdef AVL_COUNT
1110
+ avlnode->count = CALC_COUNT(avlnode);
1111
+ child->count = CALC_COUNT(child);
1112
+ gchild->count = CALC_COUNT(gchild);
1113
+ #endif
1114
+ #ifdef AVL_DEPTH
1115
+ avlnode->depth = CALC_DEPTH(avlnode);
1116
+ child->depth = CALC_DEPTH(child);
1117
+ gchild->depth = CALC_DEPTH(gchild);
1118
+ #endif
1119
+ }
1120
+ break;
1121
+ case 1:
1122
+ child = avlnode->right;
1123
+ #ifdef AVL_DEPTH
1124
+ if(R_DEPTH(child) >= L_DEPTH(child)) {
1125
+ #else
1126
+ #ifdef AVL_COUNT
1127
+ if(R_COUNT(child) >= L_COUNT(child)) {
1128
+ #else
1129
+ #error No balancing possible.
1130
+ #endif
1131
+ #endif
1132
+ avlnode->right = child->left;
1133
+ if(avlnode->right)
1134
+ avlnode->right->parent = avlnode;
1135
+ child->left = avlnode;
1136
+ avlnode->parent = child;
1137
+ *superparent = child;
1138
+ child->parent = parent;
1139
+ #ifdef AVL_COUNT
1140
+ avlnode->count = CALC_COUNT(avlnode);
1141
+ child->count = CALC_COUNT(child);
1142
+ #endif
1143
+ #ifdef AVL_DEPTH
1144
+ avlnode->depth = CALC_DEPTH(avlnode);
1145
+ child->depth = CALC_DEPTH(child);
1146
+ #endif
1147
+ } else {
1148
+ gchild = child->left;
1149
+ avlnode->right = gchild->left;
1150
+ if(avlnode->right)
1151
+ avlnode->right->parent = avlnode;
1152
+ child->left = gchild->right;
1153
+ if(child->left)
1154
+ child->left->parent = child;
1155
+ gchild->left = avlnode;
1156
+ if(gchild->left)
1157
+ gchild->left->parent = gchild;
1158
+ gchild->right = child;
1159
+ if(gchild->right)
1160
+ gchild->right->parent = gchild;
1161
+ *superparent = gchild;
1162
+ gchild->parent = parent;
1163
+ #ifdef AVL_COUNT
1164
+ avlnode->count = CALC_COUNT(avlnode);
1165
+ child->count = CALC_COUNT(child);
1166
+ gchild->count = CALC_COUNT(gchild);
1167
+ #endif
1168
+ #ifdef AVL_DEPTH
1169
+ avlnode->depth = CALC_DEPTH(avlnode);
1170
+ child->depth = CALC_DEPTH(child);
1171
+ gchild->depth = CALC_DEPTH(gchild);
1172
+ #endif
1173
+ }
1174
+ break;
1175
+ default:
1176
+ #ifdef AVL_COUNT
1177
+ avlnode->count = CALC_COUNT(avlnode);
1178
+ #endif
1179
+ #ifdef AVL_DEPTH
1180
+ avlnode->depth = CALC_DEPTH(avlnode);
1181
+ #endif
1182
+ }
1183
+ avlnode = parent;
1184
+ }
1185
+ }
1186
+
1187
+ typedef struct dlnode {
1188
+ double *x; /* The data vector */
1189
+ struct dlnode **next; /* Next-node vector */
1190
+ struct dlnode **prev; /* Previous-node vector */
1191
+ struct avl_node_t * tnode;
1192
+ int ignore;
1193
+ #if VARIANT >= 2
1194
+ double *area; /* Area */
1195
+ #endif
1196
+ #if VARIANT >= 3
1197
+ double *vol; /* Volume */
1198
+ #endif
1199
+ } dlnode_t;
1200
+
1201
+
1202
+ static avl_tree_t *tree;
1203
+ //extern int stop_dimension;
1204
+
1205
+
1206
+ static int compare_node( const void *p1, const void* p2)
1207
+ {
1208
+ const double x1 = *((*(const dlnode_t **)p1)->x);
1209
+ const double x2 = *((*(const dlnode_t **)p2)->x);
1210
+
1211
+ if ( x1 == x2 )
1212
+ return 0;
1213
+ else
1214
+ return ( x1 < x2 ) ? -1 : 1;
1215
+ }
1216
+
1217
+ static int compare_tree_asc( const void *p1, const void *p2)
1218
+ {
1219
+ const double x1= *((const double *)p1+1);
1220
+ const double x2= *((const double *)p2+1);
1221
+
1222
+ if (x1 != x2)
1223
+ return (x1 > x2) ? -1 : 1;
1224
+ else
1225
+ return 0;
1226
+ }
1227
+
1228
+
1229
+ /*
1230
+ * Setup circular double-linked list in each dimension
1231
+ */
1232
+
1233
+ static dlnode_t *
1234
+ setup_cdllist(double *data, int d, int n)
1235
+ {
1236
+ dlnode_t *head;
1237
+ dlnode_t **scratch;
1238
+ int i, j;
1239
+
1240
+ head = (dlnode_t*) ini_malloc ((n+1) * sizeof(dlnode_t));
1241
+
1242
+ head->x = data;
1243
+ head->ignore = 0; /* should never get used */
1244
+ head->next = (dlnode**) ini_malloc( d * (n+1) * sizeof(dlnode_t*));
1245
+ head->prev = (dlnode**) ini_malloc( d * (n+1) * sizeof(dlnode_t*));
1246
+ head->tnode = (avl_node_t*) ini_malloc( sizeof(avl_node_t));
1247
+
1248
+ #if VARIANT >= 2
1249
+ head->area = (double*) ini_malloc(d * (n+1) * sizeof(double));
1250
+ #endif
1251
+ #if VARIANT >= 3
1252
+ head->vol = (double*) ini_malloc(d * (n+1) * sizeof(double));
1253
+ #endif
1254
+
1255
+ for (i = 1; i <= n; i++) {
1256
+ head[i].x = head[i-1].x + d ;/* this will be fixed a few lines below... */
1257
+ head[i].ignore = 0;
1258
+ head[i].next = head[i-1].next + d;
1259
+ head[i].prev = head[i-1].prev + d;
1260
+ head[i].tnode = (avl_node_t*) ini_malloc(sizeof(avl_node_t));
1261
+ #if VARIANT >= 2
1262
+ head[i].area = head[i-1].area + d;
1263
+ #endif
1264
+ #if VARIANT >= 3
1265
+ head[i].vol = head[i-1].vol + d;
1266
+ #endif
1267
+ }
1268
+ head->x = NULL; /* head contains no data */
1269
+
1270
+ scratch = (dlnode_t**)ini_malloc(n * sizeof(dlnode_t*));
1271
+ for (i = 0; i < n; i++)
1272
+ scratch[i] = head + i + 1;
1273
+
1274
+ for (j = d-1; j >= 0; j--) {
1275
+ for (i = 0; i < n; i++)
1276
+ scratch[i]->x--;
1277
+ qsort(scratch, n, sizeof(dlnode_t*), compare_node);
1278
+ head->next[j] = scratch[0];
1279
+ scratch[0]->prev[j] = head;
1280
+ for (i = 1; i < n; i++) {
1281
+ scratch[i-1]->next[j] = scratch[i];
1282
+ scratch[i]->prev[j] = scratch[i-1];
1283
+ }
1284
+ scratch[n-1]->next[j] = head;
1285
+ head->prev[j] = scratch[n-1];
1286
+ }
1287
+
1288
+ /* free(scratch); */
1289
+
1290
+ return head;
1291
+ }
1292
+
1293
+ static void deleteNode (dlnode_t *nodep, int dim, double * bound )
1294
+ {
1295
+ int i;
1296
+
1297
+ for (i = 0; i < dim; i++) {
1298
+ nodep->prev[i]->next[i] = nodep->next[i];
1299
+ nodep->next[i]->prev[i] = nodep->prev[i];
1300
+ #if VARIANT >= 3
1301
+ if (bound[i] > nodep->x[i])
1302
+ bound[i] = nodep->x[i];
1303
+ #endif
1304
+ }
1305
+ }
1306
+
1307
+ static void reinsert (dlnode_t *nodep, int dim, double * bound )
1308
+ {
1309
+ int i;
1310
+
1311
+ for (i = 0; i < dim; i++) {
1312
+ nodep->prev[i]->next[i] = nodep;
1313
+ nodep->next[i]->prev[i] = nodep;
1314
+ #if VARIANT >= 3
1315
+ if (bound[i] > nodep->x[i])
1316
+ bound[i] = nodep->x[i];
1317
+ #endif
1318
+ }
1319
+ }
1320
+
1321
+ static double
1322
+ hv_recursive( dlnode_t *list, int dim, int c, const double * ref,
1323
+ double * bound)
1324
+ {
1325
+ dlnode_t *p0,*p1,*pp;
1326
+ double hypera,hyperv=0;
1327
+ double height;
1328
+
1329
+
1330
+ /* ------------------------------------------------------
1331
+ General case for dimensions higher than stop_dimension
1332
+ ------------------------------------------------------ */
1333
+ if ( dim > stop_dimension ) {
1334
+ p0 = list;
1335
+ #if VARIANT >= 2
1336
+ for (p1 = p0->prev[dim]; p1->x; p1 = p1->prev[dim]) {
1337
+ if (p1->ignore < dim)
1338
+ p1->ignore = 0;
1339
+ }
1340
+ #endif
1341
+ while (
1342
+ #if VARIANT >= 3
1343
+ p0->prev[dim]->x[dim] > bound[dim] &&
1344
+ #endif
1345
+ c > 1 ) {
1346
+ p0 = p0->prev[dim];
1347
+ deleteNode(p0, dim, bound);
1348
+ c--;
1349
+ }
1350
+ p1 = p0->prev[dim];
1351
+
1352
+ #if VARIANT == 1
1353
+ hypera = hv_recursive(list, dim-1, c, ref, bound);
1354
+ #elif VARIANT >= 3
1355
+ if (c > 1)
1356
+ hyperv = p1->prev[dim]->vol[dim] + p1->prev[dim]->area[dim]
1357
+ * (p1->x[dim] - p1->prev[dim]->x[dim]);
1358
+ else {
1359
+ p1->area[0] = 1;
1360
+ int i;
1361
+ for (i = 1; i <= dim; i++)
1362
+ p1->area[i] = p1->area[i-1] * (ref[i-1] - p1->x[i-1]);
1363
+ }
1364
+ p1->vol[dim] = hyperv;
1365
+ #endif
1366
+ #if VARIANT >= 2
1367
+ if (p1->ignore >= dim)
1368
+ p1->area[dim] = p1->prev[dim]->area[dim];
1369
+ else {
1370
+ p1->area[dim] = hv_recursive(list, dim-1, c, ref, bound);
1371
+ if (p1->area[dim] <= p1->prev[dim]->area[dim])
1372
+ p1->ignore = dim;
1373
+ }
1374
+ #endif
1375
+
1376
+ while (p0->x != NULL) {
1377
+ hyperv +=
1378
+ #if VARIANT == 1
1379
+ hypera
1380
+ #elif VARIANT >= 2
1381
+ p1->area[dim]
1382
+ #endif
1383
+ * (p0->x[dim] - p1->x[dim]);
1384
+ #if VARIANT >= 3
1385
+ bound[dim] = p0->x[dim];
1386
+ #endif
1387
+ reinsert(p0, dim, bound);
1388
+ c++;
1389
+ p1 = p0;
1390
+ p0 = p0->next[dim];
1391
+ #if VARIANT >= 3
1392
+ p1->vol[dim] = hyperv;
1393
+ #endif
1394
+ #if VARIANT == 1
1395
+ hypera = hv_recursive(list, dim-1, c, ref, NULL);
1396
+ #elif VARIANT >= 2
1397
+ if (p1->ignore >= dim)
1398
+ p1->area[dim] = p1->prev[dim]->area[dim];
1399
+ else {
1400
+ p1->area[dim] = hv_recursive(list, dim-1, c, ref, bound);
1401
+ if (p1->area[dim] <= p1->prev[dim]->area[dim])
1402
+ p1->ignore = dim;
1403
+ }
1404
+ #endif
1405
+ }
1406
+ hyperv +=
1407
+ #if VARIANT == 1
1408
+ hypera
1409
+ #elif VARIANT >= 2
1410
+ p1->area[dim]
1411
+ #endif
1412
+ * (ref[dim] - p1->x[dim]);
1413
+
1414
+ return hyperv;
1415
+ }
1416
+
1417
+ /* ---------------------------
1418
+ special case of dimension 3
1419
+ --------------------------- */
1420
+ else if (dim == 2) {
1421
+
1422
+ pp = list->next[2];
1423
+ avl_init_node(pp->tnode,pp->x);
1424
+ avl_insert_top(tree,pp->tnode);
1425
+
1426
+ hypera = (ref[0] - pp->x[0])*(ref[1] - pp->x[1]);
1427
+
1428
+ if (c == 1)
1429
+ height = ref[2] - pp->x[2];
1430
+ else
1431
+ height = pp->next[2]->x[2] - pp->x[2];
1432
+
1433
+ hyperv = hypera * height;
1434
+
1435
+ while ((pp=pp->next[2])->x) {
1436
+ height = (pp==list->prev[2])
1437
+ ? ref[2] - pp->x[2]
1438
+ : pp->next[2]->x[2] - pp->x[2];
1439
+ #if VARIANT >= 2
1440
+ if (pp->ignore>=2)
1441
+ hyperv += hypera * height;
1442
+ else {
1443
+ #endif
1444
+ const double * prv_ip, * nxt_ip;
1445
+ avl_node_t *tnode;
1446
+
1447
+ avl_init_node(pp->tnode, pp->x);
1448
+
1449
+ if (avl_search_closest(tree, pp->x, &tnode) <= 0) {
1450
+ nxt_ip = (double *)(tnode->item);
1451
+ tnode = tnode->prev;
1452
+ } else {
1453
+ nxt_ip = (tnode->next!=NULL)
1454
+ ? (double *)(tnode->next->item)
1455
+ : ref;
1456
+ }
1457
+
1458
+ if (nxt_ip[0] > pp->x[0]) {
1459
+
1460
+ avl_insert_after(tree, tnode, pp->tnode);
1461
+
1462
+ if (tnode !=NULL) {
1463
+ prv_ip = (double *)(tnode->item);
1464
+
1465
+ if (prv_ip[0] > pp->x[0]) {
1466
+ const double * cur_ip;
1467
+
1468
+ tnode = pp->tnode->prev;
1469
+ // cur_ip = point dominated by pp with highest [0]-coordinate
1470
+ cur_ip = (double *)(tnode->item);
1471
+ while (tnode->prev) {
1472
+ prv_ip = (double *)(tnode->prev->item);
1473
+ hypera -= (prv_ip[1] - cur_ip[1])*(nxt_ip[0] - cur_ip[0]);
1474
+ if (prv_ip[0] < pp->x[0])
1475
+ break; // prv is not dominated by pp
1476
+ cur_ip = prv_ip;
1477
+ avl_unlink_node(tree,tnode);
1478
+ tnode = tnode->prev;
1479
+ }
1480
+
1481
+ avl_unlink_node(tree,tnode);
1482
+
1483
+ if (!tnode->prev) {
1484
+ hypera -= (ref[1] - cur_ip[1])*(nxt_ip[0] - cur_ip[0]);
1485
+ prv_ip = ref;
1486
+ }
1487
+ }
1488
+ } else
1489
+ prv_ip = ref;
1490
+
1491
+ hypera += (prv_ip[1] - pp->x[1])*(nxt_ip[0] - pp->x[0]);
1492
+
1493
+ }
1494
+ else
1495
+ pp->ignore = 2;
1496
+
1497
+ if (height > 0)
1498
+ hyperv += hypera * height;
1499
+
1500
+ #if VARIANT >= 2
1501
+ }
1502
+ #endif
1503
+ }
1504
+ avl_clear_tree(tree);
1505
+ return hyperv;
1506
+ }
1507
+
1508
+ /* special case of dimension 2 */
1509
+ else if (dim == 1) {
1510
+ p1 = list->next[1];
1511
+ hypera = p1->x[0];
1512
+ while ((p0 = p1->next[1])->x) {
1513
+ hyperv += (ref[0] - hypera) * (p0->x[1] - p1->x[1]);
1514
+ if (p0->x[0] < hypera)
1515
+ hypera = p0->x[0];
1516
+ p1 = p0;
1517
+ }
1518
+ hyperv += (ref[0] - hypera) * (ref[1] - p1->x[1]);
1519
+ return hyperv;
1520
+ }
1521
+
1522
+ /* special case of dimension 1 */
1523
+ else if (dim == 0) {
1524
+ return (ref[0] - list->next[0]->x[0]);
1525
+ }
1526
+
1527
+ else {
1528
+ fprintf(stderr, "%s:%d: unreachable condition! \n"
1529
+ "This is a bug, please report it to "
1530
+ "m.lopez-ibanez@napier.ac.uk\n", __FILE__, __LINE__);
1531
+ exit(EXIT_FAILURE);
1532
+ }
1533
+ }
1534
+
1535
+ double fonseca(double *data, double *ref, unsigned int d, unsigned int n)
1536
+ {
1537
+ dlnode_t *list;
1538
+ double hyperv;
1539
+ double * bound = NULL;
1540
+
1541
+ #if VARIANT >= 3
1542
+ unsigned int i;
1543
+
1544
+ bound = (double*)ini_malloc (d * sizeof(double));
1545
+ for (i = 0; i < d; i++) bound[i] = -std::numeric_limits<double>::max();
1546
+ #endif
1547
+
1548
+ tree = avl_alloc_tree ((avl_compare_t) compare_tree_asc,
1549
+ (avl_freeitem_t) free);
1550
+
1551
+ list = setup_cdllist(data, d, n);
1552
+
1553
+ hyperv = hv_recursive(list, d-1, n, ref, bound);
1554
+
1555
+
1556
+ /* Manually free all allocated memory - kind of garbage collection */
1557
+ for (i = 0; i < allocated_pointers.size(); i++ ) {
1558
+ free( allocated_pointers[i] );
1559
+ }
1560
+
1561
+ allocated_pointers.clear();
1562
+ return hyperv;
1563
+ }
1564
+
1565
+
1566
+ struct LastObjectiveComparator {
1567
+ static unsigned int NO_OBJECTIVES;
1568
+ static int compare( const void * p1, const void * p2 ) {
1569
+ const double * d1 = reinterpret_cast<const double*>( p1 );
1570
+ const double * d2 = reinterpret_cast<const double*>( p2 );
1571
+
1572
+ if (d1[NO_OBJECTIVES-1] < d2[NO_OBJECTIVES-1]) return -1;
1573
+ else if (d1[NO_OBJECTIVES-1] > d2[NO_OBJECTIVES-1]) return 1;
1574
+ else return 0;
1575
+ }
1576
+ };
1577
+ unsigned int LastObjectiveComparator::NO_OBJECTIVES = 0;
1578
+
1579
+ double hypervolume(double* points, double* referencePoint, unsigned int noObjectives, unsigned int noPoints) {
1580
+ unsigned int i;
1581
+ if (noObjectives == 0) {
1582
+ throw std::invalid_argument("[hypervolume] dimension must be positive");
1583
+ }
1584
+ else if (noObjectives == 1) {
1585
+ // trivial
1586
+ double m = 1e100;
1587
+ for (i=0; i<noPoints; i++) if (points[i] < m) m = points[i];
1588
+ double h = *referencePoint - m;
1589
+ if (h < 0.0) h = 0.0;
1590
+ return h;
1591
+ }
1592
+ else if (noObjectives == 2) {
1593
+ // sort by last objective
1594
+ LastObjectiveComparator::NO_OBJECTIVES = 2;
1595
+ qsort(points, noPoints, noObjectives * sizeof(double), LastObjectiveComparator::compare );
1596
+ // sortByLastObjective(points, noObjectives, noPoints);
1597
+ double h = (referencePoint[0] - points[0]) * (referencePoint[1] - points[1]);
1598
+ double diffDim1;
1599
+ unsigned int pre = 0;
1600
+ for (i=1; i<noPoints; i++)
1601
+ {
1602
+ diffDim1 = points[2*pre] - points[2*i]; // Might be negative, if the i-th solution is dominated.
1603
+ if( diffDim1 > 0 )
1604
+ {
1605
+ h += diffDim1 * (referencePoint[1] - points[2*i+1]);
1606
+ pre = i;
1607
+ }
1608
+ }
1609
+ return h;
1610
+ }
1611
+ else if (noObjectives == 3) {
1612
+ return fonseca(points, referencePoint, noObjectives, noPoints);
1613
+ }
1614
+ else {
1615
+ LastObjectiveComparator::NO_OBJECTIVES = noObjectives;
1616
+ qsort(points, noPoints, noObjectives * sizeof(double), LastObjectiveComparator::compare );
1617
+ // sortByLastObjective(points, noObjectives, noPoints);
1618
+ return overmars_yap(points, referencePoint, noObjectives, noPoints);
1619
+ }
1620
+ }
1621
+