GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/nl/cad/cdcac.h Lines: 2 2 100.0 %
Date: 2021-11-07 Branches: 0 0 0.0 %

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