From 80758507541e0684cc3cd350ff1ed6a57f73c9ff Mon Sep 17 00:00:00 2001 From: Shreyas Date: Fri, 24 Jul 2020 08:51:05 +0530 Subject: [PATCH 1/3] Add clone and merge candidates --- src/transformations.jl | 65 +++++++++++++++++++++++++++++++++++- test/transformations_test.jl | 2 +- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/transformations.jl b/src/transformations.jl index 477f70e7..1e4b0667 100644 --- a/src/transformations.jl +++ b/src/transformations.jl @@ -1,5 +1,6 @@ export smooth, forget, propagate_constants, deepcopy, condition, replace_node, - split, clone, merge, split_candidates, random_split, split_step, struct_learn + split, clone, merge, split_candidates, random_split, split_step, struct_learn, + clone_candidates, merge_candidates """ Create an equivalent smooth circuit from the given circuit. @@ -253,6 +254,68 @@ function split_candidates(circuit::Node)::Tuple{Vector{Tuple{Node, Node}}, Dict{ candidates, scope end +function clone_candidates(circuit::Node)::Dict{Node, Vector{Node}} + candidates = Dict{Node, Vector{Node}}() + parents = Dict{Node, Vector{Node}}() + + f_con(n) = begin + false + end + f_lit(n) = begin + false + end + f_a(n, cv) = begin + for c in children(n) + if !(GateType(c) isa ⋁Gate) + continue + end + + if c in keys(parents) + push!(parents[c], n) + else + parents[c] = [n] + end + end + false + end + f_o(n, cv) = begin + if !(n in keys(parents)) + parents[n] = [] + end + true + end + + foldup_aggregate(circuit, f_con, f_lit, f_a, f_o, Bool) + + # Find candidates + candidates = filter(p->(length(last(p)) == 2), parents) # Set of AND gates shared by exactly 2 OR gates + candidates +end + +function merge_candidates(circuit::Node)::Vector{Vector{Node}} + signatures = prob_equiv_signature(circuit, k) + decision_nodes_by_signature = groupby(n -> signatures[n], ⋁_nodes(circuit)) + + candidates = [] + for (prob_base, nodes) in decision_nodes_by_signature + if prob_base == ones(Rational{BigInt}, k) # Tautology case + continue + else + scope_map = groupby(n -> sort(variables(n.vtree)), nodes) + filtered = filter((k, v) -> length(k) > var_thresh && length(v) > 1, scope_map) + top_candidates = Dict(k => sort(v, by=x->length(node2dag(x)), rev=true) for (k,v) in filtered) + + if length(values(top_candidates)) == 0 + continue + end + + # For now pick top two and put them as candidates + push!(candidates, [ns[1:2] for ns in values(top_candidates)]...) + end + end + + candidates +end """ Randomly picking egde and variable from candidates diff --git a/test/transformations_test.jl b/test/transformations_test.jl index 306dfb59..45aa926d 100644 --- a/test/transformations_test.jl +++ b/test/transformations_test.jl @@ -186,4 +186,4 @@ end # TODO # @test isstructdecomposable(c1) # @test isdeterministic(c1) -end \ No newline at end of file +end From e764b0c2dd069fb1295c23bc07a4c441aeb9e105 Mon Sep 17 00:00:00 2001 From: Shreyas Date: Fri, 24 Jul 2020 19:50:51 +0530 Subject: [PATCH 2/3] Added simple test for clone-candidates --- test/transformations_test.jl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/transformations_test.jl b/test/transformations_test.jl index 45aa926d..f0dee17e 100644 --- a/test/transformations_test.jl +++ b/test/transformations_test.jl @@ -187,3 +187,19 @@ end # @test isstructdecomposable(c1) # @test isdeterministic(c1) end + +@testset "Clone Candidates" begin + lit1 = compile(PlainLogicCircuit, Lit(1)) + litn1 = compile(PlainLogicCircuit, - Lit(1)) + lit2 = compile(PlainLogicCircuit, Lit(2)) + litn2 = compile(PlainLogicCircuit, - Lit(2)) + or = lit1 | litn1 + and1 = lit2 & or + and2 = or & litn2 + c1 = root = and1 | and2 + + cands = clone_candidates(c1) + candidates = [(k, v[1], v[2]) for (k,v) in cands] + + @assert (or, and1, and2) in candidates +end From decb569e61b46c6ced9ccccfa5c53b9cab2de02f Mon Sep 17 00:00:00 2001 From: Shreyas Date: Sat, 25 Jul 2020 08:51:03 +0530 Subject: [PATCH 3/3] Remove merge_candidates --- src/transformations.jl | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/src/transformations.jl b/src/transformations.jl index 1e4b0667..fe291a7b 100644 --- a/src/transformations.jl +++ b/src/transformations.jl @@ -1,6 +1,6 @@ export smooth, forget, propagate_constants, deepcopy, condition, replace_node, split, clone, merge, split_candidates, random_split, split_step, struct_learn, - clone_candidates, merge_candidates + clone_candidates """ Create an equivalent smooth circuit from the given circuit. @@ -292,31 +292,6 @@ function clone_candidates(circuit::Node)::Dict{Node, Vector{Node}} candidates end -function merge_candidates(circuit::Node)::Vector{Vector{Node}} - signatures = prob_equiv_signature(circuit, k) - decision_nodes_by_signature = groupby(n -> signatures[n], ⋁_nodes(circuit)) - - candidates = [] - for (prob_base, nodes) in decision_nodes_by_signature - if prob_base == ones(Rational{BigInt}, k) # Tautology case - continue - else - scope_map = groupby(n -> sort(variables(n.vtree)), nodes) - filtered = filter((k, v) -> length(k) > var_thresh && length(v) > 1, scope_map) - top_candidates = Dict(k => sort(v, by=x->length(node2dag(x)), rev=true) for (k,v) in filtered) - - if length(values(top_candidates)) == 0 - continue - end - - # For now pick top two and put them as candidates - push!(candidates, [ns[1:2] for ns in values(top_candidates)]...) - end - end - - candidates -end - """ Randomly picking egde and variable from candidates """