1 /********************* */
2 /*! \file inst_strategy_enumerative.cpp
4 ** Top contributors (to current version):
5 ** Andrew Reynolds, Morgan Deters
6 ** This file is part of the CVC4 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.\endverbatim
12 ** \brief Implementation of an enumerative instantiation strategy.
15 #include "theory/quantifiers/inst_strategy_enumerative.h"
17 #include "options/quantifiers_options.h"
18 #include "theory/quantifiers/instantiate.h"
19 #include "theory/quantifiers/relevant_domain.h"
20 #include "theory/quantifiers/term_database.h"
21 #include "theory/quantifiers/term_tuple_enumerator.h"
22 #include "theory/quantifiers/term_util.h"
23 #include "theory/quantifiers_engine.h"
25 using namespace CVC4::kind
;
26 using namespace CVC4::context
;
30 namespace quantifiers
{
32 InstStrategyEnum::InstStrategyEnum(QuantifiersEngine
* qe
,
34 QuantifiersInferenceManager
& qim
,
35 QuantifiersRegistry
& qr
,
38 : QuantifiersModule(qs
, qim
, qr
, tr
, qe
), d_rd(rd
), d_fullSaturateLimit(-1)
41 void InstStrategyEnum::presolve()
43 d_fullSaturateLimit
= options::fullSaturateLimit();
45 bool InstStrategyEnum::needsCheck(Theory::Effort e
)
47 if (d_fullSaturateLimit
== 0)
51 if (options::fullSaturateInterleave())
53 // if interleaved, we run at the same time as E-matching
54 if (d_qstate
.getInstWhenNeedsCheck(e
))
59 if (options::fullSaturateQuant())
61 if (e
>= Theory::EFFORT_LAST_CALL
)
69 void InstStrategyEnum::reset_round(Theory::Effort e
) {}
70 void InstStrategyEnum::check(Theory::Effort e
, QEffort quant_e
)
73 bool fullEffort
= false;
74 if (d_fullSaturateLimit
!= 0)
76 if (options::fullSaturateInterleave())
78 // we only add when interleaved with other strategies
79 doCheck
= quant_e
== QEFFORT_STANDARD
&& d_qim
.hasPendingLemma();
81 if (options::fullSaturateQuant() && !doCheck
)
83 if (!d_qstate
.getValuation().needCheck())
85 doCheck
= quant_e
== QEFFORT_LAST_CALL
;
94 Assert(!d_qstate
.isInConflict());
96 if (Trace
.isOn("fs-engine"))
98 clSet
= double(clock()) / double(CLOCKS_PER_SEC
);
99 Trace("fs-engine") << "---Full Saturation Round, effort = " << e
<< "---"
102 unsigned rstart
= options::fullSaturateQuantRd() ? 0 : 1;
103 unsigned rend
= fullEffort
? 1 : rstart
;
104 unsigned addedLemmas
= 0;
105 // First try in relevant domain of all quantified formulas, if no
106 // instantiations exist, try arbitrary ground terms.
107 // Notice that this stratification of effort levels makes it so that some
108 // quantified formulas may not be instantiated (if they have no instances
109 // at effort level r=0 but another quantified formula does). We prefer
110 // this stratification since effort level r=1 may be highly expensive in the
111 // case where we have a quantified formula with many entailed instances.
112 FirstOrderModel
* fm
= d_quantEngine
->getModel();
113 unsigned nquant
= fm
->getNumAssertedQuantifiers();
114 std::map
<Node
, bool> alreadyProc
;
115 for (unsigned r
= rstart
; r
<= rend
; r
++)
121 Trace("inst-alg") << "-> Relevant domain instantiate..." << std::endl
;
122 Trace("inst-alg-debug") << "Compute relevant domain..." << std::endl
;
124 Trace("inst-alg-debug") << "...finished" << std::endl
;
128 Trace("inst-alg") << "-> Ground term instantiate..." << std::endl
;
130 for (unsigned i
= 0; i
< nquant
; i
++)
132 Node q
= fm
->getAssertedQuantifier(i
, true);
133 bool doProcess
= d_qreg
.hasOwnership(q
, this)
134 && fm
->isQuantifierActive(q
)
135 && alreadyProc
.find(q
) == alreadyProc
.end();
138 if (process(q
, fullEffort
, r
== 0))
140 // don't need to mark this if we are not stratifying
141 if (!options::fullSaturateStratify())
143 alreadyProc
[q
] = true;
148 if (d_qstate
.isInConflict())
154 if (d_qstate
.isInConflict()
155 || (addedLemmas
> 0 && options::fullSaturateStratify()))
157 // we break if we are in conflict, or if we added any lemma at this
158 // effort level and we stratify effort levels.
163 if (Trace
.isOn("fs-engine"))
165 Trace("fs-engine") << "Added lemmas = " << addedLemmas
<< std::endl
;
166 double clSet2
= double(clock()) / double(CLOCKS_PER_SEC
);
167 Trace("fs-engine") << "Finished full saturation engine, time = "
168 << (clSet2
- clSet
) << std::endl
;
170 if (d_fullSaturateLimit
> 0)
172 d_fullSaturateLimit
--;
176 bool InstStrategyEnum::process(Node quantifier
, bool fullEffort
, bool isRd
)
178 // ignore if constant true (rare case of non-standard quantifier whose body
179 // is rewritten to true)
180 if (quantifier
[1].isConst() && quantifier
[1].getConst
<bool>())
185 TermTupleEnumeratorContext ttec
;
186 ttec
.d_quantEngine
= d_quantEngine
;
188 ttec
.d_fullEffort
= fullEffort
;
189 ttec
.d_increaseSum
= options::fullSaturateSum();
191 std::unique_ptr
<TermTupleEnumeratorInterface
> enumerator(
192 mkTermTupleEnumerator(quantifier
, &ttec
));
193 std::vector
<Node
> terms
;
194 std::vector
<bool> failMask
;
195 Instantiate
* ie
= d_qim
.getInstantiate();
196 for (enumerator
->init(); enumerator
->hasNext();)
198 if (d_qstate
.isInConflict())
200 // could be conflicting for an internal reason
203 enumerator
->next(terms
);
206 /* if (ie->addInstantiation(quantifier, terms)) */
207 if (ie
->addInstantiationExpFail(
208 quantifier
, terms
, failMask
, InferenceId::QUANTIFIERS_INST_ENUM
))
210 Trace("inst-alg-rd") << "Success!" << std::endl
;
215 enumerator
->failureReason(failMask
);
219 // TODO : term enumerator instantiation?
222 } // namespace quantifiers
223 } // namespace theory