Skip to content

Commit

Permalink
Fixing issue with post solve (#191)
Browse files Browse the repository at this point in the history
* Round candidate solutions to avoid precision errors.

* Minor change.

* Type correction in function signature.

* Tracking down the post solve issue.

* Move out of the test folder since this is only for tracking down the issue,

* Sanity check regarding the integral variables.

* Clean up new solutions.

* Add output description of the solve function.

* Some explanation and pushed up to user level.

* New flags also for the other solves.

* Push the new flags down to the original solve function.

* Incumbent update is decided in add_solution, nowhere else.

* Change default values for clean solution process.

* BCG produces non integer vertices (#194)

BCG returns non integer vertices in FrankWolfe callback due to simplex descent steps.

* Integer check only in debug mode.

* Delete debugging files.

* Update project.toml.

* Simply round the vertices at the integer entries. No extra post solve required.

* Remove show statement.

---------

Co-authored-by: Deborah Hendrych <[email protected]>
Co-authored-by: Hendrych <[email protected]>
  • Loading branch information
3 people authored Sep 5, 2024
1 parent af3b41c commit 4adbee4
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 38 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Boscia"
uuid = "36b166db-dac5-4d05-b36a-e6c4cef071c9"
authors = ["ZIB IOL"]
version = "0.1.25"
version = "0.1.26"

[deps]
Bonobo = "f7b14807-3d4d-461a-888a-05dd4bca8bc3"
Expand Down
4 changes: 4 additions & 0 deletions src/MOI_bounded_oracle.jl
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,8 @@ function solve(
use_shadow_set=true,
custom_heuristics=[Heuristic()],
rounding_prob=1.0,
clean_solutions=false,
max_clean_iter=10,
kwargs...,
)
blmo = convert(MathOptBLMO, lmo)
Expand Down Expand Up @@ -670,6 +672,8 @@ function solve(
use_shadow_set=use_shadow_set,
custom_heuristics=custom_heuristics,
rounding_prob=rounding_prob,
clean_solutions=clean_solutions,
max_clean_iter=max_clean_iter,
kwargs...,
)
end
26 changes: 8 additions & 18 deletions src/callbacks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ function build_FW_callback(
@info "$(state.v)"
check_infeasible_vertex(tree.root.problem.tlmo.blmo, tree)
@assert is_linear_feasible(tree.root.problem.tlmo, state.v)
end
end
if state.tt != FrankWolfe.simplex_descent && !is_integer_feasible(tree, state.v)
@info "Vertex not integer feasible! Here are the integer variables: $(state.v[tree.root.problem.integer_variables])"
@assert is_integer_feasible(tree, state.v)
end
end
push!(fw_iterations, state.t)

Expand All @@ -34,15 +38,8 @@ function build_FW_callback(
tree.root.options[:domain_oracle],
)
if best_val < tree.incumbent
tree.root.updated_incumbent[] = true
node = tree.nodes[tree.root.current_node_id[]]
sol = FrankWolfeSolution(best_val, best_v, node, :Solver)
push!(tree.solutions, sol)
if tree.incumbent_solution === nothing ||
sol.objective < tree.incumbent_solution.objective
tree.incumbent_solution = sol
end
tree.incumbent = best_val
add_new_solution!(tree, node, best_val, best_v, :Solver)
Bonobo.bound!(tree, node.id)
end
end
Expand All @@ -54,19 +51,12 @@ function build_FW_callback(
return false
end

if tree.root.options[:domain_oracle](state.v)
if tree.root.options[:domain_oracle](state.v) && state.tt != FrankWolfe.simplex_descent
val = tree.root.problem.f(state.v)
if val < tree.incumbent
tree.root.updated_incumbent[] = true
#TODO: update solution without adding node
node = tree.nodes[tree.root.current_node_id[]]
sol = FrankWolfeSolution(val, copy(state.v), node, :vertex)
push!(tree.solutions, sol)
if tree.incumbent_solution === nothing ||
sol.objective < tree.incumbent_solution.objective
tree.incumbent_solution = sol
end
tree.incumbent = val
add_new_solution!(tree, node, val, copy(state.v), :vertex)
Bonobo.bound!(tree, node.id)
end
end
Expand Down
21 changes: 17 additions & 4 deletions src/custom_bonobo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ function Bonobo.optimize!(
tree::Bonobo.BnBTree{<:FrankWolfeNode};
callback=(args...; kwargs...) -> (),
)
#println("OWN OPTIMIZE")
while !Bonobo.terminated(tree)
node = Bonobo.get_next_node(tree, tree.options.traverse_strategy)
lb, ub = Bonobo.evaluate_node!(tree, node)
Expand Down Expand Up @@ -84,8 +83,6 @@ function Bonobo.update_best_solution!(
)
isinf(node.ub) && return false
node.ub >= tree.incumbent && return false
tree.root.updated_incumbent[] = true
tree.incumbent = node.ub

Bonobo.add_new_solution!(tree, node)
return true
Expand All @@ -95,10 +92,25 @@ function Bonobo.add_new_solution!(
tree::Bonobo.BnBTree{N,R,V,S},
node::Bonobo.AbstractNode,
) where {N,R,V,S<:FrankWolfeSolution{N,V}}
sol = FrankWolfeSolution(node.ub, Bonobo.get_relaxed_values(tree, node), node, :iterate)
add_new_solution!(tree, node, node.ub, Bonobo.get_relaxed_values(tree, node), :iterate)
end

function add_new_solution!(
tree::Bonobo.BnBTree{N,R,V,S},
node::Bonobo.AbstractNode,
objective::T,
solution::V,
origin::Symbol,
) where {N,R,V,S<:FrankWolfeSolution{N,V},T<:Real}
sol = FrankWolfeSolution(objective, solution, node, origin)
sol.solution = solution
sol.objective = objective

push!(tree.solutions, sol)
if tree.incumbent_solution === nothing || sol.objective < tree.incumbent_solution.objective
tree.root.updated_incumbent[] = true
tree.incumbent_solution = sol
tree.incumbent = sol.objective
end
end

Expand All @@ -115,3 +127,4 @@ function Bonobo.get_solution(
end
return tree.solutions[result].solution
end

9 changes: 1 addition & 8 deletions src/heuristics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,8 @@ end
Add a new solution found from the heuristic to the tree.
"""
function add_heuristic_solution(tree, x, val, heuristic_name::Symbol)
tree.root.updated_incumbent[] = true
node = tree.nodes[tree.root.current_node_id[]]
sol = FrankWolfeSolution(val, x, node, heuristic_name)
push!(tree.solutions, sol)
if tree.incumbent_solution === nothing ||
sol.objective < tree.incumbent_solution.objective
tree.incumbent_solution = sol
end
tree.incumbent = val
add_new_solution!(tree, node, val, x, heuristic_name)
Bonobo.bound!(tree, node.id)
end

Expand Down
21 changes: 14 additions & 7 deletions src/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,15 @@ use_shadow_set - The shadow set is the set of discarded vertices which i
performance might improve by disabling this option.
custom_heuristics - List of custom heuristic from the user.
prob_rounding - The probability for calling the rounding heuristics. Since the feasibility has to be checked, it might
expensive to do this for every node.
expensive to do this for every node.
clean_solutions - Flag deciding whether new solutions should be polished. They will be rounded and then a quick Frank-Wolfe run will be started.
max_clean_iter - Maximum number of iteration in the Frank-Wolfe call for polishing new solutions.
Returns
- x - the solution.
- tlmo - the blmo wrapped in a TimeTrackingLMO instance.
- result - dictionary containg the statistics and information for plotting progress plots.
"""
function solve(
f,
Expand Down Expand Up @@ -89,6 +97,8 @@ function solve(
use_shadow_set=true,
custom_heuristics=[Heuristic()],
rounding_prob=1.0,
clean_solutions=false,
max_clean_iter=10,
kwargs...,
)
if verbose
Expand Down Expand Up @@ -202,6 +212,8 @@ function solve(
:use_shadow_set => use_shadow_set,
:heuristics => heuristics,
:heu_ncalls => 0,
:max_clean_iter => max_clean_iter,
:clean_solutions => clean_solutions,
),
),
branch_strategy=branching_strategy,
Expand Down Expand Up @@ -234,12 +246,7 @@ function solve(
@assert is_linear_feasible(blmo, start_solution) &&
is_integer_feasible(tree, start_solution)
node = tree.nodes[1]
sol = FrankWolfeSolution(f(start_solution), start_solution, node, :start)
push!(tree.solutions, sol)
if tree.incumbent_solution === nothing || sol.objective < tree.incumbent_solution.objective
tree.incumbent_solution = sol
tree.incumbent = sol.objective
end
add_new_solution!(tree, node, f(start_solution), start_solution, :start)
end

# build callbacks
Expand Down
4 changes: 4 additions & 0 deletions src/managed_blmo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ function solve(
use_shadow_set=true,
custom_heuristics=[Heuristic()],
rounding_prob=1.0,
clean_solutions=false,
max_clean_iter=10,
kwargs...,
)
blmo = ManagedBoundedLMO(sblmo, lower_bounds, upper_bounds, int_vars, n)
Expand Down Expand Up @@ -312,6 +314,8 @@ function solve(
use_shadow_set=use_shadow_set,
custom_heuristics=custom_heuristics,
rounding_prob=rounding_prob,
clean_solutions=clean_solutions,
max_clean_iter=max_clean_iter,
kwargs...,
)
end

2 comments on commit 4adbee4

@dhendryc
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register()

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/114937

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.1.26 -m "<description of version>" 4adbee49fb078867ead1d4acda9ba9d184302fe0
git push origin v0.1.26

Please sign in to comment.