Skip to content

Fix SBX prob_bin parameter to control parent exchange probability #725

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 23, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions pymoo/operators/crossover/sbx.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,14 @@ def cross_sbx(X, xl, xu, eta, prob_var, prob_bin, eps=1.0e-14):
# disable crossover when lower and upper bound are identical
cross[:, xl == xu] = False

# assign y1 the smaller and y2 the larger value
y1 = np.min(X, axis=0)[cross]
y2 = np.max(X, axis=0)[cross]
# preserve parent identity while getting values for SBX calculation
p1 = X[0][cross]
p2 = X[1][cross]

# assign y1 the smaller and y2 the larger value for SBX calculation
sm = p1 < p2
y1 = np.where(sm, p1, p2)
y2 = np.where(sm, p2, p1)

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

# with the given probability either assign the value from the first or second parent
# assign children based on parent position, then apply exchange probability
child1 = np.where(sm, c1, c2) # child for parent 1
child2 = np.where(sm, c2, c1) # child for parent 2

# exchange children with given probability
b = np.random.random(len(prob_bin)) < prob_bin
tmp = np.copy(c1[b])
c1[b] = c2[b]
c2[b] = tmp
child1, child2 = np.where(b, (child2, child1), (child1, child2))

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

# copy the positions where the crossover was done
Q[0, cross] = c1
Q[1, cross] = c2
Q[0, cross] = child1
Q[1, cross] = child2

Q[0] = repair_clamp(Q[0], xl, xu)
Q[1] = repair_clamp(Q[1], xl, xu)
Expand Down
Loading