added rules for join and transpose operators
authorPaulMeng <baolmeng@gmail.com>
Wed, 17 Feb 2016 21:01:40 +0000 (15:01 -0600)
committerPaulMeng <baolmeng@gmail.com>
Wed, 17 Feb 2016 21:01:40 +0000 (15:01 -0600)
added more benchmarks

17 files changed:
src/theory/sets/theory_sets_private.cpp
src/theory/sets/theory_sets_rels.cpp
src/theory/sets/theory_sets_rels.h
src/theory/sets/theory_sets_type_rules.h
test/regress/regress0/sets/Makefile.am
test/regress/regress0/sets/rels/rel.cvc [deleted file]
test/regress/regress0/sets/rels/rel_join.cvc [new file with mode: 0644]
test/regress/regress0/sets/rels/rel_join_0.cvc [new file with mode: 0644]
test/regress/regress0/sets/rels/rel_join_0_1.cvc [new file with mode: 0644]
test/regress/regress0/sets/rels/rel_join_1.cvc [new file with mode: 0644]
test/regress/regress0/sets/rels/rel_join_1_1.cvc [new file with mode: 0644]
test/regress/regress0/sets/rels/rel_join_2.cvc [new file with mode: 0644]
test/regress/regress0/sets/rels/rel_join_2_1.cvc [new file with mode: 0644]
test/regress/regress0/sets/rels/rel_transpose.cvc [new file with mode: 0644]
test/regress/regress0/sets/rels/rel_transpose_0.cvc [new file with mode: 0644]
test/regress/regress0/sets/rels/rel_transpose_1.cvc [new file with mode: 0644]
test/regress/regress0/sets/rels/rel_transpose_1_1.cvc [new file with mode: 0644]

index 9d3f7e08e45fc374a1a25b3fba4dfbb08cc0f78f..5e328b4fdf9ec4f5fddeede2f8a72f07a76e55bf 100644 (file)
@@ -1111,7 +1111,7 @@ TheorySetsPrivate::TheorySetsPrivate(TheorySets& external,
   d_rels(NULL)
 {
   d_termInfoManager = new TermInfoManager(*this, c, &d_equalityEngine);
-  d_rels = new TheorySetsRels(c, u, &d_equalityEngine);
+  d_rels = new TheorySetsRels(c, u, &d_equalityEngine, &d_conflict);
 
   d_equalityEngine.addFunctionKind(kind::UNION);
   d_equalityEngine.addFunctionKind(kind::INTERSECTION);
index 24a69bfdb031db5247b73118f2ac1248c4be017c..fcab5b5ca461f0e5687247f87caca93016480388 100644 (file)
@@ -35,10 +35,12 @@ namespace sets {
 
   TheorySetsRels::TheorySetsRels(context::Context* c,
                                  context::UserContext* u,
-                                 eq::EqualityEngine* eq):
+                                 eq::EqualityEngine* eq,
+                                 context::CDO<bool>* conflict):
     d_trueNode(NodeManager::currentNM()->mkConst<bool>(true)),
     d_falseNode(NodeManager::currentNM()->mkConst<bool>(false)),
     d_eqEngine(eq),
+    d_conflict(conflict),
     d_relsSaver(c)
   {
     d_eqEngine->addFunctionKind(kind::PRODUCT);
@@ -59,10 +61,8 @@ namespace sets {
 
     while( !eqcs_i.isFinished() ){
       TNode r = (*eqcs_i);
-      bool firstTime = true;
-      Debug("rels-eqc") << "  " << r;
-      Debug("rels-eqc") << " : { ";
       eq::EqClassIterator eqc_i = eq::EqClassIterator( r, d_eqEngine );
+
       while( !eqc_i.isFinished() ){
         TNode n = (*eqc_i);
 
@@ -70,53 +70,186 @@ namespace sets {
         if((d_eqEngine->getRepresentative(r) == d_eqEngine->getRepresentative(d_trueNode)
               || d_eqEngine->getRepresentative(r) == d_eqEngine->getRepresentative(d_falseNode))
             && !d_relsSaver.contains(n)) {
-          d_relsSaver.insert(n);
 
-          // case: (b, a) IS_IN (TRANSPOSE X)
-          //    => (a, b) IS_IN X
+          // case: [NOT] (b, a) IS_IN (TRANSPOSE X)
+          //    => [NOT] (a, b) IS_IN X
           if(n.getKind() == kind::MEMBER) {
+            d_relsSaver.insert(n);
             if(kind::TRANSPOSE == n[1].getKind()) {
               Node reversedTuple = reverseTuple(n[0]);
               Node fact = NodeManager::currentNM()->mkNode(kind::MEMBER, reversedTuple, n[1][0]);
-//              assertMembership(fact, n, r == d_trueNode);
+              Node exp = n;
+              if(d_eqEngine->getRepresentative(r) == d_eqEngine->getRepresentative(d_falseNode)) {
+                fact = fact.negate();
+                exp = n.negate();
+              }
+              d_pending_facts[fact] = exp;
             } else if(kind::JOIN == n[1].getKind()) {
-
+              TNode r1 = n[1][0];
+              TNode r2 = n[1][1];
+              // Need to do this efficiently... Join relations after collecting all of them
+              // So that we would just need to iterate over EE once
+              joinRelations(r1, r2, n[1].getType().getSetElementType());
+
+              // case: (a, b) IS_IN (X JOIN Y)
+              //      => (a, z) IS_IN X  && (z, b) IS_IN Y
+              if(d_eqEngine->getRepresentative(r) == d_eqEngine->getRepresentative(d_trueNode)) {
+                Debug("rels-join") << "Join rules (a, b) IS_IN (X JOIN Y) => ((a, z) IS_IN X  && (z, b) IS_IN Y)"<< std::endl;
+                Assert((r1.getType().getSetElementType()).isDatatype());
+                Assert((r2.getType().getSetElementType()).isDatatype());
+
+                unsigned int i = 0;
+                std::vector<Node> r1_tuple;
+                std::vector<Node> r2_tuple;
+                Node::iterator child_it = n[0].begin();
+                unsigned int s1_len = r1.getType().getSetElementType().getTupleLength();
+                Node shared_x = NodeManager::currentNM()->mkSkolem("sde_", r2.getType().getSetElementType().getTupleTypes()[0]);
+                Datatype dt = r1.getType().getSetElementType().getDatatype();
+
+                r1_tuple.push_back(Node::fromExpr(dt[0].getConstructor()));
+                for(; i < s1_len-1; ++child_it) {
+                  r1_tuple.push_back(*child_it);
+                  ++i;
+                }
+                r1_tuple.push_back(shared_x);
+                dt = r2.getType().getSetElementType().getDatatype();
+                r2_tuple.push_back(Node::fromExpr(dt[0].getConstructor()));
+                r2_tuple.push_back(shared_x);
+                for(; child_it != n[0].end(); ++child_it) {
+                  r2_tuple.push_back(*child_it);
+                }
+                Node t1 = NodeManager::currentNM()->mkNode(kind::APPLY_CONSTRUCTOR, r1_tuple);
+                Node t2 = NodeManager::currentNM()->mkNode(kind::APPLY_CONSTRUCTOR, r2_tuple);
+                Node f1 = NodeManager::currentNM()->mkNode(kind::MEMBER, t1, r1);
+                Node f2 = NodeManager::currentNM()->mkNode(kind::MEMBER, t2, r2);
+                d_pending_facts[f1] = n;
+                d_pending_facts[f2] = n;
+              }
             }else if(kind::PRODUCT == n[1].getKind()) {
 
             }
           }
         }
+        ++eqc_i;
+      }
+      ++eqcs_i;
+    }
+    doPendingFacts();
+  }
 
-        if( r!=n ){
-          if( firstTime ){
-            Debug("rels-eqc") << std::endl;
-            firstTime = false;
-          }
-          if (n.getKind() == kind::PRODUCT ||
-              n.getKind() == kind::JOIN ||
-              n.getKind() == kind::TRANSCLOSURE ||
-              n.getKind() == kind::TRANSPOSE) {
-            Debug("rels-eqc") << "    *** " << n << std::endl;
-          }else{
-            Debug("rels-eqc") << "    " << n <<std::endl;
+  // Join all explicitly specified tuples in r1, r2
+  // e.g. If (a, b) in X and (b, c) in Y, (a, c) in (X JOIN Y)
+  void TheorySetsRels::joinRelations(TNode r1, TNode r2, TypeNode tn) {
+    if (!d_eqEngine->consistent())
+          return;
+    Debug("rels-join") << "start joining tuples in "
+                       << r1 << " and " << r2 << std::endl;
+
+    std::vector<Node> r1_elements;
+    std::vector<Node> r2_elements;
+    eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( d_eqEngine );
+
+    // collect all tuples that are in r1, r2
+    while( !eqcs_i.isFinished() ){
+      TNode r = (*eqcs_i);
+      eq::EqClassIterator eqc_i = eq::EqClassIterator( r, d_eqEngine );
+      while( !eqc_i.isFinished() ){
+        TNode n = (*eqc_i);
+        if(d_eqEngine->getRepresentative(r) == d_eqEngine->getRepresentative(d_trueNode)
+            && n.getKind() == kind::MEMBER && n[0].getType().isTuple()) {
+          if(n[1] == r1) {
+            Debug("rels-join") << "r1 tuple: " << n[0] << std::endl;
+            r1_elements.push_back(n[0]);
+          } else if (n[1] == r2) {
+            Debug("rels-join") << "r2 tuple: " << n[0] << std::endl;
+            r2_elements.push_back(n[0]);
           }
         }
         ++eqc_i;
       }
-      if( !firstTime ){ Debug("rels-eqc") << "  "; }
-      Debug("rels-eqc") << "}" << std::endl;
       ++eqcs_i;
     }
+    if(r1_elements.size() == 0 || r2_elements.size() == 0)
+      return;
+
+    // Join r1 and r2
+    joinTuples(r1, r2, r1_elements, r2_elements, tn);
+
   }
 
+  void TheorySetsRels::joinTuples(TNode r1, TNode r2, std::vector<Node>& r1_elements, std::vector<Node>& r2_elements, TypeNode tn) {
+    Datatype dt = tn.getDatatype();
+    unsigned int t1_len = r1_elements.front().getType().getTupleLength();
+    unsigned int t2_len = r2_elements.front().getType().getTupleLength();
+
+    for(unsigned int i = 0; i < r1_elements.size(); i++) {
+      for(unsigned int j = 0; j < r2_elements.size(); j++) {
+        if(r1_elements[i][t1_len-1] == r2_elements[j][0]) {
+          std::vector<Node> joinedTuple;
+          joinedTuple.push_back(Node::fromExpr(dt[0].getConstructor()));
+          for(unsigned int k = 0; k < t1_len - 1; ++k) {
+            joinedTuple.push_back(r1_elements[i][k]);
+          }
+          for(unsigned int l = 1; l < t2_len; ++l) {
+            joinedTuple.push_back(r2_elements[j][l]);
+          }
+          Node fact = NodeManager::currentNM()->mkNode(kind::APPLY_CONSTRUCTOR, joinedTuple);
+          fact = NodeManager::currentNM()->mkNode(kind::MEMBER, fact, NodeManager::currentNM()->mkNode(kind::JOIN, r1, r2));
+          Node reason = NodeManager::currentNM()->mkNode(kind::AND,
+                                                         NodeManager::currentNM()->mkNode(kind::MEMBER, r1_elements[i], r1),
+                                                         NodeManager::currentNM()->mkNode(kind::MEMBER, r2_elements[j], r2));
+          Debug("rels-join") << "join tuples: " << r1_elements[i]
+                             << " and " << r2_elements[j]
+                             << "\nnew fact: " << fact
+                             << "\nreason: " << reason<< std::endl;
+          d_pending_facts[fact] = reason;
+        }
+      }
+    }
+  }
+
+
+  void TheorySetsRels::sendLemma(TNode fact, TNode reason, bool polarity) {
+
+  }
+
+  void TheorySetsRels::doPendingFacts() {
+    std::map<Node, Node>::iterator map_it = d_pending_facts.begin();
+    while( !(*d_conflict) && map_it != d_pending_facts.end()) {
+
+      Node fact = map_it->first;
+      Node exp = d_pending_facts[ fact ];
+      Debug("rels") << "sending out pending fact: " << fact
+                    << "  reason: " << exp
+                    << std::endl;
+      if(fact.getKind() == kind::AND) {
+        for(size_t j=0; j<fact.getNumChildren(); j++) {
+          bool polarity = fact[j].getKind() != kind::NOT;
+          TNode atom = polarity ? fact[j] : fact[j][0];
+          assertMembership(atom, exp, polarity);
+        }
+      } else {
+        bool polarity = fact.getKind() != kind::NOT;
+        TNode atom = polarity ? fact : fact[0];
+        assertMembership(atom, exp, polarity);
+      }
+      map_it++;
+    }
+    d_pending_facts.clear();
+  }
+
+
+
   Node TheorySetsRels::reverseTuple(TNode tuple) {
-    // need to register the newly created tuple?
-    Assert(tuple.getType().isDatatype());
+    Assert(tuple.getType().isTuple());
 
     std::vector<Node> elements;
-    Datatype dt = (Datatype)((tuple.getType()).getDatatype());
+    std::vector<TypeNode> tuple_types = tuple.getType().getTupleTypes();
+    std::reverse(tuple_types.begin(), tuple_types.end());
+    TypeNode tn = NodeManager::currentNM()->mkTupleType(tuple_types);
+    Datatype dt = tn.getDatatype();
 
-    elements.push_back(tuple.getOperator());
+    elements.push_back(Node::fromExpr(dt[0].getConstructor()));
     for(Node::iterator child_it = tuple.end()-1;
               child_it != tuple.begin()-1; --child_it) {
       elements.push_back(*child_it);
@@ -125,12 +258,10 @@ namespace sets {
   }
 
   void TheorySetsRels::assertMembership(TNode fact, TNode reason, bool polarity) {
-    TNode explain = reason;
-    if(!polarity) {
-      explain = reason.negate();
-    }
-    Debug("rels") << " polarity : " << polarity << " reason: " << explain << std::endl;
-    d_eqEngine->assertPredicate(fact, polarity, explain);
+    Debug("rels") << "fact: " << fact
+                  << "\npolarity : " << polarity
+                  << "\nreason: " << reason << std::endl;
+    d_eqEngine->assertPredicate(fact, polarity, reason);
   }
 }
 }
index c482172752d726c2e4d56c3a2db57417b78ebbc3..537fc2d430d6fd6addc237e761bfb5706731c5a9 100644 (file)
@@ -30,7 +30,8 @@ class TheorySetsRels {
 public:
   TheorySetsRels(context::Context* c,
                  context::UserContext* u,
-                 eq::EqualityEngine*);
+                 eq::EqualityEngine*,
+                 context::CDO<bool>* );
 
   ~TheorySetsRels();
 
@@ -42,14 +43,31 @@ private:
   Node d_trueNode;
   Node d_falseNode;
 
+  // Facts and lemmas to be sent to EE
+  std::map< Node, Node> d_pending_facts;
+  std::vector< Node > d_lemma_cache;
+
+  // Relation pairs to be joined
+//  std::map<TNode, TNode> d_rel_pairs;
+//  std::hash_set<TNode> d_rels;
+
   eq::EqualityEngine *d_eqEngine;
+  context::CDO<bool> *d_conflict;
 
   // save all the relational terms seen so far
   context::CDHashSet <Node, NodeHashFunction> d_relsSaver;
 
   void assertMembership(TNode fact, TNode reason, bool polarity);
 
-  Node reverseTuple(TNode tuple);
+  void joinRelations(TNode, TNode, TypeNode);
+  void joinTuples(TNode, TNode, std::vector<Node>&, std::vector<Node>&, TypeNode tn);
+
+  Node reverseTuple(TNode);
+
+  void sendLemma(TNode fact, TNode reason, bool polarity);
+  void doPendingLemmas();
+  void doPendingFacts();
+
 };
 
 }/* CVC4::theory::sets namespace */
index 8d294ceeb89cb9a3a19448015261247e514f86dd..0909d844284e56c59a597186f91a9220c41cf9e1 100644 (file)
@@ -209,8 +209,6 @@ struct RelBinaryOperatorTypeRule {
       }
       resultType = nodeManager->mkSetType(nodeManager->mkTupleType(newTupleTypes));
     }
-
-    Debug("rels") << "The resulting Type is " << resultType << std::endl;
     return resultType;
   }
 
@@ -263,7 +261,7 @@ struct RelTransClosureTypeRule {
 
   inline static bool computeIsConst(NodeManager* nodeManager, TNode n) {
       Assert(n.getKind() == kind::TRANSCLOSURE);
-      return true;
+      return false;
     }
 };/* struct RelTransClosureTypeRule */
 
index d694d553bbaf892d941c71910dd89db21358709e..5069d061ef0e3d0fed14186bf93662db209f9c2b 100644 (file)
@@ -39,7 +39,6 @@ TESTS =       \
        mar2014/smaller.smt2 \
        mar2014/UniqueZipper.hs.1030minimized2.cvc4.smt2 \
        mar2014/UniqueZipper.hs.1030minimized.cvc4.smt2 \
-       rels/rel.cvc \
        copy_check_heap_access_33_4.smt2 \
        cvc-sample.cvc \
        emptyset.smt2 \
@@ -84,4 +83,4 @@ regress regress0 test: check
 
 # do nothing in this subdir
 .PHONY: regress1 regress2 regress3
-regress1 regress2 regress3:
+regress1 regress2 regress3:
\ No newline at end of file
diff --git a/test/regress/regress0/sets/rels/rel.cvc b/test/regress/regress0/sets/rels/rel.cvc
deleted file mode 100644 (file)
index 27eb43b..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-% EXPECT: sat
-OPTION "logic" "ALL_SUPPORTED";
-IntPair: TYPE = [INT, INT];
-x : SET OF IntPair;
-y : SET OF IntPair;
-z : SET OF IntPair;
-m: SET OF INT;
-a: IntPair;
-b: INT;
-
-ASSERT a IS_IN (y JOIN z);
-ASSERT (y PRODUCT x) = (y PRODUCT z);
-ASSERT x = ((y JOIN z) JOIN x);
-
-ASSERT x = y | z;
-ASSERT x = y & z;
-ASSERT y = y - z;
-ASSERT z = (TRANSPOSE z);
-ASSERT z = x | y;
-CHECKSAT TRUE;
diff --git a/test/regress/regress0/sets/rels/rel_join.cvc b/test/regress/regress0/sets/rels/rel_join.cvc
new file mode 100644 (file)
index 0000000..7cce736
--- /dev/null
@@ -0,0 +1,26 @@
+% EXPECT: unsat
+OPTION "logic" "ALL_SUPPORTED";
+IntPair: TYPE = [INT, INT];
+x : SET OF IntPair;
+y : SET OF IntPair;
+r : SET OF IntPair;
+
+z : IntPair;
+ASSERT z = (1,2);
+zt : IntPair;
+ASSERT zt = (2,1);
+v : IntPair;
+ASSERT v = (1,1);
+a : IntPair;
+ASSERT a = (1,5);
+
+ASSERT (1, 7) IS_IN x;
+ASSERT (7, 5) IS_IN y;
+
+ASSERT z IS_IN x;
+ASSERT zt IS_IN y;
+%ASSERT a IS_IN (x JOIN y);
+%ASSERT NOT (v IS_IN (x JOIN y));
+ASSERT NOT (a IS_IN (x JOIN y));
+
+CHECKSAT;
diff --git a/test/regress/regress0/sets/rels/rel_join_0.cvc b/test/regress/regress0/sets/rels/rel_join_0.cvc
new file mode 100644 (file)
index 0000000..a251218
--- /dev/null
@@ -0,0 +1,25 @@
+OPTION "logic" "ALL_SUPPORTED";
+IntPair: TYPE = [INT, INT];
+x : SET OF IntPair;
+y : SET OF IntPair;
+r : SET OF IntPair;
+
+z : IntPair;
+ASSERT z = (1,2);
+zt : IntPair;
+ASSERT zt = (2,1);
+v : IntPair;
+ASSERT v = (1,1);
+a : IntPair;
+ASSERT a = (1,5);
+
+ASSERT (1, 7) IS_IN x;
+ASSERT (7, 5) IS_IN y;
+
+ASSERT z IS_IN x;
+ASSERT zt IS_IN y;
+%ASSERT a IS_IN (x JOIN y);
+%ASSERT NOT (v IS_IN (x JOIN y));
+ASSERT NOT (a IS_IN (x JOIN y));
+
+CHECKSAT;
diff --git a/test/regress/regress0/sets/rels/rel_join_0_1.cvc b/test/regress/regress0/sets/rels/rel_join_0_1.cvc
new file mode 100644 (file)
index 0000000..70e3516
--- /dev/null
@@ -0,0 +1,26 @@
+% EXPECT: sat
+OPTION "logic" "ALL_SUPPORTED";
+IntPair: TYPE = [INT, INT];
+x : SET OF IntPair;
+y : SET OF IntPair;
+r : SET OF IntPair;
+
+z : IntPair;
+ASSERT z = (1,2);
+zt : IntPair;
+ASSERT zt = (2,1);
+v : IntPair;
+ASSERT v = (1,1);
+a : IntPair;
+ASSERT a = (1,5);
+
+ASSERT (1, 7) IS_IN x;
+ASSERT (7, 5) IS_IN y;
+
+ASSERT z IS_IN x;
+ASSERT zt IS_IN y;
+%ASSERT a IS_IN (x JOIN y);
+%ASSERT NOT (v IS_IN (x JOIN y));
+ASSERT a IS_IN (x JOIN y);
+
+CHECKSAT;
diff --git a/test/regress/regress0/sets/rels/rel_join_1.cvc b/test/regress/regress0/sets/rels/rel_join_1.cvc
new file mode 100644 (file)
index 0000000..c8921af
--- /dev/null
@@ -0,0 +1,31 @@
+% EXPECT: unsat
+OPTION "logic" "ALL_SUPPORTED";
+IntPair: TYPE = [INT, INT];
+x : SET OF IntPair;
+y : SET OF IntPair;
+r : SET OF IntPair;
+
+z : IntPair;
+ASSERT z = (1,2);
+zt : IntPair;
+ASSERT zt = (2,1);
+v : IntPair;
+ASSERT v = (1,1);
+a : IntPair;
+ASSERT a = (1,5);
+
+ASSERT (1, 7) IS_IN x;
+ASSERT (2, 3) IS_IN x;
+ASSERT (3, 4) IS_IN x;
+
+ASSERT (7, 5) IS_IN y;
+ASSERT (7, 3) IS_IN y;
+ASSERT (4, 7) IS_IN y;
+
+%ASSERT (a IS_IN (r JOIN(x JOIN y)));
+
+ASSERT z IS_IN x;
+ASSERT zt IS_IN y;
+ASSERT NOT (a IS_IN (x JOIN y));
+
+CHECKSAT;
diff --git a/test/regress/regress0/sets/rels/rel_join_1_1.cvc b/test/regress/regress0/sets/rels/rel_join_1_1.cvc
new file mode 100644 (file)
index 0000000..3436bd7
--- /dev/null
@@ -0,0 +1,31 @@
+% EXPECT: sat
+OPTION "logic" "ALL_SUPPORTED";
+IntPair: TYPE = [INT, INT];
+x : SET OF IntPair;
+y : SET OF IntPair;
+r : SET OF IntPair;
+
+z : IntPair;
+ASSERT z = (1,2);
+zt : IntPair;
+ASSERT zt = (2,1);
+v : IntPair;
+ASSERT v = (1,1);
+a : IntPair;
+ASSERT a = (1,5);
+
+ASSERT (1, 7) IS_IN x;
+ASSERT (2, 3) IS_IN x;
+ASSERT (3, 4) IS_IN x;
+
+ASSERT (7, 5) IS_IN y;
+ASSERT (7, 3) IS_IN y;
+ASSERT (4, 7) IS_IN y;
+
+%ASSERT (a IS_IN (r JOIN(x JOIN y)));
+
+ASSERT z IS_IN x;
+ASSERT zt IS_IN y;
+ASSERT a IS_IN (x JOIN y);
+
+CHECKSAT;
diff --git a/test/regress/regress0/sets/rels/rel_join_2.cvc b/test/regress/regress0/sets/rels/rel_join_2.cvc
new file mode 100644 (file)
index 0000000..cac7ce8
--- /dev/null
@@ -0,0 +1,20 @@
+% EXPECT: unsat
+OPTION "logic" "ALL_SUPPORTED";
+IntPair: TYPE = [INT, INT];
+IntTup: TYPE = [INT, INT, INT];
+x : SET OF IntPair;
+y : SET OF IntTup;
+
+z : IntPair;
+ASSERT z = (1,2);
+zt : IntTup;
+ASSERT zt = (2,1,3);
+a : IntTup;
+ASSERT a = (1,1,3);
+
+ASSERT z IS_IN x;
+ASSERT zt IS_IN y;
+
+ASSERT NOT (a IS_IN (x JOIN y));
+
+CHECKSAT;
diff --git a/test/regress/regress0/sets/rels/rel_join_2_1.cvc b/test/regress/regress0/sets/rels/rel_join_2_1.cvc
new file mode 100644 (file)
index 0000000..3e27b9c
--- /dev/null
@@ -0,0 +1,20 @@
+% EXPECT: sat
+OPTION "logic" "ALL_SUPPORTED";
+IntPair: TYPE = [INT, INT];
+IntTup: TYPE = [INT, INT, INT];
+x : SET OF IntPair;
+y : SET OF IntTup;
+
+z : IntPair;
+ASSERT z = (1,2);
+zt : IntTup;
+ASSERT zt = (2,1,3);
+a : IntTup;
+ASSERT a = (1,1,3);
+
+ASSERT z IS_IN x;
+ASSERT zt IS_IN y;
+
+ASSERT a IS_IN (x JOIN y);
+
+CHECKSAT;
diff --git a/test/regress/regress0/sets/rels/rel_transpose.cvc b/test/regress/regress0/sets/rels/rel_transpose.cvc
new file mode 100644 (file)
index 0000000..10644d7
--- /dev/null
@@ -0,0 +1,12 @@
+% EXPECT: unsat
+OPTION "logic" "ALL_SUPPORTED";
+IntPair: TYPE = [INT, INT];
+x : SET OF IntPair;
+y : SET OF IntPair;
+z : IntPair;
+ASSERT z = (1,2);
+zt : IntPair;
+ASSERT zt = (2,1);
+ASSERT z IS_IN x;
+ASSERT NOT (zt IS_IN (TRANSPOSE x));
+CHECKSAT;
diff --git a/test/regress/regress0/sets/rels/rel_transpose_0.cvc b/test/regress/regress0/sets/rels/rel_transpose_0.cvc
new file mode 100644 (file)
index 0000000..d06528f
--- /dev/null
@@ -0,0 +1,14 @@
+OPTION "logic" "ALL_SUPPORTED";
+IntPair: TYPE = [INT, INT];
+x : SET OF IntPair;
+y : SET OF IntPair;
+
+z : IntPair;
+ASSERT z = (1,2);
+zt : IntPair;
+ASSERT zt = (2,1);
+
+ASSERT z IS_IN x;
+ASSERT NOT (zt IS_IN (TRANSPOSE x));
+
+CHECKSAT;
diff --git a/test/regress/regress0/sets/rels/rel_transpose_1.cvc b/test/regress/regress0/sets/rels/rel_transpose_1.cvc
new file mode 100644 (file)
index 0000000..bdcf31b
--- /dev/null
@@ -0,0 +1,12 @@
+% EXPECT: unsat
+OPTION "logic" "ALL_SUPPORTED";
+IntTup: TYPE = [INT, INT, INT];
+x : SET OF IntTup;
+y : SET OF IntTup;
+z : IntTup;
+ASSERT z = (1,2,3);
+zt : IntTup;
+ASSERT zt = (3,2,1);
+ASSERT z IS_IN x;
+ASSERT NOT (zt IS_IN (TRANSPOSE x));
+CHECKSAT;
diff --git a/test/regress/regress0/sets/rels/rel_transpose_1_1.cvc b/test/regress/regress0/sets/rels/rel_transpose_1_1.cvc
new file mode 100644 (file)
index 0000000..11653de
--- /dev/null
@@ -0,0 +1,12 @@
+% EXPECT: sat
+OPTION "logic" "ALL_SUPPORTED";
+IntTup: TYPE = [INT, INT, INT];
+x : SET OF IntTup;
+y : SET OF IntTup;
+z : IntTup;
+ASSERT z = (1,2,3);
+zt : IntTup;
+ASSERT zt = (3,2,1);
+ASSERT z IS_IN x;
+ASSERT zt IS_IN (TRANSPOSE x);
+CHECKSAT;