1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Mathias Preiner, Aina Niemetz |
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 |
|
* conjecture generator class |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/quantifiers/conjecture_generator.h" |
17 |
|
|
18 |
|
#include "expr/skolem_manager.h" |
19 |
|
#include "expr/term_canonize.h" |
20 |
|
#include "options/quantifiers_options.h" |
21 |
|
#include "theory/quantifiers/ematching/trigger_term_info.h" |
22 |
|
#include "theory/quantifiers/first_order_model.h" |
23 |
|
#include "theory/quantifiers/skolemize.h" |
24 |
|
#include "theory/quantifiers/term_database.h" |
25 |
|
#include "theory/quantifiers/term_enumeration.h" |
26 |
|
#include "theory/quantifiers/term_util.h" |
27 |
|
#include "theory/rewriter.h" |
28 |
|
#include "util/random.h" |
29 |
|
|
30 |
|
using namespace cvc5; |
31 |
|
using namespace cvc5::kind; |
32 |
|
using namespace cvc5::theory; |
33 |
|
using namespace cvc5::theory::quantifiers; |
34 |
|
using namespace std; |
35 |
|
|
36 |
|
namespace cvc5 { |
37 |
|
|
38 |
|
struct sortConjectureScore { |
39 |
|
std::vector< int > d_scores; |
40 |
|
bool operator() (unsigned i, unsigned j) { return d_scores[i]>d_scores[j]; } |
41 |
|
}; |
42 |
|
|
43 |
|
|
44 |
21898 |
void OpArgIndex::addTerm( std::vector< TNode >& terms, TNode n, unsigned index ){ |
45 |
21898 |
if( index==n.getNumChildren() ){ |
46 |
8942 |
Assert(n.hasOperator()); |
47 |
8942 |
if( std::find( d_ops.begin(), d_ops.end(), n.getOperator() )==d_ops.end() ){ |
48 |
8930 |
d_ops.push_back( n.getOperator() ); |
49 |
8930 |
d_op_terms.push_back( n ); |
50 |
|
} |
51 |
|
}else{ |
52 |
12956 |
d_child[terms[index]].addTerm( terms, n, index+1 ); |
53 |
|
} |
54 |
21898 |
} |
55 |
|
|
56 |
10202 |
Node OpArgIndex::getGroundTerm( ConjectureGenerator * s, std::vector< TNode >& args ) { |
57 |
10202 |
if( d_ops.empty() ){ |
58 |
8712 |
for( std::map< TNode, OpArgIndex >::iterator it = d_child.begin(); it != d_child.end(); ++it ){ |
59 |
6714 |
std::map< TNode, Node >::iterator itf = s->d_ground_eqc_map.find( it->first ); |
60 |
6714 |
if( itf!=s->d_ground_eqc_map.end() ){ |
61 |
5055 |
args.push_back( itf->second ); |
62 |
5200 |
Node n = it->second.getGroundTerm( s, args ); |
63 |
5055 |
args.pop_back(); |
64 |
5055 |
if( !n.isNull() ){ |
65 |
4910 |
return n; |
66 |
|
} |
67 |
|
} |
68 |
|
} |
69 |
1998 |
return Node::null(); |
70 |
|
} |
71 |
6588 |
std::vector<TNode> args2; |
72 |
3294 |
if (d_op_terms[0].getMetaKind() == kind::metakind::PARAMETERIZED) |
73 |
|
{ |
74 |
3294 |
args2.push_back( d_ops[0] ); |
75 |
|
} |
76 |
3294 |
args2.insert(args2.end(), args.begin(), args.end()); |
77 |
3294 |
return NodeManager::currentNM()->mkNode(d_op_terms[0].getKind(), args2); |
78 |
|
} |
79 |
|
|
80 |
14125 |
void OpArgIndex::getGroundTerms( ConjectureGenerator * s, std::vector< TNode >& terms ) { |
81 |
14125 |
terms.insert( terms.end(), d_op_terms.begin(), d_op_terms.end() ); |
82 |
24179 |
for( std::map< TNode, OpArgIndex >::iterator it = d_child.begin(); it != d_child.end(); ++it ){ |
83 |
10054 |
if( s->isGroundEqc( it->first ) ){ |
84 |
9294 |
it->second.getGroundTerms( s, terms ); |
85 |
|
} |
86 |
|
} |
87 |
14125 |
} |
88 |
|
|
89 |
10 |
ConjectureGenerator::ConjectureGenerator(Env& env, |
90 |
|
QuantifiersState& qs, |
91 |
|
QuantifiersInferenceManager& qim, |
92 |
|
QuantifiersRegistry& qr, |
93 |
10 |
TermRegistry& tr) |
94 |
|
: QuantifiersModule(env, qs, qim, qr, tr), |
95 |
|
d_notify(*this), |
96 |
|
d_uequalityEngine( |
97 |
|
env, context(), d_notify, "ConjectureGenerator::ee", false), |
98 |
|
d_ee_conjectures(context()), |
99 |
|
d_conj_count(0), |
100 |
|
d_subs_confirmCount(0), |
101 |
|
d_subs_unkCount(0), |
102 |
|
d_fullEffortCount(0), |
103 |
10 |
d_hasAddedLemma(false) |
104 |
|
{ |
105 |
10 |
d_true = NodeManager::currentNM()->mkConst(true); |
106 |
10 |
d_false = NodeManager::currentNM()->mkConst(false); |
107 |
10 |
d_uequalityEngine.addFunctionKind( kind::APPLY_UF ); |
108 |
10 |
d_uequalityEngine.addFunctionKind( kind::APPLY_CONSTRUCTOR ); |
109 |
|
|
110 |
10 |
} |
111 |
|
|
112 |
30 |
ConjectureGenerator::~ConjectureGenerator() |
113 |
|
{ |
114 |
33 |
for (std::map<Node, EqcInfo*>::iterator i = d_eqc_info.begin(), |
115 |
10 |
iend = d_eqc_info.end(); |
116 |
33 |
i != iend; |
117 |
|
++i) |
118 |
|
{ |
119 |
23 |
EqcInfo* current = (*i).second; |
120 |
23 |
Assert(current != nullptr); |
121 |
23 |
delete current; |
122 |
|
} |
123 |
20 |
} |
124 |
|
|
125 |
1618 |
void ConjectureGenerator::eqNotifyNewClass( TNode t ){ |
126 |
1618 |
Trace("thm-ee-debug") << "UEE : new equivalence class " << t << std::endl; |
127 |
1618 |
d_upendingAdds.push_back( t ); |
128 |
1618 |
} |
129 |
|
|
130 |
196 |
void ConjectureGenerator::eqNotifyMerge(TNode t1, TNode t2) |
131 |
|
{ |
132 |
|
//get maintained representatives |
133 |
392 |
TNode rt1 = t1; |
134 |
392 |
TNode rt2 = t2; |
135 |
196 |
std::map< Node, EqcInfo* >::iterator it1 = d_eqc_info.find( t1 ); |
136 |
196 |
if( it1!=d_eqc_info.end() && !it1->second->d_rep.get().isNull() ){ |
137 |
24 |
rt1 = it1->second->d_rep.get(); |
138 |
|
} |
139 |
196 |
std::map< Node, EqcInfo* >::iterator it2 = d_eqc_info.find( t2 ); |
140 |
196 |
if( it2!=d_eqc_info.end() && !it2->second->d_rep.get().isNull() ){ |
141 |
|
rt2 = it2->second->d_rep.get(); |
142 |
|
} |
143 |
196 |
Trace("thm-ee-debug") << "UEE : equality holds : " << t1 << " == " << t2 << std::endl; |
144 |
196 |
Trace("thm-ee-debug") << " ureps : " << rt1 << " == " << rt2 << std::endl; |
145 |
196 |
Trace("thm-ee-debug") << " relevant : " << d_pattern_is_relevant[rt1] << " " << d_pattern_is_relevant[rt2] << std::endl; |
146 |
196 |
Trace("thm-ee-debug") << " normal : " << d_pattern_is_normal[rt1] << " " << d_pattern_is_normal[rt2] << std::endl; |
147 |
196 |
Trace("thm-ee-debug") << " size : " << d_pattern_fun_sum[rt1] << " " << d_pattern_fun_sum[rt2] << std::endl; |
148 |
|
|
149 |
196 |
if( isUniversalLessThan( rt2, rt1 ) ){ |
150 |
|
EqcInfo * ei; |
151 |
45 |
if( it1==d_eqc_info.end() ){ |
152 |
23 |
ei = getOrMakeEqcInfo( t1, true ); |
153 |
|
}else{ |
154 |
22 |
ei = it1->second; |
155 |
|
} |
156 |
45 |
ei->d_rep = t2; |
157 |
|
} |
158 |
196 |
} |
159 |
|
|
160 |
|
|
161 |
23 |
ConjectureGenerator::EqcInfo::EqcInfo( context::Context* c ) : d_rep( c, Node::null() ){ |
162 |
|
|
163 |
23 |
} |
164 |
|
|
165 |
7720 |
ConjectureGenerator::EqcInfo* ConjectureGenerator::getOrMakeEqcInfo( TNode n, bool doMake ) { |
166 |
|
//Assert( getUniversalRepresentative( n )==n ); |
167 |
7720 |
std::map< Node, EqcInfo* >::iterator eqc_i = d_eqc_info.find( n ); |
168 |
7720 |
if( eqc_i!=d_eqc_info.end() ){ |
169 |
369 |
return eqc_i->second; |
170 |
7351 |
}else if( doMake ){ |
171 |
23 |
EqcInfo* ei = new EqcInfo(context()); |
172 |
23 |
d_eqc_info[n] = ei; |
173 |
23 |
return ei; |
174 |
|
}else{ |
175 |
7328 |
return NULL; |
176 |
|
} |
177 |
|
} |
178 |
|
|
179 |
5018 |
void ConjectureGenerator::setUniversalRelevant( TNode n ) { |
180 |
|
//add pattern information |
181 |
5018 |
registerPattern( n, n.getType() ); |
182 |
5018 |
d_urelevant_terms[n] = true; |
183 |
8637 |
for( unsigned i=0; i<n.getNumChildren(); i++ ){ |
184 |
3619 |
setUniversalRelevant( n[i] ); |
185 |
|
} |
186 |
5018 |
} |
187 |
|
|
188 |
307 |
bool ConjectureGenerator::isUniversalLessThan( TNode rt1, TNode rt2 ) { |
189 |
|
//prefer the one that is (normal, smaller) lexographically |
190 |
307 |
Assert(d_pattern_is_relevant.find(rt1) != d_pattern_is_relevant.end()); |
191 |
307 |
Assert(d_pattern_is_relevant.find(rt2) != d_pattern_is_relevant.end()); |
192 |
307 |
Assert(d_pattern_is_normal.find(rt1) != d_pattern_is_normal.end()); |
193 |
307 |
Assert(d_pattern_is_normal.find(rt2) != d_pattern_is_normal.end()); |
194 |
307 |
Assert(d_pattern_fun_sum.find(rt1) != d_pattern_fun_sum.end()); |
195 |
307 |
Assert(d_pattern_fun_sum.find(rt2) != d_pattern_fun_sum.end()); |
196 |
|
|
197 |
307 |
if( d_pattern_is_relevant[rt1] && !d_pattern_is_relevant[rt2] ){ |
198 |
|
Trace("thm-ee-debug") << "UEE : LT due to relevant." << std::endl; |
199 |
|
return true; |
200 |
307 |
}else if( d_pattern_is_relevant[rt1]==d_pattern_is_relevant[rt2] ){ |
201 |
290 |
if( d_pattern_is_normal[rt1] && !d_pattern_is_normal[rt2] ){ |
202 |
|
Trace("thm-ee-debug") << "UEE : LT due to normal." << std::endl; |
203 |
|
return true; |
204 |
290 |
}else if( d_pattern_is_normal[rt1]==d_pattern_is_normal[rt2] ){ |
205 |
290 |
if( d_pattern_fun_sum[rt1]<d_pattern_fun_sum[rt2] ){ |
206 |
56 |
Trace("thm-ee-debug") << "UEE : LT due to size." << std::endl; |
207 |
|
//decide which representative to use : based on size of the term |
208 |
56 |
return true; |
209 |
234 |
}else if( d_pattern_fun_sum[rt1]==d_pattern_fun_sum[rt2] ){ |
210 |
|
//same size : tie goes to term that has already been reported |
211 |
147 |
return isReportedCanon( rt1 ) && !isReportedCanon( rt2 ); |
212 |
|
} |
213 |
|
} |
214 |
|
} |
215 |
104 |
return false; |
216 |
|
} |
217 |
|
|
218 |
|
|
219 |
7487 |
bool ConjectureGenerator::isReportedCanon( TNode n ) { |
220 |
7487 |
return std::find( d_ue_canon.begin(), d_ue_canon.end(), n )==d_ue_canon.end(); |
221 |
|
} |
222 |
|
|
223 |
7193 |
void ConjectureGenerator::markReportedCanon( TNode n ) { |
224 |
7193 |
if( !isReportedCanon( n ) ){ |
225 |
|
d_ue_canon.push_back( n ); |
226 |
|
} |
227 |
7193 |
} |
228 |
|
|
229 |
46 |
bool ConjectureGenerator::areUniversalEqual( TNode n1, TNode n2 ) { |
230 |
46 |
return n1==n2 || ( d_uequalityEngine.hasTerm( n1 ) && d_uequalityEngine.hasTerm( n2 ) && d_uequalityEngine.areEqual( n1, n2 ) ); |
231 |
|
} |
232 |
|
|
233 |
|
bool ConjectureGenerator::areUniversalDisequal( TNode n1, TNode n2 ) { |
234 |
|
return n1!=n2 && d_uequalityEngine.hasTerm( n1 ) && d_uequalityEngine.hasTerm( n2 ) && d_uequalityEngine.areDisequal( n1, n2, false ); |
235 |
|
} |
236 |
|
|
237 |
7697 |
Node ConjectureGenerator::getUniversalRepresentative(TNode n, bool add) |
238 |
|
{ |
239 |
7697 |
if( add ){ |
240 |
7645 |
if( d_urelevant_terms.find( n )==d_urelevant_terms.end() ){ |
241 |
1388 |
setUniversalRelevant( n ); |
242 |
|
//add term to universal equality engine |
243 |
1388 |
d_uequalityEngine.addTerm( n ); |
244 |
|
// addding this term to equality engine will lead to a set of new terms (the new subterms of n) |
245 |
|
// now, do instantiation-based merging for each of these terms |
246 |
1388 |
Trace("thm-ee-debug") << "Merge equivalence classes based on instantiations of terms..." << std::endl; |
247 |
|
//merge all pending equalities |
248 |
1388 |
EntailmentCheck* echeck = d_treg.getEntailmentCheck(); |
249 |
4186 |
while( !d_upendingAdds.empty() ){ |
250 |
1399 |
Trace("sg-pending") << "Add " << d_upendingAdds.size() << " pending terms..." << std::endl; |
251 |
2798 |
std::vector< Node > pending; |
252 |
1399 |
pending.insert( pending.end(), d_upendingAdds.begin(), d_upendingAdds.end() ); |
253 |
1399 |
d_upendingAdds.clear(); |
254 |
3017 |
for( unsigned i=0; i<pending.size(); i++ ){ |
255 |
3236 |
Node t = pending[i]; |
256 |
3236 |
TypeNode tn = t.getType(); |
257 |
1618 |
Trace("thm-ee-add") << "UEE : Add universal term " << t << std::endl; |
258 |
3236 |
std::vector< Node > eq_terms; |
259 |
|
//if occurs modulo equality at ground level, it is equivalent to representative of ground equality engine |
260 |
3236 |
Node gt = echeck->evaluateTerm(t); |
261 |
1618 |
if( !gt.isNull() && gt!=t ){ |
262 |
56 |
eq_terms.push_back( gt ); |
263 |
|
} |
264 |
|
//get all equivalent terms based on theorem database |
265 |
1618 |
d_thm_index.getEquivalentTerms( t, eq_terms ); |
266 |
1618 |
if( !eq_terms.empty() ){ |
267 |
218 |
Trace("thm-ee-add") << "UEE : Based on ground EE/theorem DB, it is equivalent to " << eq_terms.size() << " terms : " << std::endl; |
268 |
|
//add equivalent terms as equalities to universal engine |
269 |
440 |
for (const Node& eqt : eq_terms) |
270 |
|
{ |
271 |
222 |
Trace("thm-ee-add") << " " << eqt << std::endl; |
272 |
222 |
bool assertEq = false; |
273 |
222 |
if (d_urelevant_terms.find(eqt) != d_urelevant_terms.end()) |
274 |
|
{ |
275 |
111 |
assertEq = true; |
276 |
|
} |
277 |
|
else |
278 |
|
{ |
279 |
111 |
Assert(eqt.getType() == tn); |
280 |
111 |
registerPattern(eqt, tn); |
281 |
444 |
if (isUniversalLessThan(eqt, t) |
282 |
455 |
|| (options().quantifiers.conjectureUeeIntro |
283 |
111 |
&& d_pattern_fun_sum[t] >= d_pattern_fun_sum[eqt])) |
284 |
|
{ |
285 |
11 |
setUniversalRelevant(eqt); |
286 |
11 |
assertEq = true; |
287 |
|
} |
288 |
|
} |
289 |
222 |
if( assertEq ){ |
290 |
244 |
Node exp; |
291 |
122 |
d_uequalityEngine.assertEquality(t.eqNode(eqt), true, exp); |
292 |
|
}else{ |
293 |
200 |
Trace("thm-ee-no-add") |
294 |
100 |
<< "Do not add : " << t << " == " << eqt << std::endl; |
295 |
|
} |
296 |
|
} |
297 |
|
}else{ |
298 |
1400 |
Trace("thm-ee-add") << "UEE : No equivalent terms." << std::endl; |
299 |
|
} |
300 |
|
} |
301 |
|
} |
302 |
|
} |
303 |
|
} |
304 |
|
|
305 |
7697 |
if( d_uequalityEngine.hasTerm( n ) ){ |
306 |
15394 |
Node r = d_uequalityEngine.getRepresentative( n ); |
307 |
7697 |
EqcInfo * ei = getOrMakeEqcInfo( r ); |
308 |
7697 |
if( ei && !ei->d_rep.get().isNull() ){ |
309 |
351 |
return ei->d_rep.get(); |
310 |
|
}else{ |
311 |
7346 |
return r; |
312 |
|
} |
313 |
|
}else{ |
314 |
|
return n; |
315 |
|
} |
316 |
|
} |
317 |
|
|
318 |
40890 |
Node ConjectureGenerator::getFreeVar( TypeNode tn, unsigned i ) { |
319 |
40890 |
return d_termCanon.getCanonicalFreeVar(tn, i); |
320 |
|
} |
321 |
|
|
322 |
24187 |
bool ConjectureGenerator::isHandledTerm( TNode n ){ |
323 |
72561 |
return getTermDatabase()->isTermActive(n) |
324 |
45294 |
&& inst::TriggerTermInfo::isAtomicTrigger(n) |
325 |
109603 |
&& (n.getKind() != APPLY_UF || n.getOperator().getKind() != SKOLEM); |
326 |
|
} |
327 |
|
|
328 |
|
Node ConjectureGenerator::getGroundEqc( TNode r ) { |
329 |
|
std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r ); |
330 |
|
return it!=d_ground_eqc_map.end() ? it->second : Node::null(); |
331 |
|
} |
332 |
|
|
333 |
350227 |
bool ConjectureGenerator::isGroundEqc( TNode r ) { |
334 |
350227 |
return d_ground_eqc_map.find( r )!=d_ground_eqc_map.end(); |
335 |
|
} |
336 |
|
|
337 |
|
bool ConjectureGenerator::isGroundTerm( TNode n ) { |
338 |
|
return std::find( d_ground_terms.begin(), d_ground_terms.end(), n )!=d_ground_terms.end(); |
339 |
|
} |
340 |
|
|
341 |
731 |
bool ConjectureGenerator::needsCheck( Theory::Effort e ) { |
342 |
|
// synchonized with instantiation engine |
343 |
731 |
return d_qstate.getInstWhenNeedsCheck(e); |
344 |
|
} |
345 |
|
|
346 |
77 |
bool ConjectureGenerator::hasEnumeratedUf( Node n ) { |
347 |
77 |
if (options().quantifiers.conjectureGenGtEnum > 0) |
348 |
|
{ |
349 |
77 |
std::map< Node, bool >::iterator it = d_uf_enum.find( n.getOperator() ); |
350 |
77 |
if( it==d_uf_enum.end() ){ |
351 |
15 |
d_uf_enum[n.getOperator()] = true; |
352 |
15 |
std::vector< Node > lem; |
353 |
15 |
getEnumeratePredUfTerm(n, options().quantifiers.conjectureGenGtEnum, lem); |
354 |
15 |
if( !lem.empty() ){ |
355 |
765 |
for (const Node& l : lem) |
356 |
|
{ |
357 |
750 |
d_qim.addPendingLemma(l, InferenceId::QUANTIFIERS_CONJ_GEN_GT_ENUM); |
358 |
|
} |
359 |
15 |
d_hasAddedLemma = true; |
360 |
15 |
return false; |
361 |
|
} |
362 |
|
} |
363 |
|
} |
364 |
62 |
return true; |
365 |
|
} |
366 |
|
|
367 |
153 |
void ConjectureGenerator::reset_round( Theory::Effort e ) { |
368 |
|
|
369 |
153 |
} |
370 |
166 |
void ConjectureGenerator::check(Theory::Effort e, QEffort quant_e) |
371 |
|
{ |
372 |
166 |
if (quant_e == QEFFORT_STANDARD) |
373 |
|
{ |
374 |
44 |
d_fullEffortCount++; |
375 |
44 |
if( d_fullEffortCount%optFullCheckFrequency()==0 ){ |
376 |
44 |
d_hasAddedLemma = false; |
377 |
44 |
d_tge.d_cg = this; |
378 |
44 |
double clSet = 0; |
379 |
44 |
if( Trace.isOn("sg-engine") ){ |
380 |
|
clSet = double(clock())/double(CLOCKS_PER_SEC); |
381 |
|
Trace("sg-engine") << "---Conjecture Engine Round, effort = " << e << "---" << std::endl; |
382 |
|
} |
383 |
44 |
eq::EqualityEngine * ee = getEqualityEngine(); |
384 |
44 |
d_conj_count = 0; |
385 |
|
|
386 |
44 |
Trace("sg-proc") << "Get eq classes..." << std::endl; |
387 |
44 |
d_op_arg_index.clear(); |
388 |
44 |
d_ground_eqc_map.clear(); |
389 |
44 |
d_bool_eqc[0] = Node::null(); |
390 |
44 |
d_bool_eqc[1] = Node::null(); |
391 |
88 |
std::vector< TNode > eqcs; |
392 |
44 |
d_em.clear(); |
393 |
44 |
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee ); |
394 |
9706 |
while( !eqcs_i.isFinished() ){ |
395 |
9662 |
TNode r = (*eqcs_i); |
396 |
4831 |
Trace("sg-proc-debug") << "...eqc : " << r << std::endl; |
397 |
4831 |
eqcs.push_back( r ); |
398 |
4831 |
if( r.getType().isBoolean() ){ |
399 |
845 |
if (areEqual(r, d_true)) |
400 |
|
{ |
401 |
44 |
d_ground_eqc_map[r] = d_true; |
402 |
44 |
d_bool_eqc[0] = r; |
403 |
|
} |
404 |
801 |
else if (areEqual(r, d_false)) |
405 |
|
{ |
406 |
44 |
d_ground_eqc_map[r] = d_false; |
407 |
44 |
d_bool_eqc[1] = r; |
408 |
|
} |
409 |
|
} |
410 |
4831 |
d_em[r] = eqcs.size(); |
411 |
4831 |
eq::EqClassIterator ieqc_i = eq::EqClassIterator( r, ee ); |
412 |
51587 |
while( !ieqc_i.isFinished() ){ |
413 |
46756 |
TNode n = (*ieqc_i); |
414 |
23378 |
Trace("sg-proc-debug") << "......term : " << n << std::endl; |
415 |
23378 |
if( getTermDatabase()->hasTermCurrent( n ) ){ |
416 |
23378 |
if( isHandledTerm( n ) ){ |
417 |
17884 |
std::vector<TNode> areps; |
418 |
21898 |
for (const Node& nc : n) |
419 |
|
{ |
420 |
12956 |
areps.push_back(d_qstate.getRepresentative(nc)); |
421 |
|
} |
422 |
8942 |
d_op_arg_index[r].addTerm(areps, n); |
423 |
|
} |
424 |
|
} |
425 |
23378 |
++ieqc_i; |
426 |
|
} |
427 |
4831 |
++eqcs_i; |
428 |
|
} |
429 |
44 |
Assert(!d_bool_eqc[0].isNull()); |
430 |
44 |
Assert(!d_bool_eqc[1].isNull()); |
431 |
44 |
d_urelevant_terms.clear(); |
432 |
44 |
Trace("sg-proc") << "...done get eq classes" << std::endl; |
433 |
|
|
434 |
44 |
Trace("sg-proc") << "Determine ground EQC..." << std::endl; |
435 |
|
bool success; |
436 |
111 |
do{ |
437 |
111 |
success = false; |
438 |
13150 |
for( unsigned i=0; i<eqcs.size(); i++ ){ |
439 |
26078 |
TNode r = eqcs[i]; |
440 |
13039 |
if( d_ground_eqc_map.find( r )==d_ground_eqc_map.end() ){ |
441 |
11832 |
std::vector< TNode > args; |
442 |
5916 |
Trace("sg-pat-debug") << "******* Get ground term for " << r << std::endl; |
443 |
11832 |
Node n; |
444 |
5916 |
if (Skolemize::isInductionTerm(r)) |
445 |
|
{ |
446 |
5147 |
n = d_op_arg_index[r].getGroundTerm( this, args ); |
447 |
|
}else{ |
448 |
769 |
n = r; |
449 |
|
} |
450 |
5916 |
if( !n.isNull() ){ |
451 |
4063 |
Trace("sg-pat") << "Ground term for eqc " << r << " : " << std::endl; |
452 |
4063 |
Trace("sg-pat") << " " << n << std::endl; |
453 |
4063 |
d_ground_eqc_map[r] = n; |
454 |
4063 |
success = true; |
455 |
|
}else{ |
456 |
1853 |
Trace("sg-pat-debug") << "...could not find ground term." << std::endl; |
457 |
|
} |
458 |
|
} |
459 |
|
} |
460 |
|
}while( success ); |
461 |
|
//also get ground terms |
462 |
44 |
d_ground_terms.clear(); |
463 |
4875 |
for( unsigned i=0; i<eqcs.size(); i++ ){ |
464 |
9662 |
TNode r = eqcs[i]; |
465 |
4831 |
d_op_arg_index[r].getGroundTerms( this, d_ground_terms ); |
466 |
|
} |
467 |
44 |
Trace("sg-proc") << "...done determine ground EQC" << std::endl; |
468 |
|
|
469 |
|
//debug printing |
470 |
44 |
if( Trace.isOn("sg-gen-eqc") ){ |
471 |
|
for( unsigned i=0; i<eqcs.size(); i++ ){ |
472 |
|
TNode r = eqcs[i]; |
473 |
|
//print out members |
474 |
|
bool firstTime = true; |
475 |
|
bool isFalse = areEqual(r, d_false); |
476 |
|
eq::EqClassIterator eqc_i = eq::EqClassIterator( r, ee ); |
477 |
|
while( !eqc_i.isFinished() ){ |
478 |
|
TNode n = (*eqc_i); |
479 |
|
if( getTermDatabase()->hasTermCurrent( n ) && getTermDatabase()->isTermActive( n ) && ( n.getKind()!=EQUAL || isFalse ) ){ |
480 |
|
if( firstTime ){ |
481 |
|
Trace("sg-gen-eqc") << "e" << d_em[r] << " : { " << std::endl; |
482 |
|
firstTime = false; |
483 |
|
} |
484 |
|
if( n.hasOperator() ){ |
485 |
|
Trace("sg-gen-eqc") << " (" << n.getOperator(); |
486 |
|
for (const Node& nc : n) |
487 |
|
{ |
488 |
|
TNode ar = d_qstate.getRepresentative(nc); |
489 |
|
Trace("sg-gen-eqc") << " e" << d_em[ar]; |
490 |
|
} |
491 |
|
Trace("sg-gen-eqc") << ") :: " << n << std::endl; |
492 |
|
}else{ |
493 |
|
Trace("sg-gen-eqc") << " " << n << std::endl; |
494 |
|
} |
495 |
|
} |
496 |
|
++eqc_i; |
497 |
|
} |
498 |
|
if( !firstTime ){ |
499 |
|
Trace("sg-gen-eqc") << "}" << std::endl; |
500 |
|
//print out ground term |
501 |
|
std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r ); |
502 |
|
if( it!=d_ground_eqc_map.end() ){ |
503 |
|
Trace("sg-gen-eqc") << "- Ground term : " << it->second << std::endl; |
504 |
|
} |
505 |
|
} |
506 |
|
} |
507 |
|
} |
508 |
|
|
509 |
44 |
Trace("sg-proc") << "Compute relevant eqc..." << std::endl; |
510 |
44 |
d_tge.d_relevant_eqc[0].clear(); |
511 |
44 |
d_tge.d_relevant_eqc[1].clear(); |
512 |
4875 |
for( unsigned i=0; i<eqcs.size(); i++ ){ |
513 |
9662 |
TNode r = eqcs[i]; |
514 |
4831 |
std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r ); |
515 |
4831 |
unsigned index = 1; |
516 |
4831 |
if( it==d_ground_eqc_map.end() ){ |
517 |
680 |
index = 0; |
518 |
|
} |
519 |
|
//based on unproven conjectures? TODO |
520 |
4831 |
d_tge.d_relevant_eqc[index].push_back( r ); |
521 |
|
} |
522 |
44 |
Trace("sg-gen-tg-debug") << "Initial relevant eqc : "; |
523 |
724 |
for( unsigned i=0; i<d_tge.d_relevant_eqc[0].size(); i++ ){ |
524 |
680 |
Trace("sg-gen-tg-debug") << "e" << d_em[d_tge.d_relevant_eqc[0][i]] << " "; |
525 |
|
} |
526 |
44 |
Trace("sg-gen-tg-debug") << std::endl; |
527 |
44 |
Trace("sg-proc") << "...done compute relevant eqc" << std::endl; |
528 |
|
|
529 |
|
|
530 |
44 |
Trace("sg-proc") << "Collect signature information..." << std::endl; |
531 |
44 |
d_tge.collectSignatureInformation(); |
532 |
44 |
if( d_hasAddedLemma ){ |
533 |
8 |
Trace("sg-proc") << "...added enumeration lemmas." << std::endl; |
534 |
|
} |
535 |
44 |
Trace("sg-proc") << "...done collect signature information" << std::endl; |
536 |
|
|
537 |
|
|
538 |
|
|
539 |
44 |
Trace("sg-proc") << "Build theorem index..." << std::endl; |
540 |
44 |
d_ue_canon.clear(); |
541 |
44 |
d_thm_index.clear(); |
542 |
88 |
std::vector< Node > provenConj; |
543 |
44 |
quantifiers::FirstOrderModel* m = d_treg.getModel(); |
544 |
263 |
for( unsigned i=0; i<m->getNumAssertedQuantifiers(); i++ ){ |
545 |
438 |
Node q = m->getAssertedQuantifier( i ); |
546 |
219 |
Trace("thm-db-debug") << "Is " << q << " a relevant theorem?" << std::endl; |
547 |
438 |
Node conjEq; |
548 |
219 |
if( q[1].getKind()==EQUAL ){ |
549 |
119 |
bool isSubsume = false; |
550 |
119 |
bool inEe = false; |
551 |
211 |
for( unsigned r=0; r<2; r++ ){ |
552 |
257 |
TNode nl = q[1][r==0 ? 0 : 1]; |
553 |
257 |
TNode nr = q[1][r==0 ? 1 : 0]; |
554 |
257 |
Node eq = nl.eqNode( nr ); |
555 |
165 |
if( r==1 || std::find( d_conjectures.begin(), d_conjectures.end(), q )==d_conjectures.end() ){ |
556 |
|
//check if it contains only relevant functions |
557 |
165 |
if( d_tge.isRelevantTerm( eq ) ){ |
558 |
|
//make it canonical |
559 |
92 |
Trace("sg-proc-debug") << "get canonical " << eq << std::endl; |
560 |
92 |
eq = d_termCanon.getCanonicalTerm(eq); |
561 |
|
}else{ |
562 |
73 |
eq = Node::null(); |
563 |
|
} |
564 |
|
} |
565 |
165 |
if( !eq.isNull() ){ |
566 |
92 |
if( r==0 ){ |
567 |
46 |
inEe = d_ee_conjectures.find( q[1] )!=d_ee_conjectures.end(); |
568 |
46 |
if( !inEe ){ |
569 |
|
//add to universal equality engine |
570 |
92 |
Node nlu = getUniversalRepresentative(eq[0], true); |
571 |
92 |
Node nru = getUniversalRepresentative(eq[1], true); |
572 |
46 |
if (areUniversalEqual(nlu, nru)) |
573 |
|
{ |
574 |
|
isSubsume = true; |
575 |
|
//set inactive (will be ignored by other modules) |
576 |
|
m->setQuantifierActive(q, false); |
577 |
|
} |
578 |
|
else |
579 |
|
{ |
580 |
92 |
Node exp; |
581 |
46 |
d_ee_conjectures[q[1]] = true; |
582 |
138 |
d_uequalityEngine.assertEquality( |
583 |
92 |
nlu.eqNode(nru), true, exp); |
584 |
|
} |
585 |
|
} |
586 |
46 |
Trace("sg-conjecture") << "*** CONJECTURE : currently proven" << (isSubsume ? " and subsumed" : ""); |
587 |
46 |
Trace("sg-conjecture") << " : " << q[1] << std::endl; |
588 |
46 |
provenConj.push_back( q ); |
589 |
|
} |
590 |
92 |
if( !isSubsume ){ |
591 |
92 |
Trace("thm-db-debug") << "Adding theorem to database " << eq[0] << " == " << eq[1] << std::endl; |
592 |
92 |
d_thm_index.addTheorem( eq[0], eq[1] ); |
593 |
|
}else{ |
594 |
|
break; |
595 |
|
} |
596 |
|
}else{ |
597 |
73 |
break; |
598 |
|
} |
599 |
|
} |
600 |
|
} |
601 |
|
} |
602 |
|
//examine status of other conjectures |
603 |
77 |
for( unsigned i=0; i<d_conjectures.size(); i++ ){ |
604 |
66 |
Node q = d_conjectures[i]; |
605 |
33 |
if( std::find( provenConj.begin(), provenConj.end(), q )==provenConj.end() ){ |
606 |
|
//check each skolem variable |
607 |
33 |
bool disproven = true; |
608 |
66 |
std::vector<Node> skolems; |
609 |
33 |
d_qim.getSkolemize()->getSkolemConstants(q, skolems); |
610 |
33 |
Trace("sg-conjecture") << " CONJECTURE : "; |
611 |
66 |
std::vector< Node > ce; |
612 |
38 |
for (unsigned j = 0; j < skolems.size(); j++) |
613 |
|
{ |
614 |
43 |
TNode rk = getRepresentative(skolems[j]); |
615 |
38 |
std::map< TNode, Node >::iterator git = d_ground_eqc_map.find( rk ); |
616 |
|
//check if it is a ground term |
617 |
38 |
if( git==d_ground_eqc_map.end() ){ |
618 |
33 |
Trace("sg-conjecture") << "ACTIVE : " << q; |
619 |
33 |
if( Trace.isOn("sg-gen-eqc") ){ |
620 |
|
Trace("sg-conjecture") << " { "; |
621 |
|
for (unsigned k = 0; k < skolems.size(); k++) |
622 |
|
{ |
623 |
|
Trace("sg-conjecture") << skolems[k] << (j == k ? "*" : "") |
624 |
|
<< " "; |
625 |
|
} |
626 |
|
Trace("sg-conjecture") << "}"; |
627 |
|
} |
628 |
33 |
Trace("sg-conjecture") << std::endl; |
629 |
33 |
disproven = false; |
630 |
33 |
break; |
631 |
|
}else{ |
632 |
5 |
ce.push_back( git->second ); |
633 |
|
} |
634 |
|
} |
635 |
33 |
if( disproven ){ |
636 |
|
Trace("sg-conjecture") << "disproven : " << q << " : "; |
637 |
|
for (unsigned j = 0, ceSize = ce.size(); j < ceSize; j++) |
638 |
|
{ |
639 |
|
Trace("sg-conjecture") << q[0][j] << " -> " << ce[j] << " "; |
640 |
|
} |
641 |
|
Trace("sg-conjecture") << std::endl; |
642 |
|
} |
643 |
|
} |
644 |
|
} |
645 |
44 |
Trace("thm-db") << "Theorem database is : " << std::endl; |
646 |
44 |
d_thm_index.debugPrint( "thm-db" ); |
647 |
44 |
Trace("thm-db") << std::endl; |
648 |
44 |
Trace("sg-proc") << "...done build theorem index" << std::endl; |
649 |
|
|
650 |
|
|
651 |
|
//clear patterns |
652 |
44 |
d_patterns.clear(); |
653 |
44 |
d_pattern_var_id.clear(); |
654 |
44 |
d_pattern_var_duplicate.clear(); |
655 |
44 |
d_pattern_is_normal.clear(); |
656 |
44 |
d_pattern_is_relevant.clear(); |
657 |
44 |
d_pattern_fun_id.clear(); |
658 |
44 |
d_pattern_fun_sum.clear(); |
659 |
44 |
d_rel_patterns.clear(); |
660 |
44 |
d_rel_pattern_var_sum.clear(); |
661 |
44 |
d_rel_pattern_typ_index.clear(); |
662 |
44 |
d_rel_pattern_subs_index.clear(); |
663 |
|
|
664 |
44 |
unsigned rel_term_count = 0; |
665 |
88 |
std::map< TypeNode, unsigned > rt_var_max; |
666 |
88 |
std::vector< TypeNode > rt_types; |
667 |
88 |
std::map< TypeNode, std::map< int, std::vector< Node > > > conj_lhs; |
668 |
44 |
unsigned addedLemmas = 0; |
669 |
44 |
unsigned maxDepth = options().quantifiers.conjectureGenMaxDepth; |
670 |
147 |
for( unsigned depth=1; depth<=maxDepth; depth++ ){ |
671 |
121 |
Trace("sg-proc") << "Generate relevant LHS at depth " << depth << "..." << std::endl; |
672 |
121 |
Trace("sg-rel-term") << "Relevant terms of depth " << depth << " : " << std::endl; |
673 |
|
//set up environment |
674 |
121 |
d_tge.d_var_id.clear(); |
675 |
121 |
d_tge.d_var_limit.clear(); |
676 |
121 |
d_tge.reset( depth, true, TypeNode::null() ); |
677 |
1461 |
while( d_tge.getNextTerm() ){ |
678 |
|
//construct term |
679 |
1340 |
Node nn = d_tge.getTerm(); |
680 |
1340 |
if (!options().quantifiers.conjectureFilterCanonical |
681 |
1340 |
|| considerTermCanon(nn, true)) |
682 |
|
{ |
683 |
670 |
rel_term_count++; |
684 |
670 |
Trace("sg-rel-term") << "*** Relevant term : "; |
685 |
670 |
d_tge.debugPrint( "sg-rel-term", "sg-rel-term-debug2" ); |
686 |
670 |
Trace("sg-rel-term") << std::endl; |
687 |
|
|
688 |
2010 |
for( unsigned r=0; r<2; r++ ){ |
689 |
1340 |
Trace("sg-rel-term-debug") << "...from equivalence classes (" << r << ") : "; |
690 |
1340 |
int index = d_tge.d_ccand_eqc[r].size()-1; |
691 |
25144 |
for( unsigned j=0; j<d_tge.d_ccand_eqc[r][index].size(); j++ ){ |
692 |
23804 |
Trace("sg-rel-term-debug") << "e" << d_em[d_tge.d_ccand_eqc[r][index][j]] << " "; |
693 |
|
} |
694 |
1340 |
Trace("sg-rel-term-debug") << std::endl; |
695 |
|
} |
696 |
1340 |
TypeNode tnn = nn.getType(); |
697 |
670 |
Trace("sg-gen-tg-debug") << "...term is " << nn << std::endl; |
698 |
670 |
conj_lhs[tnn][depth].push_back( nn ); |
699 |
|
|
700 |
|
//add information about pattern |
701 |
670 |
Trace("sg-gen-tg-debug") << "Collect pattern information..." << std::endl; |
702 |
670 |
Assert(std::find(d_rel_patterns[tnn].begin(), |
703 |
|
d_rel_patterns[tnn].end(), |
704 |
|
nn) |
705 |
|
== d_rel_patterns[tnn].end()); |
706 |
670 |
d_rel_patterns[tnn].push_back( nn ); |
707 |
|
//build information concerning the variables in this pattern |
708 |
670 |
unsigned sum = 0; |
709 |
1340 |
std::map< TypeNode, unsigned > typ_to_subs_index; |
710 |
1340 |
std::vector< TNode > gsubs_vars; |
711 |
1870 |
for( std::map< TypeNode, unsigned >::iterator it = d_tge.d_var_id.begin(); it != d_tge.d_var_id.end(); ++it ){ |
712 |
1200 |
if( it->second>0 ){ |
713 |
920 |
typ_to_subs_index[it->first] = sum; |
714 |
920 |
sum += it->second; |
715 |
2010 |
for( unsigned i=0; i<it->second; i++ ){ |
716 |
1090 |
gsubs_vars.push_back( |
717 |
2180 |
d_termCanon.getCanonicalFreeVar(it->first, i)); |
718 |
|
} |
719 |
|
} |
720 |
|
} |
721 |
670 |
d_rel_pattern_var_sum[nn] = sum; |
722 |
|
//register the pattern |
723 |
670 |
registerPattern( nn, tnn ); |
724 |
670 |
Assert(d_pattern_is_normal[nn]); |
725 |
670 |
Trace("sg-gen-tg-debug") << "...done collect pattern information" << std::endl; |
726 |
|
|
727 |
|
//record information about types |
728 |
670 |
Trace("sg-gen-tg-debug") << "Collect type information..." << std::endl; |
729 |
670 |
PatternTypIndex * pti = &d_rel_pattern_typ_index; |
730 |
1870 |
for( std::map< TypeNode, unsigned >::iterator it = d_tge.d_var_id.begin(); it != d_tge.d_var_id.end(); ++it ){ |
731 |
1200 |
pti = &pti->d_children[it->first][it->second]; |
732 |
|
//record maximum |
733 |
1200 |
if( rt_var_max.find( it->first )==rt_var_max.end() || it->second>rt_var_max[it->first] ){ |
734 |
60 |
rt_var_max[it->first] = it->second; |
735 |
|
} |
736 |
|
} |
737 |
670 |
if( std::find( rt_types.begin(), rt_types.end(), tnn )==rt_types.end() ){ |
738 |
95 |
rt_types.push_back( tnn ); |
739 |
|
} |
740 |
670 |
pti->d_terms.push_back( nn ); |
741 |
670 |
Trace("sg-gen-tg-debug") << "...done collect type information" << std::endl; |
742 |
|
|
743 |
670 |
Trace("sg-gen-tg-debug") << "Build substitutions for ground EQC..." << std::endl; |
744 |
1340 |
std::vector< TNode > gsubs_terms; |
745 |
670 |
gsubs_terms.resize( gsubs_vars.size() ); |
746 |
670 |
int index = d_tge.d_ccand_eqc[1].size()-1; |
747 |
23173 |
for( unsigned j=0; j<d_tge.d_ccand_eqc[1][index].size(); j++ ){ |
748 |
45006 |
TNode r = d_tge.d_ccand_eqc[1][index][j]; |
749 |
22503 |
Trace("sg-rel-term-debug") << " Matches for e" << d_em[r] << ", which is ground term " << d_ground_eqc_map[r] << ":" << std::endl; |
750 |
45006 |
std::map< TypeNode, std::map< unsigned, TNode > > subs; |
751 |
45006 |
std::map< TNode, bool > rev_subs; |
752 |
|
//only get ground terms |
753 |
22503 |
unsigned mode = 2; |
754 |
22503 |
d_tge.resetMatching( r, mode ); |
755 |
193755 |
while( d_tge.getNextMatch( r, subs, rev_subs ) ){ |
756 |
|
//we will be building substitutions |
757 |
85626 |
bool firstTime = true; |
758 |
215227 |
for( std::map< TypeNode, std::map< unsigned, TNode > >::iterator it = subs.begin(); it != subs.end(); ++it ){ |
759 |
129601 |
unsigned tindex = typ_to_subs_index[it->first]; |
760 |
318500 |
for( std::map< unsigned, TNode >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){ |
761 |
188899 |
if( !firstTime ){ |
762 |
103337 |
Trace("sg-rel-term-debug") << ", "; |
763 |
|
}else{ |
764 |
85562 |
firstTime = false; |
765 |
85562 |
Trace("sg-rel-term-debug") << " "; |
766 |
|
} |
767 |
188899 |
Trace("sg-rel-term-debug") << it->first << ":x" << it2->first << " -> " << it2->second; |
768 |
188899 |
Assert(tindex + it2->first < gsubs_terms.size()); |
769 |
188899 |
gsubs_terms[tindex+it2->first] = it2->second; |
770 |
|
} |
771 |
|
} |
772 |
85626 |
Trace("sg-rel-term-debug") << std::endl; |
773 |
85626 |
d_rel_pattern_subs_index[nn].addSubstitution( r, gsubs_vars, gsubs_terms ); |
774 |
|
} |
775 |
|
} |
776 |
670 |
Trace("sg-gen-tg-debug") << "...done build substitutions for ground EQC" << std::endl; |
777 |
|
} |
778 |
|
else |
779 |
|
{ |
780 |
|
Trace("sg-gen-tg-debug") << "> not canonical : " << nn << std::endl; |
781 |
|
} |
782 |
|
} |
783 |
121 |
Trace("sg-proc") << "...done generate terms at depth " << depth << std::endl; |
784 |
121 |
Trace("sg-stats") << "--------> Total LHS of depth " << depth << " : " << rel_term_count << std::endl; |
785 |
|
//Trace("conjecture-count") << "Total LHS of depth " << depth << " : " << conj_lhs[depth].size() << std::endl; |
786 |
|
|
787 |
|
/* test... |
788 |
|
for( unsigned i=0; i<rt_types.size(); i++ ){ |
789 |
|
Trace("sg-term-enum") << "Term enumeration for " << rt_types[i] << " : " << std::endl; |
790 |
|
Trace("sg-term-enum") << "Ground term : " << rt_types[i].mkGroundTerm() << std::endl; |
791 |
|
for( unsigned j=0; j<150; j++ ){ |
792 |
|
Trace("sg-term-enum") << " " << getEnumerateTerm( rt_types[i], j ) << std::endl; |
793 |
|
} |
794 |
|
} |
795 |
|
*/ |
796 |
|
|
797 |
|
//consider types from relevant terms |
798 |
439 |
for( unsigned rdepth=0; rdepth<=depth; rdepth++ ){ |
799 |
|
//set up environment |
800 |
336 |
d_tge.d_var_id.clear(); |
801 |
336 |
d_tge.d_var_limit.clear(); |
802 |
612 |
for( std::map< TypeNode, unsigned >::iterator it = rt_var_max.begin(); it != rt_var_max.end(); ++it ){ |
803 |
276 |
d_tge.d_var_id[ it->first ] = it->second; |
804 |
276 |
d_tge.d_var_limit[ it->first ] = it->second; |
805 |
|
} |
806 |
336 |
std::shuffle(rt_types.begin(), rt_types.end(), Random::getRandom()); |
807 |
654 |
std::map< TypeNode, std::vector< Node > > conj_rhs; |
808 |
1053 |
for( unsigned i=0; i<rt_types.size(); i++ ){ |
809 |
|
|
810 |
717 |
Trace("sg-proc") << "Generate relevant RHS terms of type " << rt_types[i] << " at depth " << rdepth << "..." << std::endl; |
811 |
717 |
d_tge.reset( rdepth, false, rt_types[i] ); |
812 |
|
|
813 |
5091 |
while( d_tge.getNextTerm() ){ |
814 |
4374 |
Node rhs = d_tge.getTerm(); |
815 |
2187 |
if( considerTermCanon( rhs, false ) ){ |
816 |
2187 |
Trace("sg-rel-prop") << "Relevant RHS : " << rhs << std::endl; |
817 |
|
//register pattern |
818 |
2187 |
Assert(rhs.getType() == rt_types[i]); |
819 |
2187 |
registerPattern( rhs, rt_types[i] ); |
820 |
2187 |
if( rdepth<depth ){ |
821 |
|
//consider against all LHS at depth |
822 |
15207 |
for( unsigned j=0; j<conj_lhs[rt_types[i]][depth].size(); j++ ){ |
823 |
13913 |
processCandidateConjecture( conj_lhs[rt_types[i]][depth][j], rhs, depth, rdepth ); |
824 |
|
} |
825 |
|
}else{ |
826 |
893 |
conj_rhs[rt_types[i]].push_back( rhs ); |
827 |
|
} |
828 |
|
} |
829 |
|
} |
830 |
|
} |
831 |
336 |
flushWaitingConjectures( addedLemmas, depth, rdepth ); |
832 |
|
//consider against all LHS up to depth |
833 |
336 |
if( rdepth==depth ){ |
834 |
304 |
for( unsigned lhs_depth = 1; lhs_depth<=depth; lhs_depth++ ){ |
835 |
394 |
if ((int)addedLemmas |
836 |
197 |
< options().quantifiers.conjectureGenPerRound) |
837 |
|
{ |
838 |
197 |
Trace("sg-proc") << "Consider conjectures at depth (" << lhs_depth << ", " << rdepth << ")..." << std::endl; |
839 |
396 |
for( std::map< TypeNode, std::vector< Node > >::iterator it = conj_rhs.begin(); it != conj_rhs.end(); ++it ){ |
840 |
1815 |
for( unsigned j=0; j<it->second.size(); j++ ){ |
841 |
8843 |
for( unsigned k=0; k<conj_lhs[it->first][lhs_depth].size(); k++ ){ |
842 |
7227 |
processCandidateConjecture( conj_lhs[it->first][lhs_depth][k], it->second[j], lhs_depth, rdepth ); |
843 |
|
} |
844 |
|
} |
845 |
|
} |
846 |
197 |
flushWaitingConjectures( addedLemmas, lhs_depth, depth ); |
847 |
|
} |
848 |
|
} |
849 |
|
} |
850 |
336 |
if ((int)addedLemmas >= options().quantifiers.conjectureGenPerRound) |
851 |
|
{ |
852 |
18 |
break; |
853 |
|
} |
854 |
|
} |
855 |
121 |
if ((int)addedLemmas >= options().quantifiers.conjectureGenPerRound) |
856 |
|
{ |
857 |
18 |
break; |
858 |
|
} |
859 |
|
} |
860 |
44 |
Trace("sg-stats") << "Total conjectures considered : " << d_conj_count << std::endl; |
861 |
44 |
if( Trace.isOn("thm-ee") ){ |
862 |
|
Trace("thm-ee") << "Universal equality engine is : " << std::endl; |
863 |
|
eq::EqClassesIterator ueqcs_i = eq::EqClassesIterator( &d_uequalityEngine ); |
864 |
|
while( !ueqcs_i.isFinished() ){ |
865 |
|
TNode r = (*ueqcs_i); |
866 |
|
bool firstTime = true; |
867 |
|
Node rr = getUniversalRepresentative(r); |
868 |
|
Trace("thm-ee") << " " << rr; |
869 |
|
Trace("thm-ee") << " : { "; |
870 |
|
eq::EqClassIterator ueqc_i = eq::EqClassIterator( r, &d_uequalityEngine ); |
871 |
|
while( !ueqc_i.isFinished() ){ |
872 |
|
TNode n = (*ueqc_i); |
873 |
|
if( rr!=n ){ |
874 |
|
if( firstTime ){ |
875 |
|
Trace("thm-ee") << std::endl; |
876 |
|
firstTime = false; |
877 |
|
} |
878 |
|
Trace("thm-ee") << " " << n << std::endl; |
879 |
|
} |
880 |
|
++ueqc_i; |
881 |
|
} |
882 |
|
if( !firstTime ){ Trace("thm-ee") << " "; } |
883 |
|
Trace("thm-ee") << "}" << std::endl; |
884 |
|
++ueqcs_i; |
885 |
|
} |
886 |
|
Trace("thm-ee") << std::endl; |
887 |
|
} |
888 |
44 |
if( Trace.isOn("sg-engine") ){ |
889 |
|
double clSet2 = double(clock())/double(CLOCKS_PER_SEC); |
890 |
|
Trace("sg-engine") << "Finished conjecture generator, time = " << (clSet2-clSet) << std::endl; |
891 |
|
} |
892 |
|
} |
893 |
|
} |
894 |
166 |
} |
895 |
|
|
896 |
533 |
unsigned ConjectureGenerator::flushWaitingConjectures( unsigned& addedLemmas, int ldepth, int rdepth ) { |
897 |
533 |
if( !d_waiting_conjectures_lhs.empty() ){ |
898 |
26 |
Trace("sg-proc") << "Generated " << d_waiting_conjectures_lhs.size() << " conjectures at depth " << ldepth << "/" << rdepth << "." << std::endl; |
899 |
26 |
if ((int)addedLemmas < options().quantifiers.conjectureGenPerRound) |
900 |
|
{ |
901 |
|
/* |
902 |
|
std::vector< unsigned > indices; |
903 |
|
for( unsigned i=0; i<d_waiting_conjectures_lhs.size(); i++ ){ |
904 |
|
indices.push_back( i ); |
905 |
|
} |
906 |
|
bool doSort = false; |
907 |
|
if( doSort ){ |
908 |
|
//sort them based on score |
909 |
|
sortConjectureScore scs; |
910 |
|
scs.d_scores.insert( scs.d_scores.begin(), d_waiting_conjectures_score.begin(), d_waiting_conjectures_score.end() ); |
911 |
|
std::sort( indices.begin(), indices.end(), scs ); |
912 |
|
} |
913 |
|
//if( doSort && d_waiting_conjectures_score[indices[0]]<optFilterScoreThreshold() ){ |
914 |
|
*/ |
915 |
26 |
unsigned prevCount = d_conj_count; |
916 |
42 |
for( unsigned i=0; i<d_waiting_conjectures_lhs.size(); i++ ){ |
917 |
34 |
if( d_waiting_conjectures_score[i]>=optFilterScoreThreshold() ){ |
918 |
|
//we have determined a relevant subgoal |
919 |
50 |
Node lhs = d_waiting_conjectures_lhs[i]; |
920 |
50 |
Node rhs = d_waiting_conjectures_rhs[i]; |
921 |
68 |
if (options().quantifiers.conjectureFilterCanonical |
922 |
118 |
&& (getUniversalRepresentative(lhs) != lhs |
923 |
52 |
|| getUniversalRepresentative(rhs) != rhs)) |
924 |
|
{ |
925 |
|
//skip |
926 |
|
} |
927 |
|
else |
928 |
|
{ |
929 |
18 |
Trace("sg-engine") << "*** Consider conjecture : " << lhs << " == " << rhs << std::endl; |
930 |
18 |
Trace("sg-engine-debug") << " score : " << d_waiting_conjectures_score[i] << std::endl; |
931 |
18 |
if( optStatsOnly() ){ |
932 |
|
d_conj_count++; |
933 |
|
}else{ |
934 |
18 |
std::vector< Node > bvs; |
935 |
25 |
for (const std::pair<const TypeNode, unsigned>& lhs_pattern : |
936 |
18 |
d_pattern_var_id[lhs]) |
937 |
|
{ |
938 |
50 |
for (unsigned j = 0; j <= lhs_pattern.second; j++) |
939 |
|
{ |
940 |
25 |
bvs.push_back(getFreeVar(lhs_pattern.first, j)); |
941 |
|
} |
942 |
|
} |
943 |
18 |
Node rsg; |
944 |
18 |
if( !bvs.empty() ){ |
945 |
36 |
Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, bvs ); |
946 |
18 |
rsg = NodeManager::currentNM()->mkNode( FORALL, bvl, lhs.eqNode( rhs ) ); |
947 |
|
}else{ |
948 |
|
rsg = lhs.eqNode( rhs ); |
949 |
|
} |
950 |
18 |
rsg = rewrite(rsg); |
951 |
18 |
d_conjectures.push_back( rsg ); |
952 |
18 |
d_eq_conjectures[lhs].push_back( rhs ); |
953 |
18 |
d_eq_conjectures[rhs].push_back( lhs ); |
954 |
|
|
955 |
18 |
Node lem = NodeManager::currentNM()->mkNode( OR, rsg.negate(), rsg ); |
956 |
18 |
d_qim.addPendingLemma(lem, |
957 |
|
InferenceId::QUANTIFIERS_CONJ_GEN_SPLIT); |
958 |
18 |
d_qim.addPendingPhaseRequirement(rsg, false); |
959 |
18 |
addedLemmas++; |
960 |
36 |
if ((int)addedLemmas |
961 |
18 |
>= options().quantifiers.conjectureGenPerRound) |
962 |
|
{ |
963 |
18 |
break; |
964 |
|
} |
965 |
|
} |
966 |
|
} |
967 |
|
} |
968 |
|
} |
969 |
26 |
Trace("sg-proc") << "...have now added " << addedLemmas << " conjecture lemmas." << std::endl; |
970 |
26 |
if( optStatsOnly() ){ |
971 |
|
Trace("sg-stats") << "Generated " << (d_conj_count-prevCount) << " conjectures at depth " << ldepth << "/" << rdepth << "." << std::endl; |
972 |
|
} |
973 |
|
} |
974 |
26 |
d_waiting_conjectures_lhs.clear(); |
975 |
26 |
d_waiting_conjectures_rhs.clear(); |
976 |
26 |
d_waiting_conjectures_score.clear(); |
977 |
26 |
d_waiting_conjectures.clear(); |
978 |
|
} |
979 |
533 |
return addedLemmas; |
980 |
|
} |
981 |
|
|
982 |
7553 |
bool ConjectureGenerator::considerTermCanon( Node ln, bool genRelevant ){ |
983 |
7553 |
if( !ln.isNull() ){ |
984 |
|
//do not consider if it is non-canonical, and either: |
985 |
|
// (1) we are not generating relevant terms, or |
986 |
|
// (2) its canonical form is a generalization. |
987 |
14938 |
Node lnr = getUniversalRepresentative(ln, true); |
988 |
7553 |
if( lnr==ln ){ |
989 |
7193 |
markReportedCanon( ln ); |
990 |
360 |
}else if( !genRelevant || isGeneralization( lnr, ln ) ){ |
991 |
168 |
Trace("sg-gen-consider-term") << "Do not consider term, " << ln << " is not canonical representation (which is " << lnr << ")." << std::endl; |
992 |
168 |
return false; |
993 |
|
} |
994 |
|
} |
995 |
7385 |
Trace("sg-gen-tg-debug") << "Will consider term canon " << ln << std::endl; |
996 |
7385 |
Trace("sg-gen-consider-term-debug") << std::endl; |
997 |
7385 |
return true; |
998 |
|
} |
999 |
|
|
1000 |
5547 |
unsigned ConjectureGenerator::collectFunctions( TNode opat, TNode pat, std::map< TNode, unsigned >& funcs, |
1001 |
|
std::map< TypeNode, unsigned >& mnvn, std::map< TypeNode, unsigned >& mxvn ){ |
1002 |
5547 |
if( pat.hasOperator() ){ |
1003 |
3003 |
funcs[pat.getOperator()]++; |
1004 |
3003 |
if( !d_tge.isRelevantFunc( pat.getOperator() ) ){ |
1005 |
|
d_pattern_is_relevant[opat] = false; |
1006 |
|
} |
1007 |
3003 |
unsigned sum = 1; |
1008 |
6940 |
for( unsigned i=0; i<pat.getNumChildren(); i++ ){ |
1009 |
3937 |
sum += collectFunctions( opat, pat[i], funcs, mnvn, mxvn ); |
1010 |
|
} |
1011 |
3003 |
return sum; |
1012 |
|
}else{ |
1013 |
2544 |
Assert(pat.getNumChildren() == 0); |
1014 |
2544 |
funcs[pat]++; |
1015 |
|
//for variables |
1016 |
2544 |
if( pat.getKind()==BOUND_VARIABLE ){ |
1017 |
2527 |
if( funcs[pat]>1 ){ |
1018 |
|
//duplicate variable |
1019 |
31 |
d_pattern_var_duplicate[opat]++; |
1020 |
|
}else{ |
1021 |
|
//check for max/min |
1022 |
4992 |
TypeNode tn = pat.getType(); |
1023 |
2496 |
unsigned vn = pat.getAttribute(InstVarNumAttribute()); |
1024 |
2496 |
std::map< TypeNode, unsigned >::iterator it = mnvn.find( tn ); |
1025 |
2496 |
if( it!=mnvn.end() ){ |
1026 |
316 |
if( vn<it->second ){ |
1027 |
|
d_pattern_is_normal[opat] = false; |
1028 |
|
mnvn[tn] = vn; |
1029 |
316 |
}else if( vn>mxvn[tn] ){ |
1030 |
|
if( vn!=mxvn[tn]+1 ){ |
1031 |
|
d_pattern_is_normal[opat] = false; |
1032 |
|
} |
1033 |
|
mxvn[tn] = vn; |
1034 |
|
} |
1035 |
|
}else{ |
1036 |
|
//first variable of this type |
1037 |
2180 |
mnvn[tn] = vn; |
1038 |
2180 |
mxvn[tn] = vn; |
1039 |
|
} |
1040 |
|
} |
1041 |
|
}else{ |
1042 |
17 |
d_pattern_is_relevant[opat] = false; |
1043 |
|
} |
1044 |
2544 |
return 1; |
1045 |
|
} |
1046 |
|
} |
1047 |
|
|
1048 |
7986 |
void ConjectureGenerator::registerPattern( Node pat, TypeNode tpat ) { |
1049 |
7986 |
if( std::find( d_patterns[tpat].begin(), d_patterns[tpat].end(), pat )==d_patterns[tpat].end() ){ |
1050 |
1610 |
d_patterns[TypeNode::null()].push_back( pat ); |
1051 |
1610 |
d_patterns[tpat].push_back( pat ); |
1052 |
|
|
1053 |
1610 |
Assert(d_pattern_fun_id.find(pat) == d_pattern_fun_id.end()); |
1054 |
1610 |
Assert(d_pattern_var_id.find(pat) == d_pattern_var_id.end()); |
1055 |
|
|
1056 |
|
//collect functions |
1057 |
3220 |
std::map< TypeNode, unsigned > mnvn; |
1058 |
1610 |
d_pattern_fun_sum[pat] = collectFunctions( pat, pat, d_pattern_fun_id[pat], mnvn, d_pattern_var_id[pat] ); |
1059 |
1610 |
if( d_pattern_is_normal.find( pat )==d_pattern_is_normal.end() ){ |
1060 |
1610 |
d_pattern_is_normal[pat] = true; |
1061 |
|
} |
1062 |
1610 |
if( d_pattern_is_relevant.find( pat )==d_pattern_is_relevant.end() ){ |
1063 |
1593 |
d_pattern_is_relevant[pat] = true; |
1064 |
|
} |
1065 |
|
} |
1066 |
7986 |
} |
1067 |
|
|
1068 |
234 |
bool ConjectureGenerator::isGeneralization( TNode patg, TNode pat, std::map< TNode, TNode >& subs ) { |
1069 |
234 |
if( patg.getKind()==BOUND_VARIABLE ){ |
1070 |
8 |
std::map< TNode, TNode >::iterator it = subs.find( patg ); |
1071 |
8 |
if( it!=subs.end() ){ |
1072 |
|
return it->second==pat; |
1073 |
|
}else{ |
1074 |
8 |
subs[patg] = pat; |
1075 |
8 |
return true; |
1076 |
|
} |
1077 |
|
}else{ |
1078 |
226 |
Assert(patg.hasOperator()); |
1079 |
226 |
if( !pat.hasOperator() || patg.getOperator()!=pat.getOperator() ){ |
1080 |
192 |
return false; |
1081 |
|
}else{ |
1082 |
34 |
Assert(patg.getNumChildren() == pat.getNumChildren()); |
1083 |
42 |
for( unsigned i=0; i<patg.getNumChildren(); i++ ){ |
1084 |
42 |
if( !isGeneralization( patg[i], pat[i], subs ) ){ |
1085 |
34 |
return false; |
1086 |
|
} |
1087 |
|
} |
1088 |
|
return true; |
1089 |
|
} |
1090 |
|
} |
1091 |
|
} |
1092 |
|
|
1093 |
|
int ConjectureGenerator::calculateGeneralizationDepth( TNode n, std::vector< TNode >& fv ) { |
1094 |
|
if( n.getKind()==BOUND_VARIABLE ){ |
1095 |
|
if( std::find( fv.begin(), fv.end(), n )==fv.end() ){ |
1096 |
|
fv.push_back( n ); |
1097 |
|
return 0; |
1098 |
|
}else{ |
1099 |
|
return 1; |
1100 |
|
} |
1101 |
|
}else{ |
1102 |
|
int depth = 1; |
1103 |
|
for( unsigned i=0; i<n.getNumChildren(); i++ ){ |
1104 |
|
depth += calculateGeneralizationDepth( n[i], fv ); |
1105 |
|
} |
1106 |
|
return depth; |
1107 |
|
} |
1108 |
|
} |
1109 |
|
|
1110 |
15 |
Node ConjectureGenerator::getPredicateForType( TypeNode tn ) { |
1111 |
15 |
std::map< TypeNode, Node >::iterator it = d_typ_pred.find( tn ); |
1112 |
15 |
if( it==d_typ_pred.end() ){ |
1113 |
11 |
NodeManager* nm = NodeManager::currentNM(); |
1114 |
11 |
SkolemManager* sm = nm->getSkolemManager(); |
1115 |
22 |
TypeNode op_tn = nm->mkFunctionType(tn, nm->booleanType()); |
1116 |
|
Node op = sm->mkDummySkolem( |
1117 |
22 |
"PE", op_tn, "was created by conjecture ground term enumerator."); |
1118 |
11 |
d_typ_pred[tn] = op; |
1119 |
11 |
return op; |
1120 |
|
}else{ |
1121 |
4 |
return it->second; |
1122 |
|
} |
1123 |
|
} |
1124 |
|
|
1125 |
15 |
void ConjectureGenerator::getEnumerateUfTerm( Node n, unsigned num, std::vector< Node >& terms ) { |
1126 |
15 |
if( n.getNumChildren()>0 ){ |
1127 |
30 |
Trace("sg-gt-enum-debug") << "Get enumerate uf terms " << n << " (" << num |
1128 |
15 |
<< ")" << std::endl; |
1129 |
15 |
TermEnumeration* te = d_treg.getTermEnumeration(); |
1130 |
|
// below, we do a fair enumeration of vectors vec of indices whose sum is |
1131 |
|
// 1,2,3, ... |
1132 |
30 |
std::vector< int > vec; |
1133 |
30 |
std::vector< TypeNode > types; |
1134 |
34 |
for( unsigned i=0; i<n.getNumChildren(); i++ ){ |
1135 |
19 |
vec.push_back( 0 ); |
1136 |
38 |
TypeNode tn = n[i].getType(); |
1137 |
19 |
if (tn.isClosedEnumerable()) |
1138 |
|
{ |
1139 |
19 |
types.push_back( tn ); |
1140 |
|
}else{ |
1141 |
|
return; |
1142 |
|
} |
1143 |
|
} |
1144 |
|
// the index of the last child is determined by the limit of the sum |
1145 |
|
// of indices of children (size_limit) and the sum of the indices of the |
1146 |
|
// other children (vec_sum). Hence, we pop here and add this value at each |
1147 |
|
// iteration of the loop. |
1148 |
15 |
vec.pop_back(); |
1149 |
15 |
int size_limit = 0; |
1150 |
15 |
int vec_sum = -1; |
1151 |
15 |
unsigned index = 0; |
1152 |
15 |
unsigned last_size = terms.size(); |
1153 |
2665 |
while( terms.size()<num ){ |
1154 |
1325 |
if( vec_sum==-1 ){ |
1155 |
590 |
vec_sum = 0; |
1156 |
|
// we will construct a new child below |
1157 |
|
// since sum is 0, the index of last child is limit |
1158 |
590 |
vec.push_back( size_limit ); |
1159 |
|
} |
1160 |
735 |
else if (index < vec.size()) |
1161 |
|
{ |
1162 |
196 |
Assert(index < types.size()); |
1163 |
|
//see if we can iterate current |
1164 |
392 |
if (vec_sum < size_limit |
1165 |
392 |
&& !te->getEnumerateTerm(types[index], vec[index] + 1).isNull()) |
1166 |
|
{ |
1167 |
160 |
vec[index]++; |
1168 |
160 |
vec_sum++; |
1169 |
|
// we will construct a new child below |
1170 |
|
// add the index of the last child, its index is (limit-sum) |
1171 |
160 |
vec.push_back( size_limit - vec_sum ); |
1172 |
|
}else{ |
1173 |
|
// reset the index |
1174 |
36 |
vec_sum -= vec[index]; |
1175 |
36 |
vec[index] = 0; |
1176 |
36 |
index++; |
1177 |
|
} |
1178 |
|
} |
1179 |
1325 |
if (index < vec.size()) |
1180 |
|
{ |
1181 |
|
// if we are ready to construct the term |
1182 |
750 |
if( vec.size()==n.getNumChildren() ){ |
1183 |
|
Node lc = |
1184 |
1500 |
te->getEnumerateTerm(types[vec.size() - 1], vec[vec.size() - 1]); |
1185 |
750 |
if( !lc.isNull() ){ |
1186 |
1700 |
for( unsigned i=0; i<vec.size(); i++ ){ |
1187 |
950 |
Trace("sg-gt-enum-debug") << vec[i] << " "; |
1188 |
|
} |
1189 |
750 |
Trace("sg-gt-enum-debug") << " / " << size_limit << std::endl; |
1190 |
1700 |
for( unsigned i=0; i<n.getNumChildren(); i++ ){ |
1191 |
950 |
Trace("sg-gt-enum-debug") << n[i].getType() << " "; |
1192 |
|
} |
1193 |
750 |
Trace("sg-gt-enum-debug") << std::endl; |
1194 |
1500 |
std::vector< Node > children; |
1195 |
750 |
children.push_back( n.getOperator() ); |
1196 |
950 |
for( unsigned i=0; i<(vec.size()-1); i++ ){ |
1197 |
400 |
Node nn = te->getEnumerateTerm(types[i], vec[i]); |
1198 |
200 |
Assert(!nn.isNull()); |
1199 |
200 |
Assert(nn.getType() == n[i].getType()); |
1200 |
200 |
children.push_back( nn ); |
1201 |
|
} |
1202 |
750 |
children.push_back( lc ); |
1203 |
1500 |
Node nenum = NodeManager::currentNM()->mkNode(APPLY_UF, children); |
1204 |
1500 |
Trace("sg-gt-enum") |
1205 |
750 |
<< "Ground term enumerate : " << nenum << std::endl; |
1206 |
750 |
terms.push_back(nenum); |
1207 |
|
} |
1208 |
|
// pop the index for the last child |
1209 |
750 |
vec.pop_back(); |
1210 |
750 |
index = 0; |
1211 |
|
} |
1212 |
|
}else{ |
1213 |
|
// no more indices to increment, we reset and increment size_limit |
1214 |
575 |
if( terms.size()>last_size ){ |
1215 |
575 |
last_size = terms.size(); |
1216 |
575 |
size_limit++; |
1217 |
611 |
for( unsigned i=0; i<vec.size(); i++ ){ |
1218 |
36 |
vec[i] = 0; |
1219 |
|
} |
1220 |
575 |
vec_sum = -1; |
1221 |
|
}else{ |
1222 |
|
// No terms were generated at the previous size. |
1223 |
|
// Thus, we've saturated, no more terms can be enumerated. |
1224 |
|
return; |
1225 |
|
} |
1226 |
|
} |
1227 |
|
} |
1228 |
|
}else{ |
1229 |
|
terms.push_back( n ); |
1230 |
|
} |
1231 |
|
} |
1232 |
|
|
1233 |
15 |
void ConjectureGenerator::getEnumeratePredUfTerm( Node n, unsigned num, std::vector< Node >& terms ) { |
1234 |
30 |
std::vector< Node > uf_terms; |
1235 |
15 |
getEnumerateUfTerm( n, num, uf_terms ); |
1236 |
30 |
Node p = getPredicateForType( n.getType() ); |
1237 |
765 |
for( unsigned i=0; i<uf_terms.size(); i++ ){ |
1238 |
750 |
terms.push_back( NodeManager::currentNM()->mkNode( APPLY_UF, p, uf_terms[i] ) ); |
1239 |
|
} |
1240 |
15 |
} |
1241 |
|
|
1242 |
21140 |
void ConjectureGenerator::processCandidateConjecture( TNode lhs, TNode rhs, unsigned lhs_depth, unsigned rhs_depth ) { |
1243 |
21140 |
int score = considerCandidateConjecture( lhs, rhs ); |
1244 |
21140 |
if( score>0 ){ |
1245 |
63 |
Trace("sg-conjecture") << "* Candidate conjecture : " << lhs << " == " << rhs << std::endl; |
1246 |
63 |
Trace("sg-conjecture-debug") << " LHS, RHS generalization depth : " << lhs_depth << ", " << rhs_depth << std::endl; |
1247 |
63 |
Trace("sg-conjecture-debug") << " confirmed = " << d_subs_confirmCount << ", #witnesses range = " << d_subs_confirmWitnessRange.size() << "." << std::endl; |
1248 |
63 |
Trace("sg-conjecture-debug") << " #witnesses for "; |
1249 |
63 |
bool firstTime = true; |
1250 |
170 |
for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){ |
1251 |
107 |
if( !firstTime ){ |
1252 |
44 |
Trace("sg-conjecture-debug") << ", "; |
1253 |
|
} |
1254 |
107 |
Trace("sg-conjecture-debug") << it->first << " : " << it->second.size(); |
1255 |
|
//if( it->second.size()==1 ){ |
1256 |
|
// Trace("sg-conjecture-debug") << " (" << it->second[0] << ")"; |
1257 |
|
//} |
1258 |
107 |
Trace("sg-conjecture-debug2") << " ("; |
1259 |
2919 |
for( unsigned j=0; j<it->second.size(); j++ ){ |
1260 |
2812 |
if( j>0 ){ Trace("sg-conjecture-debug2") << " "; } |
1261 |
2812 |
Trace("sg-conjecture-debug2") << d_ground_eqc_map[it->second[j]]; |
1262 |
|
} |
1263 |
107 |
Trace("sg-conjecture-debug2") << ")"; |
1264 |
107 |
firstTime = false; |
1265 |
|
} |
1266 |
63 |
Trace("sg-conjecture-debug") << std::endl; |
1267 |
63 |
Trace("sg-conjecture-debug") << " unknown = " << d_subs_unkCount << std::endl; |
1268 |
|
//Assert( getUniversalRepresentative( rhs )==rhs ); |
1269 |
|
//Assert( getUniversalRepresentative( lhs )==lhs ); |
1270 |
63 |
d_waiting_conjectures_lhs.push_back( lhs ); |
1271 |
63 |
d_waiting_conjectures_rhs.push_back( rhs ); |
1272 |
63 |
d_waiting_conjectures_score.push_back( score ); |
1273 |
63 |
d_waiting_conjectures[lhs].push_back( rhs ); |
1274 |
63 |
d_waiting_conjectures[rhs].push_back( lhs ); |
1275 |
|
}else{ |
1276 |
21077 |
Trace("sg-conjecture-debug2") << "...do not consider " << lhs << " == " << rhs << ", score = " << score << std::endl; |
1277 |
|
} |
1278 |
21140 |
} |
1279 |
|
|
1280 |
21140 |
int ConjectureGenerator::considerCandidateConjecture( TNode lhs, TNode rhs ) { |
1281 |
21140 |
Assert(lhs.getType() == rhs.getType()); |
1282 |
|
|
1283 |
21140 |
Trace("sg-cconj-debug") << "Consider candidate conjecture : " << lhs << " == " << rhs << "?" << std::endl; |
1284 |
21140 |
if( lhs==rhs ){ |
1285 |
318 |
Trace("sg-cconj-debug") << " -> trivial." << std::endl; |
1286 |
318 |
return -1; |
1287 |
|
}else{ |
1288 |
20822 |
if( lhs.getKind()==APPLY_CONSTRUCTOR && rhs.getKind()==APPLY_CONSTRUCTOR ){ |
1289 |
3794 |
Trace("sg-cconj-debug") << " -> irrelevant by syntactic analysis." << std::endl; |
1290 |
3794 |
return -1; |
1291 |
|
} |
1292 |
|
//variables of LHS must subsume variables of RHS |
1293 |
36987 |
for( std::map< TypeNode, unsigned >::iterator it = d_pattern_var_id[rhs].begin(); it != d_pattern_var_id[rhs].end(); ++it ){ |
1294 |
24750 |
std::map< TypeNode, unsigned >::iterator itl = d_pattern_var_id[lhs].find( it->first ); |
1295 |
24750 |
if( itl!=d_pattern_var_id[lhs].end() ){ |
1296 |
19959 |
if( itl->second<it->second ){ |
1297 |
|
Trace("sg-cconj-debug") << " -> variables of sort " << it->first << " are not subsumed." << std::endl; |
1298 |
4791 |
return -1; |
1299 |
|
}else{ |
1300 |
19959 |
Trace("sg-cconj-debug2") << " variables of sort " << it->first << " are : " << itl->second << " vs " << it->second << std::endl; |
1301 |
|
} |
1302 |
|
}else{ |
1303 |
4791 |
Trace("sg-cconj-debug") << " -> has no variables of sort " << it->first << "." << std::endl; |
1304 |
4791 |
return -1; |
1305 |
|
} |
1306 |
|
} |
1307 |
|
|
1308 |
|
//currently active conjecture? |
1309 |
12237 |
std::map< Node, std::vector< Node > >::iterator iteq = d_eq_conjectures.find( lhs ); |
1310 |
12237 |
if( iteq!=d_eq_conjectures.end() ){ |
1311 |
353 |
if( std::find( iteq->second.begin(), iteq->second.end(), rhs )!=iteq->second.end() ){ |
1312 |
31 |
Trace("sg-cconj-debug") << " -> this conjecture is already active." << std::endl; |
1313 |
31 |
return -1; |
1314 |
|
} |
1315 |
|
} |
1316 |
|
//current a waiting conjecture? |
1317 |
12206 |
std::map< Node, std::vector< Node > >::iterator itw = d_waiting_conjectures.find( lhs ); |
1318 |
12206 |
if( itw!=d_waiting_conjectures.end() ){ |
1319 |
165 |
if( std::find( itw->second.begin(), itw->second.end(), rhs )!=itw->second.end() ){ |
1320 |
|
Trace("sg-cconj-debug") << " -> already are considering this conjecture." << std::endl; |
1321 |
|
return -1; |
1322 |
|
} |
1323 |
|
} |
1324 |
|
// check if canonical representation (should be, but for efficiency this is |
1325 |
|
// not guarenteed) if( options().quantifiers.conjectureFilterCanonical && ( |
1326 |
|
// getUniversalRepresentative( lhs )!=lhs || getUniversalRepresentative( rhs |
1327 |
|
// )!=rhs ) ){ |
1328 |
|
// Trace("sg-cconj") << " -> after processing, not canonical." << |
1329 |
|
// std::endl; return -1; |
1330 |
|
//} |
1331 |
|
|
1332 |
|
int score; |
1333 |
12206 |
bool scoreSet = false; |
1334 |
|
|
1335 |
12206 |
Trace("sg-cconj") << "Consider possible candidate conjecture : " << lhs << " == " << rhs << "?" << std::endl; |
1336 |
|
//find witness for counterexample, if possible |
1337 |
12206 |
if (options().quantifiers.conjectureFilterModel) |
1338 |
|
{ |
1339 |
12206 |
Assert(d_rel_pattern_var_sum.find(lhs) != d_rel_pattern_var_sum.end()); |
1340 |
12206 |
Trace("sg-cconj-debug") << "Notify substitutions over " << d_rel_pattern_var_sum[lhs] << " variables." << std::endl; |
1341 |
19215 |
std::map< TNode, TNode > subs; |
1342 |
12206 |
d_subs_confirmCount = 0; |
1343 |
12206 |
d_subs_confirmWitnessRange.clear(); |
1344 |
12206 |
d_subs_confirmWitnessDomain.clear(); |
1345 |
12206 |
d_subs_unkCount = 0; |
1346 |
12206 |
if( !d_rel_pattern_subs_index[lhs].notifySubstitutions( this, subs, rhs, d_rel_pattern_var_sum[lhs] ) ){ |
1347 |
5197 |
Trace("sg-cconj") << " -> found witness that falsifies the conjecture." << std::endl; |
1348 |
5197 |
return -1; |
1349 |
|
} |
1350 |
|
//score is the minimum number of distinct substitutions for a variable |
1351 |
7116 |
for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){ |
1352 |
107 |
int num = (int)it->second.size(); |
1353 |
107 |
if( !scoreSet || num<score ){ |
1354 |
73 |
score = num; |
1355 |
73 |
scoreSet = true; |
1356 |
|
} |
1357 |
|
} |
1358 |
7009 |
if( !scoreSet ){ |
1359 |
6946 |
score = 0; |
1360 |
|
} |
1361 |
7009 |
Trace("sg-cconj") << " confirmed = " << d_subs_confirmCount << ", #witnesses range = " << d_subs_confirmWitnessRange.size() << "." << std::endl; |
1362 |
7116 |
for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){ |
1363 |
107 |
Trace("sg-cconj") << " #witnesses for " << it->first << " : " << it->second.size() << std::endl; |
1364 |
|
} |
1365 |
|
} |
1366 |
|
else |
1367 |
|
{ |
1368 |
|
score = 1; |
1369 |
|
} |
1370 |
|
|
1371 |
7009 |
Trace("sg-cconj") << " -> SUCCESS." << std::endl; |
1372 |
7009 |
Trace("sg-cconj") << " score : " << score << std::endl; |
1373 |
|
|
1374 |
7009 |
return score; |
1375 |
|
} |
1376 |
|
} |
1377 |
|
|
1378 |
860201 |
bool ConjectureGenerator::notifySubstitution( TNode glhs, std::map< TNode, TNode >& subs, TNode rhs ) { |
1379 |
860201 |
if( Trace.isOn("sg-cconj-debug") ){ |
1380 |
|
Trace("sg-cconj-debug") << "Ground eqc for LHS : " << glhs << ", based on substituion: " << std::endl; |
1381 |
|
for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){ |
1382 |
|
Assert(getRepresentative(it->second) == it->second); |
1383 |
|
Trace("sg-cconj-debug") << " " << it->first << " -> " << it->second << std::endl; |
1384 |
|
} |
1385 |
|
} |
1386 |
860201 |
Trace("sg-cconj-debug") << "Evaluate RHS : : " << rhs << std::endl; |
1387 |
|
//get the representative of rhs with substitution subs |
1388 |
860201 |
EntailmentCheck* echeck = d_treg.getEntailmentCheck(); |
1389 |
1720402 |
TNode grhs = echeck->getEntailedTerm(rhs, subs, true); |
1390 |
860201 |
Trace("sg-cconj-debug") << "...done evaluating term, got : " << grhs << std::endl; |
1391 |
860201 |
if( !grhs.isNull() ){ |
1392 |
17604 |
if( glhs!=grhs ){ |
1393 |
5197 |
Trace("sg-cconj-debug") << "Ground eqc for RHS : " << grhs << std::endl; |
1394 |
|
//check based on ground terms |
1395 |
5197 |
std::map< TNode, Node >::iterator itl = d_ground_eqc_map.find( glhs ); |
1396 |
5197 |
if( itl!=d_ground_eqc_map.end() ){ |
1397 |
5197 |
std::map< TNode, Node >::iterator itr = d_ground_eqc_map.find( grhs ); |
1398 |
5197 |
if( itr!=d_ground_eqc_map.end() ){ |
1399 |
1785 |
Trace("sg-cconj-debug") << "We have ground terms " << itl->second << " and " << itr->second << "." << std::endl; |
1400 |
1785 |
if( itl->second.isConst() && itr->second.isConst() ){ |
1401 |
1717 |
Trace("sg-cconj-debug") << "...disequal constants." << std::endl; |
1402 |
1717 |
Trace("sg-cconj-witness") << " Witness of falsification : " << itl->second << " != " << itr->second << ", substutition is : " << std::endl; |
1403 |
5671 |
for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){ |
1404 |
3954 |
Trace("sg-cconj-witness") << " " << it->first << " -> " << it->second << std::endl; |
1405 |
|
} |
1406 |
1717 |
return false; |
1407 |
|
} |
1408 |
|
} |
1409 |
|
} |
1410 |
|
} |
1411 |
15887 |
Trace("sg-cconj-debug") << "RHS is identical." << std::endl; |
1412 |
15887 |
bool isGroundSubs = true; |
1413 |
48948 |
for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){ |
1414 |
33061 |
std::map< TNode, Node >::iterator git = d_ground_eqc_map.find( it->second ); |
1415 |
33061 |
if( git==d_ground_eqc_map.end() ){ |
1416 |
|
isGroundSubs = false; |
1417 |
|
break; |
1418 |
|
} |
1419 |
|
} |
1420 |
15887 |
if( isGroundSubs ){ |
1421 |
15887 |
if( glhs==grhs ){ |
1422 |
12407 |
Trace("sg-cconj-witness") << " Witnessed " << glhs << " == " << grhs << ", substutition is : " << std::endl; |
1423 |
37039 |
for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){ |
1424 |
24632 |
Trace("sg-cconj-witness") << " " << it->first << " -> " << it->second << std::endl; |
1425 |
24632 |
if( std::find( d_subs_confirmWitnessDomain[it->first].begin(), d_subs_confirmWitnessDomain[it->first].end(), it->second )==d_subs_confirmWitnessDomain[it->first].end() ){ |
1426 |
5642 |
d_subs_confirmWitnessDomain[it->first].push_back( it->second ); |
1427 |
|
} |
1428 |
|
} |
1429 |
12407 |
d_subs_confirmCount++; |
1430 |
12407 |
if( std::find( d_subs_confirmWitnessRange.begin(), d_subs_confirmWitnessRange.end(), glhs )==d_subs_confirmWitnessRange.end() ){ |
1431 |
2660 |
d_subs_confirmWitnessRange.push_back( glhs ); |
1432 |
|
} |
1433 |
|
}else{ |
1434 |
3480 |
if( optFilterUnknown() ){ |
1435 |
3480 |
Trace("sg-cconj-debug") << "...ground substitution giving terms that are neither equal nor disequal." << std::endl; |
1436 |
3480 |
return false; |
1437 |
|
} |
1438 |
|
} |
1439 |
|
} |
1440 |
|
}else{ |
1441 |
842597 |
Trace("sg-cconj-debug") << "(could not ground eqc for RHS)." << std::endl; |
1442 |
|
} |
1443 |
855004 |
return true; |
1444 |
|
} |
1445 |
|
|
1446 |
|
|
1447 |
|
|
1448 |
|
|
1449 |
|
|
1450 |
|
|
1451 |
3660 |
void TermGenerator::reset( TermGenEnv * s, TypeNode tn ) { |
1452 |
3660 |
Assert(d_children.empty()); |
1453 |
3660 |
d_typ = tn; |
1454 |
3660 |
d_status = 0; |
1455 |
3660 |
d_status_num = 0; |
1456 |
3660 |
d_children.clear(); |
1457 |
3660 |
Trace("sg-gen-tg-debug2") << "...add to context " << this << std::endl; |
1458 |
3660 |
d_id = s->d_tg_id; |
1459 |
3660 |
s->changeContext( true ); |
1460 |
3660 |
} |
1461 |
|
|
1462 |
48520 |
bool TermGenerator::getNextTerm( TermGenEnv * s, unsigned depth ) { |
1463 |
48520 |
if( Trace.isOn("sg-gen-tg-debug2") ){ |
1464 |
|
Trace("sg-gen-tg-debug2") << this << " getNextTerm depth " << depth << " : status = " << d_status << ", num = " << d_status_num; |
1465 |
|
if( d_status==5 ){ |
1466 |
|
TNode f = s->getTgFunc( d_typ, d_status_num ); |
1467 |
|
Trace("sg-gen-tg-debug2") << ", f = " << f; |
1468 |
|
Trace("sg-gen-tg-debug2") << ", #args = " << s->d_func_args[f].size(); |
1469 |
|
Trace("sg-gen-tg-debug2") << ", childNum = " << d_status_child_num; |
1470 |
|
Trace("sg-gen-tg-debug2") << ", #children = " << d_children.size(); |
1471 |
|
} |
1472 |
|
Trace("sg-gen-tg-debug2") << std::endl; |
1473 |
|
} |
1474 |
|
|
1475 |
48520 |
if( d_status==0 ){ |
1476 |
3660 |
d_status++; |
1477 |
3660 |
if( !d_typ.isNull() ){ |
1478 |
3539 |
if( s->allowVar( d_typ ) ){ |
1479 |
|
//allocate variable |
1480 |
1689 |
d_status_num = s->d_var_id[d_typ]; |
1481 |
1689 |
s->addVar( d_typ ); |
1482 |
1689 |
Trace("sg-gen-tg-debug2") << this << " ...return unique var #" << d_status_num << std::endl; |
1483 |
1689 |
return s->considerCurrentTerm() ? true : getNextTerm( s, depth ); |
1484 |
|
}else{ |
1485 |
|
//check allocating new variable |
1486 |
1850 |
d_status++; |
1487 |
1850 |
d_status_num = -1; |
1488 |
1850 |
if( s->d_gen_relevant_terms ){ |
1489 |
|
s->d_tg_gdepth++; |
1490 |
|
} |
1491 |
1850 |
return getNextTerm( s, depth ); |
1492 |
|
} |
1493 |
|
}else{ |
1494 |
121 |
d_status = 4; |
1495 |
121 |
d_status_num = -1; |
1496 |
121 |
return getNextTerm( s, depth ); |
1497 |
|
} |
1498 |
44860 |
}else if( d_status==2 ){ |
1499 |
|
//cleanup previous information |
1500 |
|
//if( d_status_num>=0 ){ |
1501 |
|
// s->d_var_eq_tg[d_status_num].pop_back(); |
1502 |
|
//} |
1503 |
|
//check if there is another variable |
1504 |
6992 |
if( (d_status_num+1)<(int)s->getNumTgVars( d_typ ) ){ |
1505 |
3453 |
d_status_num++; |
1506 |
|
//we have equated two variables |
1507 |
|
//s->d_var_eq_tg[d_status_num].push_back( d_id ); |
1508 |
3453 |
Trace("sg-gen-tg-debug2") << this << "...consider other var #" << d_status_num << std::endl; |
1509 |
3453 |
return s->considerCurrentTerm() ? true : getNextTerm( s, depth ); |
1510 |
|
}else{ |
1511 |
3539 |
if( s->d_gen_relevant_terms ){ |
1512 |
1248 |
s->d_tg_gdepth--; |
1513 |
|
} |
1514 |
3539 |
d_status++; |
1515 |
3539 |
return getNextTerm( s, depth ); |
1516 |
|
} |
1517 |
37868 |
}else if( d_status==4 ){ |
1518 |
8738 |
d_status++; |
1519 |
8738 |
if( depth>0 && (d_status_num+1)<(int)s->getNumTgFuncs( d_typ ) ){ |
1520 |
5078 |
d_status_num++; |
1521 |
5078 |
d_status_child_num = 0; |
1522 |
5078 |
Trace("sg-gen-tg-debug2") << this << "...consider function " << s->getTgFunc( d_typ, d_status_num ) << std::endl; |
1523 |
5078 |
s->d_tg_gdepth++; |
1524 |
5078 |
if( !s->considerCurrentTerm() ){ |
1525 |
2380 |
s->d_tg_gdepth--; |
1526 |
|
//don't consider this function |
1527 |
2380 |
d_status--; |
1528 |
|
}else{ |
1529 |
|
//we have decided on a function application |
1530 |
|
} |
1531 |
5078 |
return getNextTerm( s, depth ); |
1532 |
|
}else{ |
1533 |
|
//do not choose function applications at depth 0 |
1534 |
3660 |
d_status++; |
1535 |
3660 |
return getNextTerm( s, depth ); |
1536 |
|
} |
1537 |
29130 |
}else if( d_status==5 ){ |
1538 |
|
//iterating over arguments |
1539 |
40484 |
TNode f = s->getTgFunc( d_typ, d_status_num ); |
1540 |
20242 |
if( d_status_child_num<0 ){ |
1541 |
|
//no more arguments |
1542 |
2698 |
s->d_tg_gdepth--; |
1543 |
2698 |
d_status--; |
1544 |
2698 |
return getNextTerm( s, depth ); |
1545 |
17544 |
}else if( d_status_child_num==(int)s->d_func_args[f].size() ){ |
1546 |
5888 |
d_status_child_num--; |
1547 |
5888 |
return s->considerCurrentTermCanon( d_id ) ? true : getNextTerm( s, depth ); |
1548 |
|
//return true; |
1549 |
|
}else{ |
1550 |
11656 |
Assert(d_status_child_num < (int)s->d_func_args[f].size()); |
1551 |
11656 |
if( d_status_child_num==(int)d_children.size() ){ |
1552 |
2822 |
d_children.push_back( s->d_tg_id ); |
1553 |
2822 |
Assert(s->d_tg_alloc.find(s->d_tg_id) == s->d_tg_alloc.end()); |
1554 |
2822 |
s->d_tg_alloc[d_children[d_status_child_num]].reset( s, s->d_func_args[f][d_status_child_num] ); |
1555 |
2822 |
return getNextTerm( s, depth ); |
1556 |
|
}else{ |
1557 |
8834 |
Assert(d_status_child_num + 1 == (int)d_children.size()); |
1558 |
8834 |
if( s->d_tg_alloc[d_children[d_status_child_num]].getNextTerm( s, depth-1 ) ){ |
1559 |
6012 |
d_status_child_num++; |
1560 |
6012 |
return getNextTerm( s, depth ); |
1561 |
|
}else{ |
1562 |
5644 |
Trace("sg-gen-tg-debug2") |
1563 |
2822 |
<< "...remove child from context " << std::endl; |
1564 |
2822 |
s->changeContext(false); |
1565 |
2822 |
d_children.pop_back(); |
1566 |
2822 |
d_status_child_num--; |
1567 |
2822 |
return getNextTerm( s, depth ); |
1568 |
|
} |
1569 |
|
} |
1570 |
|
} |
1571 |
8888 |
}else if( d_status==1 || d_status==3 ){ |
1572 |
5228 |
if( d_status==1 ){ |
1573 |
1689 |
s->removeVar( d_typ ); |
1574 |
1689 |
Assert(d_status_num == (int)s->d_var_id[d_typ]); |
1575 |
|
//check if there is only one feasible equivalence class. if so, don't make pattern any more specific. |
1576 |
|
//unsigned i = s->d_ccand_eqc[0].size()-1; |
1577 |
|
//if( s->d_ccand_eqc[0][i].size()==1 && s->d_ccand_eqc[1][i].empty() ){ |
1578 |
|
// d_status = 6; |
1579 |
|
// return getNextTerm( s, depth ); |
1580 |
|
//} |
1581 |
1689 |
s->d_tg_gdepth++; |
1582 |
|
} |
1583 |
5228 |
d_status++; |
1584 |
5228 |
d_status_num = -1; |
1585 |
5228 |
return getNextTerm( s, depth ); |
1586 |
|
}else{ |
1587 |
3660 |
Assert(d_children.empty()); |
1588 |
3660 |
return false; |
1589 |
|
} |
1590 |
|
} |
1591 |
|
|
1592 |
870523 |
void TermGenerator::resetMatching( TermGenEnv * s, TNode eqc, unsigned mode ) { |
1593 |
870523 |
d_match_status = 0; |
1594 |
870523 |
d_match_status_child_num = 0; |
1595 |
870523 |
d_match_children.clear(); |
1596 |
870523 |
d_match_children_end.clear(); |
1597 |
870523 |
d_match_mode = mode; |
1598 |
|
//if this term generalizes, it must generalize a non-ground term |
1599 |
|
//if( (d_match_mode & ( 1 << 2 ))!=0 && s->isGroundEqc( eqc ) && d_status==5 ){ |
1600 |
|
// d_match_status = -1; |
1601 |
|
//} |
1602 |
870523 |
} |
1603 |
|
|
1604 |
3365362 |
bool TermGenerator::getNextMatch( TermGenEnv * s, TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs ) { |
1605 |
3365362 |
if( d_match_status<0 ){ |
1606 |
|
return false; |
1607 |
|
} |
1608 |
3365362 |
if( Trace.isOn("sg-gen-tg-match") ){ |
1609 |
|
Trace("sg-gen-tg-match") << "Matching "; |
1610 |
|
debugPrint( s, "sg-gen-tg-match", "sg-gen-tg-match" ); |
1611 |
|
Trace("sg-gen-tg-match") << " with eqc e" << s->d_cg->d_em[eqc] << "..." << std::endl; |
1612 |
|
Trace("sg-gen-tg-match") << " mstatus = " << d_match_status; |
1613 |
|
if( d_status==5 ){ |
1614 |
|
TNode f = s->getTgFunc( d_typ, d_status_num ); |
1615 |
|
Trace("sg-gen-tg-debug2") << ", f = " << f; |
1616 |
|
Trace("sg-gen-tg-debug2") << ", #args = " << s->d_func_args[f].size(); |
1617 |
|
Trace("sg-gen-tg-debug2") << ", mchildNum = " << d_match_status_child_num; |
1618 |
|
Trace("sg-gen-tg-debug2") << ", #mchildren = " << d_match_children.size(); |
1619 |
|
} |
1620 |
|
Trace("sg-gen-tg-debug2") << ", current substitution : {"; |
1621 |
|
for( std::map< TypeNode, std::map< unsigned, TNode > >::iterator itt = subs.begin(); itt != subs.end(); ++itt ){ |
1622 |
|
for( std::map< unsigned, TNode >::iterator it = itt->second.begin(); it != itt->second.end(); ++it ){ |
1623 |
|
Trace("sg-gen-tg-debug2") << " " << it->first << " -> e" << s->d_cg->d_em[it->second]; |
1624 |
|
} |
1625 |
|
} |
1626 |
|
Trace("sg-gen-tg-debug2") << " } " << std::endl; |
1627 |
|
} |
1628 |
3365362 |
if( d_status==1 ){ |
1629 |
|
//a variable |
1630 |
562071 |
if( d_match_status==0 ){ |
1631 |
346339 |
d_match_status++; |
1632 |
346339 |
if( (d_match_mode & ( 1 << 1 ))!=0 ){ |
1633 |
|
//only ground terms |
1634 |
340173 |
if( !s->isGroundEqc( eqc ) ){ |
1635 |
3941 |
return false; |
1636 |
|
} |
1637 |
6166 |
}else if( (d_match_mode & ( 1 << 2 ))!=0 ){ |
1638 |
|
//only non-ground terms |
1639 |
|
//if( s->isGroundEqc( eqc ) ){ |
1640 |
|
// return false; |
1641 |
|
//} |
1642 |
|
} |
1643 |
|
//store the match : restricted if match_mode.0 = 1 |
1644 |
342398 |
if( (d_match_mode & ( 1 << 0 ))!=0 ){ |
1645 |
|
std::map< TNode, bool >::iterator it = rev_subs.find( eqc ); |
1646 |
|
if( it==rev_subs.end() ){ |
1647 |
|
rev_subs[eqc] = true; |
1648 |
|
}else{ |
1649 |
|
return false; |
1650 |
|
} |
1651 |
|
} |
1652 |
342398 |
Assert(subs[d_typ].find(d_status_num) == subs[d_typ].end()); |
1653 |
342398 |
subs[d_typ][d_status_num] = eqc; |
1654 |
342398 |
return true; |
1655 |
|
}else{ |
1656 |
|
//clean up |
1657 |
215732 |
subs[d_typ].erase( d_status_num ); |
1658 |
215732 |
if( (d_match_mode & ( 1 << 0 ))!=0 ){ |
1659 |
|
rev_subs.erase( eqc ); |
1660 |
|
} |
1661 |
215732 |
return false; |
1662 |
|
} |
1663 |
2803291 |
}else if( d_status==2 ){ |
1664 |
9795 |
if( d_match_status==0 ){ |
1665 |
9793 |
d_match_status++; |
1666 |
9793 |
Assert(d_status_num < (int)s->getNumTgVars(d_typ)); |
1667 |
9793 |
std::map< unsigned, TNode >::iterator it = subs[d_typ].find( d_status_num ); |
1668 |
9793 |
Assert(it != subs[d_typ].end()); |
1669 |
9793 |
return it->second==eqc; |
1670 |
|
}else{ |
1671 |
2 |
return false; |
1672 |
|
} |
1673 |
2793496 |
}else if( d_status==5 ){ |
1674 |
|
//Assert( d_match_children.size()<=d_children.size() ); |
1675 |
|
//enumerating over f-applications in eqc |
1676 |
2793496 |
if( d_match_status_child_num<0 ){ |
1677 |
277689 |
return false; |
1678 |
2515807 |
}else if( d_match_status==0 ){ |
1679 |
|
//set up next binding |
1680 |
1515099 |
if( d_match_status_child_num==(int)d_match_children.size() ){ |
1681 |
1136639 |
if( d_match_status_child_num==0 ){ |
1682 |
|
//initial binding |
1683 |
880517 |
TNode f = s->getTgFunc( d_typ, d_status_num ); |
1684 |
514391 |
Assert(!eqc.isNull()); |
1685 |
514391 |
TNodeTrie* tat = s->getTermDatabase()->getTermArgTrie(eqc, f); |
1686 |
514391 |
if( tat ){ |
1687 |
366126 |
d_match_children.push_back( tat->d_data.begin() ); |
1688 |
366126 |
d_match_children_end.push_back( tat->d_data.end() ); |
1689 |
|
}else{ |
1690 |
148265 |
d_match_status++; |
1691 |
148265 |
d_match_status_child_num--; |
1692 |
148265 |
return getNextMatch( s, eqc, subs, rev_subs ); |
1693 |
|
} |
1694 |
|
}else{ |
1695 |
622248 |
d_match_children.push_back( d_match_children[d_match_status_child_num-1]->second.d_data.begin() ); |
1696 |
622248 |
d_match_children_end.push_back( d_match_children[d_match_status_child_num-1]->second.d_data.end() ); |
1697 |
|
} |
1698 |
|
} |
1699 |
1366834 |
d_match_status++; |
1700 |
1366834 |
Assert(d_match_status_child_num + 1 == (int)d_match_children.size()); |
1701 |
1366834 |
if( d_match_children[d_match_status_child_num]==d_match_children_end[d_match_status_child_num] ){ |
1702 |
|
//no more arguments to bind |
1703 |
259532 |
d_match_children.pop_back(); |
1704 |
259532 |
d_match_children_end.pop_back(); |
1705 |
259532 |
d_match_status_child_num--; |
1706 |
259532 |
return getNextMatch( s, eqc, subs, rev_subs ); |
1707 |
|
}else{ |
1708 |
1107302 |
if( d_match_status_child_num==(int)d_children.size() ){ |
1709 |
|
//successfully matched all children |
1710 |
480737 |
d_match_children.pop_back(); |
1711 |
480737 |
d_match_children_end.pop_back(); |
1712 |
480737 |
d_match_status_child_num--; |
1713 |
480737 |
return true;//return d_match_children[d_match_status]!=d_match_children_end[d_match_status]; |
1714 |
|
}else{ |
1715 |
|
//do next binding |
1716 |
626565 |
s->d_tg_alloc[d_children[d_match_status_child_num]].resetMatching( s, d_match_children[d_match_status_child_num]->first, d_match_mode ); |
1717 |
626565 |
return getNextMatch( s, eqc, subs, rev_subs ); |
1718 |
|
} |
1719 |
|
} |
1720 |
|
}else{ |
1721 |
1000708 |
Assert(d_match_status == 1); |
1722 |
1000708 |
Assert(d_match_status_child_num + 1 == (int)d_match_children.size()); |
1723 |
1000708 |
Assert(d_match_children[d_match_status_child_num] |
1724 |
|
!= d_match_children_end[d_match_status_child_num]); |
1725 |
1000708 |
d_match_status--; |
1726 |
1000708 |
if( s->d_tg_alloc[d_children[d_match_status_child_num]].getNextMatch( s, d_match_children[d_match_status_child_num]->first, subs, rev_subs ) ){ |
1727 |
622248 |
d_match_status_child_num++; |
1728 |
622248 |
return getNextMatch( s, eqc, subs, rev_subs ); |
1729 |
|
}else{ |
1730 |
|
//iterate |
1731 |
378460 |
d_match_children[d_match_status_child_num]++; |
1732 |
378460 |
return getNextMatch( s, eqc, subs, rev_subs ); |
1733 |
|
} |
1734 |
|
} |
1735 |
|
} |
1736 |
|
Assert(false); |
1737 |
|
return false; |
1738 |
|
} |
1739 |
|
|
1740 |
|
unsigned TermGenerator::getDepth( TermGenEnv * s ) { |
1741 |
|
if( d_status==5 ){ |
1742 |
|
unsigned maxd = 0; |
1743 |
|
for( unsigned i=0; i<d_children.size(); i++ ){ |
1744 |
|
unsigned d = s->d_tg_alloc[d_children[i]].getDepth( s ); |
1745 |
|
if( d>maxd ){ |
1746 |
|
maxd = d; |
1747 |
|
} |
1748 |
|
} |
1749 |
|
return 1+maxd; |
1750 |
|
}else{ |
1751 |
|
return 0; |
1752 |
|
} |
1753 |
|
} |
1754 |
|
|
1755 |
60640 |
unsigned TermGenerator::calculateGeneralizationDepth( TermGenEnv * s, std::map< TypeNode, std::vector< int > >& fvs ) { |
1756 |
60640 |
if( d_status==5 ){ |
1757 |
36729 |
unsigned sum = 1; |
1758 |
76415 |
for( unsigned i=0; i<d_children.size(); i++ ){ |
1759 |
39686 |
sum += s->d_tg_alloc[d_children[i]].calculateGeneralizationDepth( s, fvs ); |
1760 |
|
} |
1761 |
36729 |
return sum; |
1762 |
|
}else{ |
1763 |
23911 |
Assert(d_status == 2 || d_status == 1); |
1764 |
23911 |
std::map< TypeNode, std::vector< int > >::iterator it = fvs.find( d_typ ); |
1765 |
23911 |
if( it!=fvs.end() ){ |
1766 |
3252 |
if( std::find( it->second.begin(), it->second.end(), d_status_num )!=it->second.end() ){ |
1767 |
979 |
return 1; |
1768 |
|
} |
1769 |
|
} |
1770 |
22932 |
fvs[d_typ].push_back( d_status_num ); |
1771 |
22932 |
return 0; |
1772 |
|
} |
1773 |
|
} |
1774 |
|
|
1775 |
20954 |
unsigned TermGenerator::getGeneralizationDepth( TermGenEnv * s ) { |
1776 |
|
//if( s->d_gen_relevant_terms ){ |
1777 |
|
// return s->d_tg_gdepth; |
1778 |
|
//}else{ |
1779 |
41908 |
std::map< TypeNode, std::vector< int > > fvs; |
1780 |
41908 |
return calculateGeneralizationDepth( s, fvs ); |
1781 |
|
//} |
1782 |
|
} |
1783 |
|
|
1784 |
23000 |
Node TermGenerator::getTerm( TermGenEnv * s ) { |
1785 |
23000 |
if( d_status==1 || d_status==2 ){ |
1786 |
11278 |
Assert(!d_typ.isNull()); |
1787 |
11278 |
return s->getFreeVar( d_typ, d_status_num ); |
1788 |
11722 |
}else if( d_status==5 ){ |
1789 |
11722 |
Node f = s->getTgFunc( d_typ, d_status_num ); |
1790 |
11722 |
if( d_children.size()==s->d_func_args[f].size() ){ |
1791 |
23444 |
std::vector< Node > children; |
1792 |
11722 |
if( s->d_tg_func_param[f] ){ |
1793 |
11722 |
children.push_back( f ); |
1794 |
|
} |
1795 |
27079 |
for( unsigned i=0; i<d_children.size(); i++ ){ |
1796 |
30714 |
Node nc = s->d_tg_alloc[d_children[i]].getTerm( s ); |
1797 |
15357 |
if( nc.isNull() ){ |
1798 |
|
return Node::null(); |
1799 |
|
}else{ |
1800 |
|
//Assert( nc.getType()==s->d_func_args[f][i] ); |
1801 |
15357 |
children.push_back( nc ); |
1802 |
|
} |
1803 |
|
} |
1804 |
11722 |
return NodeManager::currentNM()->mkNode( s->d_func_kind[f], children ); |
1805 |
|
} |
1806 |
|
}else{ |
1807 |
|
Assert(false); |
1808 |
|
} |
1809 |
|
return Node::null(); |
1810 |
|
} |
1811 |
|
|
1812 |
78979 |
void TermGenerator::debugPrint( TermGenEnv * s, const char * c, const char * cd ) { |
1813 |
78979 |
Trace(cd) << "[*" << d_id << "," << d_status << "]:"; |
1814 |
78979 |
if( d_status==1 || d_status==2 ){ |
1815 |
29587 |
Trace(c) << s->getFreeVar( d_typ, d_status_num ); |
1816 |
49392 |
}else if( d_status==5 ){ |
1817 |
98784 |
TNode f = s->getTgFunc( d_typ, d_status_num ); |
1818 |
49392 |
Trace(c) << "(" << f; |
1819 |
102475 |
for( unsigned i=0; i<d_children.size(); i++ ){ |
1820 |
53083 |
Trace(c) << " "; |
1821 |
53083 |
s->d_tg_alloc[d_children[i]].debugPrint( s, c, cd ); |
1822 |
|
} |
1823 |
49392 |
if( d_children.size()<s->d_func_args[f].size() ){ |
1824 |
10450 |
Trace(c) << " ..."; |
1825 |
|
} |
1826 |
49392 |
Trace(c) << ")"; |
1827 |
|
}else{ |
1828 |
|
Trace(c) << "???"; |
1829 |
|
} |
1830 |
78979 |
} |
1831 |
|
|
1832 |
44 |
void TermGenEnv::collectSignatureInformation() { |
1833 |
44 |
d_typ_tg_funcs.clear(); |
1834 |
44 |
d_funcs.clear(); |
1835 |
44 |
d_func_kind.clear(); |
1836 |
44 |
d_func_args.clear(); |
1837 |
88 |
TypeNode tnull; |
1838 |
44 |
TermDb* tdb = getTermDatabase(); |
1839 |
865 |
for (size_t i = 0, nops = tdb->getNumOperators(); i < nops; i++) |
1840 |
|
{ |
1841 |
1642 |
Node op = tdb->getOperator(i); |
1842 |
821 |
DbList* dbl = tdb->getOrMkDbListForOp(op); |
1843 |
821 |
if (!dbl->d_list.empty()) |
1844 |
|
{ |
1845 |
1618 |
Node nn = dbl->d_list[0]; |
1846 |
809 |
Trace("sg-rel-sig-debug") << "Check in signature : " << nn << std::endl; |
1847 |
809 |
if( d_cg->isHandledTerm( nn ) && nn.getKind()!=APPLY_SELECTOR_TOTAL && !nn.getType().isBoolean() ){ |
1848 |
225 |
bool do_enum = true; |
1849 |
|
//check if we have enumerated ground terms |
1850 |
225 |
if( nn.getKind()==APPLY_UF ){ |
1851 |
77 |
Trace("sg-rel-sig-debug") << "Check enumeration..." << std::endl; |
1852 |
77 |
if( !d_cg->hasEnumeratedUf( nn ) ){ |
1853 |
15 |
do_enum = false; |
1854 |
|
} |
1855 |
|
} |
1856 |
225 |
if( do_enum ){ |
1857 |
210 |
Trace("sg-rel-sig-debug") << "Set enumeration..." << std::endl; |
1858 |
210 |
d_funcs.push_back(op); |
1859 |
364 |
for (const Node& nnc : nn) |
1860 |
|
{ |
1861 |
154 |
d_func_args[op].push_back(nnc.getType()); |
1862 |
|
} |
1863 |
210 |
d_func_kind[op] = nn.getKind(); |
1864 |
210 |
d_typ_tg_funcs[tnull].push_back(op); |
1865 |
210 |
d_typ_tg_funcs[nn.getType()].push_back(op); |
1866 |
210 |
d_tg_func_param[op] = |
1867 |
210 |
(nn.getMetaKind() == kind::metakind::PARAMETERIZED); |
1868 |
420 |
Trace("sg-rel-sig") |
1869 |
210 |
<< "Will enumerate function applications of : " << op |
1870 |
420 |
<< ", #args = " << d_func_args[op].size() |
1871 |
210 |
<< ", kind = " << nn.getKind() << std::endl; |
1872 |
|
} |
1873 |
|
} |
1874 |
809 |
Trace("sg-rel-sig-debug") << "Done check in signature : " << nn << std::endl; |
1875 |
|
} |
1876 |
|
} |
1877 |
|
//shuffle functions |
1878 |
144 |
for (std::map<TypeNode, std::vector<TNode> >::iterator it = |
1879 |
44 |
d_typ_tg_funcs.begin(); |
1880 |
188 |
it != d_typ_tg_funcs.end(); |
1881 |
|
++it) |
1882 |
|
{ |
1883 |
144 |
std::shuffle(it->second.begin(), it->second.end(), Random::getRandom()); |
1884 |
144 |
if (it->first.isNull()) |
1885 |
|
{ |
1886 |
38 |
Trace("sg-gen-tg-debug") << "In this order : "; |
1887 |
248 |
for (unsigned i = 0; i < it->second.size(); i++) |
1888 |
|
{ |
1889 |
210 |
Trace("sg-gen-tg-debug") << it->second[i] << " "; |
1890 |
|
} |
1891 |
38 |
Trace("sg-gen-tg-debug") << std::endl; |
1892 |
|
} |
1893 |
|
} |
1894 |
44 |
} |
1895 |
|
|
1896 |
838 |
void TermGenEnv::reset( unsigned depth, bool genRelevant, TypeNode tn ) { |
1897 |
838 |
Assert(d_tg_alloc.empty()); |
1898 |
838 |
d_tg_alloc.clear(); |
1899 |
|
|
1900 |
838 |
if( genRelevant ){ |
1901 |
363 |
for( unsigned i=0; i<2; i++ ){ |
1902 |
242 |
d_ccand_eqc[i].clear(); |
1903 |
242 |
d_ccand_eqc[i].push_back( d_relevant_eqc[i] ); |
1904 |
|
} |
1905 |
|
} |
1906 |
|
|
1907 |
838 |
d_tg_id = 0; |
1908 |
838 |
d_tg_gdepth = 0; |
1909 |
838 |
d_tg_gdepth_limit = depth; |
1910 |
838 |
d_gen_relevant_terms = genRelevant; |
1911 |
838 |
d_tg_alloc[0].reset( this, tn ); |
1912 |
838 |
} |
1913 |
|
|
1914 |
5255 |
bool TermGenEnv::getNextTerm() { |
1915 |
5255 |
if( d_tg_alloc[0].getNextTerm( this, d_tg_gdepth_limit ) ){ |
1916 |
4417 |
Assert((int)d_tg_alloc[0].getGeneralizationDepth(this) |
1917 |
|
<= d_tg_gdepth_limit); |
1918 |
4417 |
if( (int)d_tg_alloc[0].getGeneralizationDepth( this )!=d_tg_gdepth_limit ){ |
1919 |
1560 |
return getNextTerm(); |
1920 |
|
}else{ |
1921 |
2857 |
return true; |
1922 |
|
} |
1923 |
|
} |
1924 |
838 |
Trace("sg-gen-tg-debug2") << "...remove from context " << std::endl; |
1925 |
838 |
changeContext(false); |
1926 |
838 |
return false; |
1927 |
|
} |
1928 |
|
|
1929 |
|
//reset matching |
1930 |
22503 |
void TermGenEnv::resetMatching( TNode eqc, unsigned mode ) { |
1931 |
22503 |
d_tg_alloc[0].resetMatching( this, eqc, mode ); |
1932 |
22503 |
} |
1933 |
|
|
1934 |
|
//get next match |
1935 |
108129 |
bool TermGenEnv::getNextMatch( TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs ) { |
1936 |
108129 |
return d_tg_alloc[0].getNextMatch( this, eqc, subs, rev_subs ); |
1937 |
|
} |
1938 |
|
|
1939 |
|
//get term |
1940 |
2857 |
Node TermGenEnv::getTerm() { |
1941 |
2857 |
return d_tg_alloc[0].getTerm( this ); |
1942 |
|
} |
1943 |
|
|
1944 |
670 |
void TermGenEnv::debugPrint( const char * c, const char * cd ) { |
1945 |
670 |
d_tg_alloc[0].debugPrint( this, c, cd ); |
1946 |
670 |
} |
1947 |
|
|
1948 |
16785 |
unsigned TermGenEnv::getNumTgVars( TypeNode tn ) { |
1949 |
16785 |
return d_var_id[tn]; |
1950 |
|
} |
1951 |
|
|
1952 |
3539 |
bool TermGenEnv::allowVar( TypeNode tn ) { |
1953 |
3539 |
std::map< TypeNode, unsigned >::iterator it = d_var_limit.find( tn ); |
1954 |
3539 |
if( it==d_var_limit.end() ){ |
1955 |
1689 |
return true; |
1956 |
|
}else{ |
1957 |
1850 |
return d_var_id[tn]<it->second; |
1958 |
|
} |
1959 |
|
} |
1960 |
|
|
1961 |
1689 |
void TermGenEnv::addVar( TypeNode tn ) { |
1962 |
1689 |
d_var_id[tn]++; |
1963 |
1689 |
} |
1964 |
|
|
1965 |
1689 |
void TermGenEnv::removeVar( TypeNode tn ) { |
1966 |
1689 |
d_var_id[tn]--; |
1967 |
|
//d_var_eq_tg.pop_back(); |
1968 |
|
//d_var_tg.pop_back(); |
1969 |
1689 |
} |
1970 |
|
|
1971 |
6739 |
unsigned TermGenEnv::getNumTgFuncs( TypeNode tn ) { |
1972 |
6739 |
return d_typ_tg_funcs[tn].size(); |
1973 |
|
} |
1974 |
|
|
1975 |
600825 |
TNode TermGenEnv::getTgFunc( TypeNode tn, unsigned i ) { |
1976 |
600825 |
return d_typ_tg_funcs[tn][i]; |
1977 |
|
} |
1978 |
|
|
1979 |
40865 |
Node TermGenEnv::getFreeVar( TypeNode tn, unsigned i ) { |
1980 |
40865 |
return d_cg->getFreeVar( tn, i ); |
1981 |
|
} |
1982 |
|
|
1983 |
10220 |
bool TermGenEnv::considerCurrentTerm() { |
1984 |
10220 |
Assert(!d_tg_alloc.empty()); |
1985 |
|
|
1986 |
|
//if generalization depth is too large, don't consider it |
1987 |
10220 |
unsigned i = d_tg_alloc.size(); |
1988 |
10220 |
Trace("sg-gen-tg-debug") << "Consider term "; |
1989 |
10220 |
d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" ); |
1990 |
10220 |
Trace("sg-gen-tg-debug") << "? curr term size = " << d_tg_alloc.size() << ", last status = " << d_tg_alloc[i-1].d_status; |
1991 |
10220 |
Trace("sg-gen-tg-debug") << std::endl; |
1992 |
|
|
1993 |
10220 |
if( d_tg_gdepth_limit>=0 && d_tg_alloc[0].getGeneralizationDepth( this )>(unsigned)d_tg_gdepth_limit ){ |
1994 |
1900 |
Trace("sg-gen-consider-term") << "-> generalization depth of "; |
1995 |
1900 |
d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-tg-debug" ); |
1996 |
1900 |
Trace("sg-gen-consider-term") << " is too high " << d_tg_gdepth << " " << d_tg_alloc[0].getGeneralizationDepth( this ) << ", do not consider." << std::endl; |
1997 |
1900 |
return false; |
1998 |
|
} |
1999 |
|
|
2000 |
|
//----optimizations |
2001 |
|
/* |
2002 |
|
if( d_tg_alloc[i-1].d_status==1 ){ |
2003 |
|
}else if( d_tg_alloc[i-1].d_status==2 ){ |
2004 |
|
}else if( d_tg_alloc[i-1].d_status==5 ){ |
2005 |
|
}else{ |
2006 |
|
Trace("sg-gen-tg-debug") << "Bad tg: " << &d_tg_alloc[i-1] << std::endl; |
2007 |
|
Assert( false ); |
2008 |
|
} |
2009 |
|
*/ |
2010 |
|
//if equated two variables, first check if context-independent TODO |
2011 |
|
//----end optimizations |
2012 |
|
|
2013 |
|
|
2014 |
|
//check based on which candidate equivalence classes match |
2015 |
8320 |
if( d_gen_relevant_terms ){ |
2016 |
3243 |
Trace("sg-gen-tg-debug") << "Filter based on relevant ground EQC"; |
2017 |
3243 |
Trace("sg-gen-tg-debug") << ", #eqc to try = " << d_ccand_eqc[0][i-1].size() << "/" << d_ccand_eqc[1][i-1].size() << std::endl; |
2018 |
|
|
2019 |
3243 |
Assert(d_ccand_eqc[0].size() >= 2); |
2020 |
3243 |
Assert(d_ccand_eqc[0].size() == d_ccand_eqc[1].size()); |
2021 |
3243 |
Assert(d_ccand_eqc[0].size() == d_tg_id + 1); |
2022 |
3243 |
Assert(d_tg_id == d_tg_alloc.size()); |
2023 |
9729 |
for( unsigned r=0; r<2; r++ ){ |
2024 |
6486 |
d_ccand_eqc[r][i].clear(); |
2025 |
|
} |
2026 |
|
|
2027 |
|
//re-check feasibility of EQC |
2028 |
9729 |
for( unsigned r=0; r<2; r++ ){ |
2029 |
227941 |
for( unsigned j=0; j<d_ccand_eqc[r][i-1].size(); j++ ){ |
2030 |
442910 |
std::map< TypeNode, std::map< unsigned, TNode > > subs; |
2031 |
442910 |
std::map< TNode, bool > rev_subs; |
2032 |
|
unsigned mode; |
2033 |
221455 |
if( r==0 ){ |
2034 |
20352 |
mode = d_cg->optReqDistinctVarPatterns() ? ( 1 << 0 ) : 0; |
2035 |
20352 |
mode = mode | (1 << 2 ); |
2036 |
|
}else{ |
2037 |
201103 |
mode = 1 << 1; |
2038 |
|
} |
2039 |
221455 |
d_tg_alloc[0].resetMatching( this, d_ccand_eqc[r][i-1][j], mode ); |
2040 |
221455 |
if( d_tg_alloc[0].getNextMatch( this, d_ccand_eqc[r][i-1][j], subs, rev_subs ) ){ |
2041 |
115749 |
d_ccand_eqc[r][i].push_back( d_ccand_eqc[r][i-1][j] ); |
2042 |
|
} |
2043 |
|
} |
2044 |
|
} |
2045 |
9729 |
for( unsigned r=0; r<2; r++ ){ |
2046 |
6486 |
Trace("sg-gen-tg-debug") << "Current eqc of type " << r << " : "; |
2047 |
122235 |
for( unsigned j=0; j<d_ccand_eqc[r][i].size(); j++ ){ |
2048 |
115749 |
Trace("sg-gen-tg-debug") << "e" << d_cg->d_em[d_ccand_eqc[r][i][j]] << " "; |
2049 |
|
} |
2050 |
6486 |
Trace("sg-gen-tg-debug") << std::endl; |
2051 |
|
} |
2052 |
3243 |
if( options::conjectureFilterActiveTerms() && d_ccand_eqc[0][i].empty() ){ |
2053 |
859 |
Trace("sg-gen-consider-term") << "Do not consider term of form "; |
2054 |
859 |
d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-consider-term-debug" ); |
2055 |
859 |
Trace("sg-gen-consider-term") << " since no relevant EQC matches it." << std::endl; |
2056 |
859 |
return false; |
2057 |
|
} |
2058 |
2384 |
if( options::conjectureFilterModel() && d_ccand_eqc[1][i].empty() ){ |
2059 |
54 |
Trace("sg-gen-consider-term") << "Do not consider term of form "; |
2060 |
54 |
d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-consider-term-debug" ); |
2061 |
54 |
Trace("sg-gen-consider-term") << " since no ground EQC matches it." << std::endl; |
2062 |
54 |
return false; |
2063 |
|
} |
2064 |
|
} |
2065 |
7407 |
Trace("sg-gen-tg-debug") << "Will consider term "; |
2066 |
7407 |
d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" ); |
2067 |
7407 |
Trace("sg-gen-tg-debug") << std::endl; |
2068 |
7407 |
Trace("sg-gen-consider-term-debug") << std::endl; |
2069 |
7407 |
return true; |
2070 |
|
} |
2071 |
|
|
2072 |
7320 |
void TermGenEnv::changeContext( bool add ) { |
2073 |
7320 |
if( add ){ |
2074 |
10980 |
for( unsigned r=0; r<2; r++ ){ |
2075 |
7320 |
d_ccand_eqc[r].push_back( std::vector< TNode >() ); |
2076 |
|
} |
2077 |
3660 |
d_tg_id++; |
2078 |
|
}else{ |
2079 |
10980 |
for( unsigned r=0; r<2; r++ ){ |
2080 |
7320 |
d_ccand_eqc[r].pop_back(); |
2081 |
|
} |
2082 |
3660 |
d_tg_id--; |
2083 |
3660 |
Assert(d_tg_alloc.find(d_tg_id) != d_tg_alloc.end()); |
2084 |
3660 |
d_tg_alloc.erase( d_tg_id ); |
2085 |
|
} |
2086 |
7320 |
} |
2087 |
|
|
2088 |
5888 |
bool TermGenEnv::considerCurrentTermCanon( unsigned tg_id ){ |
2089 |
5888 |
Assert(tg_id < d_tg_alloc.size()); |
2090 |
5888 |
if( options::conjectureFilterCanonical() ){ |
2091 |
|
//check based on a canonicity of the term (if there is one) |
2092 |
4786 |
Trace("sg-gen-tg-debug") << "Consider term canon "; |
2093 |
4786 |
d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" ); |
2094 |
4786 |
Trace("sg-gen-tg-debug") << ", tg is [" << tg_id << "]..." << std::endl; |
2095 |
|
|
2096 |
9572 |
Node ln = d_tg_alloc[tg_id].getTerm( this ); |
2097 |
4786 |
Trace("sg-gen-tg-debug") << "Term is " << ln << std::endl; |
2098 |
4786 |
return d_cg->considerTermCanon( ln, d_gen_relevant_terms ); |
2099 |
|
} |
2100 |
1102 |
return true; |
2101 |
|
} |
2102 |
|
|
2103 |
3488 |
bool TermGenEnv::isRelevantFunc( Node f ) { |
2104 |
3488 |
return std::find( d_funcs.begin(), d_funcs.end(), f )!=d_funcs.end(); |
2105 |
|
} |
2106 |
|
|
2107 |
958 |
bool TermGenEnv::isRelevantTerm( Node t ) { |
2108 |
958 |
if( t.getKind()!=BOUND_VARIABLE ){ |
2109 |
658 |
if( t.getKind()!=EQUAL ){ |
2110 |
489 |
if( t.hasOperator() ){ |
2111 |
901 |
TNode op = t.getOperator(); |
2112 |
485 |
if( !isRelevantFunc( op ) ){ |
2113 |
69 |
return false; |
2114 |
|
} |
2115 |
|
}else{ |
2116 |
4 |
return false; |
2117 |
|
} |
2118 |
|
} |
2119 |
1293 |
for( unsigned i=0; i<t.getNumChildren(); i++ ){ |
2120 |
793 |
if( !isRelevantTerm( t[i] ) ){ |
2121 |
85 |
return false; |
2122 |
|
} |
2123 |
|
} |
2124 |
|
} |
2125 |
800 |
return true; |
2126 |
|
} |
2127 |
|
|
2128 |
514435 |
TermDb * TermGenEnv::getTermDatabase() { |
2129 |
514435 |
return d_cg->getTermDatabase(); |
2130 |
|
} |
2131 |
|
Node TermGenEnv::getGroundEqc( TNode r ) { |
2132 |
|
return d_cg->getGroundEqc( r ); |
2133 |
|
} |
2134 |
340173 |
bool TermGenEnv::isGroundEqc( TNode r ){ |
2135 |
340173 |
return d_cg->isGroundEqc( r ); |
2136 |
|
} |
2137 |
|
bool TermGenEnv::isGroundTerm( TNode n ){ |
2138 |
|
return d_cg->isGroundTerm( n ); |
2139 |
|
} |
2140 |
|
|
2141 |
|
|
2142 |
274525 |
void SubstitutionIndex::addSubstitution( TNode eqc, std::vector< TNode >& vars, std::vector< TNode >& terms, unsigned i ) { |
2143 |
274525 |
if( i==vars.size() ){ |
2144 |
85626 |
d_var = eqc; |
2145 |
|
}else{ |
2146 |
188899 |
Assert(d_var.isNull() || d_var == vars[i]); |
2147 |
188899 |
d_var = vars[i]; |
2148 |
188899 |
d_children[terms[i]].addSubstitution( eqc, vars, terms, i+1 ); |
2149 |
|
} |
2150 |
274525 |
} |
2151 |
|
|
2152 |
1157231 |
bool SubstitutionIndex::notifySubstitutions( ConjectureGenerator * s, std::map< TNode, TNode >& subs, TNode rhs, unsigned numVars, unsigned i ) { |
2153 |
1157231 |
if( i==numVars ){ |
2154 |
860201 |
Assert(d_children.empty()); |
2155 |
860201 |
return s->notifySubstitution( d_var, subs, rhs ); |
2156 |
|
}else{ |
2157 |
297030 |
Assert(i == 0 || !d_children.empty()); |
2158 |
1429672 |
for( std::map< TNode, SubstitutionIndex >::iterator it = d_children.begin(); it != d_children.end(); ++it ){ |
2159 |
1145025 |
Trace("sg-cconj-debug2") << "Try " << d_var << " -> " << it->first << " (" << i << "/" << numVars << ")" << std::endl; |
2160 |
1145025 |
subs[d_var] = it->first; |
2161 |
1145025 |
if( !it->second.notifySubstitutions( s, subs, rhs, numVars, i+1 ) ){ |
2162 |
12383 |
return false; |
2163 |
|
} |
2164 |
|
} |
2165 |
284647 |
return true; |
2166 |
|
} |
2167 |
|
} |
2168 |
|
|
2169 |
|
|
2170 |
506 |
void TheoremIndex::addTheorem( std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs ){ |
2171 |
506 |
if( lhs_v.empty() ){ |
2172 |
92 |
if( std::find( d_terms.begin(), d_terms.end(), rhs )==d_terms.end() ){ |
2173 |
92 |
d_terms.push_back( rhs ); |
2174 |
|
} |
2175 |
|
}else{ |
2176 |
414 |
unsigned index = lhs_v.size()-1; |
2177 |
414 |
if( lhs_arg[index]==lhs_v[index].getNumChildren() ){ |
2178 |
184 |
lhs_v.pop_back(); |
2179 |
184 |
lhs_arg.pop_back(); |
2180 |
184 |
addTheorem( lhs_v, lhs_arg, rhs ); |
2181 |
|
}else{ |
2182 |
230 |
lhs_arg[index]++; |
2183 |
230 |
addTheoremNode( lhs_v[index][lhs_arg[index]-1], lhs_v, lhs_arg, rhs ); |
2184 |
|
} |
2185 |
|
} |
2186 |
506 |
} |
2187 |
|
|
2188 |
322 |
void TheoremIndex::addTheoremNode( TNode curr, std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs ){ |
2189 |
322 |
Trace("thm-db-debug") << "Adding conjecture for subterm " << curr << "..." << std::endl; |
2190 |
322 |
if( curr.hasOperator() ){ |
2191 |
184 |
lhs_v.push_back( curr ); |
2192 |
184 |
lhs_arg.push_back( 0 ); |
2193 |
184 |
d_children[curr.getOperator()].addTheorem( lhs_v, lhs_arg, rhs ); |
2194 |
|
}else{ |
2195 |
138 |
Assert(curr.getKind() == kind::BOUND_VARIABLE); |
2196 |
276 |
TypeNode tn = curr.getType(); |
2197 |
138 |
Assert(d_var[tn].isNull() || d_var[tn] == curr); |
2198 |
138 |
d_var[tn] = curr; |
2199 |
138 |
d_children[curr].addTheorem( lhs_v, lhs_arg, rhs ); |
2200 |
|
} |
2201 |
322 |
} |
2202 |
|
|
2203 |
2280 |
void TheoremIndex::getEquivalentTerms( std::vector< TNode >& n_v, std::vector< unsigned >& n_arg, |
2204 |
|
std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs, |
2205 |
|
std::vector< Node >& terms ) { |
2206 |
2280 |
Trace("thm-db-debug") << "Get equivalent terms " << n_v.size() << " " << n_arg.size() << std::endl; |
2207 |
2280 |
if( n_v.empty() ){ |
2208 |
166 |
Trace("thm-db-debug") << "Number of terms : " << d_terms.size() << std::endl; |
2209 |
|
//apply substutitions to RHS's |
2210 |
332 |
for( unsigned i=0; i<d_terms.size(); i++ ){ |
2211 |
332 |
Node n = d_terms[i].substitute( vars.begin(), vars.end(), subs.begin(), subs.end() ); |
2212 |
166 |
terms.push_back( n ); |
2213 |
|
} |
2214 |
|
}else{ |
2215 |
2114 |
unsigned index = n_v.size()-1; |
2216 |
2114 |
if( n_arg[index]==n_v[index].getNumChildren() ){ |
2217 |
332 |
n_v.pop_back(); |
2218 |
332 |
n_arg.pop_back(); |
2219 |
332 |
getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms ); |
2220 |
|
}else{ |
2221 |
1782 |
n_arg[index]++; |
2222 |
1782 |
getEquivalentTermsNode( n_v[index][n_arg[index]-1], n_v, n_arg, smap, vars, subs, terms ); |
2223 |
|
} |
2224 |
|
} |
2225 |
2280 |
} |
2226 |
|
|
2227 |
3400 |
void TheoremIndex::getEquivalentTermsNode( Node curr, std::vector< TNode >& n_v, std::vector< unsigned >& n_arg, |
2228 |
|
std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs, |
2229 |
|
std::vector< Node >& terms ) { |
2230 |
3400 |
Trace("thm-db-debug") << "Get equivalent based on subterm " << curr << "..." << std::endl; |
2231 |
3400 |
if( curr.hasOperator() ){ |
2232 |
2379 |
Trace("thm-db-debug") << "Check based on operator..." << std::endl; |
2233 |
2379 |
std::map< TNode, TheoremIndex >::iterator it = d_children.find( curr.getOperator() ); |
2234 |
2379 |
if( it!=d_children.end() ){ |
2235 |
1143 |
n_v.push_back( curr ); |
2236 |
1143 |
n_arg.push_back( 0 ); |
2237 |
1143 |
it->second.getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms ); |
2238 |
|
} |
2239 |
2379 |
Trace("thm-db-debug") << "...done check based on operator" << std::endl; |
2240 |
|
} |
2241 |
6800 |
TypeNode tn = curr.getType(); |
2242 |
3400 |
std::map< TypeNode, TNode >::iterator itt = d_var.find( tn ); |
2243 |
3400 |
if( itt!=d_var.end() ){ |
2244 |
805 |
Trace("thm-db-debug") << "Check for substitution with " << itt->second << "..." << std::endl; |
2245 |
805 |
Assert(curr.getType() == itt->second.getType()); |
2246 |
|
//add to substitution if possible |
2247 |
805 |
bool success = false; |
2248 |
805 |
std::map< TNode, TNode >::iterator it = smap.find( itt->second ); |
2249 |
805 |
if( it==smap.end() ){ |
2250 |
805 |
smap[itt->second] = curr; |
2251 |
805 |
vars.push_back( itt->second ); |
2252 |
805 |
subs.push_back( curr ); |
2253 |
805 |
success = true; |
2254 |
|
}else if( it->second==curr ){ |
2255 |
|
success = true; |
2256 |
|
}else{ |
2257 |
|
//also check modulo equality (in universal equality engine) |
2258 |
|
} |
2259 |
805 |
Trace("thm-db-debug") << "...check for substitution with " << itt->second << ", success = " << success << "." << std::endl; |
2260 |
805 |
if( success ){ |
2261 |
805 |
d_children[itt->second].getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms ); |
2262 |
|
} |
2263 |
|
} |
2264 |
3400 |
} |
2265 |
|
|
2266 |
338 |
void TheoremIndex::debugPrint( const char * c, unsigned ind ) { |
2267 |
632 |
for( std::map< TNode, TheoremIndex >::iterator it = d_children.begin(); it != d_children.end(); ++it ){ |
2268 |
294 |
for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; } |
2269 |
294 |
Trace(c) << it->first << std::endl; |
2270 |
294 |
it->second.debugPrint( c, ind+1 ); |
2271 |
|
} |
2272 |
338 |
if( !d_terms.empty() ){ |
2273 |
92 |
for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; } |
2274 |
92 |
Trace(c) << "{"; |
2275 |
184 |
for( unsigned i=0; i<d_terms.size(); i++ ){ |
2276 |
92 |
Trace(c) << " " << d_terms[i]; |
2277 |
|
} |
2278 |
92 |
Trace(c) << " }" << std::endl; |
2279 |
|
} |
2280 |
|
//if( !d_var.isNull() ){ |
2281 |
|
// for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; } |
2282 |
|
// Trace(c) << "var:" << d_var << std::endl; |
2283 |
|
//} |
2284 |
338 |
} |
2285 |
|
|
2286 |
20352 |
bool ConjectureGenerator::optReqDistinctVarPatterns() { return false; } |
2287 |
3480 |
bool ConjectureGenerator::optFilterUnknown() { return true; } //may change |
2288 |
34 |
int ConjectureGenerator::optFilterScoreThreshold() { return 1; } |
2289 |
44 |
unsigned ConjectureGenerator::optFullCheckFrequency() { return 1; } |
2290 |
|
|
2291 |
44 |
bool ConjectureGenerator::optStatsOnly() { return false; } |
2292 |
|
|
2293 |
31137 |
} // namespace cvc5 |