From c66c791eb58c83dca0184b64ee07e790b198650a Mon Sep 17 00:00:00 2001 From: c-allergic Date: Wed, 26 Mar 2025 14:14:58 +0800 Subject: [PATCH 1/6] New reduction rule: BinaryMatrixFactorization to BicliqueCover --- src/models/BMF.jl | 2 +- src/models/BicliqueCover.jl | 3 ++- src/rules/BMF_BicliqueCover.jl | 30 ++++++++++++++++++++++++++++++ src/rules/rules.jl | 3 ++- test/rules/BMF_BicliqueCover.jl | 13 +++++++++++++ test/rules/rules.jl | 4 ++++ 6 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 src/rules/BMF_BicliqueCover.jl create mode 100644 test/rules/BMF_BicliqueCover.jl diff --git a/src/models/BMF.jl b/src/models/BMF.jl index c17fa53..eb1bb3e 100644 --- a/src/models/BMF.jl +++ b/src/models/BMF.jl @@ -18,7 +18,7 @@ The Boolean Matrix Factorization (BMF) problem is defined on a binary matrix A i struct BinaryMatrixFactorization<: AbstractProblem A::BitMatrix k::Int - function BinaryMatrixFactorization(A::BitMatrix, k::Int) where K + function BinaryMatrixFactorization(A::BitMatrix, k::Int) new(A, k) end end diff --git a/src/models/BicliqueCover.jl b/src/models/BicliqueCover.jl index edc1c38..4344548 100644 --- a/src/models/BicliqueCover.jl +++ b/src/models/BicliqueCover.jl @@ -35,7 +35,7 @@ problem_size(c::BicliqueCover) = (; num_vertices=nv(c.graph), num_edges=ne(c.gra # Variables Interface # each vertex is assigned to a biclique, with k bicliques, variables(c::BicliqueCover) = fill(1,c.k * nv(c.graph)) num_variables(c::BicliqueCover) = nv(c.graph) * c.k -num_flavors(c::BicliqueCover) = 2 +num_flavors(::Type{BicliqueCover{Int64}}) = 2 # constraints interface function constraints(c::BicliqueCover) @@ -46,6 +46,7 @@ function _biclique_cover(config) end # solution_size function for BicliqueCover, the solution size is the sum of the weights of the bicliques function solution_size_multiple(c::BicliqueCover, configs) + print(configs) @assert all(length(config) <= c.k for config in configs) return map(configs) do config return SolutionSize(sum(i -> count(k -> k ==1, i),config), is_biclique_cover(c,config)) diff --git a/src/rules/BMF_BicliqueCover.jl b/src/rules/BMF_BicliqueCover.jl new file mode 100644 index 0000000..013d443 --- /dev/null +++ b/src/rules/BMF_BicliqueCover.jl @@ -0,0 +1,30 @@ +""" +$TYPEDEF + +The reduction result from BinaryMatrixFactorization to BicliqueCover. + +### Fields +- `bicliquecover`: The BicliqueCover problem. +- `k`: The number of bicliques. +""" +struct BMF_BicliqueCover{Int64} <: AbstractReductionResult + bicliquecover::BicliqueCover{Int64} + k::Int64 +end +Base.:(==)(a::BMF_BicliqueCover, b::BMF_BicliqueCover) = a.bicliquecover == b.bicliquecover && a.k == b.k +target_problem(res::BMF_BicliqueCover) = res.bicliquecover + +function reduceto(::Type{BicliqueCover}, bmf::BinaryMatrixFactorization) + k = bmf.k + A = Int.(bmf.A) + return BMF_BicliqueCover(ProblemReductions.biclique_cover_from_matrix(A, k), k) +end + +# Not implemented +function extract_solution(res::BMF_BicliqueCover, solution::Vector{Vector{Int64}}) + return solution +end + +function extract_multiple_solutions(res::BMF_BicliqueCover, solution_set) + return unique(extract_solution.(Ref(res), solution_set)) +end \ No newline at end of file diff --git a/src/rules/rules.jl b/src/rules/rules.jl index a81b74d..9c851f7 100644 --- a/src/rules/rules.jl +++ b/src/rules/rules.jl @@ -88,4 +88,5 @@ include("sat_dominatingset.jl") include("independentset_setpacking.jl") include("circuit_sat.jl") include("vertexcovering_independentset.jl") -include("matching_setpacking.jl") \ No newline at end of file +include("matching_setpacking.jl") +include("BMF_BicliqueCover.jl") \ No newline at end of file diff --git a/test/rules/BMF_BicliqueCover.jl b/test/rules/BMF_BicliqueCover.jl new file mode 100644 index 0000000..1a33f7a --- /dev/null +++ b/test/rules/BMF_BicliqueCover.jl @@ -0,0 +1,13 @@ +using Test, ProblemReductions, Graphs + +@testset "BMF_BicliqueCover" begin + A = [1 0 ; 1 1] + A = BitMatrix(A) + bmf1 = BinaryMatrixFactorization(A, 2) + bc1 = ProblemReductions.biclique_cover_from_matrix(Int.(A), 2) + res = reduceto(BicliqueCover, bmf1) + @test res.k == 2 + @test res.bicliquecover == bc1 + @test res.bicliquecover.part1 == [i for i in 1:size(A,1)] + @test target_problem(res) == bc1 +end \ No newline at end of file diff --git a/test/rules/rules.jl b/test/rules/rules.jl index 8a24877..32ead72 100644 --- a/test/rules/rules.jl +++ b/test/rules/rules.jl @@ -52,6 +52,10 @@ end include("matching_setpacking.jl") end +@testset "BMF_BicliqueCover" begin + include("BMF_BicliqueCover.jl") +end + @testset "rules" begin circuit = CircuitSAT(@circuit begin x = a ∨ ¬b From e16bdb20d26e5f7b23cd324ef4b45aefe7a97aff Mon Sep 17 00:00:00 2001 From: c-allergic Date: Mon, 31 Mar 2025 14:45:15 +0800 Subject: [PATCH 2/6] Correct Naming Error, Add extract_solution interface --- src/ProblemReductions.jl | 1 + src/models/BicliqueCover.jl | 1 - src/rules/BMF_BicliqueCover.jl | 32 ++++++++++++++++++++++++-------- test/models/BicliqueCover.jl | 1 + test/rules/BMF_BicliqueCover.jl | 3 +++ 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/ProblemReductions.jl b/src/ProblemReductions.jl index 0ee2489..7e3575f 100644 --- a/src/ProblemReductions.jl +++ b/src/ProblemReductions.jl @@ -48,6 +48,7 @@ export ReductionIndependentSetToSetPacking, ReductionSetPackingToIndependentSet export ReductionSATToCircuit export ReductionIndependentSetToVertexCovering export ReductionMatchingToSetPacking +export ReductionBMFToBicliqueCover # reduction path export ReductionGraph, reduction_graph, reduction_paths, ConcatenatedReduction diff --git a/src/models/BicliqueCover.jl b/src/models/BicliqueCover.jl index 4344548..111677a 100644 --- a/src/models/BicliqueCover.jl +++ b/src/models/BicliqueCover.jl @@ -46,7 +46,6 @@ function _biclique_cover(config) end # solution_size function for BicliqueCover, the solution size is the sum of the weights of the bicliques function solution_size_multiple(c::BicliqueCover, configs) - print(configs) @assert all(length(config) <= c.k for config in configs) return map(configs) do config return SolutionSize(sum(i -> count(k -> k ==1, i),config), is_biclique_cover(c,config)) diff --git a/src/rules/BMF_BicliqueCover.jl b/src/rules/BMF_BicliqueCover.jl index 013d443..c899df8 100644 --- a/src/rules/BMF_BicliqueCover.jl +++ b/src/rules/BMF_BicliqueCover.jl @@ -7,24 +7,40 @@ The reduction result from BinaryMatrixFactorization to BicliqueCover. - `bicliquecover`: The BicliqueCover problem. - `k`: The number of bicliques. """ -struct BMF_BicliqueCover{Int64} <: AbstractReductionResult +struct ReductionBMFToBicliqueCover{Int64} <: AbstractReductionResult bicliquecover::BicliqueCover{Int64} k::Int64 end -Base.:(==)(a::BMF_BicliqueCover, b::BMF_BicliqueCover) = a.bicliquecover == b.bicliquecover && a.k == b.k -target_problem(res::BMF_BicliqueCover) = res.bicliquecover +Base.:(==)(a::ReductionBMFToBicliqueCover, b::ReductionBMFToBicliqueCover) = a.bicliquecover == b.bicliquecover && a.k == b.k +target_problem(res::ReductionBMFToBicliqueCover) = res.bicliquecover function reduceto(::Type{BicliqueCover}, bmf::BinaryMatrixFactorization) k = bmf.k A = Int.(bmf.A) - return BMF_BicliqueCover(ProblemReductions.biclique_cover_from_matrix(A, k), k) + return ReductionBMFToBicliqueCover(ProblemReductions.biclique_cover_from_matrix(A, k), k) end -# Not implemented -function extract_solution(res::BMF_BicliqueCover, solution::Vector{Vector{Int64}}) - return solution +function extract_solution(res::ReductionBMFToBicliqueCover{Int64}, solution::Vector{Vector{Int64}}) + len_part1 = length(res.bicliquecover.part1) + len_part2 = nv(res.bicliquecover.graph) - len_part1 + B = falses((len_part1,res.k)) + C = falses((res.k,len_part1)) + # each iteration, we update the a-th column of B and the a-th row of C + for a in range(1,res.k) + for i in range(1,len_part1) + if solution[a][i] == 1 + B[i,a] = true + end + end + for j in range(1,len_part2) + if solution[a][j+len_part1] == 1 + C[a,j] = true + end + end + end + return (B,C) end -function extract_multiple_solutions(res::BMF_BicliqueCover, solution_set) +function extract_multiple_solutions(res::ReductionBMFToBicliqueCover{Int64}, solution_set::Vector{Vector{Vector{Int64}}}) return unique(extract_solution.(Ref(res), solution_set)) end \ No newline at end of file diff --git a/test/models/BicliqueCover.jl b/test/models/BicliqueCover.jl index 711fa53..98de819 100644 --- a/test/models/BicliqueCover.jl +++ b/test/models/BicliqueCover.jl @@ -10,6 +10,7 @@ using Test, ProblemReductions, Graphs # variable and weight interfaces @test num_variables(bc) == 12 @test num_flavors(bc) == 2 + @test num_flavors(BicliqueCover) == 2 @test problem_size(bc) == (num_vertices=6, num_edges=5, k=2) bc_matrix = ProblemReductions.biclique_cover_from_matrix([1 1 0;1 1 0;0 0 1],2) @test bc_matrix == bc diff --git a/test/rules/BMF_BicliqueCover.jl b/test/rules/BMF_BicliqueCover.jl index 1a33f7a..3c025ca 100644 --- a/test/rules/BMF_BicliqueCover.jl +++ b/test/rules/BMF_BicliqueCover.jl @@ -6,8 +6,11 @@ using Test, ProblemReductions, Graphs bmf1 = BinaryMatrixFactorization(A, 2) bc1 = ProblemReductions.biclique_cover_from_matrix(Int.(A), 2) res = reduceto(BicliqueCover, bmf1) + res1 = ReductionBMFToBicliqueCover(bc1,2) + @test res == res1 @test res.k == 2 @test res.bicliquecover == bc1 @test res.bicliquecover.part1 == [i for i in 1:size(A,1)] @test target_problem(res) == bc1 + @test extract_solution(res,[[1,1,1,0],[0,1,0,1]]) == ([true false ; true true], [true false ; false true]) end \ No newline at end of file From f915691b1ee105b376a699b6395a643d48f10ce8 Mon Sep 17 00:00:00 2001 From: c-allergic Date: Mon, 31 Mar 2025 14:46:53 +0800 Subject: [PATCH 3/6] Add test --- test/rules/BMF_BicliqueCover.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/rules/BMF_BicliqueCover.jl b/test/rules/BMF_BicliqueCover.jl index 3c025ca..dc46e84 100644 --- a/test/rules/BMF_BicliqueCover.jl +++ b/test/rules/BMF_BicliqueCover.jl @@ -13,4 +13,5 @@ using Test, ProblemReductions, Graphs @test res.bicliquecover.part1 == [i for i in 1:size(A,1)] @test target_problem(res) == bc1 @test extract_solution(res,[[1,1,1,0],[0,1,0,1]]) == ([true false ; true true], [true false ; false true]) + @test extract_multiple_solutions(res,[[[1,1,1,0],[0,1,0,1]]]) == [([true false ; true true], [true false ; false true])] end \ No newline at end of file From f263d1e3ed391ec2d5b52869b9f2bc87acff7682 Mon Sep 17 00:00:00 2001 From: c-allergic Date: Mon, 31 Mar 2025 14:53:52 +0800 Subject: [PATCH 4/6] Necessary Revise of test --- test/models/BicliqueCover.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/models/BicliqueCover.jl b/test/models/BicliqueCover.jl index 98de819..18876df 100644 --- a/test/models/BicliqueCover.jl +++ b/test/models/BicliqueCover.jl @@ -10,7 +10,7 @@ using Test, ProblemReductions, Graphs # variable and weight interfaces @test num_variables(bc) == 12 @test num_flavors(bc) == 2 - @test num_flavors(BicliqueCover) == 2 + @test num_flavors(BicliqueCover{Int64}) == 2 @test problem_size(bc) == (num_vertices=6, num_edges=5, k=2) bc_matrix = ProblemReductions.biclique_cover_from_matrix([1 1 0;1 1 0;0 0 1],2) @test bc_matrix == bc From 435723adeb91cb7365ca012857f7c201cb21ddac Mon Sep 17 00:00:00 2001 From: c-allergic Date: Tue, 1 Apr 2025 22:45:55 +0800 Subject: [PATCH 5/6] New version of reduction and New feature: read_solution --- src/ProblemReductions.jl | 6 ++-- src/models/BMF.jl | 22 +++++++++++++ src/models/BicliqueCover.jl | 28 ++++++++++++++++ src/rules/BMF_BicliqueCover.jl | 57 ++++++++++++++++++--------------- test/models/BMF.jl | 39 ++++++++++++---------- test/models/BicliqueCover.jl | 2 ++ test/rules/BMF_BicliqueCover.jl | 20 +++++++++--- 7 files changed, 124 insertions(+), 50 deletions(-) diff --git a/src/ProblemReductions.jl b/src/ProblemReductions.jl index 7e3575f..9344b2b 100644 --- a/src/ProblemReductions.jl +++ b/src/ProblemReductions.jl @@ -30,8 +30,8 @@ export Factoring, is_factoring export Matching, is_matching export MaximalIS export PaintShop -export BinaryMatrixFactorization, is_binary_matrix_factorization -export BicliqueCover, is_biclique_cover +export BinaryMatrixFactorization, is_binary_matrix_factorization, read_solution +export BicliqueCover, is_biclique_cover, read_solution, biclique_cover_from_matrix # rules export target_problem, AbstractProblem, ConstraintSatisfactionProblem, solution_size, solution_size_multiple, SolutionSize, objectives, constraints, energy_mode @@ -48,7 +48,7 @@ export ReductionIndependentSetToSetPacking, ReductionSetPackingToIndependentSet export ReductionSATToCircuit export ReductionIndependentSetToVertexCovering export ReductionMatchingToSetPacking -export ReductionBMFToBicliqueCover +export ReductionBMFToBicliqueCover, ReductionBicliqueCoverToBMF # reduction path export ReductionGraph, reduction_graph, reduction_paths, ConcatenatedReduction diff --git a/src/models/BMF.jl b/src/models/BMF.jl index eb1bb3e..7b28ccd 100644 --- a/src/models/BMF.jl +++ b/src/models/BMF.jl @@ -49,5 +49,27 @@ function is_binary_matrix_factorization(bmf::BinaryMatrixFactorization, b::BitMa return solution_size(bmf,b,c) == 0 end +""" + + read_solution(bmf::BinaryMatrixFactorization, solution::Vector{BitMatrix}) + Read the solution of the BinaryMatrixFactorization problem from the solution of the BMF problem, return a vector of cliques +""" +function read_solution(bmf::BinaryMatrixFactorization, a::BitMatrix, b::BitMatrix) + @assert size(a,2) == size(b,1) == bmf.k "Dimension mismatch" + cliques = [zeros(Int64,size(a,1)+size(b,2)) for i in range(1,bmf.k)] + for i in range(1,bmf.k) + for j in range(1,size(a,1)) + if a[j,i] + cliques[i][j] = 1 + end + end + for j in range(1,size(b,2)) + if b[i,j] + cliques[i][j+size(a,1)] = 1 + end + end + end + return cliques +end diff --git a/src/models/BicliqueCover.jl b/src/models/BicliqueCover.jl index 111677a..8b77992 100644 --- a/src/models/BicliqueCover.jl +++ b/src/models/BicliqueCover.jl @@ -94,3 +94,31 @@ function is_biclique(config,bc::BicliqueCover) end return true end + +""" + + read_solution(bicliquecover::BicliqueCover, solution::Vector{Vector{Int64}}) + +Read the solution of the BicliqueCover problem from the solution of the BMF problem, return a vector of two bit matrix +""" +function read_solution(bicliquecover::BicliqueCover, solution::Vector{Vector{Int64}}) + len_part1 = length(bicliquecover.part1) + len_part2 = nv(bicliquecover.graph) - len_part1 + k = bicliquecover.k + B = falses((len_part1,k)) + C = falses((k,len_part1)) + # each iteration, we update the a-th column of B and the a-th row of C + for a in range(1,k) + for i in range(1,len_part1) + if solution[a][i] == 1 + B[i,a] = true + end + end + for j in range(1,len_part2) + if solution[a][j+len_part1] == 1 + C[a,j] = true + end + end + end + return [B,C] +end diff --git a/src/rules/BMF_BicliqueCover.jl b/src/rules/BMF_BicliqueCover.jl index c899df8..b29e5e7 100644 --- a/src/rules/BMF_BicliqueCover.jl +++ b/src/rules/BMF_BicliqueCover.jl @@ -5,42 +5,47 @@ The reduction result from BinaryMatrixFactorization to BicliqueCover. ### Fields - `bicliquecover`: The BicliqueCover problem. -- `k`: The number of bicliques. """ struct ReductionBMFToBicliqueCover{Int64} <: AbstractReductionResult bicliquecover::BicliqueCover{Int64} - k::Int64 end -Base.:(==)(a::ReductionBMFToBicliqueCover, b::ReductionBMFToBicliqueCover) = a.bicliquecover == b.bicliquecover && a.k == b.k +Base.:(==)(a::ReductionBMFToBicliqueCover, b::ReductionBMFToBicliqueCover) = a.bicliquecover == b.bicliquecover target_problem(res::ReductionBMFToBicliqueCover) = res.bicliquecover -function reduceto(::Type{BicliqueCover}, bmf::BinaryMatrixFactorization) - k = bmf.k - A = Int.(bmf.A) - return ReductionBMFToBicliqueCover(ProblemReductions.biclique_cover_from_matrix(A, k), k) +function reduceto(::Type{<:BicliqueCover}, bmf::BinaryMatrixFactorization) + bc = biclique_cover_from_matrix(Int.(bmf.A), bmf.k) + return ReductionBMFToBicliqueCover(bc) end -function extract_solution(res::ReductionBMFToBicliqueCover{Int64}, solution::Vector{Vector{Int64}}) - len_part1 = length(res.bicliquecover.part1) - len_part2 = nv(res.bicliquecover.graph) - len_part1 - B = falses((len_part1,res.k)) - C = falses((res.k,len_part1)) - # each iteration, we update the a-th column of B and the a-th row of C - for a in range(1,res.k) - for i in range(1,len_part1) - if solution[a][i] == 1 - B[i,a] = true - end - end - for j in range(1,len_part2) - if solution[a][j+len_part1] == 1 - C[a,j] = true - end +function extract_solution(res::ReductionBMFToBicliqueCover{Int64}, solution) + return solution +end + +""" +$TYPEDEF + +The reduction result from BicliqueCover to BinaryMatrixFactorization. + +### Fields +- `BMF`: The BinaryMatrixFactorization problem. +""" +struct ReductionBicliqueCoverToBMF <: AbstractReductionResult + BMF::BinaryMatrixFactorization +end +Base.:(==)(a::ReductionBicliqueCoverToBMF, b::ReductionBicliqueCoverToBMF) = a.BMF == b.BMF +target_problem(res::ReductionBicliqueCoverToBMF) = res.BMF + +function reduceto(::Type{<:BinaryMatrixFactorization}, biclique::BicliqueCover) + len_part1 = length(biclique.part1) + A = falses((len_part1,nv(biclique.graph)-len_part1)) + for e in edges(biclique.graph) + if e.src in biclique.part1 + A[e.src, e.dst-len_part1] = true end end - return (B,C) + return ReductionBicliqueCoverToBMF(BinaryMatrixFactorization(A, biclique.k)) end -function extract_multiple_solutions(res::ReductionBMFToBicliqueCover{Int64}, solution_set::Vector{Vector{Vector{Int64}}}) - return unique(extract_solution.(Ref(res), solution_set)) +function extract_solution(res::ReductionBicliqueCoverToBMF, solution) + return solution end \ No newline at end of file diff --git a/test/models/BMF.jl b/test/models/BMF.jl index 86346f6..348d8d1 100644 --- a/test/models/BMF.jl +++ b/test/models/BMF.jl @@ -4,32 +4,37 @@ using Test, ProblemReductions # test 1 A = trues(3, 3) k = 2 - bmf = BinaryMatrixFactorization(A, k) + bmf1 = BinaryMatrixFactorization(A, k) - @test variables(bmf) == [i for i in 1:12] - @test num_variables(bmf) == 12 + @test variables(bmf1) == [i for i in 1:12] + @test num_variables(bmf1) == 12 @test flavors(BinaryMatrixFactorization) == (0, 1) @test num_flavors(BinaryMatrixFactorization) == 2 - @test problem_size(bmf) == (num_rows=3, num_cols=3, k=2) - @test solution_size(bmf, falses(3, 2), falses(2, 3)) == 9 + @test problem_size(bmf1) == (num_rows=3, num_cols=3, k=2) + @test solution_size(bmf1, falses(3, 2), falses(2, 3)) == 9 @test energy_mode(BinaryMatrixFactorization) == SmallerSizeIsBetter() - @test is_binary_matrix_factorization(bmf, falses(3, 2), falses(2, 3)) == false - @test is_binary_matrix_factorization(bmf,trues(3, 2), trues(2, 3)) == true - bmf1 = BinaryMatrixFactorization(trues(3,3), 3) - @test bmf != bmf1 - bmf2 = BinaryMatrixFactorization(trues(3,3), 2) - @test bmf == bmf2 + @test is_binary_matrix_factorization(bmf1, falses(3, 2), falses(2, 3)) == false + @test is_binary_matrix_factorization(bmf1,trues(3, 2), trues(2, 3)) == true + bmf_a = BinaryMatrixFactorization(trues(3,3), 3) + @test bmf1 != bmf_a + bmf_b = BinaryMatrixFactorization(trues(3,3), 2) + @test bmf1 == bmf_b # test 2 A = trues(3, 3) k = 2 - bmf = BinaryMatrixFactorization(A, k) + bmf2 = BinaryMatrixFactorization(A, k) - @test num_variables(bmf) == 12 + @test num_variables(bmf2) == 12 @test flavors(BinaryMatrixFactorization) == (0, 1) - @test problem_size(bmf) == (num_rows=3, num_cols=3, k=2) - @test solution_size(bmf, falses(3, 2), falses(2, 3)) == 9 + @test problem_size(bmf2) == (num_rows=3, num_cols=3, k=2) + @test solution_size(bmf2, falses(3, 2), falses(2, 3)) == 9 @test energy_mode(BinaryMatrixFactorization) == SmallerSizeIsBetter() - @test is_binary_matrix_factorization(bmf, falses(3, 2), falses(2, 3)) == false - @test is_binary_matrix_factorization(bmf,trues(3, 2), trues(2, 3)) == true + @test is_binary_matrix_factorization(bmf2, falses(3, 2), falses(2, 3)) == false + @test is_binary_matrix_factorization(bmf2,trues(3, 2), trues(2, 3)) == true + + # test 3 + A = BitMatrix([1 0;1 1]) + bmf3 = BinaryMatrixFactorization(A, 2) + @test read_solution(bmf3, BitMatrix([1 0 ; 1 1]), BitMatrix([1 0 ; 0 1])) == [[1,1,1,0],[0,1,0,1]] end \ No newline at end of file diff --git a/test/models/BicliqueCover.jl b/test/models/BicliqueCover.jl index 18876df..c49f1fe 100644 --- a/test/models/BicliqueCover.jl +++ b/test/models/BicliqueCover.jl @@ -25,4 +25,6 @@ using Test, ProblemReductions, Graphs @test ProblemReductions.is_satisfied(bc,[[1,1,0,1,1,0],[0,0,1,0,0,1]]) == true @test solution_size(bc, [[1,1,0,1,1,0],[0,0,1,0,0,1]]) == ProblemReductions.SolutionSize(6, true) @test solution_size(bc, [[1,1,0,1,1,0],[0,0,1,0,0,0]]) == ProblemReductions.SolutionSize(5, false) + B,C = BitMatrix([1 0;1 0;0 1]), BitMatrix([1 1 0;0 0 1]) + @test read_solution(bc, [[1,1,0,1,1,0],[0,0,1,0,0,1]]) == [B,C] end diff --git a/test/rules/BMF_BicliqueCover.jl b/test/rules/BMF_BicliqueCover.jl index dc46e84..3335a58 100644 --- a/test/rules/BMF_BicliqueCover.jl +++ b/test/rules/BMF_BicliqueCover.jl @@ -6,12 +6,24 @@ using Test, ProblemReductions, Graphs bmf1 = BinaryMatrixFactorization(A, 2) bc1 = ProblemReductions.biclique_cover_from_matrix(Int.(A), 2) res = reduceto(BicliqueCover, bmf1) - res1 = ReductionBMFToBicliqueCover(bc1,2) + res1 = ReductionBMFToBicliqueCover(bc1) @test res == res1 - @test res.k == 2 @test res.bicliquecover == bc1 @test res.bicliquecover.part1 == [i for i in 1:size(A,1)] @test target_problem(res) == bc1 - @test extract_solution(res,[[1,1,1,0],[0,1,0,1]]) == ([true false ; true true], [true false ; false true]) - @test extract_multiple_solutions(res,[[[1,1,1,0],[0,1,0,1]]]) == [([true false ; true true], [true false ; false true])] + @test extract_solution(res,[[1,1,1,0],[0,1,0,1]]) == [[1,1,1,0],[0,1,0,1]] +end + +@testset "BicliqueCover_BMF" begin + g = SimpleGraph(4) + for (i,j) in [(1,3),(2,3),(2,4)] + add_edge!(g,i,j) + end + bc = BicliqueCover(g,[1,2], 2) + res = reduceto(BinaryMatrixFactorization, bc) + res1 = ReductionBicliqueCoverToBMF(BinaryMatrixFactorization(BitMatrix([1 0; 1 1]), 2)) + @test res == res1 + @test res.BMF == BinaryMatrixFactorization(BitMatrix([1 0; 1 1]), 2) + @test target_problem(res) == BinaryMatrixFactorization(BitMatrix([1 0; 1 1]), 2) + @test extract_solution(res,[[1,0,1,0],[0,1,0,1]]) == [[1,0,1,0],[0,1,0,1]] end \ No newline at end of file From 9e23fb023fca384baf616533e0c41192978d5e80 Mon Sep 17 00:00:00 2001 From: Sheldon LI Date: Wed, 2 Apr 2025 11:19:24 +0800 Subject: [PATCH 6/6] Update src/models/BicliqueCover.jl Co-authored-by: Jinguo Liu --- src/models/BicliqueCover.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/BicliqueCover.jl b/src/models/BicliqueCover.jl index 8b77992..77d7418 100644 --- a/src/models/BicliqueCover.jl +++ b/src/models/BicliqueCover.jl @@ -35,7 +35,7 @@ problem_size(c::BicliqueCover) = (; num_vertices=nv(c.graph), num_edges=ne(c.gra # Variables Interface # each vertex is assigned to a biclique, with k bicliques, variables(c::BicliqueCover) = fill(1,c.k * nv(c.graph)) num_variables(c::BicliqueCover) = nv(c.graph) * c.k -num_flavors(::Type{BicliqueCover{Int64}}) = 2 +num_flavors(::Type{<:BicliqueCover}) = 2 # constraints interface function constraints(c::BicliqueCover)