GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/equality_query.cpp Lines: 68 89 76.4 %
Date: 2021-09-29 Branches: 163 418 39.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Mathias Preiner, 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
 * Utilities used for querying about equality information.
14
 */
15
16
#include "theory/quantifiers/equality_query.h"
17
18
#include "options/quantifiers_options.h"
19
#include "theory/quantifiers/first_order_model.h"
20
#include "theory/quantifiers/quantifiers_attributes.h"
21
#include "theory/quantifiers/quantifiers_state.h"
22
#include "theory/quantifiers/term_util.h"
23
24
using namespace std;
25
using namespace cvc5::kind;
26
using namespace cvc5::context;
27
28
namespace cvc5 {
29
namespace theory {
30
namespace quantifiers {
31
32
6271
EqualityQuery::EqualityQuery(Env& env, QuantifiersState& qs, FirstOrderModel* m)
33
    : QuantifiersUtil(env),
34
      d_qstate(qs),
35
      d_model(m),
36
      d_eqi_counter(context()),
37
6271
      d_reset_count(0)
38
{
39
6271
}
40
41
6268
EqualityQuery::~EqualityQuery() {}
42
43
19493
bool EqualityQuery::reset(Theory::Effort e)
44
{
45
19493
  d_int_rep.clear();
46
19493
  d_reset_count++;
47
19493
  return true;
48
}
49
50
71339
Node EqualityQuery::getInternalRepresentative(Node a, Node q, size_t index)
51
{
52
71339
  Assert(q.isNull() || q.getKind() == FORALL);
53
142678
  Node r = d_qstate.getRepresentative(a);
54
71339
  if( options::finiteModelFind() ){
55
61376
    if( r.isConst() && quantifiers::TermUtil::containsUninterpretedConstant( r ) ){
56
      //map back from values assigned by model, if any
57
3920
      if (d_model != nullptr)
58
      {
59
7840
        Node tr = d_model->getRepSet()->getTermForRepresentative(r);
60
3920
        if (!tr.isNull())
61
        {
62
3920
          r = tr;
63
3920
          r = d_qstate.getRepresentative(r);
64
        }else{
65
          if( r.getType().isSort() ){
66
            Trace("internal-rep-warn") << "No representative for UF constant." << std::endl;
67
            //should never happen : UF constants should never escape model
68
            Assert(false);
69
          }
70
        }
71
      }
72
    }
73
  }
74
142678
  TypeNode v_tn = q.isNull() ? a.getType() : q[0][index].getType();
75
71339
  if (options::quantRepMode() == options::QuantRepMode::EE)
76
  {
77
    int32_t score = getRepScore(r, q, index, v_tn);
78
    if (score >= 0)
79
    {
80
      return r;
81
    }
82
    // if we are not a valid representative, try to select one below
83
  }
84
71339
  std::map<Node, Node>& v_int_rep = d_int_rep[v_tn];
85
71339
  std::map<Node, Node>::const_iterator itir = v_int_rep.find(r);
86
71339
  if (itir != v_int_rep.end())
87
  {
88
64335
    return itir->second;
89
  }
90
  // find best selection for representative
91
14008
  Node r_best;
92
14008
  std::vector<Node> eqc;
93
7004
  d_qstate.getEquivalenceClass(r, eqc);
94
14008
  Trace("internal-rep-select")
95
7004
      << "Choose representative for equivalence class : " << eqc
96
7004
      << ", type = " << v_tn << std::endl;
97
7004
  int32_t r_best_score = -1;
98
56991
  for (const Node& n : eqc)
99
  {
100
49987
    int32_t score = getRepScore(n, q, index, v_tn);
101
49987
    if (score != -2)
102
    {
103
91482
      if (r_best.isNull()
104
45741
          || (score >= 0 && (r_best_score < 0 || score < r_best_score)))
105
      {
106
7204
        r_best = n;
107
7204
        r_best_score = score;
108
      }
109
    }
110
  }
111
7004
  if (r_best.isNull())
112
  {
113
    Trace("internal-rep-warn")
114
        << "No valid choice for representative in eqc class " << eqc
115
        << std::endl;
116
    return Node::null();
117
  }
118
  // now, make sure that no other member of the class is an instance
119
14008
  std::unordered_map<TNode, Node> cache;
120
7004
  r_best = getInstance(r_best, eqc, cache);
121
  // store that this representative was chosen at this point
122
7004
  if (d_rep_score.find(r_best) == d_rep_score.end())
123
  {
124
1263
    d_rep_score[r_best] = d_reset_count;
125
  }
126
14008
  Trace("internal-rep-select")
127
7004
      << "...Choose " << r_best << " with score " << r_best_score
128
7004
      << " and type " << r_best.getType() << std::endl;
129
7004
  Assert(r_best.getType().isSubtypeOf(v_tn));
130
7004
  v_int_rep[r] = r_best;
131
7004
  if (Trace.isOn("internal-rep-debug"))
132
  {
133
    if (r_best != a)
134
    {
135
      Trace("internal-rep-debug")
136
          << "rep( " << a << " ) = " << r << ", " << std::endl;
137
      Trace("internal-rep-debug")
138
          << "int_rep( " << a << " ) = " << r_best << ", " << std::endl;
139
    }
140
  }
141
7004
  return r_best;
142
}
143
144
//helper functions
145
146
10871
Node EqualityQuery::getInstance(Node n,
147
                                const std::vector<Node>& eqc,
148
                                std::unordered_map<TNode, Node>& cache)
149
{
150
10871
  if(cache.find(n) != cache.end()) {
151
395
    return cache[n];
152
  }
153
14331
  for( size_t i=0; i<n.getNumChildren(); i++ ){
154
7722
    Node nn = getInstance( n[i], eqc, cache );
155
3867
    if( !nn.isNull() ){
156
12
      return cache[n] = nn;
157
    }
158
  }
159
10464
  if( std::find( eqc.begin(), eqc.end(), n )!=eqc.end() ){
160
7004
    return cache[n] = n;
161
  }else{
162
3460
    return cache[n] = Node::null();
163
  }
164
}
165
166
//-2 : invalid, -1 : undesired, otherwise : smaller the score, the better
167
49987
int32_t EqualityQuery::getRepScore(Node n, Node q, size_t index, TypeNode v_tn)
168
{
169
49987
  if( options::cegqi() && quantifiers::TermUtil::hasInstConstAttr(n) ){  //reject
170
    return -2;
171
49987
  }else if( !n.getType().isSubtypeOf( v_tn ) ){  //reject if incorrect type
172
4246
    return -2;
173
45741
  }else if( options::instMaxLevel()!=-1 ){
174
    //score prefer lowest instantiation level
175
    if( n.hasAttribute(InstLevelAttribute()) ){
176
      return n.getAttribute(InstLevelAttribute());
177
    }
178
    return options::instLevelInputOnly() ? -1 : 0;
179
  }
180
45741
  else if (options::quantRepMode() == options::QuantRepMode::FIRST)
181
  {
182
    // score prefers earliest use of this term as a representative
183
45741
    return d_rep_score.find(n) == d_rep_score.end() ? -1 : d_rep_score[n];
184
  }
185
  Assert(options::quantRepMode() == options::QuantRepMode::DEPTH);
186
  return quantifiers::TermUtil::getTermDepth(n);
187
}
188
189
}  // namespace quantifiers
190
}  // namespace theory
191
22746
}  // namespace cvc5