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 expand definitions for an SMT engine. 11 : : */ 12 : : 13 : : #include "smt/expand_definitions.h" 14 : : 15 : : #include <stack> 16 : : #include <utility> 17 : : 18 : : #include "preprocessing/assertion_pipeline.h" 19 : : #include "smt/env.h" 20 : : #include "theory/rewriter.h" 21 : : #include "theory/theory.h" 22 : : #include "util/resource_manager.h" 23 : : 24 : : using namespace cvc5::internal::preprocessing; 25 : : using namespace cvc5::internal::theory; 26 : : using namespace cvc5::internal::kind; 27 : : 28 : : namespace cvc5::internal { 29 : : namespace smt { 30 : : 31 : 21110 : ExpandDefs::ExpandDefs(Env& env) : EnvObj(env) {} 32 : : 33 : 21110 : ExpandDefs::~ExpandDefs() {} 34 : : 35 : 42400 : Node ExpandDefs::expandDefinitions(TNode n, 36 : : std::unordered_map<Node, Node>& cache) 37 : : { 38 : 42400 : const TNode orig = n; 39 : 42400 : std::stack<std::tuple<Node, Node, bool>> worklist; 40 : 42400 : std::stack<Node> result; 41 : 42400 : worklist.push(std::make_tuple(Node(n), Node(n), false)); 42 : : // The worklist is made of triples, each is input / original node then the 43 : : // output / rewritten node and finally a flag tracking whether the children 44 : : // have been explored (i.e. if this is a downward or upward pass). 45 : : 46 : 42400 : ResourceManager* rm = d_env.getResourceManager(); 47 : 42400 : Rewriter* rr = d_env.getRewriter(); 48 : : do 49 : : { 50 : 671248 : rm->spendResource(Resource::PreprocessStep); 51 : : 52 : : // n is the input / original 53 : : // node is the output / result 54 : 671248 : Node node; 55 : : bool childrenPushed; 56 : 671248 : std::tie(n, node, childrenPushed) = worklist.top(); 57 : 671248 : worklist.pop(); 58 : : 59 : : // Working downwards 60 [ + + ]: 671248 : if (!childrenPushed) 61 : : { 62 : : // we can short circuit (variable) leaves and closures, whose bodies 63 : : // are not preprocessed 64 [ + + ][ + + ]: 463964 : if (n.isVar() || n.isClosure()) [ + + ] 65 : : { 66 : : // don't bother putting in the cache 67 : 153401 : result.push(n); 68 : 256680 : continue; 69 : : } 70 : : 71 : : // maybe it's in the cache 72 : 310563 : std::unordered_map<Node, Node>::iterator cacheHit = cache.find(n); 73 [ + + ]: 310563 : if (cacheHit != cache.end()) 74 : : { 75 : 103279 : TNode ret = (*cacheHit).second; 76 [ + + ]: 103279 : result.push(ret.isNull() ? n : ret); 77 : 103279 : continue; 78 : 103279 : } 79 : : // ensure rewritten 80 : 207284 : Node nr = rewrite(n); 81 : : // now get the appropriate theory 82 : 207284 : theory::TheoryId tid = d_env.theoryOf(nr); 83 : 207284 : theory::TheoryRewriter* tr = rr->getTheoryRewriter(tid); 84 : : 85 [ - + ][ - + ]: 207284 : Assert(tr != NULL); [ - - ] 86 [ + - ]: 414568 : Trace("expand") << "Expand definition on " << nr << " (from " << n << ")" 87 : 207284 : << std::endl; 88 : 207284 : Node nre = tr->expandDefinition(nr); 89 [ + - ]: 207284 : Trace("expand") << "...returns " << nre << std::endl; 90 [ + + ]: 207284 : node = nre.isNull() ? nr : nre; 91 : : // the partial functions can fall through, in which case we still 92 : : // consider their children 93 : 207284 : worklist.push(std::make_tuple( 94 : 414568 : Node(n), node, true)); // Original and rewritten result 95 : : 96 [ + + ]: 628848 : for (const Node& nc : node) 97 : : { 98 : : // Rewrite the children of the result only 99 : 421564 : worklist.push(std::make_tuple(nc, nc, false)); 100 : 421564 : } 101 : 207284 : } 102 : : else 103 : : { 104 : : // Working upwards 105 : : // Reconstruct the node from it's (now rewritten) children on the stack 106 : : 107 [ + - ]: 207284 : Trace("expand") << "cons : " << node << std::endl; 108 [ + + ]: 207284 : if (node.getNumChildren() > 0) 109 : : { 110 : : // cout << "cons : " << node << std::endl; 111 : 182476 : NodeBuilder nb(nodeManager(), node.getKind()); 112 [ + + ]: 182476 : if (node.getMetaKind() == metakind::PARAMETERIZED) 113 : : { 114 [ + - ][ - + ]: 9093 : Trace("expand") << "op : " << node.getOperator() << std::endl; [ - - ] 115 : : // cout << "op : " << node.getOperator() << std::endl; 116 : 9093 : nb << node.getOperator(); 117 : : } 118 [ + + ]: 604040 : for (size_t i = 0, nchild = node.getNumChildren(); i < nchild; ++i) 119 : : { 120 [ - + ][ - + ]: 421564 : Assert(!result.empty()); [ - - ] 121 : 421564 : Node expanded = result.top(); 122 : 421564 : result.pop(); 123 : : // cout << "exchld : " << expanded << std::endl; 124 [ + - ]: 421564 : Trace("expand") << "exchld : " << expanded << std::endl; 125 : 421564 : nb << expanded; 126 : 421564 : } 127 : 182476 : node = nb; 128 : 182476 : } 129 : : // Only cache once all subterms are expanded 130 [ + + ]: 207284 : cache[n] = n == node ? Node::null() : node; 131 : 207284 : result.push(node); 132 : : } 133 [ + + ][ + + ]: 1342496 : } while (!worklist.empty()); 134 : : 135 [ - + ][ - + ]: 42400 : AlwaysAssert(result.size() == 1); [ - - ] 136 : : 137 : 84800 : return result.top(); 138 : 42400 : } 139 : : 140 : : } // namespace smt 141 : : } // namespace cvc5::internal