Skip to content

Commit

Permalink
Merge pull request #49 from harshangrjn/heuristics
Browse files Browse the repository at this point in the history
Heuristics for LaplacianOpt
  • Loading branch information
harshangrjn authored Aug 22, 2023
2 parents 22e31bf + 0765b23 commit c845933
Show file tree
Hide file tree
Showing 16 changed files with 1,430 additions and 134 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
LaplacianOpt.jl Change Log
=========================

### v0.6.0
- Added mutiple heuristics to handle both spanning trees and graphs with loops
- Refactored `log.jl` to handle solutions from heuristics
- Included more user options for heuristic in `model_options`
- Cleaned up populating and logging of eigen cuts
- Updated docs and unit tests to reflect above changes

### v0.5.0
- Generalized eigen cuts to handle any size of non-negative minors (`2x2`-`NxN`)
- Dropped support for `constraint_eigen_cuts_on_2minors` and `constraint_eigen_cuts_on_3minors`
Expand Down
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "LaplacianOpt"
uuid = "bb20392f-64fb-4001-92e8-14b3aedd5a9e"
authors = ["Harsha Nagarajan"]
version = "0.5.0"
version = "0.6.0"

[deps]
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Expand All @@ -11,9 +11,9 @@ JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
Memento = "f28f55f0-a522-5efc-85c2-fe41dfb9b2d9"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
TikzGraphs = "b4f28e30-c73f-5eaf-a395-8a9db949a742"
TikzPictures = "37f6aa50-8035-52d0-81c2-5a1d08754b2d"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[compat]
DataStructures = "~0.17, ~0.18"
Expand Down
3 changes: 3 additions & 0 deletions docs/src/quickguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ results = LOpt.run_LOpt(params, lopt_optimizer)
!!! tip
Run times of [LaplacianOpt](https://github.com/harshangrjn/LaplacianOpt.jl)'s mathematical optimization models are significantly faster using [Gurobi](https://www.gurobi.com) as the underlying mixed-integer programming (MIP) solver. Note that this solver's individual-usage license is available [free](https://www.gurobi.com/academia/academic-program-and-licenses/) for academic purposes.

!!! tip
Note that [LaplacianOpt](https://github.com/harshangrjn/LaplacianOpt.jl) tries to find the global solution of a combinatiorial optimization problem, that is known to be [NP-hard to compute](https://doi.org/10.1016/j.orl.2008.09.001) in the size of `num_nodes`. To obtain quick feasible solutions via "k-opt-based" heristics, just set `:solution_type` to `"heuristics"` and adjust the `num_swaps_bound_kopt` parameter to appropriate values, where larger value implies a better-quality feasible solution at the cost of the heuristic run time.

# Extracting results
The run commands (for example, `run_LOpt`) in LaplacianOpt return detailed results in the form of a dictionary. This dictionary can be used for further processing of the results. For example, for the given instance of a complete graph, the algorithm's runtime and the optimal objective value (maximum algebraic connectivity) can be accessed with,

Expand Down
4 changes: 4 additions & 0 deletions examples/instances/5_nodes/5_11.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{"edges_to_augment":[[[1,5],5.1749106],[[2,3],6.1501476],[[2,4],13.66149798]],
"num_nodes":5,
"edges_existing":[[[1,2],34.99664955],[[1,3],3.86014785],[[1,4],11.2685551],[[2,5],21.90200648],[[3,4],29.11616571],[[3,5],27.74393888],[[4,5],2.83029978]]
}
9 changes: 0 additions & 9 deletions examples/plots/plot_5.dot

This file was deleted.

52 changes: 0 additions & 52 deletions examples/plots/plot_5.tex

This file was deleted.

14 changes: 7 additions & 7 deletions examples/run_examples.jl
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import LaplacianOpt as LOpt
using JuMP
using CPLEX
# using Gurobi
# using GLPK

include("optimizer.jl")

#----------------------------------#
# MIP solver #
# (Cplex 22.1 performs the best) #
#----------------------------------#
#-----------------------------------#
# MIP solver #
# (> Cplex 22.1 performs the best) #
#-----------------------------------#
lopt_optimizer = get_cplex()

#-------------------------------------#
Expand Down Expand Up @@ -47,6 +46,7 @@ end
num_nodes = 8
instance = 1
data_dict, augment_budget = data_I(num_nodes, instance)
# data_dict, augment_budget = data_II()

params = Dict{String,Any}("data_dict" => data_dict, "augment_budget" => augment_budget)

Expand All @@ -57,7 +57,7 @@ params = Dict{String,Any}("data_dict" => data_dict, "augment_budget" => augment_

# For more model options, check https://github.com/harshangrjn/LaplacianOpt.jl/blob/master/src/types.jl
model_options = Dict{Symbol,Any}(
:eigen_cuts_sizes => [2, num_nodes],
:eigen_cuts_sizes => [data_dict["num_nodes"], 2],
:topology_flow_cuts => true,
:solution_type => "optimal",
)
Expand All @@ -67,5 +67,5 @@ result = LOpt.run_LOpt(
lopt_optimizer;
options = model_options,
visualize_solution = false, # Make it true to plot the graph solution
visualizing_tool = "tikz", # "graphviz" is another option
visualizing_tool = "tikz", # "tikz", "graphviz" are the options
)
9 changes: 4 additions & 5 deletions src/constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ function constraint_lazycallback_wrapper(lom::LaplacianOptModel; optimizer = not
"Callback status: unknown - solution may not be integer feasible",
)

elseif status in
[MOI.CALLBACK_NODE_STATUS_INTEGER, MOI.CALLBACK_NODE_STATUS_FRACTIONAL]
elseif status in [MOI.CALLBACK_NODE_STATUS_INTEGER]
# [MOI.CALLBACK_NODE_STATUS_INTEGER, MOI.CALLBACK_NODE_STATUS_FRACTIONAL]
if !(lom.options.formulation_type == "max_span_tree")
if (
size(lom.options.eigen_cuts_sizes)[1] > 0 &&
Expand Down Expand Up @@ -133,9 +133,8 @@ function constraint_lazycallback_wrapper(lom::LaplacianOptModel; optimizer = not
end

function constraint_eigen_cuts(W_val::Matrix{<:Number}, cb_cuts, lom::LaplacianOptModel)
if (size(lom.options.eigen_cuts_sizes)[1] > 0) &&
(minimum(lom.options.eigen_cuts_sizes) >= 2)
for cut_size in sort(unique(lom.options.eigen_cuts_sizes), rev = true)
if (length(keys(lom.minor_idx_dict)) > 0)
for cut_size in sort(collect(keys(lom.minor_idx_dict)), rev = true)
for i in lom.minor_idx_dict[cut_size]
LOpt._add_eigen_cut_lazy(W_val, cb_cuts, lom, collect(i))
end
Expand Down
Loading

0 comments on commit c845933

Please sign in to comment.