individual.bend
unified-nsga-iii@0.2.1.0 · 146 lines · 0 definitions
1# Individual — C# Unsga3.Algorithm.Individual.
2# Objectives + decision variables + evaluated + tournament bookkeeping
3# (rank / niche / associated ref / perp distance).
4# Constraints are g ≤ 0. `cv` is the sum of the positive parts
5# (RefreshConstraintViolation). Feasible iff cv ≤ 0. Empty g is cv 0,
6# so unconstrained ZDT / DTLZ stay on the Pareto path.
7# `lnk` is false until `stamp` (C# AssociatedReference starts at -1).
8# CV-fill clears it again: those members are not in a niche.
9
10import Base
11
12type Individual is Data:
13 MkIndividual{
14 x: List<&2, F32>
15 f: List<&2, F32>
16 g: List<&2, F32>
17 cv: F32
18 rnk: Nat
19 nic: Nat
20 aref: Nat
21 dist: F32
22 ev: Bool
23 lnk: Bool
24 }
25
26def pos_part(+x: F32) -> F32:
27 Bool.pick(F32, F32.is_gt(x, 0.0), x, 0.0)
28
29# Sum of g_i where g_i > 0. Non-positive parts add nothing.
30def sum_pos(xs: List<&2, F32>) -> F32:
31 match xs:
32 case Nil{}:
33 0.0
34 case +h <> t:
35 F32.add(pos_part(h), sum_pos(t))
36
37# v0 / A/B path: objectives already known; no decision vector.
38# No constraints → cv 0 (feasible).
39def from_objectives(+f: List<&2, F32>) -> Individual:
40 MkIndividual{Nil{}, f, Nil{}, 0.0, 0n, 0n, 0n, 0.0, True{}, False{}}
41
42# Unevaluated candidate: variables set, objectives zeroed (C# ctor).
43# Constraints empty until a problem writes them.
44def from_variables(+x: List<&2, F32>, n_obj: Nat) -> Individual:
45 MkIndividual{x, List.replicate(F32, n_obj, 0.0), Nil{}, 0.0, 0n, 0n, 0n, 0.0, False{}, False{}}
46
47def variables(ind: Individual) -> List<&2, F32>:
48 match ind:
49 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
50 x
51
52def objectives(ind: Individual) -> List<&2, F32>:
53 match ind:
54 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
55 f
56
57def constraints(ind: Individual) -> List<&2, F32>:
58 match ind:
59 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
60 g
61
62def constraint_violation(ind: Individual) -> F32:
63 match ind:
64 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
65 cv
66
67# C# IsFeasible: ConstraintViolation <= 0.
68def feasible(ind: Individual) -> Bool:
69 F32.is_le(constraint_violation(ind), 0.0)
70
71def rank(ind: Individual) -> Nat:
72 match ind:
73 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
74 rnk
75
76def evaluated(ind: Individual) -> Bool:
77 match ind:
78 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
79 ev
80
81def n_obj(ind: Individual) -> Nat:
82 List.length(&2, F32, objectives(ind))
83
84def n_var(ind: Individual) -> Nat:
85 List.length(&2, F32, variables(ind))
86
87def var_at(ind: Individual, i: Nat) -> F32:
88 Maybe.default(&2, F32, List.get(&2, F32, variables(ind), i), 0.0)
89
90def set_var_at(ind: Individual, i: Nat, v: F32) -> Individual:
91 match ind:
92 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
93 MkIndividual{List.set(&2, F32, x, i, v), f, g, cv, rnk, nic, ar, pd, ev, lnk}
94
95def set_evaluated(ind: Individual, ev2: Bool) -> Individual:
96 match ind:
97 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
98 MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev2, lnk}
99
100def niche(ind: Individual) -> Nat:
101 match ind:
102 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
103 nic
104
105def associated_ref(ind: Individual) -> Nat:
106 match ind:
107 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
108 ar
109
110def perp_dist(ind: Individual) -> F32:
111 match ind:
112 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
113 pd
114
115def set_objectives(ind: Individual, +f2: List<&2, F32>) -> Individual:
116 match ind:
117 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
118 MkIndividual{x, f2, g, cv, rnk, nic, ar, pd, True{}, lnk}
119
120# Replace g and recompute cv (sum of positive parts).
121def set_constraints(ind: Individual, +g2: List<&2, F32>) -> Individual:
122 match ind:
123 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
124 MkIndividual{x, f, g2, sum_pos(g2), rnk, nic, ar, pd, ev, lnk}
125
126def set_rank(ind: Individual, rnk2: Nat) -> Individual:
127 match ind:
128 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
129 MkIndividual{x, f, g, cv, rnk2, nic, ar, pd, ev, lnk}
130
131def stamp(ind: Individual, +rnk2: Nat, +nic2: Nat, +aref2: Nat, +dist2: F32) -> Individual:
132 match ind:
133 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
134 MkIndividual{x, f, g, cv, rnk2, nic2, aref2, dist2, ev, True{}}
135
136# C# AssociatedReference starts at -1. `stamp` is the assignment.
137def niche_linked(ind: Individual) -> Bool:
138 match ind:
139 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
140 lnk
141
142# CV fill does not assign a niche (pymoo merges these after survival).
143def clear_niche(ind: Individual) -> Individual:
144 match ind:
145 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev, lnk}:
146 MkIndividual{x, f, g, cv, rnk, 0n, 0n, 0.0, ev, False{}}