Branch data Line data Source code
1 : : /****************************************************************************** 2 : : * Top contributors (to current version): 3 : : * Andrew Reynolds, Hans-Joerg Schurr, Aina Niemetz 4 : : * 5 : : * This file is part of the cvc5 project. 6 : : * 7 : : * Copyright (c) 2009-2024 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 : : * Implementation of quantifiers proof checker. 14 : : */ 15 : : 16 : : #include "theory/quantifiers/proof_checker.h" 17 : : 18 : : #include "expr/node_algorithm.h" 19 : : #include "expr/skolem_manager.h" 20 : : #include "theory/builtin/proof_checker.h" 21 : : #include "theory/quantifiers/skolemize.h" 22 : : 23 : : using namespace cvc5::internal::kind; 24 : : 25 : : namespace cvc5::internal { 26 : : namespace theory { 27 : : namespace quantifiers { 28 : : 29 : 49207 : QuantifiersProofRuleChecker::QuantifiersProofRuleChecker(NodeManager* nm) 30 : 49207 : : ProofRuleChecker(nm) 31 : : { 32 : 49207 : } 33 : : 34 : 18572 : void QuantifiersProofRuleChecker::registerTo(ProofChecker* pc) 35 : : { 36 : : // add checkers 37 : 18572 : pc->registerChecker(ProofRule::SKOLEM_INTRO, this); 38 : 18572 : pc->registerChecker(ProofRule::SKOLEMIZE, this); 39 : 18572 : pc->registerChecker(ProofRule::INSTANTIATE, this); 40 : 18572 : pc->registerChecker(ProofRule::ALPHA_EQUIV, this); 41 : 18572 : } 42 : : 43 : 26716 : Node QuantifiersProofRuleChecker::checkInternal( 44 : : ProofRule id, 45 : : const std::vector<Node>& children, 46 : : const std::vector<Node>& args) 47 : : { 48 [ + + ]: 26716 : if (id == ProofRule::SKOLEM_INTRO) 49 : : { 50 [ - + ][ - + ]: 19808 : Assert(children.empty()); [ - - ] 51 [ - + ][ - + ]: 19808 : Assert(args.size() == 1); [ - - ] 52 : 39616 : Node t = SkolemManager::getUnpurifiedForm(args[0]); 53 : 19808 : return args[0].eqNode(t); 54 : : } 55 [ + + ]: 6908 : else if (id == ProofRule::SKOLEMIZE) 56 : : { 57 [ - + ][ - + ]: 1032 : Assert(children.size() == 1); [ - - ] 58 [ - + ][ - + ]: 1032 : Assert(args.empty()); [ - - ] 59 : : // must use negated FORALL 60 : 1032 : if (children[0].getKind() != Kind::NOT 61 [ + - ][ - + ]: 2064 : || children[0][0].getKind() != Kind::FORALL) [ + - ][ - + ] [ - - ] 62 : : { 63 : 0 : return Node::null(); 64 : : } 65 : 2064 : Node q = children[0][0]; 66 : 3096 : std::vector<Node> vars(q[0].begin(), q[0].end()); 67 : 2064 : std::vector<Node> skolems = Skolemize::getSkolemConstants(q); 68 : : Node res = q[1].substitute( 69 : 2064 : vars.begin(), vars.end(), skolems.begin(), skolems.end()); 70 : 1032 : res = res.notNode(); 71 : 1032 : return res; 72 : : } 73 [ + + ]: 5876 : else if (id == ProofRule::INSTANTIATE) 74 : : { 75 [ - + ][ - + ]: 5828 : Assert(children.size() == 1); [ - - ] 76 : : // note we may have more arguments than just the term vector 77 [ + - ][ - + ]: 5828 : if (children[0].getKind() != Kind::FORALL || args.empty()) [ - + ] 78 : : { 79 : 0 : return Node::null(); 80 : : } 81 : 11656 : Node body = children[0][1]; 82 : 11656 : std::vector<Node> vars; 83 : 11656 : std::vector<Node> subs; 84 [ + + ]: 20694 : for (size_t i = 0, nc = children[0][0].getNumChildren(); i < nc; i++) 85 : : { 86 : 14866 : vars.push_back(children[0][0][i]); 87 : 14866 : subs.push_back(args[0][i]); 88 : : } 89 : : Node inst = 90 : 11656 : body.substitute(vars.begin(), vars.end(), subs.begin(), subs.end()); 91 : 5828 : return inst; 92 : : } 93 [ + - ]: 48 : else if (id == ProofRule::ALPHA_EQUIV) 94 : : { 95 [ - + ][ - + ]: 48 : Assert(children.empty()); [ - - ] 96 [ - + ][ - + ]: 48 : Assert(args.size() == 3); [ - - ] 97 : : // must be lists of the same length 98 [ + - ]: 96 : if (args[1].getKind() != Kind::SEXPR || args[2].getKind() != Kind::SEXPR 99 [ + - ][ - + ]: 96 : || args[1].getNumChildren() != args[2].getNumChildren()) [ - + ] 100 : : { 101 : 0 : return Node::null(); 102 : : } 103 : : // arguments must be lists of bound variables that are pairwise unique 104 [ + + ][ + + ]: 288 : std::unordered_set<Node> allVars[2]; [ - - ] 105 : 96 : std::vector<Node> vars; 106 : 96 : std::vector<Node> newVars; 107 [ + + ]: 104 : for (size_t i = 0, nargs = args[1].getNumChildren(); i < nargs; i++) 108 : : { 109 [ + + ]: 168 : for (size_t j = 1; j <= 2; j++) 110 : : { 111 : 112 : Node v = args[j][i]; 112 : 112 : std::unordered_set<Node>& av = allVars[j - 1]; 113 [ + - ][ - + ]: 112 : if (v.getKind() != Kind::BOUND_VARIABLE || av.find(v) != av.end()) [ - + ] 114 : : { 115 : 0 : return Node::null(); 116 : : } 117 : 112 : av.insert(v); 118 : : } 119 : 56 : vars.push_back(args[1][i]); 120 : 56 : newVars.push_back(args[2][i]); 121 : : } 122 : 48 : Node renamedBody = args[0].substitute( 123 : 96 : vars.begin(), vars.end(), newVars.begin(), newVars.end()); 124 : 48 : return args[0].eqNode(renamedBody); 125 : : } 126 : : 127 : : // no rule 128 : 0 : return Node::null(); 129 : : } 130 : : 131 : : } // namespace quantifiers 132 : : } // namespace theory 133 : : } // namespace cvc5::internal