summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>2020-09-16 14:55:16 -0500
committerGitHub <noreply@github.com>2020-09-16 14:55:16 -0500
commit3fb8d4e50fa64ca416c3633bdbce77f94329ea25 (patch)
tree3dc2c6217ad53dbf6a6fe889bb51b495a2a44e81 /src
parentfad31c95dfaa94c4552aed61206aae9ac7658da5 (diff)
parent2c2f05c96e021006275a2bc70b9ede70b280616d (diff)
Merge branch 'master' into fixIssue5074fixIssue5074
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/expr/CMakeLists.txt2
-rw-r--r--src/expr/lazy_proof_chain.cpp239
-rw-r--r--src/expr/lazy_proof_chain.h135
-rw-r--r--src/expr/proof_node_algorithm.cpp28
-rw-r--r--src/expr/proof_node_algorithm.h5
-rw-r--r--src/expr/proof_node_manager.cpp11
-rw-r--r--src/expr/proof_rule.cpp4
-rw-r--r--src/expr/proof_rule.h39
-rw-r--r--src/main/command_executor.h3
-rw-r--r--src/main/main.cpp1
-rw-r--r--src/parser/antlr_input.cpp1
-rw-r--r--src/parser/cvc/cvc.cpp1
-rw-r--r--src/parser/cvc/cvc.h1
-rw-r--r--src/parser/input.cpp1
-rw-r--r--src/parser/smt2/smt2.h2
-rw-r--r--src/parser/tptp/tptp.cpp1
-rw-r--r--src/parser/tptp/tptp.h3
-rw-r--r--src/preprocessing/passes/bv_to_int.cpp70
-rw-r--r--src/preprocessing/passes/bv_to_int.h5
-rw-r--r--src/preprocessing/preprocessing_pass.cpp10
-rw-r--r--src/printer/ast/ast_printer.cpp75
-rw-r--r--src/printer/cvc/cvc_printer.cpp68
-rw-r--r--src/printer/smt2/smt2_printer.cpp95
-rw-r--r--src/proof/unsat_core.cpp1
-rw-r--r--src/prop/cnf_stream.cpp37
-rw-r--r--src/prop/cnf_stream.h17
-rw-r--r--src/prop/minisat/core/Solver.cc3
-rw-r--r--src/prop/minisat/core/Solver.h4
-rw-r--r--src/prop/prop_engine.cpp9
-rw-r--r--src/prop/prop_engine.h6
-rw-r--r--src/prop/theory_proxy.cpp7
-rw-r--r--src/prop/theory_proxy.h3
-rw-r--r--src/smt/command.cpp16
-rw-r--r--src/smt/dump.cpp100
-rw-r--r--src/smt/dump.h22
-rw-r--r--src/smt/dump_manager.cpp12
-rw-r--r--src/smt/dump_manager.h4
-rw-r--r--src/smt/listeners.cpp12
-rw-r--r--src/smt/listeners.h5
-rw-r--r--src/smt/output_manager.cpp35
-rw-r--r--src/smt/output_manager.h57
-rw-r--r--src/smt/preprocessor.cpp6
-rw-r--r--src/smt/process_assertions.cpp5
-rw-r--r--src/smt/smt_engine.cpp188
-rw-r--r--src/smt/smt_engine.h15
-rw-r--r--src/smt/smt_solver.cpp17
-rw-r--r--src/smt/sygus_solver.cpp15
-rw-r--r--src/smt/sygus_solver.h10
-rw-r--r--src/smt/term_formula_removal.h1
-rw-r--r--src/theory/arith/theory_arith.cpp59
-rw-r--r--src/theory/arith/theory_arith.h19
-rw-r--r--src/theory/arith/theory_arith_private.cpp57
-rw-r--r--src/theory/arith/theory_arith_private.h14
-rw-r--r--src/theory/arrays/theory_arrays.cpp1
-rw-r--r--src/theory/booleans/proof_checker.cpp137
-rw-r--r--src/theory/bv/abstraction.cpp32
-rw-r--r--src/theory/bv/bitblast/eager_bitblaster.cpp2
-rw-r--r--src/theory/bv/bitblast/lazy_bitblaster.cpp9
-rw-r--r--src/theory/bv/bv_subtheory_algebraic.cpp35
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules.h15
-rw-r--r--src/theory/quantifiers/skolemize.h3
-rw-r--r--src/theory/quantifiers/sygus/ce_guided_single_inv_sol.cpp1
-rw-r--r--src/theory/sep/theory_sep.cpp118
-rw-r--r--src/theory/sep/theory_sep.h15
-rw-r--r--src/theory/theory.h6
-rw-r--r--src/theory/theory_engine.cpp91
-rw-r--r--src/theory/theory_engine.h20
-rw-r--r--src/theory/uf/eq_proof.cpp112
69 files changed, 1405 insertions, 750 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3b0794a8f..e6cb97894 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -216,6 +216,8 @@ libcvc4_add_sources(
smt/node_command.h
smt/options_manager.cpp
smt/options_manager.h
+ smt/output_manager.cpp
+ smt/output_manager.h
smt/quant_elim_solver.cpp
smt/quant_elim_solver.h
smt/preprocessor.cpp
diff --git a/src/expr/CMakeLists.txt b/src/expr/CMakeLists.txt
index 3e3b569af..7fa8b12e7 100644
--- a/src/expr/CMakeLists.txt
+++ b/src/expr/CMakeLists.txt
@@ -17,6 +17,8 @@ libcvc4_add_sources(
kind_map.h
lazy_proof.cpp
lazy_proof.h
+ lazy_proof_chain.cpp
+ lazy_proof_chain.h
match_trie.cpp
match_trie.h
node.cpp
diff --git a/src/expr/lazy_proof_chain.cpp b/src/expr/lazy_proof_chain.cpp
new file mode 100644
index 000000000..a01d541eb
--- /dev/null
+++ b/src/expr/lazy_proof_chain.cpp
@@ -0,0 +1,239 @@
+/********************* */
+/*! \file lazy_proof_chain.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Haniel Barbosa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Implementation of lazy proof utility
+ **/
+
+#include "expr/lazy_proof_chain.h"
+
+#include "expr/proof.h"
+#include "expr/proof_node_algorithm.h"
+#include "options/smt_options.h"
+
+namespace CVC4 {
+
+LazyCDProofChain::LazyCDProofChain(ProofNodeManager* pnm,
+ bool cyclic,
+ context::Context* c)
+ : d_manager(pnm), d_cyclic(cyclic), d_context(), d_gens(c ? c : &d_context)
+{
+}
+
+LazyCDProofChain::~LazyCDProofChain() {}
+
+std::shared_ptr<ProofNode> LazyCDProofChain::getProofFor(Node fact)
+{
+ Trace("lazy-cdproofchain")
+ << "LazyCDProofChain::getProofFor " << fact << "\n";
+ // which facts have had proofs retrieved for. This is maintained to avoid
+ // cycles. It also saves the proof node of the fact
+ std::unordered_map<Node, std::shared_ptr<ProofNode>, NodeHashFunction>
+ toConnect;
+ // leaves of proof node links in the chain, i.e. assumptions, yet to be
+ // expanded
+ std::unordered_map<Node,
+ std::vector<std::shared_ptr<ProofNode>>,
+ NodeHashFunction>
+ assumptionsToExpand;
+ // invariant of the loop below, the first iteration notwhistanding:
+ // visit = domain(assumptionsToExpand) \ domain(toConnect)
+ std::vector<Node> visit{fact};
+ std::unordered_map<Node, bool, NodeHashFunction> visited;
+ Node cur;
+ do
+ {
+ cur = visit.back();
+ visit.pop_back();
+ auto itVisited = visited.find(cur);
+ // pre-traversal
+ if (itVisited == visited.end())
+ {
+ Trace("lazy-cdproofchain")
+ << "LazyCDProofChain::getProofFor: check " << cur << "\n";
+ ProofGenerator* pg = getGeneratorFor(cur);
+ if (!pg)
+ {
+ Trace("lazy-cdproofchain")
+ << "LazyCDProofChain::getProofFor: nothing to do\n";
+ // nothing to do for this fact, it'll be a leaf in the final proof node,
+ // don't post-traverse.
+ visited[cur] = true;
+ continue;
+ }
+ Trace("lazy-cdproofchain")
+ << "LazyCDProofChain::getProofFor: Call generator " << pg->identify()
+ << " for chain link " << cur << "\n";
+ std::shared_ptr<ProofNode> curPfn = pg->getProofFor(cur);
+ Trace("lazy-cdproofchain-debug")
+ << "LazyCDProofChain::getProofFor: stored proof: " << *curPfn.get()
+ << "\n";
+ // retrieve free assumptions and their respective proof nodes
+ std::map<Node, std::vector<std::shared_ptr<ProofNode>>> famap;
+ expr::getFreeAssumptionsMap(curPfn, famap);
+ if (Trace.isOn("lazy-cdproofchain"))
+ {
+ Trace("lazy-cdproofchain")
+ << "LazyCDProofChain::getProofFor: free assumptions:\n";
+ for (auto fap : famap)
+ {
+ Trace("lazy-cdproofchain")
+ << "LazyCDProofChain::getProofFor: - " << fap.first << "\n";
+ }
+ }
+ // map node whose proof node must be expanded to the respective poof node
+ toConnect[cur] = curPfn;
+ // mark for post-traversal if we are controlling cycles
+ if (d_cyclic)
+ {
+ visit.push_back(cur);
+ visited[cur] = false;
+ Trace("lazy-cdproofchain") << push;
+ Trace("lazy-cdproofchain-debug") << push;
+ }
+ else
+ {
+ visited[cur] = true;
+ }
+ // enqueue free assumptions to process
+ for (const std::pair<const Node, std::vector<std::shared_ptr<ProofNode>>>&
+ fap : famap)
+ {
+ // check cycles, which are cases in which the assumption has already
+ // been marked to be connected but we have not finished processing the
+ // nodes it depends on
+ if (d_cyclic && toConnect.find(fap.first) != toConnect.end()
+ && std::find(visit.begin(), visit.end(), fap.first) != visit.end())
+ {
+ // Since we have a cycle with an assumption, this fact will be an
+ // assumption in the final proof node produced by this method. This we
+ // mark the proof node it results on, i.e. its value in the toConnect
+ // map, as an assumption proof node. Note that we don't assign
+ // visited[fap.first] to true so that we properly pop the traces
+ // previously pushed.
+ Trace("lazy-cdproofchain")
+ << "LazyCDProofChain::getProofFor: removing cyclic assumption "
+ << fap.first << " from expansion\n";
+ toConnect[fap.first] = fap.second[0];
+ continue;
+ }
+ // only process further the assumptions not already in the map
+ auto it = assumptionsToExpand.find(fap.first);
+ if (it == assumptionsToExpand.end())
+ {
+ visit.push_back(fap.first);
+ }
+ // add assumption proof nodes to be updated
+ assumptionsToExpand[fap.first].insert(
+ assumptionsToExpand[fap.first].end(),
+ fap.second.begin(),
+ fap.second.end());
+ }
+ }
+ else if (!itVisited->second)
+ {
+ visited[cur] = true;
+ Trace("lazy-cdproofchain") << pop;
+ Trace("lazy-cdproofchain-debug") << pop;
+ }
+ } while (!visit.empty());
+ // expand all assumptions marked to be connected
+ for (const std::pair<const Node, std::shared_ptr<ProofNode>>& npfn :
+ toConnect)
+ {
+ auto it = assumptionsToExpand.find(npfn.first);
+ if (it == assumptionsToExpand.end())
+ {
+ Assert(npfn.first == fact);
+ continue;
+ }
+ Trace("lazy-cdproofchain")
+ << "LazyCDProofChain::getProofFor: expand assumption " << npfn.first
+ << "\n";
+ Trace("lazy-cdproofchain-debug")
+ << "LazyCDProofChain::getProofFor: ...expand to " << *npfn.second.get()
+ << "\n";
+ // update each assumption proof node
+ for (std::shared_ptr<ProofNode> pfn : it->second)
+ {
+ d_manager->updateNode(pfn.get(), npfn.second.get());
+ }
+ }
+ // final proof of fact
+ auto it = toConnect.find(fact);
+ if (it == toConnect.end())
+ {
+ return nullptr;
+ }
+ return it->second;
+}
+
+void LazyCDProofChain::addLazyStep(Node expected, ProofGenerator* pg)
+{
+ Assert(pg != nullptr);
+ Trace("lazy-cdproofchain") << "LazyCDProofChain::addLazyStep: " << expected
+ << " set to generator " << pg->identify() << "\n";
+ // note this will replace the generator for expected, if any
+ d_gens.insert(expected, pg);
+}
+
+void LazyCDProofChain::addLazyStep(Node expected,
+ ProofGenerator* pg,
+ const std::vector<Node>& assumptions,
+ const char* ctx)
+{
+ Assert(pg != nullptr);
+ Trace("lazy-cdproofchain") << "LazyCDProofChain::addLazyStep: " << expected
+ << " set to generator " << pg->identify() << "\n";
+ // note this will rewrite the generator for expected, if any
+ d_gens.insert(expected, pg);
+ // check if chain is closed if options::proofNewEagerChecking() is on
+ if (options::proofNewEagerChecking())
+ {
+ Trace("lazy-cdproofchain")
+ << "LazyCDProofChain::addLazyStep: Checking closed proof...\n";
+ std::shared_ptr<ProofNode> pfn = pg->getProofFor(expected);
+ std::vector<Node> allowedLeaves{assumptions.begin(), assumptions.end()};
+ // add all current links in the chain
+ for (const std::pair<const Node, ProofGenerator*>& link : d_gens)
+ {
+ allowedLeaves.push_back(link.first);
+ }
+ if (Trace.isOn("lazy-cdproofchain"))
+ {
+ Trace("lazy-cdproofchain") << "Checking relative to leaves...\n";
+ for (const Node& n : allowedLeaves)
+ {
+ Trace("lazy-cdproofchain") << " - " << n << "\n";
+ }
+ Trace("lazy-cdproofchain") << "\n";
+ }
+ pfnEnsureClosedWrt(pfn.get(), allowedLeaves, "lazy-cdproofchain", ctx);
+ }
+}
+
+bool LazyCDProofChain::hasGenerator(Node fact) const
+{
+ return d_gens.find(fact) != d_gens.end();
+}
+
+ProofGenerator* LazyCDProofChain::getGeneratorFor(Node fact)
+{
+ auto it = d_gens.find(fact);
+ if (it != d_gens.end())
+ {
+ return (*it).second;
+ }
+ return nullptr;
+}
+
+std::string LazyCDProofChain::identify() const { return "LazyCDProofChain"; }
+
+} // namespace CVC4
diff --git a/src/expr/lazy_proof_chain.h b/src/expr/lazy_proof_chain.h
new file mode 100644
index 000000000..7fa49bccc
--- /dev/null
+++ b/src/expr/lazy_proof_chain.h
@@ -0,0 +1,135 @@
+/********************* */
+/*! \file lazy_proof_chain.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Haniel Barbosa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Lazy proof chain utility
+ **/
+
+#include "cvc4_private.h"
+
+#ifndef CVC4__EXPR__LAZY_PROOF_CHAIN_H
+#define CVC4__EXPR__LAZY_PROOF_CHAIN_H
+
+#include <unordered_map>
+#include <vector>
+
+#include "context/cdhashmap.h"
+#include "expr/proof_generator.h"
+#include "expr/proof_node_manager.h"
+
+namespace CVC4 {
+
+/**
+ * A (context-dependent) lazy generator for proof chains. This class is an
+ * extension of ProofGenerator that additionally that maps facts to proof
+ * generators in a context-dependent manner. The map is built with the addition
+ * of lazy steps mapping facts to proof generators. More importantly, its
+ * getProofFor method expands the proof generators registered to this class by
+ * connecting, for the proof generated to one fact, assumptions to the proofs
+ * generated for those assumptinos that are registered in the chain.
+ */
+class LazyCDProofChain : public ProofGenerator
+{
+ public:
+ /** Constructor
+ *
+ * @param pnm The proof node manager for constructing ProofNode objects.
+ * @param cyclic Whether this instance is robust to cycles in the cahin.
+ * @param c The context that this class depends on. If none is provided,
+ * this class is context-independent.
+ */
+ LazyCDProofChain(ProofNodeManager* pnm,
+ bool cyclic = true,
+ context::Context* c = nullptr);
+ ~LazyCDProofChain();
+ /**
+ * Get lazy proof for fact, or nullptr if it does not exist, by connecting the
+ * proof nodes generated for each intermediate relevant fact registered in the
+ * chain (i.e., in the domain of d_gens).
+ *
+ * For example, if d_gens consists of the following pairs
+ *
+ * --- (A, PG1)
+ * --- (B, PG2)
+ * --- (C, PG3)
+ *
+ * and getProofFor(A) is called, with PG1 generating a proof with assumptions
+ * B and D, then B is expanded, with its assumption proof node being updated
+ * to the expanded proof node, while D is not. Assuming PG2 provides a proof
+ * with assumptions C and E, then C is expanded and E is not. Suppose PG3
+ * gives a closed proof, thus the call getProofFor(A) produces a proof node
+ *
+ * A : ( ... B : ( ... C : (...), ... ASSUME( E ) ), ... ASSUME( D ) )
+ *
+ * Note that the expansions are done directly on the proof nodes produced by
+ * the generators.
+ *
+ * If this instance has been set to be robust to cyclic proofs (i.e., d_cyclic
+ * is true), then the construction of the proof chain checks that there are no
+ * cycles, i.e., a given fact would have itself as an assumption when
+ * connecting the chain links. If such a cycle were to be detected then the
+ * fact will be marked as an assumption and not expanded in the final proof
+ * node. The method does not fail.
+ */
+ std::shared_ptr<ProofNode> getProofFor(Node fact) override;
+ /** Add step by generator
+ *
+ * This method stores that expected can be proven by proof generator pg if
+ * it is required to do so. This mapping is maintained in the remainder of
+ * the current context (according to the context c provided to this class).
+ *
+ * Moreover the lazy steps of this class are expected to fulfill the
+ * requirement that pg.getProofFor(expected) generates a proof node closed
+ * with relation to
+ * (1) a fixed set F1, ..., Fn,
+ * (2) formulas in the current domain of d_gens.
+ *
+ * This is so that we only add links to the chain that depend on a fixed set
+ * of assumptions or in other links.
+ *
+ * @param expected The fact that can be proven.
+ * @param pg The generator that can proof expected.
+ * @param assumptions The fixed set of assumptions with relation to which the
+ * chain, now augmented with expect, must be closed.
+ * @param ctx The context we are in (for debugging).
+ */
+ void addLazyStep(Node expected,
+ ProofGenerator* pg,
+ const std::vector<Node>& assumptions,
+ const char* ctx = "LazyCDProofChain::addLazyStep");
+
+ /** As above but does not do the closedness check. */
+ void addLazyStep(Node expected, ProofGenerator* pg);
+
+ /** Does the given fact have an explicitly provided generator? */
+ bool hasGenerator(Node fact) const;
+
+ /**
+ * Get generator for fact, or nullptr if it doesnt exist.
+ */
+ ProofGenerator* getGeneratorFor(Node fact);
+
+ /** identify */
+ std::string identify() const override;
+
+ private:
+ /** The proof manager, used for allocating new ProofNode objects */
+ ProofNodeManager* d_manager;
+ /** Whether this instance is robust to cycles in the chain. */
+ bool d_cyclic;
+ /** A dummy context used by this class if none is provided */
+ context::Context d_context;
+ /** Maps facts that can be proven to generators */
+ context::CDHashMap<Node, ProofGenerator*, NodeHashFunction> d_gens;
+};
+
+} // namespace CVC4
+
+#endif /* CVC4__EXPR__LAZY_PROOF_CHAIN_H */
diff --git a/src/expr/proof_node_algorithm.cpp b/src/expr/proof_node_algorithm.cpp
index 9e1018024..984379d54 100644
--- a/src/expr/proof_node_algorithm.cpp
+++ b/src/expr/proof_node_algorithm.cpp
@@ -19,22 +19,26 @@ namespace expr {
void getFreeAssumptions(ProofNode* pn, std::vector<Node>& assump)
{
- std::map<Node, std::vector<ProofNode*>> amap;
- getFreeAssumptionsMap(pn, amap);
- for (const std::pair<const Node, std::vector<ProofNode*>>& p : amap)
+ std::map<Node, std::vector<std::shared_ptr<ProofNode>>> amap;
+ std::shared_ptr<ProofNode> spn = std::make_shared<ProofNode>(
+ pn->getRule(), pn->getChildren(), pn->getArguments());
+ getFreeAssumptionsMap(spn, amap);
+ for (const std::pair<const Node, std::vector<std::shared_ptr<ProofNode>>>& p :
+ amap)
{
assump.push_back(p.first);
}
}
-void getFreeAssumptionsMap(ProofNode* pn,
- std::map<Node, std::vector<ProofNode*>>& amap)
+void getFreeAssumptionsMap(
+ std::shared_ptr<ProofNode> pn,
+ std::map<Node, std::vector<std::shared_ptr<ProofNode>>>& amap)
{
// proof should not be cyclic
// visited set false after preorder traversal, true after postorder traversal
std::unordered_map<ProofNode*, bool> visited;
std::unordered_map<ProofNode*, bool>::iterator it;
- std::vector<ProofNode*> visit;
+ std::vector<std::shared_ptr<ProofNode>> visit;
// Maps a bound assumption to the number of bindings it is under
// e.g. in (SCOPE (SCOPE (ASSUME x) (x y)) (y)), y would be mapped to 2 at
// (ASSUME x), and x would be mapped to 1.
@@ -54,17 +58,17 @@ void getFreeAssumptionsMap(ProofNode* pn,
// after postvisiting SCOPE2: {}
//
std::unordered_map<Node, uint32_t, NodeHashFunction> scopeDepth;
- ProofNode* cur;
+ std::shared_ptr<ProofNode> cur;
visit.push_back(pn);
do
{
cur = visit.back();
visit.pop_back();
- it = visited.find(cur);
+ it = visited.find(cur.get());
const std::vector<Node>& cargs = cur->getArguments();
if (it == visited.end())
{
- visited[cur] = true;
+ visited[cur.get()] = true;
PfRule id = cur->getRule();
if (id == PfRule::ASSUME)
{
@@ -85,7 +89,7 @@ void getFreeAssumptionsMap(ProofNode* pn,
scopeDepth[a] += 1;
}
// will need to unbind the variables below
- visited[cur] = false;
+ visited[cur.get()] = false;
visit.push_back(cur);
}
// The following loop cannot be merged with the loop above because the
@@ -93,13 +97,13 @@ void getFreeAssumptionsMap(ProofNode* pn,
const std::vector<std::shared_ptr<ProofNode>>& cs = cur->getChildren();
for (const std::shared_ptr<ProofNode>& cp : cs)
{
- visit.push_back(cp.get());
+ visit.push_back(cp);
}
}
}
else if (!it->second)
{
- visited[cur] = true;
+ visited[cur.get()] = true;
Assert(cur->getRule() == PfRule::SCOPE);
// unbind its assumptions
for (const Node& a : cargs)
diff --git a/src/expr/proof_node_algorithm.h b/src/expr/proof_node_algorithm.h
index bc44d7314..aec098e17 100644
--- a/src/expr/proof_node_algorithm.h
+++ b/src/expr/proof_node_algorithm.h
@@ -49,8 +49,9 @@ void getFreeAssumptions(ProofNode* pn, std::vector<Node>& assump);
* @param amap The mapping to add the free asumptions of pn and their
* corresponding proof nodes to.
*/
-void getFreeAssumptionsMap(ProofNode* pn,
- std::map<Node, std::vector<ProofNode*>>& amap);
+void getFreeAssumptionsMap(
+ std::shared_ptr<ProofNode> pn,
+ std::map<Node, std::vector<std::shared_ptr<ProofNode>>>& amap);
} // namespace expr
} // namespace CVC4
diff --git a/src/expr/proof_node_manager.cpp b/src/expr/proof_node_manager.cpp
index 0d13531a5..54315ee05 100644
--- a/src/expr/proof_node_manager.cpp
+++ b/src/expr/proof_node_manager.cpp
@@ -75,10 +75,11 @@ std::shared_ptr<ProofNode> ProofNodeManager::mkScope(
bool computedAcr = false;
// The free assumptions of the proof
- std::map<Node, std::vector<ProofNode*>> famap;
- expr::getFreeAssumptionsMap(pf.get(), famap);
+ std::map<Node, std::vector<std::shared_ptr<ProofNode>>> famap;
+ expr::getFreeAssumptionsMap(pf, famap);
std::unordered_set<Node, NodeHashFunction> acu;
- for (const std::pair<const Node, std::vector<ProofNode*>>& fa : famap)
+ for (const std::pair<const Node, std::vector<std::shared_ptr<ProofNode>>>&
+ fa : famap)
{
Node a = fa.first;
if (ac.find(a) != ac.end())
@@ -135,10 +136,10 @@ std::shared_ptr<ProofNode> ProofNodeManager::mkScope(
children.push_back(pfaa);
std::vector<Node> args;
args.push_back(a);
- for (ProofNode* pfs : fa.second)
+ for (std::shared_ptr<ProofNode> pfs : fa.second)
{
Assert(pfs->getResult() == a);
- updateNode(pfs, PfRule::MACRO_SR_PRED_TRANSFORM, children, args);
+ updateNode(pfs.get(), PfRule::MACRO_SR_PRED_TRANSFORM, children, args);
}
Trace("pnm-scope") << "...finished" << std::endl;
acu.insert(aMatch);
diff --git a/src/expr/proof_rule.cpp b/src/expr/proof_rule.cpp
index 1d46b183f..57dd3e0bd 100644
--- a/src/expr/proof_rule.cpp
+++ b/src/expr/proof_rule.cpp
@@ -42,6 +42,10 @@ const char* toString(PfRule id)
case PfRule::THEORY_PREPROCESS_LEMMA: return "THEORY_PREPROCESS_LEMMA";
case PfRule::WITNESS_AXIOM: return "WITNESS_AXIOM";
//================================================= Boolean rules
+ case PfRule::RESOLUTION: return "RESOLUTION";
+ case PfRule::CHAIN_RESOLUTION: return "CHAIN_RESOLUTION";
+ case PfRule::FACTORING: return "FACTORING";
+ case PfRule::REORDERING: return "REORDERING";
case PfRule::SPLIT: return "SPLIT";
case PfRule::EQ_RESOLVE: return "EQ_RESOLVE";
case PfRule::AND_ELIM: return "AND_ELIM";
diff --git a/src/expr/proof_rule.h b/src/expr/proof_rule.h
index 825503d5d..c02292dab 100644
--- a/src/expr/proof_rule.h
+++ b/src/expr/proof_rule.h
@@ -226,6 +226,45 @@ enum class PfRule : uint32_t
WITNESS_AXIOM,
//================================================= Boolean rules
+ // ======== Resolution
+ // Children:
+ // (P1:(or F_1 ... F_i-1 F_i F_i+1 ... F_n),
+ // P2:(or G_1 ... G_j-1 G_j G_j+1 ... G_m))
+ //
+ // Arguments: (F_i)
+ // ---------------------
+ // Conclusion: (or F_1 ... F_i-1 F_i+1 ... F_n G_1 ... G_j-1 G_j+1 ... G_m)
+ // where
+ // G_j = (not F_i)
+ RESOLUTION,
+ // ======== Chain Resolution
+ // Children: (P1:(or F_{1,1} ... F_{1,n1}), ..., Pm:(or F_{m,1} ... F_{m,nm}))
+ // Arguments: (L_1, ..., L_{m-1})
+ // ---------------------
+ // Conclusion: C_m'
+ // where
+ // let "C_1 <>_l C_2" represent the resolution of C_1 with C_2 with pivot l,
+ // let C_1' = C_1 (from P_1),
+ // for each i > 1, C_i' = C_i <>_L_i C_{i-1}'
+ CHAIN_RESOLUTION,
+ // ======== Factoring
+ // Children: (P:C1)
+ // Arguments: ()
+ // ---------------------
+ // Conclusion: C2
+ // where
+ // Set representations of C1 and C2 is the same and the number of literals in
+ // C2 is smaller than that of C1
+ FACTORING,
+ // ======== Reordering
+ // Children: (P:C1)
+ // Arguments: (C2)
+ // ---------------------
+ // Conclusion: C2
+ // where
+ // Set representations of C1 and C2 is the same but the number of literals in
+ // C2 is the same of that of C1
+ REORDERING,
// ======== Split
// Children: none
// Arguments: (F)
diff --git a/src/main/command_executor.h b/src/main/command_executor.h
index de21db74d..1c10aa09f 100644
--- a/src/main/command_executor.h
+++ b/src/main/command_executor.h
@@ -21,12 +21,13 @@
#include "api/cvc4cpp.h"
#include "expr/expr_manager.h"
#include "options/options.h"
-#include "smt/command.h"
#include "smt/smt_engine.h"
#include "util/statistics_registry.h"
namespace CVC4 {
+class Command;
+
namespace api {
class Solver;
}
diff --git a/src/main/main.cpp b/src/main/main.cpp
index 9cf168392..7b72ae249 100644
--- a/src/main/main.cpp
+++ b/src/main/main.cpp
@@ -32,7 +32,6 @@
#include "parser/parser.h"
#include "parser/parser_builder.h"
#include "parser/parser_exception.h"
-#include "smt/command.h"
#include "smt/smt_engine.h"
#include "util/result.h"
#include "util/statistics.h"
diff --git a/src/parser/antlr_input.cpp b/src/parser/antlr_input.cpp
index bf5e8824a..54165feb7 100644
--- a/src/parser/antlr_input.cpp
+++ b/src/parser/antlr_input.cpp
@@ -33,7 +33,6 @@
#include "parser/smt2/smt2_input.h"
#include "parser/smt2/sygus_input.h"
#include "parser/tptp/tptp_input.h"
-#include "smt/command.h"
using namespace std;
using namespace CVC4;
diff --git a/src/parser/cvc/cvc.cpp b/src/parser/cvc/cvc.cpp
index 4d409a0b4..7caa35dd6 100644
--- a/src/parser/cvc/cvc.cpp
+++ b/src/parser/cvc/cvc.cpp
@@ -15,6 +15,7 @@
**/
#include "parser/cvc/cvc.h"
+#include "smt/command.h"
namespace CVC4 {
namespace parser {
diff --git a/src/parser/cvc/cvc.h b/src/parser/cvc/cvc.h
index 7c226168f..3930a02f5 100644
--- a/src/parser/cvc/cvc.h
+++ b/src/parser/cvc/cvc.h
@@ -21,7 +21,6 @@
#include "api/cvc4cpp.h"
#include "parser/parser.h"
-#include "smt/command.h"
namespace CVC4 {
diff --git a/src/parser/input.cpp b/src/parser/input.cpp
index 13903eaf5..8d5057151 100644
--- a/src/parser/input.cpp
+++ b/src/parser/input.cpp
@@ -23,7 +23,6 @@
#include "expr/type.h"
#include "parser/parser.h"
#include "parser/parser_exception.h"
-#include "smt/command.h"
using namespace std;
diff --git a/src/parser/smt2/smt2.h b/src/parser/smt2/smt2.h
index 2e725f9bf..ebf3811c4 100644
--- a/src/parser/smt2/smt2.h
+++ b/src/parser/smt2/smt2.h
@@ -28,12 +28,12 @@
#include "api/cvc4cpp.h"
#include "parser/parse_op.h"
#include "parser/parser.h"
-#include "smt/command.h"
#include "theory/logic_info.h"
#include "util/abstract_value.h"
namespace CVC4 {
+class Command;
class SExpr;
namespace api {
diff --git a/src/parser/tptp/tptp.cpp b/src/parser/tptp/tptp.cpp
index cb4d3fd9e..ab6a4c5eb 100644
--- a/src/parser/tptp/tptp.cpp
+++ b/src/parser/tptp/tptp.cpp
@@ -24,6 +24,7 @@
#include "expr/type.h"
#include "options/options.h"
#include "parser/parser.h"
+#include "smt/command.h"
// ANTLR defines these, which is really bad!
#undef true
diff --git a/src/parser/tptp/tptp.h b/src/parser/tptp/tptp.h
index 3d5419be9..40dd85f63 100644
--- a/src/parser/tptp/tptp.h
+++ b/src/parser/tptp/tptp.h
@@ -28,11 +28,12 @@
#include "api/cvc4cpp.h"
#include "parser/parse_op.h"
#include "parser/parser.h"
-#include "smt/command.h"
#include "util/hash.h"
namespace CVC4 {
+class Command;
+
namespace api {
class Solver;
}
diff --git a/src/preprocessing/passes/bv_to_int.cpp b/src/preprocessing/passes/bv_to_int.cpp
index e40b828b5..13ad086e8 100644
--- a/src/preprocessing/passes/bv_to_int.cpp
+++ b/src/preprocessing/passes/bv_to_int.cpp
@@ -687,11 +687,7 @@ Node BVToInt::translateNoChildren(Node original)
uint64_t bvsize = original.getType().getBitVectorSize();
translation = newVar;
d_rangeAssertions.insert(mkRangeConstraint(newVar, bvsize));
- std::vector<Expr> args;
- Node intToBVOp = d_nm->mkConst<IntToBitVector>(IntToBitVector(bvsize));
- Node newNode = d_nm->mkNode(intToBVOp, newVar);
- smt::currentSmtEngine()->defineFunction(
- original.toExpr(), args, newNode.toExpr(), true);
+ defineBVUFAsIntUF(original, newVar);
}
else if (original.getType().isFunction())
{
@@ -756,41 +752,49 @@ Node BVToInt::translateFunctionSymbol(Node bvUF)
void BVToInt::defineBVUFAsIntUF(Node bvUF, Node intUF)
{
- // This function should only be called after translating
- // the function symbol to a new function symbol
- // with the right domain and range.
-
- // get domain and range of the original function
- TypeNode tn = bvUF.getType();
- vector<TypeNode> bvDomain = tn.getArgTypes();
- TypeNode bvRange = tn.getRangeType();
-
+ // The resulting term
+ Node result;
+ // The type of the resulting term
+ TypeNode resultType;
// symbolic arguments of original function
vector<Expr> args;
- // children of the new symbolic application
- vector<Node> achildren;
- achildren.push_back(intUF);
- int i = 0;
- for (TypeNode d : bvDomain)
- {
- // Each bit-vector argument is casted to a natural number
- // Other arguments are left intact.
- Node fresh_bound_var = d_nm->mkBoundVar(d);
- args.push_back(fresh_bound_var.toExpr());
- Node castedArg = args[i];
- if (d.isBitVector())
+ if (!bvUF.getType().isFunction()) {
+ // bvUF is a variable.
+ // in this case, the result is just the original term
+ // (it will be casted later if needed)
+ result = intUF;
+ resultType = bvUF.getType();
+ } else {
+ // bvUF is a function with arguments
+ // The arguments need to be casted as well.
+ TypeNode tn = bvUF.getType();
+ resultType = tn.getRangeType();
+ vector<TypeNode> bvDomain = tn.getArgTypes();
+ // children of the new symbolic application
+ vector<Node> achildren;
+ achildren.push_back(intUF);
+ int i = 0;
+ for (const TypeNode& d : bvDomain)
{
- castedArg = castToType(castedArg, d_nm->integerType());
+ // Each bit-vector argument is casted to a natural number
+ // Other arguments are left intact.
+ Node fresh_bound_var = d_nm->mkBoundVar(d);
+ args.push_back(fresh_bound_var.toExpr());
+ Node castedArg = args[i];
+ if (d.isBitVector())
+ {
+ castedArg = castToType(castedArg, d_nm->integerType());
+ }
+ achildren.push_back(castedArg);
+ i++;
}
- achildren.push_back(castedArg);
- i++;
+ result = d_nm->mkNode(kind::APPLY_UF, achildren);
}
- Node intApplication = d_nm->mkNode(kind::APPLY_UF, achildren);
- // If the range is BV, the application needs to be casted back.
- intApplication = castToType(intApplication, bvRange);
+ // If the result is BV, it needs to be casted back.
+ result = castToType(result, resultType);
// add the function definition to the smt engine.
smt::currentSmtEngine()->defineFunction(
- bvUF.toExpr(), args, intApplication.toExpr(), true);
+ bvUF.toExpr(), args, result.toExpr(), true);
}
bool BVToInt::childrenTypesChanged(Node n)
diff --git a/src/preprocessing/passes/bv_to_int.h b/src/preprocessing/passes/bv_to_int.h
index db2d08b7d..b84726878 100644
--- a/src/preprocessing/passes/bv_to_int.h
+++ b/src/preprocessing/passes/bv_to_int.h
@@ -289,11 +289,12 @@ class BVToInt : public PreprocessingPass
* When a UF f is translated to a UF g,
* we add a define-fun command to the smt-engine
* to relate between f and g.
+ * We do the same when f and g are just variables.
* This is useful, for example, when asking
* for a model-value of a term that includes the
* original UF f.
- * @param bvUF the original function
- * @param intUF the translated function
+ * @param bvUF the original function or variable
+ * @param intUF the translated function or variable
*/
void defineBVUFAsIntUF(Node bvUF, Node intUF);
diff --git a/src/preprocessing/preprocessing_pass.cpp b/src/preprocessing/preprocessing_pass.cpp
index 965edcd2f..cd2a51c45 100644
--- a/src/preprocessing/preprocessing_pass.cpp
+++ b/src/preprocessing/preprocessing_pass.cpp
@@ -18,6 +18,7 @@
#include "smt/dump.h"
#include "smt/smt_statistics_registry.h"
+#include "printer/printer.h"
namespace CVC4 {
namespace preprocessing {
@@ -39,8 +40,13 @@ void PreprocessingPass::dumpAssertions(const char* key,
if (Dump.isOn("assertions") && Dump.isOn(std::string("assertions:") + key))
{
// Push the simplified assertions to the dump output stream
- for (const auto& n : assertionList) {
- Dump("assertions") << AssertCommand(Expr(n.toExpr()));
+ OutputManager& outMgr = d_preprocContext->getSmt()->getOutputManager();
+ const Printer& printer = outMgr.getPrinter();
+ std::ostream& out = outMgr.getDumpOut();
+
+ for (const auto& n : assertionList)
+ {
+ printer.toStreamCmdAssert(out, n);
}
}
}
diff --git a/src/printer/ast/ast_printer.cpp b/src/printer/ast/ast_printer.cpp
index f776d07db..e179b7ffd 100644
--- a/src/printer/ast/ast_printer.cpp
+++ b/src/printer/ast/ast_printer.cpp
@@ -166,23 +166,28 @@ void AstPrinter::toStream(std::ostream& out,
void AstPrinter::toStreamCmdEmpty(std::ostream& out,
const std::string& name) const
{
- out << "EmptyCommand(" << name << ')';
+ out << "EmptyCommand(" << name << ')' << std::endl;
}
void AstPrinter::toStreamCmdEcho(std::ostream& out,
const std::string& output) const
{
- out << "EchoCommand(" << output << ')';
+ out << "EchoCommand(" << output << ')' << std::endl;
}
void AstPrinter::toStreamCmdAssert(std::ostream& out, Node n) const
{
- out << "Assert(" << n << ')';
+ out << "Assert(" << n << ')' << std::endl;
}
-void AstPrinter::toStreamCmdPush(std::ostream& out) const { out << "Push()"; }
+void AstPrinter::toStreamCmdPush(std::ostream& out) const
+{
+ out << "Push()" << std::endl;
+}
-void AstPrinter::toStreamCmdPop(std::ostream& out) const { out << "Pop()"; }
+void AstPrinter::toStreamCmdPop(std::ostream& out) const {
+ out << "Pop()" << std::endl;
+}
void AstPrinter::toStreamCmdCheckSat(std::ostream& out, Node n) const
{
@@ -194,6 +199,7 @@ void AstPrinter::toStreamCmdCheckSat(std::ostream& out, Node n) const
{
out << "CheckSat(" << n << ')';
}
+ out << std::endl;
}
void AstPrinter::toStreamCmdCheckSatAssuming(
@@ -201,22 +207,28 @@ void AstPrinter::toStreamCmdCheckSatAssuming(
{
out << "CheckSatAssuming( << ";
copy(nodes.begin(), nodes.end(), ostream_iterator<Node>(out, ", "));
- out << ">> )";
+ out << ">> )" << std::endl;
}
void AstPrinter::toStreamCmdQuery(std::ostream& out, Node n) const
{
- out << "Query(" << n << ')';
+ out << "Query(" << n << ')' << std::endl;
}
-void AstPrinter::toStreamCmdReset(std::ostream& out) const { out << "Reset()"; }
+void AstPrinter::toStreamCmdReset(std::ostream& out) const
+{
+ out << "Reset()" << std::endl;
+}
void AstPrinter::toStreamCmdResetAssertions(std::ostream& out) const
{
- out << "ResetAssertions()";
+ out << "ResetAssertions()" << std::endl;
}
-void AstPrinter::toStreamCmdQuit(std::ostream& out) const { out << "Quit()"; }
+void AstPrinter::toStreamCmdQuit(std::ostream& out) const
+{
+ out << "Quit()" << std::endl;
+}
void AstPrinter::toStreamCmdDeclarationSequence(
std::ostream& out, const std::vector<Command*>& sequence) const
@@ -228,7 +240,7 @@ void AstPrinter::toStreamCmdDeclarationSequence(
{
out << *i << endl;
}
- out << "]";
+ out << "]" << std::endl;
}
void AstPrinter::toStreamCmdCommandSequence(
@@ -241,14 +253,14 @@ void AstPrinter::toStreamCmdCommandSequence(
{
out << *i << endl;
}
- out << "]";
+ out << "]" << std::endl;
}
void AstPrinter::toStreamCmdDeclareFunction(std::ostream& out,
const std::string& id,
TypeNode type) const
{
- out << "Declare(" << id << "," << type << ')';
+ out << "Declare(" << id << "," << type << ')' << std::endl;
}
void AstPrinter::toStreamCmdDefineFunction(std::ostream& out,
@@ -263,7 +275,7 @@ void AstPrinter::toStreamCmdDefineFunction(std::ostream& out,
copy(formals.begin(), formals.end() - 1, ostream_iterator<Node>(out, ", "));
out << formals.back();
}
- out << "], << " << formula << " >> )";
+ out << "], << " << formula << " >> )" << std::endl;
}
void AstPrinter::toStreamCmdDeclareType(std::ostream& out,
@@ -271,7 +283,8 @@ void AstPrinter::toStreamCmdDeclareType(std::ostream& out,
size_t arity,
TypeNode type) const
{
- out << "DeclareType(" << id << "," << arity << "," << type << ')';
+ out << "DeclareType(" << id << "," << arity << "," << type << ')'
+ << std::endl;
}
void AstPrinter::toStreamCmdDefineType(std::ostream& out,
@@ -287,7 +300,7 @@ void AstPrinter::toStreamCmdDefineType(std::ostream& out,
ostream_iterator<TypeNode>(out, ", "));
out << params.back();
}
- out << "]," << t << ')';
+ out << "]," << t << ')' << std::endl;
}
void AstPrinter::toStreamCmdDefineNamedFunction(
@@ -304,7 +317,7 @@ void AstPrinter::toStreamCmdDefineNamedFunction(
void AstPrinter::toStreamCmdSimplify(std::ostream& out, Node n) const
{
- out << "Simplify( << " << n << " >> )";
+ out << "Simplify( << " << n << " >> )" << std::endl;
}
void AstPrinter::toStreamCmdGetValue(std::ostream& out,
@@ -312,70 +325,70 @@ void AstPrinter::toStreamCmdGetValue(std::ostream& out,
{
out << "GetValue( << ";
copy(nodes.begin(), nodes.end(), ostream_iterator<Node>(out, ", "));
- out << ">> )";
+ out << ">> )" << std::endl;
}
void AstPrinter::toStreamCmdGetModel(std::ostream& out) const
{
- out << "GetModel()";
+ out << "GetModel()" << std::endl;
}
void AstPrinter::toStreamCmdGetAssignment(std::ostream& out) const
{
- out << "GetAssignment()";
+ out << "GetAssignment()" << std::endl;
}
void AstPrinter::toStreamCmdGetAssertions(std::ostream& out) const
{
- out << "GetAssertions()";
+ out << "GetAssertions()" << std::endl;
}
void AstPrinter::toStreamCmdGetProof(std::ostream& out) const
{
- out << "GetProof()";
+ out << "GetProof()" << std::endl;
}
void AstPrinter::toStreamCmdGetUnsatCore(std::ostream& out) const
{
- out << "GetUnsatCore()";
+ out << "GetUnsatCore()" << std::endl;
}
void AstPrinter::toStreamCmdSetBenchmarkStatus(std::ostream& out,
Result::Sat status) const
{
- out << "SetBenchmarkStatus(" << status << ')';
+ out << "SetBenchmarkStatus(" << status << ')' << std::endl;
}
void AstPrinter::toStreamCmdSetBenchmarkLogic(std::ostream& out,
const std::string& logic) const
{
- out << "SetBenchmarkLogic(" << logic << ')';
+ out << "SetBenchmarkLogic(" << logic << ')' << std::endl;
}
void AstPrinter::toStreamCmdSetInfo(std::ostream& out,
const std::string& flag,
SExpr sexpr) const
{
- out << "SetInfo(" << flag << ", " << sexpr << ')';
+ out << "SetInfo(" << flag << ", " << sexpr << ')' << std::endl;
}
void AstPrinter::toStreamCmdGetInfo(std::ostream& out,
const std::string& flag) const
{
- out << "GetInfo(" << flag << ')';
+ out << "GetInfo(" << flag << ')' << std::endl;
}
void AstPrinter::toStreamCmdSetOption(std::ostream& out,
const std::string& flag,
SExpr sexpr) const
{
- out << "SetOption(" << flag << ", " << sexpr << ')';
+ out << "SetOption(" << flag << ", " << sexpr << ')' << std::endl;
}
void AstPrinter::toStreamCmdGetOption(std::ostream& out,
const std::string& flag) const
{
- out << "GetOption(" << flag << ')';
+ out << "GetOption(" << flag << ')' << std::endl;
}
void AstPrinter::toStreamCmdDatatypeDeclaration(
@@ -386,13 +399,13 @@ void AstPrinter::toStreamCmdDatatypeDeclaration(
{
out << t << ";" << endl;
}
- out << "])";
+ out << "])" << std::endl;
}
void AstPrinter::toStreamCmdComment(std::ostream& out,
const std::string& comment) const
{
- out << "CommentCommand([" << comment << "])";
+ out << "CommentCommand([" << comment << "])" << std::endl;
}
template <class T>
diff --git a/src/printer/cvc/cvc_printer.cpp b/src/printer/cvc/cvc_printer.cpp
index 02afa715d..46b509388 100644
--- a/src/printer/cvc/cvc_printer.cpp
+++ b/src/printer/cvc/cvc_printer.cpp
@@ -1203,12 +1203,18 @@ void CvcPrinter::toStream(std::ostream& out,
void CvcPrinter::toStreamCmdAssert(std::ostream& out, Node n) const
{
- out << "ASSERT " << n << ';';
+ out << "ASSERT " << n << ';' << std::endl;
}
-void CvcPrinter::toStreamCmdPush(std::ostream& out) const { out << "PUSH;"; }
+void CvcPrinter::toStreamCmdPush(std::ostream& out) const
+{
+ out << "PUSH;" << std::endl;
+}
-void CvcPrinter::toStreamCmdPop(std::ostream& out) const { out << "POP;"; }
+void CvcPrinter::toStreamCmdPop(std::ostream& out) const
+{
+ out << "POP;" << std::endl;
+}
void CvcPrinter::toStreamCmdCheckSat(std::ostream& out, Node n) const
{
@@ -1228,6 +1234,7 @@ void CvcPrinter::toStreamCmdCheckSat(std::ostream& out, Node n) const
{
out << " POP;";
}
+ out << std::endl;
}
void CvcPrinter::toStreamCmdCheckSatAssuming(
@@ -1251,6 +1258,7 @@ void CvcPrinter::toStreamCmdCheckSatAssuming(
{
out << " POP;";
}
+ out << std::endl;
}
void CvcPrinter::toStreamCmdQuery(std::ostream& out, Node n) const
@@ -1271,18 +1279,22 @@ void CvcPrinter::toStreamCmdQuery(std::ostream& out, Node n) const
{
out << " POP;";
}
+ out << std::endl;
}
-void CvcPrinter::toStreamCmdReset(std::ostream& out) const { out << "RESET;"; }
+void CvcPrinter::toStreamCmdReset(std::ostream& out) const
+{
+ out << "RESET;" << std::endl;
+}
void CvcPrinter::toStreamCmdResetAssertions(std::ostream& out) const
{
- out << "RESET ASSERTIONS;";
+ out << "RESET ASSERTIONS;" << std::endl;
}
void CvcPrinter::toStreamCmdQuit(std::ostream& out) const
{
- // out << "EXIT;";
+ // out << "EXIT;" << std::endl;
}
void CvcPrinter::toStreamCmdCommandSequence(
@@ -1292,7 +1304,7 @@ void CvcPrinter::toStreamCmdCommandSequence(
i != sequence.cend();
++i)
{
- out << *i << endl;
+ out << *i;
}
}
@@ -1314,13 +1326,14 @@ void CvcPrinter::toStreamCmdDeclarationSequence(
break;
}
}
+ out << std::endl;
}
void CvcPrinter::toStreamCmdDeclareFunction(std::ostream& out,
const std::string& id,
TypeNode type) const
{
- out << id << " : " << type << ';';
+ out << id << " : " << type << ';' << std::endl;
}
void CvcPrinter::toStreamCmdDefineFunction(std::ostream& out,
@@ -1353,7 +1366,7 @@ void CvcPrinter::toStreamCmdDefineFunction(std::ostream& out,
}
out << "): ";
}
- out << formula << ';';
+ out << formula << ';' << std::endl;
}
void CvcPrinter::toStreamCmdDeclareType(std::ostream& out,
@@ -1370,7 +1383,7 @@ void CvcPrinter::toStreamCmdDeclareType(std::ostream& out,
}
else
{
- out << id << " : TYPE;";
+ out << id << " : TYPE;" << std::endl;
}
}
@@ -1387,7 +1400,7 @@ void CvcPrinter::toStreamCmdDefineType(std::ostream& out,
}
else
{
- out << id << " : TYPE = " << t << ';';
+ out << id << " : TYPE = " << t << ';' << std::endl;
}
}
@@ -1403,7 +1416,7 @@ void CvcPrinter::toStreamCmdDefineNamedFunction(
void CvcPrinter::toStreamCmdSimplify(std::ostream& out, Node n) const
{
- out << "TRANSFORM " << n << ';';
+ out << "TRANSFORM " << n << ';' << std::endl;
}
void CvcPrinter::toStreamCmdGetValue(std::ostream& out,
@@ -1414,44 +1427,44 @@ void CvcPrinter::toStreamCmdGetValue(std::ostream& out,
copy(nodes.begin(),
nodes.end() - 1,
ostream_iterator<Node>(out, ";\nGET_VALUE "));
- out << nodes.back() << ';';
+ out << nodes.back() << ';' << std::endl;
}
void CvcPrinter::toStreamCmdGetModel(std::ostream& out) const
{
- out << "COUNTERMODEL;";
+ out << "COUNTERMODEL;" << std::endl;
}
void CvcPrinter::toStreamCmdGetAssignment(std::ostream& out) const
{
- out << "% (get-assignment)";
+ out << "% (get-assignment)" << std::endl;
}
void CvcPrinter::toStreamCmdGetAssertions(std::ostream& out) const
{
- out << "WHERE;";
+ out << "WHERE;" << std::endl;
}
void CvcPrinter::toStreamCmdGetProof(std::ostream& out) const
{
- out << "DUMP_PROOF;";
+ out << "DUMP_PROOF;" << std::endl;
}
void CvcPrinter::toStreamCmdGetUnsatCore(std::ostream& out) const
{
- out << "DUMP_UNSAT_CORE;";
+ out << "DUMP_UNSAT_CORE;" << std::endl;
}
void CvcPrinter::toStreamCmdSetBenchmarkStatus(std::ostream& out,
Result::Sat status) const
{
- out << "% (set-info :status " << status << ')';
+ out << "% (set-info :status " << status << ')' << std::endl;
}
void CvcPrinter::toStreamCmdSetBenchmarkLogic(std::ostream& out,
const std::string& logic) const
{
- out << "OPTION \"logic\" \"" << logic << "\";";
+ out << "OPTION \"logic\" \"" << logic << "\";" << std::endl;
}
void CvcPrinter::toStreamCmdSetInfo(std::ostream& out,
@@ -1462,13 +1475,13 @@ void CvcPrinter::toStreamCmdSetInfo(std::ostream& out,
OutputLanguage language =
d_cvc3Mode ? language::output::LANG_CVC3 : language::output::LANG_CVC4;
SExpr::toStream(out, sexpr, language);
- out << ')';
+ out << ')' << std::endl;
}
void CvcPrinter::toStreamCmdGetInfo(std::ostream& out,
const std::string& flag) const
{
- out << "% (get-info " << flag << ')';
+ out << "% (get-info " << flag << ')' << std::endl;
}
void CvcPrinter::toStreamCmdSetOption(std::ostream& out,
@@ -1477,13 +1490,13 @@ void CvcPrinter::toStreamCmdSetOption(std::ostream& out,
{
out << "OPTION \"" << flag << "\" ";
SExpr::toStream(out, sexpr, language::output::LANG_CVC4);
- out << ';';
+ out << ';' << std::endl;
}
void CvcPrinter::toStreamCmdGetOption(std::ostream& out,
const std::string& flag) const
{
- out << "% (get-option " << flag << ')';
+ out << "% (get-option " << flag << ')' << std::endl;
}
void CvcPrinter::toStreamCmdDatatypeDeclaration(
@@ -1552,25 +1565,26 @@ void CvcPrinter::toStreamCmdDatatypeDeclaration(
}
firstDatatype = false;
}
- out << endl << "END;";
+ out << endl << "END;" << std::endl;
}
}
void CvcPrinter::toStreamCmdComment(std::ostream& out,
const std::string& comment) const
{
- out << "% " << comment;
+ out << "% " << comment << std::endl;
}
void CvcPrinter::toStreamCmdEmpty(std::ostream& out,
const std::string& name) const
{
+ out << std::endl;
}
void CvcPrinter::toStreamCmdEcho(std::ostream& out,
const std::string& output) const
{
- out << "ECHO \"" << output << "\";";
+ out << "ECHO \"" << output << "\";" << std::endl;
}
template <class T>
diff --git a/src/printer/smt2/smt2_printer.cpp b/src/printer/smt2/smt2_printer.cpp
index 2cc6c8973..7ef02c576 100644
--- a/src/printer/smt2/smt2_printer.cpp
+++ b/src/printer/smt2/smt2_printer.cpp
@@ -1451,15 +1451,18 @@ void Smt2Printer::toStream(std::ostream& out,
void Smt2Printer::toStreamCmdAssert(std::ostream& out, Node n) const
{
- out << "(assert " << n << ')';
+ out << "(assert " << n << ')' << std::endl;
}
void Smt2Printer::toStreamCmdPush(std::ostream& out) const
{
- out << "(push 1)";
+ out << "(push 1)" << std::endl;
}
-void Smt2Printer::toStreamCmdPop(std::ostream& out) const { out << "(pop 1)"; }
+void Smt2Printer::toStreamCmdPop(std::ostream& out) const
+{
+ out << "(pop 1)" << std::endl;
+}
void Smt2Printer::toStreamCmdCheckSat(std::ostream& out, Node n) const
{
@@ -1477,6 +1480,7 @@ void Smt2Printer::toStreamCmdCheckSat(std::ostream& out, Node n) const
{
out << "(check-sat)";
}
+ out << std::endl;
}
void Smt2Printer::toStreamCmdCheckSatAssuming(
@@ -1484,7 +1488,7 @@ void Smt2Printer::toStreamCmdCheckSatAssuming(
{
out << "(check-sat-assuming ( ";
copy(nodes.begin(), nodes.end(), ostream_iterator<Node>(out, " "));
- out << "))";
+ out << "))" << std::endl;
}
void Smt2Printer::toStreamCmdQuery(std::ostream& out, Node n) const
@@ -1508,34 +1512,25 @@ void Smt2Printer::toStreamCmdQuery(std::ostream& out, Node n) const
void Smt2Printer::toStreamCmdReset(std::ostream& out) const
{
- out << "(reset)";
+ out << "(reset)" << std::endl;
}
void Smt2Printer::toStreamCmdResetAssertions(std::ostream& out) const
{
- out << "(reset-assertions)";
+ out << "(reset-assertions)" << std::endl;
}
-void Smt2Printer::toStreamCmdQuit(std::ostream& out) const { out << "(exit)"; }
+void Smt2Printer::toStreamCmdQuit(std::ostream& out) const
+{
+ out << "(exit)" << std::endl;
+}
void Smt2Printer::toStreamCmdCommandSequence(
std::ostream& out, const std::vector<Command*>& sequence) const
{
- CommandSequence::const_iterator i = sequence.cbegin();
- if (i != sequence.cend())
+ for (Command* i : sequence)
{
- for (;;)
- {
- out << *i;
- if (++i != sequence.cend())
- {
- out << endl;
- }
- else
- {
- break;
- }
- }
+ out << *i;
}
}
@@ -1563,7 +1558,7 @@ void Smt2Printer::toStreamCmdDeclareFunction(std::ostream& out,
type = type.getRangeType();
}
- out << ") " << type << ')';
+ out << ") " << type << ')' << std::endl;
}
void Smt2Printer::toStreamCmdDefineFunction(std::ostream& out,
@@ -1590,7 +1585,7 @@ void Smt2Printer::toStreamCmdDefineFunction(std::ostream& out,
}
}
}
- out << ") " << range << ' ' << formula << ')';
+ out << ") " << range << ' ' << formula << ')' << std::endl;
}
void Smt2Printer::toStreamCmdDefineFunctionRec(
@@ -1659,7 +1654,7 @@ void Smt2Printer::toStreamCmdDefineFunctionRec(
{
out << ")";
}
- out << ")";
+ out << ")" << std::endl;
}
static void toStreamRational(std::ostream& out,
@@ -1704,7 +1699,8 @@ void Smt2Printer::toStreamCmdDeclareType(std::ostream& out,
size_t arity,
TypeNode type) const
{
- out << "(declare-sort " << CVC4::quoteSymbol(id) << " " << arity << ")";
+ out << "(declare-sort " << CVC4::quoteSymbol(id) << " " << arity << ")"
+ << std::endl;
}
void Smt2Printer::toStreamCmdDefineType(std::ostream& out,
@@ -1719,7 +1715,7 @@ void Smt2Printer::toStreamCmdDefineType(std::ostream& out,
params.begin(), params.end() - 1, ostream_iterator<TypeNode>(out, " "));
out << params.back();
}
- out << ") " << t << ")";
+ out << ") " << t << ")" << std::endl;
}
void Smt2Printer::toStreamCmdDefineNamedFunction(
@@ -1738,7 +1734,7 @@ void Smt2Printer::toStreamCmdDefineNamedFunction(
void Smt2Printer::toStreamCmdSimplify(std::ostream& out, Node n) const
{
- out << "(simplify " << n << ')';
+ out << "(simplify " << n << ')' << std::endl;
}
void Smt2Printer::toStreamCmdGetValue(std::ostream& out,
@@ -1746,49 +1742,49 @@ void Smt2Printer::toStreamCmdGetValue(std::ostream& out,
{
out << "(get-value ( ";
copy(nodes.begin(), nodes.end(), ostream_iterator<Node>(out, " "));
- out << "))";
+ out << "))" << std::endl;
}
void Smt2Printer::toStreamCmdGetModel(std::ostream& out) const
{
- out << "(get-model)";
+ out << "(get-model)" << std::endl;
}
void Smt2Printer::toStreamCmdGetAssignment(std::ostream& out) const
{
- out << "(get-assignment)";
+ out << "(get-assignment)" << std::endl;
}
void Smt2Printer::toStreamCmdGetAssertions(std::ostream& out) const
{
- out << "(get-assertions)";
+ out << "(get-assertions)" << std::endl;
}
void Smt2Printer::toStreamCmdGetProof(std::ostream& out) const
{
- out << "(get-proof)";
+ out << "(get-proof)" << std::endl;
}
void Smt2Printer::toStreamCmdGetUnsatAssumptions(std::ostream& out) const
{
- out << "(get-unsat-assumptions)";
+ out << "(get-unsat-assumptions)" << std::endl;
}
void Smt2Printer::toStreamCmdGetUnsatCore(std::ostream& out) const
{
- out << "(get-unsat-core)";
+ out << "(get-unsat-core)" << std::endl;
}
void Smt2Printer::toStreamCmdSetBenchmarkStatus(std::ostream& out,
Result::Sat status) const
{
- out << "(set-info :status " << status << ')';
+ out << "(set-info :status " << status << ')' << std::endl;
}
void Smt2Printer::toStreamCmdSetBenchmarkLogic(std::ostream& out,
const std::string& logic) const
{
- out << "(set-logic " << logic << ')';
+ out << "(set-logic " << logic << ')' << std::endl;
}
void Smt2Printer::toStreamCmdSetInfo(std::ostream& out,
@@ -1797,13 +1793,13 @@ void Smt2Printer::toStreamCmdSetInfo(std::ostream& out,
{
out << "(set-info :" << flag << ' ';
SExpr::toStream(out, sexpr, variantToLanguage(d_variant));
- out << ')';
+ out << ')' << std::endl;
}
void Smt2Printer::toStreamCmdGetInfo(std::ostream& out,
const std::string& flag) const
{
- out << "(get-info :" << flag << ')';
+ out << "(get-info :" << flag << ')' << std::endl;
}
void Smt2Printer::toStreamCmdSetOption(std::ostream& out,
@@ -1812,13 +1808,13 @@ void Smt2Printer::toStreamCmdSetOption(std::ostream& out,
{
out << "(set-option :" << flag << ' ';
SExpr::toStream(out, sexpr, language::output::LANG_SMTLIB_V2_5);
- out << ')';
+ out << ')' << std::endl;
}
void Smt2Printer::toStreamCmdGetOption(std::ostream& out,
const std::string& flag) const
{
- out << "(get-option :" << flag << ')';
+ out << "(get-option :" << flag << ')' << std::endl;
}
void Smt2Printer::toStream(std::ostream& out, const DType& dt) const
@@ -1951,7 +1947,7 @@ void Smt2Printer::toStreamCmdDatatypeDeclaration(
}
out << ")";
}
- out << ")" << endl;
+ out << ")" << std::endl;
}
void Smt2Printer::toStreamCmdComment(std::ostream& out,
@@ -1964,12 +1960,13 @@ void Smt2Printer::toStreamCmdComment(std::ostream& out,
s.replace(pos, 1, d_variant == smt2_0_variant ? "\\\"" : "\"\"");
pos += 2;
}
- out << "(set-info :notes \"" << s << "\")";
+ out << "(set-info :notes \"" << s << "\")" << std::endl;
}
void Smt2Printer::toStreamCmdEmpty(std::ostream& out,
const std::string& name) const
{
+ out << std::endl;
}
void Smt2Printer::toStreamCmdEcho(std::ostream& out,
@@ -1983,7 +1980,7 @@ void Smt2Printer::toStreamCmdEcho(std::ostream& out,
s.replace(pos, 1, d_variant == smt2_0_variant ? "\\\"" : "\"\"");
pos += 2;
}
- out << "(echo \"" << s << "\")";
+ out << "(echo \"" << s << "\")" << std::endl;
}
/*
@@ -2084,31 +2081,31 @@ void Smt2Printer::toStreamCmdSynthFun(std::ostream& out,
{
toStreamSygusGrammar(out, sygusType);
}
- out << ')';
+ out << ')' << std::endl;
}
void Smt2Printer::toStreamCmdDeclareVar(std::ostream& out,
Node var,
TypeNode type) const
{
- out << "(declare-var " << var << ' ' << type << ')';
+ out << "(declare-var " << var << ' ' << type << ')' << std::endl;
}
void Smt2Printer::toStreamCmdConstraint(std::ostream& out, Node n) const
{
- out << "(constraint " << n << ')';
+ out << "(constraint " << n << ')' << std::endl;
}
void Smt2Printer::toStreamCmdInvConstraint(
std::ostream& out, Node inv, Node pre, Node trans, Node post) const
{
out << "(inv-constraint " << inv << ' ' << pre << ' ' << trans << ' ' << post
- << ')';
+ << ')' << std::endl;
}
void Smt2Printer::toStreamCmdCheckSynth(std::ostream& out) const
{
- out << "(check-synth)";
+ out << "(check-synth)" << std::endl;
}
void Smt2Printer::toStreamCmdGetAbduct(std::ostream& out,
@@ -2125,7 +2122,7 @@ void Smt2Printer::toStreamCmdGetAbduct(std::ostream& out,
{
toStreamSygusGrammar(out, sygusType);
}
- out << ')';
+ out << ')' << std::endl;
}
/*
diff --git a/src/proof/unsat_core.cpp b/src/proof/unsat_core.cpp
index e54d976c9..03d614433 100644
--- a/src/proof/unsat_core.cpp
+++ b/src/proof/unsat_core.cpp
@@ -20,7 +20,6 @@
#include "expr/expr_iomanip.h"
#include "options/base_options.h"
#include "printer/printer.h"
-#include "smt/command.h"
#include "smt/smt_engine_scope.h"
namespace CVC4 {
diff --git a/src/prop/cnf_stream.cpp b/src/prop/cnf_stream.cpp
index c46cd5136..203ed34e9 100644
--- a/src/prop/cnf_stream.cpp
+++ b/src/prop/cnf_stream.cpp
@@ -31,7 +31,9 @@
#include "prop/minisat/minisat.h"
#include "prop/prop_engine.h"
#include "prop/theory_proxy.h"
-#include "smt/command.h"
+#include "smt/dump.h"
+#include "smt/smt_engine.h"
+#include "printer/printer.h"
#include "smt/smt_engine_scope.h"
#include "theory/theory.h"
#include "theory/theory_engine.h"
@@ -42,10 +44,14 @@ using namespace CVC4::kind;
namespace CVC4 {
namespace prop {
-CnfStream::CnfStream(SatSolver* satSolver, Registrar* registrar,
- context::Context* context, bool fullLitToNodeMap,
+CnfStream::CnfStream(SatSolver* satSolver,
+ Registrar* registrar,
+ context::Context* context,
+ OutputManager* outMgr,
+ bool fullLitToNodeMap,
std::string name)
: d_satSolver(satSolver),
+ d_outMgr(outMgr),
d_booleanVariables(context),
d_nodeToLiteralMap(context),
d_literalToNodeMap(context),
@@ -54,32 +60,41 @@ CnfStream::CnfStream(SatSolver* satSolver, Registrar* registrar,
d_registrar(registrar),
d_name(name),
d_cnfProof(NULL),
- d_removable(false) {
+ d_removable(false)
+{
}
TseitinCnfStream::TseitinCnfStream(SatSolver* satSolver,
Registrar* registrar,
context::Context* context,
+ OutputManager* outMgr,
ResourceManager* rm,
bool fullLitToNodeMap,
std::string name)
- : CnfStream(satSolver, registrar, context, fullLitToNodeMap, name),
+ : CnfStream(satSolver, registrar, context, outMgr, fullLitToNodeMap, name),
d_resourceManager(rm)
{}
void CnfStream::assertClause(TNode node, SatClause& c) {
Debug("cnf") << "Inserting into stream " << c << " node = " << node << endl;
- if(Dump.isOn("clauses")) {
- if(c.size() == 1) {
- Dump("clauses") << AssertCommand(Expr(getNode(c[0]).toExpr()));
- } else {
+ if (Dump.isOn("clauses") && d_outMgr != nullptr)
+ {
+ const Printer& printer = d_outMgr->getPrinter();
+ std::ostream& out = d_outMgr->getDumpOut();
+ if (c.size() == 1)
+ {
+ printer.toStreamCmdAssert(out, getNode(c[0]));
+ }
+ else
+ {
Assert(c.size() > 1);
NodeBuilder<> b(kind::OR);
- for(unsigned i = 0; i < c.size(); ++i) {
+ for (unsigned i = 0; i < c.size(); ++i)
+ {
b << getNode(c[i]);
}
Node n = b;
- Dump("clauses") << AssertCommand(Expr(n.toExpr()));
+ printer.toStreamCmdAssert(out, n);
}
}
diff --git a/src/prop/cnf_stream.h b/src/prop/cnf_stream.h
index aec4257f2..f538a60a1 100644
--- a/src/prop/cnf_stream.h
+++ b/src/prop/cnf_stream.h
@@ -34,6 +34,8 @@
namespace CVC4 {
+class OutputManager;
+
namespace prop {
class PropEngine;
@@ -56,6 +58,9 @@ class CnfStream {
/** The SAT solver we will be using */
SatSolver* d_satSolver;
+ /** Reference to the output manager of the smt engine */
+ OutputManager* d_outMgr;
+
/** Boolean variables that we translated */
context::CDList<TNode> d_booleanVariables;
@@ -166,12 +171,17 @@ class CnfStream {
* @param satSolver the sat solver to use.
* @param registrar the entity that takes care of preregistration of Nodes.
* @param context the context that the CNF should respect.
+ * @param outMgr Reference to the output manager of the smt engine. Assertions
+ * will not be dumped if outMgr == nullptr.
* @param fullLitToNodeMap maintain a full SAT-literal-to-Node mapping.
* @param name string identifier to distinguish between different instances
* even for non-theory literals.
*/
- CnfStream(SatSolver* satSolver, Registrar* registrar,
- context::Context* context, bool fullLitToNodeMap = false,
+ CnfStream(SatSolver* satSolver,
+ Registrar* registrar,
+ context::Context* context,
+ OutputManager* outMgr = nullptr,
+ bool fullLitToNodeMap = false,
std::string name = "");
/**
@@ -256,6 +266,8 @@ class TseitinCnfStream : public CnfStream {
* @param satSolver the sat solver to use
* @param registrar the entity that takes care of pre-registration of Nodes
* @param context the context that the CNF should respect.
+ * @param outMgr reference to the output manager of the smt engine. Assertions
+ * will not be dumped if outMgr == nullptr.
* @param rm the resource manager of the CNF stream
* @param fullLitToNodeMap maintain a full SAT-literal-to-Node mapping,
* even for non-theory literals
@@ -263,6 +275,7 @@ class TseitinCnfStream : public CnfStream {
TseitinCnfStream(SatSolver* satSolver,
Registrar* registrar,
context::Context* context,
+ OutputManager* outMgr,
ResourceManager* rm,
bool fullLitToNodeMap = false,
std::string name = "");
diff --git a/src/prop/minisat/core/Solver.cc b/src/prop/minisat/core/Solver.cc
index 311224a03..e769ba6cc 100644
--- a/src/prop/minisat/core/Solver.cc
+++ b/src/prop/minisat/core/Solver.cc
@@ -669,9 +669,6 @@ void Solver::cancelUntil(int level) {
// Pop the SMT context
for (int l = trail_lim.size() - level; l > 0; --l) {
d_context->pop();
- if(Dump.isOn("state")) {
- d_proxy->dumpStatePop();
- }
}
for (int c = trail.size()-1; c >= trail_lim[level]; c--){
Var x = var(trail[c]);
diff --git a/src/prop/minisat/core/Solver.h b/src/prop/minisat/core/Solver.h
index a5f3664e8..0630df1b7 100644
--- a/src/prop/minisat/core/Solver.h
+++ b/src/prop/minisat/core/Solver.h
@@ -572,10 +572,6 @@ inline void Solver::newDecisionLevel()
trail_lim.push(trail.size());
flipped.push(false);
d_context->push();
- if (Dump.isOn("state"))
- {
- Dump("state") << CVC4::PushCommand();
- }
}
inline int Solver::decisionLevel () const { return trail_lim.size(); }
diff --git a/src/prop/prop_engine.cpp b/src/prop/prop_engine.cpp
index e71e681e5..4b114aa2c 100644
--- a/src/prop/prop_engine.cpp
+++ b/src/prop/prop_engine.cpp
@@ -34,7 +34,6 @@
#include "prop/sat_solver.h"
#include "prop/sat_solver_factory.h"
#include "prop/theory_proxy.h"
-#include "smt/command.h"
#include "smt/smt_statistics_registry.h"
#include "theory/theory_engine.h"
#include "theory/theory_registrar.h"
@@ -70,7 +69,8 @@ public:
PropEngine::PropEngine(TheoryEngine* te,
Context* satContext,
UserContext* userContext,
- ResourceManager* rm)
+ ResourceManager* rm,
+ OutputManager& outMgr)
: d_inCheckSat(false),
d_theoryEngine(te),
d_context(satContext),
@@ -79,7 +79,8 @@ PropEngine::PropEngine(TheoryEngine* te,
d_registrar(NULL),
d_cnfStream(NULL),
d_interrupted(false),
- d_resourceManager(rm)
+ d_resourceManager(rm),
+ d_outMgr(outMgr)
{
Debug("prop") << "Constructing the PropEngine" << endl;
@@ -91,7 +92,7 @@ PropEngine::PropEngine(TheoryEngine* te,
d_registrar = new theory::TheoryRegistrar(d_theoryEngine);
d_cnfStream = new CVC4::prop::TseitinCnfStream(
- d_satSolver, d_registrar, userContext, rm, true);
+ d_satSolver, d_registrar, userContext, &d_outMgr, rm, true);
d_theoryProxy = new TheoryProxy(
this, d_theoryEngine, d_decisionEngine.get(), d_context, d_cnfStream);
diff --git a/src/prop/prop_engine.h b/src/prop/prop_engine.h
index 1df862568..75f628d9a 100644
--- a/src/prop/prop_engine.h
+++ b/src/prop/prop_engine.h
@@ -36,6 +36,7 @@ namespace CVC4 {
class ResourceManager;
class DecisionEngine;
+class OutputManager;
class TheoryEngine;
namespace theory {
@@ -62,7 +63,8 @@ class PropEngine
PropEngine(TheoryEngine*,
context::Context* satContext,
context::UserContext* userContext,
- ResourceManager* rm);
+ ResourceManager* rm,
+ OutputManager& outMgr);
/**
* Destructor.
@@ -255,6 +257,8 @@ class PropEngine
/** Pointer to resource manager for associated SmtEngine */
ResourceManager* d_resourceManager;
+ /** Reference to the output manager of the smt engine */
+ OutputManager& d_outMgr;
};
} // namespace prop
diff --git a/src/prop/theory_proxy.cpp b/src/prop/theory_proxy.cpp
index 8165c5d8a..a89c8799f 100644
--- a/src/prop/theory_proxy.cpp
+++ b/src/prop/theory_proxy.cpp
@@ -22,7 +22,6 @@
#include "prop/cnf_stream.h"
#include "prop/prop_engine.h"
#include "proof/cnf_proof.h"
-#include "smt/command.h"
#include "smt/smt_statistics_registry.h"
#include "theory/rewriter.h"
#include "theory/theory_engine.h"
@@ -150,11 +149,5 @@ SatValue TheoryProxy::getDecisionPolarity(SatVariable var) {
return d_decisionEngine->getPolarity(var);
}
-void TheoryProxy::dumpStatePop() {
- if(Dump.isOn("state")) {
- Dump("state") << PopCommand();
- }
-}
-
}/* CVC4::prop namespace */
}/* CVC4 namespace */
diff --git a/src/prop/theory_proxy.h b/src/prop/theory_proxy.h
index 7fd735bf2..688bd4e1c 100644
--- a/src/prop/theory_proxy.h
+++ b/src/prop/theory_proxy.h
@@ -88,9 +88,6 @@ class TheoryProxy
SatValue getDecisionPolarity(SatVariable var);
- /** Shorthand for Dump("state") << PopCommand() */
- void dumpStatePop();
-
private:
/** The prop engine we are using. */
PropEngine* d_propEngine;
diff --git a/src/smt/command.cpp b/src/smt/command.cpp
index 64ef60906..38c799fca 100644
--- a/src/smt/command.cpp
+++ b/src/smt/command.cpp
@@ -106,20 +106,6 @@ std::ostream& operator<<(std::ostream& out, BenchmarkStatus status)
}
// !!! Temporary until commands are migrated to the new API !!!
-std::vector<Node> exprVectorToNodes(const std::vector<Expr>& exprs)
-{
- std::vector<Node> nodes;
- nodes.reserve(exprs.size());
-
- for (Expr e : exprs)
- {
- nodes.push_back(Node::fromExpr(e));
- }
-
- return nodes;
-}
-
-// !!! Temporary until commands are migrated to the new API !!!
std::vector<TypeNode> typeVectorToTypeNodes(const std::vector<Type>& types)
{
std::vector<TypeNode> typeNodes;
@@ -2977,7 +2963,7 @@ void SetBenchmarkStatusCommand::toStream(std::ostream& out,
size_t dag,
OutputLanguage language) const
{
- Result::Sat status;
+ Result::Sat status = Result::SAT_UNKNOWN;
switch (d_status)
{
case BenchmarkStatus::SMT_SATISFIABLE: status = Result::SAT; break;
diff --git a/src/smt/dump.cpp b/src/smt/dump.cpp
index d8d486e12..28cf8a34f 100644
--- a/src/smt/dump.cpp
+++ b/src/smt/dump.cpp
@@ -19,9 +19,29 @@
#include "base/output.h"
#include "lib/strtok_r.h"
#include "preprocessing/preprocessing_pass_registry.h"
+#include "smt/command.h"
+#include "smt/node_command.h"
namespace CVC4 {
+CVC4dumpstream& CVC4dumpstream::operator<<(const Command& c)
+{
+ if (d_os != nullptr)
+ {
+ (*d_os) << c;
+ }
+ return *this;
+}
+
+CVC4dumpstream& CVC4dumpstream::operator<<(const NodeCommand& nc)
+{
+ if (d_os != nullptr)
+ {
+ (*d_os) << nc;
+ }
+ return *this;
+}
+
DumpC DumpChannel CVC4_PUBLIC;
std::ostream& DumpC::setStream(std::ostream* os) {
@@ -100,42 +120,6 @@ void DumpC::setDumpFromString(const std::string& optarg) {
|| !strcmp(optargPtr, "bv-rewrites")
|| !strcmp(optargPtr, "theory::fullcheck"))
{
- // These are "non-state-dumping" modes. If state (SAT decisions,
- // propagations, etc.) is dumped, it will interfere with the validity
- // of these generated queries.
- if (Dump.isOn("state"))
- {
- throw OptionException(std::string("dump option `") + optargPtr +
- "' conflicts with a previous, "
- "state-dumping dump option. You cannot "
- "mix stateful and non-stateful dumping modes; "
- "see --dump help.");
- }
- else
- {
- Dump.on("no-permit-state");
- }
- }
- else if (!strcmp(optargPtr, "state")
- || !strcmp(optargPtr, "missed-t-conflicts")
- || !strcmp(optargPtr, "t-propagations")
- || !strcmp(optargPtr, "missed-t-propagations"))
- {
- // These are "state-dumping" modes. If state (SAT decisions,
- // propagations, etc.) is not dumped, it will interfere with the
- // validity of these generated queries.
- if (Dump.isOn("no-permit-state"))
- {
- throw OptionException(std::string("dump option `") + optargPtr +
- "' conflicts with a previous, "
- "non-state-dumping dump option. You cannot "
- "mix stateful and non-stateful dumping modes; "
- "see --dump help.");
- }
- else
- {
- Dump.on("state");
- }
}
else if (!strcmp(optargPtr, "help"))
{
@@ -152,14 +136,6 @@ void DumpC::setDumpFromString(const std::string& optarg) {
puts(ss.str().c_str());
exit(1);
}
- else if (!strcmp(optargPtr, "bv-abstraction"))
- {
- Dump.on("bv-abstraction");
- }
- else if (!strcmp(optargPtr, "bv-algebraic"))
- {
- Dump.on("bv-algebraic");
- }
else
{
throw OptionException(std::string("unknown option for --dump: `")
@@ -222,49 +198,25 @@ clauses\n\
+ Do all the preprocessing outlined above, and dump the CNF-converted\n\
output\n\
\n\
-state\n\
-+ Dump all contextual assertions (e.g., SAT decisions, propagations..).\n\
- Implied by all \"stateful\" modes below and conflicts with all\n\
- non-stateful modes below.\n\
-\n\
-t-conflicts [non-stateful]\n\
+t-conflicts\n\
+ Output correctness queries for all theory conflicts\n\
\n\
-missed-t-conflicts [stateful]\n\
-+ Output completeness queries for theory conflicts\n\
-\n\
-t-propagations [stateful]\n\
-+ Output correctness queries for all theory propagations\n\
-\n\
-missed-t-propagations [stateful]\n\
-+ Output completeness queries for theory propagations (LARGE and EXPENSIVE)\n\
-\n\
-t-lemmas [non-stateful]\n\
+t-lemmas\n\
+ Output correctness queries for all theory lemmas\n\
\n\
-t-explanations [non-stateful]\n\
+t-explanations\n\
+ Output correctness queries for all theory explanations\n\
\n\
-bv-rewrites [non-stateful]\n\
+bv-rewrites\n\
+ Output correctness queries for all bitvector rewrites\n\
\n\
-bv-abstraction [non-stateful]\n\
-+ Output correctness queries for all bv abstraction \n\
-\n\
-bv-algebraic [non-stateful]\n\
-+ Output correctness queries for bv algebraic solver. \n\
-\n\
-theory::fullcheck [non-stateful]\n\
+theory::fullcheck\n\
+ Output completeness queries for all full-check effort-level theory checks\n\
\n\
Dump modes can be combined with multiple uses of --dump. Generally you want\n\
raw-benchmark or, alternatively, one from the assertions category (either\n\
-assertions or clauses), and perhaps one or more stateful or non-stateful modes\n\
+assertions or clauses), and perhaps one or more other modes\n\
for checking correctness and completeness of decision procedure implementations.\n\
-Stateful modes dump the contextual assertions made by the core solver (all\n\
-decisions and propagations as assertions); this affects the validity of the\n\
-resulting correctness and completeness queries, so of course stateful and\n\
-non-stateful modes cannot be mixed in the same run.\n\
\n\
The --output-language option controls the language used for dumping, and\n\
this allows you to connect CVC4 to another solver implementation via a UNIX\n\
diff --git a/src/smt/dump.h b/src/smt/dump.h
index 4c0efeb6e..ec13a9ae9 100644
--- a/src/smt/dump.h
+++ b/src/smt/dump.h
@@ -20,11 +20,12 @@
#define CVC4__DUMP_H
#include "base/output.h"
-#include "smt/command.h"
-#include "smt/node_command.h"
namespace CVC4 {
+class Command;
+class NodeCommand;
+
#if defined(CVC4_DUMPING) && !defined(CVC4_MUZZLE)
class CVC4_PUBLIC CVC4dumpstream
@@ -33,27 +34,14 @@ class CVC4_PUBLIC CVC4dumpstream
CVC4dumpstream() : d_os(nullptr) {}
CVC4dumpstream(std::ostream& os) : d_os(&os) {}
- CVC4dumpstream& operator<<(const Command& c) {
- if (d_os != nullptr)
- {
- (*d_os) << c << std::endl;
- }
- return *this;
- }
+ CVC4dumpstream& operator<<(const Command& c);
/** A convenience function for dumping internal commands.
*
* Since Commands are now part of the public API, internal code should use
* NodeCommands and this function (instead of the one above) to dump them.
*/
- CVC4dumpstream& operator<<(const NodeCommand& nc)
- {
- if (d_os != nullptr)
- {
- (*d_os) << nc << std::endl;
- }
- return *this;
- }
+ CVC4dumpstream& operator<<(const NodeCommand& nc);
private:
std::ostream* d_os;
diff --git a/src/smt/dump_manager.cpp b/src/smt/dump_manager.cpp
index 033be405f..849339106 100644
--- a/src/smt/dump_manager.cpp
+++ b/src/smt/dump_manager.cpp
@@ -17,6 +17,7 @@
#include "expr/expr_manager.h"
#include "options/smt_options.h"
#include "smt/dump.h"
+#include "smt/node_command.h"
namespace CVC4 {
namespace smt {
@@ -98,11 +99,11 @@ void DumpManager::setPrintFuncInModel(Node f, bool p)
Trace("setp-model") << "Set printInModel " << f << " to " << p << std::endl;
for (std::unique_ptr<NodeCommand>& c : d_modelGlobalCommands)
{
- DeclareFunctionCommand* dfc =
- dynamic_cast<DeclareFunctionCommand*>(c.get());
+ DeclareFunctionNodeCommand* dfc =
+ dynamic_cast<DeclareFunctionNodeCommand*>(c.get());
if (dfc != NULL)
{
- Node df = Node::fromExpr(dfc->getFunction());
+ Node df = dfc->getFunction();
if (df == f)
{
dfc->setPrintInModel(p);
@@ -111,10 +112,11 @@ void DumpManager::setPrintFuncInModel(Node f, bool p)
}
for (NodeCommand* c : d_modelCommands)
{
- DeclareFunctionCommand* dfc = dynamic_cast<DeclareFunctionCommand*>(c);
+ DeclareFunctionNodeCommand* dfc =
+ dynamic_cast<DeclareFunctionNodeCommand*>(c);
if (dfc != NULL)
{
- Node df = Node::fromExpr(dfc->getFunction());
+ Node df = dfc->getFunction();
if (df == f)
{
dfc->setPrintInModel(p);
diff --git a/src/smt/dump_manager.h b/src/smt/dump_manager.h
index 2ce0570e4..5954817bd 100644
--- a/src/smt/dump_manager.h
+++ b/src/smt/dump_manager.h
@@ -22,9 +22,11 @@
#include "context/cdlist.h"
#include "expr/node.h"
-#include "smt/node_command.h"
namespace CVC4 {
+
+class NodeCommand;
+
namespace smt {
/**
diff --git a/src/smt/listeners.cpp b/src/smt/listeners.cpp
index 52ddcf156..fdf32fa41 100644
--- a/src/smt/listeners.cpp
+++ b/src/smt/listeners.cpp
@@ -18,9 +18,10 @@
#include "expr/expr.h"
#include "expr/node_manager_attributes.h"
#include "options/smt_options.h"
-#include "smt/node_command.h"
+#include "printer/printer.h"
#include "smt/dump.h"
#include "smt/dump_manager.h"
+#include "smt/node_command.h"
#include "smt/smt_engine.h"
#include "smt/smt_engine_scope.h"
@@ -36,7 +37,11 @@ void ResourceOutListener::notify()
d_smt.interrupt();
}
-SmtNodeManagerListener::SmtNodeManagerListener(DumpManager& dm) : d_dm(dm) {}
+SmtNodeManagerListener::SmtNodeManagerListener(DumpManager& dm,
+ OutputManager& outMgr)
+ : d_dm(dm), d_outMgr(outMgr)
+{
+}
void SmtNodeManagerListener::nmNotifyNewSort(TypeNode tn, uint32_t flags)
{
@@ -92,7 +97,8 @@ void SmtNodeManagerListener::nmNotifyNewSkolem(TNode n,
DeclareFunctionNodeCommand c(id, n, n.getType());
if (Dump.isOn("skolems") && comment != "")
{
- Dump("skolems") << CommentCommand(id + " is " + comment);
+ d_outMgr.getPrinter().toStreamCmdComment(d_outMgr.getDumpOut(),
+ id + " is " + comment);
}
if ((flags & ExprManager::VAR_FLAG_DEFINED) == 0)
{
diff --git a/src/smt/listeners.h b/src/smt/listeners.h
index 77d6d257f..0efbed096 100644
--- a/src/smt/listeners.h
+++ b/src/smt/listeners.h
@@ -24,6 +24,7 @@
namespace CVC4 {
+class OutputManager;
class SmtEngine;
namespace smt {
@@ -49,7 +50,7 @@ class DumpManager;
class SmtNodeManagerListener : public NodeManagerListener
{
public:
- SmtNodeManagerListener(DumpManager& dm);
+ SmtNodeManagerListener(DumpManager& dm, OutputManager& outMgr);
/** Notify when new sort is created */
void nmNotifyNewSort(TypeNode tn, uint32_t flags) override;
/** Notify when new sort constructor is created */
@@ -69,6 +70,8 @@ class SmtNodeManagerListener : public NodeManagerListener
private:
/** Reference to the dump manager of smt engine */
DumpManager& d_dm;
+ /** Reference to the output manager of the smt engine */
+ OutputManager& d_outMgr;
};
} // namespace smt
diff --git a/src/smt/output_manager.cpp b/src/smt/output_manager.cpp
new file mode 100644
index 000000000..a801b7527
--- /dev/null
+++ b/src/smt/output_manager.cpp
@@ -0,0 +1,35 @@
+/********************* */
+/*! \file output_manager.cpp
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Abdalrhman Mohamed
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Implementation of OutputManager functions.
+ **
+ ** Implementation of OutputManager functions.
+ **/
+
+#include "smt/output_manager.h"
+
+#include "smt/smt_engine.h"
+
+namespace CVC4 {
+
+OutputManager::OutputManager(SmtEngine* smt) : d_smt(smt) {}
+
+const Printer& OutputManager::getPrinter() const
+{
+ return *d_smt->getPrinter();
+}
+
+std::ostream& OutputManager::getDumpOut() const
+{
+ return *d_smt->getOptions().getOut();
+}
+
+} // namespace CVC4
diff --git a/src/smt/output_manager.h b/src/smt/output_manager.h
new file mode 100644
index 000000000..5ffd6b964
--- /dev/null
+++ b/src/smt/output_manager.h
@@ -0,0 +1,57 @@
+/********************* */
+/*! \file output_manager.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Abdalrhman Mohamed
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief The output manager for the SmtEngine.
+ **
+ ** The output manager provides helper functions for printing commands
+ ** internally.
+ **/
+
+#ifndef CVC4__SMT__OUTPUT_MANAGER_H
+#define CVC4__SMT__OUTPUT_MANAGER_H
+
+#include <ostream>
+
+namespace CVC4 {
+
+class Printer;
+class SmtEngine;
+
+/** This utility class provides helper functions for printing commands
+ * internally */
+class OutputManager
+{
+ public:
+ /** Constructor
+ *
+ * @param smt SMT engine to manage output for
+ */
+ explicit OutputManager(SmtEngine* smt);
+
+ /** Get the current printer based on the current options
+ *
+ * @return the current printer
+ */
+ const Printer& getPrinter() const;
+
+ /** Get the output stream that --dump=X should print to
+ *
+ * @return the output stream
+ */
+ std::ostream& getDumpOut() const;
+
+ private:
+ SmtEngine* d_smt;
+};
+
+} // namespace CVC4
+
+#endif // CVC4__SMT__OUTPUT_MANAGER_H
diff --git a/src/smt/preprocessor.cpp b/src/smt/preprocessor.cpp
index ea5ef2bad..c376c99ba 100644
--- a/src/smt/preprocessor.cpp
+++ b/src/smt/preprocessor.cpp
@@ -15,9 +15,10 @@
#include "smt/preprocessor.h"
#include "options/smt_options.h"
+#include "printer/printer.h"
#include "smt/abstract_values.h"
#include "smt/assertions.h"
-#include "smt/command.h"
+#include "smt/dump.h"
#include "smt/smt_engine.h"
using namespace CVC4::theory;
@@ -128,7 +129,8 @@ Node Preprocessor::simplify(const Node& node, bool removeItes)
Trace("smt") << "SMT simplify(" << node << ")" << endl;
if (Dump.isOn("benchmark"))
{
- Dump("benchmark") << SimplifyCommand(node.toExpr());
+ d_smt.getOutputManager().getPrinter().toStreamCmdSimplify(
+ d_smt.getOutputManager().getDumpOut(), node);
}
Node nas = d_absValues.substituteAbstractValues(node);
if (options::typeChecking())
diff --git a/src/smt/process_assertions.cpp b/src/smt/process_assertions.cpp
index 33d092def..944f35593 100644
--- a/src/smt/process_assertions.cpp
+++ b/src/smt/process_assertions.cpp
@@ -27,7 +27,9 @@
#include "options/uf_options.h"
#include "preprocessing/assertion_pipeline.h"
#include "preprocessing/preprocessing_pass_registry.h"
+#include "printer/printer.h"
#include "smt/defined_function.h"
+#include "smt/dump.h"
#include "smt/smt_engine.h"
#include "theory/logic_info.h"
#include "theory/quantifiers/fun_def_process.h"
@@ -562,7 +564,8 @@ void ProcessAssertions::dumpAssertions(const char* key,
for (unsigned i = 0; i < assertionList.size(); ++i)
{
TNode n = assertionList[i];
- Dump("assertions") << AssertCommand(Expr(n.toExpr()));
+ d_smt.getOutputManager().getPrinter().toStreamCmdAssert(
+ d_smt.getOutputManager().getDumpOut(), n);
}
}
}
diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp
index d271ca05d..d520d664c 100644
--- a/src/smt/smt_engine.cpp
+++ b/src/smt/smt_engine.cpp
@@ -71,7 +71,7 @@
#include "smt/abduction_solver.h"
#include "smt/abstract_values.h"
#include "smt/assertions.h"
-#include "smt/command.h"
+#include "smt/node_command.h"
#include "smt/defined_function.h"
#include "smt/dump_manager.h"
#include "smt/expr_names.h"
@@ -114,9 +114,19 @@ using namespace CVC4::theory;
namespace CVC4 {
-namespace smt {
+// !!! Temporary until commands are migrated to the new API !!!
+std::vector<Node> exprVectorToNodes(const std::vector<Expr>& exprs)
+{
+ std::vector<Node> nodes;
+ nodes.reserve(exprs.size());
-}/* namespace CVC4::smt */
+ for (Expr e : exprs)
+ {
+ nodes.push_back(Node::fromExpr(e));
+ }
+
+ return nodes;
+}
SmtEngine::SmtEngine(ExprManager* em, Options* optr)
: d_state(new SmtEngineState(*this)),
@@ -127,7 +137,7 @@ SmtEngine::SmtEngine(ExprManager* em, Options* optr)
d_exprNames(new ExprNames(getUserContext())),
d_dumpm(new DumpManager(getUserContext())),
d_routListener(new ResourceOutListener(*this)),
- d_snmListener(new SmtNodeManagerListener(*d_dumpm.get())),
+ d_snmListener(new SmtNodeManagerListener(*d_dumpm.get(), d_outMgr)),
d_smtSolver(nullptr),
d_proofManager(nullptr),
d_pfManager(nullptr),
@@ -143,6 +153,7 @@ SmtEngine::SmtEngine(ExprManager* em, Options* optr)
d_isInternalSubsolver(false),
d_statisticsRegistry(nullptr),
d_stats(nullptr),
+ d_outMgr(this),
d_resourceManager(nullptr),
d_optm(nullptr),
d_pp(nullptr),
@@ -183,7 +194,8 @@ SmtEngine::SmtEngine(ExprManager* em, Options* optr)
d_smtSolver.reset(
new SmtSolver(*this, *d_state, d_resourceManager.get(), *d_pp, *d_stats));
// make the SyGuS solver
- d_sygusSolver.reset(new SygusSolver(*d_smtSolver, *d_pp, getUserContext()));
+ d_sygusSolver.reset(
+ new SygusSolver(*d_smtSolver, *d_pp, getUserContext(), d_outMgr));
// make the quantifier elimination solver
d_quantElimSolver.reset(new QuantElimSolver(*d_smtSolver));
@@ -285,12 +297,13 @@ void SmtEngine::finishInit()
{
LogicInfo everything;
everything.lock();
- Dump("benchmark") << CommentCommand(
+ getOutputManager().getPrinter().toStreamCmdComment(
+ getOutputManager().getDumpOut(),
"CVC4 always dumps the most general, all-supported logic (below), as "
"some internals might require the use of a logic more general than "
- "the input.")
- << SetBenchmarkLogicCommand(
- everything.getLogicString());
+ "the input.");
+ getOutputManager().getPrinter().toStreamCmdSetBenchmarkLogic(
+ getOutputManager().getDumpOut(), everything.getLogicString());
}
// initialize the dump manager
@@ -404,8 +417,8 @@ void SmtEngine::setLogic(const std::string& s)
// dump out a set-logic command
if (Dump.isOn("raw-benchmark"))
{
- Dump("raw-benchmark")
- << SetBenchmarkLogicCommand(d_logic.getLogicString());
+ getOutputManager().getPrinter().toStreamCmdSetBenchmarkLogic(
+ getOutputManager().getDumpOut(), d_logic.getLogicString());
}
}
catch (IllegalArgumentException& e)
@@ -459,12 +472,14 @@ void SmtEngine::setInfo(const std::string& key, const CVC4::SExpr& value)
if(Dump.isOn("benchmark")) {
if(key == "status") {
string s = value.getValue();
- BenchmarkStatus status =
- (s == "sat") ? SMT_SATISFIABLE :
- ((s == "unsat") ? SMT_UNSATISFIABLE : SMT_UNKNOWN);
- Dump("benchmark") << SetBenchmarkStatusCommand(status);
+ Result::Sat status =
+ (s == "sat") ? Result::SAT
+ : ((s == "unsat") ? Result::UNSAT : Result::SAT_UNKNOWN);
+ getOutputManager().getPrinter().toStreamCmdSetBenchmarkStatus(
+ getOutputManager().getDumpOut(), status);
} else {
- Dump("benchmark") << SetInfoCommand(key, value);
+ getOutputManager().getPrinter().toStreamCmdSetInfo(
+ getOutputManager().getDumpOut(), key, value);
}
}
@@ -774,16 +789,15 @@ void SmtEngine::defineFunctionsRec(
if (Dump.isOn("raw-benchmark"))
{
- std::vector<api::Term> tFuncs = api::exprVectorToTerms(d_solver, funcs);
- std::vector<std::vector<api::Term>> tFormals;
+ std::vector<Node> nFuncs = exprVectorToNodes(funcs);
+ std::vector<std::vector<Node>> nFormals;
for (const std::vector<Expr>& formal : formals)
{
- tFormals.emplace_back(api::exprVectorToTerms(d_solver, formal));
+ nFormals.emplace_back(exprVectorToNodes(formal));
}
- std::vector<api::Term> tFormulas =
- api::exprVectorToTerms(d_solver, formulas);
- Dump("raw-benchmark") << DefineFunctionRecCommand(
- d_solver, tFuncs, tFormals, tFormulas, global);
+ std::vector<Node> nFormulas = exprVectorToNodes(formulas);
+ getOutputManager().getPrinter().toStreamCmdDefineFunctionRec(
+ getOutputManager().getDumpOut(), nFuncs, nFormals, nFormulas);
}
ExprManager* em = getExprManager();
@@ -930,7 +944,11 @@ void SmtEngine::notifyPostSolvePost()
Result SmtEngine::checkSat(const Expr& assumption, bool inUnsatCore)
{
- Dump("benchmark") << CheckSatCommand(assumption);
+ if (Dump.isOn("benchmark"))
+ {
+ getOutputManager().getPrinter().toStreamCmdCheckSat(
+ getOutputManager().getDumpOut(), assumption);
+ }
std::vector<Node> assump;
if (!assumption.isNull())
{
@@ -941,13 +959,18 @@ Result SmtEngine::checkSat(const Expr& assumption, bool inUnsatCore)
Result SmtEngine::checkSat(const vector<Expr>& assumptions, bool inUnsatCore)
{
- if (assumptions.empty())
- {
- Dump("benchmark") << CheckSatCommand();
- }
- else
+ if (Dump.isOn("benchmark"))
{
- Dump("benchmark") << CheckSatAssumingCommand(assumptions);
+ if (assumptions.empty())
+ {
+ getOutputManager().getPrinter().toStreamCmdCheckSat(
+ getOutputManager().getDumpOut());
+ }
+ else
+ {
+ getOutputManager().getPrinter().toStreamCmdCheckSatAssuming(
+ getOutputManager().getDumpOut(), exprVectorToNodes(assumptions));
+ }
}
std::vector<Node> assumps;
for (const Expr& e : assumptions)
@@ -959,7 +982,11 @@ Result SmtEngine::checkSat(const vector<Expr>& assumptions, bool inUnsatCore)
Result SmtEngine::checkEntailed(const Expr& node, bool inUnsatCore)
{
- Dump("benchmark") << QueryCommand(node, inUnsatCore);
+ if (Dump.isOn("benchmark"))
+ {
+ getOutputManager().getPrinter().toStreamCmdQuery(
+ getOutputManager().getDumpOut(), node.getNode());
+ }
return checkSatInternal(node.isNull()
? std::vector<Node>()
: std::vector<Node>{Node::fromExpr(node)},
@@ -1045,7 +1072,8 @@ std::vector<Node> SmtEngine::getUnsatAssumptions(void)
finishInit();
if (Dump.isOn("benchmark"))
{
- Dump("benchmark") << GetUnsatAssumptionsCommand();
+ getOutputManager().getPrinter().toStreamCmdGetUnsatAssumptions(
+ getOutputManager().getDumpOut());
}
UnsatCore core = getUnsatCoreInternal();
std::vector<Node> res;
@@ -1069,7 +1097,8 @@ Result SmtEngine::assertFormula(const Node& formula, bool inUnsatCore)
Trace("smt") << "SmtEngine::assertFormula(" << formula << ")" << endl;
if (Dump.isOn("raw-benchmark")) {
- Dump("raw-benchmark") << AssertCommand(formula.toExpr());
+ getOutputManager().getPrinter().toStreamCmdAssert(
+ getOutputManager().getDumpOut(), formula);
}
// Substitute out any abstract values in ex
@@ -1090,8 +1119,11 @@ void SmtEngine::declareSygusVar(const std::string& id, Node var, TypeNode type)
SmtScope smts(this);
finishInit();
d_sygusSolver->declareSygusVar(id, var, type);
- Dump("raw-benchmark") << DeclareSygusVarCommand(
- id, var.toExpr(), type.toType());
+ if (Dump.isOn("raw-benchmark"))
+ {
+ getOutputManager().getPrinter().toStreamCmdDeclareVar(
+ getOutputManager().getDumpOut(), var, type);
+ }
// don't need to set that the conjecture is stale
}
@@ -1112,22 +1144,14 @@ void SmtEngine::declareSynthFun(const std::string& id,
if (Dump.isOn("raw-benchmark"))
{
- std::stringstream ss;
-
- Printer::getPrinter(options::outputLanguage())
- ->toStreamCmdSynthFun(ss,
- id,
- vars,
- func.getType().isFunction()
- ? func.getType().getRangeType()
- : func.getType(),
- isInv,
- sygusType);
-
- // must print it on the standard output channel since it is not possible
- // to print anything except for commands with Dump.
- std::ostream& out = *d_options.getOut();
- out << ss.str() << std::endl;
+ getOutputManager().getPrinter().toStreamCmdSynthFun(
+ getOutputManager().getDumpOut(),
+ id,
+ vars,
+ func.getType().isFunction() ? func.getType().getRangeType()
+ : func.getType(),
+ isInv,
+ sygusType);
}
}
@@ -1136,7 +1160,11 @@ void SmtEngine::assertSygusConstraint(Node constraint)
SmtScope smts(this);
finishInit();
d_sygusSolver->assertSygusConstraint(constraint);
- Dump("raw-benchmark") << SygusConstraintCommand(constraint.toExpr());
+ if (Dump.isOn("raw-benchmark"))
+ {
+ getOutputManager().getPrinter().toStreamCmdConstraint(
+ getOutputManager().getDumpOut(), constraint);
+ }
}
void SmtEngine::assertSygusInvConstraint(Node inv,
@@ -1147,8 +1175,11 @@ void SmtEngine::assertSygusInvConstraint(Node inv,
SmtScope smts(this);
finishInit();
d_sygusSolver->assertSygusInvConstraint(inv, pre, trans, post);
- Dump("raw-benchmark") << SygusInvConstraintCommand(
- inv.toExpr(), pre.toExpr(), trans.toExpr(), post.toExpr());
+ if (Dump.isOn("raw-benchmark"))
+ {
+ getOutputManager().getPrinter().toStreamCmdInvConstraint(
+ getOutputManager().getDumpOut(), inv, pre, trans, post);
+ }
}
Result SmtEngine::checkSynth()
@@ -1192,7 +1223,7 @@ Node SmtEngine::getValue(const Node& ex) const
Trace("smt") << "SMT getValue(" << ex << ")" << endl;
if(Dump.isOn("benchmark")) {
- Dump("benchmark") << GetValueCommand(ex.toExpr());
+ d_outMgr.getPrinter().toStreamCmdGetValue(d_outMgr.getDumpOut(), {ex});
}
TypeNode expectedType = ex.getType();
@@ -1290,7 +1321,8 @@ vector<pair<Expr, Expr>> SmtEngine::getAssignment()
SmtScope smts(this);
finishInit();
if(Dump.isOn("benchmark")) {
- Dump("benchmark") << GetAssignmentCommand();
+ getOutputManager().getPrinter().toStreamCmdGetAssignment(
+ getOutputManager().getDumpOut());
}
if(!options::produceAssignments()) {
const char* msg =
@@ -1351,7 +1383,8 @@ Model* SmtEngine::getModel() {
finishInit();
if(Dump.isOn("benchmark")) {
- Dump("benchmark") << GetModelCommand();
+ getOutputManager().getPrinter().toStreamCmdGetModel(
+ getOutputManager().getDumpOut());
}
TheoryModel* m = getAvailableModel("get model");
@@ -1384,7 +1417,8 @@ Result SmtEngine::blockModel()
if (Dump.isOn("benchmark"))
{
- Dump("benchmark") << BlockModelCommand();
+ getOutputManager().getPrinter().toStreamCmdBlockModel(
+ getOutputManager().getDumpOut());
}
TheoryModel* m = getAvailableModel("block model");
@@ -1415,7 +1449,8 @@ Result SmtEngine::blockModelValues(const std::vector<Expr>& exprs)
"block model values must be called on non-empty set of terms");
if (Dump.isOn("benchmark"))
{
- Dump("benchmark") << BlockModelValuesCommand(exprs);
+ getOutputManager().getPrinter().toStreamCmdBlockModelValues(
+ getOutputManager().getDumpOut(), exprVectorToNodes(exprs));
}
TheoryModel* m = getAvailableModel("block model values");
@@ -1573,7 +1608,8 @@ void SmtEngine::checkModel(bool hardFailure) {
SubstitutionMap substitutions(&fakeContext, /* substituteUnderQuantifiers = */ false);
for(size_t k = 0; k < m->getNumCommands(); ++k) {
- const DeclareFunctionCommand* c = dynamic_cast<const DeclareFunctionCommand*>(m->getCommand(k));
+ const DeclareFunctionNodeCommand* c =
+ dynamic_cast<const DeclareFunctionNodeCommand*>(m->getCommand(k));
Notice() << "SmtEngine::checkModel(): model command " << k << " : " << m->getCommand(k) << endl;
if(c == NULL) {
// we don't care about DECLARE-DATATYPES, DECLARE-SORT, ...
@@ -1584,7 +1620,7 @@ void SmtEngine::checkModel(bool hardFailure) {
// We'll first do some checks, then add to our substitution map
// the mapping: function symbol |-> value
- Expr func = c->getFunction();
+ Expr func = c->getFunction().toExpr();
Node val = m->getValue(func);
Notice() << "SmtEngine::checkModel(): adding substitution: " << func << " |-> " << val << endl;
@@ -1767,7 +1803,8 @@ UnsatCore SmtEngine::getUnsatCore() {
SmtScope smts(this);
finishInit();
if(Dump.isOn("benchmark")) {
- Dump("benchmark") << GetUnsatCoreCommand();
+ getOutputManager().getPrinter().toStreamCmdGetUnsatCore(
+ getOutputManager().getDumpOut());
}
return getUnsatCoreInternal();
}
@@ -1896,7 +1933,8 @@ std::vector<Expr> SmtEngine::getAssertions()
finishInit();
d_state->doPendingPops();
if(Dump.isOn("benchmark")) {
- Dump("benchmark") << GetAssertionsCommand();
+ getOutputManager().getPrinter().toStreamCmdGetAssertions(
+ getOutputManager().getDumpOut());
}
Trace("smt") << "SMT getAssertions()" << endl;
if(!options::produceAssertions()) {
@@ -1923,7 +1961,8 @@ void SmtEngine::push()
Trace("smt") << "SMT push()" << endl;
d_smtSolver->processAssertions(*d_asserts);
if(Dump.isOn("benchmark")) {
- Dump("benchmark") << PushCommand();
+ getOutputManager().getPrinter().toStreamCmdPush(
+ getOutputManager().getDumpOut());
}
d_state->userPush();
}
@@ -1933,7 +1972,8 @@ void SmtEngine::pop() {
finishInit();
Trace("smt") << "SMT pop()" << endl;
if(Dump.isOn("benchmark")) {
- Dump("benchmark") << PopCommand();
+ getOutputManager().getPrinter().toStreamCmdPop(
+ getOutputManager().getDumpOut());
}
d_state->userPop();
@@ -1954,7 +1994,8 @@ void SmtEngine::reset()
ExprManager *em = d_exprManager;
Trace("smt") << "SMT reset()" << endl;
if(Dump.isOn("benchmark")) {
- Dump("benchmark") << ResetCommand();
+ getOutputManager().getPrinter().toStreamCmdReset(
+ getOutputManager().getDumpOut());
}
std::string filename = d_state->getFilename();
Options opts;
@@ -1983,7 +2024,8 @@ void SmtEngine::resetAssertions()
Trace("smt") << "SMT resetAssertions()" << endl;
if (Dump.isOn("benchmark"))
{
- Dump("benchmark") << ResetAssertionsCommand();
+ getOutputManager().getPrinter().toStreamCmdResetAssertions(
+ getOutputManager().getDumpOut());
}
d_state->notifyResetAssertions();
@@ -2073,7 +2115,8 @@ void SmtEngine::setOption(const std::string& key, const CVC4::SExpr& value)
Trace("smt") << "SMT setOption(" << key << ", " << value << ")" << endl;
if(Dump.isOn("benchmark")) {
- Dump("benchmark") << SetOptionCommand(key, value);
+ getOutputManager().getPrinter().toStreamCmdSetOption(
+ getOutputManager().getDumpOut(), key, value);
}
if(key == "command-verbosity") {
@@ -2126,7 +2169,7 @@ CVC4::SExpr SmtEngine::getOption(const std::string& key) const
}
if(Dump.isOn("benchmark")) {
- Dump("benchmark") << GetOptionCommand(key);
+ d_outMgr.getPrinter().toStreamCmdGetOption(d_outMgr.getDumpOut(), key);
}
if(key == "command-verbosity") {
@@ -2181,4 +2224,11 @@ ResourceManager* SmtEngine::getResourceManager()
DumpManager* SmtEngine::getDumpManager() { return d_dumpm.get(); }
+const Printer* SmtEngine::getPrinter() const
+{
+ return Printer::getPrinter(d_options[options::outputLanguage]);
+}
+
+OutputManager& SmtEngine::getOutputManager() { return d_outMgr; }
+
}/* CVC4 namespace */
diff --git a/src/smt/smt_engine.h b/src/smt/smt_engine.h
index eec17a5f8..d855e3181 100644
--- a/src/smt/smt_engine.h
+++ b/src/smt/smt_engine.h
@@ -31,6 +31,7 @@
#include "options/options.h"
#include "proof/unsat_core.h"
#include "smt/logic_exception.h"
+#include "smt/output_manager.h"
#include "smt/smt_mode.h"
#include "theory/logic_info.h"
#include "util/hash.h"
@@ -63,6 +64,8 @@ class Model;
class LogicRequest;
class StatisticsRegistry;
+class Printer;
+
/* -------------------------------------------------------------------------- */
namespace api {
@@ -130,6 +133,8 @@ namespace theory {
class Rewriter;
}/* CVC4::theory namespace */
+std::vector<Node> exprVectorToNodes(const std::vector<Expr>& exprs);
+
// TODO: SAT layer (esp. CNF- versus non-clausal solvers under the
// hood): use a type parameter and have check() delegate, or subclass
// SmtEngine and override check()?
@@ -862,6 +867,12 @@ class CVC4_PUBLIC SmtEngine
/** Permit access to the underlying dump manager. */
smt::DumpManager* getDumpManager();
+ /** Get the printer used by this SMT engine */
+ const Printer* getPrinter() const;
+
+ /** Get the output manager for this SMT engine */
+ OutputManager& getOutputManager();
+
/** Get a pointer to the Rewriter owned by this SmtEngine. */
theory::Rewriter* getRewriter() { return d_rewriter.get(); }
@@ -1139,6 +1150,10 @@ class CVC4_PUBLIC SmtEngine
/** The options object */
Options d_options;
+
+ /** the output manager for commands */
+ mutable OutputManager d_outMgr;
+
/**
* Manager for limiting time and abstract resource usage.
*/
diff --git a/src/smt/smt_solver.cpp b/src/smt/smt_solver.cpp
index c64689be6..922831106 100644
--- a/src/smt/smt_solver.cpp
+++ b/src/smt/smt_solver.cpp
@@ -51,7 +51,8 @@ void SmtSolver::finishInit(const LogicInfo& logicInfo)
d_smt.getUserContext(),
d_rm,
d_pp.getTermFormulaRemover(),
- logicInfo));
+ logicInfo,
+ d_smt.getOutputManager()));
// Add the theories
for (theory::TheoryId id = theory::THEORY_FIRST; id < theory::THEORY_LAST;
@@ -65,8 +66,11 @@ void SmtSolver::finishInit(const LogicInfo& logicInfo)
* are unregistered by the obsolete PropEngine object before registered
* again by the new PropEngine object */
d_propEngine.reset(nullptr);
- d_propEngine.reset(new PropEngine(
- d_theoryEngine.get(), d_smt.getContext(), d_smt.getUserContext(), d_rm));
+ d_propEngine.reset(new PropEngine(d_theoryEngine.get(),
+ d_smt.getContext(),
+ d_smt.getUserContext(),
+ d_rm,
+ d_smt.getOutputManager()));
Trace("smt-debug") << "Setting up theory engine..." << std::endl;
d_theoryEngine->setPropEngine(getPropEngine());
@@ -82,8 +86,11 @@ void SmtSolver::resetAssertions()
* statistics are unregistered by the obsolete PropEngine object before
* registered again by the new PropEngine object */
d_propEngine.reset(nullptr);
- d_propEngine.reset(new PropEngine(
- d_theoryEngine.get(), d_smt.getContext(), d_smt.getUserContext(), d_rm));
+ d_propEngine.reset(new PropEngine(d_theoryEngine.get(),
+ d_smt.getContext(),
+ d_smt.getUserContext(),
+ d_rm,
+ d_smt.getOutputManager()));
d_theoryEngine->setPropEngine(getPropEngine());
// Notice that we do not reset TheoryEngine, nor does it require calling
// finishInit again. In particular, TheoryEngine::finishInit does not
diff --git a/src/smt/sygus_solver.cpp b/src/smt/sygus_solver.cpp
index 0fc63d198..979eaec6d 100644
--- a/src/smt/sygus_solver.cpp
+++ b/src/smt/sygus_solver.cpp
@@ -17,6 +17,8 @@
#include "expr/dtype.h"
#include "options/quantifiers_options.h"
#include "options/smt_options.h"
+#include "printer/printer.h"
+#include "smt/dump.h"
#include "smt/preprocessor.h"
#include "smt/smt_solver.h"
#include "theory/smt_engine_subsolver.h"
@@ -30,8 +32,12 @@ namespace smt {
SygusSolver::SygusSolver(SmtSolver& sms,
Preprocessor& pp,
- context::UserContext* u)
- : d_smtSolver(sms), d_pp(pp), d_sygusConjectureStale(u, true)
+ context::UserContext* u,
+ OutputManager& outMgr)
+ : d_smtSolver(sms),
+ d_pp(pp),
+ d_sygusConjectureStale(u, true),
+ d_outMgr(outMgr)
{
}
@@ -205,7 +211,10 @@ Result SygusSolver::checkSynth(Assertions& as)
te->setUserAttribute("sygus", sygusVar, {}, "");
Trace("smt") << "Check synthesis conjecture: " << body << std::endl;
- Dump("raw-benchmark") << CheckSynthCommand();
+ if (Dump.isOn("raw-benchmark"))
+ {
+ d_outMgr.getPrinter().toStreamCmdCheckSynth(d_outMgr.getDumpOut());
+ }
d_sygusConjectureStale = false;
diff --git a/src/smt/sygus_solver.h b/src/smt/sygus_solver.h
index 621bea9f3..deb253142 100644
--- a/src/smt/sygus_solver.h
+++ b/src/smt/sygus_solver.h
@@ -24,6 +24,9 @@
#include "util/result.h"
namespace CVC4 {
+
+class OutputManager;
+
namespace smt {
class Preprocessor;
@@ -41,7 +44,10 @@ class SmtSolver;
class SygusSolver
{
public:
- SygusSolver(SmtSolver& sms, Preprocessor& pp, context::UserContext* u);
+ SygusSolver(SmtSolver& sms,
+ Preprocessor& pp,
+ context::UserContext* u,
+ OutputManager& outMgr);
~SygusSolver();
/**
@@ -174,6 +180,8 @@ class SygusSolver
* Whether we need to reconstruct the sygus conjecture.
*/
context::CDO<bool> d_sygusConjectureStale;
+ /** Reference to the output manager of the smt engine */
+ OutputManager& d_outMgr;
};
} // namespace smt
diff --git a/src/smt/term_formula_removal.h b/src/smt/term_formula_removal.h
index 85f0c30d7..00bf74360 100644
--- a/src/smt/term_formula_removal.h
+++ b/src/smt/term_formula_removal.h
@@ -27,7 +27,6 @@
#include "expr/node.h"
#include "expr/term_context_stack.h"
#include "expr/term_conversion_proof_generator.h"
-#include "smt/dump.h"
#include "theory/eager_proof_generator.h"
#include "theory/trust_node.h"
#include "util/bool.h"
diff --git a/src/theory/arith/theory_arith.cpp b/src/theory/arith/theory_arith.cpp
index 1436198a8..4884d8484 100644
--- a/src/theory/arith/theory_arith.cpp
+++ b/src/theory/arith/theory_arith.cpp
@@ -21,6 +21,7 @@
#include "smt/smt_statistics_registry.h"
#include "theory/arith/arith_rewriter.h"
#include "theory/arith/infer_bounds.h"
+#include "theory/arith/nl/nonlinear_extension.h"
#include "theory/arith/theory_arith_private.h"
#include "theory/ext_theory.h"
@@ -42,7 +43,8 @@ TheoryArith::TheoryArith(context::Context* c,
new TheoryArithPrivate(*this, c, u, out, valuation, logicInfo, pnm)),
d_ppRewriteTimer("theory::arith::ppRewriteTimer"),
d_astate(*d_internal, c, u, valuation),
- d_inferenceManager(*this, d_astate, pnm)
+ d_inferenceManager(*this, d_astate, pnm),
+ d_nonlinearExtension(nullptr)
{
smtStatisticsRegistry()->registerStat(&d_ppRewriteTimer);
@@ -76,6 +78,13 @@ void TheoryArith::finishInit()
d_valuation.setUnevaluatedKind(kind::SINE);
d_valuation.setUnevaluatedKind(kind::PI);
}
+ // only need to create nonlinear extension if non-linear logic
+ const LogicInfo& logicInfo = getLogicInfo();
+ if (logicInfo.isTheoryEnabled(THEORY_ARITH) && !logicInfo.isLinear())
+ {
+ d_nonlinearExtension.reset(
+ new nl::NonlinearExtension(*this, d_equalityEngine));
+ }
// finish initialize internally
d_internal->finishInit();
}
@@ -123,7 +132,53 @@ void TheoryArith::propagate(Effort e) {
}
bool TheoryArith::collectModelInfo(TheoryModel* m)
{
- return d_internal->collectModelInfo(m);
+ std::set<Node> termSet;
+ // Work out which variables are needed
+ const std::set<Kind>& irrKinds = m->getIrrelevantKinds();
+ computeAssertedTerms(termSet, irrKinds);
+ // this overrides behavior to not assert equality engine
+ return collectModelValues(m, termSet);
+}
+
+bool TheoryArith::collectModelValues(TheoryModel* m,
+ const std::set<Node>& termSet)
+{
+ // get the model from the linear solver
+ std::map<Node, Node> arithModel;
+ d_internal->collectModelValues(termSet, arithModel);
+ // if non-linear is enabled, intercept the model, which may repair its values
+ if (d_nonlinearExtension != nullptr)
+ {
+ // Non-linear may repair values to satisfy non-linear constraints (see
+ // documentation for NonlinearExtension::interceptModel).
+ d_nonlinearExtension->interceptModel(arithModel);
+ }
+ // We are now ready to assert the model.
+ for (const std::pair<const Node, Node>& p : arithModel)
+ {
+ // maps to constant of comparable type
+ Assert(p.first.getType().isComparableTo(p.second.getType()));
+ Assert(p.second.isConst());
+ if (m->assertEquality(p.first, p.second, true))
+ {
+ continue;
+ }
+ // If we failed to assert an equality, it is likely due to theory
+ // combination, namely the repaired model for non-linear changed
+ // an equality status that was agreed upon by both (linear) arithmetic
+ // and another theory. In this case, we must add a lemma, or otherwise
+ // we would terminate with an invalid model. Thus, we add a splitting
+ // lemma of the form ( x = v V x != v ) where v is the model value
+ // assigned by the non-linear solver to x.
+ if (d_nonlinearExtension != nullptr)
+ {
+ Node eq = p.first.eqNode(p.second);
+ Node lem = NodeManager::currentNM()->mkNode(kind::OR, eq, eq.negate());
+ d_out->lemma(lem);
+ }
+ return false;
+ }
+ return true;
}
void TheoryArith::notifyRestart(){
diff --git a/src/theory/arith/theory_arith.h b/src/theory/arith/theory_arith.h
index 4851f1c5d..30ad724cc 100644
--- a/src/theory/arith/theory_arith.h
+++ b/src/theory/arith/theory_arith.h
@@ -25,12 +25,15 @@
namespace CVC4 {
namespace theory {
-
namespace arith {
+namespace nl {
+class NonlinearExtension;
+}
+
/**
- * Implementation of QF_LRA.
- * Based upon:
+ * Implementation of linear and non-linear integer and real arithmetic.
+ * The linear arithmetic solver is based upon:
* http://research.microsoft.com/en-us/um/people/leonardo/cav06.pdf
*/
class TheoryArith : public Theory {
@@ -78,6 +81,11 @@ class TheoryArith : public Theory {
TrustNode explain(TNode n) override;
bool collectModelInfo(TheoryModel* m) override;
+ /**
+ * Collect model values in m based on the relevant terms given by termSet.
+ */
+ bool collectModelValues(TheoryModel* m,
+ const std::set<Node>& termSet) override;
void shutdown() override {}
@@ -110,6 +118,11 @@ class TheoryArith : public Theory {
/** The arith::InferenceManager. */
InferenceManager d_inferenceManager;
+ /**
+ * The non-linear extension, responsible for all approaches for non-linear
+ * arithmetic.
+ */
+ std::unique_ptr<nl::NonlinearExtension> d_nonlinearExtension;
};/* class TheoryArith */
}/* CVC4::theory::arith namespace */
diff --git a/src/theory/arith/theory_arith_private.cpp b/src/theory/arith/theory_arith_private.cpp
index 1b49b7350..8595e26b5 100644
--- a/src/theory/arith/theory_arith_private.cpp
+++ b/src/theory/arith/theory_arith_private.cpp
@@ -164,7 +164,6 @@ TheoryArithPrivate::TheoryArithPrivate(TheoryArith& containing,
TheoryArithPrivate::~TheoryArithPrivate(){
if(d_treeLog != NULL){ delete d_treeLog; }
if(d_approxStats != NULL) { delete d_approxStats; }
- if(d_nonlinearExtension != NULL) { delete d_nonlinearExtension; }
}
TheoryRewriter* TheoryArithPrivate::getTheoryRewriter() { return &d_rewriter; }
@@ -177,12 +176,7 @@ void TheoryArithPrivate::finishInit()
eq::EqualityEngine* ee = d_containing.getEqualityEngine();
Assert(ee != nullptr);
d_congruenceManager.finishInit(ee);
- const LogicInfo& logicInfo = getLogicInfo();
- // only need to create nonlinear extension if non-linear logic
- if (logicInfo.isTheoryEnabled(THEORY_ARITH) && !logicInfo.isLinear())
- {
- d_nonlinearExtension = new nl::NonlinearExtension(d_containing, ee);
- }
+ d_nonlinearExtension = d_containing.d_nonlinearExtension.get();
}
static bool contains(const ConstraintCPVec& v, ConstraintP con){
@@ -4074,7 +4068,8 @@ Rational TheoryArithPrivate::deltaValueForTotalOrder() const{
return belowMin;
}
-bool TheoryArithPrivate::collectModelInfo(TheoryModel* m)
+void TheoryArithPrivate::collectModelValues(const std::set<Node>& termSet,
+ std::map<Node, Node>& arithModel)
{
AlwaysAssert(d_qflraStatus == Result::SAT);
//AlwaysAssert(!d_nlIncomplete, "Arithmetic solver cannot currently produce models for input with nonlinear arithmetic constraints");
@@ -4085,10 +4080,6 @@ bool TheoryArithPrivate::collectModelInfo(TheoryModel* m)
Debug("arith::collectModelInfo") << "collectModelInfo() begin " << endl;
- std::set<Node> termSet;
- const std::set<Kind>& irrKinds = m->getIrrelevantKinds();
- d_containing.computeAssertedTerms(termSet, irrKinds, true);
-
// Delta lasts at least the duration of the function call
const Rational& delta = d_partialModel.getDelta();
std::unordered_set<TNode, TNodeHashFunction> shared = d_containing.currentlySharedTerms();
@@ -4096,8 +4087,6 @@ bool TheoryArithPrivate::collectModelInfo(TheoryModel* m)
// TODO:
// This is not very good for user push/pop....
// Revisit when implementing push/pop
- // Map of terms to values, constructed when non-linear arithmetic is active.
- std::map<Node, Node> arithModel;
for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
ArithVar v = *vi;
@@ -4112,56 +4101,20 @@ bool TheoryArithPrivate::collectModelInfo(TheoryModel* m)
Node qNode = mkRationalNode(qmodel);
Debug("arith::collectModelInfo") << "m->assertEquality(" << term << ", " << qmodel << ", true)" << endl;
- if (d_nonlinearExtension != nullptr)
- {
- // Let non-linear extension inspect the values before they are sent
- // to the theory model.
- arithModel[term] = qNode;
- }
- else
- {
- if (!m->assertEquality(term, qNode, true))
- {
- return false;
- }
- }
+ // Add to the map
+ arithModel[term] = qNode;
}else{
Debug("arith::collectModelInfo") << "Skipping m->assertEquality(" << term << ", true)" << endl;
}
}
}
- if (d_nonlinearExtension != nullptr)
- {
- // Non-linear may repair values to satisfy non-linear constraints (see
- // documentation for NonlinearExtension::interceptModel).
- d_nonlinearExtension->interceptModel(arithModel);
- // We are now ready to assert the model.
- for (std::pair<const Node, Node>& p : arithModel)
- {
- if (!m->assertEquality(p.first, p.second, true))
- {
- // If we failed to assert an equality, it is likely due to theory
- // combination, namely the repaired model for non-linear changed
- // an equality status that was agreed upon by both (linear) arithmetic
- // and another theory. In this case, we must add a lemma, or otherwise
- // we would terminate with an invalid model. Thus, we add a splitting
- // lemma of the form ( x = v V x != v ) where v is the model value
- // assigned by the non-linear solver to x.
- Node eq = p.first.eqNode(p.second);
- Node lem = NodeManager::currentNM()->mkNode(kind::OR, eq, eq.negate());
- d_containing.d_out->lemma(lem);
- return false;
- }
- }
- }
// Iterate over equivalence classes in LinearEqualityModule
// const eq::EqualityEngine& ee = d_congruenceManager.getEqualityEngine();
// m->assertEqualityEngine(&ee);
Debug("arith::collectModelInfo") << "collectModelInfo() end " << endl;
- return true;
}
bool TheoryArithPrivate::safeToReset() const {
diff --git a/src/theory/arith/theory_arith_private.h b/src/theory/arith/theory_arith_private.h
index d0428f2ef..6d030dece 100644
--- a/src/theory/arith/theory_arith_private.h
+++ b/src/theory/arith/theory_arith_private.h
@@ -371,7 +371,7 @@ public:
FCSimplexDecisionProcedure d_fcSimplex;
SumOfInfeasibilitiesSPD d_soiSimplex;
AttemptSolutionSDP d_attemptSolSimplex;
-
+
/** non-linear algebraic approach */
nl::NonlinearExtension* d_nonlinearExtension;
@@ -456,6 +456,18 @@ public:
Rational deltaValueForTotalOrder() const;
bool collectModelInfo(TheoryModel* m);
+ /**
+ * Collect model values. This is the main method for extracting information
+ * about how to construct the model. This method relies on the caller for
+ * processing the map, which is done so that other modules (e.g. the
+ * non-linear extension) can modify arithModel before it is sent to the model.
+ *
+ * @param termSet The set of relevant terms
+ * @param arithModel Mapping from terms (of real type) to their values. The
+ * caller should assert equalities to the model for each entry in this map.
+ */
+ void collectModelValues(const std::set<Node>& termSet,
+ std::map<Node, Node>& arithModel);
void shutdown(){ }
diff --git a/src/theory/arrays/theory_arrays.cpp b/src/theory/arrays/theory_arrays.cpp
index 408f4c682..3dc19d39b 100644
--- a/src/theory/arrays/theory_arrays.cpp
+++ b/src/theory/arrays/theory_arrays.cpp
@@ -23,7 +23,6 @@
#include "expr/node_algorithm.h"
#include "options/arrays_options.h"
#include "options/smt_options.h"
-#include "smt/command.h"
#include "smt/logic_exception.h"
#include "smt/smt_statistics_registry.h"
#include "theory/arrays/theory_arrays_rewriter.h"
diff --git a/src/theory/booleans/proof_checker.cpp b/src/theory/booleans/proof_checker.cpp
index 6a8244ce0..e9dafdad6 100644
--- a/src/theory/booleans/proof_checker.cpp
+++ b/src/theory/booleans/proof_checker.cpp
@@ -21,6 +21,10 @@ namespace booleans {
void BoolProofRuleChecker::registerTo(ProofChecker* pc)
{
pc->registerChecker(PfRule::SPLIT, this);
+ pc->registerChecker(PfRule::RESOLUTION, this);
+ pc->registerChecker(PfRule::CHAIN_RESOLUTION, this);
+ pc->registerChecker(PfRule::FACTORING, this);
+ pc->registerChecker(PfRule::REORDERING, this);
pc->registerChecker(PfRule::EQ_RESOLVE, this);
pc->registerChecker(PfRule::AND_ELIM, this);
pc->registerChecker(PfRule::AND_INTRO, this);
@@ -68,6 +72,139 @@ Node BoolProofRuleChecker::checkInternal(PfRule id,
const std::vector<Node>& children,
const std::vector<Node>& args)
{
+ if (id == PfRule::RESOLUTION)
+ {
+ Assert(children.size() == 2);
+ Assert(args.size() == 1);
+ std::vector<Node> disjuncts;
+ for (unsigned i = 0; i < 2; ++i)
+ {
+ // if first clause, eliminate pivot, otherwise its negation
+ Node elim = i == 0 ? args[0] : args[0].notNode();
+ for (unsigned j = 0, size = children[i].getNumChildren(); j < size; ++j)
+ {
+ if (elim != children[i][j])
+ {
+ disjuncts.push_back(children[i][j]);
+ }
+ }
+ }
+ return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::FACTORING)
+ {
+ Assert(children.size() == 1);
+ Assert(args.empty());
+ if (children[0].getKind() != kind::OR)
+ {
+ return Node::null();
+ }
+ // remove duplicates while keeping the order of children
+ std::unordered_set<TNode, TNodeHashFunction> clauseSet;
+ std::vector<Node> disjuncts;
+ unsigned size = children[0].getNumChildren();
+ for (unsigned i = 0; i < size; ++i)
+ {
+ if (clauseSet.count(children[0][i]))
+ {
+ continue;
+ }
+ disjuncts.push_back(children[0][i]);
+ clauseSet.insert(children[0][i]);
+ }
+ if (disjuncts.size() == size)
+ {
+ return Node::null();
+ }
+ NodeManager* nm = NodeManager::currentNM();
+ return disjuncts.empty()
+ ? nm->mkConst<bool>(false)
+ : disjuncts.size() == 1 ? disjuncts[0]
+ : nm->mkNode(kind::OR, disjuncts);
+ }
+ if (id == PfRule::REORDERING)
+ {
+ Assert(children.size() == 1);
+ Assert(args.size() == 1);
+ std::unordered_set<Node, NodeHashFunction> clauseSet1, clauseSet2;
+ if (children[0].getKind() == kind::OR)
+ {
+ clauseSet1.insert(children[0].begin(), children[0].end());
+ }
+ else
+ {
+ clauseSet1.insert(children[0]);
+ }
+ if (args[0].getKind() == kind::OR)
+ {
+ clauseSet2.insert(args[0].begin(), args[0].end());
+ }
+ else
+ {
+ clauseSet2.insert(args[0]);
+ }
+ if (clauseSet1 != clauseSet2)
+ {
+ Trace("bool-pfcheck") << id << ": clause set1: " << clauseSet1 << "\n"
+ << id << ": clause set2: " << clauseSet2 << "\n";
+ return Node::null();
+ }
+ return args[0];
+ }
+ if (id == PfRule::CHAIN_RESOLUTION)
+ {
+ Assert(children.size() > 1);
+ Assert(args.size() == children.size() - 1);
+ Trace("bool-pfcheck") << "chain_res:\n" << push;
+ std::vector<Node> clauseNodes;
+ for (unsigned i = 0, childrenSize = children.size(); i < childrenSize; ++i)
+ {
+ std::unordered_set<Node, NodeHashFunction> elim;
+ // literals to be removed from "first" clause
+ if (i < childrenSize - 1)
+ {
+ elim.insert(args.begin() + i, args.end());
+ }
+ // literal to be removed from "second" clause. They will be negated
+ if (i > 0)
+ {
+ elim.insert(args[i - 1].negate());
+ }
+ Trace("bool-pfcheck") << i << ": elimination set: " << elim << "\n";
+ // only add to conclusion nodes that are not in elimination set. First get
+ // the nodes.
+ //
+ // Since unit clauses can also be OR nodes, we rely on the invariant that
+ // non-unit clauses will not occur themselves in their elimination sets.
+ // If they do then they must be unit.
+ std::vector<Node> lits;
+ if (children[i].getKind() == kind::OR && elim.count(children[i]) == 0)
+ {
+ lits.insert(lits.end(), children[i].begin(), children[i].end());
+ }
+ else
+ {
+ lits.push_back(children[i]);
+ }
+ Trace("bool-pfcheck") << i << ": clause lits: " << lits << "\n";
+ std::vector<Node> added;
+ for (unsigned j = 0, size = lits.size(); j < size; ++j)
+ {
+ if (elim.count(lits[j]) == 0)
+ {
+ clauseNodes.push_back(lits[j]);
+ added.push_back(lits[j]);
+ }
+ }
+ Trace("bool-pfcheck") << i << ": added lits: " << added << "\n\n";
+ }
+ Trace("bool-pfcheck") << "clause: " << clauseNodes << "\n" << pop;
+ NodeManager* nm = NodeManager::currentNM();
+ return clauseNodes.empty()
+ ? nm->mkConst<bool>(false)
+ : clauseNodes.size() == 1 ? clauseNodes[0]
+ : nm->mkNode(kind::OR, clauseNodes);
+ }
if (id == PfRule::SPLIT)
{
Assert(children.empty());
diff --git a/src/theory/bv/abstraction.cpp b/src/theory/bv/abstraction.cpp
index a9ec7aa53..d7899f010 100644
--- a/src/theory/bv/abstraction.cpp
+++ b/src/theory/bv/abstraction.cpp
@@ -15,12 +15,14 @@
#include "theory/bv/abstraction.h"
#include "options/bv_options.h"
+#include "printer/printer.h"
#include "smt/dump.h"
+#include "smt/smt_engine.h"
+#include "smt/smt_engine_scope.h"
#include "smt/smt_statistics_registry.h"
#include "theory/bv/theory_bv_utils.h"
#include "theory/rewriter.h"
-
using namespace CVC4;
using namespace CVC4::theory;
using namespace CVC4::theory::bv;
@@ -691,15 +693,6 @@ Node AbstractionModule::substituteArguments(TNode signature, TNode apply, unsign
}
Node AbstractionModule::simplifyConflict(TNode conflict) {
- if (Dump.isOn("bv-abstraction")) {
- NodeNodeMap seen;
- Node c = reverseAbstraction(conflict, seen);
- Dump("bv-abstraction") << PushCommand();
- Dump("bv-abstraction") << AssertCommand(c.toExpr());
- Dump("bv-abstraction") << CheckSatCommand();
- Dump("bv-abstraction") << PopCommand();
- }
-
Debug("bv-abstraction-dbg") << "AbstractionModule::simplifyConflict " << conflict << "\n";
if (conflict.getKind() != kind::AND)
return conflict;
@@ -742,16 +735,6 @@ Node AbstractionModule::simplifyConflict(TNode conflict) {
Debug("bv-abstraction") << "AbstractionModule::simplifyConflict conflict " << conflict <<"\n";
Debug("bv-abstraction") << " => " << new_conflict <<"\n";
- if (Dump.isOn("bv-abstraction")) {
-
- NodeNodeMap seen;
- Node nc = reverseAbstraction(new_conflict, seen);
- Dump("bv-abstraction") << PushCommand();
- Dump("bv-abstraction") << AssertCommand(nc.toExpr());
- Dump("bv-abstraction") << CheckSatCommand();
- Dump("bv-abstraction") << PopCommand();
- }
-
return new_conflict;
}
@@ -836,15 +819,6 @@ void AbstractionModule::generalizeConflict(TNode conflict, std::vector<Node>& le
lemmas.push_back(lemma);
Debug("bv-abstraction-gen") << "adding lemma " << lemma << "\n";
storeLemma(lemma);
-
- if (Dump.isOn("bv-abstraction")) {
- NodeNodeMap seen;
- Node l = reverseAbstraction(lemma, seen);
- Dump("bv-abstraction") << PushCommand();
- Dump("bv-abstraction") << AssertCommand(l.toExpr());
- Dump("bv-abstraction") << CheckSatCommand();
- Dump("bv-abstraction") << PopCommand();
- }
}
}
}
diff --git a/src/theory/bv/bitblast/eager_bitblaster.cpp b/src/theory/bv/bitblast/eager_bitblaster.cpp
index 6417740fd..48aa0fbd6 100644
--- a/src/theory/bv/bitblast/eager_bitblaster.cpp
+++ b/src/theory/bv/bitblast/eager_bitblaster.cpp
@@ -20,6 +20,7 @@
#include "options/bv_options.h"
#include "prop/cnf_stream.h"
#include "prop/sat_solver_factory.h"
+#include "smt/smt_engine.h"
#include "smt/smt_statistics_registry.h"
#include "theory/bv/bv_solver_lazy.h"
#include "theory/bv/theory_bv.h"
@@ -71,6 +72,7 @@ EagerBitblaster::EagerBitblaster(BVSolverLazy* theory_bv, context::Context* c)
d_cnfStream.reset(new prop::TseitinCnfStream(d_satSolver.get(),
d_bitblastingRegistrar.get(),
d_nullContext.get(),
+ nullptr,
rm,
false,
"EagerBitblaster"));
diff --git a/src/theory/bv/bitblast/lazy_bitblaster.cpp b/src/theory/bv/bitblast/lazy_bitblaster.cpp
index 1813784d7..93c91719b 100644
--- a/src/theory/bv/bitblast/lazy_bitblaster.cpp
+++ b/src/theory/bv/bitblast/lazy_bitblaster.cpp
@@ -21,6 +21,7 @@
#include "prop/cnf_stream.h"
#include "prop/sat_solver.h"
#include "prop/sat_solver_factory.h"
+#include "smt/smt_engine.h"
#include "smt/smt_statistics_registry.h"
#include "theory/bv/abstraction.h"
#include "theory/bv/bv_solver_lazy.h"
@@ -82,6 +83,7 @@ TLazyBitblaster::TLazyBitblaster(context::Context* c,
d_cnfStream.reset(new prop::TseitinCnfStream(d_satSolver.get(),
d_nullRegistrar.get(),
d_nullContext.get(),
+ nullptr,
rm,
false,
"LazyBitblaster"));
@@ -573,8 +575,11 @@ void TLazyBitblaster::clearSolver() {
d_satSolver.reset(
prop::SatSolverFactory::createMinisat(d_ctx, smtStatisticsRegistry()));
ResourceManager* rm = smt::currentResourceManager();
- d_cnfStream.reset(new prop::TseitinCnfStream(
- d_satSolver.get(), d_nullRegistrar.get(), d_nullContext.get(), rm));
+ d_cnfStream.reset(new prop::TseitinCnfStream(d_satSolver.get(),
+ d_nullRegistrar.get(),
+ d_nullContext.get(),
+ nullptr,
+ rm));
d_satSolverNotify.reset(
d_emptyNotify
? (prop::BVSatSolverNotify*)new MinisatEmptyNotify()
diff --git a/src/theory/bv/bv_subtheory_algebraic.cpp b/src/theory/bv/bv_subtheory_algebraic.cpp
index e900566f9..52f68c6ef 100644
--- a/src/theory/bv/bv_subtheory_algebraic.cpp
+++ b/src/theory/bv/bv_subtheory_algebraic.cpp
@@ -19,6 +19,10 @@
#include "expr/node_algorithm.h"
#include "options/bv_options.h"
+#include "printer/printer.h"
+#include "smt/dump.h"
+#include "smt/smt_engine.h"
+#include "smt/smt_engine_scope.h"
#include "smt/smt_statistics_registry.h"
#include "smt_util/boolean_simplification.h"
#include "theory/bv/bv_quick_check.h"
@@ -321,16 +325,6 @@ bool AlgebraicSolver::check(Theory::Effort e)
TNode fact = worklist[r].node;
unsigned id = worklist[r].id;
- if (Dump.isOn("bv-algebraic")) {
- Node expl = d_explanations[id];
- Node query = utils::mkNot(nm->mkNode(kind::IMPLIES, expl, fact));
- Dump("bv-algebraic") << EchoCommand("ThoeryBV::AlgebraicSolver::substitution explanation");
- Dump("bv-algebraic") << PushCommand();
- Dump("bv-algebraic") << AssertCommand(query.toExpr());
- Dump("bv-algebraic") << CheckSatCommand();
- Dump("bv-algebraic") << PopCommand();
- }
-
if (fact.isConst() &&
fact.getConst<bool>() == true) {
continue;
@@ -344,16 +338,6 @@ bool AlgebraicSolver::check(Theory::Effort e)
d_isComplete.set(true);
Debug("bv-subtheory-algebraic") << " UNSAT: assertion simplfies to false with conflict: "<< conflict << "\n";
- if (Dump.isOn("bv-algebraic")) {
- Dump("bv-algebraic")
- << EchoCommand("BVSolverLazy::AlgebraicSolver::conflict");
- Dump("bv-algebraic") << PushCommand();
- Dump("bv-algebraic") << AssertCommand(conflict.toExpr());
- Dump("bv-algebraic") << CheckSatCommand();
- Dump("bv-algebraic") << PopCommand();
- }
-
-
++(d_statistics.d_numSimplifiesToFalse);
++(d_numSolved);
return false;
@@ -536,17 +520,6 @@ bool AlgebraicSolver::solve(TNode fact, TNode reason, SubstitutionEx& subst) {
Node new_right = nm->mkNode(kind::BITVECTOR_XOR, right, inverse);
bool changed = subst.addSubstitution(var, new_right, reason);
- if (Dump.isOn("bv-algebraic")) {
- Node query = utils::mkNot(nm->mkNode(
- kind::EQUAL, fact, nm->mkNode(kind::EQUAL, var, new_right)));
- Dump("bv-algebraic") << EchoCommand("ThoeryBV::AlgebraicSolver::substitution explanation");
- Dump("bv-algebraic") << PushCommand();
- Dump("bv-algebraic") << AssertCommand(query.toExpr());
- Dump("bv-algebraic") << CheckSatCommand();
- Dump("bv-algebraic") << PopCommand();
- }
-
-
return changed;
}
diff --git a/src/theory/bv/theory_bv_rewrite_rules.h b/src/theory/bv/theory_bv_rewrite_rules.h
index 0dbb51753..549843421 100644
--- a/src/theory/bv/theory_bv_rewrite_rules.h
+++ b/src/theory/bv/theory_bv_rewrite_rules.h
@@ -22,7 +22,10 @@
#include <sstream>
#include "context/context.h"
-#include "smt/command.h"
+#include "printer/printer.h"
+#include "smt/dump.h"
+#include "smt/smt_engine.h"
+#include "smt/smt_engine_scope.h"
#include "theory/bv/theory_bv_utils.h"
#include "theory/theory.h"
#include "util/statistics_registry.h"
@@ -449,9 +452,13 @@ public:
Node condition = node.eqNode(result).notNode();
- Dump("bv-rewrites")
- << CommentCommand(os.str())
- << CheckSatCommand(condition.toExpr());
+ const Printer& printer =
+ smt::currentSmtEngine()->getOutputManager().getPrinter();
+ std::ostream& out =
+ smt::currentSmtEngine()->getOutputManager().getDumpOut();
+
+ printer.toStreamCmdComment(out, os.str());
+ printer.toStreamCmdCheckSat(out, condition);
}
}
Debug("theory::bv::rewrite") << "RewriteRule<" << rule << ">(" << node << ") => " << result << std::endl;
diff --git a/src/theory/quantifiers/skolemize.h b/src/theory/quantifiers/skolemize.h
index f5c13b183..0e1c5f6ce 100644
--- a/src/theory/quantifiers/skolemize.h
+++ b/src/theory/quantifiers/skolemize.h
@@ -26,6 +26,9 @@
#include "theory/quantifiers/quant_util.h"
namespace CVC4 {
+
+class DTypeConstructor;
+
namespace theory {
namespace quantifiers {
diff --git a/src/theory/quantifiers/sygus/ce_guided_single_inv_sol.cpp b/src/theory/quantifiers/sygus/ce_guided_single_inv_sol.cpp
index b89015b00..bd9697084 100644
--- a/src/theory/quantifiers/sygus/ce_guided_single_inv_sol.cpp
+++ b/src/theory/quantifiers/sygus/ce_guided_single_inv_sol.cpp
@@ -17,6 +17,7 @@
#include "expr/dtype.h"
#include "expr/node_algorithm.h"
#include "options/quantifiers_options.h"
+#include "smt/command.h"
#include "theory/arith/arith_msum.h"
#include "theory/quantifiers/ematching/trigger.h"
#include "theory/quantifiers/first_order_model.h"
diff --git a/src/theory/sep/theory_sep.cpp b/src/theory/sep/theory_sep.cpp
index 573449287..b9b7b6061 100644
--- a/src/theory/sep/theory_sep.cpp
+++ b/src/theory/sep/theory_sep.cpp
@@ -50,10 +50,9 @@ TheorySep::TheorySep(context::Context* c,
d_lemmas_produced_c(u),
d_bounds_init(false),
d_state(c, u, valuation),
+ d_im(*this, d_state, pnm),
d_notify(*this),
d_reduce(u),
- d_infer(c),
- d_infer_exp(c),
d_spatial_assertions(c)
{
d_true = NodeManager::currentNM()->mkConst<bool>(true);
@@ -61,6 +60,7 @@ TheorySep::TheorySep(context::Context* c,
// indicate we are using the default theory state object
d_theoryState = &d_state;
+ d_inferManager = &d_im;
}
TheorySep::~TheorySep() {
@@ -128,31 +128,10 @@ bool TheorySep::propagateLit(TNode literal)
return ok;
}
-void TheorySep::explain(TNode literal, std::vector<TNode>& assumptions) {
- if( literal.getKind()==kind::SEP_LABEL ||
- ( literal.getKind()==kind::NOT && literal[0].getKind()==kind::SEP_LABEL ) ){
- //labelled assertions are never given to equality engine and should only come from the outside
- assumptions.push_back( literal );
- }else{
- // Do the work
- bool polarity = literal.getKind() != kind::NOT;
- TNode atom = polarity ? literal : literal[0];
- if (atom.getKind() == kind::EQUAL) {
- d_equalityEngine->explainEquality(
- atom[0], atom[1], polarity, assumptions, NULL);
- } else {
- d_equalityEngine->explainPredicate(atom, polarity, assumptions);
- }
- }
-}
-
TrustNode TheorySep::explain(TNode literal)
{
Debug("sep") << "TheorySep::explain(" << literal << ")" << std::endl;
- std::vector<TNode> assumptions;
- explain(literal, assumptions);
- Node exp = mkAnd(assumptions);
- return TrustNode::mkTrustPropExp(literal, exp, nullptr);
+ return d_im.explainLit(literal);
}
@@ -298,7 +277,7 @@ bool TheorySep::preNotifyFact(
return false;
}
// otherwise, maybe propagate
- doPendingFacts();
+ doPending();
return true;
}
@@ -316,7 +295,7 @@ void TheorySep::notifyFact(TNode atom,
addPto(ei, r, atom, polarity);
}
// maybe propagate
- doPendingFacts();
+ doPending();
}
void TheorySep::reduceFact(TNode atom, bool polarity, TNode fact)
@@ -943,12 +922,7 @@ bool TheorySep::needsCheckLastEffort() {
void TheorySep::conflict(TNode a, TNode b) {
Trace("sep-conflict") << "Sep::conflict : " << a << " " << b << std::endl;
- Node eq = a.eqNode(b);
- std::vector<TNode> assumptions;
- explain(eq, assumptions);
- Node conflictNode = mkAnd(assumptions);
- d_state.notifyInConflict();
- d_out->conflict( conflictNode );
+ d_im.conflictEqConstantMerge(a, b);
}
@@ -1825,81 +1799,29 @@ void TheorySep::sendLemma( std::vector< Node >& ant, Node conc, const char * c,
Trace("sep-lemma-debug") << "Got : " << conc << std::endl;
if( conc!=d_true ){
if( infer && conc!=d_false ){
- Node ant_n;
- if( ant.empty() ){
- ant_n = d_true;
- }else if( ant.size()==1 ){
- ant_n = ant[0];
- }else{
- ant_n = NodeManager::currentNM()->mkNode( kind::AND, ant );
- }
+ Node ant_n = NodeManager::currentNM()->mkAnd(ant);
Trace("sep-lemma") << "Sep::Infer: " << conc << " from " << ant_n << " by " << c << std::endl;
- d_pending_exp.push_back( ant_n );
- d_pending.push_back( conc );
- d_infer.push_back( ant_n );
- d_infer_exp.push_back( conc );
+ d_im.addPendingFact(conc, ant_n);
}else{
- std::vector< TNode > ant_e;
- for( unsigned i=0; i<ant.size(); i++ ){
- Trace("sep-lemma-debug") << "Explain : " << ant[i] << std::endl;
- explain( ant[i], ant_e );
- }
- Node ant_n;
- if( ant_e.empty() ){
- ant_n = d_true;
- }else if( ant_e.size()==1 ){
- ant_n = ant_e[0];
- }else{
- ant_n = NodeManager::currentNM()->mkNode( kind::AND, ant_e );
- }
if( conc==d_false ){
- Trace("sep-lemma") << "Sep::Conflict: " << ant_n << " by " << c << std::endl;
- d_out->conflict( ant_n );
- d_state.notifyInConflict();
+ Trace("sep-lemma") << "Sep::Conflict: " << ant << " by " << c
+ << std::endl;
+ d_im.conflictExp(ant, nullptr);
}else{
- Trace("sep-lemma") << "Sep::Lemma: " << conc << " from " << ant_n << " by " << c << std::endl;
- d_pending_exp.push_back( ant_n );
- d_pending.push_back( conc );
- d_pending_lem.push_back( d_pending.size()-1 );
+ Trace("sep-lemma") << "Sep::Lemma: " << conc << " from " << ant
+ << " by " << c << std::endl;
+ TrustNode trn = d_im.mkLemmaExp(conc, ant, {});
+ d_im.addPendingLemma(
+ trn.getNode(), LemmaProperty::NONE, trn.getGenerator());
}
}
}
}
-void TheorySep::doPendingFacts() {
- if( d_pending_lem.empty() ){
- for( unsigned i=0; i<d_pending.size(); i++ ){
- if (d_state.isInConflict())
- {
- break;
- }
- Node atom = d_pending[i].getKind()==kind::NOT ? d_pending[i][0] : d_pending[i];
- bool pol = d_pending[i].getKind()!=kind::NOT;
- Trace("sep-pending") << "Sep : Assert to EE : " << atom << ", pol = " << pol << std::endl;
- if( atom.getKind()==kind::EQUAL ){
- d_equalityEngine->assertEquality(atom, pol, d_pending_exp[i]);
- }else{
- d_equalityEngine->assertPredicate(atom, pol, d_pending_exp[i]);
- }
- }
- }else{
- for( unsigned i=0; i<d_pending_lem.size(); i++ ){
- if (d_state.isInConflict())
- {
- break;
- }
- int index = d_pending_lem[i];
- Node lem = NodeManager::currentNM()->mkNode( kind::IMPLIES, d_pending_exp[index], d_pending[index] );
- if( d_lemmas_produced_c.find( lem )==d_lemmas_produced_c.end() ){
- d_lemmas_produced_c.insert( lem );
- d_out->lemma( lem );
- Trace("sep-pending") << "Sep : Lemma : " << lem << std::endl;
- }
- }
- }
- d_pending_exp.clear();
- d_pending.clear();
- d_pending_lem.clear();
+void TheorySep::doPending()
+{
+ d_im.doPendingFacts();
+ d_im.doPendingLemmas();
}
void TheorySep::debugPrintHeap( HeapInfo& heap, const char * c ) {
diff --git a/src/theory/sep/theory_sep.h b/src/theory/sep/theory_sep.h
index 6bef1b37e..8eb9927f0 100644
--- a/src/theory/sep/theory_sep.h
+++ b/src/theory/sep/theory_sep.h
@@ -23,6 +23,7 @@
#include "context/cdhashset.h"
#include "context/cdlist.h"
#include "context/cdqueue.h"
+#include "theory/inference_manager_buffered.h"
#include "theory/sep/theory_sep_rewriter.h"
#include "theory/theory.h"
#include "theory/uf/equality_engine.h"
@@ -60,6 +61,8 @@ class TheorySep : public Theory {
TheorySepRewriter d_rewriter;
/** A (default) theory state object */
TheoryState d_state;
+ /** A buffered inference manager */
+ InferenceManagerBuffered d_im;
Node mkAnd( std::vector< TNode >& assumptions );
@@ -108,8 +111,6 @@ class TheorySep : public Theory {
bool propagateLit(TNode literal);
/** Conflict when merging constants */
void conflict(TNode a, TNode b);
- /** Explain why this literal is true by adding assumptions */
- void explain(TNode literal, std::vector<TNode>& assumptions);
public:
TrustNode explain(TNode n) override;
@@ -213,11 +214,6 @@ class TheorySep : public Theory {
/** The notify class for d_equalityEngine */
NotifyClass d_notify;
- /** Are we in conflict? */
- std::vector< Node > d_pending_exp;
- std::vector< Node > d_pending;
- std::vector< int > d_pending_lem;
-
/** list of all refinement lemms */
std::map< Node, std::map< Node, std::vector< Node > > > d_refinement_lem;
@@ -230,9 +226,6 @@ class TheorySep : public Theory {
std::map<Node, std::unique_ptr<DecisionStrategySingleton> >
d_neg_guard_strategy;
std::map< Node, Node > d_guard_to_assertion;
- /** inferences: maintained to ensure ref count for internally introduced nodes */
- NodeList d_infer;
- NodeList d_infer_exp;
NodeList d_spatial_assertions;
//data,ref type (globally fixed)
@@ -327,7 +320,7 @@ class TheorySep : public Theory {
void eqNotifyMerge(TNode t1, TNode t2);
void sendLemma( std::vector< Node >& ant, Node conc, const char * c, bool infer = false );
- void doPendingFacts();
+ void doPending();
public:
diff --git a/src/theory/theory.h b/src/theory/theory.h
index 77652f874..da651d259 100644
--- a/src/theory/theory.h
+++ b/src/theory/theory.h
@@ -32,8 +32,6 @@
#include "expr/node.h"
#include "options/options.h"
#include "options/theory_options.h"
-#include "smt/command.h"
-#include "smt/dump.h"
#include "smt/logic_request.h"
#include "theory/assertion.h"
#include "theory/care_graph.h"
@@ -911,10 +909,6 @@ inline theory::Assertion Theory::get() {
Trace("theory") << "Theory::get() => " << fact << " (" << d_facts.size() - d_factsHead << " left)" << std::endl;
- if(Dump.isOn("state")) {
- Dump("state") << AssertCommand(fact.d_assertion.toExpr());
- }
-
return fact;
}
diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp
index 7ff073cf3..b5167ffe4 100644
--- a/src/theory/theory_engine.cpp
+++ b/src/theory/theory_engine.cpp
@@ -31,6 +31,8 @@
#include "options/quantifiers_options.h"
#include "options/theory_options.h"
#include "preprocessing/assertion_pipeline.h"
+#include "printer/printer.h"
+#include "smt/dump.h"
#include "smt/logic_exception.h"
#include "smt/term_formula_removal.h"
#include "theory/arith/arith_ite_utils.h"
@@ -211,17 +213,18 @@ TheoryEngine::TheoryEngine(context::Context* context,
context::UserContext* userContext,
ResourceManager* rm,
RemoveTermFormulas& iteRemover,
- const LogicInfo& logicInfo)
+ const LogicInfo& logicInfo,
+ OutputManager& outMgr)
: d_propEngine(nullptr),
d_context(context),
d_userContext(userContext),
d_logicInfo(logicInfo),
+ d_outMgr(outMgr),
d_pnm(nullptr),
d_lazyProof(
- d_pnm != nullptr
- ? new LazyCDProof(
- d_pnm, nullptr, d_userContext, "TheoryEngine::LazyCDProof")
- : nullptr),
+ d_pnm != nullptr ? new LazyCDProof(
+ d_pnm, nullptr, d_userContext, "TheoryEngine::LazyCDProof")
+ : nullptr),
d_tepg(new TheoryEngineProofGenerator(d_pnm, d_userContext)),
d_sharedTerms(this, context),
d_tc(nullptr),
@@ -231,8 +234,6 @@ TheoryEngine::TheoryEngine(context::Context* context,
d_preRegistrationVisitor(this, context),
d_sharedTermsVisitor(d_sharedTerms),
d_eager_model_building(false),
- d_possiblePropagations(context),
- d_hasPropagated(context),
d_inConflict(context, false),
d_inSatMode(false),
d_hasShutDown(false),
@@ -285,11 +286,8 @@ TheoryEngine::~TheoryEngine() {
void TheoryEngine::interrupt() { d_interrupted = true; }
void TheoryEngine::preRegister(TNode preprocessed) {
-
- Debug("theory") << "TheoryEngine::preRegister( " << preprocessed << ")" << std::endl;
- if(Dump.isOn("missed-t-propagations")) {
- d_possiblePropagations.push_back(preprocessed);
- }
+ Debug("theory") << "TheoryEngine::preRegister( " << preprocessed << ")"
+ << std::endl;
d_preregisterQueue.push(preprocessed);
if (!d_inPreregister) {
@@ -400,26 +398,28 @@ void TheoryEngine::printAssertions(const char* tag) {
void TheoryEngine::dumpAssertions(const char* tag) {
if (Dump.isOn(tag)) {
- Dump(tag) << CommentCommand("Starting completeness check");
+ const Printer& printer = d_outMgr.getPrinter();
+ std::ostream& out = d_outMgr.getDumpOut();
+ printer.toStreamCmdComment(out, "Starting completeness check");
for (TheoryId theoryId = THEORY_FIRST; theoryId < THEORY_LAST; ++theoryId) {
Theory* theory = d_theoryTable[theoryId];
if (theory && d_logicInfo.isTheoryEnabled(theoryId)) {
- Dump(tag) << CommentCommand("Completeness check");
- Dump(tag) << PushCommand();
+ printer.toStreamCmdComment(out, "Completeness check");
+ printer.toStreamCmdPush(out);
// Dump the shared terms
if (d_logicInfo.isSharingEnabled()) {
- Dump(tag) << CommentCommand("Shared terms");
+ printer.toStreamCmdComment(out, "Shared terms");
context::CDList<TNode>::const_iterator it = theory->shared_terms_begin(), it_end = theory->shared_terms_end();
for (unsigned i = 0; it != it_end; ++ it, ++i) {
stringstream ss;
ss << (*it);
- Dump(tag) << CommentCommand(ss.str());
+ printer.toStreamCmdComment(out, ss.str());
}
}
// Dump the assertions
- Dump(tag) << CommentCommand("Assertions");
+ printer.toStreamCmdComment(out, "Assertions");
context::CDList<Assertion>::const_iterator it = theory->facts_begin(), it_end = theory->facts_end();
for (; it != it_end; ++ it) {
// Get the assertion
@@ -428,17 +428,17 @@ void TheoryEngine::dumpAssertions(const char* tag) {
if ((*it).d_isPreregistered)
{
- Dump(tag) << CommentCommand("Preregistered");
+ printer.toStreamCmdComment(out, "Preregistered");
}
else
{
- Dump(tag) << CommentCommand("Shared assertion");
+ printer.toStreamCmdComment(out, "Shared assertion");
}
- Dump(tag) << AssertCommand(assertionNode.toExpr());
+ printer.toStreamCmdAssert(out, assertionNode);
}
- Dump(tag) << CheckSatCommand();
+ printer.toStreamCmdCheckSat(out);
- Dump(tag) << PopCommand();
+ printer.toStreamCmdPop(out);
}
}
}
@@ -516,12 +516,6 @@ void TheoryEngine::check(Theory::Effort effort) {
// Do the checking
CVC4_FOR_EACH_THEORY;
- if(Dump.isOn("missed-t-conflicts")) {
- Dump("missed-t-conflicts")
- << CommentCommand("Completeness check for T-conflicts; expect sat")
- << CheckSatCommand();
- }
-
Debug("theory") << "TheoryEngine::check(" << effort << "): running propagation after the initial check" << endl;
// We are still satisfiable, propagate as much as possible
@@ -622,25 +616,6 @@ void TheoryEngine::propagate(Theory::Effort effort)
// Propagate for each theory using the statement above
CVC4_FOR_EACH_THEORY;
-
- if(Dump.isOn("missed-t-propagations")) {
- for(unsigned i = 0; i < d_possiblePropagations.size(); ++i) {
- Node atom = d_possiblePropagations[i];
- bool value;
- if(d_propEngine->hasValue(atom, value)) {
- continue;
- }
- // Doesn't have a value, check it (and the negation)
- if(d_hasPropagated.find(atom) == d_hasPropagated.end()) {
- Dump("missed-t-propagations")
- << CommentCommand("Completeness check for T-propagations; expect invalid")
- << EchoCommand(atom.toString())
- << QueryCommand(atom.toExpr())
- << EchoCommand(atom.notNode().toString())
- << QueryCommand(atom.notNode().toExpr());
- }
- }
- }
}
Node TheoryEngine::getNextDecisionRequest()
@@ -1134,14 +1109,6 @@ bool TheoryEngine::propagate(TNode literal, theory::TheoryId theory) {
// spendResource();
- if(Dump.isOn("t-propagations")) {
- Dump("t-propagations") << CommentCommand("negation of theory propagation: expect valid")
- << QueryCommand(literal.toExpr());
- }
- if(Dump.isOn("missed-t-propagations")) {
- d_hasPropagated.insert(literal);
- }
-
// Get the atom
bool polarity = literal.getKind() != kind::NOT;
TNode atom = polarity ? literal : literal[0];
@@ -1484,8 +1451,10 @@ theory::LemmaStatus TheoryEngine::lemma(theory::TrustNode tlemma,
if(Dump.isOn("t-lemmas")) {
// we dump the negation of the lemma, to show validity of the lemma
Node n = lemma.negate();
- Dump("t-lemmas") << CommentCommand("theory lemma: expect valid")
- << CheckSatCommand(n.toExpr());
+ const Printer& printer = d_outMgr.getPrinter();
+ std::ostream& out = d_outMgr.getDumpOut();
+ printer.toStreamCmdComment(out, "theory lemma: expect valid");
+ printer.toStreamCmdCheckSat(out, n);
}
bool removable = isLemmaPropertyRemovable(p);
bool preprocess = isLemmaPropertyPreprocess(p);
@@ -1621,8 +1590,10 @@ void TheoryEngine::conflict(theory::TrustNode tconflict, TheoryId theoryId)
d_inConflict = true;
if(Dump.isOn("t-conflicts")) {
- Dump("t-conflicts") << CommentCommand("theory conflict: expect unsat")
- << CheckSatCommand(conflict.toExpr());
+ const Printer& printer = d_outMgr.getPrinter();
+ std::ostream& out = d_outMgr.getDumpOut();
+ printer.toStreamCmdComment(out, "theory conflict: expect unsat");
+ printer.toStreamCmdCheckSat(out, conflict);
}
// In the multiple-theories case, we need to reconstruct the conflict
diff --git a/src/theory/theory_engine.h b/src/theory/theory_engine.h
index 550a4f496..a6258b7d6 100644
--- a/src/theory/theory_engine.h
+++ b/src/theory/theory_engine.h
@@ -33,7 +33,6 @@
#include "options/smt_options.h"
#include "options/theory_options.h"
#include "prop/prop_engine.h"
-#include "smt/command.h"
#include "theory/atom_requests.h"
#include "theory/engine_output_channel.h"
#include "theory/interrupted.h"
@@ -139,6 +138,9 @@ class TheoryEngine {
*/
const LogicInfo& d_logicInfo;
+ /** Reference to the output manager of the smt engine */
+ OutputManager& d_outMgr;
+
//--------------------------------- new proofs
/** Proof node manager used by this theory engine, if proofs are enabled */
ProofNodeManager* d_pnm;
@@ -182,19 +184,6 @@ class TheoryEngine {
typedef std::unordered_map<TNode, Node, TNodeHashFunction> TNodeMap;
/**
- * Used for "missed-t-propagations" dumping mode only. A set of all
- * theory-propagable literals.
- */
- context::CDList<TNode> d_possiblePropagations;
-
- /**
- * Used for "missed-t-propagations" dumping mode only. A
- * context-dependent set of those theory-propagable literals that
- * have been propagated.
- */
- context::CDHashSet<Node, NodeHashFunction> d_hasPropagated;
-
- /**
* Output channels for individual theories.
*/
theory::EngineOutputChannel* d_theoryOut[theory::THEORY_LAST];
@@ -330,7 +319,8 @@ class TheoryEngine {
context::UserContext* userContext,
ResourceManager* rm,
RemoveTermFormulas& iteRemover,
- const LogicInfo& logic);
+ const LogicInfo& logic,
+ OutputManager& outMgr);
/** Destroys a theory engine */
~TheoryEngine();
diff --git a/src/theory/uf/eq_proof.cpp b/src/theory/uf/eq_proof.cpp
index d7b615ffa..8b1e05fb0 100644
--- a/src/theory/uf/eq_proof.cpp
+++ b/src/theory/uf/eq_proof.cpp
@@ -16,6 +16,7 @@
#include "theory/uf/eq_proof.h"
#include "expr/proof.h"
+#include "options/uf_options.h"
namespace CVC4 {
namespace theory {
@@ -700,9 +701,10 @@ void EqProof::reduceNestedCongruence(
<< transitivityMatrix[i].back() << "\n";
// if i == 0, first child must be REFL step, standing for (= f f), which can
// be ignored in a first-order calculus
- Assert(i > 0 || d_children[0]->d_id == MERGED_THROUGH_REFLEXIVITY);
+ Assert(i > 0 || d_children[0]->d_id == MERGED_THROUGH_REFLEXIVITY
+ || options::ufHo());
// recurse
- if (i > 0)
+ if (i > 1)
{
Trace("eqproof-conv")
<< "EqProof::reduceNestedCongruence: Reduce first child\n"
@@ -716,9 +718,21 @@ void EqProof::reduceNestedCongruence(
isNary);
Trace("eqproof-conv") << pop;
}
+ // higher-order case
+ else if (d_children[0]->d_id != MERGED_THROUGH_REFLEXIVITY)
+ {
+ Trace("eqproof-conv") << "EqProof::reduceNestedCongruence: HO case. "
+ "Processing first child\n";
+ // we only handle these cases
+ Assert(d_children[0]->d_id == MERGED_THROUGH_EQUALITY
+ || d_children[0]->d_id == MERGED_THROUGH_TRANS);
+ transitivityMatrix[0].push_back(
+ d_children[0]->addToProof(p, visited, assumptions));
+ }
return;
}
- Assert(d_id == MERGED_THROUGH_TRANS);
+ Assert(d_id == MERGED_THROUGH_TRANS)
+ << "id is " << static_cast<MergeReasonType>(d_id) << "\n";
Trace("eqproof-conv") << "EqProof::reduceNestedCongruence: it's a "
"transitivity step.\n";
Assert(d_node.isNull()
@@ -1186,23 +1200,24 @@ Node EqProof::addToProof(
// example).
if (d_node[0].getNumChildren() != d_node[1].getNumChildren())
{
- Assert(isNary);
+ Assert(isNary) << "We only handle congruences of apps with different "
+ "number of children for theory n-ary operators";
arity =
d_node[1].getNumChildren() < arity ? arity : d_node[1].getNumChildren();
Trace("eqproof-conv")
<< "EqProof::addToProof: Mismatching arities in cong conclusion "
<< d_node << ". Use tentative arity " << arity << "\n";
}
- // For a congruence proof of (= (f a0 ... an-1) (f b0 ... bn-1)), build a
- // transitivity matrix where each row contains a transitivity chain justifying
- // (= ai bi)
+ // For a congruence proof of (= (f a0 ... an-1) (g b0 ... bn-1)), build a
+ // transitivity matrix of n rows where the first row contains a transitivity
+ // chain justifying (= f g) and the next rows (= ai bi)
std::vector<std::vector<Node>> transitivityChildren;
- for (unsigned i = 0; i < arity; ++i)
+ for (unsigned i = 0; i < arity + 1; ++i)
{
transitivityChildren.push_back(std::vector<Node>());
}
reduceNestedCongruence(
- arity - 1, d_node, transitivityChildren, p, visited, assumptions, isNary);
+ arity, d_node, transitivityChildren, p, visited, assumptions, isNary);
// Congruences over n-ary operators may require changing the conclusion (as in
// the above example). This is handled in a general manner below according to
// whether the transitivity matrix computed by reduceNestedCongruence contains
@@ -1212,7 +1227,7 @@ Node EqProof::addToProof(
if (isNary)
{
unsigned emptyRows = 0;
- for (unsigned i = 0; i < arity; ++i)
+ for (unsigned i = 1; i <= arity; ++i)
{
if (transitivityChildren[i].empty())
{
@@ -1232,7 +1247,11 @@ Node EqProof::addToProof(
// n - k1 == m - k2
// Note that by construction the equality between the first emptyRows + 1
// arguments of each application is justified by the transitivity step in
- // the row emptyRows +1 in the matrix.
+ // the row emptyRows + 1 in the matrix.
+ //
+ // All of the above is with the very first row in the matrix, reserved for
+ // justifying the equality between the functions, which is not necessary in
+ // the n-ary case, notwithstanding.
if (emptyRows > 0)
{
Trace("eqproof-conv")
@@ -1242,9 +1261,11 @@ Node EqProof::addToProof(
// beginning are eliminated, as the new arity is the maximal arity among
// the applications minus the number of empty rows.
std::vector<std::vector<Node>> newTransitivityChildren{
- transitivityChildren.begin() + emptyRows, transitivityChildren.end()};
+ transitivityChildren.begin() + 1 + emptyRows,
+ transitivityChildren.end()};
transitivityChildren.clear();
- transitivityChildren.insert(transitivityChildren.begin(),
+ transitivityChildren.push_back(std::vector<Node>());
+ transitivityChildren.insert(transitivityChildren.end(),
newTransitivityChildren.begin(),
newTransitivityChildren.end());
unsigned arityPrefix1 =
@@ -1293,27 +1314,40 @@ Node EqProof::addToProof(
Trace("eqproof-conv")
<< "EqProof::addToProof: premises from reduced cong of " << conclusion
<< ":\n";
- for (unsigned i = 0; i < arity; ++i)
+ for (unsigned i = 0; i <= arity; ++i)
{
Trace("eqproof-conv") << "EqProof::addToProof:\t" << i
<< "-th arg: " << transitivityChildren[i] << "\n";
}
}
+ std::vector<Node> children(arity + 1);
+ // Check if there is a justification for equality between functions (HO case)
+ if (!transitivityChildren[0].empty())
+ {
+ Assert(k == kind::APPLY_UF) << "Congruence with different functions only "
+ "allowed for uninterpreted functions.\n";
+
+ children[0] =
+ conclusion[0].getOperator().eqNode(conclusion[1].getOperator());
+ Assert(transitivityChildren[0].size() == 1
+ && CDProof::isSame(children[0], transitivityChildren[0][0]))
+ << "Justification of operators equality is wrong: "
+ << transitivityChildren[0] << "\n";
+ }
// Proccess transitivity matrix to (possibly) generate transitivity steps for
// congruence premises (= ai bi)
- std::vector<Node> children(arity);
- for (unsigned i = 0; i < arity; ++i)
+ for (unsigned i = 1; i <= arity; ++i)
{
- Node transConclusion = conclusion[0][i].eqNode(conclusion[1][i]);
+ Node transConclusion = conclusion[0][i - 1].eqNode(conclusion[1][i - 1]);
children[i] = transConclusion;
Assert(!transitivityChildren[i].empty())
<< "EqProof::addToProof: did not add any justification for " << i
<< "-th arg of congruence " << conclusion << "\n";
// If the transitivity conclusion is a reflexivity step, just add it. Note
- // that this can happen with with transitivityChildren containing several
- // equalities in the case of (= ai bi) being the same n-ary application that
- // was justified by a congruence step, which can happen in the current
- // equality engine
+ // that this can happen even with the respective transitivityChildren row
+ // containing several equalities in the case of (= ai bi) being the same
+ // n-ary application that was justified by a congruence step, which can
+ // happen in the current equality engine.
if (transConclusion[0] == transConclusion[1])
{
p->addStep(transConclusion, PfRule::REFL, {}, {transConclusion[0]});
@@ -1355,18 +1389,34 @@ Node EqProof::addToProof(
transConclusion, PfRule::TRANS, transitivityChildren[i], {}, true);
}
}
- // Get node of the function operator over which congruence is being applied.
- std::vector<Node> args;
- args.push_back(ProofRuleChecker::mkKindNode(k));
- if (kind::metaKindOf(k) == kind::metakind::PARAMETERIZED)
+ // first-order case
+ if (children[0].isNull())
+ {
+ // remove placehold for function equality case
+ children.erase(children.begin());
+ // Get node of the function operator over which congruence is being
+ // applied.
+ std::vector<Node> args;
+ args.push_back(ProofRuleChecker::mkKindNode(k));
+ if (kind::metaKindOf(k) == kind::metakind::PARAMETERIZED)
+ {
+ args.push_back(conclusion[0].getOperator());
+ }
+ // Add congruence step
+ Trace("eqproof-conv") << "EqProof::addToProof: build cong step of "
+ << conclusion << " with op " << args[0]
+ << " and children " << children << "\n";
+ p->addStep(conclusion, PfRule::CONG, children, args, true);
+ }
+ // higher-order case
+ else
{
- args.push_back(conclusion[0].getOperator());
+ // Add congruence step
+ Trace("eqproof-conv") << "EqProof::addToProof: build HO-cong step of "
+ << conclusion << " with children " << children
+ << "\n";
+ p->addStep(conclusion, PfRule::HO_CONG, children, {}, true);
}
- // Add congruence step
- Trace("eqproof-conv") << "EqProof::addToProof: build cong step of "
- << conclusion << " with op " << args[0]
- << " and children " << children << "\n";
- p->addStep(conclusion, PfRule::CONG, children, args, true);
// If the conclusion of the congruence step changed due to the n-ary handling,
// we obtained for example (= (f (f t1 t2 t3) t4) (f (f t5 t6) t7)), which is
// flattened into the original conclusion (= (f t1 t2 t3 t4) (f t5 t6 t7)) via
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback