f27e14121b6e383636830cb6cd12050801c4476b
1 /******************************************************************************
2 * Top contributors (to current version):
5 * This file is part of the cvc5 project.
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 * ****************************************************************************
13 * Implementation of entailment check class.
16 #include "theory/quantifiers/entailment_check.h"
18 #include "theory/quantifiers/quantifiers_state.h"
19 #include "theory/quantifiers/term_database.h"
21 using namespace cvc5::kind
;
22 using namespace cvc5::context
;
26 namespace quantifiers
{
28 EntailmentCheck::EntailmentCheck(Env
& env
, QuantifiersState
& qs
, TermDb
& tdb
)
29 : EnvObj(env
), d_qstate(qs
), d_tdb(tdb
)
31 d_true
= NodeManager::currentNM()->mkConst(true);
32 d_false
= NodeManager::currentNM()->mkConst(false);
35 EntailmentCheck::~EntailmentCheck() {}
36 Node
EntailmentCheck::evaluateTerm2(TNode n
,
37 std::map
<TNode
, Node
>& visited
,
38 std::vector
<Node
>& exp
,
39 bool useEntailmentTests
,
43 std::map
<TNode
, Node
>::iterator itv
= visited
.find(n
);
44 if (itv
!= visited
.end())
48 size_t prevSize
= exp
.size();
49 Trace("term-db-eval") << "evaluate term : " << n
<< std::endl
;
51 if (n
.getKind() == FORALL
|| n
.getKind() == BOUND_VARIABLE
)
55 else if (d_qstate
.hasTerm(n
))
57 Trace("term-db-eval") << "...exists in ee, return rep" << std::endl
;
58 ret
= d_qstate
.getRepresentative(n
);
63 exp
.push_back(n
.eqNode(ret
));
68 else if (n
.hasOperator())
70 std::vector
<TNode
> args
;
73 std::vector
<Node
> tempExp
;
74 for (unsigned i
= 0, nchild
= n
.getNumChildren(); i
< nchild
; i
++)
76 TNode c
= evaluateTerm2(
77 n
[i
], visited
, tempExp
, useEntailmentTests
, computeExp
, reqHasTerm
);
84 else if (c
== d_true
|| c
== d_false
)
87 if ((k
== AND
&& c
== d_false
) || (k
== OR
&& c
== d_true
))
94 else if (k
== ITE
&& i
== 0)
96 ret
= evaluateTerm2(n
[c
== d_true
? 1 : 2],
109 exp
.insert(exp
.end(), tempExp
.begin(), tempExp
.end());
111 Trace("term-db-eval") << " child " << i
<< " : " << c
<< std::endl
;
116 // if we short circuited
120 exp
.insert(exp
.end(), tempExp
.begin(), tempExp
.end());
125 // get the (indexed) operator of n, if it exists
126 TNode f
= d_tdb
.getMatchOperator(n
);
127 // if it is an indexed term, return the congruent term
130 // if f is congruent to a term indexed by this class
131 TNode nn
= d_tdb
.getCongruentTerm(f
, args
);
132 Trace("term-db-eval") << " got congruent term " << nn
133 << " from DB for " << n
<< std::endl
;
138 Assert(nn
.getNumChildren() == n
.getNumChildren());
139 for (size_t i
= 0, nchild
= nn
.getNumChildren(); i
< nchild
; i
++)
143 exp
.push_back(nn
[i
].eqNode(n
[i
]));
147 ret
= d_qstate
.getRepresentative(nn
);
148 Trace("term-db-eval") << "return rep" << std::endl
;
151 Assert(!ret
.isNull());
156 exp
.push_back(nn
.eqNode(ret
));
163 Trace("term-db-eval") << "return rewrite" << std::endl
;
164 // a theory symbol or a new UF term
165 if (n
.getMetaKind() == metakind::PARAMETERIZED
)
167 args
.insert(args
.begin(), n
.getOperator());
169 ret
= NodeManager::currentNM()->mkNode(n
.getKind(), args
);
171 if (ret
.getKind() == EQUAL
)
173 if (d_qstate
.areDisequal(ret
[0], ret
[1]))
178 if (useEntailmentTests
)
180 if (ret
.getKind() == EQUAL
|| ret
.getKind() == GEQ
)
182 Valuation
& val
= d_qstate
.getValuation();
183 for (unsigned j
= 0; j
< 2; j
++)
185 std::pair
<bool, Node
> et
= val
.entailmentCheck(
186 options::TheoryOfMode::THEORY_OF_TYPE_BASED
,
187 j
== 0 ? ret
: ret
.negate());
190 ret
= j
== 0 ? d_true
: d_false
;
193 exp
.push_back(et
.second
);
203 // must have the term
204 if (reqHasTerm
&& !ret
.isNull())
206 Kind k
= ret
.getKind();
207 if (k
!= OR
&& k
!= AND
&& k
!= EQUAL
&& k
!= ITE
&& k
!= NOT
210 if (!d_qstate
.hasTerm(ret
))
216 Trace("term-db-eval") << "evaluated term : " << n
<< ", got : " << ret
217 << ", reqHasTerm = " << reqHasTerm
<< std::endl
;
218 // clear the explanation if failed
219 if (computeExp
&& ret
.isNull())
221 exp
.resize(prevSize
);
227 TNode
EntailmentCheck::getEntailedTerm2(TNode n
,
228 std::map
<TNode
, TNode
>& subs
,
232 Trace("term-db-entail") << "get entailed term : " << n
<< std::endl
;
233 if (d_qstate
.hasTerm(n
))
235 Trace("term-db-entail") << "...exists in ee, return rep " << std::endl
;
238 else if (n
.getKind() == BOUND_VARIABLE
)
242 std::map
<TNode
, TNode
>::iterator it
= subs
.find(n
);
243 if (it
!= subs
.end())
245 Trace("term-db-entail")
246 << "...substitution is : " << it
->second
<< std::endl
;
249 Assert(d_qstate
.hasTerm(it
->second
));
250 Assert(d_qstate
.getRepresentative(it
->second
) == it
->second
);
253 return getEntailedTerm2(it
->second
, subs
, subsRep
, hasSubs
);
257 else if (n
.getKind() == ITE
)
259 for (uint32_t i
= 0; i
< 2; i
++)
261 if (isEntailed2(n
[0], subs
, subsRep
, hasSubs
, i
== 0))
263 return getEntailedTerm2(n
[i
== 0 ? 1 : 2], subs
, subsRep
, hasSubs
);
271 TNode f
= d_tdb
.getMatchOperator(n
);
274 std::vector
<TNode
> args
;
275 for (size_t i
= 0, nchild
= n
.getNumChildren(); i
< nchild
; i
++)
277 TNode c
= getEntailedTerm2(n
[i
], subs
, subsRep
, hasSubs
);
280 return TNode::null();
282 c
= d_qstate
.getRepresentative(c
);
283 Trace("term-db-entail") << " child " << i
<< " : " << c
<< std::endl
;
286 TNode nn
= d_tdb
.getCongruentTerm(f
, args
);
287 Trace("term-db-entail")
288 << " got congruent term " << nn
<< " for " << n
<< std::endl
;
293 return TNode::null();
296 Node
EntailmentCheck::evaluateTerm(TNode n
,
297 bool useEntailmentTests
,
300 std::map
<TNode
, Node
> visited
;
301 std::vector
<Node
> exp
;
302 return evaluateTerm2(n
, visited
, exp
, useEntailmentTests
, false, reqHasTerm
);
305 Node
EntailmentCheck::evaluateTerm(TNode n
,
306 std::vector
<Node
>& exp
,
307 bool useEntailmentTests
,
310 std::map
<TNode
, Node
> visited
;
311 return evaluateTerm2(n
, visited
, exp
, useEntailmentTests
, true, reqHasTerm
);
314 TNode
EntailmentCheck::getEntailedTerm(TNode n
,
315 std::map
<TNode
, TNode
>& subs
,
318 return getEntailedTerm2(n
, subs
, subsRep
, true);
321 TNode
EntailmentCheck::getEntailedTerm(TNode n
)
323 std::map
<TNode
, TNode
> subs
;
324 return getEntailedTerm2(n
, subs
, false, false);
327 bool EntailmentCheck::isEntailed2(
328 TNode n
, std::map
<TNode
, TNode
>& subs
, bool subsRep
, bool hasSubs
, bool pol
)
330 Trace("term-db-entail") << "Check entailed : " << n
<< ", pol = " << pol
332 Assert(n
.getType().isBoolean());
333 if (n
.getKind() == EQUAL
&& !n
[0].getType().isBoolean())
335 TNode n1
= getEntailedTerm2(n
[0], subs
, subsRep
, hasSubs
);
338 TNode n2
= getEntailedTerm2(n
[1], subs
, subsRep
, hasSubs
);
347 Assert(d_qstate
.hasTerm(n1
));
348 Assert(d_qstate
.hasTerm(n2
));
351 return d_qstate
.areEqual(n1
, n2
);
355 return d_qstate
.areDisequal(n1
, n2
);
361 else if (n
.getKind() == NOT
)
363 return isEntailed2(n
[0], subs
, subsRep
, hasSubs
, !pol
);
365 else if (n
.getKind() == OR
|| n
.getKind() == AND
)
367 bool simPol
= (pol
&& n
.getKind() == OR
) || (!pol
&& n
.getKind() == AND
);
368 for (size_t i
= 0, nchild
= n
.getNumChildren(); i
< nchild
; i
++)
370 if (isEntailed2(n
[i
], subs
, subsRep
, hasSubs
, pol
))
386 // Boolean equality here
388 else if (n
.getKind() == EQUAL
|| n
.getKind() == ITE
)
390 for (size_t i
= 0; i
< 2; i
++)
392 if (isEntailed2(n
[0], subs
, subsRep
, hasSubs
, i
== 0))
394 size_t ch
= (n
.getKind() == EQUAL
|| i
== 0) ? 1 : 2;
395 bool reqPol
= (n
.getKind() == ITE
|| i
== 0) ? pol
: !pol
;
396 return isEntailed2(n
[ch
], subs
, subsRep
, hasSubs
, reqPol
);
400 else if (n
.getKind() == APPLY_UF
)
402 TNode n1
= getEntailedTerm2(n
, subs
, subsRep
, hasSubs
);
405 Assert(d_qstate
.hasTerm(n1
));
410 else if (n1
== d_false
)
416 return d_qstate
.getRepresentative(n1
) == (pol
? d_true
: d_false
);
420 else if (n
.getKind() == FORALL
&& !pol
)
422 return isEntailed2(n
[1], subs
, subsRep
, hasSubs
, pol
);
427 bool EntailmentCheck::isEntailed(TNode n
, bool pol
)
429 std::map
<TNode
, TNode
> subs
;
430 return isEntailed2(n
, subs
, false, false, pol
);
433 bool EntailmentCheck::isEntailed(TNode n
,
434 std::map
<TNode
, TNode
>& subs
,
438 return isEntailed2(n
, subs
, subsRep
, true, pol
);
441 } // namespace quantifiers
442 } // namespace theory