LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/arith/nl/coverings - cdcac.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2 2 100.0 %
Date: 2025-02-26 13:09:00 Functions: 2 2 100.0 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Gereon Kremer, Andrew Reynolds, Aina Niemetz
       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                 :            :  * Implements the CDCAC approach as described in
      14                 :            :  * https://arxiv.org/pdf/2003.05633.pdf.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include "cvc5_private.h"
      18                 :            : 
      19                 :            : #ifndef CVC5__THEORY__ARITH__NL__COVERINGS__CDCAC_H
      20                 :            : #define CVC5__THEORY__ARITH__NL__COVERINGS__CDCAC_H
      21                 :            : 
      22                 :            : #ifdef CVC5_POLY_IMP
      23                 :            : 
      24                 :            : #include <poly/polyxx.h>
      25                 :            : 
      26                 :            : #include <vector>
      27                 :            : 
      28                 :            : #include "smt/env.h"
      29                 :            : #include "smt/env_obj.h"
      30                 :            : #include "theory/arith/nl/coverings/cdcac_utils.h"
      31                 :            : #include "theory/arith/nl/coverings/constraints.h"
      32                 :            : #include "theory/arith/nl/coverings/lazard_evaluation.h"
      33                 :            : #include "theory/arith/nl/coverings/proof_generator.h"
      34                 :            : #include "theory/arith/nl/coverings/variable_ordering.h"
      35                 :            : 
      36                 :            : namespace cvc5::internal {
      37                 :            : namespace theory {
      38                 :            : namespace arith {
      39                 :            : namespace nl {
      40                 :            : 
      41                 :            : class NlModel;
      42                 :            : 
      43                 :            : namespace coverings {
      44                 :            : 
      45                 :            : /**
      46                 :            :  * This class implements Cylindrical Algebraic Coverings as presented in
      47                 :            :  * https://arxiv.org/pdf/2003.05633.pdf
      48                 :            :  */
      49                 :            : class CDCAC : protected EnvObj
      50                 :            : {
      51                 :            :  public:
      52                 :            :   /** Initialize this method with the given variable ordering. */
      53                 :            :   CDCAC(Env& env, const std::vector<poly::Variable>& ordering = {});
      54                 :            : 
      55                 :            :   /** Reset this instance. */
      56                 :            :   void reset();
      57                 :            : 
      58                 :            :   /** Collect variables from the constraints and compute a variable ordering. */
      59                 :            :   void computeVariableOrdering();
      60                 :            : 
      61                 :            :   /**
      62                 :            :    * Extract an initial assignment from the given model.
      63                 :            :    * This initial assignment is used to guide sampling if possible.
      64                 :            :    * The ran_variable should be the variable used to encode real algebraic
      65                 :            :    * numbers in the model and is simply passed on to node_to_value.
      66                 :            :    */
      67                 :            :   void retrieveInitialAssignment(NlModel& model, const Node& ran_variable);
      68                 :            : 
      69                 :            :   /**
      70                 :            :    * Returns the constraints as a non-const reference. Can be used to add new
      71                 :            :    * constraints.
      72                 :            :    */
      73                 :            :   Constraints& getConstraints();
      74                 :            :   /** Returns the constraints as a const reference. */
      75                 :            :   const Constraints& getConstraints() const;
      76                 :            : 
      77                 :            :   /**
      78                 :            :    * Returns the current assignment. This is a satisfying model if
      79                 :            :    * get_unsat_cover() returned an empty vector.
      80                 :            :    */
      81                 :            :   const poly::Assignment& getModel() const;
      82                 :            : 
      83                 :            :   /** Returns the current variable ordering. */
      84                 :            :   const std::vector<poly::Variable>& getVariableOrdering() const;
      85                 :            : 
      86                 :            :   /**
      87                 :            :    * Collect all unsatisfiable intervals for the given variable.
      88                 :            :    * Combines unsatisfiable regions from d_constraints evaluated over
      89                 :            :    * d_assignment. Implements Algorithm 2.
      90                 :            :    */
      91                 :            :   std::vector<CACInterval> getUnsatIntervals(std::size_t cur_variable);
      92                 :            : 
      93                 :            :   /**
      94                 :            :    * Sample outside of the set of intervals.
      95                 :            :    * Uses a given initial value from mInitialAssignment if possible.
      96                 :            :    * Returns whether a sample was found (true) or the infeasible intervals cover
      97                 :            :    * the whole real line (false).
      98                 :            :    */
      99                 :            :   bool sampleOutsideWithInitial(const std::vector<CACInterval>& infeasible,
     100                 :            :                                 poly::Value& sample,
     101                 :            :                                 std::size_t cur_variable);
     102                 :            : 
     103                 :            :   /**
     104                 :            :    * Collects the coefficients required for projection from the given
     105                 :            :    * polynomial. Implements Algorithm 6, depending on the command line
     106                 :            :    * arguments. Either directly implements Algorithm 6, or improved variants
     107                 :            :    * based on Lazard's projection.
     108                 :            :    */
     109                 :            :   PolyVector requiredCoefficients(const poly::Polynomial& p);
     110                 :            : 
     111                 :            :   /**
     112                 :            :    * Constructs a characterization of the given covering.
     113                 :            :    * A characterization contains polynomials whose roots bound the region around
     114                 :            :    * the current assignment. Implements Algorithm 4.
     115                 :            :    */
     116                 :            :   PolyVector constructCharacterization(std::vector<CACInterval>& intervals);
     117                 :            : 
     118                 :            :   /**
     119                 :            :    * Constructs an infeasible interval from a characterization.
     120                 :            :    * Implements Algorithm 5.
     121                 :            :    */
     122                 :            :   CACInterval intervalFromCharacterization(const PolyVector& characterization,
     123                 :            :                                            std::size_t cur_variable,
     124                 :            :                                            const poly::Value& sample);
     125                 :            : 
     126                 :            :   /**
     127                 :            :    * Internal implementation of getUnsatCover().
     128                 :            :    * @param curVariable The id of the variable (within d_variableOrdering) to
     129                 :            :    * be considered. This argument is used to manage the recursion internally and
     130                 :            :    * should always be zero if called externally.
     131                 :            :    * @param returnFirstInterval If true, the function returns after the first
     132                 :            :    * interval obtained from a recursive call. The result is not (necessarily) an
     133                 :            :    * unsat cover, but merely a list of infeasible intervals.
     134                 :            :    */
     135                 :            :   std::vector<CACInterval> getUnsatCoverImpl(std::size_t curVariable = 0,
     136                 :            :                                              bool returnFirstInterval = false);
     137                 :            : 
     138                 :            :   /**
     139                 :            :    * Main method that checks for the satisfiability of the constraints.
     140                 :            :    * Recursively explores possible assignments and excludes regions based on the
     141                 :            :    * coverings. Returns either a covering for the lowest dimension or an empty
     142                 :            :    * vector. If the covering is empty, the result is SAT and an assignment can
     143                 :            :    * be obtained from d_assignment. If the covering is not empty, the result is
     144                 :            :    * UNSAT and an infeasible subset can be extracted from the returned covering.
     145                 :            :    * Implements Algorithm 2.
     146                 :            :    * This method itself only takes care of the outermost proof scope and calls
     147                 :            :    * out to getUnsatCoverImpl() with curVariable set to zero.
     148                 :            :    * @param returnFirstInterval If true, the function returns after the first
     149                 :            :    * interval obtained from a recursive call. The result is not (necessarily) an
     150                 :            :    * unsat cover, but merely a list of infeasible intervals.
     151                 :            :    */
     152                 :            :   std::vector<CACInterval> getUnsatCover(bool returnFirstInterval = false);
     153                 :            : 
     154                 :            :   void startNewProof();
     155                 :            :   /**
     156                 :            :    * Finish the generated proof (if proofs are enabled) with a scope over the
     157                 :            :    * given assertions.
     158                 :            :    */
     159                 :            :   ProofGenerator* closeProof(const std::vector<Node>& assertions);
     160                 :            : 
     161                 :            :   /** Get the proof generator */
     162                 :          1 :   CoveringsProofGenerator* getProof() { return d_proof.get(); }
     163                 :            : 
     164                 :            :  private:
     165                 :            :   /** Check whether proofs are enabled */
     166                 :      19755 :   bool isProofEnabled() const { return d_proof != nullptr; }
     167                 :            : 
     168                 :            :   /**
     169                 :            :    * Check whether the current sample satisfies the integrality condition of the
     170                 :            :    * current variable. Returns true if the variable is not integral or the
     171                 :            :    * sample is integral.
     172                 :            :    */
     173                 :            :   bool checkIntegrality(std::size_t cur_variable, const poly::Value& value);
     174                 :            :   /**
     175                 :            :    * Constructs an interval that excludes the non-integral region around the
     176                 :            :    * current sample. Assumes !check_integrality(cur_variable, value).
     177                 :            :    */
     178                 :            :   CACInterval buildIntegralityInterval(std::size_t cur_variable,
     179                 :            :                                        const poly::Value& value);
     180                 :            : 
     181                 :            :   /**
     182                 :            :    * Check whether the polynomial has a real root above the given value (when
     183                 :            :    * evaluated over the current assignment).
     184                 :            :    */
     185                 :            :   bool hasRootAbove(const poly::Polynomial& p, const poly::Value& val) const;
     186                 :            :   /**
     187                 :            :    * Check whether the polynomial has a real root below the given value (when
     188                 :            :    * evaluated over the current assignment).
     189                 :            :    */
     190                 :            :   bool hasRootBelow(const poly::Polynomial& p, const poly::Value& val) const;
     191                 :            : 
     192                 :            :   /**
     193                 :            :    * Sort intervals according to section 4.4.1. and removes fully redundant
     194                 :            :    * intervals as in 4.5. 1. by calling out to cleanIntervals.
     195                 :            :    * Additionally makes sure to prune proofs for removed intervals.
     196                 :            :    */
     197                 :            :   void pruneRedundantIntervals(std::vector<CACInterval>& intervals);
     198                 :            : 
     199                 :            :   /**
     200                 :            :    * Prepare the lazard evaluation object with the current assignment, if the
     201                 :            :    * lazard lifting is enabled. Otherwise, this function does nothing.
     202                 :            :    */
     203                 :            :   void prepareRootIsolation(LazardEvaluation& le, size_t cur_variable) const;
     204                 :            : 
     205                 :            :   /**
     206                 :            :    * Isolates the real roots of the polynomial `p`. If the lazard lifting is
     207                 :            :    * enabled, this function uses `le.isolateRealRoots()`, otherwise uses the
     208                 :            :    * regular `poly::isolate_real_roots()`.
     209                 :            :    */
     210                 :            :   std::vector<poly::Value> isolateRealRoots(LazardEvaluation& le,
     211                 :            :                                             const poly::Polynomial& p) const;
     212                 :            : 
     213                 :            :   /**
     214                 :            :    * The current assignment. When the method terminates with SAT, it contains a
     215                 :            :    * model for the input constraints.
     216                 :            :    */
     217                 :            :   poly::Assignment d_assignment;
     218                 :            : 
     219                 :            :   /** The set of input constraints to be checked for consistency. */
     220                 :            :   Constraints d_constraints;
     221                 :            : 
     222                 :            :   /** The computed variable ordering used for this method. */
     223                 :            :   std::vector<poly::Variable> d_variableOrdering;
     224                 :            : 
     225                 :            :   /** The object computing the variable ordering. */
     226                 :            :   VariableOrdering d_varOrder;
     227                 :            : 
     228                 :            :   /** The linear assignment used as an initial guess. */
     229                 :            :   std::vector<poly::Value> d_initialAssignment;
     230                 :            : 
     231                 :            :   /** The proof generator */
     232                 :            :   std::unique_ptr<CoveringsProofGenerator> d_proof;
     233                 :            : 
     234                 :            :   /** The next interval id */
     235                 :            :   size_t d_nextIntervalId = 1;
     236                 :            : };
     237                 :            : 
     238                 :            : }  // namespace coverings
     239                 :            : }  // namespace nl
     240                 :            : }  // namespace arith
     241                 :            : }  // namespace theory
     242                 :            : }  // namespace cvc5::internal
     243                 :            : 
     244                 :            : #endif
     245                 :            : 
     246                 :            : #endif

Generated by: LCOV version 1.14