Skip to content

Commit

Permalink
allow setting initial gamma
Browse files Browse the repository at this point in the history
  • Loading branch information
GiggleLiu committed Jan 19, 2025
1 parent 8549665 commit 943c81e
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 27 deletions.
8 changes: 4 additions & 4 deletions lib/OptimalBranchingCore/src/branch.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ A [`OptimalBranchingResult`](@ref) object representing the optimal branching rul
function optimal_branching_rule(table::BranchingTable, variables::Vector, problem::AbstractProblem, m::AbstractMeasure, solver::AbstractSetCoverSolver)
candidates = candidate_clauses(table)
size_reductions = [size_reduction(problem, m, candidate, variables) for candidate in candidates]
return minimize_γ(table, candidates, size_reductions, solver; γ0 = 2.0)
return minimize_γ(table, candidates, size_reductions, solver)
end

function size_reduction(p::AbstractProblem, m::AbstractMeasure, cl::Clause{INT}, variables::Vector) where {INT}
Expand Down Expand Up @@ -72,7 +72,7 @@ function branch_and_reduce(problem::AbstractProblem, config::BranchingStrategy,
has_zero_size(problem) && return zero(result_type)
# reduce the problem
rp, reducedvalue = reduce_problem(result_type, problem, reducer)
rp !== problem && return branch_and_reduce(rp, config, reducer, result_type; tag) * reducedvalue
rp !== problem && return branch_and_reduce(rp, config, reducer, result_type; tag, show_progress) * reducedvalue

# branch the problem
variables = select_variables(rp, config.measure, config.selector) # select a subset of variables
Expand All @@ -92,9 +92,9 @@ function print_sequence(io::IO, sequence::Vector{Tuple{Int,Int}})
if i == n
print(io, "")
elseif i == 1
print(io, "")
print(io, "")
else
print(io, "")
print(io, "")
end
end
end
21 changes: 11 additions & 10 deletions lib/OptimalBranchingCore/src/setcovering.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,39 @@ abstract type AbstractSetCoverSolver end

"""
LPSolver <: AbstractSetCoverSolver
LPSolver(; optimizer = HiGHS.Optimizer, max_itr::Int = 5, verbose::Bool = false)
LPSolver(; optimizer = HiGHS.Optimizer, max_itr::Int = 20, γ0::Float64 = 2.0, verbose::Bool = false)
A linear programming solver for set covering problems.
### Fields
- `optimizer`: The optimizer to be used.
- `max_itr::Int`: The maximum number of iterations to be performed.
- `γ0::Float64`: The initial γ value.
- `verbose::Bool`: Whether to print the solver's output.
"""
Base.@kwdef struct LPSolver <: AbstractSetCoverSolver
optimizer = HiGHS.Optimizer
max_itr::Int = 5
max_itr::Int = 20
γ0::Float64 = 2.0
verbose::Bool = false
end

"""
IPSolver <: AbstractSetCoverSolver
IPSolver(; optimizer = HiGHS.Optimizer, max_itr::Int = 5, verbose::Bool = false)
IPSolver(; optimizer = HiGHS.Optimizer, max_itr::Int = 20, γ0::Float64 = 2.0, verbose::Bool = false)
An integer programming solver for set covering problems.
### Fields
- `optimizer`: The optimizer to be used.
- `max_itr::Int`: The maximum number of iterations to be performed.
- `γ0::Float64`: The initial γ value.
- `verbose::Bool`: Whether to print the solver's output.
"""
Base.@kwdef struct IPSolver <: AbstractSetCoverSolver
optimizer = HiGHS.Optimizer
max_itr::Int = 5
max_itr::Int = 20
γ0::Float64 = 2.0
verbose::Bool = false
end

Expand Down Expand Up @@ -127,23 +131,20 @@ It utilizes an integer programming solver to optimize the selection of sub-cover
- `Δρ::Vector`: A vector of problem size reduction for each candidate clause.
- `solver`: The solver to be used. It can be an instance of `LPSolver` or `IPSolver`.
### Keyword Arguments
- `γ0::Float64`: The initial γ value.
### Returns
A tuple of two elements: (indices of selected subsets, γ)
"""
function minimize_γ(table::BranchingTable, candidates::Vector{Clause{INT}}, Δρ::Vector, solver::AbstractSetCoverSolver; γ0::Float64 = 2.0) where {INT}
function minimize_γ(table::BranchingTable, candidates::Vector{Clause{INT}}, Δρ::Vector, solver::AbstractSetCoverSolver) where {INT}
subsets = [covered_items(table.table, c) for c in candidates]
@debug "solver = $(solver), subsets = $(subsets), γ0 = $γ0, Δρ = $(Δρ)"
@debug "solver = $(solver), subsets = $(subsets), γ0 = $(solver.γ0), Δρ = $(Δρ)"
num_items = length(table.table)

# Note: the following instance is captured for time saving, and also for it may cause IP solver to fail
for (k, subset) in enumerate(subsets)
(length(subset) == num_items) && return OptimalBranchingResult(DNF([candidates[k]]), [Δρ[k]], 1.0)
end

cx_old = cx = γ0
cx_old = cx = solver.γ0
local picked_scs
for i = 1:solver.max_itr
weights = 1 ./ cx_old .^ Δρ
Expand Down
25 changes: 18 additions & 7 deletions lib/OptimalBranchingCore/test/mockproblem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,31 @@ end
n = 100
nsample = 3
p = MockProblem(rand(Bool, n))
config = BranchingStrategy(table_solver=MockTableSolver(nsample), measure=NumOfVariables(), selector=RandomSelector(16))
config = BranchingStrategy(table_solver=MockTableSolver(nsample), measure=NumOfVariables(), selector=RandomSelector(16), set_cover_solver=NaiveBranch())
res0 = branch_and_reduce(p, config, NoReducer(), MaxSizeBranchCount; show_progress=false)
@test res0.size == 100

config = BranchingStrategy(table_solver=MockTableSolver(nsample), measure=NumOfVariables(), selector=RandomSelector(16), set_cover_solver=IPSolver())
@test branch_and_reduce(p, config, NoReducer(), MaxSize).size == 100
res1 = branch_and_reduce(p, config, NoReducer(), MaxSizeBranchCount; show_progress=true)
@test res1.size == 100
@test res1.count < res0.count

config = BranchingStrategy(table_solver=MockTableSolver(nsample), measure=NumOfVariables(), selector=RandomSelector(16), set_cover_solver=NaiveBranch())
res2 = branch_and_reduce(p, config, NoReducer(), MaxSizeBranchCount; show_progress=true)
config = BranchingStrategy(table_solver=MockTableSolver(nsample), measure=NumOfVariables(), selector=RandomSelector(16), set_cover_solver=LPSolver())
res2 = branch_and_reduce(p, config, NoReducer(), MaxSizeBranchCount; show_progress=false)
@test res2.size == 100
@test res1.count < res2.count
@test res2.count < res0.count

config = BranchingStrategy(table_solver=MockTableSolver(nsample), measure=NumOfVariables(), selector=RandomSelector(16), set_cover_solver=GreedyMerge())
res3 = branch_and_reduce(p, config, NoReducer(), MaxSizeBranchCount; show_progress=true)
res3 = branch_and_reduce(p, config, NoReducer(), MaxSizeBranchCount; show_progress=false)
@test res3.size == 100
@test res2.count > res3.count
@test res3.count < res0.count

# gamma informed, let γ0 be 1.05
config = BranchingStrategy(table_solver=MockTableSolver(nsample), measure=NumOfVariables(), selector=RandomSelector(16), set_cover_solver=IPSolver(max_itr=1, γ0=1.05))
res4 = branch_and_reduce(p, config, NoReducer(), MaxSizeBranchCount; show_progress=false)
@test res4.size == 100
@test res4.count < res0.count

@show res1.count, res2.count, res3.count
@show res0.count, res1.count, res2.count, res3.count, res4.count
end
18 changes: 12 additions & 6 deletions lib/OptimalBranchingMIS/src/interfaces.jl
Original file line number Diff line number Diff line change
@@ -1,37 +1,43 @@
"""
mis_size(g::AbstractGraph; branching_strategy::BranchingStrategy = BranchingStrategy(table_solver = TensorNetworkSolver(), selector = MinBoundaryHighDegreeSelector(2, 6, 0), measure=D3Measure()), reducer::AbstractReducer = MISReducer())
mis_size(g::AbstractGraph; branching_strategy::BranchingStrategy = BranchingStrategy(table_solver = TensorNetworkSolver(), selector = MinBoundaryHighDegreeSelector(2, 6, 0), measure=D3Measure()), reducer::AbstractReducer = MISReducer(), show_progress::Bool = false)
Calculate the size of the Maximum Independent Set (MIS) for a given graph.
### Arguments
- `g::AbstractGraph`: The graph for which the MIS size is to be calculated.
### Keyword Arguments
- `branching_strategy::BranchingStrategy`: (optional) The branching strategy to be used. Defaults to a strategy using `table_solver=TensorNetworkSolver`, `selector=MinBoundaryHighDegreeSelector(2, 6, 0)`, and `measure=D3Measure`.
- `reducer::AbstractReducer`: (optional) The reducer to be applied. Defaults to `MISReducer`.
- `show_progress::Bool`: (optional) Whether to show the progress of the branching and reduction process. Defaults to `false`.
### Returns
- An integer representing the size of the Maximum Independent Set for the given graph.
"""
function mis_size(g::AbstractGraph; branching_strategy::BranchingStrategy = BranchingStrategy(table_solver = TensorNetworkSolver(), selector = MinBoundaryHighDegreeSelector(2, 6, 0), measure = D3Measure()), reducer = MISReducer())
function mis_size(g::AbstractGraph; branching_strategy::BranchingStrategy = BranchingStrategy(table_solver = TensorNetworkSolver(), selector = MinBoundaryHighDegreeSelector(2, 6, 0), measure = D3Measure()), reducer = MISReducer(), show_progress::Bool = false)
p = MISProblem(g)
res = branch_and_reduce(p, branching_strategy, reducer, MaxSize)
res = branch_and_reduce(p, branching_strategy, reducer, MaxSize; show_progress)
return res.size
end

"""
mis_branch_count(g::AbstractGraph; branching_strategy::BranchingStrategy = BranchingStrategy(table_solver = TensorNetworkSolver(), selector = MinBoundaryHighDegreeSelector(2, 6, 0), measure=D3Measure()), reducer=MISReducer())
mis_branch_count(g::AbstractGraph; branching_strategy::BranchingStrategy = BranchingStrategy(table_solver = TensorNetworkSolver(), selector = MinBoundaryHighDegreeSelector(2, 6, 0), measure=D3Measure()), reducer=MISReducer(), show_progress::Bool = false)
Calculate the size and the number of branches of the Maximum Independent Set (MIS) for a given graph.
### Arguments
- `g::AbstractGraph`: The graph for which the MIS size and the number of branches are to be calculated.
### Keyword Arguments
- `branching_strategy::BranchingStrategy`: (optional) The branching strategy to be used. Defaults to a strategy using `table_solver=TensorNetworkSolver`, `selector=MinBoundaryHighDegreeSelector(2, 6, 0)`, and `measure=D3Measure`.
- `reducer::AbstractReducer`: (optional) The reducer to be applied. Defaults to `MISReducer`.
- `show_progress::Bool`: (optional) Whether to show the progress of the branching and reduction process. Defaults to `false`.
### Returns
- A tuple `(size, count)` where `size` is the size of the Maximum Independent Set and `count` is the number of branches.
"""
function mis_branch_count(g::AbstractGraph; branching_strategy::BranchingStrategy = BranchingStrategy(table_solver = TensorNetworkSolver(), selector = MinBoundaryHighDegreeSelector(2, 6, 0), measure = D3Measure()), reducer = MISReducer())
function mis_branch_count(g::AbstractGraph; branching_strategy::BranchingStrategy = BranchingStrategy(table_solver = TensorNetworkSolver(), selector = MinBoundaryHighDegreeSelector(2, 6, 0), measure = D3Measure()), reducer = MISReducer(), show_progress::Bool = false)
p = MISProblem(g)
res = branch_and_reduce(p, branching_strategy, reducer, MaxSizeBranchCount)
res = branch_and_reduce(p, branching_strategy, reducer, MaxSizeBranchCount; show_progress)
return (res.size, res.count)
end

0 comments on commit 943c81e

Please sign in to comment.