Branch data Line data Source code
1 : : /****************************************************************************** 2 : : * This file is part of the cvc5 project. 3 : : * 4 : : * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS 5 : : * in the top-level source directory and their institutional affiliations. 6 : : * All rights reserved. See the file COPYING in the top-level source 7 : : * directory for licensing information. 8 : : * **************************************************************************** 9 : : * 10 : : * Implementation of the lazy tree proof generator class. 11 : : */ 12 : : 13 : : #include "proof/lazy_tree_proof_generator.h" 14 : : 15 : : #include <iostream> 16 : : 17 : : #include "base/output.h" 18 : : #include "expr/node.h" 19 : : #include "proof/proof_generator.h" 20 : : #include "proof/proof_node.h" 21 : : #include "proof/proof_node_manager.h" 22 : : #include "smt/env.h" 23 : : 24 : : namespace cvc5::internal { 25 : : 26 : 62 : LazyTreeProofGenerator::LazyTreeProofGenerator(Env& env, 27 : 62 : const std::string& name) 28 : 62 : : EnvObj(env), d_name(name) 29 : : { 30 : 62 : d_stack.emplace_back(&d_proof); 31 : 62 : } 32 : 3395 : void LazyTreeProofGenerator::openChild() 33 : : { 34 [ + - ]: 3395 : Trace("proof-ltpg") << "openChild() start" << std::endl << *this << std::endl; 35 : 3395 : detail::TreeProofNode& pn = getCurrent(); 36 : 3395 : pn.d_children.emplace_back(); 37 : 3395 : d_stack.emplace_back(&pn.d_children.back()); 38 [ + - ]: 3395 : Trace("proof-ltpg") << "openChild() end" << std::endl << *this << std::endl; 39 : 3395 : } 40 : 3426 : void LazyTreeProofGenerator::closeChild() 41 : : { 42 [ + - ]: 6852 : Trace("proof-ltpg") << "closeChild() start" << std::endl 43 : 3426 : << *this << std::endl; 44 [ - + ][ - + ]: 3426 : Assert(getCurrent().d_rule != ProofRule::UNKNOWN); [ - - ] 45 : 3426 : d_stack.pop_back(); 46 [ + - ]: 3426 : Trace("proof-ltpg") << "closeChild() end" << std::endl << *this << std::endl; 47 : 3426 : } 48 : 12654 : detail::TreeProofNode& LazyTreeProofGenerator::getCurrent() 49 : : { 50 [ - + ][ - + ]: 12654 : Assert(!d_stack.empty()) << "Proof construction has already been finished."; [ - - ] 51 : 12654 : return *d_stack.back(); 52 : : } 53 : 3426 : void LazyTreeProofGenerator::setCurrent(size_t objectId, 54 : : ProofRule rule, 55 : : const std::vector<Node>& premise, 56 : : std::vector<Node> args, 57 : : Node proven) 58 : : { 59 : 3426 : detail::TreeProofNode& pn = getCurrent(); 60 : 3426 : pn.d_objectId = objectId; 61 : 3426 : pn.d_rule = rule; 62 : 3426 : pn.d_premise = premise; 63 : 3426 : pn.d_args = args; 64 : 3426 : pn.d_proven = proven; 65 : 3426 : } 66 : : 67 : 1966 : void LazyTreeProofGenerator::setCurrentTrust(size_t objectId, 68 : : TrustId tid, 69 : : const std::vector<Node>& premise, 70 : : std::vector<Node> args, 71 : : Node proven) 72 : : { 73 : 1966 : std::vector<Node> newArgs; 74 : 1966 : newArgs.push_back(mkTrustId(nodeManager(), tid)); 75 : 1966 : newArgs.push_back(proven); 76 : 1966 : newArgs.insert(newArgs.end(), args.begin(), args.end()); 77 : 1966 : setCurrent(objectId, ProofRule::TRUST, premise, newArgs, proven); 78 : 1966 : } 79 : 107 : std::shared_ptr<ProofNode> LazyTreeProofGenerator::getProof() const 80 : : { 81 : : // Check cache 82 [ + + ]: 107 : if (d_cached) return d_cached; 83 [ - + ][ - + ]: 37 : Assert(d_stack.empty()) << "Proof construction has not yet been finished."; [ - - ] 84 : 37 : std::vector<std::shared_ptr<ProofNode>> scope; 85 : 37 : d_cached = getProof(scope, d_proof); 86 : 37 : return d_cached; 87 : 37 : } 88 : : 89 : 35 : std::shared_ptr<ProofNode> LazyTreeProofGenerator::getProofFor( 90 : : CVC5_UNUSED Node f) 91 : : { 92 [ - + ][ - + ]: 35 : Assert(hasProofFor(f)); [ - - ] 93 : 35 : return getProof(); 94 : : } 95 : : 96 : 72 : bool LazyTreeProofGenerator::hasProofFor(Node f) 97 : : { 98 : 72 : return f == getProof()->getResult(); 99 : : } 100 : : 101 : 482 : std::shared_ptr<ProofNode> LazyTreeProofGenerator::getProof( 102 : : std::vector<std::shared_ptr<ProofNode>>& scope, 103 : : const detail::TreeProofNode& pn) const 104 : : { 105 : 482 : ProofNodeManager* pnm = d_env.getProofNodeManager(); 106 : : // Store scope size to reset scope afterwards 107 : 482 : std::size_t before = scope.size(); 108 : 482 : std::vector<std::shared_ptr<ProofNode>> children; 109 [ + + ]: 482 : if (pn.d_rule == ProofRule::SCOPE) 110 : : { 111 : : // Extend scope for all but the root node 112 [ + + ]: 238 : if (&pn != &d_proof) 113 : : { 114 [ + + ]: 402 : for (const auto& a : pn.d_args) 115 : : { 116 : 201 : scope.emplace_back(pnm->mkAssume(a)); 117 : : } 118 : : } 119 : : } 120 : : else 121 : : { 122 : : // Initialize the children with the scope 123 : 244 : children = scope; 124 : : } 125 [ + + ]: 927 : for (auto& c : pn.d_children) 126 : : { 127 : : // Recurse into tree 128 : 445 : children.emplace_back(getProof(scope, c)); 129 : : } 130 [ + + ]: 624 : for (const auto& p : pn.d_premise) 131 : : { 132 : : // Add premises as assumptions 133 : 142 : children.emplace_back(pnm->mkAssume(p)); 134 : : } 135 : : // Reset scope 136 : 482 : scope.resize(before); 137 : 964 : return pnm->mkNode(pn.d_rule, children, pn.d_args); 138 : 482 : } 139 : : 140 : 0 : void LazyTreeProofGenerator::print(std::ostream& os, 141 : : const std::string& prefix, 142 : : const detail::TreeProofNode& pn) const 143 : : { 144 : 0 : os << prefix << pn.d_rule << " [" << pn.d_objectId << "]: "; 145 : 0 : container_to_stream(os, pn.d_premise); 146 : 0 : os << " ==> " << pn.d_proven << std::endl; 147 [ - - ]: 0 : if (!pn.d_args.empty()) 148 : : { 149 : 0 : os << prefix << ":args "; 150 : 0 : container_to_stream(os, pn.d_args); 151 : 0 : os << std::endl; 152 : : } 153 [ - - ]: 0 : for (const auto& c : pn.d_children) 154 : : { 155 : 0 : print(os, prefix + '\t', c); 156 : : } 157 : 0 : } 158 : : 159 : 0 : std::ostream& operator<<(std::ostream& os, const LazyTreeProofGenerator& ltpg) 160 : : { 161 : 0 : ltpg.print(os, "", ltpg.d_proof); 162 : 0 : return os; 163 : : } 164 : : 165 : : } // namespace cvc5::internal