Branch data Line data Source code
1 : : /****************************************************************************** 2 : : * Top contributors (to current version): 3 : : * Andrew Reynolds, Aina Niemetz, Daniel Larraz 4 : : * 5 : : * This file is part of the cvc5 project. 6 : : * 7 : : * Copyright (c) 2009-2025 by the authors listed in the file AUTHORS 8 : : * in the top-level source directory and their institutional affiliations. 9 : : * All rights reserved. See the file COPYING in the top-level source 10 : : * directory for licensing information. 11 : : * **************************************************************************** 12 : : * 13 : : * Oracle caller 14 : : */ 15 : : 16 : : #include "expr/oracle_caller.h" 17 : : 18 : : #include "theory/quantifiers/quantifiers_attributes.h" 19 : : 20 : : namespace cvc5::internal { 21 : : 22 : 326 : OracleCaller::OracleCaller(const Node& n) 23 : : : d_oracleNode(getOracleFor(n)), 24 : 326 : d_oracle(n.getNodeManager()->getOracleFor(d_oracleNode)) 25 : : { 26 [ - + ][ - + ]: 326 : Assert(!d_oracleNode.isNull()); [ - - ] 27 : 326 : } 28 : : 29 : 1182 : bool OracleCaller::callOracle(const Node& fapp, std::vector<Node>& res) 30 : : { 31 : 1182 : std::map<Node, std::vector<Node>>::iterator it = d_cachedResults.find(fapp); 32 [ - + ]: 1182 : if (it != d_cachedResults.end()) 33 : : { 34 [ - - ]: 0 : Trace("oracle-calls") << "Using cached oracle result for " << fapp 35 : 0 : << std::endl; 36 : 0 : res = it->second; 37 : : // don't bother setting runResult 38 : 0 : return false; 39 : : } 40 [ - + ][ - + ]: 1182 : Assert(fapp.getKind() == Kind::APPLY_UF); [ - - ] 41 [ - + ][ - + ]: 1182 : Assert(getOracleFor(fapp.getOperator()) == d_oracleNode); [ - - ] 42 : : 43 [ + - ]: 1182 : Trace("oracle-calls") << "Call oracle " << fapp << std::endl; 44 : : // get the input arguments from the application 45 : 2364 : std::vector<Node> args(fapp.begin(), fapp.end()); 46 : : // run the oracle method 47 : 1182 : std::vector<Node> response = d_oracle.run(args); 48 [ + - ]: 1182 : Trace("oracle-calls") << "response node " << response << std::endl; 49 : : // cache the response 50 : 1182 : d_cachedResults[fapp] = response; 51 : 1182 : res = response; 52 : 1182 : return true; 53 : : } 54 : : 55 : 3342 : bool OracleCaller::isOracleFunction(Node f) 56 : : { 57 : 3342 : return f.hasAttribute(theory::OracleInterfaceAttribute()); 58 : : } 59 : : 60 : 652 : bool OracleCaller::isOracleFunctionApp(Node n) 61 : : { 62 [ + + ]: 652 : if (n.getKind() == Kind::APPLY_UF) 63 : : { 64 : 326 : return isOracleFunction(n.getOperator()); 65 : : } 66 : : // possibly 0-ary 67 : 326 : return isOracleFunction(n); 68 : : } 69 : : 70 : 1508 : Node OracleCaller::getOracleFor(const Node& n) 71 : : { 72 : : // oracle functions have no children 73 [ + - ]: 1508 : if (n.isVar()) 74 : : { 75 [ - + ][ - + ]: 1508 : Assert(isOracleFunction(n)); [ - - ] 76 : 3016 : Node o = n.getAttribute(theory::OracleInterfaceAttribute()); 77 [ - + ][ - + ]: 1508 : Assert(o.getKind() == Kind::ORACLE); [ - - ] 78 : 1508 : return o; 79 : : } 80 [ - - ]: 0 : else if (n.getKind() == Kind::FORALL) 81 : : { 82 : : // oracle interfaces have children, and the attribute is stored in 2nd child 83 [ - - ]: 0 : for (const Node& v : n[2][0]) 84 : : { 85 [ - - ]: 0 : if (v.getKind() == Kind::ORACLE) 86 : : { 87 : 0 : return v; 88 : : } 89 : : } 90 : : } 91 : 0 : Assert(false) << "Unexpected node for oracle " << n; 92 : : return Node::null(); 93 : : } 94 : : 95 : 0 : const std::map<Node, std::vector<Node>>& OracleCaller::getCachedResults() const 96 : : { 97 : 0 : return d_cachedResults; 98 : : } 99 : : 100 : : } // namespace cvc5::internal