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