d7dbee4c05
We're using the Gram matrix engine for the next stage of development, so the algebraic engine shouldn't be at the top level anymore.
111 lines
2.6 KiB
Julia
111 lines
2.6 KiB
Julia
module HittingSet
|
|
|
|
export HittingSetProblem, solve
|
|
|
|
HittingSetProblem{T} = Pair{Set{T}, Vector{Pair{T, Set{Set{T}}}}}
|
|
|
|
# `targets` should be a collection of Set objects
|
|
function HittingSetProblem(targets, chosen = Set())
|
|
wholeset = union(targets...)
|
|
T = eltype(wholeset)
|
|
unsorted_moves = [
|
|
elt => Set(filter(s -> elt ∉ s, targets))
|
|
for elt in wholeset
|
|
]
|
|
moves = sort(unsorted_moves, by = pair -> length(pair.second))
|
|
Set{T}(chosen) => moves
|
|
end
|
|
|
|
function Base.display(problem::HittingSetProblem{T}) where T
|
|
println("HittingSetProblem{$T}")
|
|
|
|
chosen = problem.first
|
|
println(" {", join(string.(chosen), ", "), "}")
|
|
|
|
moves = problem.second
|
|
for (choice, missed) in moves
|
|
println(" | ", choice)
|
|
for s in missed
|
|
println(" | | {", join(string.(s), ", "), "}")
|
|
end
|
|
end
|
|
println()
|
|
end
|
|
|
|
function solve(pblm::HittingSetProblem{T}, maxdepth = Inf) where T
|
|
problems = Dict(pblm)
|
|
while length(first(problems).first) < maxdepth
|
|
subproblems = typeof(problems)()
|
|
for (chosen, moves) in problems
|
|
if isempty(moves)
|
|
return chosen
|
|
else
|
|
for (choice, missed) in moves
|
|
to_be_chosen = union(chosen, Set([choice]))
|
|
if isempty(missed)
|
|
return to_be_chosen
|
|
elseif !haskey(subproblems, to_be_chosen)
|
|
push!(subproblems, HittingSetProblem(missed, to_be_chosen))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
problems = subproblems
|
|
end
|
|
problems
|
|
end
|
|
|
|
function test(n = 1)
|
|
T = [Int64, Int64, Symbol, Symbol][n]
|
|
targets = Set{T}.([
|
|
[
|
|
[1, 3, 5],
|
|
[2, 3, 4],
|
|
[1, 4],
|
|
[2, 3, 4, 5],
|
|
[4, 5]
|
|
],
|
|
# example from Amit Chakrabarti's graduate-level algorithms class (CS 105)
|
|
# notes by Valika K. Wan and Khanh Do Ba, Winter 2005
|
|
# https://www.cs.dartmouth.edu/~ac/Teach/CS105-Winter05/
|
|
[
|
|
[1, 3], [1, 4], [1, 5],
|
|
[1, 3], [1, 2, 4], [1, 2, 5],
|
|
[4, 3], [ 2, 4], [ 2, 5],
|
|
[6, 3], [6, 4], [ 5]
|
|
],
|
|
[
|
|
[:w, :x, :y],
|
|
[:x, :y, :z],
|
|
[:w, :z],
|
|
[:x, :y]
|
|
],
|
|
# Wikipedia showcases this as an example of a problem where the greedy
|
|
# algorithm performs especially poorly
|
|
[
|
|
[:a, :x, :t1],
|
|
[:a, :y, :t2],
|
|
[:a, :y, :t3],
|
|
[:a, :z, :t4],
|
|
[:a, :z, :t5],
|
|
[:a, :z, :t6],
|
|
[:a, :z, :t7],
|
|
[:b, :x, :t8],
|
|
[:b, :y, :t9],
|
|
[:b, :y, :t10],
|
|
[:b, :z, :t11],
|
|
[:b, :z, :t12],
|
|
[:b, :z, :t13],
|
|
[:b, :z, :t14]
|
|
]
|
|
][n])
|
|
problem = HittingSetProblem(targets)
|
|
if isa(problem, HittingSetProblem{T})
|
|
println("Correct type")
|
|
else
|
|
println("Wrong type: ", typeof(problem))
|
|
end
|
|
problem
|
|
end
|
|
|
|
end |