-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
KaHyPar selector and greedy merge (#46)
* greedymerge * size_reduction * size_reduction * spaces * sapces * add test on coverd_by * fix test * fix test * update * update-greedy-implementation * merge and fix bugs * fix doc * save * kahypar selector * add more test * rm simulated annealing * speedup greedy method (#47) * save * update * update * update * fix test * use priority queue * update * add inbounds * update * ugly fix * fix tests * update * new visualization * update * change name --------- Co-authored-by: nzy <[email protected]> --------- Co-authored-by: GiggleLiu <[email protected]> Co-authored-by: nzy <[email protected]>
- Loading branch information
1 parent
9f425a3
commit dd34198
Showing
24 changed files
with
625 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,3 +12,5 @@ lib/OptimalBranchingMIS/docs/build/ | |
lib/OptimalBranchingCore/docs/build/ | ||
|
||
docs/src/generated/ | ||
|
||
report.typ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
struct GreedyMerge <: AbstractSetCoverSolver end | ||
struct NaiveBranch <: AbstractSetCoverSolver end | ||
function optimal_branching_rule(table::BranchingTable, variables::Vector, problem::AbstractProblem, m::AbstractMeasure, solver::GreedyMerge) | ||
candidates = bit_clauses(table) | ||
return greedymerge(candidates, problem, variables, m) | ||
end | ||
|
||
function optimal_branching_rule(table::BranchingTable, variables::Vector, problem::AbstractProblem, m::AbstractMeasure, solver::NaiveBranch) | ||
candidates = bit_clauses(table) | ||
size_reductions = [Float64(size_reduction(problem, m, first(candidate), variables)) for candidate in candidates] | ||
γ = complexity_bv(size_reductions) | ||
return OptimalBranchingResult(DNF(first.(candidates)), size_reductions, γ) | ||
end | ||
|
||
function bit_clauses(tbl::BranchingTable{INT}) where {INT} | ||
n, bss = tbl.bit_length, tbl.table | ||
temp_clauses = [[Clause(bmask(INT, 1:n), bs) for bs in bss1] for bss1 in bss] | ||
return temp_clauses | ||
end | ||
|
||
function greedymerge(cls::Vector{Vector{Clause{INT}}}, problem::AbstractProblem, variables::Vector, m::AbstractMeasure) where {INT} | ||
function reduction_merge(cli, clj) | ||
clmax, iimax, jjmax, reductionmax = Clause(zero(INT), zero(INT)), -1, -1, 0.0 | ||
@inbounds for ii = 1:length(cli), jj = 1:length(clj) | ||
cl12 = gather2(length(variables), cli[ii], clj[jj]) | ||
iszero(cl12.mask) && continue | ||
reduction = Float64(size_reduction(problem, m, cl12, variables)) | ||
if reduction > reductionmax | ||
clmax, iimax, jjmax, reductionmax = cl12, ii, jj, reduction | ||
end | ||
end | ||
return clmax, iimax, jjmax, reductionmax | ||
end | ||
cls = copy(cls) | ||
size_reductions = [Float64(size_reduction(problem, m, first(candidate), variables)) for candidate in cls] | ||
k = 0 | ||
@inbounds while true | ||
nc = length(cls) | ||
mask = trues(nc) | ||
γ = complexity_bv(size_reductions) | ||
weights = map(s -> γ^(-s), size_reductions) | ||
queue = PriorityQueue{NTuple{2, Int}, Float64}() # from small to large | ||
for i ∈ 1:nc, j ∈ i+1:nc | ||
_, _, _, reduction = reduction_merge(cls[i], cls[j]) | ||
dE = γ^(-reduction) - weights[i] - weights[j] | ||
dE <= -1e-12 && enqueue!(queue, (i, j), dE - 1e-12 * (k += 1; k)) | ||
end | ||
isempty(queue) && return OptimalBranchingResult(DNF(first.(cls)), size_reductions, γ) | ||
while !isempty(queue) | ||
(i, j) = dequeue!(queue) | ||
# remove i, j-th row | ||
for rowid in (i, j) | ||
mask[rowid] = false | ||
for k = 1:nc | ||
if mask[k] | ||
a, b = minmax(rowid, k) | ||
haskey(queue, (a, b)) && delete!(queue, (a, b)) | ||
end | ||
end | ||
end | ||
# add i-th row | ||
mask[i] = true | ||
clij, _, _, size_reductions[i] = reduction_merge(cls[i], cls[j]) | ||
cls[i] = [clij] | ||
weights[i] = γ^(-size_reductions[i]) | ||
for k = 1:nc | ||
if i !== k && mask[k] | ||
a, b = minmax(i, k) | ||
_, _, _, reduction = reduction_merge(cls[a], cls[b]) | ||
dE = γ^(-reduction) - weights[a] - weights[b] | ||
|
||
dE <= -1e-12 && enqueue!(queue, (a, b), dE - 1e-12 * (k += 1; k)) | ||
end | ||
end | ||
end | ||
cls, size_reductions = cls[mask], size_reductions[mask] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
struct MockProblem <: AbstractProblem | ||
optimal::BitVector | ||
end | ||
|
||
""" | ||
NumOfVariables | ||
A struct representing a measure that counts the number of variables in a problem. | ||
Each variable is counted as 1. | ||
""" | ||
struct NumOfVariables <: AbstractMeasure end | ||
measure(p::MockProblem, ::NumOfVariables) = length(p.optimal) | ||
|
||
|
||
""" | ||
struct RandomSelector <: AbstractSelector | ||
The `RandomSelector` struct represents a strategy for selecting a subset of variables randomly. | ||
# Fields | ||
- `n::Int`: The number of variables to select. | ||
""" | ||
struct RandomSelector <: AbstractSelector | ||
n::Int | ||
end | ||
function select_variables(p::MockProblem, ::NumOfVariables, selector::RandomSelector) | ||
nv = min(length(p.optimal), selector.n) | ||
return sortperm(rand(length(p.optimal)))[1:nv] | ||
end | ||
|
||
""" | ||
struct MockTableSolver <: AbstractTableSolver | ||
The `MockTableSolver` randomly generates a branching table with a given number of rows. | ||
Each row must have at least one variable to be covered by the branching rule. | ||
### Fields | ||
- `n::Int`: The number of rows in the branching table. | ||
- `p::Float64 = 0.0`: The probability of generating more than one variables in a row, following the Poisson distribution. | ||
""" | ||
struct MockTableSolver <: AbstractTableSolver | ||
n::Int | ||
p::Float64 | ||
end | ||
MockTableSolver(n::Int) = MockTableSolver(n, 0.0) | ||
function branching_table(p::MockProblem, table_solver::MockTableSolver, variables) | ||
function rand_fib() # random independent set on 1D chain | ||
bs = falses(length(variables)) | ||
for i=1:length(variables) | ||
if rand() < min(0.5, i == 1 ? 1.0 : 1 - bs[i-1]) | ||
bs[i] = true | ||
end | ||
end | ||
return bs | ||
end | ||
rows = unique!([[rand_fib()] for _ in 1:table_solver.n] ∪ [[p.optimal[variables]]]) | ||
for i in 1:length(rows) | ||
for _ = 1:100 | ||
if rand() < table_solver.p | ||
push!(rows[i], rand_fib()) | ||
else | ||
break | ||
end | ||
end | ||
end | ||
return BranchingTable(length(variables), unique!.(rows)) | ||
end | ||
|
||
function apply_branch(p::MockProblem, clause::Clause{INT}, variables::Vector{T}) where {INT<:Integer, T<:Integer} | ||
remain_mask = trues(length(p.optimal)) | ||
for i in 1:length(variables) | ||
isone(readbit(clause.mask, i)) && (remain_mask[variables[i]] = false) | ||
end | ||
return MockProblem(p.optimal[remain_mask]), count(i -> isone(readbit(clause.mask, i)) && (readbit(clause.val, i) == p.optimal[variables[i]]), 1:length(variables)) | ||
end | ||
has_zero_size(p::MockProblem) = measure(p, NumOfVariables()) == 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.