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}