Make symmetry-breaker-exp into a preprocessing pass (#1890)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Wed, 9 May 2018 15:50:55 +0000 (10:50 -0500)
committerGitHub <noreply@github.com>
Wed, 9 May 2018 15:50:55 +0000 (10:50 -0500)
src/preprocessing/passes/symmetry_breaker.cpp
src/preprocessing/passes/symmetry_breaker.h
src/smt/smt_engine.cpp
test/regress/Makefile.tests
test/regress/regress1/sym/sym1.smt2
test/regress/regress1/sym/sym2.smt2
test/regress/regress1/sym/sym3.smt2
test/regress/regress1/sym/sym4.smt2
test/regress/regress1/sym/sym5.smt2
test/regress/regress1/sym/sym6.smt2
test/regress/regress1/sym/sym7-uf.smt2 [new file with mode: 0644]

index 2e8c873cd02d4ae2d1354773a737f2c204efdac4..c6ad09e9128dfd0a7312fbac12c4a6a49551c71c 100644 (file)
@@ -13,6 +13,7 @@
  **/
 
 #include "preprocessing/passes/symmetry_breaker.h"
+#include "preprocessing/passes/symmetry_detect.h"
 
 using namespace std;
 
@@ -47,7 +48,7 @@ Node SymmetryBreaker::generateSymBkConstraints(const vector<vector<Node>>& parts
       {
         for (unsigned int i = 0; i < part.size(); ++i)
         {
-          for (unsigned int j = i + 2; j < part.size(); ++i)
+          for (unsigned int j = i + 2; j < part.size(); ++j)
           {
             // Generate consecutive constraints v_i = v_j => v_i = v_{j-1} for all 0
             // <= i < j-1 < j < part.size()
@@ -100,7 +101,7 @@ Node SymmetryBreaker::generateSymBkConstraints(const vector<vector<Node>>& parts
   {
     return constraints[0];
   }
-  return nm->mkNode(kind::AND, constraints);;
+  return nm->mkNode(kind::AND, constraints);
 }
 
 Kind SymmetryBreaker::getOrderKind(Node node)
@@ -119,6 +120,42 @@ Kind SymmetryBreaker::getOrderKind(Node node)
   }
 }
 
+SymBreakerPass::SymBreakerPass(PreprocessingPassContext* preprocContext)
+    : PreprocessingPass(preprocContext, "sym-break"){};
+
+PreprocessingPassResult SymBreakerPass::applyInternal(
+    AssertionPipeline* assertionsToPreprocess)
+{
+  Trace("sym-break-pass") << "Apply symmetry breaker pass..." << std::endl;
+  // detect symmetries
+  std::vector<std::vector<Node>> part;
+  SymmetryDetect symd;
+  symd.getPartition(part, assertionsToPreprocess->ref());
+  if (Trace.isOn("sym-break-pass"))
+  {
+    Trace("sym-break-pass") << "Detected symmetry partition:" << std::endl;
+    for (const std::vector<Node>& p : part)
+    {
+      Trace("sym-break-pass") << "  " << p << std::endl;
+    }
+  }
+  // construct the symmetry breaking constraint
+  Trace("sym-break-pass") << "Construct symmetry breaking constraint..."
+                          << std::endl;
+  SymmetryBreaker symb;
+  Node sbConstraint = symb.generateSymBkConstraints(part);
+  // add symmetry breaking constraint to the set of assertions
+  Trace("sym-break-pass") << "...got: " << sbConstraint << std::endl;
+  // if not true
+  if (!sbConstraint.isConst())
+  {
+    // add to assertions
+    assertionsToPreprocess->push_back(sbConstraint);
+  }
+
+  return PreprocessingPassResult::NO_CONFLICT;
+}
+
 }  // namespace passes
 }  // namespace preprocessing
 }  // namespace CVC4
index a89f67a613859a222a57257e1d98279e6a9b8eff..898b7a1221acce85f82c52b31ad18a2392638a5d 100644 (file)
@@ -20,6 +20,9 @@
 #include <vector>
 #include "expr/node.h"
 
+#include "preprocessing/preprocessing_pass.h"
+#include "preprocessing/preprocessing_pass_context.h"
+
 namespace CVC4 {
 namespace preprocessing {
 namespace passes {
@@ -84,6 +87,21 @@ class SymmetryBreaker
   Kind getOrderKind(Node node);
 };
 
+/**
+ * This class detects symmetries in the input assertions in the form of a
+ * partition (see symmetry_detect.h), and subsequently adds symmetry breaking
+ * constraints that correspond to this partition, using the above class.
+ */
+class SymBreakerPass : public PreprocessingPass
+{
+ public:
+  SymBreakerPass(PreprocessingPassContext* preprocContext);
+
+ protected:
+  PreprocessingPassResult applyInternal(
+      AssertionPipeline* assertionsToPreprocess) override;
+};
+
 }  // namespace passes
 }  // namespace preprocessing
 }  // namespace CVC4
index 09a495d1ea403bd37ed247a258568bc897feb7a7..c750b8a12be75f1b9f39351fdf31d37a84ed4483 100644 (file)
@@ -2600,6 +2600,8 @@ void SmtEnginePrivate::finishInit() {
       new PseudoBooleanProcessor(d_preprocessingPassContext.get()));
   std::unique_ptr<RealToInt> realToInt(
       new RealToInt(d_preprocessingPassContext.get()));
+  std::unique_ptr<SymBreakerPass> sbProc(
+      new SymBreakerPass(d_preprocessingPassContext.get()));
   d_preprocessingPassRegistry.registerPass("bool-to-bv", std::move(boolToBv));
   d_preprocessingPassRegistry.registerPass("bv-abstraction",
                                            std::move(bvAbstract));
@@ -2611,6 +2613,7 @@ void SmtEnginePrivate::finishInit() {
   d_preprocessingPassRegistry.registerPass("pseudo-boolean-processor",
                                            std::move(pbProc));
   d_preprocessingPassRegistry.registerPass("real-to-int", std::move(realToInt));
+  d_preprocessingPassRegistry.registerPass("sym-break", std::move(sbProc));
 }
 
 Node SmtEnginePrivate::expandDefinitions(TNode n, unordered_map<Node, Node, NodeHashFunction>& cache, bool expandOnly)
@@ -4198,11 +4201,8 @@ void SmtEnginePrivate::processAssertions() {
 
   if (options::symmetryBreakerExp())
   {
-    SymmetryDetect symd;
-    SymmetryBreaker symb;
-    vector<vector<Node>> part;
-    symd.getPartition(part, d_assertions.ref());
-    Node sbConstraint = symb.generateSymBkConstraints(part);
+    // apply symmetry breaking
+    d_preprocessingPassRegistry.getPass("sym-break")->apply(&d_assertions);
   }
 
   dumpAssertions("pre-static-learning", d_assertions);
index b86ee911d2d1d47d902d50ae1711575c8e8a1711..c3de09de2e8fb484f331f3e4c8aa2cb5e11f5774 100644 (file)
@@ -1522,6 +1522,7 @@ REG1_TESTS = \
        regress1/sym/sym4.smt2 \
        regress1/sym/sym5.smt2 \
        regress1/sym/sym6.smt2 \
+       regress1/sym/sym7-uf.smt2 \
        regress1/test12.cvc \
        regress1/trim.cvc \
        regress1/uf2.smt2 \
index ac1c0215f6990d66c4f50ef9052f392bf6058085..c063f8b8f404089958d0365a3cae885279cfdb1c 100644 (file)
@@ -1,4 +1,4 @@
-; COMMAND-LINE: --symmetry-detect
+; COMMAND-LINE: --symmetry-breaker-exp
 (set-logic ALL)
 (set-info :status sat)
 (declare-fun x () Int)
index cff424ba91b47c767e2a5629eb995a55dcdc3bd4..e2e62cbb61ad4f3cfec7aafb2a85cc3a2bc2d5ac 100644 (file)
@@ -1,4 +1,4 @@
-; COMMAND-LINE: --symmetry-detect
+; COMMAND-LINE: --symmetry-breaker-exp
 (set-logic ALL)
 (set-info :status sat)
 (declare-fun x () Int)
index 52f9855c9c541897278ccee2c4bdc4db99cd3f7e..c6b87adebbd26ff8bf323d9fd0539b983d37e630 100644 (file)
@@ -1,4 +1,4 @@
-; COMMAND-LINE: --symmetry-detect
+; COMMAND-LINE: --symmetry-breaker-exp
 (set-logic ALL)
 (set-info :status sat)
 (declare-fun x () Int)
index 5582ef7d0934cb12daf03cc6293239e6938971c7..1cbd6f5b2640051748ce5e8af34d22925939fbd0 100644 (file)
@@ -1,4 +1,4 @@
-; COMMAND-LINE: --symmetry-detect
+; COMMAND-LINE: --symmetry-breaker-exp
 (set-info :smt-lib-version 2.6)
 (set-logic QF_LIA)
 (set-info :category "crafted")
@@ -45,4 +45,4 @@
 (assert (<= (+ (* 59 x_0) (* 59 x_1) (* 59 x_2) (* 59 x_3) (* 59 x_4) (* 59 x_5) (* 59 x_6) (* 59 x_7) (* 59 x_8) (* 59 x_9) (* 59 x_10) (* 59 x_11) (* 59 x_12) (* 59 x_13) (* 59 x_14) (* 59 x_15) (* (- 382) x_16)) 0))
 (assert (>= (+ x_0 x_1 x_2 x_3 x_4 x_5 x_6 x_7 x_8 x_9 x_10 x_11 x_12 x_13 x_14 x_15 x_16) 1))
 (check-sat)
-(exit)
\ No newline at end of file
+(exit)
index f5ef1d003cd2c0655d9f366e0164b74a30fe54a4..6b16d9d355b82ada0766ae3b92258a49b2d2b459 100644 (file)
@@ -1,4 +1,4 @@
-; COMMAND-LINE: --symmetry-detect
+; COMMAND-LINE: --symmetry-breaker-exp
 (set-logic ALL)
 (set-info :status unsat)
 (declare-fun A () (Set Int))
@@ -16,4 +16,4 @@
 (assert (subset B A))
 (assert (= C (intersection A B)))
 (assert (member j C))
-(check-sat)
\ No newline at end of file
+(check-sat)
index 3da6b4cb4517790854204cbcf94839e7a17741fc..10218ebc961342835d09304baa2db81b703f70d8 100644 (file)
@@ -1,4 +1,4 @@
-; COMMAND-LINE: --symmetry-detect
+; COMMAND-LINE: --symmetry-breaker-exp
 (set-logic ALL)
 (set-info :status sat)
 (declare-fun x () Int)
diff --git a/test/regress/regress1/sym/sym7-uf.smt2 b/test/regress/regress1/sym/sym7-uf.smt2
new file mode 100644 (file)
index 0000000..ee91240
--- /dev/null
@@ -0,0 +1,20 @@
+; COMMAND-LINE: --symmetry-breaker-exp
+(set-logic ALL)
+(set-info :status sat)
+(declare-sort U 0)
+(declare-fun x () U)
+(declare-fun y () U)
+(declare-fun z () U)
+(declare-fun w () U)
+(declare-fun u () U)
+(declare-fun v () U)
+(declare-fun a () U)
+(declare-fun P (U) Bool)
+
+(assert (distinct w u v a))
+(assert (or (= x y) (= x z) (= y z)))
+(assert (or (P x) (P y) (P z) (P w)))
+
+; should get { x, y, z }, { w }, { u, v, a }
+(check-sat)
+