LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/uf - cardinality_extension.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 49 51 96.1 %
Date: 2024-09-21 10:47:20 Functions: 30 32 93.8 %
Branches: 14 24 58.3 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andrew Reynolds, Morgan Deters, Tim King
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2024 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 UF with cardinality.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "cvc5_private.h"
      17                 :            : 
      18                 :            : #ifndef CVC5__THEORY_UF_STRONG_SOLVER_H
      19                 :            : #define CVC5__THEORY_UF_STRONG_SOLVER_H
      20                 :            : 
      21                 :            : #include "context/cdhashmap.h"
      22                 :            : #include "context/context.h"
      23                 :            : #include "smt/env_obj.h"
      24                 :            : #include "theory/decision_strategy.h"
      25                 :            : #include "theory/theory.h"
      26                 :            : #include "util/statistics_stats.h"
      27                 :            : 
      28                 :            : namespace cvc5::internal {
      29                 :            : namespace theory {
      30                 :            : namespace uf {
      31                 :            : 
      32                 :            : class TheoryUF;
      33                 :            : 
      34                 :            : /**
      35                 :            :  * This module implements a theory solver for UF with cardinality constraints.
      36                 :            :  * For high level details, see Reynolds et al "Finite Model Finding in SMT",
      37                 :            :  * CAV 2013, or Reynolds dissertation "Finite Model Finding in Satisfiability
      38                 :            :  * Modulo Theories".
      39                 :            :  */
      40                 :            : class CardinalityExtension : protected EnvObj
      41                 :            : {
      42                 :            :  protected:
      43                 :            :   typedef context::CDHashMap<Node, bool> NodeBoolMap;
      44                 :            :   typedef context::CDHashMap<Node, int> NodeIntMap;
      45                 :            : 
      46                 :            :  public:
      47                 :            :   /**
      48                 :            :    * Information for incremental conflict/clique finding for a
      49                 :            :    * particular sort.
      50                 :            :    */
      51                 :            :   class SortModel : protected EnvObj
      52                 :            :   {
      53                 :            :    private:
      54                 :            :     std::map< Node, std::vector< int > > d_totality_lems;
      55                 :            :     std::map< TypeNode, std::map< int, std::vector< Node > > > d_sym_break_terms;
      56                 :            :     std::map< Node, int > d_sym_break_index;
      57                 :            : 
      58                 :            :    public:
      59                 :            :     /**
      60                 :            :      * A partition of the current equality graph for which cliques
      61                 :            :      * can occur internally.
      62                 :            :      */
      63                 :            :     class Region
      64                 :            :     {
      65                 :            :      public:
      66                 :            :       /** information stored about each node in region */
      67                 :            :       class RegionNodeInfo {
      68                 :            :       public:
      69                 :            :         /** disequality list for node */
      70                 :            :         class DiseqList {
      71                 :            :         public:
      72                 :      28604 :          DiseqList(context::Context* c) : d_size(c, 0), d_disequalities(c) {}
      73                 :      28604 :          ~DiseqList() {}
      74                 :            : 
      75                 :     619559 :          void setDisequal(Node n, bool valid)
      76                 :            :          {
      77                 :     619559 :            Assert((!isSet(n)) || getDisequalityValue(n) != valid);
      78                 :     619559 :            d_disequalities[n] = valid;
      79         [ +  + ]:     619559 :            d_size = d_size + (valid ? 1 : -1);
      80                 :     619559 :           }
      81                 :    1952860 :           bool isSet(Node n) const {
      82                 :    1952860 :             return d_disequalities.find(n) != d_disequalities.end();
      83                 :            :           }
      84                 :     563565 :           bool getDisequalityValue(Node n) const {
      85 [ -  + ][ -  + ]:     563565 :             Assert(isSet(n));
                 [ -  - ]
      86                 :     563565 :             return (*(d_disequalities.find(n))).second;
      87                 :            :           }
      88                 :            : 
      89                 :     350386 :           int size() const { return d_size; }
      90                 :            :           
      91                 :            :           typedef NodeBoolMap::iterator iterator;
      92                 :     255729 :           iterator begin() { return d_disequalities.begin(); }
      93                 :     693706 :           iterator end() { return d_disequalities.end(); }
      94                 :            : 
      95                 :            :         private:
      96                 :            :          context::CDO<int> d_size;
      97                 :            :          NodeBoolMap d_disequalities;
      98                 :            :         }; /* class DiseqList */
      99                 :            :        public:
     100                 :            :         /** constructor */
     101                 :      14302 :         RegionNodeInfo(context::Context* c)
     102                 :      14302 :             : d_internal(c), d_external(c), d_valid(c, true)
     103                 :            :         {
     104                 :      14302 :           d_disequalities[0] = &d_internal;
     105                 :      14302 :           d_disequalities[1] = &d_external;
     106                 :      14302 :         }
     107                 :      14302 :         ~RegionNodeInfo(){}
     108                 :            :        
     109                 :     107900 :         int getNumDisequalities() const {
     110                 :     107900 :           return d_disequalities[0]->size() + d_disequalities[1]->size();
     111                 :            :         }
     112                 :      81142 :         int getNumExternalDisequalities() const {
     113                 :      81142 :           return d_disequalities[0]->size();
     114                 :            :         }
     115                 :      53444 :         int getNumInternalDisequalities() const {
     116                 :      53444 :           return d_disequalities[1]->size();
     117                 :            :         }
     118                 :            : 
     119                 :    1488970 :         bool valid() const { return d_valid; }
     120                 :     112848 :         void setValid(bool valid) { d_valid = valid; }
     121                 :            : 
     122                 :    1645020 :         DiseqList* get(unsigned i) { return d_disequalities[i]; }
     123                 :            : 
     124                 :            :        private:
     125                 :            :         DiseqList d_internal;
     126                 :            :         DiseqList d_external;
     127                 :            :         context::CDO<bool> d_valid;
     128                 :            :         DiseqList* d_disequalities[2];
     129                 :            :       }; /* class RegionNodeInfo */
     130                 :            : 
     131                 :            :     private:
     132                 :            :       /** conflict find pointer */
     133                 :            :       SortModel* d_cf;
     134                 :            : 
     135                 :            :       context::CDO<size_t> d_testCliqueSize;
     136                 :            :       context::CDO<unsigned> d_splitsSize;
     137                 :            :       //a postulated clique
     138                 :            :       NodeBoolMap d_testClique;
     139                 :            :       //disequalities needed for this clique to happen
     140                 :            :       NodeBoolMap d_splits;
     141                 :            :       //number of valid representatives in this region
     142                 :            :       context::CDO<size_t> d_reps_size;
     143                 :            :       //total disequality size (external)
     144                 :            :       context::CDO<unsigned> d_total_diseq_external;
     145                 :            :       //total disequality size (internal)
     146                 :            :       context::CDO<unsigned> d_total_diseq_internal;
     147                 :            :       /** set rep */
     148                 :            :       void setRep( Node n, bool valid );
     149                 :            :       //region node infomation
     150                 :            :       std::map< Node, RegionNodeInfo* > d_nodes;
     151                 :            :       //whether region is valid
     152                 :            :       context::CDO<bool> d_valid;
     153                 :            : 
     154                 :            :      public:
     155                 :            :       //constructor
     156                 :            :       Region(SortModel* cf, context::Context* c);
     157                 :            :       virtual ~Region();
     158                 :            : 
     159                 :            :       typedef std::map< Node, RegionNodeInfo* >::iterator iterator;
     160                 :     109055 :       iterator begin() { return d_nodes.begin(); }
     161                 :     774557 :       iterator end() { return d_nodes.end(); }
     162                 :            : 
     163                 :            :       typedef NodeBoolMap::iterator split_iterator;
     164                 :       5433 :       split_iterator begin_splits() { return d_splits.begin(); }
     165                 :      43003 :       split_iterator end_splits() { return d_splits.end(); }
     166                 :            : 
     167                 :            :       /** Returns a RegionInfo. */
     168                 :      54228 :       RegionNodeInfo* getRegionInfo(Node n) {
     169 [ -  + ][ -  + ]:      54228 :         Assert(d_nodes.find(n) != d_nodes.end());
                 [ -  - ]
     170                 :      54228 :         return (* (d_nodes.find(n))).second;
     171                 :            :       }
     172                 :            : 
     173                 :            :       /** Returns whether or not d_valid is set in current context. */
     174                 :    2384540 :       bool valid() const { return d_valid; }
     175                 :            : 
     176                 :            :       /** Sets d_valid to the value valid in the current context.*/
     177                 :      60116 :       void setValid(bool valid) { d_valid = valid; }
     178                 :            : 
     179                 :            :       /** add rep */
     180                 :            :       void addRep( Node n );
     181                 :            :       //take node from region
     182                 :            :       void takeNode( Region* r, Node n );
     183                 :            :       //merge with other region
     184                 :            :       void combine( Region* r );
     185                 :            :       /** merge */
     186                 :            :       void setEqual( Node a, Node b );
     187                 :            :       //set n1 != n2 to value 'valid', type is whether it is internal/external
     188                 :            :       void setDisequal( Node n1, Node n2, int type, bool valid );
     189                 :            :       //get num reps
     190                 :     252079 :       size_t getNumReps() const { return d_reps_size; }
     191                 :            :       //get test clique size
     192                 :            :       size_t getTestCliqueSize() const { return d_testCliqueSize; }
     193                 :            :       // has representative
     194                 :     371810 :       bool hasRep( Node n ) {
     195 [ +  + ][ +  + ]:     371810 :         return d_nodes.find(n) != d_nodes.end() && d_nodes[n]->valid();
     196                 :            :       }
     197                 :            :       // is disequal
     198                 :            :       bool isDisequal( Node n1, Node n2, int type );
     199                 :            :       /** get must merge */
     200                 :            :       bool getMustCombine( int cardinality );
     201                 :            :       /** has splits */
     202                 :       3022 :       bool hasSplits() { return d_splitsSize>0; }
     203                 :            :       /** get external disequalities */
     204                 :            :       void getNumExternalDisequalities(std::map< Node, int >& num_ext_disequalities );
     205                 :            :       /** check for cliques */
     206                 :            :       bool check( Theory::Effort level, int cardinality, std::vector< Node >& clique );
     207                 :            :       //print debug
     208                 :            :       void debugPrint( const char* c, bool incClique = false );
     209                 :            : 
     210                 :            :       // Returns the first key in d_nodes.
     211                 :        224 :       Node frontKey() const { return d_nodes.begin()->first; }
     212                 :            :     }; /* class Region */
     213                 :            : 
     214                 :            :    private:
     215                 :            :     /** the type this model is for */
     216                 :            :     TypeNode d_type;
     217                 :            :     /** Reference to the state object */
     218                 :            :     TheoryState& d_state;
     219                 :            :     /** Reference to the inference manager */
     220                 :            :     TheoryInferenceManager& d_im;
     221                 :            :     /** Pointer to the cardinality extension that owns this. */
     222                 :            :     CardinalityExtension* d_thss;
     223                 :            :     /** regions used to d_region_index */
     224                 :            :     context::CDO<size_t> d_regions_index;
     225                 :            :     /** vector of regions */
     226                 :            :     std::vector< Region* > d_regions;
     227                 :            :     /** map from Nodes to index of d_regions they exist in, -1 means invalid */
     228                 :            :     NodeIntMap d_regions_map;
     229                 :            :     /** the score for each node for splitting */
     230                 :            :     NodeIntMap d_split_score;
     231                 :            :     /** number of valid disequalities in d_disequalities */
     232                 :            :     context::CDO<unsigned> d_disequalities_index;
     233                 :            :     /** list of all disequalities */
     234                 :            :     std::vector< Node > d_disequalities;
     235                 :            :     /** number of representatives in all regions */
     236                 :            :     context::CDO<unsigned> d_reps;
     237                 :            : 
     238                 :            :     /** get number of disequalities from node n to region ri */
     239                 :            :     int getNumDisequalitiesToRegion( Node n, int ri );
     240                 :            :     /** get number of disequalities from Region r to other regions */
     241                 :            :     void getDisequalitiesToRegions( int ri, std::map< int, int >& regions_diseq );
     242                 :            :     /** is valid */
     243                 :     554100 :     bool isValid( int ri ) {
     244 [ +  - ][ +  - ]:     554100 :       return ri>=0 && ri<(int)d_regions_index && d_regions[ ri ]->valid();
                 [ +  + ]
     245                 :            :     }
     246                 :            :     /** set split score */
     247                 :            :     void setSplitScore( Node n, int s );
     248                 :            :     /** check if we need to combine region ri */
     249                 :            :     void checkRegion( int ri, bool checkCombine = true );
     250                 :            :     /** force combine region */
     251                 :            :     int forceCombineRegion( int ri, bool useDensity = true );
     252                 :            :     /** merge regions */
     253                 :            :     int combineRegions( int ai, int bi );
     254                 :            :     /** move node n to region ri */
     255                 :            :     void moveNode( Node n, int ri );
     256                 :            :     /** allocate cardinality */
     257                 :            :     void allocateCardinality();
     258                 :            :     /**
     259                 :            :      * Add splits. Returns
     260                 :            :      *   0 = no split,
     261                 :            :      *  -1 = entailed disequality added, or
     262                 :            :      *   1 = split added.
     263                 :            :      */
     264                 :            :     int addSplit(Region* r);
     265                 :            :     /** add clique lemma */
     266                 :            :     void addCliqueLemma(std::vector<Node>& clique);
     267                 :            :     /** cardinality */
     268                 :            :     context::CDO<uint32_t> d_cardinality;
     269                 :            :     /** cardinality literals */
     270                 :            :     std::map<uint32_t, Node> d_cardinality_literal;
     271                 :            :     /** whether a positive cardinality constraint has been asserted */
     272                 :            :     context::CDO<bool> d_hasCard;
     273                 :            :     /** clique lemmas that have been asserted */
     274                 :            :     std::map< int, std::vector< std::vector< Node > > > d_cliques;
     275                 :            :     /** maximum negatively asserted cardinality */
     276                 :            :     context::CDO<uint32_t> d_maxNegCard;
     277                 :            :     /** list of fresh representatives allocated */
     278                 :            :     std::vector< Node > d_fresh_aloc_reps;
     279                 :            :     /** whether we are initialized */
     280                 :            :     context::CDO<bool> d_initialized;
     281                 :            :     /** simple check cardinality */
     282                 :            :     void simpleCheckCardinality();
     283                 :            : 
     284                 :            :    public:
     285                 :            :     SortModel(Env& env,
     286                 :            :               TypeNode tn,
     287                 :            :               TheoryState& state,
     288                 :            :               TheoryInferenceManager& im,
     289                 :            :               CardinalityExtension* thss);
     290                 :            :     virtual ~SortModel();
     291                 :            :     /** initialize */
     292                 :            :     void initialize();
     293                 :            :     /** new node */
     294                 :            :     void newEqClass( Node n );
     295                 :            :     /** merge */
     296                 :            :     void merge( Node a, Node b );
     297                 :            :     /** assert terms are disequal */
     298                 :            :     void assertDisequal( Node a, Node b, Node reason );
     299                 :            :     /** are disequal */
     300                 :            :     bool areDisequal( Node a, Node b );
     301                 :            :     /** check */
     302                 :            :     void check(Theory::Effort level);
     303                 :            :     /** presolve */
     304                 :            :     void presolve();
     305                 :            :     /** assert cardinality */
     306                 :            :     void assertCardinality(uint32_t c, bool val);
     307                 :            :     /** get cardinality */
     308                 :          0 :     uint32_t getCardinality() const { return d_cardinality; }
     309                 :            :     /** has cardinality */
     310                 :          0 :     bool hasCardinalityAsserted() const { return d_hasCard; }
     311                 :            :     /** get cardinality term */
     312                 :            :     TypeNode getType() const { return d_type; }
     313                 :            :     /** get cardinality literal */
     314                 :            :     Node getCardinalityLiteral(uint32_t c);
     315                 :            :     /** get maximum negative cardinality */
     316                 :      95946 :     uint32_t getMaximumNegativeCardinality() const
     317                 :            :     {
     318                 :      95946 :       return d_maxNegCard.get();
     319                 :            :     }
     320                 :            :     //print debug
     321                 :            :     void debugPrint( const char* c );
     322                 :            :     /**
     323                 :            :      * Check at last call effort. This will verify that the model is minimal.
     324                 :            :      * This return lemmas if there are terms in the model that the cardinality
     325                 :            :      * extension was not notified of.
     326                 :            :      *
     327                 :            :      * @return false if current model is not minimal. In this case, lemmas are
     328                 :            :      * sent on the output channel of the UF theory.
     329                 :            :      */
     330                 :            :     bool checkLastCall();
     331                 :            :     /** get number of regions (for debugging) */
     332                 :            :     int getNumRegions();
     333                 :            : 
     334                 :            :    private:
     335                 :            :     /**
     336                 :            :      * Decision strategy for cardinality constraints. This asserts
     337                 :            :      * the minimal constraint positively in the SAT context. For details, see
     338                 :            :      * Section 6.3 of Reynolds et al, "Constraint Solving for Finite Model
     339                 :            :      * Finding in SMT Solvers", TPLP 2017.
     340                 :            :      */
     341                 :            :     class CardinalityDecisionStrategy : public DecisionStrategyFmf
     342                 :            :     {
     343                 :            :      public:
     344                 :            :       CardinalityDecisionStrategy(Env& env, TypeNode type, Valuation valuation);
     345                 :            :       /** make literal (the i^th combined cardinality literal) */
     346                 :            :       Node mkLiteral(unsigned i) override;
     347                 :            :       /** identify */
     348                 :            :       std::string identify() const override;
     349                 :            :      private:
     350                 :            :       /** The type we are considering cardinality constraints for */
     351                 :            :       TypeNode d_type;
     352                 :            :     };
     353                 :            :     /** cardinality decision strategy */
     354                 :            :     std::unique_ptr<CardinalityDecisionStrategy> d_c_dec_strat;
     355                 :            :   }; /** class SortModel */
     356                 :            : 
     357                 :            :  public:
     358                 :            :   CardinalityExtension(Env& env,
     359                 :            :                        TheoryState& state,
     360                 :            :                        TheoryInferenceManager& im,
     361                 :            :                        TheoryUF* th);
     362                 :            :   ~CardinalityExtension();
     363                 :            :   /** get theory */
     364                 :      21330 :   TheoryUF* getTheory() { return d_th; }
     365                 :            :   /** new node */
     366                 :            :   void newEqClass( Node n );
     367                 :            :   /** merge */
     368                 :            :   void merge( Node a, Node b );
     369                 :            :   /** assert terms are disequal */
     370                 :            :   void assertDisequal( Node a, Node b, Node reason );
     371                 :            :   /** assert node */
     372                 :            :   void assertNode( Node n, bool isDecision );
     373                 :            :   /** are disequal */
     374                 :            :   bool areDisequal( Node a, Node b );
     375                 :            :   /** check */
     376                 :            :   void check( Theory::Effort level );
     377                 :            :   /** presolve */
     378                 :            :   void presolve();
     379                 :            :   /** preregister a term */
     380                 :            :   void preRegisterTerm( TNode n );
     381                 :            :   /** identify */
     382                 :            :   std::string identify() const { return std::string("CardinalityExtension"); }
     383                 :            :   //print debug
     384                 :            :   void debugPrint( const char* c );
     385                 :            :   /** get cardinality for node */
     386                 :            :   int getCardinality( Node n );
     387                 :            :   /** get cardinality for type */
     388                 :            :   int getCardinality( TypeNode tn );
     389                 :            :   /** has eqc */
     390                 :            :   bool hasEqc(Node a);
     391                 :            : 
     392                 :            :   class Statistics {
     393                 :            :    public:
     394                 :            :     IntStat d_clique_conflicts;
     395                 :            :     IntStat d_clique_lemmas;
     396                 :            :     IntStat d_split_lemmas;
     397                 :            :     IntStat d_max_model_size;
     398                 :            :     Statistics(StatisticsRegistry& sr);
     399                 :            :   };
     400                 :            :   /** statistics class */
     401                 :            :   Statistics d_statistics;
     402                 :            : 
     403                 :            :  private:
     404                 :            :   /** get sort model */
     405                 :            :   SortModel* getSortModel(Node n);
     406                 :            :   /** initialize */
     407                 :            :   void initializeCombinedCardinality();
     408                 :            :   /** check */
     409                 :            :   void checkCombinedCardinality();
     410                 :            :   /** ensure eqc */
     411                 :            :   void ensureEqc(SortModel* c, Node a);
     412                 :            :   /** ensure eqc for all subterms of n */
     413                 :            :   void ensureEqcRec(Node n);
     414                 :            : 
     415                 :            :   /** Reference to the state object */
     416                 :            :   TheoryState& d_state;
     417                 :            :   /** Reference to the inference manager */
     418                 :            :   TheoryInferenceManager& d_im;
     419                 :            :   /** theory uf pointer */
     420                 :            :   TheoryUF* d_th;
     421                 :            :   /** rep model structure, one for each type */
     422                 :            :   std::map<TypeNode, SortModel*> d_rep_model;
     423                 :            : 
     424                 :            :   /** minimum positive combined cardinality */
     425                 :            :   context::CDO<uint32_t> d_min_pos_com_card;
     426                 :            :   /** Whether the field above has been set */
     427                 :            :   context::CDO<bool> d_min_pos_com_card_set;
     428                 :            :   /**
     429                 :            :    * Decision strategy for combined cardinality constraints. This asserts
     430                 :            :    * the minimal combined cardinality constraint positively in the SAT
     431                 :            :    * context. It is enabled by the ufssFairness option. For details, see
     432                 :            :    * the extension to multiple sorts in Section 6.3 of Reynolds et al,
     433                 :            :    * "Constraint Solving for Finite Model Finding in SMT Solvers", TPLP 2017.
     434                 :            :    */
     435                 :            :   class CombinedCardinalityDecisionStrategy : public DecisionStrategyFmf
     436                 :            :   {
     437                 :            :    public:
     438                 :            :     CombinedCardinalityDecisionStrategy(Env& env, Valuation valuation);
     439                 :            :     /** make literal (the i^th combined cardinality literal) */
     440                 :            :     Node mkLiteral(unsigned i) override;
     441                 :            :     /** identify */
     442                 :            :     std::string identify() const override;
     443                 :            :   };
     444                 :            :   /** combined cardinality decision strategy */
     445                 :            :   std::unique_ptr<CombinedCardinalityDecisionStrategy> d_cc_dec_strat;
     446                 :            :   /** Have we initialized combined cardinality? */
     447                 :            :   context::CDO<bool> d_initializedCombinedCardinality;
     448                 :            : 
     449                 :            :   /** cardinality literals for which we have added */
     450                 :            :   NodeBoolMap d_card_assertions_eqv_lemma;
     451                 :            :   /** the master monotone type (if ufssFairnessMonotone enabled) */
     452                 :            :   TypeNode d_tn_mono_master;
     453                 :            :   std::map<TypeNode, bool> d_tn_mono_slave;
     454                 :            :   /** The minimum positive asserted master cardinality */
     455                 :            :   context::CDO<uint32_t> d_min_pos_tn_master_card;
     456                 :            :   /** Whether the field above has been set */
     457                 :            :   context::CDO<bool> d_min_pos_tn_master_card_set;
     458                 :            :   /** relevant eqc */
     459                 :            :   NodeBoolMap d_rel_eqc;
     460                 :            : }; /* class CardinalityExtension */
     461                 :            : 
     462                 :            : }  // namespace uf
     463                 :            : }  // namespace theory
     464                 :            : }  // namespace cvc5::internal
     465                 :            : 
     466                 :            : #endif /* CVC5__THEORY_UF_STRONG_SOLVER_H */

Generated by: LCOV version 1.14