Skip to content

Commit 6c45dcf

Browse files
committed
Fix SBX prob_bin parameter to control parent exchange probability
- Preserve parent identity during SBX crossover calculations - Make prob_bin represent probability of parent value exchange - Ensure Child 1 inherits from Parent 1 when prob_bin=0.0 - Use cleaner np.where syntax for child assignment and exchange With this fix: - prob_bin=0.0: Child1←Parent1, Child2←Parent2 (no exchange) - prob_bin=0.25: 25% chance of exchange (Child1←Parent2, Child2←Parent1) - prob_bin=0.5: 50% chance of exchange (equivalent to old behavior) - prob_bin=1.0: Always exchange (Child1←Parent2, Child2←Parent1) Addresses #673
1 parent 188eef9 commit 6c45dcf

File tree

1 file changed

+16
-9
lines changed
  • pymoo/operators/crossover

1 file changed

+16
-9
lines changed

pymoo/operators/crossover/sbx.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,14 @@ def cross_sbx(X, xl, xu, eta, prob_var, prob_bin, eps=1.0e-14):
2525
# disable crossover when lower and upper bound are identical
2626
cross[:, xl == xu] = False
2727

28-
# assign y1 the smaller and y2 the larger value
29-
y1 = np.min(X, axis=0)[cross]
30-
y2 = np.max(X, axis=0)[cross]
28+
# preserve parent identity while getting values for SBX calculation
29+
p1 = X[0][cross]
30+
p2 = X[1][cross]
31+
32+
# assign y1 the smaller and y2 the larger value for SBX calculation
33+
sm = p1 < p2
34+
y1 = np.where(sm, p1, p2)
35+
y2 = np.where(sm, p2, p1)
3136

3237
# mask all the values that should be crossovered
3338
_xl = np.repeat(xl[None, :], n_matings, axis=0)[cross]
@@ -60,18 +65,20 @@ def calc_betaq(beta):
6065
betaq = calc_betaq(beta)
6166
c2 = 0.5 * ((y1 + y2) + betaq * delta)
6267

63-
# with the given probability either assign the value from the first or second parent
68+
# assign children based on parent position, then apply exchange probability
69+
child1 = np.where(sm, c1, c2) # child for parent 1
70+
child2 = np.where(sm, c2, c1) # child for parent 2
71+
72+
# exchange children with given probability
6473
b = np.random.random(len(prob_bin)) < prob_bin
65-
tmp = np.copy(c1[b])
66-
c1[b] = c2[b]
67-
c2[b] = tmp
74+
child1, child2 = np.where(b, (child2, child1), (child1, child2))
6875

6976
# first copy the unmodified parents
7077
Q = np.copy(X)
7178

7279
# copy the positions where the crossover was done
73-
Q[0, cross] = c1
74-
Q[1, cross] = c2
80+
Q[0, cross] = child1
81+
Q[1, cross] = child2
7582

7683
Q[0] = repair_clamp(Q[0], xl, xu)
7784
Q[1] = repair_clamp(Q[1], xl, xu)

0 commit comments

Comments
 (0)