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