GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/sets/cardinality_extension.h Lines: 4 4 100.0 %
Date: 2021-08-14 Branches: 0 0 0.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Mudathir Mohamed
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
 * An extension of the theory sets for handling cardinality constraints.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__SETS__CARDINALITY_EXTENSION_H
19
#define CVC5__THEORY__SETS__CARDINALITY_EXTENSION_H
20
21
#include "context/cdhashset.h"
22
#include "context/context.h"
23
#include "theory/sets/inference_manager.h"
24
#include "theory/sets/solver_state.h"
25
#include "theory/sets/term_registry.h"
26
#include "theory/type_set.h"
27
#include "theory/uf/equality_engine.h"
28
29
namespace cvc5 {
30
namespace theory {
31
namespace sets {
32
33
/**
34
 * This class implements a variant of the procedure from Bansal et al, IJCAR
35
 * 2016. It is used during a full effort check in the following way:
36
 *    reset(); { registerTerm(n,lemmas); | n in CardTerms }  check();
37
 * where CardTerms is the set of all applications of CARD in the current
38
 * context.
39
 *
40
 * The remaining public methods are used during model construction, i.e.
41
 * the collectModelInfo method of the theory of sets.
42
 *
43
 * The procedure from Bansal et al IJCAR 2016 introduces the notion of a
44
 * "cardinality graph", where the nodes of this graph are sets and (directed)
45
 * edges connect sets to their Venn regions wrt to other sets. For example,
46
 * if (A \ B) is a term in the current context, then the node A is
47
 * connected via an edge to child (A \ B). The node (A ^ B) is a child
48
 * of both A and B. The notion of a cardinality graph is loosely followed
49
 * in the procedure implemented by this class.
50
 *
51
 * The main difference wrt Bansal et al IJCAR 2016 is that the nodes of the
52
 * cardinality graph considered by this class are not arbitrary set terms, but
53
 * are instead representatives of equivalence classes. For more details, see
54
 * documentation of the inference schemas in the private methods of this class.
55
 *
56
 * This variant of the procedure takes inspiration from the procedure
57
 * for word equations in Liang et al, CAV 2014. In that procedure, "normal
58
 * forms" are generated for String terms by recursively expanding
59
 * concatentations modulo equality. This procedure similarly maintains
60
 * normal forms, where the normal form for Set terms is a set of (equivalence
61
 * class representatives of) Venn regions that do not contain the empty set.
62
 */
63
class CardinalityExtension
64
{
65
  typedef context::CDHashSet<Node> NodeSet;
66
67
 public:
68
  /**
69
   * Constructs a new instance of the cardinality solver w.r.t. the provided
70
   * contexts.
71
   */
72
  CardinalityExtension(SolverState& s,
73
                       InferenceManager& im,
74
                       TermRegistry& treg);
75
76
9853
  ~CardinalityExtension() {}
77
  /** reset
78
   *
79
   * Called at the beginning of a full effort check. This resets the data
80
   * structures used by this class during a full effort check.
81
   */
82
  void reset();
83
  /** register term
84
   *
85
   * Register that the term n exists in the current context, where n is an
86
   * application of CARD.
87
   */
88
  void registerTerm(Node n);
89
  /** check
90
   *
91
   * Invoke a full effort check of the cardinality solver. At a high level,
92
   * this asserts inferences via the inference manager object d_im. If no
93
   * inferences are made, then the current set of assertions is satisfied
94
   * with respect to constraints involving set cardinality.
95
   *
96
   * This method applies various inference schemas in succession until an
97
   * inference is made. These inference schemas are given in the private
98
   * methods of this class (e.g. checkMinCard, checkCardBuildGraph, etc.).
99
   */
100
  void check();
101
  /** Is model value basic?
102
   *
103
   * This returns true if equivalence class eqc is a "leaf" in the cardinality
104
   * graph.
105
   */
106
  bool isModelValueBasic(Node eqc);
107
  /** get model elements
108
   *
109
   * This method updates els so that it is the set of elements that occur in
110
   * an equivalence class (whose representative is eqc) in the model we are
111
   * building. Notice that els may already have elements in it (from explicit
112
   * memberships from the base set solver for leaf nodes of the cardinality
113
   * graph). This method is used during the collectModelInfo method of theory
114
   * of sets.
115
   *
116
   * The argument v is the Valuation utility of the theory of sets, which is
117
   * used by this method to query the value assigned to cardinality terms by
118
   * the theory of arithmetic.
119
   *
120
   * The argument mvals maps set equivalence classes to their model values.
121
   * Due to our model construction algorithm, it can be assumed that all
122
   * sets in the normal form of eqc occur in the domain of mvals by the order
123
   * in which sets are assigned.
124
   */
125
  void mkModelValueElementsFor(Valuation& v,
126
                               Node eqc,
127
                               std::vector<Node>& els,
128
                               const std::map<Node, Node>& mvals,
129
                               TheoryModel* model);
130
  /** get ordered sets equivalence classes
131
   *
132
   * Get the ordered set of equivalence classes computed by this class. This
133
   * ordering ensures the invariant mentioned above mkModelValueElementsFor.
134
   *
135
   * This ordering ensures that all children of a node in the cardinality
136
   * graph computed by this class occur before it in this list.
137
   */
138
81
  const std::vector<Node>& getOrderedSetsEqClasses() { return d_oSetEqc; }
139
140
  /**
141
   * get the slack elements generated for each finite type. This function is
142
   * called by TheorySetsPrivate::collectModelInfo to ask the TheoryModel to
143
   * exclude these slack elements from the members in all sets of that type.
144
   */
145
71
  const std::map<TypeNode, std::vector<TNode> >& getFiniteTypeSlackElements()
146
      const
147
  {
148
71
    return d_finite_type_slack_elements;
149
  }
150
  /**
151
   * get non-slack members in all sets of the given finite type. This function
152
   * is called by TheorySetsPrivate::collectModelInfo to specify the exclusion
153
   * sets for TheoryModel
154
   */
155
  const std::vector<Node>& getFiniteTypeMembers(TypeNode typeNode);
156
157
 private:
158
  /** constants */
159
  Node d_true;
160
  Node d_zero;
161
  /** the empty vector */
162
  std::vector<Node> d_emp_exp;
163
  /** Reference to the state object for the theory of sets */
164
  SolverState& d_state;
165
  /** Reference to the inference manager for the theory of sets */
166
  InferenceManager& d_im;
167
  /** Reference to the term registry */
168
  TermRegistry& d_treg;
169
  /** register cardinality term
170
   *
171
   * This method adds lemmas corresponding to the definition of
172
   * the cardinality of set term n. For example, if n is A^B (denoting set
173
   * intersection as ^), then we consider the lemmas card(A^B)>=0,
174
   * card(A) = card(A\B) + card(A^B) and card(B) = card(B\A) + card(A^B).
175
   *
176
   * The exact form of this lemma is modified such that proxy variables are
177
   * introduced for set terms as needed (see SolverState::getProxy).
178
   */
179
  void registerCardinalityTerm(Node n);
180
  /** check register
181
   *
182
   * This ensures that all (non-redundant, relevant) non-variable set terms in
183
   * the current context have been passed to registerCardinalityTerm. In other
184
   * words, this ensures that the cardinality graph for these terms can be
185
   * constructed since the cardinality relationships for these terms have been
186
   * elaborated as lemmas.
187
   *
188
   * Notice a term is redundant in a context if it is congruent to another
189
   * term that is already in the context; it is not relevant if no cardinality
190
   * constraints exist for its type.
191
   */
192
  void checkRegister();
193
  /** check minimum cardinality
194
   *
195
   * This adds lemmas to the argument of the method of the form
196
   *   distinct(x1,...,xn) ^ member(x1,S) ^ ... ^ member(xn,S) => card(S) >= n
197
   * This lemma enforces the rules GUESS_LOWER_BOUND and PROPAGATE_MIN_SIZE
198
   * from Bansal et. al IJCAR 2016.
199
   *
200
   * Notice that member(x1,S) is implied to hold in the current context. This
201
   * means that it may be the case that member(x,T) ^ T = S are asserted
202
   * literals. Furthermore, x1, ..., xn reside in distinct equivalence classes
203
   * but are not necessarily entailed to be distinct.
204
   */
205
  void checkMinCard();
206
  /** check cardinality cycles
207
   *
208
   * The purpose of this inference schema is to construct two data structures:
209
   *
210
   * (1) d_card_parent, which maps set terms (A op B) for op in { \, ^ } to
211
   * equivalence class representatives of their "parents", where:
212
   *   parent( A ^ B ) = A, B
213
   *   parent( A \ B ) = A
214
   * Additionally, (A union B) is a parent of all three of the above sets
215
   * if it exists as a term in the current context. As exceptions,
216
   * if A op B = A, then A is not a parent of A ^ B and similarly for B.
217
   * If A ^ B is empty, then it has no parents.
218
   *
219
   * We say the cardinality graph induced by the current set of equalities
220
   * is an (irreflexive, acyclic) graph whose nodes are equivalence classes and
221
   * which contains a (directed) edge r1 to r2 if there exists a term t2 in r2
222
   * that has some parent t1 in r1.
223
   *
224
   * (2) d_oSetEqc, an ordered set of equivalence classes whose types are set.
225
   * These equivalence classes have the property that if r1 is a descendant
226
   * of r2 in the cardinality graph, then r1 must come before r2 in d_oSetEqc.
227
   *
228
   * This inference schema may make various inferences while building these
229
   * two data structures if the current equality arrangement of sets is not
230
   * as expected. For example, it will infer equalities between sets based on
231
   * the emptiness and equalities of sets in adjacent children in the
232
   * cardinality graph, to give some examples:
233
   *   (A \ B = empty) => A = A ^ B
234
   *   A^B = B => B \ A = empty
235
   *   A union B = A ^ B => A \ B = empty AND B \ A = empty
236
   * and so on.
237
   *
238
   * It will also recognize when a cycle occurs in the cardinality graph, in
239
   * which case an equality chain between sets can be inferred. For an example,
240
   * see checkCardCyclesRec below.
241
   *
242
   * This method is inspired by the checkCycles inference schema in the theory
243
   * of strings.
244
   */
245
  void checkCardCycles();
246
  /**
247
   * Helper function for above. Called when wish to process equivalence class
248
   * eqc.
249
   *
250
   * Argument curr contains the equivalence classes we are currently processing,
251
   * which are descendants of eqc in the cardinality graph, where eqc is the
252
   * representative of some equivalence class.
253
   *
254
   * Argument exp contains an explanation of why the chain of children curr
255
   * are descedants of . For example, say we are in context with equivalence
256
   * classes:
257
   *   { A, B, C^D }, { D, B ^ C,  A ^ E }
258
   * We may recursively call this method via the following steps:
259
   *   eqc = D, curr = {}, exp = {}
260
   *   eqc = A, curr = { D }, exp = { D = B^C }
261
   *   eqc = A, curr = { D, A }, exp = { D = B^C, A = C^D }
262
   * after which we discover a cycle in the cardinality graph. We infer
263
   * that A must be equal to D, where exp is an explanation of the cycle.
264
   */
265
  void checkCardCyclesRec(Node eqc,
266
                          std::vector<Node>& curr,
267
                          std::vector<Node>& exp);
268
  /** check normal forms
269
   *
270
   * This method attempts to assign "normal forms" to all set equivalence
271
   * classes whose types have cardinality constraints. Normal forms are
272
   * defined recursively.
273
   *
274
   * A "normal form" of an equivalence class [r] (where [r] denotes the
275
   * equivalence class whose representative is r) is a set of representatives
276
   * U = { r1, ..., rn }. If there exists at least one set in [r] that has a
277
   * "flat form", then all sets in the equivalence class have flat form U.
278
   * If no set in U has a flat form, then U = { r } if r does not contain
279
   * the empty set, and {} otherwise. Notice that the choice of representative
280
   * r is determined by the equality engine.
281
   *
282
   * A "flat form" of a set term T is the union of the normal forms of the
283
   * equivalence classes that contain sets whose parent is T.
284
   *
285
   * In terms of the cardinality graph, the "flat form" of term t is the set
286
   * of leaves of t that are descendants of it in the cardinality graph induced
287
   * by the current set of assertions. Notice a flat form is only defined if t
288
   * has children. If all terms in an equivalence class E with flat forms have
289
   * the same flat form, then E is added as a node to the cardinality graph with
290
   * edges connecting to all equivalence classes with terms that have a parent
291
   * in E.
292
   *
293
   * In the following inference schema, the argument intro_sets is updated to
294
   * contain the set of new set terms that the procedure is requesting to
295
   * introduce for the purpose of forcing the flat forms of two equivalent sets
296
   * to become identical. If any equivalence class cannot be assigned a normal
297
   * form, then the resulting intro_sets is guaranteed to be non-empty.
298
   *
299
   * As an example, say we have a context with equivalence classes:
300
   *   {A, D}, {C, A^B}, {E, C^D}, {C\D}, {D\C}, {A\B}, {empty, B\A},
301
   * where assume the first term in each set is its representative. An ordered
302
   * list d_oSetEqc for this context:
303
   *   A, C, E, C\D, D\C, A\B, empty, ...
304
   * The normal form of {empty, B\A} is {}, since it contains the empty set.
305
   * The normal forms for each of the singleton equivalence classes are
306
   * themselves.
307
   * The flat form of each of E and C^D does not exist, hence the normal form
308
   * of {E, C^D} is {E}.
309
   * The flat form of C is {E, C\D}, noting that C^D and C\D are terms whose
310
   * parent is C, hence {E, C\D} is the normal form for class {C, A^B}.
311
   * The flat form of A is {E, C\D, A\B} and the flat form of D is {E, D\C}.
312
   * Hence, no normal form can be assigned to class {A, D}. Instead this method
313
   * will e.g. add (C\D)^E to intro_sets, which will force the solver
314
   * to explore a model where the Venn regions (C\D)^E (C\D)\E and E\(C\D) are
315
   * considered while constructing flat forms. Splitting on whether these sets
316
   * are empty will eventually lead to a model where the flat forms of A and D
317
   * are the same.
318
   */
319
  void checkNormalForms(std::vector<Node>& intro_sets);
320
  /**
321
   * Called for each equivalence class, in order of d_oSetEqc, by the above
322
   * function.
323
   */
324
  void checkNormalForm(Node eqc, std::vector<Node>& intro_sets);
325
326
  /**
327
   * Add cardinality lemmas for the univset of each type with cardinality terms.
328
   * The lemmas are explained below.
329
   */
330
  void checkCardinalityExtended();
331
  /**
332
   * This function adds the following lemmas for type t for each S
333
   * where S is a (representative) set term of type t, and for each negative
334
   * member x not in S:
335
   * 1- (=> true (<= (card (as univset t)) n) where n is the
336
   * cardinality of t, which may be symbolic
337
   * 2- (=> true (subset S (as univset t)) where S is a set
338
   * term of type t
339
   * 3- (=> (not (member negativeMember S))) (member
340
   * negativeMember (as univset t)))
341
   */
342
  void checkCardinalityExtended(TypeNode& t);
343
344
  /** element types of sets for which cardinality is enabled */
345
  std::map<TypeNode, bool> d_t_card_enabled;
346
  /**
347
   * This maps equivalence classes r to an application of cardinality of the
348
   * form card( t ), where t = r holds in the current context.
349
   */
350
  std::map<Node, Node> d_eqc_to_card_term;
351
  /**
352
   * User-context-dependent set of set terms for which we have called
353
   * registerCardinalityTerm on.
354
   */
355
  NodeSet d_card_processed;
356
  /** The ordered set of equivalence classes, see checkCardCycles. */
357
  std::vector<Node> d_oSetEqc;
358
  /**
359
   * This maps set terms to the set of representatives of their "parent" sets,
360
   * see checkCardCycles. Parents are stored as a pair of the form
361
   *   (r, t)
362
   * where t is the parent term and r is the representative of equivalence
363
   * class of t.
364
   */
365
  std::map<Node, std::vector<std::pair<Node, Node>>> d_cardParent;
366
  /**
367
   * Maps equivalence classes + set terms in that equivalence class to their
368
   * "flat form" (see checkNormalForms).
369
   */
370
  std::map<Node, std::map<Node, std::vector<Node> > > d_ff;
371
  /** Maps equivalence classes to their "normal form" (see checkNormalForms). */
372
  std::map<Node, std::vector<Node> > d_nf;
373
  /** The local base node map
374
   *
375
   * This maps set terms to the "local base node" of its cardinality graph.
376
   * The local base node of S is the intersection node that is either S itself
377
   * or is adjacent to S in the cardinality graph. This maps
378
   *
379
   * For example, the ( A ^ B ) is the local base of each of the sets (A \ B),
380
   * ( A ^ B ), and (B \ A).
381
   */
382
  std::map<Node, Node> d_localBase;
383
384
  /**
385
   * a map to store proxy nodes for the universe sets
386
   */
387
  std::map<Node, Node> d_univProxy;
388
389
  /**
390
   * collect the elements in all sets of finite types in model, and
391
   * store them in the field d_finite_type_elements
392
   */
393
  void collectFiniteTypeSetElements(TheoryModel* model);
394
  /**
395
   * a map to store the non-slack elements encountered so far in all finite
396
   * types
397
   */
398
  std::map<TypeNode, std::vector<Node> > d_finite_type_elements;
399
  /**
400
   * a map to store slack elements in all finite types
401
   */
402
  std::map<TypeNode, std::vector<TNode> > d_finite_type_slack_elements;
403
  /** This boolean determines whether we already collected finite type constants
404
   *  present in the current model.
405
   *  Default value is false
406
   */
407
  bool d_finite_type_constants_processed;
408
409
  /*
410
   * a map that stores skolem nodes n that satisfies the constraint
411
   * (<= (card t) n) where t is an infinite type
412
   */
413
  std::map<TypeNode, Node> d_infiniteTypeUnivCardSkolems;
414
415
}; /* class CardinalityExtension */
416
417
}  // namespace sets
418
}  // namespace theory
419
}  // namespace cvc5
420
421
#endif