API References

Core types

Missing docstring.

Missing docstring for BLProblem. Check Documenter's build log for details.

BilevelHeuristics.BLOptionsType
BLOptions(; ul = Options(), ll = Options())

Configuration settings (population size, iteration budget, tolerances, verbosity, etc.) for both the upper and lower levels.

Fields

Example

options = BLOptions(
    ul = Options(f_calls_limit = 10_000, verbose = true),
    ll = Options(f_calls_limit = 50_000),
)
source
Missing docstring.

Missing docstring for BLAlgorithm. Check Documenter's build log for details.

BilevelHeuristics.BLStateType
BLState{T}

The result of a bilevel optimisation run. Returned by optimize.

Fields

  • best_sol — the best BLIndividual found (according to the algorithm's comparison criterion).
  • population — the final population of BLIndividuals.
  • F_calls, f_calls — number of upper- and lower-level function evaluations.
  • iteration — number of completed iterations.
  • convergence — history of BLState snapshots (if store_convergence is enabled in options).
  • start_time, final_time, overall_time — timing information (seconds).
  • stop — whether the run stopped.
  • stop_msg — termination reason string.

Extracting results

Use minimum and minimizer to get the objective values and decision vectors of the best solution:

Fmin, fmin = minimum(res)      # (F, f) at the best solution
x, y       = minimizer(res)    # (x, y) at the best solution
source

Main interface

Metaheuristics.optimizeFunction
  optimize(
        f::Function, # objective function
        search_space,
        method::AbstractAlgorithm = ECA();
        logger::Function = (status) -> nothing,
  )

Minimize a n-dimensional function f with domain search_space (2×n matrix) using method = ECA() by default.

Example

Minimize f(x) = Σx² where x ∈ [-10, 10]³.

Solution:

julia> f(x) = sum(x.^2)
f (generic function with 1 method)

julia> bounds = [  -10.0 -10 -10; # lower bounds
                    10.0  10 10 ] # upper bounds
2×3 Array{Float64,2}:
 -10.0  -10.0  -10.0
  10.0   10.0   10.0

julia> result = optimize(f, bounds)
+=========== RESULT ==========+
  iteration: 1429
    minimum: 2.5354499999999998e-222
  minimizer: [-1.5135301653303966e-111, 3.8688354844737692e-112, 3.082095708730726e-112]
    f calls: 29989
 total time: 0.1543 s
+============================+
optimize(F, f, bounds_ul, bounds_ll, method = BCA(); logger = (status) -> nothing)

Solve a bilevel optimization problem using a heuristic or metaheuristic method.

The upper-level problem is min_x F(x, y) subject to x ∈ bounds_ul and any upper-level constraints returned by F, while y must be an optimal solution of the lower-level problem min_y f(x, y) subject to y ∈ bounds_ll and its own constraints.

Parameters

  • F(x, y) — upper-level objective function. Must return one of:
    • scalar value (unconstrained),
    • (fval, g, h) tuple where g / h are vectors of inequality / equality constraints.
  • f(x, y) — lower-level objective function (same signature as F).
  • bounds_ul — upper-level bounds, a 2 × D_ul matrix where row 1 = lower bounds, row 2 = upper bounds.
  • bounds_ll — lower-level bounds, a 2 × D_ll matrix (same layout).
  • method — a bilevel algorithm, e.g. BCA, QBCA, SABO, SMS_MOBO, etc. (default: BCA()).
  • logger — a function status -> ... called at the end of every iteration (useful for custom logging or visualisation).

Returns

A BLState object containing the best solution found, the final population, convergence history, and function evaluation counts. Use minimum and minimizer to extract results.

Example (single-objective, unconstrained)

F(x, y) = sum(x.^2) + sum(y.^2)
f(x, y) = sum((x - y).^2) + y[1]^2
bounds = [-ones(5)'; ones(5)']

res = optimize(F, f, bounds, bounds, BCA())
x, y = minimizer(res)
Fmin, fmin = minimum(res)

Example (constrained)

function F(x, y)
    fval = sum(x.^2) + sum(y.^2)
    g = [x[1] + x[2] - 1, x[3] - y[3] - 10]   # inequality constraints
    h = [0.0]                                     # equality constraints
    return fval, g, h
end

function f(x, y)
    fval = sum((x - y).^2) + y[1]^2
    g = [x[2] - y[1]^2 - 5]
    h = [0.0]
    return fval, g, h
end

bounds_ul = [-ones(5) ones(5)]
bounds_ll = [-ones(5) ones(5)]
res = optimize(F, f, bounds_ul, bounds_ll, BCA())

Example (multi-objective)

function F(x, y)  # two upper-level objectives
    [y[1] - x[1], y[2]], [-1.0 - sum(y)], [0.0]
end

function f(x, y)  # two lower-level objectives
    y, [-x[1]^2 + sum(y .^ 2)], [0.0]
end

bounds_ul = [0.0 1.0]'
bounds_ll = [-1 -1; 1 1.0]
res = optimize(F, f, bounds_ul, bounds_ll, SMS_MOBO())
source
Base.minimumFunction
minimum(f, itr; [init])

Returns the smallest result of calling function f on each element of itr.

The value returned for empty itr can be specified by init. It must be a neutral element for min (i.e. which is greater than or equal to any other element) as it is unspecified whether init is used for non-empty collections.

Julia 1.6

Keyword argument init requires Julia 1.6 or later.

Examples

julia> minimum(length, ["Julion", "Julia", "Jule"])
4

julia> minimum(length, []; init=typemax(Int64))
9223372036854775807

julia> minimum(sin, Real[]; init=1.0)  # good, since output of sin is <= 1
1.0
source
minimum(itr; [init])

Returns the smallest element in a collection.

The value returned for empty itr can be specified by init. It must be a neutral element for min (i.e. which is greater than or equal to any other element) as it is unspecified whether init is used for non-empty collections.

Julia 1.6

Keyword argument init requires Julia 1.6 or later.

Examples

julia> minimum(-20.5:10)
-20.5

julia> minimum([1,2,3])
1

julia> minimum([])
ERROR: ArgumentError: reducing over an empty collection is not allowed
Stacktrace:
[...]

julia> minimum([]; init=Inf)
Inf
source
minimum(A::AbstractArray; dims)

Compute the minimum value of an array over the given dimensions. See also the min(a,b) function to take the minimum of two or more arguments, which can be applied elementwise to arrays via min.(a,b).

See also: minimum!, extrema, findmin, argmin.

Examples

julia> A = [1 2; 3 4]
2×2 Matrix{Int64}:
 1  2
 3  4

julia> minimum(A, dims=1)
1×2 Matrix{Int64}:
 1  2

julia> minimum(A, dims=2)
2×1 Matrix{Int64}:
 1
 3
source
minimum(f, A::AbstractArray; dims)

Compute the minimum value by calling the function f on each element of an array over the given dimensions.

Examples

julia> A = [1 2; 3 4]
2×2 Matrix{Int64}:
 1  2
 3  4

julia> minimum(abs2, A, dims=1)
1×2 Matrix{Int64}:
 1  4

julia> minimum(abs2, A, dims=2)
2×1 Matrix{Int64}:
 1
 9
source
minimum(state::Metaheuristics.State)

Returns the approximation to the minimum (min f(x)) stored in state.

minimum(status::BLState) -> (Fval, fval)

Return the upper- and lower-level objective values of the best solution found.

source

Solution accessors

Missing docstring.

Missing docstring for leader_pos. Check Documenter's build log for details.

Missing docstring.

Missing docstring for follower_pos. Check Documenter's build log for details.

Missing docstring.

Missing docstring for leader_f. Check Documenter's build log for details.

Missing docstring.

Missing docstring for follower_f. Check Documenter's build log for details.

Population accessors

BilevelHeuristics.ulpositionsFunction
ulpositions(population)

Extract the upper-level decision vectors from every solution in population. Returns an N × D_ul matrix.

source
BilevelHeuristics.llpositionsFunction
llpositions(population)

Extract the lower-level decision vectors from every solution in population. Returns an N × D_ll matrix.

source
BilevelHeuristics.ulfvalsFunction
ulfvals(pop)

Extract all upper-level objective values from population. Returns a vector of length N (single-objective) or an N × M matrix (multi-objective).

source
BilevelHeuristics.llfvalsFunction
llfvals(pop)

Extract all lower-level objective values from population. Returns a vector of length N (single-objective) or an N × M matrix (multi-objective).

source
BilevelHeuristics.ulgvalsFunction
ulgvals(pop)

Extract upper-level inequality constraint values G(x, y) for each solution in population. Returns an N × n_ineq matrix.

source
BilevelHeuristics.llgvalsFunction
llgvals(pop)

Extract lower-level inequality constraint values g(x, y) for each solution in population. Returns an N × n_ineq matrix.

source
BilevelHeuristics.ulhvalsFunction
ulhvals(pop)

Extract upper-level equality constraint values H(x, y) for each solution in population. Returns an N × n_eq matrix.

source
BilevelHeuristics.llhvalsFunction
llhvals(pop)

Extract lower-level equality constraint values h(x, y) for each solution in population. Returns an N × n_eq matrix.

source

Validation

BilevelHeuristics.is_pseudo_feasibleFunction
is_pseudo_feasible(A, B, δ1, δ2, ε1, ε2)

Check whether A is a pseudo-feasible solution with respect to B.

A solution (x_A, y_A) is pseudo-feasible relative to (x_B, y_B) when:

  • The upper-level objectives are close: |F(A) - F(B)| < ε1.
  • The lower-level objectives are close: |f(A) - f(B)| < ε2.
  • The upper-level positions are close: |x_A - x_B| < δ1.
  • The lower-level positions are distant: |y_A - y_B| > δ2.

This indicates that the two solutions have similar objective values at both levels but different lower-level responses — a sign of multi-modality at the lower level. Such solutions can mislead the search, and algorithms like QBCA2 explicitly avoid them.

source