GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/witness_form.cpp Lines: 45 64 70.3 %
Date: 2021-11-05 Branches: 81 296 27.4 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds
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
 * The module for managing witness form conversion in proofs.
14
 */
15
16
#include "smt/witness_form.h"
17
18
#include "expr/skolem_manager.h"
19
#include "smt/env.h"
20
#include "theory/rewriter.h"
21
22
namespace cvc5 {
23
namespace smt {
24
25
7987
WitnessFormGenerator::WitnessFormGenerator(Env& env)
26
7987
    : d_rewriter(env.getRewriter()),
27
      d_tcpg(env.getProofNodeManager(),
28
             nullptr,
29
             TConvPolicy::FIXPOINT,
30
             TConvCachePolicy::NEVER,
31
             "WfGenerator::TConvProofGenerator",
32
             nullptr,
33
             true),
34
      d_wintroPf(env.getProofNodeManager(),
35
                 nullptr,
36
                 nullptr,
37
                 "WfGenerator::LazyCDProof"),
38
      d_pskPf(
39
15974
          env.getProofNodeManager(), nullptr, "WfGenerator::PurifySkolemProof")
40
{
41
7987
}
42
43
8903
std::shared_ptr<ProofNode> WitnessFormGenerator::getProofFor(Node eq)
44
{
45
8903
  if (eq.getKind() != kind::EQUAL)
46
  {
47
    // expecting an equality
48
    return nullptr;
49
  }
50
17806
  Node lhs = eq[0];
51
17806
  Node rhs = convertToWitnessForm(eq[0]);
52
8903
  if (rhs != eq[1])
53
  {
54
    // expecting witness form
55
    return nullptr;
56
  }
57
17806
  std::shared_ptr<ProofNode> pn = d_tcpg.getProofFor(eq);
58
8903
  Assert(pn != nullptr);
59
8903
  return pn;
60
}
61
62
std::string WitnessFormGenerator::identify() const
63
{
64
  return "WitnessFormGenerator";
65
}
66
67
8903
Node WitnessFormGenerator::convertToWitnessForm(Node t)
68
{
69
8903
  Node tw = SkolemManager::getOriginalForm(t);
70
8903
  if (t == tw)
71
  {
72
    // trivial case
73
    return tw;
74
  }
75
8903
  std::unordered_set<TNode>::iterator it;
76
17806
  std::vector<TNode> visit;
77
17806
  TNode cur;
78
17806
  TNode curw;
79
8903
  visit.push_back(t);
80
62989
  do
81
  {
82
71892
    cur = visit.back();
83
71892
    visit.pop_back();
84
71892
    it = d_visited.find(cur);
85
71892
    if (it == d_visited.end())
86
    {
87
29567
      d_visited.insert(cur);
88
29567
      curw = SkolemManager::getOriginalForm(cur);
89
      // if its witness form is different
90
29567
      if (cur != curw)
91
      {
92
21056
        if (cur.isVar())
93
        {
94
7138
          Node eq = cur.eqNode(curw);
95
          // equality between a variable and its original form
96
3569
          d_eqs.insert(eq);
97
          // ------- SKOLEM_INTRO
98
          // k = t
99
3569
          d_wintroPf.addStep(eq, PfRule::SKOLEM_INTRO, {}, {cur});
100
3569
          d_tcpg.addRewriteStep(
101
              cur, curw, &d_wintroPf, true, PfRule::ASSUME, true);
102
        }
103
        else
104
        {
105
          // A term whose witness form is different from itself, recurse.
106
          // It should be the case that cur has children, since the witness
107
          // form of constants are themselves.
108
17487
          Assert(cur.getNumChildren() > 0);
109
17487
          if (cur.hasOperator())
110
          {
111
17487
            visit.push_back(cur.getOperator());
112
          }
113
17487
          visit.insert(visit.end(), cur.begin(), cur.end());
114
        }
115
      }
116
    }
117
71892
  } while (!visit.empty());
118
8903
  return tw;
119
}
120
121
36651
bool WitnessFormGenerator::requiresWitnessFormTransform(Node t, Node s) const
122
{
123
36651
  return d_rewriter->rewrite(t) != d_rewriter->rewrite(s);
124
}
125
126
8100
bool WitnessFormGenerator::requiresWitnessFormIntro(Node t) const
127
{
128
16200
  Node tr = d_rewriter->rewrite(t);
129
16200
  return !tr.isConst() || !tr.getConst<bool>();
130
}
131
132
const std::unordered_set<Node>& WitnessFormGenerator::getWitnessFormEqs() const
133
{
134
  return d_eqs;
135
}
136
137
ProofGenerator* WitnessFormGenerator::convertExistsInternal(Node exists)
138
{
139
  Assert(exists.getKind() == kind::EXISTS);
140
  if (exists[0].getNumChildren() == 1 && exists[1].getKind() == kind::EQUAL
141
      && exists[1][0] == exists[0][0])
142
  {
143
    Node tpurified = exists[1][1];
144
    Trace("witness-form") << "convertExistsInternal: infer purification "
145
                          << exists << " for " << tpurified << std::endl;
146
    // ------ REFL
147
    // t = t
148
    // ---------------- EXISTS_INTRO
149
    // exists x. x = t
150
    // The concluded existential is then used to construct the witness term
151
    // via witness intro.
152
    Node teq = tpurified.eqNode(tpurified);
153
    d_pskPf.addStep(teq, PfRule::REFL, {}, {tpurified});
154
    d_pskPf.addStep(exists, PfRule::EXISTS_INTRO, {teq}, {exists});
155
    return &d_pskPf;
156
  }
157
  return nullptr;
158
}
159
160
}  // namespace smt
161
31125
}  // namespace cvc5