1 /********************* */
2 /*! \file quantifiers_attributes.cpp
4 ** Top contributors (to current version):
5 ** Andrew Reynolds, Morgan Deters, Paul Meng
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2017 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.\endverbatim
12 ** \brief Implementation of QuantifiersAttributes class
15 #include "theory/quantifiers/quantifiers_attributes.h"
17 #include "options/quantifiers_options.h"
18 #include "theory/arith/arith_msum.h"
19 #include "theory/quantifiers/fun_def_engine.h"
20 #include "theory/quantifiers/rewrite_engine.h"
21 #include "theory/quantifiers/sygus/ce_guided_instantiation.h"
22 #include "theory/quantifiers/term_util.h"
23 #include "theory/quantifiers_engine.h"
26 using namespace CVC4::kind
;
27 using namespace CVC4::context
;
31 namespace quantifiers
{
33 QuantAttributes::QuantAttributes( QuantifiersEngine
* qe
) :
38 void QuantAttributes::setUserAttribute( const std::string
& attr
, Node n
, std::vector
< Node
>& node_values
, std::string str_value
){
39 Trace("quant-attr-debug") << "Set " << attr
<< " " << n
<< std::endl
;
41 Trace("quant-attr-debug") << "Set axiom " << n
<< std::endl
;
43 n
.setAttribute( aa
, true );
44 }else if( attr
=="conjecture" ){
45 Trace("quant-attr-debug") << "Set conjecture " << n
<< std::endl
;
46 ConjectureAttribute ca
;
47 n
.setAttribute( ca
, true );
48 }else if( attr
=="fun-def" ){
49 Trace("quant-attr-debug") << "Set function definition " << n
<< std::endl
;
51 n
.setAttribute( fda
, true );
52 }else if( attr
=="sygus" ){
53 Trace("quant-attr-debug") << "Set sygus " << n
<< std::endl
;
55 n
.setAttribute( ca
, true );
56 } else if (attr
== "sygus-synth-grammar") {
57 Assert( node_values
.size()==1 );
58 Trace("quant-attr-debug") << "Set sygus synth grammar " << n
<< " to "
59 << node_values
[0] << std::endl
;
60 SygusSynthGrammarAttribute ssg
;
61 n
.setAttribute(ssg
, node_values
[0]);
62 }else if( attr
=="sygus-synth-fun-var-list" ){
63 Assert( node_values
.size()==1 );
64 Trace("quant-attr-debug") << "Set sygus synth fun var list to " << n
<< " to " << node_values
[0] << std::endl
;
65 SygusSynthFunVarListAttribute ssfvla
;
66 n
.setAttribute( ssfvla
, node_values
[0] );
67 }else if( attr
=="synthesis" ){
68 Trace("quant-attr-debug") << "Set synthesis " << n
<< std::endl
;
69 SynthesisAttribute ca
;
70 n
.setAttribute( ca
, true );
71 }else if( attr
=="quant-inst-max-level" ){
72 Assert( node_values
.size()==1 );
73 uint64_t lvl
= node_values
[0].getConst
<Rational
>().getNumerator().getLong();
74 Trace("quant-attr-debug") << "Set instantiation level " << n
<< " to " << lvl
<< std::endl
;
75 QuantInstLevelAttribute qila
;
76 n
.setAttribute( qila
, lvl
);
77 }else if( attr
=="rr-priority" ){
78 Assert( node_values
.size()==1 );
79 uint64_t lvl
= node_values
[0].getConst
<Rational
>().getNumerator().getLong();
80 Trace("quant-attr-debug") << "Set rewrite rule priority " << n
<< " to " << lvl
<< std::endl
;
81 RrPriorityAttribute rrpa
;
82 n
.setAttribute( rrpa
, lvl
);
83 }else if( attr
=="quant-elim" ){
84 Trace("quant-attr-debug") << "Set quantifier elimination " << n
<< std::endl
;
85 QuantElimAttribute qea
;
86 n
.setAttribute( qea
, true );
87 }else if( attr
=="quant-elim-partial" ){
88 Trace("quant-attr-debug") << "Set partial quantifier elimination " << n
<< std::endl
;
89 QuantElimPartialAttribute qepa
;
90 n
.setAttribute( qepa
, true );
94 bool QuantAttributes::checkRewriteRule( Node q
) {
95 return !getRewriteRule( q
).isNull();
98 Node
QuantAttributes::getRewriteRule( Node q
) {
99 if (q
.getKind() == FORALL
&& q
.getNumChildren() == 3
100 && q
[2][0].getNumChildren() > 0
101 && q
[2][0][0].getKind() == REWRITE_RULE
)
109 bool QuantAttributes::checkFunDef( Node q
) {
110 return !getFunDefHead( q
).isNull();
113 bool QuantAttributes::checkFunDefAnnotation( Node ipl
) {
115 for( unsigned i
=0; i
<ipl
.getNumChildren(); i
++ ){
116 if( ipl
[i
].getKind()==INST_ATTRIBUTE
){
117 if( ipl
[i
][0].getAttribute(FunDefAttribute()) ){
126 Node
QuantAttributes::getFunDefHead( Node q
) {
127 //&& q[1].getKind()==EQUAL && q[1][0].getKind()==APPLY_UF &&
128 if( q
.getKind()==FORALL
&& q
.getNumChildren()==3 ){
130 for (unsigned i
= 0; i
< ipl
.getNumChildren(); i
++)
132 if (ipl
[i
].getKind() == INST_ATTRIBUTE
133 && ipl
[i
][0].getAttribute(FunDefAttribute()))
141 Node
QuantAttributes::getFunDefBody( Node q
) {
142 Node h
= getFunDefHead( q
);
144 if( q
[1].getKind()==EQUAL
){
147 }else if( q
[1][1]==h
){
150 else if (q
[1][0].getType().isReal())
152 // solve for h in the equality
153 std::map
<Node
, Node
> msum
;
154 if (ArithMSum::getMonomialSum(q
[1], msum
))
157 int res
= ArithMSum::isolate(h
, msum
, veq
, EQUAL
);
160 Assert(veq
.getKind() == EQUAL
);
161 return res
== 1 ? veq
[0] : veq
[1];
166 Node atom
= q
[1].getKind()==NOT
? q
[1][0] : q
[1];
167 bool pol
= q
[1].getKind()!=NOT
;
169 return NodeManager::currentNM()->mkConst( pol
);
176 bool QuantAttributes::checkSygusConjecture( Node q
) {
177 return ( q
.getKind()==FORALL
&& q
.getNumChildren()==3 ) ? checkSygusConjectureAnnotation( q
[2] ) : false;
180 bool QuantAttributes::checkSygusConjectureAnnotation( Node ipl
){
182 for( unsigned i
=0; i
<ipl
.getNumChildren(); i
++ ){
183 if( ipl
[i
].getKind()==INST_ATTRIBUTE
){
184 Node avar
= ipl
[i
][0];
185 if( avar
.getAttribute(SygusAttribute()) ){
194 bool QuantAttributes::checkQuantElimAnnotation( Node ipl
) {
196 for( unsigned i
=0; i
<ipl
.getNumChildren(); i
++ ){
197 if( ipl
[i
].getKind()==INST_ATTRIBUTE
){
198 Node avar
= ipl
[i
][0];
199 if( avar
.getAttribute(QuantElimAttribute()) ){
208 void QuantAttributes::computeAttributes( Node q
) {
209 computeQuantAttributes( q
, d_qattr
[q
] );
210 if( !d_qattr
[q
].d_rr
.isNull() ){
211 if( d_quantEngine
->getRewriteEngine()==NULL
){
212 Trace("quant-warn") << "WARNING : rewrite engine is null, and we have : " << q
<< std::endl
;
214 //set rewrite engine as owner
215 d_quantEngine
->setOwner( q
, d_quantEngine
->getRewriteEngine(), 2 );
217 if( d_qattr
[q
].isFunDef() ){
218 Node f
= d_qattr
[q
].d_fundef_f
;
219 if( d_fun_defs
.find( f
)!=d_fun_defs
.end() ){
220 Message() << "Cannot define function " << f
<< " more than once." << std::endl
;
223 d_fun_defs
[f
] = true;
224 d_quantEngine
->setOwner( q
, d_quantEngine
->getFunDefEngine(), 2 );
226 if( d_qattr
[q
].d_sygus
){
227 if( d_quantEngine
->getCegInstantiation()==NULL
){
228 Trace("quant-warn") << "WARNING : ceg instantiation is null, and we have : " << q
<< std::endl
;
230 d_quantEngine
->setOwner( q
, d_quantEngine
->getCegInstantiation(), 2 );
232 if( d_qattr
[q
].d_synthesis
){
233 if( d_quantEngine
->getCegInstantiation()==NULL
){
234 Trace("quant-warn") << "WARNING : ceg instantiation is null, and we have : " << q
<< std::endl
;
236 d_quantEngine
->setOwner( q
, d_quantEngine
->getCegInstantiation(), 2 );
240 void QuantAttributes::computeQuantAttributes( Node q
, QAttributes
& qa
){
241 Trace("quant-attr-debug") << "Compute attributes for " << q
<< std::endl
;
242 if( q
.getNumChildren()==3 ){
244 for( unsigned i
=0; i
<q
[2].getNumChildren(); i
++ ){
245 Trace("quant-attr-debug") << "Check : " << q
[2][i
] << " " << q
[2][i
].getKind() << std::endl
;
246 if( q
[2][i
].getKind()==INST_PATTERN
|| q
[2][i
].getKind()==INST_NO_PATTERN
){
247 qa
.d_hasPattern
= true;
248 }else if( q
[2][i
].getKind()==INST_ATTRIBUTE
){
249 Node avar
= q
[2][i
][0];
250 if( avar
.getAttribute(AxiomAttribute()) ){
251 Trace("quant-attr") << "Attribute : axiom : " << q
<< std::endl
;
254 if( avar
.getAttribute(ConjectureAttribute()) ){
255 Trace("quant-attr") << "Attribute : conjecture : " << q
<< std::endl
;
256 qa
.d_conjecture
= true;
258 if( avar
.getAttribute(FunDefAttribute()) ){
259 Trace("quant-attr") << "Attribute : function definition : " << q
<< std::endl
;
260 //get operator directly from pattern
261 qa
.d_fundef_f
= q
[2][i
][0].getOperator();
263 if( avar
.getAttribute(SygusAttribute()) ){
264 //not necessarily nested existential
265 //Assert( q[1].getKind()==NOT );
266 //Assert( q[1][0].getKind()==FORALL );
267 Trace("quant-attr") << "Attribute : sygus : " << q
<< std::endl
;
270 if( avar
.getAttribute(SynthesisAttribute()) ){
271 Trace("quant-attr") << "Attribute : synthesis : " << q
<< std::endl
;
272 qa
.d_synthesis
= true;
274 if( avar
.hasAttribute(QuantInstLevelAttribute()) ){
275 qa
.d_qinstLevel
= avar
.getAttribute(QuantInstLevelAttribute());
276 Trace("quant-attr") << "Attribute : quant inst level " << qa
.d_qinstLevel
<< " : " << q
<< std::endl
;
278 if( avar
.hasAttribute(RrPriorityAttribute()) ){
279 qa
.d_rr_priority
= avar
.getAttribute(RrPriorityAttribute());
280 Trace("quant-attr") << "Attribute : rr priority " << qa
.d_rr_priority
<< " : " << q
<< std::endl
;
282 if( avar
.getAttribute(QuantElimAttribute()) ){
283 Trace("quant-attr") << "Attribute : quantifier elimination : " << q
<< std::endl
;
284 qa
.d_quant_elim
= true;
285 //don't set owner, should happen naturally
287 if( avar
.getAttribute(QuantElimPartialAttribute()) ){
288 Trace("quant-attr") << "Attribute : quantifier elimination partial : " << q
<< std::endl
;
289 qa
.d_quant_elim
= true;
290 qa
.d_quant_elim_partial
= true;
291 //don't set owner, should happen naturally
293 if( avar
.hasAttribute(QuantIdNumAttribute()) ){
295 Trace("quant-attr") << "Attribute : id number " << qa
.d_qid_num
.getAttribute(QuantIdNumAttribute()) << " : " << q
<< std::endl
;
297 if( avar
.getKind()==REWRITE_RULE
){
298 Trace("quant-attr") << "Attribute : rewrite rule : " << q
<< std::endl
;
307 bool QuantAttributes::isConjecture( Node q
) {
308 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
309 if( it
==d_qattr
.end() ){
312 return it
->second
.d_conjecture
;
316 bool QuantAttributes::isAxiom( Node q
) {
317 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
318 if( it
==d_qattr
.end() ){
321 return it
->second
.d_axiom
;
325 bool QuantAttributes::isFunDef( Node q
) {
326 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
327 if( it
==d_qattr
.end() ){
330 return it
->second
.isFunDef();
334 bool QuantAttributes::isSygus( Node q
) {
335 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
336 if( it
==d_qattr
.end() ){
339 return it
->second
.d_sygus
;
343 bool QuantAttributes::isSynthesis( Node q
) {
344 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
345 if( it
==d_qattr
.end() ){
348 return it
->second
.d_synthesis
;
352 int QuantAttributes::getQuantInstLevel( Node q
) {
353 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
354 if( it
==d_qattr
.end() ){
357 return it
->second
.d_qinstLevel
;
361 int QuantAttributes::getRewriteRulePriority( Node q
) {
362 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
363 if( it
==d_qattr
.end() ){
366 return it
->second
.d_rr_priority
;
370 bool QuantAttributes::isQuantElim( Node q
) {
371 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
372 if( it
==d_qattr
.end() ){
375 return it
->second
.d_quant_elim
;
379 bool QuantAttributes::isQuantElimPartial( Node q
) {
380 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
381 if( it
==d_qattr
.end() ){
384 return it
->second
.d_quant_elim_partial
;
388 int QuantAttributes::getQuantIdNum( Node q
) {
389 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
390 if( it
!=d_qattr
.end() ){
391 if( !it
->second
.d_qid_num
.isNull() ){
392 return it
->second
.d_qid_num
.getAttribute(QuantIdNumAttribute());
398 Node
QuantAttributes::getQuantIdNumNode( Node q
) {
399 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
400 if( it
==d_qattr
.end() ){
403 return it
->second
.d_qid_num
;
407 void QuantAttributes::setInstantiationLevelAttr(Node n
, Node qn
, uint64_t level
)
409 Trace("inst-level-debug2") << "IL : " << n
<< " " << qn
<< " " << level
411 // if not from the vector of terms we instantiatied
412 if (qn
.getKind() != BOUND_VARIABLE
&& n
!= qn
)
414 // if this is a new term, without an instantiation level
415 if (!n
.hasAttribute(InstLevelAttribute()))
417 InstLevelAttribute ila
;
418 n
.setAttribute(ila
, level
);
419 Trace("inst-level-debug") << "Set instantiation level " << n
<< " to "
420 << level
<< std::endl
;
421 Assert(n
.getNumChildren() == qn
.getNumChildren());
422 for (unsigned i
= 0; i
< n
.getNumChildren(); i
++)
424 setInstantiationLevelAttr(n
[i
], qn
[i
], level
);
430 void QuantAttributes::setInstantiationLevelAttr(Node n
, uint64_t level
)
432 if (!n
.hasAttribute(InstLevelAttribute()))
434 InstLevelAttribute ila
;
435 n
.setAttribute(ila
, level
);
436 Trace("inst-level-debug") << "Set instantiation level " << n
<< " to "
437 << level
<< std::endl
;
438 for (unsigned i
= 0; i
< n
.getNumChildren(); i
++)
440 setInstantiationLevelAttr(n
[i
], level
);
445 } /* CVC4::theory::quantifiers namespace */
446 } /* CVC4::theory namespace */
447 } /* CVC4 namespace */