[unconstrained] Fix gathering of visited-once vars (#4652)
authorAndres Noetzli <andres.noetzli@gmail.com>
Wed, 24 Jun 2020 17:41:03 +0000 (10:41 -0700)
committerGitHub <noreply@github.com>
Wed, 24 Jun 2020 17:41:03 +0000 (12:41 -0500)
Fixes #4644. This commit fixes an issue where the set `d_unconstrained`
in the unconstrained simplification pass was not computed correctly. The
problem was that visiting the same term multiple times did not remove
the variables appearing in that term from the visited-once set. A simple
example that triggers the issue is the following:

```
(set-logic ALL)
(declare-fun a () Bool)
(declare-fun b () Bool)
(assert (not (= a b)))
(assert (= a (= a b)))
(check-sat)
```

After running `UnconstrainedSimplifier::visitAll()` on both assertions,
we end up with `[b]` as our `d_unconstrained` set. We end up inferring
the substitution `(= a b) --> b` and get `(not b)` and `b`, which is
unsat even though the original problem is sat.

This commit fixes the issue by visiting all the children of a node if we
visit a node for a second time. This makes sure that we remove any
children from the visisted-once set.

src/preprocessing/passes/unconstrained_simplifier.cpp
test/regress/CMakeLists.txt
test/regress/regress0/unconstrained/issue4644.smt2 [new file with mode: 0644]

index e20403d2a2930b3e7e9d735fa76d2fb519f8fb55..7d1f66d65e758053bb47da5bc8617d36356066f5 100644 (file)
@@ -75,6 +75,16 @@ void UnconstrainedSimplifier::visitAll(TNode assertion)
         {
           d_unconstrained.erase(current);
         }
+        else
+        {
+          // Also erase the children from the visited-once set when we visit a
+          // node a second time, otherwise variables in this node are not
+          // erased from the set of unconstrained variables.
+          for (TNode childNode : current)
+          {
+            toVisit.push_back(unc_preprocess_stack_element(childNode, current));
+          }
+        }
       }
       ++find->second;
       continue;
index bb0f311d138edc53255ae3d4cab06d1a5fa47655..7863c5ec0606843b5b425193edee00a72d9175cb 100644 (file)
@@ -1178,6 +1178,7 @@ set(regress_0_tests
   regress0/unconstrained/bvult5.smt2
   regress0/unconstrained/geq.smt2
   regress0/unconstrained/gt.smt2
+  regress0/unconstrained/issue4644.smt2
   regress0/unconstrained/ite.smt2
   regress0/unconstrained/leq.smt2
   regress0/unconstrained/lt.smt2
diff --git a/test/regress/regress0/unconstrained/issue4644.smt2 b/test/regress/regress0/unconstrained/issue4644.smt2
new file mode 100644 (file)
index 0000000..aeb2bfc
--- /dev/null
@@ -0,0 +1,9 @@
+; COMMAND-LINE: --unconstrained-simp
+(set-logic ALL)
+(declare-fun a () Bool)
+(declare-fun b () Bool)
+(declare-fun c () Bool)
+(assert (distinct a c))
+(assert (= a b (= b c)))
+(set-info :status sat)
+(check-sat)