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