Skip to content

Commit

Permalink
decouple strong branching from tree search data structures (#676)
Browse files Browse the repository at this point in the history
  • Loading branch information
guimarqu authored Aug 5, 2022
1 parent 6706626 commit ad3d0b2
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 18 deletions.
8 changes: 4 additions & 4 deletions src/Algorithm/branching/branchinggroup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ mutable struct BranchingGroup
candidate::AbstractBranchingCandidate # the left-hand side in general.
local_id::Int64
lhs::Float64
children::Vector{Node}
children::Vector{SbNode}
isconquered::Bool
score::Float64
end

function BranchingGroup(
candidate::AbstractBranchingCandidate, local_id::Int64, lhs::Float64
)
return BranchingGroup(candidate, local_id, lhs, Node[], false, typemin(Float64))
return BranchingGroup(candidate, local_id, lhs, SbNode[], false, typemin(Float64))
end

get_lhs_distance_to_integer(group::BranchingGroup) =
Expand All @@ -61,9 +61,9 @@ end
# TODO : it does not look like a regeneration but more like a new vector where we
# reassign children
function regenerate_children!(group::BranchingGroup, parent::Node)
new_children = Node[]
new_children = SbNode[]
for child in group.children
push!(new_children, Node(parent, child))
push!(new_children, SbNode(parent, child))
end
group.children = new_children
return
Expand Down
4 changes: 2 additions & 2 deletions src/Algorithm/branching/varbranching.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function generate_children(
)
end
child1description = candidate.varname * ">=" * string(ceil(lhs))
child1 = Node(master, parent, child1description, store_records!(reform))
child1 = SbNode(master, parent, child1description, store_records!(reform))

# adding the second branching constraints
restore_from_records!(units_to_restore, copy_records(parent.recordids))
Expand All @@ -61,7 +61,7 @@ function generate_children(
)
end
child2description = candidate.varname * "<=" * string(floor(lhs))
child2 = Node(master, parent, child2description, store_records!(reform))
child2 = SbNode(master, parent, child2description, store_records!(reform))

return [child1, child2]
end
Expand Down
24 changes: 24 additions & 0 deletions src/Algorithm/conquer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,30 @@ function apply_conquer_alg_to_node!(
return
end

# This is only for strong branching
# returns the optimization part of the output of the conquer algorithm
function apply_conquer_alg_to_node!(
node::SbNode, algo::AbstractConquerAlgorithm, env::Env, reform::Reformulation,
units_to_restore::UnitsUsage, opt_rtol::Float64 = Coluna.DEF_OPTIMALITY_RTOL,
opt_atol::Float64 = Coluna.DEF_OPTIMALITY_ATOL
)
nodestate = getoptstate(node)
if isverbose(algo)
@logmsg LogLevel(-1) string("Node IP DB: ", get_ip_dual_bound(nodestate))
@logmsg LogLevel(-1) string("Tree IP PB: ", get_ip_primal_bound(nodestate))
end
if ip_gap_closed(nodestate, rtol = opt_rtol, atol = opt_atol)
@info "IP Gap is closed: $(ip_gap(nodestate)). Abort treatment."
else
isverbose(algo) && @logmsg LogLevel(-1) string("IP Gap is positive. Need to treat node.")

run!(algo, env, reform, ConquerInput(Node(node), units_to_restore))
store_records!(reform, node.recordids)
end
node.conquerwasrun = true
return
end

####################################################################
# ParameterisedHeuristic
####################################################################
Expand Down
2 changes: 1 addition & 1 deletion src/Algorithm/divide.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Output of a divide algorithm used by the tree search algorithm.
Should contain the vector of generated nodes.
"""
struct DivideOutput <: AbstractOutput
children::Vector{Node}
children::Vector{SbNode}
optstate::OptimizationState
end

Expand Down
71 changes: 62 additions & 9 deletions src/Algorithm/node.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,6 @@ function Node(
)
end

# this function creates a child node by copying info from another child
# used in strong branching
function Node(parent::Node, child::Node)
depth = getdepth(parent) + 1
return Node(
-1, false, depth, parent, getoptstate(child),
child.branchdescription, child.recordids, false
)
end

get_tree_order(n::Node) = n.tree_order
set_tree_order!(n::Node, tree_order::Int) = n.tree_order = tree_order
Expand All @@ -64,3 +55,65 @@ function to_be_pruned(node::Node)
getterminationstatus(nodestate) == INFEASIBLE && return true
return ip_gap_closed(nodestate)
end


### WIP
### Node for the strong branching (Goal: decouple strong branching from tree search)

mutable struct SbNode
tree_order::Int
istreated::Bool
depth::Int
parent::Union{Nothing, Node}
optstate::OptimizationState
#branch::Union{Nothing, Branch} # branch::ConstrId
branchdescription::String
recordids::RecordsVector
conquerwasrun::Bool
end

# this function creates a child node by copying info from another child
# used in strong branching
function SbNode(parent::Node, child::SbNode)
depth = getdepth(parent) + 1
return SbNode(
-1, false, depth, parent, getoptstate(child),
child.branchdescription, child.recordids, false
)
end

function SbNode(
form::AbstractFormulation, parent::Node, branchdescription::String, recordrecordids::RecordsVector
)
depth = getdepth(parent) + 1
nodestate = OptimizationState(form, getoptstate(parent), false, false)

return SbNode(
-1, false, depth, parent, nodestate, branchdescription, recordrecordids, false
)
end

function Node(node::SbNode)
return Node(node.tree_order, node.istreated, node.depth, node.parent, node.optstate, node.branchdescription, node.recordids, node.conquerwasrun)
end


get_tree_order(n::SbNode) = n.tree_order
set_tree_order!(n::SbNode, tree_order::Int) = n.tree_order = tree_order
getdepth(n::SbNode) = n.depth
getparent(n::SbNode) = n.parent
getchildren(n::SbNode) = n.children
getoptstate(n::SbNode) = n.optstate
addchild!(n::SbNode, child::SbNode) = push!(n.children, child)
settreated!(n::SbNode) = n.istreated = true
istreated(n::SbNode) = n.istreated
isrootnode(n::SbNode) = n.tree_order == 1
getinfeasible(n::SbNode) = n.infesible
setinfeasible(n::SbNode, status::Bool) = n.infeasible = status

# TODO remove
function to_be_pruned(node::SbNode)
nodestate = getoptstate(node)
getterminationstatus(nodestate) == INFEASIBLE && return true
return ip_gap_closed(nodestate)
end
2 changes: 1 addition & 1 deletion src/Algorithm/treesearch.jl
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ function run_divide_algorithm!(
end
print("", get_tree_order(child) ," ")
end
push!(tsdata, child)
push!(tsdata, Node(child))
end
!first_child_with_runconquer && println()
return
Expand Down
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ include("ColunaTests.jl")
retest(Coluna, ColunaTests)

# Run a specific test:
#retest(ColunaTests, "toy instance with objective constant")
#retest(ColunaTests, "small instance")

0 comments on commit ad3d0b2

Please sign in to comment.