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