Skip to content

Commit

Permalink
Fix set cover (#41)
Browse files Browse the repository at this point in the history
* fix set cover

* Update test/models/SetCovering.jl
  • Loading branch information
GiggleLiu authored Jul 18, 2024
1 parent 3263af0 commit f1cbde3
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 37 deletions.
40 changes: 8 additions & 32 deletions src/models/SetCovering.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ Positional arguments
-------------------------------
* `sets` is a vector of vectors, a collection of subsets of universe , each set is associated with a weight specified in `weights`.
* `weights` are associated with sets.
"""

struct SetCovering{ET, WT<:Union{UnitWeight, Vector}} <: AbstractProblem
Expand All @@ -22,10 +21,7 @@ Base.:(==)(a::SetCovering, b::SetCovering) = a.sets == b.sets && a.weights == b.

#variables interface
variables(gp::SetCovering) = gp.sets
num_variables(c::SetCovering) = length(c.sets)
flavors(::Type{<:SetCovering}) = [0, 1] #whether the set is selected or not


flavors(::Type{<:SetCovering}) = [0, 1] # whether the set is selected (1) or not (0)

# weights interface
parameters(c::SetCovering) = c.weights
Expand All @@ -41,33 +37,12 @@ sum of the weights of the sets that are selected. Config is a vector of boolean

function evaluate(c::SetCovering, config)
@assert length(config) == num_variables(c)
set_covering_energy(c.weights, config )
set_covering_energy(c.sets, c.weights, config )
end
set_covering_energy(weights::AbstractVector, config) = sum(weights[i]*config[i] for i=1:length(weights))

"""
findbest(c::SetCovering) -> Vector
Find the best configurations of the `c` using the `method`. We offer bruteforce search as the default method.
"""

function findbest(c::SetCovering, method="bruteforce")
best = nothing
best_energy = Inf
for config in Iterators.product((fill([0,1],num_variables(c)))...)
if sum(config) == 0
continue
end
if is_set_covering(c,config)
energy = evaluate(c,config)
if energy < best_energy
best = config
best_energy = energy
end
end
end
return best
function set_covering_energy(sets::AbstractVector, weights::AbstractVector, config)
@assert length(sets) == length(weights) == length(config)
!is_set_covering(SetCovering(sets, weights), config) && return typemax(eltype(weights))
return sum(weights[i] * config[i] for i=1:length(weights))
end

"""
Expand All @@ -76,5 +51,6 @@ end
Return true if `config` (a vector of boolean numbers as the mask of sets) is a set covering of `sets`.
"""
function is_set_covering(c::SetCovering, config)
return reduce(union,c.sets)==reduce(union,c.sets[i] for i in 1:length(config) if config[i]==1)
@assert length(config) == num_variables(c)
return Set(vcat(c.sets...)) == Set(vcat([c.sets[i] for i in 1:length(config) if config[i]==1]...))
end
11 changes: 6 additions & 5 deletions test/models/SetCovering.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ using ProblemReductions: SetCovering, variables, flavors, terms, evaluate, set_p
@test set_parameters(c, [1, 2, 3]) == SetCovering([[1, 2], [2, 3], [2, 3, 4]], [1, 2, 3])

# evaluate
@test evaluate(c, [0, 1, 1]) == 3
@test set_covering_energy([1, 1, 2], [0, 0, 1]) == 2
@test evaluate(c, [0, 1, 1]) == typemax(Int)
@test evaluate(c, [1, 0, 1]) == 3
@test set_covering_energy(c.sets, [1, 1, 2], [0, 0, 1]) == typemax(Int)
@test is_set_covering(c,[1,0,1]) == true
@test is_set_covering(c,[0,0,1]) == false

# findbest
@test findbest(c) == (1,0,1)
@test findbest(c, "bruteforce") == (1,0,1)
@test findbest(c, BruteForce()) == [[1, 0, 1]]
@test findbest(c, BruteForce()) == [[1, 0, 1]]
g = SetCovering([[1, 2], [1, 3, 4], [2, 3]], [1, 1, 2])
@test findbest(g) == (1,1,0)
@test findbest(g, BruteForce()) == [[1, 1, 0]]
end

0 comments on commit f1cbde3

Please sign in to comment.