The nonlinear constrained optimization interface in Evolutionary assumes that the user can write the optimization problem as follows:
\[\min_{x\in\mathbb{R}^n} f(x) \quad \text{such that}\\ l_x \leq \phantom{c(}x\phantom{)} \leq u_x \\ l_c \leq c(x) \leq u_c.\]
For equality constraints on $x_j$ or $c(x)_j$ you set those particular entries of bounds to be equal, $l_j=u_j$. Likewise, setting $l_j=-\infty$ or $u_j=\infty$ means that the constraint is unbounded from below or above respectively.
Following examples show how to use constraints to optimize the Booth function. The function is defined as follows:
julia> f(x)=(x[1]+2x[2]-7)^2+(2x[1]+x[2]-5)^2 # Boothf (generic function with 1 method)
The function is usually evaluated on the square $x_i ∈ [-10, 10]$, for all $i = 1, 2$. The global minimum on this function is located at $(1,3)$.
ga = GA(populationSize=100,selection=uniformranking(3),
mutation=gaussian(),crossover=uniformbin())
x0 = [0., 0.]
results = Evolutionary.optimize(f, x0, ga)
* Status: success
* Candidate solution
Minimizer: [1.0432333731446404, 2.9420270506960593]
Minimum: 0.006099007825884248
Iterations: 28
* Found with
Algorithm: GA[P=100,x=0.8,μ=0.1,ɛ=0]
* Convergence measures
|f(x) - f(x')| = 0.0 ≤ 1.0e-12
* Work counters
Seconds run: 0.0055 (vs limit Inf)
Iterations: 28
f(x) calls: 2900
Box Constrained Optimization
We want to optimize the Booth function in the box $0.5 \leq x_i \leq 2.0$, starting from the point $x_0=(1,1)$.
Reusing our Booth example from above, boxed minimization is performed by providing vectors of lower and upper bounds as follows:
lower = [0.5, 0.5]
upper = [2.0, 2.0]
x0 = [1., 1.]
results = Evolutionary.optimize(f, BoxConstraints(lower, upper), x0, ga)
* Status: success
* Candidate solution
Minimizer: [1.7491949009716918, 2.0]
Minimum: 1.812905790436381
Iterations: 14
* Found with
Algorithm: GA[P=100,x=0.8,μ=0.1,ɛ=0]
* Convergence measures
|f(x) - f(x')| = 0.0 ≤ 1.0e-12
* Work counters
Seconds run: 0.0006 (vs limit Inf)
Iterations: 14
f(x) calls: 1500
The box constraints can be also defined using BoxConstraints object.
Evolutionary.BoxConstraints — Type
This type encodes box constraints for the optimization function parameters.
The constructor takes following arguments:
loweris the vector of value lower boundsupperis the vector of value upper bounds
Note: Sizes of the lower and upper bound vectors must be equal.
cnst = BoxConstraints([0.5, 0.5], [2.0, 2.0])Box Constraints:
x[1]≥0.5, x[1]≤2.0, x[2]≥0.5, x[2]≤2.0This object can be passed as a parameter to the optimization call, Evolutionary.optimize:
results = Evolutionary.optimize(f, cnst, x0, ga) # or Evolutionary.optimize(f, cnst, ga)
* Status: success
* Candidate solution
Minimizer: [1.7837244091240685, 2.0]
Minimum: 1.8013244742918035
Iterations: 24
* Found with
Algorithm: GA[P=100,x=0.8,μ=0.1,ɛ=0]
* Convergence measures
|f(x) - f(x')| = 0.0 ≤ 1.0e-12
* Work counters
Seconds run: 0.001 (vs limit Inf)
Iterations: 24
f(x) calls: 2500
Penalty Constrained Optimization
For the penalty constrained optimization, any value and linear/nonlinear constraints are transformed into the penalty to the minimized fitness function. In order to provide linear/nonlinear constraints to an optimization problem, you can use the following penalty constraint algorithm:
Evolutionary.PenaltyConstraints — Type
This type encodes constraints as the following additional penalty for an objective function:
$p(x) = \sum^n_{i=1} r_i max(0, g_i(x))^2$
where $r_i$ is a penalty value for $i$th constraint, and $g_i(x)$ is an inequality constraint. The equality constraints $h_i(x) = 0$ are transformed to inequality constraints as follows:
$h(x) - \epsilon \leq 0$
The constructor takes following arguments:
penalties: a vector of penalty values per constraint (optional)lx: a vector of value lower boundsux: a vector of value upper boundslc: a vector of constrain function lower boundsuc: a vector of constrain function upper boundsc: a constraint function which returns a constrain values
We want to minimize the following function $f(x,y) = 3x+9y$ that is subject to constraints $\sqrt(xy) \geq 100$ and $x,y \geq 0$. The minimum of this function is near $(173.41, 57.8)$. We begin by defining constraints as follows:
# x, y ≥ 0
lx = [0.0, 0.0] # lower bound for values
ux = [Inf, Inf] # upper bound for values
# √xy ≥ 100
c(x) = [ prod(map(e->sqrt(e>0 ? e : 0.0), x)) ] # negative values are zeroed
lc = [100.0] # lower bound for constraint function
uc = [ Inf ] # upper bound for constraint function
con = PenaltyConstraints(100.0, lx, ux, lc, uc, c) # first parameter is a penalty valuePenalty Constraints:
Penalties: [100.0, 100.0, 100.0]
ConstraintBounds:
Variables:
x[1]≥0.0, x[2]≥0.0
Linear/nonlinear constraints:
c_1≥100.0Now, we define the fitness function, an initial individual structure, and algorithm parameters; then we perform minimization as follows:
f(x) = 3x[1]+9x[2] # fitness function
x0 = [1., 1.] # individual
ga = GA(populationSize=100,selection=tournament(7),
mutation=gaussian(),crossover=intermediate(2))
results = Evolutionary.optimize(f, con, x0, ga)
* Status: success
* Candidate solution
Minimizer: [173.04042387335875, 57.72963159858678]
Minimum: 1038.9605864183598
Iterations: 35
* Found with
Algorithm: GA[P=100,x=0.8,μ=0.1,ɛ=0]
* Convergence measures
|f(x) - f(x')| = 0.0 ≤ 1.0e-12
* Work counters
Seconds run: 0.0043 (vs limit Inf)
Iterations: 35
f(x) calls: 3600
We can use worst fitness constraint algorithm which doesn't require to specify the constraint penalty value
Evolutionary.WorstFitnessConstraints — Type
This type encodes constraints as the following additional penalty for an objective function:
$p(x) = f_{worst} + \sum^n_{i=1} |g_i(x)|$
if $x$ is not feasible, otherwise no penalty is applied.
The constructor takes following arguments:
lx: a vector of value lower boundsux: a vector of value upper boundslc: a vector of constrain function lower boundsuc: a vector of constrain function upper boundsc: a constraint function which returns a constrain values
con = WorstFitnessConstraints(lx, ux, lc, uc, c)Worst Fitness ConstraintBounds:
Variables:
x[1]≥0.0, x[2]≥0.0
Linear/nonlinear constraints:
c_1≥100.0results = Evolutionary.optimize(f, con, x0, ga)
* Status: success
* Candidate solution
Minimizer: [167.96091588680574, 59.53768350155998]
Minimum: 1039.7218991744571
Iterations: 101
* Found with
Algorithm: GA[P=100,x=0.8,μ=0.1,ɛ=0]
* Convergence measures
|f(x) - f(x')| = 0.0 ≤ 1.0e-12
* Work counters
Seconds run: 0.0127 (vs limit Inf)
Iterations: 101
f(x) calls: 10200
Auxiliary Functions
Evolutionary.constraint_values — Method
constraint_values(c::AbstractConstraints, x)Return the nonlinear constraint-function values for candidate x under c.
Interface
Custom AbstractConstraints implementations with nonlinear constraints must extend this function. Return nothing when no nonlinear constraint function is present. Otherwise, return an indexable collection ordered consistently with the constraint bounds returned by bounds: equality values first, then inequality values.
Arguments
c: Constraint object being evaluated.x: Candidate optimization variable.
Returns
nothing for constraints without nonlinear constraint functions, or the values used by isfeasible and penalty to evaluate c.
Examples
julia> constraint_values(NoConstraints(), [1.0, 2.0])
nothingEvolutionary.isfeasible — Function
isfeasible(bounds::ConstraintBounds, x) -> BoolReturn true if point x is feasible, given the bounds object with bounds lx, ux, lc, and uc. x is feasible if
lx[i] <= x[i] <= ux[i]
lc[i] <= c(x)[i] <= uc[i]for all possible i.
isfeasible(c::AbstractConstraints, x) -> BoolReturn true if point x is feasible, given the constraints object c.
Evolutionary.penalty — Function
penalty(constraints, x)Calculate a penalty for the variable x given the set of constraints.
Evolutionary.penalty! — Function
penalty!(fitness, constraints, population)Set a penalty to the fitness given the set of constraints and population.
Evolutionary.apply! — Function
apply!(c::AbstractConstraints, x)Appliy constrains c to a variable x, and return the variable.
Evolutionary.bounds — Function
bounds(c::AbstractConstraints)Return bounds for the constraint c.