parent_centric_crossover#
- moocore.parent_centric_crossover(population, /, *, targets=None, lower=None, upper=None, sigma_zeta=0.1, sigma_eta=0.1, seed=None)[source]#
Parent-centric crossover (PCX).
Each target \(x\) is an index parent. Two more parents \(a, b\) are drawn from
population, distinct from each other and from the target. Let \(d = x - g\), where \(g\) is the centroid of the three parents, and let \(\bar{D}\) be the mean distance from \(a\) and \(b\) to the line through \(x\) along \(d\). The offspring is\[x + \zeta d + \bar{D} \eta,\]where \(\zeta \sim N(0, \sigma_\zeta^2)\) and \(\eta\) is a vector of independent \(N(0, \sigma_\eta^2)\) values projected onto the subspace orthogonal to \(d\). Finally, the offspring is clipped to the bounds.
- Parameters:
population (
ArrayLike) – 2D array of numerical values, where each row is a decision vector. It must have at least 3 rows.targets (
ArrayLike|None) – 1D vector of row indices ofpopulation. Each index produces one offspring.Noneuses every row. (default:None)lower (
ArrayLike|None) – Lower bounds of the decision variables. Either a single value, which will be used for all variables, or one value per column.Nonemeans no lower bound. (default:None)upper (
ArrayLike|None) – Upper bounds of the decision variables. Either a single value, which will be used for all variables, or one value per column.Nonemeans no upper bound. (default:None)sigma_zeta (
float) – Standard deviation \(\sigma_\zeta > 0\) of the step along \(d\). (default:0.1)sigma_eta (
float) – Standard deviation \(\sigma_\eta > 0\) of the steps orthogonal to \(d\). (default:0.1)seed (
int|Generator|None) – Either an integer to seednumpy.random.default_rng(), a Numpy default random number generator (RNG) or an instance of a Numpy-compatible RNG.Noneuses the equivalent of a random seed, as innumpy.random.default_rng(). (default:None)
- Returns:
ndarray– Array with one row per target, where rowiis the offspring of index parenttargets[i].
Notes
PCX was proposed by Deb, Anand and Joshi (2002), who use three parents and \(\sigma_\zeta = \sigma_\eta = 0.1\). Their equation (2) writes the step orthogonal to \(d\) as a sum of normal steps along \(\mu - 1\) orthonormal vectors, where \(\mu\) is the number of parents. Like pymoo, which bases its implementation on the authors’ C code, this function projects an isotropic normal vector onto the whole subspace orthogonal to \(d\), so the step covers every direction orthogonal to \(d\), not only \(\mu - 1\) of them. If \(x\) is (almost) the centroid, the projection is skipped.
References
K. Deb, A. Anand and D. Joshi (2002). A computationally efficient evolutionary algorithm for real-parameter optimization. Evolutionary Computation, 10(4):371–395. https://doi.org/10.1162/106365602760972767
Examples
>>> population = np.array([[0.2, 0.2], [0.4, 0.9], [0.8, 0.3], [0.5, 0.5]]) >>> moocore.parent_centric_crossover( ... population, targets=[0, 3], lower=0, upper=1, seed=42 ... ) array([[0.18832072, 0.19642879], [0.50136187, 0.44711562]])