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 : : * Oracle caller 11 : : */ 12 : : 13 : : #include "expr/oracle_caller.h" 14 : : 15 : : #include "theory/quantifiers/quantifiers_attributes.h" 16 : : 17 : : namespace cvc5::internal { 18 : : 19 : 326 : OracleCaller::OracleCaller(const Node& n) 20 : 326 : : d_oracleNode(getOracleFor(n)), 21 : 326 : d_oracle(n.getNodeManager()->getOracleFor(d_oracleNode)) 22 : : { 23 [ - + ][ - + ]: 326 : Assert(!d_oracleNode.isNull()); [ - - ] 24 : 326 : } 25 : : 26 : 1182 : bool OracleCaller::callOracle(const Node& fapp, std::vector<Node>& res) 27 : : { 28 : 1182 : std::map<Node, std::vector<Node>>::iterator it = d_cachedResults.find(fapp); 29 [ - + ]: 1182 : if (it != d_cachedResults.end()) 30 : : { 31 [ - - ]: 0 : Trace("oracle-calls") << "Using cached oracle result for " << fapp 32 : 0 : << std::endl; 33 : 0 : res = it->second; 34 : : // don't bother setting runResult 35 : 0 : return false; 36 : : } 37 [ - + ][ - + ]: 1182 : Assert(fapp.getKind() == Kind::APPLY_UF); [ - - ] 38 [ - + ][ - + ]: 1182 : Assert(getOracleFor(fapp.getOperator()) == d_oracleNode); [ - - ] 39 : : 40 [ + - ]: 1182 : Trace("oracle-calls") << "Call oracle " << fapp << std::endl; 41 : : // get the input arguments from the application 42 : 1182 : std::vector<Node> args(fapp.begin(), fapp.end()); 43 : : // run the oracle method 44 : 1182 : std::vector<Node> response = d_oracle.run(args); 45 [ + - ]: 1182 : Trace("oracle-calls") << "response node " << response << std::endl; 46 : : // cache the response 47 : 1182 : d_cachedResults[fapp] = response; 48 : 1182 : res = response; 49 : 1182 : return true; 50 : 1182 : } 51 : : 52 : 3342 : bool OracleCaller::isOracleFunction(Node f) 53 : : { 54 : 3342 : return f.hasAttribute(theory::OracleInterfaceAttribute()); 55 : : } 56 : : 57 : 652 : bool OracleCaller::isOracleFunctionApp(Node n) 58 : : { 59 [ + + ]: 652 : if (n.getKind() == Kind::APPLY_UF) 60 : : { 61 : 326 : return isOracleFunction(n.getOperator()); 62 : : } 63 : : // possibly 0-ary 64 : 326 : return isOracleFunction(n); 65 : : } 66 : : 67 : 1508 : Node OracleCaller::getOracleFor(const Node& n) 68 : : { 69 : : // oracle functions have no children 70 [ + - ]: 1508 : if (n.isVar()) 71 : : { 72 [ - + ][ - + ]: 1508 : Assert(isOracleFunction(n)); [ - - ] 73 : 1508 : Node o = n.getAttribute(theory::OracleInterfaceAttribute()); 74 [ - + ][ - + ]: 1508 : Assert(o.getKind() == Kind::ORACLE); [ - - ] 75 : 1508 : return o; 76 : 1508 : } 77 [ - - ]: 0 : else if (n.getKind() == Kind::FORALL) 78 : : { 79 : : // oracle interfaces have children, and the attribute is stored in 2nd child 80 [ - - ]: 0 : for (const Node& v : n[2][0]) 81 : : { 82 [ - - ]: 0 : if (v.getKind() == Kind::ORACLE) 83 : : { 84 : 0 : return v; 85 : : } 86 [ - - ][ - - ]: 0 : } 87 : : } 88 : 0 : DebugUnhandled() << "Unexpected node for oracle " << n; 89 : : return Node::null(); 90 : : } 91 : : 92 : 0 : const std::map<Node, std::vector<Node>>& OracleCaller::getCachedResults() const 93 : : { 94 : 0 : return d_cachedResults; 95 : : } 96 : : 97 : : } // namespace cvc5::internal