Skip to content

Commit

Permalink
Option to run the presolve algorithm (#1130)
Browse files Browse the repository at this point in the history
* Option to run the presolve algorithm

* Remove unused field from BaBSearchSpace
  • Loading branch information
rrsadykov authored Feb 5, 2024
1 parent d9004b2 commit 43cd5bb
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 3 deletions.
4 changes: 4 additions & 0 deletions src/Algorithm/branchcutprice.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Coluna.Algorithm.BranchCutAndPriceAlgorithm(;
run_presolve::Bool = false,
maxnumnodes::Int = 100000,
opt_atol::Float64 = Coluna.DEF_OPTIMALITY_ATOL,
opt_rtol::Float64 = Coluna.DEF_OPTIMALITY_RTOL,
Expand All @@ -20,6 +21,7 @@ Alias for a simplified parameterisation
of the branch-cut-and-price algorithm.
Parameters :
- `run_presolve` : whether to call the presolve algorithm before running the branch-cut-and-price
- `maxnumnodes` : maximum number of nodes explored by the algorithm
- `opt_atol` : optimality absolute tolerance
- `opt_rtol` : optimality relative tolerance
Expand Down Expand Up @@ -55,6 +57,7 @@ Parameters :


function BranchCutAndPriceAlgorithm(;
run_presolve::Bool = false,
maxnumnodes::Int = 100000,
branchingtreefile::String = "",
jsonfile::String = "",
Expand Down Expand Up @@ -153,6 +156,7 @@ function BranchCutAndPriceAlgorithm(;
end

return TreeSearchAlgorithm(
presolvealg = run_presolve ? PresolveAlgorithm() : nothing,
conqueralg = conquer,
dividealg = branching,
maxnumnodes = maxnumnodes,
Expand Down
4 changes: 4 additions & 0 deletions src/Algorithm/presolve/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -312,10 +312,14 @@ struct PresolveInput
partial_sol_to_fix::Dict{VarId,Float64}
end

PresolveInput() = PresolveInput(Dict{VarId,Float64}())

struct PresolveOutput
feasible::Bool
end

isfeasible(output::PresolveOutput) = output.feasible

function presolve_formulation!(presolve_form::PresolveFormulation)
tightened_bounds = bounds_tightening(presolve_form.form)
presolve_form = propagate_in_presolve_form(presolve_form, Int[], tightened_bounds)
Expand Down
23 changes: 20 additions & 3 deletions src/Algorithm/treesearch.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""
Coluna.Algorithm.TreeSearchAlgorithm(
presolvealg = nothing,
conqueralg::AbstractConquerAlgorithm = ColCutGenConquer(),
dividealg::AbstractDivideAlgorithm = Branching(),
explorestrategy::AbstractExploreStrategy = DepthFirstStrategy(),
Expand All @@ -16,7 +17,8 @@
This algorithm is a branch and bound that uses a search tree to optimize the reformulation.
At each node in the tree, it applies `conqueralg` to evaluate the node and improve the bounds,
`dividealg` to generate branching constraints, and `explorestrategy`
to select the next node to treat.
to select the next node to treat. Optionally, the `presolvealg` is run in the beginning to
preprocess the formulation.
The three main elements of the algorithm are:
- the conquer strategy (`conqueralg`): evaluation of the problem at a node of the Branch-and-Bound tree. Depending on the type of decomposition used ahead of the Branch-and-Bound, you can use either Column Generation (if your problem is decomposed following Dantzig-Wolfe transformation) and/or Cut Generation (for Dantzig-Wolfe and Benders decompositions).
Expand All @@ -39,6 +41,7 @@ Options:
in the json file.
"""
struct TreeSearchAlgorithm <: AbstractOptimizationAlgorithm
presolvealg::Union{Nothing,PresolveAlgorithm}
conqueralg::AbstractConquerAlgorithm
dividealg::AlgoAPI.AbstractDivideAlgorithm
explorestrategy::TreeSearch.AbstractExploreStrategy
Expand All @@ -51,6 +54,7 @@ struct TreeSearchAlgorithm <: AbstractOptimizationAlgorithm
jsonfile::String
print_node_info::Bool
TreeSearchAlgorithm(;
presolvealg = nothing,
conqueralg = ColCutGenConquer(),
dividealg = ClassicBranching(),
explorestrategy = TreeSearch.DepthFirstStrategy(),
Expand All @@ -62,7 +66,7 @@ struct TreeSearchAlgorithm <: AbstractOptimizationAlgorithm
branchingtreefile = "",
jsonfile = "",
print_node_info = true
) = new(conqueralg, dividealg, explorestrategy, maxnumnodes, opennodeslimit, timelimit, opt_atol, opt_rtol, branchingtreefile, jsonfile, print_node_info)
) = new(presolvealg, conqueralg, dividealg, explorestrategy, maxnumnodes, opennodeslimit, timelimit, opt_atol, opt_rtol, branchingtreefile, jsonfile, print_node_info)
end

# TreeSearchAlgorithm is a manager algorithm (manages storing and restoring storage units)
Expand All @@ -71,10 +75,14 @@ ismanager(algo::TreeSearchAlgorithm) = true
# TreeSearchAlgorithm does not use any record itself,
# therefore get_units_usage() is not defined for it
function get_child_algorithms(algo::TreeSearchAlgorithm, reform::Reformulation)
return Dict(
child_algos = Dict(
"conquer" => (algo.conqueralg, reform),
"divide" => (algo.dividealg, reform)
)
if !isnothing(algo.presolvealg)
child_algos["presolve"] = (algo.presolvealg, reform)
end
return child_algos
end

function run!(algo::TreeSearchAlgorithm, env::Env, reform::Reformulation, input::OptimizationState)
Expand All @@ -85,6 +93,15 @@ function run!(algo::TreeSearchAlgorithm, env::Env, reform::Reformulation, input:
else
@warn "Global time limit has been set through JuMP/MOI. Ignoring the time limit of TreeSearchAlgorithm."
end

if !isnothing(algo.presolvealg)
if !isfeasible(run!(algo.presolvealg, env, reform, PresolveInput()))
output = input
setterminationstatus!(output, ColunaBase.INFEASIBLE)
return output
end
end

search_space = TreeSearch.new_space(TreeSearch.search_space_type(algo), algo, reform, input)
return TreeSearch.tree_search(algo.explorestrategy, search_space, env, input)
end
Expand Down
1 change: 1 addition & 0 deletions test/e2e/gap/generalized_assignment.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ function gap_toy_instance()
solver = ClA.BranchCutAndPriceAlgorithm(
branchingtreefile = "playgap.dot",
colgen_strict_integrality_check = true, # only for testing purposes, not really needed here
run_presolve = true
),
local_art_var_cost=10000.0,
global_art_var_cost=100000.0),
Expand Down

0 comments on commit 43cd5bb

Please sign in to comment.