1 /********************* */
2 /*! \file quantifiers_attributes.cpp
4 ** Top contributors (to current version):
5 ** Andrew Reynolds, Paul Meng, Morgan Deters
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2020 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/sygus/synth_engine.h"
20 #include "theory/quantifiers/term_util.h"
21 #include "theory/quantifiers_engine.h"
24 using namespace CVC4::kind
;
25 using namespace CVC4::context
;
29 namespace quantifiers
{
31 bool QAttributes::isStandard() const
33 return !d_sygus
&& !d_quant_elim
&& !isFunDef() && d_name
.isNull();
36 QuantAttributes::QuantAttributes( QuantifiersEngine
* qe
) :
41 void QuantAttributes::setUserAttribute( const std::string
& attr
, Node n
, std::vector
< Node
>& node_values
, std::string str_value
){
42 Trace("quant-attr-debug") << "Set " << attr
<< " " << n
<< std::endl
;
43 if (attr
== "fun-def")
45 Trace("quant-attr-debug") << "Set function definition " << n
<< std::endl
;
47 n
.setAttribute( fda
, true );
48 }else if( attr
=="sygus" ){
49 Trace("quant-attr-debug") << "Set sygus " << n
<< std::endl
;
51 n
.setAttribute( ca
, true );
53 else if (attr
== "qid")
55 // using z3 syntax "qid"
56 Trace("quant-attr-debug") << "Set quant-name " << n
<< std::endl
;
57 QuantNameAttribute qna
;
58 n
.setAttribute(qna
, true);
59 } else if (attr
== "sygus-synth-grammar") {
60 Assert(node_values
.size() == 1);
61 Trace("quant-attr-debug") << "Set sygus synth grammar " << n
<< " to "
62 << node_values
[0] << std::endl
;
63 SygusSynthGrammarAttribute ssg
;
64 n
.setAttribute(ssg
, node_values
[0]);
65 }else if( attr
=="sygus-synth-fun-var-list" ){
66 Assert(node_values
.size() == 1);
67 Trace("quant-attr-debug") << "Set sygus synth fun var list to " << n
<< " to " << node_values
[0] << std::endl
;
68 SygusSynthFunVarListAttribute ssfvla
;
69 n
.setAttribute( ssfvla
, node_values
[0] );
70 }else if( attr
=="quant-inst-max-level" ){
71 Assert(node_values
.size() == 1);
72 uint64_t lvl
= node_values
[0].getConst
<Rational
>().getNumerator().getLong();
73 Trace("quant-attr-debug") << "Set instantiation level " << n
<< " to " << lvl
<< std::endl
;
74 QuantInstLevelAttribute qila
;
75 n
.setAttribute( qila
, lvl
);
76 }else if( attr
=="quant-elim" ){
77 Trace("quant-attr-debug") << "Set quantifier elimination " << n
<< std::endl
;
78 QuantElimAttribute qea
;
79 n
.setAttribute( qea
, true );
80 }else if( attr
=="quant-elim-partial" ){
81 Trace("quant-attr-debug") << "Set partial quantifier elimination " << n
<< std::endl
;
82 QuantElimPartialAttribute qepa
;
83 n
.setAttribute( qepa
, true );
87 bool QuantAttributes::checkFunDef( Node q
) {
88 return !getFunDefHead( q
).isNull();
91 bool QuantAttributes::checkFunDefAnnotation( Node ipl
) {
93 for( unsigned i
=0; i
<ipl
.getNumChildren(); i
++ ){
94 if( ipl
[i
].getKind()==INST_ATTRIBUTE
){
95 if( ipl
[i
][0].getAttribute(FunDefAttribute()) ){
104 Node
QuantAttributes::getFunDefHead( Node q
) {
105 //&& q[1].getKind()==EQUAL && q[1][0].getKind()==APPLY_UF &&
106 if( q
.getKind()==FORALL
&& q
.getNumChildren()==3 ){
108 for (unsigned i
= 0; i
< ipl
.getNumChildren(); i
++)
110 if (ipl
[i
].getKind() == INST_ATTRIBUTE
111 && ipl
[i
][0].getAttribute(FunDefAttribute()))
119 Node
QuantAttributes::getFunDefBody( Node q
) {
120 Node h
= getFunDefHead( q
);
122 if( q
[1].getKind()==EQUAL
){
125 }else if( q
[1][1]==h
){
128 else if (q
[1][0].getType().isReal())
130 // solve for h in the equality
131 std::map
<Node
, Node
> msum
;
132 if (ArithMSum::getMonomialSumLit(q
[1], msum
))
135 int res
= ArithMSum::isolate(h
, msum
, veq
, EQUAL
);
138 Assert(veq
.getKind() == EQUAL
);
139 return res
== 1 ? veq
[1] : veq
[0];
144 Node atom
= q
[1].getKind()==NOT
? q
[1][0] : q
[1];
145 bool pol
= q
[1].getKind()!=NOT
;
147 return NodeManager::currentNM()->mkConst( pol
);
154 bool QuantAttributes::checkSygusConjecture( Node q
) {
155 return ( q
.getKind()==FORALL
&& q
.getNumChildren()==3 ) ? checkSygusConjectureAnnotation( q
[2] ) : false;
158 bool QuantAttributes::checkSygusConjectureAnnotation( Node ipl
){
160 for( unsigned i
=0; i
<ipl
.getNumChildren(); i
++ ){
161 if( ipl
[i
].getKind()==INST_ATTRIBUTE
){
162 Node avar
= ipl
[i
][0];
163 if( avar
.getAttribute(SygusAttribute()) ){
172 bool QuantAttributes::checkQuantElimAnnotation( Node ipl
) {
174 for( unsigned i
=0; i
<ipl
.getNumChildren(); i
++ ){
175 if( ipl
[i
].getKind()==INST_ATTRIBUTE
){
176 Node avar
= ipl
[i
][0];
177 if( avar
.getAttribute(QuantElimAttribute()) ){
186 void QuantAttributes::computeAttributes( Node q
) {
187 computeQuantAttributes( q
, d_qattr
[q
] );
188 QAttributes
& qa
= d_qattr
[q
];
191 Node f
= qa
.d_fundef_f
;
192 if( d_fun_defs
.find( f
)!=d_fun_defs
.end() ){
193 Message() << "Cannot define function " << f
<< " more than once." << std::endl
;
196 d_fun_defs
[f
] = true;
198 // set ownership of quantified formula q based on the computed attributes
199 d_quantEngine
->setOwner(q
, qa
);
202 void QuantAttributes::computeQuantAttributes( Node q
, QAttributes
& qa
){
203 Trace("quant-attr-debug") << "Compute attributes for " << q
<< std::endl
;
204 if( q
.getNumChildren()==3 ){
206 for( unsigned i
=0; i
<q
[2].getNumChildren(); i
++ ){
207 Trace("quant-attr-debug") << "Check : " << q
[2][i
] << " " << q
[2][i
].getKind() << std::endl
;
208 if( q
[2][i
].getKind()==INST_PATTERN
|| q
[2][i
].getKind()==INST_NO_PATTERN
){
209 qa
.d_hasPattern
= true;
210 }else if( q
[2][i
].getKind()==INST_ATTRIBUTE
){
211 Node avar
= q
[2][i
][0];
212 if( avar
.getAttribute(FunDefAttribute()) ){
213 Trace("quant-attr") << "Attribute : function definition : " << q
<< std::endl
;
214 //get operator directly from pattern
215 qa
.d_fundef_f
= q
[2][i
][0].getOperator();
217 if( avar
.getAttribute(SygusAttribute()) ){
218 //not necessarily nested existential
219 //Assert( q[1].getKind()==NOT );
220 //Assert( q[1][0].getKind()==FORALL );
221 Trace("quant-attr") << "Attribute : sygus : " << q
<< std::endl
;
224 if (avar
.hasAttribute(SygusSideConditionAttribute()))
226 qa
.d_sygusSideCondition
=
227 avar
.getAttribute(SygusSideConditionAttribute());
229 << "Attribute : sygus side condition : "
230 << qa
.d_sygusSideCondition
<< " : " << q
<< std::endl
;
232 if (avar
.getAttribute(QuantNameAttribute()))
234 Trace("quant-attr") << "Attribute : quantifier name : " << avar
235 << " for " << q
<< std::endl
;
238 if( avar
.hasAttribute(QuantInstLevelAttribute()) ){
239 qa
.d_qinstLevel
= avar
.getAttribute(QuantInstLevelAttribute());
240 Trace("quant-attr") << "Attribute : quant inst level " << qa
.d_qinstLevel
<< " : " << q
<< std::endl
;
242 if( avar
.getAttribute(QuantElimAttribute()) ){
243 Trace("quant-attr") << "Attribute : quantifier elimination : " << q
<< std::endl
;
244 qa
.d_quant_elim
= true;
245 //don't set owner, should happen naturally
247 if( avar
.getAttribute(QuantElimPartialAttribute()) ){
248 Trace("quant-attr") << "Attribute : quantifier elimination partial : " << q
<< std::endl
;
249 qa
.d_quant_elim
= true;
250 qa
.d_quant_elim_partial
= true;
251 //don't set owner, should happen naturally
253 if( avar
.hasAttribute(QuantIdNumAttribute()) ){
255 Trace("quant-attr") << "Attribute : id number " << qa
.d_qid_num
.getAttribute(QuantIdNumAttribute()) << " : " << q
<< std::endl
;
262 bool QuantAttributes::isFunDef( Node q
) {
263 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
264 if( it
==d_qattr
.end() ){
267 return it
->second
.isFunDef();
271 bool QuantAttributes::isSygus( Node q
) {
272 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
273 if( it
==d_qattr
.end() ){
276 return it
->second
.d_sygus
;
280 int QuantAttributes::getQuantInstLevel( Node q
) {
281 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
282 if( it
==d_qattr
.end() ){
285 return it
->second
.d_qinstLevel
;
289 bool QuantAttributes::isQuantElim( Node q
) {
290 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
291 if( it
==d_qattr
.end() ){
294 return it
->second
.d_quant_elim
;
298 bool QuantAttributes::isQuantElimPartial( Node q
) {
299 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
300 if( it
==d_qattr
.end() ){
303 return it
->second
.d_quant_elim_partial
;
307 Node
QuantAttributes::getQuantName(Node q
) const
309 std::map
<Node
, QAttributes
>::const_iterator it
= d_qattr
.find(q
);
310 if (it
!= d_qattr
.end())
312 return it
->second
.d_name
;
317 int QuantAttributes::getQuantIdNum( Node q
) {
318 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
319 if( it
!=d_qattr
.end() ){
320 if( !it
->second
.d_qid_num
.isNull() ){
321 return it
->second
.d_qid_num
.getAttribute(QuantIdNumAttribute());
327 Node
QuantAttributes::getQuantIdNumNode( Node q
) {
328 std::map
< Node
, QAttributes
>::iterator it
= d_qattr
.find( q
);
329 if( it
==d_qattr
.end() ){
332 return it
->second
.d_qid_num
;
336 void QuantAttributes::setInstantiationLevelAttr(Node n
, Node qn
, uint64_t level
)
338 Trace("inst-level-debug2") << "IL : " << n
<< " " << qn
<< " " << level
340 // if not from the vector of terms we instantiatied
341 if (qn
.getKind() != BOUND_VARIABLE
&& n
!= qn
)
343 // if this is a new term, without an instantiation level
344 if (!n
.hasAttribute(InstLevelAttribute()))
346 InstLevelAttribute ila
;
347 n
.setAttribute(ila
, level
);
348 Trace("inst-level-debug") << "Set instantiation level " << n
<< " to "
349 << level
<< std::endl
;
350 Assert(n
.getNumChildren() == qn
.getNumChildren());
351 for (unsigned i
= 0; i
< n
.getNumChildren(); i
++)
353 setInstantiationLevelAttr(n
[i
], qn
[i
], level
);
359 void QuantAttributes::setInstantiationLevelAttr(Node n
, uint64_t level
)
361 if (!n
.hasAttribute(InstLevelAttribute()))
363 InstLevelAttribute ila
;
364 n
.setAttribute(ila
, level
);
365 Trace("inst-level-debug") << "Set instantiation level " << n
<< " to "
366 << level
<< std::endl
;
367 for (unsigned i
= 0; i
< n
.getNumChildren(); i
++)
369 setInstantiationLevelAttr(n
[i
], level
);
374 } /* CVC4::theory::quantifiers namespace */
375 } /* CVC4::theory namespace */
376 } /* CVC4 namespace */