GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/smt/witness_form.cpp Lines: 44 63 69.8 %
Date: 2021-05-22 Branches: 77 290 26.6 %

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