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