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