GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/sep/theory_sep.h Lines: 18 32 56.3 %
Date: 2021-09-10 Branches: 21 102 20.6 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Tim King, Haniel Barbosa
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
 * Theory of separation logic.
14
 */
15
16
#include "cvc5_private.h"
17
18
#ifndef CVC5__THEORY__SEP__THEORY_SEP_H
19
#define CVC5__THEORY__SEP__THEORY_SEP_H
20
21
#include "context/cdhashmap.h"
22
#include "context/cdhashset.h"
23
#include "context/cdlist.h"
24
#include "context/cdqueue.h"
25
#include "theory/decision_strategy.h"
26
#include "theory/inference_manager_buffered.h"
27
#include "theory/sep/theory_sep_rewriter.h"
28
#include "theory/theory.h"
29
#include "theory/theory_state.h"
30
#include "theory/uf/equality_engine.h"
31
#include "util/statistics_stats.h"
32
33
namespace cvc5 {
34
namespace theory {
35
36
class TheoryModel;
37
38
namespace sep {
39
40
class TheorySep : public Theory {
41
  typedef context::CDList<Node> NodeList;
42
  typedef context::CDHashSet<Node> NodeSet;
43
  typedef context::CDHashMap<Node, Node> NodeNodeMap;
44
45
  /////////////////////////////////////////////////////////////////////////////
46
  // MISC
47
  /////////////////////////////////////////////////////////////////////////////
48
49
 private:
50
  /** all lemmas sent */
51
  NodeSet d_lemmas_produced_c;
52
53
  /** True node for predicates = true */
54
  Node d_true;
55
56
  /** True node for predicates = false */
57
  Node d_false;
58
59
  //whether bounds have been initialized
60
  bool d_bounds_init;
61
62
  TheorySepRewriter d_rewriter;
63
  /** A (default) theory state object */
64
  TheoryState d_state;
65
  /** A buffered inference manager */
66
  InferenceManagerBuffered d_im;
67
68
  Node mkAnd( std::vector< TNode >& assumptions );
69
70
  int processAssertion(
71
      Node n,
72
      std::map<int, std::map<Node, int> >& visited,
73
      std::map<int, std::map<Node, std::vector<Node> > >& references,
74
      std::map<int, std::map<Node, bool> >& references_strict,
75
      bool pol,
76
      bool hasPol,
77
      bool underSpatial);
78
79
 public:
80
  TheorySep(Env& env, OutputChannel& out, Valuation valuation);
81
  ~TheorySep();
82
83
  /**
84
   * Declare heap. For smt2 inputs, this is called when the command
85
   * (declare-heap (locT datat)) is invoked by the user. This sets locT as the
86
   * location type and dataT is the data type for the heap. This command can be
87
   * executed once only, and must be invoked before solving separation logic
88
   * inputs.
89
   */
90
  void declareSepHeap(TypeNode locT, TypeNode dataT) override;
91
92
  //--------------------------------- initialization
93
  /** get the official theory rewriter of this theory */
94
  TheoryRewriter* getTheoryRewriter() override;
95
  /** get the proof checker of this theory */
96
  ProofRuleChecker* getProofChecker() override;
97
  /**
98
   * Returns true if we need an equality engine. If so, we initialize the
99
   * information regarding how it should be setup. For details, see the
100
   * documentation in Theory::needsEqualityEngine.
101
   */
102
  bool needsEqualityEngine(EeSetupInfo& esi) override;
103
  /** finish initialization */
104
  void finishInit() override;
105
  //--------------------------------- end initialization
106
  /** preregister term */
107
  void preRegisterTerm(TNode n) override;
108
109
  std::string identify() const override { return std::string("TheorySep"); }
110
111
  /////////////////////////////////////////////////////////////////////////////
112
  // PREPROCESSING
113
  /////////////////////////////////////////////////////////////////////////////
114
115
 public:
116
  void ppNotifyAssertions(const std::vector<Node>& assertions) override;
117
  /////////////////////////////////////////////////////////////////////////////
118
  // T-PROPAGATION / REGISTRATION
119
  /////////////////////////////////////////////////////////////////////////////
120
121
 private:
122
  /** Should be called to propagate the literal.  */
123
  bool propagateLit(TNode literal);
124
  /** Conflict when merging constants */
125
  void conflict(TNode a, TNode b);
126
127
 public:
128
  TrustNode explain(TNode n) override;
129
130
 public:
131
  void computeCareGraph() override;
132
133
  /////////////////////////////////////////////////////////////////////////////
134
  // MODEL GENERATION
135
  /////////////////////////////////////////////////////////////////////////////
136
137
 public:
138
  void postProcessModel(TheoryModel* m) override;
139
140
  /////////////////////////////////////////////////////////////////////////////
141
  // NOTIFICATIONS
142
  /////////////////////////////////////////////////////////////////////////////
143
144
 public:
145
146
  void presolve() override;
147
9904
  void shutdown() override {}
148
149
  /////////////////////////////////////////////////////////////////////////////
150
  // MAIN SOLVER
151
  /////////////////////////////////////////////////////////////////////////////
152
153
  //--------------------------------- standard check
154
  /** Do we need a check call at last call effort? */
155
  bool needsCheckLastEffort() override;
156
  /** Post-check, called after the fact queue of the theory is processed. */
157
  void postCheck(Effort level) override;
158
  /** Pre-notify fact, return true if processed. */
159
  bool preNotifyFact(TNode atom,
160
                     bool pol,
161
                     TNode fact,
162
                     bool isPrereg,
163
                     bool isInternal) override;
164
  /** Notify fact */
165
  void notifyFact(TNode atom, bool pol, TNode fact, bool isInternal) override;
166
  //--------------------------------- end standard check
167
168
 private:
169
  /** Ensures that the reduction has been added for the given fact */
170
  void reduceFact(TNode atom, bool polarity, TNode fact);
171
  /** Is spatial kind? */
172
  bool isSpatialKind(Kind k) const;
173
  // NotifyClass: template helper class for d_equalityEngine - handles
174
  // call-back from congruence closure module
175
9910
  class NotifyClass : public eq::EqualityEngineNotify
176
  {
177
    TheorySep& d_sep;
178
179
   public:
180
9913
    NotifyClass(TheorySep& sep) : d_sep(sep) {}
181
182
    bool eqNotifyTriggerPredicate(TNode predicate, bool value) override
183
    {
184
      Debug("sep::propagate")
185
          << "NotifyClass::eqNotifyTriggerPredicate(" << predicate << ", "
186
          << (value ? "true" : "false") << ")" << std::endl;
187
      Assert(predicate.getKind() == kind::EQUAL);
188
      // Just forward to sep
189
      if (value)
190
      {
191
        return d_sep.propagateLit(predicate);
192
      }
193
      return d_sep.propagateLit(predicate.notNode());
194
    }
195
3923
    bool eqNotifyTriggerTermEquality(TheoryId tag,
196
                                     TNode t1,
197
                                     TNode t2,
198
                                     bool value) override
199
    {
200
7846
      Debug("sep::propagate")
201
3923
          << "NotifyClass::eqNotifyTriggerTermEquality(" << t1 << ", " << t2
202
3923
          << ", " << (value ? "true" : "false") << ")" << std::endl;
203
3923
      if (value)
204
      {
205
        // Propagate equality between shared terms
206
1194
        return d_sep.propagateLit(t1.eqNode(t2));
207
      }
208
2729
      return d_sep.propagateLit(t1.eqNode(t2).notNode());
209
    }
210
211
    void eqNotifyConstantTermMerge(TNode t1, TNode t2) override
212
    {
213
      Debug("sep::propagate") << "NotifyClass::eqNotifyConstantTermMerge(" << t1
214
                              << ", " << t2 << ")" << std::endl;
215
      d_sep.conflict(t1, t2);
216
    }
217
218
3441
    void eqNotifyNewClass(TNode t) override {}
219
15431
    void eqNotifyMerge(TNode t1, TNode t2) override
220
    {
221
15431
      d_sep.eqNotifyMerge(t1, t2);
222
15431
    }
223
2729
    void eqNotifyDisequal(TNode t1, TNode t2, TNode reason) override {}
224
  };
225
226
  /** The notify class for d_equalityEngine */
227
  NotifyClass d_notify;
228
229
  /** list of all refinement lemms */
230
  std::map< Node, std::map< Node, std::vector< Node > > > d_refinement_lem;
231
232
  //cache for positive polarity start reduction
233
  NodeSet d_reduce;
234
  std::map< Node, std::map< Node, Node > > d_red_conc;
235
  std::map< Node, std::map< Node, Node > > d_neg_guard;
236
  std::vector< Node > d_neg_guards;
237
  /** a (singleton) decision strategy for each negative guard. */
238
  std::map<Node, std::unique_ptr<DecisionStrategySingleton> >
239
      d_neg_guard_strategy;
240
  std::map< Node, Node > d_guard_to_assertion;
241
  NodeList d_spatial_assertions;
242
243
  //data,ref type (globally fixed)
244
  TypeNode d_type_ref;
245
  TypeNode d_type_data;
246
  //currently fix one data type for each location type, throw error if using more than one
247
  std::map< TypeNode, TypeNode > d_loc_to_data_type;
248
  //information about types
249
  std::map< TypeNode, Node > d_base_label;
250
  std::map< TypeNode, Node > d_nil_ref;
251
  //reference bound
252
  std::map< TypeNode, Node > d_reference_bound;
253
  std::map< TypeNode, Node > d_reference_bound_max;
254
  std::map< TypeNode, std::vector< Node > > d_type_references;
255
  //kind of bound for reference types
256
  enum {
257
    bound_strict,
258
    bound_default,
259
    bound_invalid,
260
  };
261
  std::map< TypeNode, unsigned > d_bound_kind;
262
263
  std::map< TypeNode, std::vector< Node > > d_type_references_card;
264
  std::map< Node, unsigned > d_type_ref_card_id;
265
  std::map< TypeNode, std::vector< Node > > d_type_references_all;
266
  std::map< TypeNode, unsigned > d_card_max;
267
  //for empty argument
268
  std::map< TypeNode, Node > d_emp_arg;
269
  //map from ( atom, label, child index ) -> label
270
  std::map< Node, std::map< Node, std::map< int, Node > > > d_label_map;
271
  std::map< Node, Node > d_label_map_parent;
272
273
  //term model
274
  std::map< Node, Node > d_tmodel;
275
  std::map< Node, Node > d_pto_model;
276
277
  class HeapAssertInfo {
278
  public:
279
    HeapAssertInfo( context::Context* c );
280
293
    ~HeapAssertInfo(){}
281
    context::CDO< Node > d_pto;
282
    context::CDO< bool > d_has_neg_pto;
283
  };
284
  std::map< Node, HeapAssertInfo * > d_eqc_info;
285
  HeapAssertInfo * getOrMakeEqcInfo( Node n, bool doMake = false );
286
287
  //get global reference/data type
288
  TypeNode getReferenceType( Node n );
289
  TypeNode getDataType( Node n );
290
  /**
291
   * Register reference data types for atom. Calls the method below for
292
   * the appropriate types.
293
   */
294
  void registerRefDataTypesAtom(Node atom);
295
  /**
296
   * This is called either when:
297
   * (A) a declare-heap command is issued with tn1/tn2, and atom is null, or
298
   * (B) an atom specifying the heap type tn1/tn2 is registered to this theory.
299
   * We set the heap type if we are are case (A), and check whether the
300
   * heap type is consistent in the case of (B).
301
   */
302
  void registerRefDataTypes(TypeNode tn1, TypeNode tn2, Node atom);
303
  //get location/data type
304
  //get the base label for the spatial assertion
305
  Node getBaseLabel( TypeNode tn );
306
  Node getNilRef( TypeNode tn );
307
  void setNilRef( TypeNode tn, Node n );
308
  Node getLabel( Node atom, int child, Node lbl );
309
  Node applyLabel( Node n, Node lbl, std::map< Node, Node >& visited );
310
  void getLabelChildren( Node atom, Node lbl, std::vector< Node >& children, std::vector< Node >& labels );
311
312
395
  class HeapInfo {
313
  public:
314
395
    HeapInfo() : d_computed(false) {}
315
    //information about the model
316
    bool d_computed;
317
    std::vector< Node > d_heap_locs;
318
    std::vector< Node > d_heap_locs_model;
319
    //get value
320
    Node getValue( TypeNode tn );
321
  };
322
  //heap info ( label -> HeapInfo )
323
  std::map< Node, HeapInfo > d_label_model;
324
  // loc -> { data_1, ..., data_n } where (not (pto loc data_1))...(not (pto loc data_n))).
325
  std::map< Node, std::vector< Node > > d_heap_locs_nptos;
326
327
  void debugPrintHeap( HeapInfo& heap, const char * c );
328
  void validatePto( HeapAssertInfo * ei, Node ei_n );
329
  void addPto( HeapAssertInfo * ei, Node ei_n, Node p, bool polarity );
330
  void mergePto( Node p1, Node p2 );
331
  void computeLabelModel( Node lbl );
332
  Node instantiateLabel(Node n,
333
                        Node o_lbl,
334
                        Node lbl,
335
                        Node lbl_v,
336
                        std::map<Node, Node>& visited,
337
                        std::map<Node, Node>& pto_model,
338
                        TypeNode rtn,
339
                        std::map<Node, bool>& active_lbl,
340
                        unsigned ind = 0);
341
  void setInactiveAssertionRec( Node fact, std::map< Node, std::vector< Node > >& lbl_to_assertions, std::map< Node, bool >& assert_active );
342
343
  Node mkUnion( TypeNode tn, std::vector< Node >& locs );
344
345
 private:
346
  Node getRepresentative( Node t );
347
  bool hasTerm( Node a );
348
  bool areEqual( Node a, Node b );
349
  bool areDisequal( Node a, Node b );
350
  void eqNotifyMerge(TNode t1, TNode t2);
351
352
  void sendLemma( std::vector< Node >& ant, Node conc, InferenceId id, bool infer = false );
353
  void doPending();
354
355
 public:
356
357
  void initializeBounds();
358
};/* class TheorySep */
359
360
}  // namespace sep
361
}  // namespace theory
362
}  // namespace cvc5
363
364
#endif /* CVC5__THEORY__SEP__THEORY_SEP_H */