Skip to content

[WIP] Add subsolver reducer #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/OptimalBranchingMIS/src/OptimalBranchingMIS.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ using SparseArrays
using KaHyPar

export MISProblem
export MISReducer, XiaoReducer, TensorNetworkReducer
export MISReducer, XiaoReducer, TensorNetworkReducer, SubsolverReducer, MatryoshkaReducer
export MinBoundarySelector, MinBoundaryHighDegreeSelector,KaHyParSelector
export TensorNetworkSolver
export NumOfVertices, D3Measure
Expand Down
51 changes: 50 additions & 1 deletion lib/OptimalBranchingMIS/src/reducer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,29 @@
└── recheck - $(reducer.recheck)
""")

"""
struct SubsolverReducer{TR, TS} <: AbstractReducer

After the size of the problem is smaller than the threshold, use a subsolver to find reduction rules.

# Fields
- `reducer::TR = XiaoReducer()`: The reducer used to reduce the graph.
- `subsolver::Symbol = :xiao`: subsolvers include `:mis2`, `:xiao` and `:ip`.
- `threshold::Int = 100`: The threshold for using the subsolver.
"""
@kwdef struct SubsolverReducer <: AbstractReducer
reducer::AbstractReducer = XiaoReducer()
subsolver::Symbol = :xiao # :mis2, :xiao or :ip
threshold::Int = 100 # the threshold for using the subsolver
end

@kwdef struct MatryoshkaReducer <: AbstractReducer
reducer::AbstractReducer
subconfig::BranchingStrategy
subreducer::Union{MatryoshkaReducer, SubsolverReducer}
threshold::Int
end

"""
reduce_problem(::Type{R}, p::MISProblem, ::MISReducer) where R

Expand All @@ -71,7 +94,7 @@
- If there are two vertices, it returns an empty instance and a count based on the presence of an edge between them.
- For graphs with more than two vertices, it calculates the degrees of the vertices and identifies the vertex with the minimum degree to determine which vertices to remove.
"""
function OptimalBranchingCore.reduce_problem(::Type{R}, p::MISProblem, reducer::Union{MISReducer, XiaoReducer, TensorNetworkReducer}) where R
function OptimalBranchingCore.reduce_problem(::Type{R}, p::MISProblem, reducer::Union{MISReducer, XiaoReducer, TensorNetworkReducer, SubsolverReducer, MatryoshkaReducer}) where R
g_new, r, _ = reduce_graph(p.g, reducer)
if (nv(g_new) == nv(p.g)) && iszero(r)
return p, R(0)
Expand Down Expand Up @@ -228,4 +251,30 @@
end
return best_cl
end
end

function reduce_graph(g::SimpleGraph{Int}, reducer::SubsolverReducer)
if nv(g) <= reducer.threshold
# use the subsolver the directly solve the problem
if reducer.subsolver == :mis2
res = mis2(EliminateGraph(g))

Check warning on line 260 in lib/OptimalBranchingMIS/src/reducer.jl

View check run for this annotation

Codecov / codecov/patch

lib/OptimalBranchingMIS/src/reducer.jl#L260

Added line #L260 was not covered by tests
elseif reducer.subsolver == :xiao
res = counting_xiao2013(g).size
elseif reducer.subsolver == :ip
res = ip_mis(g)

Check warning on line 264 in lib/OptimalBranchingMIS/src/reducer.jl

View check run for this annotation

Codecov / codecov/patch

lib/OptimalBranchingMIS/src/reducer.jl#L263-L264

Added lines #L263 - L264 were not covered by tests
else
error("Subsolver $(reducer.subsolver) not supported, please choose from :mis2, :xiao or :ip")

Check warning on line 266 in lib/OptimalBranchingMIS/src/reducer.jl

View check run for this annotation

Codecov / codecov/patch

lib/OptimalBranchingMIS/src/reducer.jl#L266

Added line #L266 was not covered by tests
end
return SimpleGraph(0), res, Int[]
else
return reduce_graph(g, reducer.reducer)

Check warning on line 270 in lib/OptimalBranchingMIS/src/reducer.jl

View check run for this annotation

Codecov / codecov/patch

lib/OptimalBranchingMIS/src/reducer.jl#L270

Added line #L270 was not covered by tests
end
end

function reduce_graph(g::SimpleGraph{Int}, reducer::MatryoshkaReducer)
if nv(g) > reducer.threshold
return reduce_graph(g, reducer.reducer)

Check warning on line 276 in lib/OptimalBranchingMIS/src/reducer.jl

View check run for this annotation

Codecov / codecov/patch

lib/OptimalBranchingMIS/src/reducer.jl#L274-L276

Added lines #L274 - L276 were not covered by tests
else
return SimpleGraph(0), mis_size(g, branching_strategy = reducer.subconfig, reducer = reducer.subreducer), Int[]

Check warning on line 278 in lib/OptimalBranchingMIS/src/reducer.jl

View check run for this annotation

Codecov / codecov/patch

lib/OptimalBranchingMIS/src/reducer.jl#L278

Added line #L278 was not covered by tests
end
end
2 changes: 1 addition & 1 deletion lib/OptimalBranchingMIS/test/branch.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ using Test, Random
mis_xiao = counting_xiao2013(g).size
p = MISProblem(g)

for set_cover_solver in [IPSolver(max_itr = 10, verbose = false), LPSolver(max_itr = 10, verbose = false)], measure in [D3Measure(), NumOfVertices()], reducer in [NoReducer(), MISReducer(), XiaoReducer(), TensorNetworkReducer()], prune_by_env in [true, false], selector in [MinBoundarySelector(2), MinBoundaryHighDegreeSelector(2, 6, 0), MinBoundaryHighDegreeSelector(2, 6, 1)]
for set_cover_solver in [IPSolver(max_itr = 10, verbose = false), LPSolver(max_itr = 10, verbose = false)], measure in [D3Measure(), NumOfVertices()], reducer in [NoReducer(), MISReducer(), XiaoReducer(), TensorNetworkReducer(), SubsolverReducer()], prune_by_env in [true, false], selector in [MinBoundarySelector(2), MinBoundaryHighDegreeSelector(2, 6, 0), MinBoundaryHighDegreeSelector(2, 6, 1)]
@info "set_cover_solver = $set_cover_solver, measure = $measure, reducer = $reducer, prune_by_env = $prune_by_env, selector = $selector"
branching_strategy = BranchingStrategy(; set_cover_solver, table_solver=TensorNetworkSolver(; prune_by_env), selector=selector, measure)
res = branch_and_reduce(p, branching_strategy, reducer, MaxSize)
Expand Down
Loading