BlockDecomposition.AbstractCustomConstrDataType
AbstractCustomConstrData

Every custom data associated to a non-robust constraint should inherit from AbstractCustomConstrData.

This data is used to determine the coefficient of the columns in non-robust constraints.

BlockDecomposition.AbstractCustomVarDataType
AbstractCustomVarData

Every custom data associated to a solution passed in PricingSolution should inherit from AbstractCustomVarData.

This data is used to

  • Determine the coefficient of the corresponding column in non-robust constraints
  • Store the information about pricing solution not expressed with subproblem variables (and thus not used in the master formulation); this information can then be retrieved using [customdata(info)]@ref by the user.
  • determine the branching priority of the corresponding column (if [branchingpriority(::AbstractCustomVarData)] is defined for the concrete type).
BlockDecomposition.AutoDwStrategyType

The following scores rank bordered block-diagonal structures according to their suitability to a Dantzig-Wolfe reformulation.

white_score: Prefer structures with a low relative border area and many blocks.

blockborderscore: Both the quality of the border area and of the block-diagonal are taken into account. Desired characteristics of the block-diagonal are granularity, homogeneity and isomorphism. Score is taken from https://doi.org/10.1287/ijoc.2017.0797.

relativeborderarea_score: Prefer structures with a low relative border area. Score is taken from https://doi.org/10.1007/s10107-014-0761-5.

inactive: Automatic Dantzig-Wolfe decomposition is not used.

BlockDecomposition.DecompositionNotOverAxisType
DecompositionNotOverAxis{T}

Decomposition must be done over an axis. Getting started guide available at https://atoptima.github.io/Coluna.jl/stable/start/start/

The container on which you try to decompose is of type T and available at error.container.

BlockDecomposition.MasterVarInDwSpType

Error thrown when a master variable is in a constraint that belongs to a Dantzig-Wolfe subproblem.

You can retrieve the JuMP variable and the JuMP constraint where the error occurs:

error.variable
error.constraint
BlockDecomposition.NotRepresentativeOfDwSpType

Error thrown when a variable representative of a set of subproblems is involved in a constraint that belongs to a subproblem which is to in the set.

For example, consider a variable x representative of subproblems A and B. Assume that a constraint of subproblem C involves variable x. BlockDecomposition with throw NotRepresentativeOfDwSp error.

BlockDecomposition.PricingDualBoundType
PricingDualBound(cbdata)

Dual bound of the pricing subproblem. This bound is used to compute the contribution of the subproblem to the dual bound in column generation.

BlockDecomposition.PricingSolutionType
PricingSolution(cbdata)

Solution to a subproblem. The user submits the solution as variables, values where values[i] gives the value of variables[i].

BlockDecomposition.RepresentativeAlreadyInDwSpType

Error when you try to define a subproblem variable (i.e. that has an AxisId in its indices) as a representative of many subproblems.

julia A = @axis(K, [1,2,3]) @variable(model, x[k in K, e in E]) # cannot be a representative because K is an axis. @variable(model, y[e in E]) # can be a representative because no axis in its indices.`

BlockDecomposition.VarInDwSpCheckType

Checks:

  • master variable in dantzig-wolfe subproblem
  • dantzig-wolfe variable not in good subproblem
  • representative variable not in good subproblem
BlockDecomposition.VarsOfSameDwSpInMasterType

Warning when a master constraint involves variables that belong to the same Dantzig-Wolfe subproblem. It means you can move the constraint in a subproblem.

BlockDecomposition.BlockModelMethod
BlockModel(optimizer [, direct_model = false])

Return a JuMP model which BlockDecomposition will decompose using instructions given by the user.

If you define direct_model = true, the method creates the model with JuMP.direct_model, otherwise it uses JuMP.Model.

BlockDecomposition.annotationMethod
annotation(node)

Return the annotation that describes the master/subproblem of a given node of the decomposition tree.

annotation(model, variable)
annotation(model, constraint)

Return the subproblem to which a variable or a constraint belongs.

BlockDecomposition.branchingpriority!Method
branchingpriority!(x, value::Float64)

Set the branching priority of variable x to value.

You can use fractional branching priorities. The idea is to have both "soft" and "hard" branching priorities. For instance :

  • if the number of branching candidates with priority 4.0 is less than the maximum number of candidates considered, no branching candidates with priority 3.0 will be considered
  • if the number of branching candidates with priority 3.5 is less than the maximum number of candidates considered, then some branching candidates with priority 3.0 will be considered (to bring the total number to the maximum)
  • if the number of branching candidates with priority 3.5 is not less than the maximum number, then no branching candidates with priority 3.0 will be considered

Branching priority is also used in rounding and diving heuristics to determine which variables should be fixed first.

BlockDecomposition.branchingpriorityMethod
branchingpriority(<:AbstractCustomVarData)

This function should be redefined for a concrete type which inherits from AbstractCustomVarData if a custom branching priority is defined for columns associated with this data type. If this function is not redefined, the branching priority of each column equals to the branching priority of the pricing problem which generated it.

BlockDecomposition.customconstrs!Method
customconstrs!(model, customconstr::Type{AbstractCustomConstrData})
customconstrs!(model, customconstrs::Vector{Type{AbstractCustomConstrData}})

Set the possible custom data types of constraints in a model.

BlockDecomposition.customdata!Method
customdata!(var, custom_data)
customdata!(constr, custom_data)

Attach a custom data to a variable or a constraint.

BlockDecomposition.customdataMethod
customdata(var)
customdata(constr)

Returns the custom data attached to a variable or a constraint; nothing if no custom data.

BlockDecomposition.customvars!Method
customvars!(model, customvar::Type{<:AbstractCustomVarData})
customvars!(model, customvars::Vector{Type{<:AbstractCustomVarData}})

Set the possible custom data types of variables in a model.

BlockDecomposition.getmasterMethod
getmaster(node) -> MasterForm

Return an object that wraps the annotation that describes the master formulation of a decomposition stored at the node of the decomposition tree.

This method is not defined if the node is a leaf of the decomposition tree.

BlockDecomposition.getsubproblemsMethod
getsubproblems(node) -> Vector{SubproblemForm}

Return a vector of objects that wrap the annotations that describe subproblem formulations of a decomposition stored at node of the decomposition tree.

This method is not defined if the node is a leaf of the decomposition tree.

BlockDecomposition.objectivedualbound!Method
objectivedualbound!(model, db)

Define a dual bound on the optimal objective value. (lower bound for a minimisation, upper bound for a maximisation)

BlockDecomposition.objectiveprimalbound!Method
objectiveprimalbound!(model, pb)

Define a primal bound on the optimal objective value (upper bound for a minimisation, lower bound for a maximisation).

BlockDecomposition.register_decompositionMethod
register_decomposition(model)

Assign to each variable and constraint an annotation indicating in which partition (master/subproblem) of the original formulation the variable or the constraint is located.

This method is called by the JuMP.optimize! hook.

BlockDecomposition.specify!Method
specify!(
    subproblem, 
    lower_multiplicity = 1,
    upper_multiplicity = 1,
    solver = nothing,
    branching_priority = 1
)

Method that allows the user to specify additional property of the subproblems.

The multiplicity of subproblem is the number of times that the same independent block shaped by the subproblem in the coefficient matrix appears in the model. It is equivalent to the number of solutions to the subproblem that can appear in the solution of the original problem.

Branching priority of a subproblem is equal to the branching priority of the associated integer variable (the number of columns from this subproblem in the global solution). It also determines the default branching priority of columns generated by this subproblem. Branching priority is also used in rounding and diving heuristics to prioritize which variables and columns to fix the first.

The solver of the subproblem is the way the subproblem will be optimized. It can be either a function (pricing callback), an optimizer of MathOptInterface (e.g. Gurobi.Optimizer, CPLEX.Optimizer, Glpk.Optimizer... with attributes), or nothing. In the latter case, the solver will use a default optimizer that should be defined in the parameters of the main solver.

Advanced usage : The user can use several solvers to optimize a subproblem :

specify!(subproblem, solver = [Gurobi.Optimizer, my_callback, my_second_callback])

Coluna always uses the first solver by default. Be cautious because changes are always buffered to all solvers. So you may degrade performances if you use a lot of solvers.

BlockDecomposition.valueMethod
value(info, x)

Return the coefficient of original variable x in the column associated to info.

BlockDecomposition.@axisMacro
@axis(name, collection)

Declare collection as an index-set of subproblems. You can access the axis using the variable name.

Examples

Consider a formulation that has a decomposition which gives raise to 5 subproblems. Let {1,2,3,4,5} be the index-set of the subproblems.

To perform this decomposition with BlockDecomposition, we must declare an axis that contains the index-set of the subproblems :

julia> L = 1:5
1:5

julia> @axis(K, L)
BlockDecomposition.Axis{:K, Int64}(:K, BlockDecomposition.AxisId{:K, Int64}[1, 2, 3, 4, 5])

julia> K[1]
1

julia> typeof(K[1])
BlockDecomposition.AxisId{:K, Int64}

The elements of the axis are AxisId. You must use AxisId in the indices of the variables and the constraints that you declare otherwise BlockDecomposition assign them to the master problem.

@variable(model, x[l in L]) # x[l] belongs to the master for any l ∈ L
@variable(model, y[k in K]) # y[k], k ∈ K, belongs to subproblem k (because K is an axis)
BlockDecomposition.@benders_decompositionMacro
@benders_decomposition(model, name, axis)

Register a Benders decomposition on the JuMP model model where the index-set of the subproblems is defined by the axis axis.

Create a variable name from which the user can access decomposition tree.

BlockDecomposition.@dantzig_wolfe_decompositionMacro
@dantzig_wolfe_decomposition(model, name, axis)

Register a Dantzig-Wolfe decomposition on the JuMP model model where the index-set of the subproblems is defined by the axis axis.

Create a variable name from which the user can access the decomposition tree.