individual.bend
unified-nsga-iii@0.2.0.0 · 131 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
8import Base
9
10type Individual is Data:
11 MkIndividual{
12 x: List<&2, F32>
13 f: List<&2, F32>
14 g: List<&2, F32>
15 cv: F32
16 rnk: Nat
17 nic: Nat
18 aref: Nat
19 dist: F32
20 ev: Bool
21 }
22
23def pos_part(+x: F32) -> F32:
24 Bool.pick(F32, F32.is_gt(x, 0.0), x, 0.0)
25
26# Sum of g_i where g_i > 0. Non-positive parts add nothing.
27def sum_pos(xs: List<&2, F32>) -> F32:
28 match xs:
29 case Nil{}:
30 0.0
31 case +h <> t:
32 F32.add(pos_part(h), sum_pos(t))
33
34# v0 / A/B path: objectives already known; no decision vector.
35# No constraints → cv 0 (feasible).
36def from_objectives(+f: List<&2, F32>) -> Individual:
37 MkIndividual{Nil{}, f, Nil{}, 0.0, 0n, 0n, 0n, 0.0, True{}}
38
39# Unevaluated candidate: variables set, objectives zeroed (C# ctor).
40# Constraints empty until a problem writes them.
41def from_variables(+x: List<&2, F32>, n_obj: Nat) -> Individual:
42 MkIndividual{x, List.replicate(F32, n_obj, 0.0), Nil{}, 0.0, 0n, 0n, 0n, 0.0, False{}}
43
44def variables(ind: Individual) -> List<&2, F32>:
45 match ind:
46 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
47 x
48
49def objectives(ind: Individual) -> List<&2, F32>:
50 match ind:
51 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
52 f
53
54def constraints(ind: Individual) -> List<&2, F32>:
55 match ind:
56 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
57 g
58
59def constraint_violation(ind: Individual) -> F32:
60 match ind:
61 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
62 cv
63
64# C# IsFeasible: ConstraintViolation <= 0.
65def feasible(ind: Individual) -> Bool:
66 F32.is_le(constraint_violation(ind), 0.0)
67
68def rank(ind: Individual) -> Nat:
69 match ind:
70 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
71 rnk
72
73def evaluated(ind: Individual) -> Bool:
74 match ind:
75 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
76 ev
77
78def n_obj(ind: Individual) -> Nat:
79 List.length(&2, F32, objectives(ind))
80
81def n_var(ind: Individual) -> Nat:
82 List.length(&2, F32, variables(ind))
83
84def var_at(ind: Individual, i: Nat) -> F32:
85 Maybe.default(&2, F32, List.get(&2, F32, variables(ind), i), 0.0)
86
87def set_var_at(ind: Individual, i: Nat, v: F32) -> Individual:
88 match ind:
89 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
90 MkIndividual{List.set(&2, F32, x, i, v), f, g, cv, rnk, nic, ar, pd, ev}
91
92def set_evaluated(ind: Individual, ev2: Bool) -> Individual:
93 match ind:
94 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
95 MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev2}
96
97def niche(ind: Individual) -> Nat:
98 match ind:
99 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
100 nic
101
102def associated_ref(ind: Individual) -> Nat:
103 match ind:
104 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
105 ar
106
107def perp_dist(ind: Individual) -> F32:
108 match ind:
109 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
110 pd
111
112def set_objectives(ind: Individual, +f2: List<&2, F32>) -> Individual:
113 match ind:
114 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
115 MkIndividual{x, f2, g, cv, rnk, nic, ar, pd, True{}}
116
117# Replace g and recompute cv (sum of positive parts).
118def set_constraints(ind: Individual, +g2: List<&2, F32>) -> Individual:
119 match ind:
120 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
121 MkIndividual{x, f, g2, sum_pos(g2), rnk, nic, ar, pd, ev}
122
123def set_rank(ind: Individual, rnk2: Nat) -> Individual:
124 match ind:
125 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
126 MkIndividual{x, f, g, cv, rnk2, nic, ar, pd, ev}
127
128def stamp(ind: Individual, +rnk2: Nat, +nic2: Nat, +aref2: Nat, +dist2: F32) -> Individual:
129 match ind:
130 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}:
131 MkIndividual{x, f, g, cv, rnk2, nic2, aref2, dist2, ev}