GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/proof_checker.cpp Lines: 43 63 68.3 %
Date: 2021-08-14 Branches: 69 308 22.4 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Aina Niemetz
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 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
22
using namespace cvc5::kind;
23
24
namespace cvc5 {
25
namespace theory {
26
namespace quantifiers {
27
28
3768
void QuantifiersProofRuleChecker::registerTo(ProofChecker* pc)
29
{
30
  // add checkers
31
3768
  pc->registerChecker(PfRule::SKOLEM_INTRO, this);
32
3768
  pc->registerChecker(PfRule::EXISTS_INTRO, this);
33
3768
  pc->registerChecker(PfRule::SKOLEMIZE, this);
34
3768
  pc->registerChecker(PfRule::INSTANTIATE, this);
35
  // trusted rules
36
3768
  pc->registerTrustedChecker(PfRule::QUANTIFIERS_PREPROCESS, this, 3);
37
3768
}
38
39
12977
Node QuantifiersProofRuleChecker::checkInternal(
40
    PfRule id, const std::vector<Node>& children, const std::vector<Node>& args)
41
{
42
12977
  NodeManager* nm = NodeManager::currentNM();
43
12977
  SkolemManager* sm = nm->getSkolemManager();
44
  // compute what was proven
45
12977
  if (id == PfRule::EXISTS_INTRO)
46
  {
47
    Assert(children.size() == 1);
48
    Assert(args.size() == 1);
49
    Node p = children[0];
50
    Node exists = args[0];
51
    if (exists.getKind() != kind::EXISTS || exists[0].getNumChildren() != 1)
52
    {
53
      return Node::null();
54
    }
55
    std::unordered_map<Node, Node> subs;
56
    if (!expr::match(exists[1], p, subs))
57
    {
58
      return Node::null();
59
    }
60
    // substitution must contain only the variable of the existential
61
    for (const std::pair<const Node, Node>& s : subs)
62
    {
63
      if (s.first != exists[0][0])
64
      {
65
        return Node::null();
66
      }
67
    }
68
    return exists;
69
  }
70
12977
  else if (id == PfRule::SKOLEM_INTRO)
71
  {
72
3571
    Assert(children.empty());
73
3571
    Assert(args.size() == 1);
74
7142
    Node t = SkolemManager::getOriginalForm(args[0]);
75
3571
    return args[0].eqNode(t);
76
  }
77
9406
  else if (id == PfRule::SKOLEMIZE)
78
  {
79
412
    Assert(children.size() == 1);
80
412
    Assert(args.empty());
81
    // can use either negated FORALL or EXISTS
82
824
    if (children[0].getKind() != EXISTS
83
824
        && (children[0].getKind() != NOT || children[0][0].getKind() != FORALL))
84
    {
85
      return Node::null();
86
    }
87
824
    Node exists;
88
412
    if (children[0].getKind() == EXISTS)
89
    {
90
87
      exists = children[0];
91
    }
92
    else
93
    {
94
650
      std::vector<Node> echildren(children[0][0].begin(), children[0][0].end());
95
325
      echildren[1] = echildren[1].notNode();
96
325
      exists = nm->mkNode(EXISTS, echildren);
97
    }
98
824
    std::vector<Node> skolems;
99
824
    Node res = sm->mkSkolemize(exists, skolems, "k");
100
412
    return res;
101
  }
102
8994
  else if (id == PfRule::INSTANTIATE)
103
  {
104
8994
    Assert(children.size() == 1);
105
    // note we may have more arguments than just the term vector
106
17988
    if (children[0].getKind() != FORALL
107
17988
        || args.size() < children[0][0].getNumChildren())
108
    {
109
      return Node::null();
110
    }
111
17988
    Node body = children[0][1];
112
17988
    std::vector<Node> vars;
113
17988
    std::vector<Node> subs;
114
38003
    for (size_t i = 0, nc = children[0][0].getNumChildren(); i < nc; i++)
115
    {
116
29009
      vars.push_back(children[0][0][i]);
117
29009
      subs.push_back(args[i]);
118
    }
119
    Node inst =
120
17988
        body.substitute(vars.begin(), vars.end(), subs.begin(), subs.end());
121
8994
    return inst;
122
  }
123
  else if (id == PfRule::QUANTIFIERS_PREPROCESS)
124
  {
125
    Assert(!args.empty());
126
    Assert(args[0].getType().isBoolean());
127
    return args[0];
128
  }
129
130
  // no rule
131
  return Node::null();
132
}
133
134
}  // namespace quantifiers
135
}  // namespace theory
136
29340
}  // namespace cvc5