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