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