#include <sstream>
#include "options/expr_options.h"
+#include "options/proof_options.h"
#include "printer/smt2/smt2_printer.h"
#include "proof/proof_checker.h"
#include "proof/proof_node_manager.h"
namespace proof {
DotPrinter::DotPrinter()
- : d_lbind(options::defaultDagThresh() ? options::defaultDagThresh() + 1 : 0)
+ : d_lbind(options::defaultDagThresh() ? options::defaultDagThresh() + 1
+ : 0),
+ d_ruleID(0)
{
}
void DotPrinter::print(std::ostream& out, const ProofNode* pn)
{
- uint64_t ruleID = 0;
countSubproofs(pn);
letifyResults(pn);
}
out << "}}\";\n";
}
- DotPrinter::printInternal(out, pn, ruleID, 0, false);
+
+ std::map<size_t, uint64_t> proofLet;
+ DotPrinter::printInternal(out, pn, proofLet, 0, false);
out << "}\n";
}
-void DotPrinter::printInternal(std::ostream& out,
- const ProofNode* pn,
- uint64_t& ruleID,
- uint64_t scopeCounter,
- bool inPropositionalView)
+uint64_t DotPrinter::printInternal(std::ostream& out,
+ const ProofNode* pn,
+ std::map<size_t, uint64_t>& pfLet,
+ uint64_t scopeCounter,
+ bool inPropositionalView)
{
- uint64_t currentRuleID = ruleID;
- const std::vector<std::shared_ptr<ProofNode>>& children = pn->getChildren();
+ uint64_t currentRuleID = d_ruleID;
+
+ // Print DAG option enabled
+ if (options::proofDotDAG())
+ {
+ ProofNodeHashFunction hasher;
+ size_t currentHash = hasher(pn);
+ auto proofIt = pfLet.find(currentHash);
+
+ // If this node has been already counted
+ if (proofIt != pfLet.end())
+ {
+ return proofIt->second;
+ }
+
+ pfLet[currentHash] = currentRuleID;
+ }
+ d_ruleID++;
+
std::ostringstream currentArguments, resultStr, classes, colors;
out << "\t" << currentRuleID << " [ label = \"{";
out << ", comment = \"{\\\"subProofQty\\\":" << it->second << "}\"";
out << " ];\n";
+ const std::vector<std::shared_ptr<ProofNode>>& children = pn->getChildren();
for (const std::shared_ptr<ProofNode>& c : children)
{
- ++ruleID;
- out << "\t" << ruleID << " -> " << currentRuleID << ";\n";
- printInternal(out, c.get(), ruleID, scopeCounter, inPropositionalView);
+ uint64_t childId =
+ printInternal(out, c.get(), pfLet, scopeCounter, inPropositionalView);
+ out << "\t" << childId << " -> " << currentRuleID << ";\n";
}
+
+ return currentRuleID;
}
void DotPrinter::ruleArguments(std::ostringstream& currentArguments,
* the child as argument.
* @param out the output stream
* @param pn the proof node to print
- * @param ruleID the id of the rule to print
+ * @param pfLet the map of the hashs of proof nodes already printed to their ids
* @param scopeCounter counter of how many SCOPE were already depth-first
* traversed in the proof up to this point
* @param inPropositionalView flag used to mark the proof node being traversed
* was generated by the SAT solver and thus belong to the propositional view
+ * @return the id of the proof node printed
*/
- void printInternal(std::ostream& out,
- const ProofNode* pn,
- uint64_t& ruleID,
- uint64_t scopeCounter,
- bool inPropositionalView);
+ uint64_t printInternal(std::ostream& out,
+ const ProofNode* pn,
+ std::map<size_t, uint64_t>& pfLet,
+ uint64_t scopeCounter,
+ bool inPropositionalView);
/**
* Return the arguments of a ProofNode
/** Let binder for terms in proof nodes */
LetBinding d_lbind;
+
+ /** Counter that indicates the current rule ID */
+ uint64_t d_ruleID;
};
} // namespace proof
return out;
}
+size_t ProofNodeHashFunction::operator()(const ProofNode* pfn) const
+{
+ uint64_t ret = fnv1a::offsetBasis;
+
+ ret = fnv1a::fnv1a_64(ret, std::hash<Node>()(pfn->getResult()));
+ ret = fnv1a::fnv1a_64(ret, static_cast<size_t>(pfn->getRule()));
+
+ const std::vector<std::shared_ptr<ProofNode>>& children = pfn->getChildren();
+ for (const Pf& child : children)
+ {
+ ret = fnv1a::fnv1a_64(ret, std::hash<Node>()(child->getResult()));
+ }
+
+ const std::vector<Node>& args = pfn->getArguments();
+ for (const Node& arg : args)
+ {
+ ret = fnv1a::fnv1a_64(ret, std::hash<Node>()(arg));
+ }
+
+ return static_cast<size_t>(ret);
+}
+
} // namespace cvc5