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: 2026-06-24 10:35:45 Functions: 2 2 100.0 %
Branches: 0 0 -

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

Generated by: LCOV version 1.14