problems.bend
unified-nsga-iii@0.1.2.0 · 180 lines · 0 definitions
1# Named problems — C# Unsga3.Problems Zdt1 / Zdt2 / Dtlz2.
2# Bounds + Evaluate match the attached C# IProblem / problem files.
3# Minimize. Unconstrained (NumberOfConstraints = 0).
4
5import Base
6import unified-nsga-iii@0.1.2.0/individual.bend as Ind
7import unified-nsga-iii@0.1.2.0/bounds.bend as Bounds
8import unified-nsga-iii@0.1.2.0/util.bend as Util
9
10type Family is Data:
11 Zdt1{}
12 Zdt2{}
13 Dtlz2{}
14
15type Problem is Data:
16 MkProblem{
17 kind: Family
18 box: Bounds.Box
19 }
20
21def box_of(p: Problem) -> Bounds.Box:
22 match p:
23 case MkProblem{kind, box}:
24 box
25
26def kind_of(p: Problem) -> Family:
27 match p:
28 case MkProblem{kind, box}:
29 kind
30
31def n_obj(p: Problem) -> Nat:
32 Bounds.n_obj(box_of(p))
33
34def n_var(p: Problem) -> Nat:
35 Bounds.n_var(box_of(p))
36
37# ZDT1 / ZDT2: n variables (C# default 30), 2 objectives, x ∈ [0,1]^n.
38def zdt1(n: Nat) -> Problem:
39 MkProblem{Zdt1{}, Bounds.unit_n(n, 2n)}
40
41def zdt2(n: Nat) -> Problem:
42 MkProblem{Zdt2{}, Bounds.unit_n(n, 2n)}
43
44# n = M + k - 1 (C# Dtlz2Problem).
45def dtlz_n(m: Nat, k: Nat) -> Nat:
46 match m:
47 case 0n:
48 k
49 case 1n+pm:
50 match k:
51 case 0n:
52 pm
53 case 1n+pk:
54 Nat.add(pm, 1n+pk)
55
56# DTLZ2: C# default M=3, k=10 ⇒ n=12, x ∈ [0,1]^n.
57def dtlz2(+m: Nat, k: Nat) -> Problem:
58 MkProblem{Dtlz2{}, Bounds.unit_n(dtlz_n(m, k), m)}
59
60def sum_from(xs: List<&2, F32>) -> F32:
61 match xs:
62 case Nil{}:
63 0.0
64 case h <> t:
65 F32.add(h, sum_from(t))
66
67def sum_tail(xs: List<&2, F32>) -> F32:
68 match xs:
69 case Nil{}:
70 0.0
71 case h <> t:
72 sum_from(t)
73
74def zdt_den(n: Nat) -> F32:
75 match n:
76 case 0n:
77 1.0
78 case 1n:
79 1.0
80 case 1n+p:
81 F32.from_nat(p)
82
83# C# Zdt1Problem.GLinear: 1 + 9 * sum(x[1..]) / (n - 1).
84def zdt_g(+x: List<&2, F32>) -> F32:
85 +n = Util.list_len(F32, x)
86 F32.add(1.0, F32.div(F32.mul(9.0, sum_tail(x)), zdt_den(n)))
87
88def zdt1_f(+x: List<&2, F32>) -> List<&2, F32>:
89 +x0 = Util.get_f32(x, 0n)
90 +g = zdt_g(x)
91 x0 <> [F32.mul(g, F32.sub(1.0, F32.sqrt(F32.div(x0, g))))]
92
93def zdt2_f(+x: List<&2, F32>) -> List<&2, F32>:
94 +x0 = Util.get_f32(x, 0n)
95 +g = zdt_g(x)
96 +r = F32.div(x0, g)
97 x0 <> [F32.mul(g, F32.sub(1.0, F32.mul(r, r)))]
98
99def pred(n: Nat) -> Nat:
100 match n:
101 case 0n:
102 0n
103 case 1n+p:
104 p
105
106def sum_sq_half(xs: List<&2, F32>) -> F32:
107 match xs:
108 case Nil{}:
109 0.0
110 case h <> t:
111 F32.add(F32.square(F32.sub(h, 0.5)), sum_sq_half(t))
112
113# C# DtlzHelper.GDtlz2: sum (x[i] - 0.5)^2 for i >= M-1.
114def dtlz2_g(+x: List<&2, F32>, m: Nat) -> F32:
115 sum_sq_half(List.drop(&2, F32, x, pred(m)))
116
117def half_pi() -> F32:
118 F32.div(F32.pi(), 2.0)
119
120def prod_cos.go(+x: List<&2, F32>, fuel: Nat, +i: Nat, acc: F32) -> F32:
121 match fuel:
122 case 0n:
123 acc
124 case 1n+f:
125 prod_cos.go(
126 x,
127 f,
128 1n+i,
129 F32.mul(acc, F32.cos(F32.mul(Util.get_f32(x, i), half_pi())))
130 )
131
132def prod_cos(+x: List<&2, F32>, n: Nat) -> F32:
133 prod_cos.go(x, n, 0n, 1.0)
134
135def dtlz2_sin(+x: List<&2, F32>, +m: Nat, +i: Nat) -> F32:
136 F32.sin(F32.mul(Util.get_f32(x, pred(Nat.sub(m, i))), half_pi()))
137
138def dtlz2_fi.tail(+x: List<&2, F32>, +m: Nat, +g: F32, +i: Nat, +body: F32, first: Bool) -> F32:
139 match first:
140 case True{}:
141 body
142 case False{}:
143 F32.mul(body, dtlz2_sin(x, m, i))
144
145# C# Dtlz2Problem: (1+g) * prod_{j<M-i-1} cos(x[j] π/2) [* sin(x[M-i-1] π/2) if i>0].
146def dtlz2_fi(+x: List<&2, F32>, +m: Nat, +g: F32, +i: Nat) -> F32:
147 dtlz2_fi.tail(
148 x,
149 m,
150 g,
151 i,
152 F32.mul(F32.add(1.0, g), prod_cos(x, pred(Nat.sub(m, i)))),
153 Nat.is_eq(i, 0n)
154 )
155
156def dtlz2_fs.go(+x: List<&2, F32>, +m: Nat, +g: F32, fuel: Nat, +i: Nat) -> List<&2, F32>:
157 match fuel:
158 case 0n:
159 Nil{}
160 case 1n+f:
161 dtlz2_fi(x, m, g, i) <> dtlz2_fs.go(x, m, g, f, 1n+i)
162
163def dtlz2_f(+x: List<&2, F32>, +m: Nat) -> List<&2, F32>:
164 dtlz2_fs.go(x, m, dtlz2_g(x, m), m, 0n)
165
166def eval_kind(kind: Family, +x: List<&2, F32>, +m: Nat) -> List<&2, F32>:
167 match kind:
168 case Zdt1{}:
169 zdt1_f(x)
170 case Zdt2{}:
171 zdt2_f(x)
172 case Dtlz2{}:
173 dtlz2_f(x, m)
174
175def evaluate(+p: Problem, +ind: Ind.Individual) -> Ind.Individual:
176 Ind.set_objectives(ind, eval_kind(kind_of(p), Ind.variables(ind), n_obj(p)))
177
178# Independent per individual. Mid-split + parallel recurse; same order as cons.
179def evaluate_all(+p: Problem, +xs: List<&2, Ind.Individual>) -> List<&2, Ind.Individual>:
180 Util.map_halves(~Ind.Individual, ~Ind.Individual, ~Problem, ~evaluate, p, xs)