GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/quantifiers_attributes.cpp Lines: 152 210 72.4 %
Date: 2021-08-19 Branches: 331 792 41.8 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Paul Meng, Morgan Deters
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 QuantifiersAttributes class.
14
 */
15
16
#include "theory/quantifiers/quantifiers_attributes.h"
17
18
#include "options/quantifiers_options.h"
19
#include "theory/arith/arith_msum.h"
20
#include "theory/quantifiers/sygus/synth_engine.h"
21
#include "theory/quantifiers/term_util.h"
22
23
using namespace std;
24
using namespace cvc5::kind;
25
using namespace cvc5::context;
26
27
namespace cvc5 {
28
namespace theory {
29
namespace quantifiers {
30
31
962566
bool QAttributes::isStandard() const
32
{
33
962566
  return !d_sygus && !d_quant_elim && !isFunDef() && !d_isInternal;
34
}
35
36
9854
QuantAttributes::QuantAttributes() {}
37
38
241
void QuantAttributes::setUserAttribute( const std::string& attr, Node n, std::vector< Node >& node_values, std::string str_value ){
39
241
  Trace("quant-attr-debug") << "Set " << attr << " " << n << std::endl;
40
241
  if (attr == "fun-def")
41
  {
42
    Trace("quant-attr-debug") << "Set function definition " << n << std::endl;
43
    FunDefAttribute fda;
44
    n.setAttribute( fda, true );
45
  }
46
241
  else if (attr == "qid")
47
  {
48
    // using z3 syntax "qid"
49
211
    Trace("quant-attr-debug") << "Set quant-name " << n << std::endl;
50
    QuantNameAttribute qna;
51
211
    n.setAttribute(qna, true);
52
30
  }else if( attr=="quant-inst-max-level" ){
53
    Assert(node_values.size() == 1);
54
    uint64_t lvl = node_values[0].getConst<Rational>().getNumerator().getLong();
55
    Trace("quant-attr-debug") << "Set instantiation level " << n << " to " << lvl << std::endl;
56
    QuantInstLevelAttribute qila;
57
    n.setAttribute( qila, lvl );
58
30
  }else if( attr=="quant-elim" ){
59
27
    Trace("quant-attr-debug") << "Set quantifier elimination " << n << std::endl;
60
    QuantElimAttribute qea;
61
27
    n.setAttribute( qea, true );
62
3
  }else if( attr=="quant-elim-partial" ){
63
3
    Trace("quant-attr-debug") << "Set partial quantifier elimination " << n << std::endl;
64
    QuantElimPartialAttribute qepa;
65
3
    n.setAttribute( qepa, true );
66
  }
67
241
}
68
69
bool QuantAttributes::checkFunDef( Node q ) {
70
  return !getFunDefHead( q ).isNull();
71
}
72
73
bool QuantAttributes::checkFunDefAnnotation( Node ipl ) {
74
  if( !ipl.isNull() ){
75
    for( unsigned i=0; i<ipl.getNumChildren(); i++ ){
76
      if( ipl[i].getKind()==INST_ATTRIBUTE ){
77
        if( ipl[i][0].getAttribute(FunDefAttribute()) ){
78
          return true;
79
        }
80
      }
81
    }
82
  }
83
  return false;
84
}
85
86
615
Node QuantAttributes::getFunDefHead( Node q ) {
87
  //&& q[1].getKind()==EQUAL && q[1][0].getKind()==APPLY_UF &&
88
615
  if( q.getKind()==FORALL && q.getNumChildren()==3 ){
89
238
    Node ipl = q[2];
90
238
    for (unsigned i = 0; i < ipl.getNumChildren(); i++)
91
    {
92
708
      if (ipl[i].getKind() == INST_ATTRIBUTE
93
708
          && ipl[i][0].getAttribute(FunDefAttribute()))
94
      {
95
234
        return ipl[i][0];
96
      }
97
    }
98
  }
99
381
  return Node::null();
100
}
101
117
Node QuantAttributes::getFunDefBody( Node q ) {
102
234
  Node h = getFunDefHead( q );
103
117
  if( !h.isNull() ){
104
117
    if( q[1].getKind()==EQUAL ){
105
112
      if( q[1][0]==h ){
106
63
        return q[1][1];
107
49
      }else if( q[1][1]==h ){
108
48
        return q[1][0];
109
      }
110
1
      else if (q[1][0].getType().isReal())
111
      {
112
        // solve for h in the equality
113
1
        std::map<Node, Node> msum;
114
1
        if (ArithMSum::getMonomialSumLit(q[1], msum))
115
        {
116
1
          Node veq;
117
1
          int res = ArithMSum::isolate(h, msum, veq, EQUAL);
118
1
          if (res != 0)
119
          {
120
1
            Assert(veq.getKind() == EQUAL);
121
1
            return res == 1 ? veq[1] : veq[0];
122
          }
123
        }
124
      }
125
    }else{
126
5
      Node atom = q[1].getKind()==NOT ? q[1][0] : q[1];
127
5
      bool pol = q[1].getKind()!=NOT;
128
5
      if( atom==h ){
129
5
        return NodeManager::currentNM()->mkConst( pol );
130
      }
131
    }
132
  }
133
  return Node::null();
134
}
135
136
2351
bool QuantAttributes::checkSygusConjecture( Node q ) {
137
2351
  return ( q.getKind()==FORALL && q.getNumChildren()==3 ) ? checkSygusConjectureAnnotation( q[2] ) : false;
138
}
139
140
421
bool QuantAttributes::checkSygusConjectureAnnotation( Node ipl ){
141
421
  if( !ipl.isNull() ){
142
509
    for( unsigned i=0; i<ipl.getNumChildren(); i++ ){
143
421
      if( ipl[i].getKind()==INST_ATTRIBUTE ){
144
509
        Node avar = ipl[i][0];
145
421
        if( avar.getAttribute(SygusAttribute()) ){
146
333
          return true;
147
        }
148
      }
149
    }
150
  }
151
88
  return false;
152
}
153
154
bool QuantAttributes::checkQuantElimAnnotation( Node ipl ) {
155
  if( !ipl.isNull() ){
156
    for( unsigned i=0; i<ipl.getNumChildren(); i++ ){
157
      if( ipl[i].getKind()==INST_ATTRIBUTE ){
158
        Node avar = ipl[i][0];
159
        if( avar.getAttribute(QuantElimAttribute()) ){
160
          return true;
161
        }
162
      }
163
    }
164
  }
165
  return false;
166
}
167
168
25031
void QuantAttributes::computeAttributes( Node q ) {
169
25031
  computeQuantAttributes( q, d_qattr[q] );
170
25031
  QAttributes& qa = d_qattr[q];
171
25031
  if (qa.isFunDef())
172
  {
173
272
    Node f = qa.d_fundef_f;
174
136
    if( d_fun_defs.find( f )!=d_fun_defs.end() ){
175
      CVC5Message() << "Cannot define function " << f << " more than once."
176
                    << std::endl;
177
      AlwaysAssert(false);
178
    }
179
136
    d_fun_defs[f] = true;
180
  }
181
25031
}
182
183
192675
void QuantAttributes::computeQuantAttributes( Node q, QAttributes& qa ){
184
192675
  Trace("quant-attr-debug") << "Compute attributes for " << q << std::endl;
185
192675
  if( q.getNumChildren()==3 ){
186
34128
    qa.d_ipl = q[2];
187
72012
    for( unsigned i=0; i<q[2].getNumChildren(); i++ ){
188
37884
      Kind k = q[2][i].getKind();
189
75768
      Trace("quant-attr-debug")
190
37884
          << "Check : " << q[2][i] << " " << k << std::endl;
191
37884
      if (k == INST_PATTERN || k == INST_NO_PATTERN)
192
      {
193
27220
        qa.d_hasPattern = true;
194
      }
195
10664
      else if (k == INST_POOL || k == INST_ADD_TO_POOL
196
10608
               || k == SKOLEM_ADD_TO_POOL)
197
      {
198
112
        qa.d_hasPool = true;
199
      }
200
10552
      else if (k == INST_ATTRIBUTE)
201
      {
202
21104
        Node avar = q[2][i][0];
203
10552
        if( avar.getAttribute(FunDefAttribute()) ){
204
1058
          Trace("quant-attr") << "Attribute : function definition : " << q << std::endl;
205
          //get operator directly from pattern
206
1058
          qa.d_fundef_f = q[2][i][0].getOperator();
207
        }
208
10552
        if( avar.getAttribute(SygusAttribute()) ){
209
          //not necessarily nested existential
210
          //Assert( q[1].getKind()==NOT );
211
          //Assert( q[1][0].getKind()==FORALL );
212
2413
          Trace("quant-attr") << "Attribute : sygus : " << q << std::endl;
213
2413
          qa.d_sygus = true;
214
        }
215
10552
        if (avar.hasAttribute(SygusSideConditionAttribute()))
216
        {
217
132
          qa.d_sygusSideCondition =
218
264
              avar.getAttribute(SygusSideConditionAttribute());
219
264
          Trace("quant-attr")
220
132
              << "Attribute : sygus side condition : "
221
132
              << qa.d_sygusSideCondition << " : " << q << std::endl;
222
        }
223
10552
        if (avar.getAttribute(QuantNameAttribute()))
224
        {
225
6460
          Trace("quant-attr") << "Attribute : quantifier name : " << avar
226
3230
                              << " for " << q << std::endl;
227
3230
          qa.d_name = avar;
228
        }
229
10552
        if( avar.hasAttribute(QuantInstLevelAttribute()) ){
230
          qa.d_qinstLevel = avar.getAttribute(QuantInstLevelAttribute());
231
          Trace("quant-attr") << "Attribute : quant inst level " << qa.d_qinstLevel << " : " << q << std::endl;
232
        }
233
10552
        if( avar.getAttribute(QuantElimAttribute()) ){
234
379
          Trace("quant-attr") << "Attribute : quantifier elimination : " << q << std::endl;
235
379
          qa.d_quant_elim = true;
236
          //don't set owner, should happen naturally
237
        }
238
10552
        if( avar.getAttribute(QuantElimPartialAttribute()) ){
239
17
          Trace("quant-attr") << "Attribute : quantifier elimination partial : " << q << std::endl;
240
17
          qa.d_quant_elim = true;
241
17
          qa.d_quant_elim_partial = true;
242
          //don't set owner, should happen naturally
243
        }
244
10552
        if (avar.getAttribute(InternalQuantAttribute()))
245
        {
246
3081
          Trace("quant-attr") << "Attribute : internal : " << q << std::endl;
247
3081
          qa.d_isInternal = true;
248
        }
249
10552
        if( avar.hasAttribute(QuantIdNumAttribute()) ){
250
          qa.d_qid_num = avar;
251
          Trace("quant-attr") << "Attribute : id number " << qa.d_qid_num.getAttribute(QuantIdNumAttribute()) << " : " << q << std::endl;
252
        }
253
      }
254
    }
255
  }
256
192675
}
257
258
769
bool QuantAttributes::isFunDef( Node q ) {
259
769
  std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
260
769
  if( it==d_qattr.end() ){
261
    return false;
262
  }else{
263
769
    return it->second.isFunDef();
264
  }
265
}
266
267
1065
bool QuantAttributes::isSygus( Node q ) {
268
1065
  std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
269
1065
  if( it==d_qattr.end() ){
270
    return false;
271
  }else{
272
1065
    return it->second.d_sygus;
273
  }
274
}
275
276
970
int64_t QuantAttributes::getQuantInstLevel(Node q)
277
{
278
970
  std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
279
970
  if( it==d_qattr.end() ){
280
    return -1;
281
  }else{
282
970
    return it->second.d_qinstLevel;
283
  }
284
}
285
286
bool QuantAttributes::isQuantElim( Node q ) {
287
  std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
288
  if( it==d_qattr.end() ){
289
    return false;
290
  }else{
291
    return it->second.d_quant_elim;
292
  }
293
}
294
295
5796
bool QuantAttributes::isQuantElimPartial( Node q ) {
296
5796
  std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
297
5796
  if( it==d_qattr.end() ){
298
    return false;
299
  }else{
300
5796
    return it->second.d_quant_elim_partial;
301
  }
302
}
303
304
66145
bool QuantAttributes::isInternal(Node q) const
305
{
306
66145
  std::map<Node, QAttributes>::const_iterator it = d_qattr.find(q);
307
66145
  if (it != d_qattr.end())
308
  {
309
66145
    return it->second.d_isInternal;
310
  }
311
  return false;
312
}
313
314
34
Node QuantAttributes::getQuantName(Node q) const
315
{
316
34
  std::map<Node, QAttributes>::const_iterator it = d_qattr.find(q);
317
34
  if (it != d_qattr.end())
318
  {
319
34
    return it->second.d_name;
320
  }
321
  return Node::null();
322
}
323
324
std::string QuantAttributes::quantToString(Node q) const
325
{
326
  std::stringstream ss;
327
  Node name = getQuantName(q);
328
  ss << (name.isNull() ? q : name);
329
  return ss.str();
330
}
331
332
int QuantAttributes::getQuantIdNum( Node q ) {
333
  std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
334
  if( it!=d_qattr.end() ){
335
    if( !it->second.d_qid_num.isNull() ){
336
      return it->second.d_qid_num.getAttribute(QuantIdNumAttribute());
337
    }
338
  }
339
  return -1;
340
}
341
342
Node QuantAttributes::getQuantIdNumNode( Node q ) {
343
  std::map< Node, QAttributes >::iterator it = d_qattr.find( q );
344
  if( it==d_qattr.end() ){
345
    return Node::null();
346
  }else{
347
    return it->second.d_qid_num;
348
  }
349
}
350
351
2835
void QuantAttributes::setInstantiationLevelAttr(Node n, Node qn, uint64_t level)
352
{
353
5670
  Trace("inst-level-debug2") << "IL : " << n << " " << qn << " " << level
354
2835
                             << std::endl;
355
  // if not from the vector of terms we instantiatied
356
2835
  if (qn.getKind() != BOUND_VARIABLE && n != qn)
357
  {
358
    // if this is a new term, without an instantiation level
359
2078
    if (!n.hasAttribute(InstLevelAttribute()))
360
    {
361
      InstLevelAttribute ila;
362
1188
      n.setAttribute(ila, level);
363
2376
      Trace("inst-level-debug") << "Set instantiation level " << n << " to "
364
1188
                                << level << std::endl;
365
1188
      Assert(n.getNumChildren() == qn.getNumChildren());
366
3677
      for (unsigned i = 0; i < n.getNumChildren(); i++)
367
      {
368
2489
        setInstantiationLevelAttr(n[i], qn[i], level);
369
      }
370
    }
371
  }
372
2835
}
373
374
2099
void QuantAttributes::setInstantiationLevelAttr(Node n, uint64_t level)
375
{
376
2099
  if (!n.hasAttribute(InstLevelAttribute()))
377
  {
378
    InstLevelAttribute ila;
379
1104
    n.setAttribute(ila, level);
380
2208
    Trace("inst-level-debug") << "Set instantiation level " << n << " to "
381
1104
                              << level << std::endl;
382
2973
    for (unsigned i = 0; i < n.getNumChildren(); i++)
383
    {
384
1869
      setInstantiationLevelAttr(n[i], level);
385
    }
386
  }
387
2099
}
388
389
}  // namespace quantifiers
390
}  // namespace theory
391
29349
}  // namespace cvc5