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