From 10d380161120f65c8353e156c173247e8b89d458 Mon Sep 17 00:00:00 2001 From: Luke McCombs Date: Sat, 21 Dec 2024 16:16:57 -0500 Subject: [PATCH 1/2] Fix prob_bin behavior --- pymoo/operators/crossover/sbx.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pymoo/operators/crossover/sbx.py b/pymoo/operators/crossover/sbx.py index 41a1c025a..a75948042 100644 --- a/pymoo/operators/crossover/sbx.py +++ b/pymoo/operators/crossover/sbx.py @@ -26,8 +26,8 @@ def cross_sbx(X, xl, xu, eta, prob_var, prob_bin, eps=1.0e-14): 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] + p1_low = X[0] < X[1] + y1, y2 = np.where(p1_low[None, ...], X, X[::-1])[:, cross] # mask all the values that should be crossovered _xl = np.repeat(xl[None, :], n_matings, axis=0)[cross] @@ -61,10 +61,8 @@ def calc_betaq(beta): c2 = 0.5 * ((y1 + y2) + betaq * delta) # with the given probability either assign the value from the first or second parent - b = np.random.random(len(prob_bin)) < prob_bin - tmp = np.copy(c1[b]) - c1[b] = c2[b] - c2[b] = tmp + b = (np.random.random(len(prob_bin)) < prob_bin) == p1_low[cross] + c1, c2 = np.where(b[None, ...], [c1, c2], [c2, c1]) # first copy the unmodified parents Q = np.copy(X) From ca8370ed841c22ecd0c1101c607256746d15f7f0 Mon Sep 17 00:00:00 2001 From: Luke McCombs Date: Mon, 13 Jan 2025 13:39:46 -0500 Subject: [PATCH 2/2] Fewer masks --- pymoo/operators/crossover/sbx.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pymoo/operators/crossover/sbx.py b/pymoo/operators/crossover/sbx.py index a75948042..d56e6973d 100644 --- a/pymoo/operators/crossover/sbx.py +++ b/pymoo/operators/crossover/sbx.py @@ -26,8 +26,9 @@ def cross_sbx(X, xl, xu, eta, prob_var, prob_bin, eps=1.0e-14): cross[:, xl == xu] = False # assign y1 the smaller and y2 the larger value - p1_low = X[0] < X[1] - y1, y2 = np.where(p1_low[None, ...], X, X[::-1])[:, cross] + X_cross = X[:, cross] + p1_low = X_cross[0] < X_cross[1] + y1, y2 = np.where(p1_low[None,], X_cross, X_cross[::-1]) # mask all the values that should be crossovered _xl = np.repeat(xl[None, :], n_matings, axis=0)[cross] @@ -61,15 +62,15 @@ def calc_betaq(beta): c2 = 0.5 * ((y1 + y2) + betaq * delta) # with the given probability either assign the value from the first or second parent - b = (np.random.random(len(prob_bin)) < prob_bin) == p1_low[cross] - c1, c2 = np.where(b[None, ...], [c1, c2], [c2, c1]) + b = (np.random.random(len(prob_bin)) < prob_bin) == p1_low + C = np.stack((c1, c2), 0) + C = np.where(b[None,], C, C[::-1]) # 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[:, cross] = C Q[0] = repair_clamp(Q[0], xl, xu) Q[1] = repair_clamp(Q[1], xl, xu)