LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/sep - theory_sep.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 15 30 50.0 %
Date: 2026-02-12 13:01:42 Functions: 7 10 70.0 %
Branches: 3 14 21.4 %

           Branch data     Line data    Source code
       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-2025 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::internal {
      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                 :            :   /** True node for predicates = true */
      51                 :            :   Node d_true;
      52                 :            : 
      53                 :            :   /** True node for predicates = false */
      54                 :            :   Node d_false;
      55                 :            : 
      56                 :            :   /** Trust id (for proofs) */
      57                 :            :   Node d_tiid;
      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                 :            :   size_t processAssertion(
      69                 :            :       Node n,
      70                 :            :       std::map<int, std::map<Node, size_t> >& visited,
      71                 :            :       std::map<int, std::map<Node, std::vector<Node> > >& references,
      72                 :            :       std::map<int, std::map<Node, bool> >& references_strict,
      73                 :            :       bool pol,
      74                 :            :       bool hasPol,
      75                 :            :       bool underSpatial);
      76                 :            : 
      77                 :            :  public:
      78                 :            :   TheorySep(Env& env, OutputChannel& out, Valuation valuation);
      79                 :            :   ~TheorySep();
      80                 :            : 
      81                 :            :   //--------------------------------- initialization
      82                 :            :   /** get the official theory rewriter of this theory */
      83                 :            :   TheoryRewriter* getTheoryRewriter() override;
      84                 :            :   /** get the proof checker of this theory */
      85                 :            :   ProofRuleChecker* getProofChecker() override;
      86                 :            :   /**
      87                 :            :    * Returns true if we need an equality engine. If so, we initialize the
      88                 :            :    * information regarding how it should be setup. For details, see the
      89                 :            :    * documentation in Theory::needsEqualityEngine.
      90                 :            :    */
      91                 :            :   bool needsEqualityEngine(EeSetupInfo& esi) override;
      92                 :            :   /** finish initialization */
      93                 :            :   void finishInit() override;
      94                 :            :   //--------------------------------- end initialization
      95                 :            :   /** preregister term */
      96                 :            :   void preRegisterTerm(TNode n) override;
      97                 :            : 
      98                 :          0 :   std::string identify() const override { return std::string("TheorySep"); }
      99                 :            : 
     100                 :            :   void ppNotifyAssertions(const std::vector<Node>& assertions) override;
     101                 :            : 
     102                 :            :   TrustNode explain(TNode n) override;
     103                 :            : 
     104                 :            :   void postProcessModel(TheoryModel* m) override;
     105                 :            : 
     106                 :            :  private:
     107                 :            :   /**
     108                 :            :    * Initialize heap. For smt2 inputs, this will initialize the heap types
     109                 :            :    * based on if a command (declare-heap (locT datat)) was used. This command
     110                 :            :    * can be executed once only, and must be invoked before solving separation
     111                 :            :    * logic inputs, which is controlled by the solver engine.
     112                 :            :    */
     113                 :            :   void initializeHeapTypes();
     114                 :            :   /** Should be called to propagate the literal.  */
     115                 :            :   bool propagateLit(TNode literal);
     116                 :            :   /** Conflict when merging constants */
     117                 :            :   void conflict(TNode a, TNode b);
     118                 :            : 
     119                 :            :  public:
     120                 :            : 
     121                 :            :   void presolve() override;
     122                 :            : 
     123                 :            :   /////////////////////////////////////////////////////////////////////////////
     124                 :            :   // MAIN SOLVER
     125                 :            :   /////////////////////////////////////////////////////////////////////////////
     126                 :            : 
     127                 :            :   //--------------------------------- standard check
     128                 :            :   /** Do we need a check call at last call effort? */
     129                 :            :   bool needsCheckLastEffort() override;
     130                 :            :   /** Post-check, called after the fact queue of the theory is processed. */
     131                 :            :   void postCheck(Effort level) override;
     132                 :            :   /** Pre-notify fact, return true if processed. */
     133                 :            :   bool preNotifyFact(TNode atom,
     134                 :            :                      bool pol,
     135                 :            :                      TNode fact,
     136                 :            :                      bool isPrereg,
     137                 :            :                      bool isInternal) override;
     138                 :            :   /** Notify fact */
     139                 :            :   void notifyFact(TNode atom, bool pol, TNode fact, bool isInternal) override;
     140                 :            :   //--------------------------------- end standard check
     141                 :            : 
     142                 :            :  private:
     143                 :            :   /** Ensures that the reduction has been added for the given fact */
     144                 :            :   void reduceFact(TNode atom, bool polarity, TNode fact);
     145                 :            :   /** Is spatial kind? */
     146                 :            :   bool isSpatialKind(Kind k) const;
     147                 :            :   // NotifyClass: template helper class for d_equalityEngine - handles
     148                 :            :   // call-back from congruence closure module
     149                 :            :   class NotifyClass : public eq::EqualityEngineNotify
     150                 :            :   {
     151                 :            :     TheorySep& d_sep;
     152                 :            : 
     153                 :            :    public:
     154                 :      49899 :     NotifyClass(TheorySep& sep) : d_sep(sep) {}
     155                 :            : 
     156                 :          0 :     bool eqNotifyTriggerPredicate(TNode predicate, bool value) override
     157                 :            :     {
     158         [ -  - ]:          0 :       Trace("sep::propagate")
     159                 :          0 :           << "NotifyClass::eqNotifyTriggerPredicate(" << predicate << ", "
     160         [ -  - ]:          0 :           << (value ? "true" : "false") << ")" << std::endl;
     161                 :          0 :       Assert(predicate.getKind() == Kind::EQUAL);
     162                 :            :       // Just forward to sep
     163         [ -  - ]:          0 :       if (value)
     164                 :            :       {
     165                 :          0 :         return d_sep.propagateLit(predicate);
     166                 :            :       }
     167                 :          0 :       return d_sep.propagateLit(predicate.notNode());
     168                 :            :     }
     169                 :      17429 :     bool eqNotifyTriggerTermEquality(CVC5_UNUSED TheoryId tag,
     170                 :            :                                      TNode t1,
     171                 :            :                                      TNode t2,
     172                 :            :                                      bool value) override
     173                 :            :     {
     174         [ +  - ]:      34858 :       Trace("sep::propagate")
     175                 :          0 :           << "NotifyClass::eqNotifyTriggerTermEquality(" << t1 << ", " << t2
     176         [ -  - ]:      17429 :           << ", " << (value ? "true" : "false") << ")" << std::endl;
     177         [ +  + ]:      17429 :       if (value)
     178                 :            :       {
     179                 :            :         // Propagate equality between shared terms
     180                 :       8140 :         return d_sep.propagateLit(t1.eqNode(t2));
     181                 :            :       }
     182                 :       9289 :       return d_sep.propagateLit(t1.eqNode(t2).notNode());
     183                 :            :     }
     184                 :            : 
     185                 :          0 :     void eqNotifyConstantTermMerge(TNode t1, TNode t2) override
     186                 :            :     {
     187         [ -  - ]:          0 :       Trace("sep::propagate") << "NotifyClass::eqNotifyConstantTermMerge(" << t1
     188                 :          0 :                               << ", " << t2 << ")" << std::endl;
     189                 :          0 :       d_sep.conflict(t1, t2);
     190                 :          0 :     }
     191                 :            : 
     192                 :      16890 :     void eqNotifyNewClass(CVC5_UNUSED TNode t) override {}
     193                 :      28553 :     void eqNotifyMerge(TNode t1, TNode t2) override
     194                 :            :     {
     195                 :      28553 :       d_sep.eqNotifyMerge(t1, t2);
     196                 :      28553 :     }
     197                 :       9289 :     void eqNotifyDisequal(CVC5_UNUSED TNode t1,
     198                 :            :                           CVC5_UNUSED TNode t2,
     199                 :            :                           CVC5_UNUSED TNode reason) override
     200                 :            :     {
     201                 :       9289 :     }
     202                 :            :   };
     203                 :            : 
     204                 :            :   /** The notify class for d_equalityEngine */
     205                 :            :   NotifyClass d_notify;
     206                 :            : 
     207                 :            :   /** list of all refinement lemms */
     208                 :            :   std::map< Node, std::map< Node, std::vector< Node > > > d_refinement_lem;
     209                 :            : 
     210                 :            :   //cache for positive polarity start reduction
     211                 :            :   NodeSet d_reduce;
     212                 :            :   std::map< Node, std::map< Node, Node > > d_red_conc;
     213                 :            :   std::map< Node, std::map< Node, Node > > d_neg_guard;
     214                 :            :   std::vector< Node > d_neg_guards;
     215                 :            :   /** a (singleton) decision strategy for each negative guard. */
     216                 :            :   std::map<Node, std::unique_ptr<DecisionStrategySingleton> >
     217                 :            :       d_neg_guard_strategy;
     218                 :            :   std::map< Node, Node > d_guard_to_assertion;
     219                 :            :   NodeList d_spatial_assertions;
     220                 :            : 
     221                 :            :   //data,ref type (globally fixed)
     222                 :            :   TypeNode d_type_ref;
     223                 :            :   TypeNode d_type_data;
     224                 :            :   //information about types
     225                 :            :   Node d_base_label;
     226                 :            :   Node d_nil_ref;
     227                 :            :   //reference bound
     228                 :            :   Node d_reference_bound;
     229                 :            :   Node d_reference_bound_max;
     230                 :            :   std::vector<Node> d_type_references;
     231                 :            :   //kind of bound for reference types
     232                 :            :   enum {
     233                 :            :     bound_strict,
     234                 :            :     bound_default,
     235                 :            :     bound_invalid,
     236                 :            :   };
     237                 :            :   unsigned d_bound_kind;
     238                 :            : 
     239                 :            :   std::vector<Node> d_type_references_card;
     240                 :            :   std::map< Node, unsigned > d_type_ref_card_id;
     241                 :            :   std::vector<Node> d_type_references_all;
     242                 :            :   size_t d_card_max;
     243                 :            :   //for empty argument
     244                 :            :   Node d_emp_arg;
     245                 :            :   //map from ( atom, label, child index ) -> label
     246                 :            :   std::map< Node, std::map< Node, std::map< int, Node > > > d_label_map;
     247                 :            : 
     248                 :            :   /**
     249                 :            :    * Maps label sets to their direct parents. A set may have multiple parents
     250                 :            :    * if sep.wand constraints are present.
     251                 :            :    */
     252                 :            :   std::map<Node, std::vector<Node> > d_parentMap;
     253                 :            :   /**
     254                 :            :    * Maps label sets to their direct children. This map is only stored for
     255                 :            :    * labels with children that do not share a root label with the base label.
     256                 :            :    */
     257                 :            :   std::map<Node, std::vector<Node> > d_childrenMap;
     258                 :            : 
     259                 :            :   /**
     260                 :            :    * This sends the lemmas:
     261                 :            :    *   parent = (set.union children)
     262                 :            :    *   (set.inter children_i children_j) = empty, for each i != j
     263                 :            :    * It also stores these relationships in d_parentMap.
     264                 :            :    */
     265                 :            :   void makeDisjointHeap(Node parent, const std::vector<Node>& children);
     266                 :            :   /**
     267                 :            :    * Get the sets that are parents of p and are roots in the graph induced
     268                 :            :    * by d_parentMap.
     269                 :            :    */
     270                 :            :   std::vector<Node> getRootLabels(Node p) const;
     271                 :            :   /**
     272                 :            :    * Do p and q have a root label in common?
     273                 :            :    */
     274                 :            :   bool sharesRootLabel(Node p, Node q) const;
     275                 :            : 
     276                 :            :   //term model
     277                 :            :   std::map< Node, Node > d_tmodel;
     278                 :            :   std::map< Node, Node > d_pto_model;
     279                 :            : 
     280                 :            :   /**
     281                 :            :    * A heap assert info is maintained per set equivalence class. It is
     282                 :            :    * used to ensure that list of positive and negative pto constraints for
     283                 :            :    * all label sets that are equal to a given one are satisfied.
     284                 :            :    *
     285                 :            :    * Note that sets referring to subsets of different heaps may become equated,
     286                 :            :    * e.g. if wand constraints are present. Thus, we keep a list of pto
     287                 :            :    * constraints, which track their labels. In the checkPto method, we
     288                 :            :    * distinguish whether the pto constraints refer to the same heap.
     289                 :            :    */
     290                 :            :   class HeapAssertInfo {
     291                 :            :   public:
     292                 :            :    HeapAssertInfo(context::Context* c);
     293                 :       1496 :    ~HeapAssertInfo() {}
     294                 :            :    /** List of positive pto */
     295                 :            :    NodeList d_posPto;
     296                 :            :    /** List of negative pto */
     297                 :            :    NodeList d_negPto;
     298                 :            :   };
     299                 :            :   std::map< Node, HeapAssertInfo * > d_eqc_info;
     300                 :            :   HeapAssertInfo * getOrMakeEqcInfo( Node n, bool doMake = false );
     301                 :            : 
     302                 :            :   /**
     303                 :            :    * Ensure that reference and data types have been set to something that is
     304                 :            :    * non-null, and compatible with separation logic constraint atom.
     305                 :            :    */
     306                 :            :   void ensureHeapTypesFor(Node atom) const;
     307                 :            :   /**
     308                 :            :    * This is called either when:
     309                 :            :    * (A) a declare-heap command is issued with tn1/tn2, and atom is null, or
     310                 :            :    * (B) an atom specifying the heap type tn1/tn2 is registered to this theory.
     311                 :            :    * We set the heap type if we are are case (A), and check whether the
     312                 :            :    * heap type is consistent in the case of (B).
     313                 :            :    */
     314                 :            :   void registerRefDataTypes(TypeNode tn1, TypeNode tn2, Node atom);
     315                 :            :   //get location/data type
     316                 :            :   //get the base label for the spatial assertion
     317                 :            :   Node getBaseLabel();
     318                 :            :   Node getLabel( Node atom, int child, Node lbl );
     319                 :            :   /**
     320                 :            :    * Apply label lbl to all top-level spatial assertions, recursively, in n.
     321                 :            :    */
     322                 :            :   Node applyLabel( Node n, Node lbl, std::map< Node, Node >& visited );
     323                 :            :   void getLabelChildren( Node atom, Node lbl, std::vector< Node >& children, std::vector< Node >& labels );
     324                 :            : 
     325                 :            :   class HeapInfo {
     326                 :            :   public:
     327                 :       1398 :     HeapInfo() : d_computed(false) {}
     328                 :            :     //information about the model
     329                 :            :     bool d_computed;
     330                 :            :     std::vector< Node > d_heap_locs;
     331                 :            :     std::vector< Node > d_heap_locs_model;
     332                 :            :     //get value
     333                 :            :     Node getValue(NodeManager* nm, TypeNode tn);
     334                 :            :   };
     335                 :            :   //heap info ( label -> HeapInfo )
     336                 :            :   std::map< Node, HeapInfo > d_label_model;
     337                 :            :   /**
     338                 :            :    * This checks the impact of adding the pto assertion p to heap assert info e,
     339                 :            :    * where p has been asserted with the given polarity.
     340                 :            :    *
     341                 :            :    * This method implements two propagation schemes for pairs of
     342                 :            :    * positive/positive and positive/negative pto constraints.
     343                 :            :    *
     344                 :            :    * @param e The heap assert info
     345                 :            :    * @param p The (label) pto constraint
     346                 :            :    * @param polarity Its asserted polarity
     347                 :            :    * @return true if p should be added to the list of constraints in e, false
     348                 :            :    * if the constraint was redundant.
     349                 :            :    */
     350                 :            :   bool checkPto(HeapAssertInfo* e, Node p, bool polarity);
     351                 :            :   void computeLabelModel( Node lbl );
     352                 :            :   Node instantiateLabel(Node n,
     353                 :            :                         Node o_lbl,
     354                 :            :                         Node lbl,
     355                 :            :                         Node lbl_v,
     356                 :            :                         std::map<Node, Node>& visited,
     357                 :            :                         std::map<Node, Node>& pto_model,
     358                 :            :                         TypeNode rtn,
     359                 :            :                         std::map<Node, bool>& active_lbl,
     360                 :            :                         unsigned ind = 0);
     361                 :            :   void setInactiveAssertionRec( Node fact, std::map< Node, std::vector< Node > >& lbl_to_assertions, std::map< Node, bool >& assert_active );
     362                 :            : 
     363                 :            :   Node mkUnion( TypeNode tn, std::vector< Node >& locs );
     364                 :            : 
     365                 :            :   Node getRepresentative( Node t );
     366                 :            :   bool hasTerm( Node a );
     367                 :            :   bool areEqual( Node a, Node b );
     368                 :            :   bool areDisequal( Node a, Node b );
     369                 :            :   void eqNotifyMerge(TNode t1, TNode t2);
     370                 :            : 
     371                 :            :   void sendLemma( std::vector< Node >& ant, Node conc, InferenceId id, bool infer = false );
     372                 :            :   void doPending();
     373                 :            : 
     374                 :            :   void initializeBounds();
     375                 :            : };/* class TheorySep */
     376                 :            : 
     377                 :            : }  // namespace sep
     378                 :            : }  // namespace theory
     379                 :            : }  // namespace cvc5::internal
     380                 :            : 
     381                 :            : #endif /* CVC5__THEORY__SEP__THEORY_SEP_H */

Generated by: LCOV version 1.14