GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/conjecture_generator.cpp Lines: 1255 1416 88.6 %
Date: 2021-11-07 Branches: 2547 5974 42.6 %

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