GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/cegqi/ceg_instantiator.h Lines: 43 57 75.4 %
Date: 2021-08-14 Branches: 16 28 57.1 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Mathias Preiner, Tim King
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
 * Counterexample-guided quantifier instantiation.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__QUANTIFIERS__CEG_INSTANTIATOR_H
19
#define CVC5__THEORY__QUANTIFIERS__CEG_INSTANTIATOR_H
20
21
#include <vector>
22
23
#include "expr/node.h"
24
#include "theory/inference_id.h"
25
#include "util/statistics_stats.h"
26
27
namespace cvc5 {
28
namespace theory {
29
namespace quantifiers {
30
31
class Instantiator;
32
class InstantiatorPreprocess;
33
class InstStrategyCegqi;
34
class QuantifiersState;
35
class TermRegistry;
36
37
/**
38
 * Descriptions of the types of constraints that a term was solved for in.
39
 */
40
enum CegTermType
41
{
42
  // invalid
43
  CEG_TT_INVALID,
44
  // term was the result of solving an equality
45
  CEG_TT_EQUAL,
46
  // term was the result of solving a non-strict lower bound x >= t
47
  CEG_TT_LOWER,
48
  // term was the result of solving a strict lower bound x > t
49
  CEG_TT_LOWER_STRICT,
50
  // term was the result of solving a non-strict upper bound x <= t
51
  CEG_TT_UPPER,
52
  // term was the result of solving a strict upper bound x < t
53
  CEG_TT_UPPER_STRICT,
54
};
55
/** make (non-strict term type) c a strict term type */
56
CegTermType mkStrictCTT(CegTermType c);
57
/** negate c (lower/upper bounds are swapped) */
58
CegTermType mkNegateCTT(CegTermType c);
59
/** is c a strict term type? */
60
bool isStrictCTT(CegTermType c);
61
/** is c a lower bound? */
62
bool isLowerBoundCTT(CegTermType c);
63
/** is c an upper bound? */
64
bool isUpperBoundCTT(CegTermType c);
65
66
/** Term Properties
67
 *
68
 * Stores properties for a variable to solve for in counterexample-guided
69
 * instantiation.
70
 *
71
 * For LIA, this includes the coefficient of the variable, and the bound type
72
 * for the variable.
73
 */
74
2125364
class TermProperties {
75
 public:
76
848648
  TermProperties() : d_type(CEG_TT_EQUAL) {}
77
2973966
  virtual ~TermProperties() {}
78
79
  /**
80
   * Type for the solution term. For arithmetic this corresponds to bound type
81
   * of the constraint that the constraint the term was solved for in.
82
   */
83
  CegTermType d_type;
84
  // for arithmetic
85
  Node d_coeff;
86
  // get cache node
87
  // we consider terms + TermProperties that are unique up to their cache node
88
  // (see constructInstantiationInc)
89
40941
  virtual Node getCacheNode() const { return d_coeff; }
90
  // is non-basic
91
122631
  virtual bool isBasic() const { return d_coeff.isNull(); }
92
  // get modified term
93
3993
  virtual Node getModifiedTerm( Node pv ) const {
94
3993
    if( !d_coeff.isNull() ){
95
243
      return NodeManager::currentNM()->mkNode( kind::MULT, d_coeff, pv );
96
    }else{
97
3750
      return pv;
98
    }
99
  }
100
  // compose property, should be such that:
101
  //   p.getModifiedTerm( this.getModifiedTerm( x ) ) = this_updated.getModifiedTerm( x )
102
  virtual void composeProperty(TermProperties& p);
103
};
104
105
/** Solved form
106
 *  This specifies a substitution:
107
 *  { d_props[i].getModifiedTerm(d_vars[i]) -> d_subs[i] | i = 0...|d_vars| }
108
 */
109
15746
class SolvedForm {
110
public:
111
  // list of variables
112
  std::vector< Node > d_vars;
113
  // list of terms that they are substituted to
114
  std::vector< Node > d_subs;
115
  // properties for each variable
116
  std::vector< TermProperties > d_props;
117
  // the variables that have non-basic information regarding how they are substituted
118
  //   an example is for linear arithmetic, we store "substitution with coefficients".
119
  std::vector<Node> d_non_basic;
120
  // push the substitution pv_prop.getModifiedTerm(pv) -> n
121
  void push_back(Node pv, Node n, TermProperties& pv_prop);
122
  // pop the substitution pv_prop.getModifiedTerm(pv) -> n
123
  void pop_back(Node pv, Node n, TermProperties& pv_prop);
124
  // is this solved form empty?
125
2278
  bool empty() { return d_vars.empty(); }
126
public:
127
  // theta values (for LIA, see Section 4 of Reynolds/King/Kuncak FMSD 2017)
128
  std::vector< Node > d_theta;
129
  // get the current value for theta (for LIA, see Section 4 of Reynolds/King/Kuncak FMSD 2017)
130
23204
  Node getTheta() {
131
23204
    if( d_theta.empty() ){
132
22890
      return Node::null();
133
    }else{
134
314
      return d_theta[d_theta.size()-1];
135
    }
136
  }
137
};
138
139
/** instantiation effort levels
140
 *
141
 * This effort is used to stratify the construction of
142
 * instantiations for some theories that may result to
143
 * using model value instantiations.
144
 */
145
enum CegInstEffort
146
{
147
  // uninitialized
148
  CEG_INST_EFFORT_NONE,
149
  // standard effort level
150
  CEG_INST_EFFORT_STANDARD,
151
  // standard effort level, but we have used model values
152
  CEG_INST_EFFORT_STANDARD_MV,
153
  // full effort level
154
  CEG_INST_EFFORT_FULL
155
};
156
157
std::ostream& operator<<(std::ostream& os, CegInstEffort e);
158
159
/** instantiation phase for variables
160
 *
161
 * This indicates the phase in which we constructed
162
 * a substitution for individual variables.
163
 */
164
enum CegInstPhase
165
{
166
  // uninitialized
167
  CEG_INST_PHASE_NONE,
168
  // instantiation constructed during traversal of equivalence classes
169
  CEG_INST_PHASE_EQC,
170
  // instantiation constructed during solving equalities
171
  CEG_INST_PHASE_EQUAL,
172
  // instantiation constructed by looking at theory assertions
173
  CEG_INST_PHASE_ASSERTION,
174
  // instantiation constructed by querying model value
175
  CEG_INST_PHASE_MVALUE,
176
};
177
178
std::ostream& operator<<(std::ostream& os, CegInstPhase phase);
179
180
/**
181
 * The handled status of a sort/term/quantified formula, indicating whether
182
 * counterexample-guided instantiation handles it.
183
 */
184
enum CegHandledStatus
185
{
186
  // the sort/term/quantified formula is unhandled by cegqi
187
  CEG_UNHANDLED,
188
  // the sort/term/quantified formula is partially handled by cegqi
189
  CEG_PARTIALLY_HANDLED,
190
  // the sort/term/quantified formula is handled by cegqi
191
  CEG_HANDLED,
192
  // the sort/term/quantified formula is handled by cegqi, regardless of
193
  // additional factors
194
  CEG_HANDLED_UNCONDITIONAL,
195
};
196
std::ostream& operator<<(std::ostream& os, CegHandledStatus status);
197
198
/** Ceg instantiator
199
 *
200
 * This class manages counterexample-guided quantifier instantiation
201
 * for a single quantified formula.
202
 *
203
 * For details on counterexample-guided quantifier instantiation
204
 * (for linear arithmetic), see Reynolds/King/Kuncak FMSD 2017.
205
 */
206
class CegInstantiator {
207
 public:
208
  /**
209
   * The instantiator will be constructing instantiations for quantified formula
210
   * q, parent is the owner of this object.
211
   */
212
  CegInstantiator(Node q,
213
                  QuantifiersState& qs,
214
                  TermRegistry& tr,
215
                  InstStrategyCegqi* parent);
216
  virtual ~CegInstantiator();
217
  /** check
218
   * This adds instantiations based on the state of d_vars in current context
219
   * on the output channel d_out of this class.
220
   */
221
  bool check();
222
  /** Register the counterexample lemma
223
   *
224
   * @param lem contains the counterexample lemma of the quantified formula we
225
   * are processing. The counterexample lemma is the formula { ~phi[e/x] } in
226
   * Figure 1 of Reynolds et al. FMSD 2017.
227
   * @param ce_vars contains the variables e. Notice these are variables of
228
   * INST_CONSTANT kind, since we do not permit bound variables in assertions.
229
   * This method may add additional variables to this vector if it decides there
230
   * are additional auxiliary variables to solve for.
231
   * @param auxLems : if this method decides that additional lemmas should be
232
   * sent on the output channel, they are added to this vector, and sent out by
233
   * the caller of this method.
234
   */
235
  void registerCounterexampleLemma(Node lem,
236
                                   std::vector<Node>& ce_vars,
237
                                   std::vector<Node>& auxLems);
238
  //------------------------------interface for instantiators
239
  /** push stack variable
240
   * This adds a new variable to solve for in the stack
241
   * of variables we are processing. This stack is only
242
   * used for datatypes, where e.g. the DtInstantiator
243
   * solving for a list x may push the stack "variables"
244
   * head(x) and tail(x).
245
   */
246
  void pushStackVariable(Node v);
247
  /** pop stack variable */
248
  void popStackVariable();
249
  /** construct instantiation increment
250
   *
251
   * Adds the substitution { pv_prop.getModifiedTerm(pv) -> n } to the current
252
   * instantiation, specified by sf.
253
   *
254
   * This function returns true if a call to
255
   * Instantiate::addInstantiation(...)
256
   * was successfully made in a recursive call.
257
   *
258
   * The solved form sf is reverted to its original state if
259
   *   this function returns false, or
260
   *   revertOnSuccess is true and this function returns true.
261
   */
262
  bool constructInstantiationInc(Node pv,
263
                                 Node n,
264
                                 TermProperties& pv_prop,
265
                                 SolvedForm& sf,
266
                                 bool revertOnSuccess = false);
267
  /** get the current model value of term n */
268
  Node getModelValue(Node n);
269
  /** get bound variable for type
270
   *
271
   * This gets the next (canonical) bound variable of
272
   * type tn. This can be used for instance when
273
   * constructing instantiations that involve witness expressions.
274
   */
275
  Node getBoundVariable(TypeNode tn);
276
  /** has this assertion been marked as solved? */
277
  bool isSolvedAssertion(Node n) const;
278
  /** marked solved */
279
  void markSolved(Node n, bool solved = true);
280
  //------------------------------end interface for instantiators
281
282
  /**
283
   * Get the number of atoms in the counterexample lemma of the quantified
284
   * formula we are processing with this class.
285
   */
286
  unsigned getNumCEAtoms() { return d_ce_atoms.size(); }
287
  /**
288
   * Get the i^th atom of the counterexample lemma of the quantified
289
   * formula we are processing with this class.
290
   */
291
  Node getCEAtom(unsigned i) { return d_ce_atoms[i]; }
292
  /** is n a term that is eligible for instantiation? */
293
  bool isEligible(Node n);
294
  /** does n have variable pv? */
295
  bool hasVariable(Node n, Node pv);
296
  /** are we processing a nested quantified formula? */
297
3112
  bool hasNestedQuantification() const { return d_is_nested_quant; }
298
  /**
299
   * Are we allowed to instantiate the current quantified formula with n? This
300
   * includes restrictions such as if n is a variable, it must occur free in
301
   * the current quantified formula.
302
   */
303
  bool isEligibleForInstantiation(Node n) const;
304
  //------------------------------------ static queries
305
  /** Is k a kind for which counterexample-guided instantiation is possible?
306
   *
307
   * If this method returns CEG_UNHANDLED, then we prohibit cegqi for terms
308
   * involving this kind. If this method returns CEG_HANDLED, our approaches
309
   * for cegqi fully handle the kind.
310
   *
311
   * This typically corresponds to kinds that correspond to operators that
312
   * have total interpretations and are a part of the signature of
313
   * satisfaction complete theories (see Reynolds et al., CAV 2015).
314
   */
315
  static CegHandledStatus isCbqiKind(Kind k);
316
  /** is cbqi term?
317
   *
318
   * This method returns whether the term is handled by cegqi techniques, i.e.
319
   * whether all subterms of n have kinds that can be handled by cegqi.
320
   */
321
  static CegHandledStatus isCbqiTerm(Node n);
322
  /** is cbqi sort?
323
   *
324
   * This method returns whether the type tn is handled by cegqi techniques.
325
   * If the result is CEG_HANDLED_UNCONDITIONAL, then this indicates that a
326
   * variable of this type is handled regardless of the formula it appears in.
327
   */
328
  static CegHandledStatus isCbqiSort(TypeNode tn);
329
  /** is cbqi quantifier prefix
330
   *
331
   * This returns the minimum value of the above method for a bound variable
332
   * in the prefix of quantified formula q.
333
   */
334
  static CegHandledStatus isCbqiQuantPrefix(Node q);
335
  /** is cbqi quantified formula
336
   *
337
   * This returns whether quantified formula q can and should be handled by
338
   * counterexample-guided instantiation. If this function returns
339
   * a status CEG_HANDLED or above, then q is fully handled by counterexample
340
   * guided quantifier instantiation and need not be processed by any other
341
   * strategy for quantifiers (e.g. E-matching). Otherwise, if this function
342
   * returns CEG_PARTIALLY_HANDLED, then it may be worthwhile to handle the
343
   * quantified formula using cegqi, however other strategies should also be
344
   * tried.
345
   */
346
  static CegHandledStatus isCbqiQuant(Node q);
347
  //------------------------------------ end static queries
348
 private:
349
  /** The quantified formula of this instantiator */
350
  Node d_quant;
351
  /** Reference to the quantifiers state */
352
  QuantifiersState& d_qstate;
353
  /** Reference to the term registry */
354
  TermRegistry& d_treg;
355
  /** The parent of this instantiator */
356
  InstStrategyCegqi* d_parent;
357
358
  //-------------------------------globally cached
359
  /** cache from nodes to the set of variables it contains
360
    * (from the quantified formula we are instantiating).
361
    */
362
  std::unordered_map<Node, std::unordered_set<Node>> d_prog_var;
363
  /** cache of the set of terms that we have established are
364
   * ineligible for instantiation.
365
    */
366
  std::unordered_set<Node> d_inelig;
367
  /** ensures n is in d_prog_var and d_inelig. */
368
  void computeProgVars(Node n);
369
  //-------------------------------end globally cached
370
371
  //-------------------------------cached per round
372
  /** current assertions per theory */
373
  std::map<TheoryId, std::vector<Node> > d_curr_asserts;
374
  /** map from representatives to the terms in their equivalence class */
375
  std::map<Node, std::vector<Node> > d_curr_eqc;
376
  /** map from types to representatives of that type */
377
  std::map<TypeNode, std::vector<Node> > d_curr_type_eqc;
378
  /** solved asserts */
379
  std::unordered_set<Node> d_solved_asserts;
380
  /** process assertions
381
   * This is called once at the beginning of check to
382
   * set up all necessary information for constructing instantiations,
383
   * such as the above data structures.
384
   */
385
  void processAssertions();
386
  /** cache bound variables for type returned
387
   * by getBoundVariable(...).
388
   */
389
  std::unordered_map<TypeNode, std::vector<Node>> d_bound_var;
390
  /** current index of bound variables for type.
391
   * The next call to getBoundVariable(...) for
392
   * type tn returns the d_bound_var_index[tn]^th
393
   * element of d_bound_var[tn], or a fresh variable
394
   * if not in bounds.
395
   */
396
  std::unordered_map<TypeNode, unsigned> d_bound_var_index;
397
  //-------------------------------end cached per round
398
399
  //-------------------------------data per theory
400
  /** relevant theory ids
401
   * A list of theory ids that contain at least one
402
   * constraint in the body of the quantified formula we
403
   * are processing.
404
   */
405
  std::vector<TheoryId> d_tids;
406
  /** map from theory ids to instantiator preprocessors */
407
  std::map<TheoryId, InstantiatorPreprocess*> d_tipp;
408
  /** registers all theory ids associated with type tn
409
   *
410
   * This recursively calls registerTheoryId for typeOf(tn') for
411
   * all parameters and datatype subfields of type tn.
412
   * visited stores the types we have already visited.
413
   */
414
  void registerTheoryIds(TypeNode tn, std::map<TypeNode, bool>& visited);
415
  /** register theory id tid
416
   *
417
   * This is called when the quantified formula we are processing
418
   * with this class involves theory tid. In this case, we will
419
   * construct instantiations based on the assertion list of this theory.
420
   */
421
  void registerTheoryId(TheoryId tid);
422
  //-------------------------------end data per theory
423
424
  //-------------------------------the variables
425
  /** the variables we are instantiating
426
   *
427
   * This is a superset of the variables for the instantiations we are
428
   * generating and sending on the output channel of this class.
429
   */
430
  std::vector<Node> d_vars;
431
  /** set form of d_vars */
432
  std::unordered_set<Node> d_vars_set;
433
  /** index of variables reported in instantiation */
434
  std::vector<unsigned> d_var_order_index;
435
  /** number of input variables
436
   *
437
   * These are the variables, in order, for the instantiations we are generating
438
   * and sending on the output channel of this class.
439
   */
440
  std::vector<Node> d_input_vars;
441
  /** register variable */
442
  void registerVariable(Node v);
443
  //-------------------------------the variables
444
445
  //-------------------------------quantified formula info
446
  /** are we processing a nested quantified formula? */
447
  bool d_is_nested_quant;
448
  /** the atoms of the CE lemma */
449
  std::vector<Node> d_ce_atoms;
450
  /** collect atoms */
451
  void collectCeAtoms(Node n, std::map<Node, bool>& visited);
452
  //-------------------------------end quantified formula info
453
454
  //-------------------------------current state
455
  /** the current effort level of the instantiator
456
   * This indicates the effort Instantiator objects
457
   * will put into the terms they return.
458
   */
459
  CegInstEffort d_effort;
460
  /** for each variable, the instantiator used for that variable */
461
  std::map<Node, Instantiator*> d_active_instantiators;
462
  /** map from variables to the index in the prefix of the quantified
463
   * formula we are processing.
464
   */
465
  std::map<Node, unsigned> d_curr_index;
466
  /** map from variables to the phase in which we instantiated them */
467
  std::map<Node, CegInstPhase> d_curr_iphase;
468
  /** cache of current substitutions tried between activate/deactivate */
469
  std::map<Node, std::map<Node, std::map<Node, bool> > > d_curr_subs_proc;
470
  /** stack of temporary variables we are solving for,
471
   * e.g. subfields of datatypes.
472
   */
473
  std::vector<Node> d_stack_vars;
474
  /** activate instantiation variable v at index
475
   *
476
   * This is called when variable (inst constant) v is activated
477
   * for the quantified formula we are processing.
478
   * This method initializes the instantiator class for
479
   * that variable if necessary, where this class is
480
   * determined by the type of v. It also initializes
481
   * the cache of values we have tried substituting for v
482
   * (in d_curr_subs_proc), and stores its index.
483
   */
484
  void activateInstantiationVariable(Node v, unsigned index);
485
  /** deactivate instantiation variable
486
   *
487
   * This is called when variable (inst constant) v is deactivated
488
   * for the quantified formula we are processing.
489
   */
490
  void deactivateInstantiationVariable(Node v);
491
  /**
492
   * Have we tried an instantiation for v after the last call to
493
   * activateInstantiationVariable.
494
   */
495
  bool hasTriedInstantiation(Node v);
496
  //-------------------------------end current state
497
498
  //---------------------------------for applying substitutions
499
  /** can use basic substitution */
500
  bool canApplyBasicSubstitution( Node n, std::vector< Node >& non_basic );
501
  /** apply substitution
502
  * We wish to process the substitution:
503
  *   ( pv = n * sf )
504
  * where pv is a variable with type tn, and * denotes application of substitution.
505
  * The return value "ret" and pv_prop is such that the above equality is equivalent to
506
  *   ( pv_prop.getModifiedTerm(pv) = ret )
507
  */
508
675075
  Node applySubstitution( TypeNode tn, Node n, SolvedForm& sf, TermProperties& pv_prop, bool try_coeff = true ) {
509
675075
    return applySubstitution( tn, n, sf.d_vars, sf.d_subs, sf.d_props, sf.d_non_basic, pv_prop, try_coeff );
510
  }
511
  /** apply substitution, with solved form expanded to subs/prop/non_basic/vars */
512
  Node applySubstitution( TypeNode tn, Node n, std::vector< Node >& vars, std::vector< Node >& subs, std::vector< TermProperties >& prop,
513
                          std::vector< Node >& non_basic, TermProperties& pv_prop, bool try_coeff = true );
514
  /** apply substitution to literal lit
515
  * The return value is equivalent to ( lit * sf )
516
  * where * denotes application of substitution.
517
  */
518
427561
  Node applySubstitutionToLiteral( Node lit, SolvedForm& sf ) {
519
427561
    return applySubstitutionToLiteral( lit, sf.d_vars, sf.d_subs, sf.d_props, sf.d_non_basic );
520
  }
521
  /** apply substitution to literal lit, with solved form expanded to subs/prop/non_basic/vars */
522
  Node applySubstitutionToLiteral( Node lit, std::vector< Node >& vars, std::vector< Node >& subs, std::vector< TermProperties >& prop,
523
                                   std::vector< Node >& non_basic );
524
  //---------------------------------end for applying substitutions
525
526
  /** map from variables to their instantiators */
527
  std::map<Node, Instantiator*> d_instantiator;
528
529
  /** construct instantiation
530
   *
531
   * This method attempts to find a term for the i^th variable in d_vars to
532
   * include in the current instantiation, given by sf.
533
   *
534
   * It returns true if a successful call to the output channel's
535
   * doAddInstantiation was made.
536
   */
537
  bool constructInstantiation(SolvedForm& sf, unsigned i);
538
  /** construct instantiation
539
   *
540
   * Helper method for the above method. This method attempts to find a term for
541
   * variable pv to include in the current instantiation, given by sf based
542
   * on equality and theory-specific instantiation techniques. The latter is
543
   * managed by the instantiator object vinst. Prior to calling this method,
544
   * the variable pv has been activated by a call to
545
   * activateInstantiationVariable.
546
   */
547
  bool constructInstantiation(SolvedForm& sf, Instantiator* vinst, Node pv);
548
  /** do add instantiation
549
   * This method is called by the above function after we finalize the
550
   * variables/substitution and auxiliary lemmas.
551
   * It returns true if a successful call to the output channel's
552
   * doAddInstantiation was made.
553
   */
554
  bool doAddInstantiation(std::vector<Node>& vars, std::vector<Node>& subs);
555
556
  //------------------------------------ static queries
557
  /** is cbqi sort
558
   *
559
   * Helper function for isCbqiSort. This function recurses over the structure
560
   * of the type tn, where visited stores the types we have visited.
561
   */
562
  static CegHandledStatus isCbqiSort(
563
      TypeNode tn, std::map<TypeNode, CegHandledStatus>& visited);
564
  //------------------------------------ end  static queries
565
};
566
567
/** Instantiator class
568
 *
569
 * This is a virtual class that is used for methods for constructing
570
 * substitutions for individual variables in counterexample-guided
571
 * instantiation techniques.
572
 *
573
 * This class contains a set of interface functions below, which are called
574
 * based on a fixed instantiation method implemented by CegInstantiator.
575
 * In these calls, the Instantiator in turn makes calls to methods in
576
 * CegInstanatior (primarily constructInstantiationInc).
577
 */
578
class Instantiator {
579
public:
580
 Instantiator(TypeNode tn);
581
3027
 virtual ~Instantiator() {}
582
 /** reset
583
  * This is called once, prior to any of the below methods are called.
584
  * This function sets up any initial information necessary for constructing
585
  * instantiations for pv based on the current context.
586
  */
587
6808
 virtual void reset(CegInstantiator* ci,
588
                    SolvedForm& sf,
589
                    Node pv,
590
                    CegInstEffort effort)
591
 {
592
6808
 }
593
594
  /** has process equal term
595
   *
596
   * Whether this instantiator implements processEqualTerm and
597
   * processEqualTerms.
598
   */
599
39641
  virtual bool hasProcessEqualTerm(CegInstantiator* ci,
600
                                   SolvedForm& sf,
601
                                   Node pv,
602
                                   CegInstEffort effort)
603
  {
604
39641
    return false;
605
  }
606
  /** process equal term
607
   *
608
   * This method is called when the entailment:
609
   *   E |= pv_prop.getModifiedTerm(pv) = n
610
   * holds in the current context E, and n is eligible for instantiation.
611
   *
612
   * Returns true if an instantiation was successfully added via a call to
613
   * CegInstantiator::constructInstantiationInc.
614
   */
615
  virtual bool processEqualTerm(CegInstantiator* ci,
616
                                SolvedForm& sf,
617
                                Node pv,
618
                                TermProperties& pv_prop,
619
                                Node n,
620
                                CegInstEffort effort);
621
  /** process equal terms
622
   *
623
   * This method is called after process equal term, where eqc is the list of
624
   * eligible terms in the equivalence class of pv.
625
   *
626
   * Returns true if an instantiation was successfully added via a call to
627
   * CegInstantiator::constructInstantiationInc.
628
   */
629
  virtual bool processEqualTerms(CegInstantiator* ci,
630
                                 SolvedForm& sf,
631
                                 Node pv,
632
                                 std::vector<Node>& eqc,
633
                                 CegInstEffort effort)
634
  {
635
    return false;
636
  }
637
638
  /** whether the instantiator implements processEquality */
639
11850
  virtual bool hasProcessEquality(CegInstantiator* ci,
640
                                  SolvedForm& sf,
641
                                  Node pv,
642
                                  CegInstEffort effort)
643
  {
644
11850
    return false;
645
  }
646
  /** process equality
647
   *  The input is such that term_props.size() = terms.size() = 2
648
   *  This method is called when the entailment:
649
   *    E ^ term_props[0].getModifiedTerm(x0) =
650
   *    terms[0] ^ term_props[1].getModifiedTerm(x1) = terms[1] |= x0 = x1
651
   *  holds in current context E for fresh variables xi, terms[i] are eligible,
652
   *  and at least one terms[i] contains pv for i = 0,1.
653
   *  Notice in the basic case, E |= terms[0] = terms[1].
654
   *
655
   *  Returns true if an instantiation was successfully added via a call to
656
   *  CegInstantiator::constructInstantiationInc.
657
   */
658
  virtual bool processEquality(CegInstantiator* ci,
659
                               SolvedForm& sf,
660
                               Node pv,
661
                               std::vector<TermProperties>& term_props,
662
                               std::vector<Node>& terms,
663
                               CegInstEffort effort)
664
  {
665
    return false;
666
  }
667
668
  /** whether the instantiator implements processAssertion for any literal */
669
6670
  virtual bool hasProcessAssertion(CegInstantiator* ci,
670
                                   SolvedForm& sf,
671
                                   Node pv,
672
                                   CegInstEffort effort)
673
  {
674
6670
    return false;
675
  }
676
  /** has process assertion
677
  *
678
  * This method is called when the entailment:
679
  *   E |= lit
680
  * holds in current context E. Typically, lit belongs to the list of current
681
  * assertions.
682
  *
683
  * This method is used to determine whether the instantiator implements
684
  * processAssertion for literal lit.
685
  *   If this method returns null, then this intantiator does not handle the
686
  *   literal lit. Otherwise, this method returns a literal lit' such that:
687
  *   (1) lit' is true in the current model,
688
  *   (2) lit' implies lit.
689
  *   where typically lit' = lit.
690
  */
691
  virtual Node hasProcessAssertion(CegInstantiator* ci,
692
                                   SolvedForm& sf,
693
                                   Node pv,
694
                                   Node lit,
695
                                   CegInstEffort effort)
696
  {
697
    return Node::null();
698
  }
699
  /** process assertion
700
   * This method processes the assertion slit for variable pv.
701
   * lit : the substituted form (under sf) of a literal returned by
702
   *       hasProcessAssertion
703
   * alit : the asserted literal, given as input to hasProcessAssertion
704
   *
705
   *  Returns true if an instantiation was successfully added via a call to
706
   *  CegInstantiator::constructInstantiationInc.
707
   */
708
  virtual bool processAssertion(CegInstantiator* ci,
709
                                SolvedForm& sf,
710
                                Node pv,
711
                                Node lit,
712
                                Node alit,
713
                                CegInstEffort effort)
714
  {
715
    return false;
716
  }
717
  /** process assertions
718
   *
719
   * Called after processAssertion is called for each literal asserted to the
720
   * instantiator.
721
   *
722
   * Returns true if an instantiation was successfully added via a call to
723
   * CegInstantiator::constructInstantiationInc.
724
   */
725
  virtual bool processAssertions(CegInstantiator* ci,
726
                                 SolvedForm& sf,
727
                                 Node pv,
728
                                 CegInstEffort effort)
729
  {
730
    return false;
731
  }
732
733
  /** do we use the model value as instantiation for pv?
734
   * This method returns true if we use model value instantiations
735
   * at the same effort level as those determined by this instantiator.
736
   */
737
1353
  virtual bool useModelValue(CegInstantiator* ci,
738
                             SolvedForm& sf,
739
                             Node pv,
740
                             CegInstEffort effort)
741
  {
742
1353
    return effort > CEG_INST_EFFORT_STANDARD;
743
  }
744
  /** do we allow the model value as instantiation for pv? */
745
11404
  virtual bool allowModelValue(CegInstantiator* ci,
746
                               SolvedForm& sf,
747
                               Node pv,
748
                               CegInstEffort effort)
749
  {
750
11404
    return d_closed_enum_type;
751
  }
752
753
  /** do we need to postprocess the solved form for pv? */
754
12701
  virtual bool needsPostProcessInstantiationForVariable(CegInstantiator* ci,
755
                                                        SolvedForm& sf,
756
                                                        Node pv,
757
                                                        CegInstEffort effort)
758
  {
759
12701
    return false;
760
  }
761
  /** postprocess the solved form for pv
762
   *
763
   * This method returns true if we successfully postprocessed the solved form.
764
   * lemmas is a set of lemmas we wish to return along with the instantiation.
765
   */
766
  virtual bool postProcessInstantiationForVariable(CegInstantiator* ci,
767
                                                   SolvedForm& sf,
768
                                                   Node pv,
769
                                                   CegInstEffort effort)
770
  {
771
    return true;
772
  }
773
774
  /** Identify this module (for debugging) */
775
148
  virtual std::string identify() const { return "Default"; }
776
 protected:
777
  /** the type of the variable we are instantiating */
778
  TypeNode d_type;
779
  /** whether d_type is a closed enumerable type */
780
  bool d_closed_enum_type;
781
};
782
783
class ModelValueInstantiator : public Instantiator {
784
public:
785
211
 ModelValueInstantiator(TypeNode tn) : Instantiator(tn) {}
786
422
 virtual ~ModelValueInstantiator() {}
787
6516
 bool useModelValue(CegInstantiator* ci,
788
                    SolvedForm& sf,
789
                    Node pv,
790
                    CegInstEffort effort) override
791
 {
792
6516
   return true;
793
 }
794
6516
  std::string identify() const override { return "ModelValue"; }
795
};
796
797
/** instantiator preprocess
798
 *
799
 * This class implements techniques for preprocessing the counterexample lemma
800
 * generated for counterexample-guided quantifier instantiation.
801
 */
802
class InstantiatorPreprocess
803
{
804
 public:
805
717
  InstantiatorPreprocess() {}
806
717
  virtual ~InstantiatorPreprocess() {}
807
  /** register counterexample lemma
808
   * This implements theory-specific preprocessing and registration
809
   * of counterexample lemmas, with the same contract as
810
   * CegInstantiation::registerCounterexampleLemma.
811
   */
812
  virtual void registerCounterexampleLemma(Node lem,
813
                                           std::vector<Node>& ceVars,
814
                                           std::vector<Node>& auxLems)
815
  {
816
  }
817
};
818
819
}  // namespace quantifiers
820
}  // namespace theory
821
}  // namespace cvc5
822
823
#endif