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 8 import Base 9 10 type 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 23 def 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. 27 def 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). 36 def 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. 41 def 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 44 def variables(ind: Individual) -> List<&2, F32>: 45 match ind: 46 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}: 47 x 48 49 def objectives(ind: Individual) -> List<&2, F32>: 50 match ind: 51 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}: 52 f 53 54 def constraints(ind: Individual) -> List<&2, F32>: 55 match ind: 56 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}: 57 g 58 59 def 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. 65 def feasible(ind: Individual) -> Bool: 66 F32.is_le(constraint_violation(ind), 0.0) 67 68 def rank(ind: Individual) -> Nat: 69 match ind: 70 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}: 71 rnk 72 73 def evaluated(ind: Individual) -> Bool: 74 match ind: 75 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}: 76 ev 77 78 def n_obj(ind: Individual) -> Nat: 79 List.length(&2, F32, objectives(ind)) 80 81 def n_var(ind: Individual) -> Nat: 82 List.length(&2, F32, variables(ind)) 83 84 def var_at(ind: Individual, i: Nat) -> F32: 85 Maybe.default(&2, F32, List.get(&2, F32, variables(ind), i), 0.0) 86 87 def 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 92 def 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 97 def niche(ind: Individual) -> Nat: 98 match ind: 99 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}: 100 nic 101 102 def associated_ref(ind: Individual) -> Nat: 103 match ind: 104 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}: 105 ar 106 107 def perp_dist(ind: Individual) -> F32: 108 match ind: 109 case MkIndividual{x, f, g, cv, rnk, nic, ar, pd, ev}: 110 pd 111 112 def 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). 118 def 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 123 def 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 128 def 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}