Skip to content

Fix to complex numbers in cxSimulatedBinaryBounded#567

Open
markstrefford wants to merge 1 commit into
DEAP:masterfrom
markstrefford:master
Open

Fix to complex numbers in cxSimulatedBinaryBounded#567
markstrefford wants to merge 1 commit into
DEAP:masterfrom
markstrefford:master

Conversation

@markstrefford

Copy link
Copy Markdown

In certain situations, beta_q is creating a complex number (see https://stackoverflow.com/questions/66903214/why-is-python-creating-a-complex-number-here/66903343). This is because the unary - in a negative result for (1.0 / (2.0 - rand * alpha)) takes precedence over ** (1.0 / (eta + 1)).

This fix identifies the sign (-/+) and uses the absolute values in the calculation for beta_q, then retrospectively applies the correct sign again.

@fmder

fmder commented Nov 13, 2021

Copy link
Copy Markdown
Member

Not sure it is really operator precedence as the expression is wrapped in parenthesis.

@delaidam

delaidam commented Jul 8, 2026

Copy link
Copy Markdown

@fmder you're right that it's not operator precedence- The parenthesization
is already correct there. I dug into this a bit more and think the actual
root cause is one step earlier, in the alpha computation:

beta = 1.0 + (2.0 * (x1 - xl) / (x2 - x1))
alpha = 2.0 - beta ** -(eta + 1)

beta goes negative when x1 (or x2, in the symmetric second calculation)
falls even slightly outside [xl, xu] which can legitimately happen after
a prior mutation step, before this crossover runs. With a non-integer eta
(a perfectly normal value, e.g. 15.5), beta ** -(eta + 1) is then a
negative base raised to a fractional exponent, which Python evaluates as
complex. That complex alpha is what breaks the <= comparison downstream which is the same failure mode reported again more recently in #740.

Minimal repro:

x1, x2, xl, xu, eta = -6.0, 5.0, 0.0, 10.0, 15.5
beta = 1.0 + (2.0 * (x1 - xl) / (x2 - x1))   # -0.0909...
alpha = 2.0 - beta ** -(eta + 1)              # (-35.23+1.52e17j)

Since the function already clamps the output back into [xl, xu]
(c1 = min(max(c1, xl), xu)), the more consistent fix is probably to clamp
the inputs (x1, x2) into [xl, xu] before computing beta, rather than
patching the beta_q line this PR touches and that would stop beta from ever
going negative in the first place, for any eta. Happy to help however's
useful, but wanted to flag the diagnosis in case it changes the direction
of the fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants