summaryrefslogtreecommitdiff
path: root/src/theory/arith/nl/nl_solver.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/theory/arith/nl/nl_solver.h')
-rw-r--r--src/theory/arith/nl/nl_solver.h370
1 files changed, 370 insertions, 0 deletions
diff --git a/src/theory/arith/nl/nl_solver.h b/src/theory/arith/nl/nl_solver.h
new file mode 100644
index 000000000..b5176a4dd
--- /dev/null
+++ b/src/theory/arith/nl/nl_solver.h
@@ -0,0 +1,370 @@
+/********************* */
+/*! \file nl_solver.h
+ ** \verbatim
+ ** Top contributors (to current version):
+ ** Andrew Reynolds, Tim King, Tianyi Liang
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
+ ** in the top-level source directory) and their institutional affiliations.
+ ** All rights reserved. See the file COPYING in the top-level source
+ ** directory for licensing information.\endverbatim
+ **
+ ** \brief Solver for standard non-linear constraints
+ **/
+
+#ifndef CVC4__THEORY__ARITH__NL_SOLVER_H
+#define CVC4__THEORY__ARITH__NL_SOLVER_H
+
+#include <map>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "context/cdhashset.h"
+#include "context/cdinsert_hashmap.h"
+#include "context/cdlist.h"
+#include "context/cdqueue.h"
+#include "context/context.h"
+#include "expr/kind.h"
+#include "expr/node.h"
+#include "theory/arith/nl/nl_constraint.h"
+#include "theory/arith/nl/nl_lemma_utils.h"
+#include "theory/arith/nl/nl_model.h"
+#include "theory/arith/nl/nl_monomial.h"
+#include "theory/arith/theory_arith.h"
+
+namespace CVC4 {
+namespace theory {
+namespace arith {
+namespace nl {
+
+typedef std::map<Node, unsigned> NodeMultiset;
+
+/** Non-linear solver class
+ *
+ * This class implements model-based refinement schemes
+ * for non-linear arithmetic, described in:
+ *
+ * - "Invariant Checking of NRA Transition Systems
+ * via Incremental Reduction to LRA with EUF" by
+ * Cimatti et al., TACAS 2017.
+ *
+ * - Section 5 of "Desiging Theory Solvers with
+ * Extensions" by Reynolds et al., FroCoS 2017.
+ */
+class NlSolver
+{
+ typedef std::map<Node, NodeMultiset> MonomialExponentMap;
+ typedef context::CDHashSet<Node, NodeHashFunction> NodeSet;
+
+ public:
+ NlSolver(TheoryArith& containing, NlModel& model);
+ ~NlSolver();
+
+ /** init last call
+ *
+ * This is called at the beginning of last call effort check, where
+ * assertions are the set of assertions belonging to arithmetic,
+ * false_asserts is the subset of assertions that are false in the current
+ * model, and xts is the set of extended function terms that are active in
+ * the current context.
+ */
+ void initLastCall(const std::vector<Node>& assertions,
+ const std::vector<Node>& false_asserts,
+ const std::vector<Node>& xts);
+ //-------------------------------------------- lemma schemas
+ /** check split zero
+ *
+ * Returns a set of theory lemmas of the form
+ * t = 0 V t != 0
+ * where t is a term that exists in the current context.
+ */
+ std::vector<NlLemma> checkSplitZero();
+
+ /** check monomial sign
+ *
+ * Returns a set of valid theory lemmas, based on a
+ * lemma schema which ensures that non-linear monomials
+ * respect sign information based on their facts.
+ * For more details, see Section 5 of "Design Theory
+ * Solvers with Extensions" by Reynolds et al., FroCoS 2017,
+ * Figure 5, this is the schema "Sign".
+ *
+ * Examples:
+ *
+ * x > 0 ^ y > 0 => x*y > 0
+ * x < 0 => x*y*y < 0
+ * x = 0 => x*y*z = 0
+ */
+ std::vector<NlLemma> checkMonomialSign();
+
+ /** check monomial magnitude
+ *
+ * Returns a set of valid theory lemmas, based on a
+ * lemma schema which ensures that comparisons between
+ * non-linear monomials respect the magnitude of their
+ * factors.
+ * For more details, see Section 5 of "Design Theory
+ * Solvers with Extensions" by Reynolds et al., FroCoS 2017,
+ * Figure 5, this is the schema "Magnitude".
+ *
+ * Examples:
+ *
+ * |x|>|y| => |x*z|>|y*z|
+ * |x|>|y| ^ |z|>|w| ^ |x|>=1 => |x*x*z*u|>|y*w|
+ *
+ * Argument c indicates the class of inferences to perform for the
+ * (non-linear) monomials in the vector d_ms. 0 : compare non-linear monomials
+ * against 1, 1 : compare non-linear monomials against variables, 2 : compare
+ * non-linear monomials against other non-linear monomials.
+ */
+ std::vector<NlLemma> checkMonomialMagnitude(unsigned c);
+
+ /** check monomial inferred bounds
+ *
+ * Returns a set of valid theory lemmas, based on a
+ * lemma schema that infers new constraints about existing
+ * terms based on mulitplying both sides of an existing
+ * constraint by a term.
+ * For more details, see Section 5 of "Design Theory
+ * Solvers with Extensions" by Reynolds et al., FroCoS 2017,
+ * Figure 5, this is the schema "Multiply".
+ *
+ * Examples:
+ *
+ * x > 0 ^ (y > z + w) => x*y > x*(z+w)
+ * x < 0 ^ (y > z + w) => x*y < x*(z+w)
+ * ...where (y > z + w) and x*y are a constraint and term
+ * that occur in the current context.
+ */
+ std::vector<NlLemma> checkMonomialInferBounds(
+ std::vector<NlLemma>& nt_lemmas,
+ const std::vector<Node>& asserts,
+ const std::vector<Node>& false_asserts);
+
+ /** check factoring
+ *
+ * Returns a set of valid theory lemmas, based on a
+ * lemma schema that states a relationship betwen monomials
+ * with common factors that occur in the same constraint.
+ *
+ * Examples:
+ *
+ * x*z+y*z > t => ( k = x + y ^ k*z > t )
+ * ...where k is fresh and x*z + y*z > t is a
+ * constraint that occurs in the current context.
+ */
+ std::vector<NlLemma> checkFactoring(const std::vector<Node>& asserts,
+ const std::vector<Node>& false_asserts);
+
+ /** check monomial infer resolution bounds
+ *
+ * Returns a set of valid theory lemmas, based on a
+ * lemma schema which "resolves" upper bounds
+ * of one inequality with lower bounds for another.
+ * This schema is not enabled by default, and can
+ * be enabled by --nl-ext-rbound.
+ *
+ * Examples:
+ *
+ * ( y>=0 ^ s <= x*z ^ x*y <= t ) => y*s <= z*t
+ * ...where s <= x*z and x*y <= t are constraints
+ * that occur in the current context.
+ */
+ std::vector<NlLemma> checkMonomialInferResBounds();
+
+ /** check tangent planes
+ *
+ * Returns a set of valid theory lemmas, based on an
+ * "incremental linearization" of non-linear monomials.
+ * This linearization is accomplished by adding constraints
+ * corresponding to "tangent planes" at the current
+ * model value of each non-linear monomial. In particular
+ * consider the definition for constants a,b :
+ * T_{a,b}( x*y ) = b*x + a*y - a*b.
+ * The lemmas added by this function are of the form :
+ * ( ( x>a ^ y<b) ^ (x<a ^ y>b) ) => x*y < T_{a,b}( x*y )
+ * ( ( x>a ^ y>b) ^ (x<a ^ y<b) ) => x*y > T_{a,b}( x*y )
+ * It is inspired by "Invariant Checking of NRA Transition
+ * Systems via Incremental Reduction to LRA with EUF" by
+ * Cimatti et al., TACAS 2017.
+ * This schema is not terminating in general.
+ * It is not enabled by default, and can
+ * be enabled by --nl-ext-tplanes.
+ *
+ * Examples:
+ *
+ * ( ( x>2 ^ y>5) ^ (x<2 ^ y<5) ) => x*y > 5*x + 2*y - 10
+ * ( ( x>2 ^ y<5) ^ (x<2 ^ y>5) ) => x*y < 5*x + 2*y - 10
+ */
+ std::vector<NlLemma> checkTangentPlanes();
+
+ //-------------------------------------------- end lemma schemas
+ private:
+ // The theory of arithmetic containing this extension.
+ TheoryArith& d_containing;
+ /** Reference to the non-linear model object */
+ NlModel& d_model;
+ /** commonly used terms */
+ Node d_zero;
+ Node d_one;
+ Node d_neg_one;
+ Node d_two;
+ Node d_true;
+ Node d_false;
+ /** Context-independent database of monomial information */
+ MonomialDb d_mdb;
+ /** Context-independent database of constraint information */
+ ConstraintDb d_cdb;
+
+ // ( x*y, x*z, y ) for each pair of monomials ( x*y, x*z ) with common factors
+ std::map<Node, std::map<Node, Node> > d_mono_diff;
+
+ /** cache of terms t for which we have added the lemma ( t = 0 V t != 0 ). */
+ NodeSet d_zero_split;
+
+ // ordering, stores variables and 0,1,-1
+ std::map<Node, unsigned> d_order_vars;
+ std::vector<Node> d_order_points;
+
+ // information about monomials
+ std::vector<Node> d_ms;
+ std::vector<Node> d_ms_vars;
+ std::map<Node, bool> d_ms_proc;
+ std::vector<Node> d_mterms;
+
+ // list of monomials with factors whose model value is non-constant in model
+ // e.g. y*cos( x )
+ std::map<Node, bool> d_m_nconst_factor;
+ /** the set of monomials we should apply tangent planes to */
+ std::unordered_set<Node, NodeHashFunction> d_tplane_refine;
+ /** maps nodes to their factor skolems */
+ std::map<Node, Node> d_factor_skolem;
+ /** tangent plane bounds */
+ std::map<Node, std::map<Node, Node> > d_tangent_val_bound[4];
+ // term -> coeff -> rhs -> ( status, exp, b ),
+ // where we have that : exp => ( coeff * term <status> rhs )
+ // b is true if degree( term ) >= degree( rhs )
+ std::map<Node, std::map<Node, std::map<Node, Kind> > > d_ci;
+ std::map<Node, std::map<Node, std::map<Node, Node> > > d_ci_exp;
+ std::map<Node, std::map<Node, std::map<Node, bool> > > d_ci_max;
+
+ /** Make literal */
+ static Node mkLit(Node a, Node b, int status, bool isAbsolute = false);
+ /** register monomial */
+ void setMonomialFactor(Node a, Node b, const NodeMultiset& common);
+ /** assign order ids */
+ void assignOrderIds(std::vector<Node>& vars,
+ NodeMultiset& d_order,
+ bool isConcrete,
+ bool isAbsolute);
+
+ /** Check whether we have already inferred a relationship between monomials
+ * x and y based on the information in cmp_infers. This computes the
+ * transitive closure of the relation stored in cmp_infers.
+ */
+ bool cmp_holds(Node x,
+ Node y,
+ std::map<Node, std::map<Node, Node> >& cmp_infers,
+ std::vector<Node>& exp,
+ std::map<Node, bool>& visited);
+ /** In the following functions, status states a relationship
+ * between two arithmetic terms, where:
+ * 0 : equal
+ * 1 : greater than or equal
+ * 2 : greater than
+ * -X : (greater -> less)
+ * TODO (#1287) make this an enum?
+ */
+ /** compute the sign of a.
+ *
+ * Calls to this function are such that :
+ * exp => ( oa = a ^ a <status> 0 )
+ *
+ * This function iterates over the factors of a,
+ * where a_index is the index of the factor in a
+ * we are currently looking at.
+ *
+ * This function returns a status, which indicates
+ * a's relationship to 0.
+ * We add lemmas to lem of the form given by the
+ * lemma schema checkSign(...).
+ */
+ int compareSign(Node oa,
+ Node a,
+ unsigned a_index,
+ int status,
+ std::vector<Node>& exp,
+ std::vector<NlLemma>& lem);
+ /** compare monomials a and b
+ *
+ * Initially, a call to this function is such that :
+ * exp => ( oa = a ^ ob = b )
+ *
+ * This function returns true if we can infer a valid
+ * arithmetic lemma of the form :
+ * P => abs( a ) >= abs( b )
+ * where P is true and abs( a ) >= abs( b ) is false in the
+ * current model.
+ *
+ * This function is implemented by "processing" factors
+ * of monomials a and b until an inference of the above
+ * form can be made. For example, if :
+ * a = x*x*y and b = z*w
+ * Assuming we are trying to show abs( a ) >= abs( c ),
+ * then if abs( M( x ) ) >= abs( M( z ) ) where M is the current model,
+ * then we can add abs( x ) >= abs( z ) to our explanation, and
+ * mark one factor of x as processed in a, and
+ * one factor of z as processed in b. The number of processed factors of a
+ * and b are stored in a_exp_proc and b_exp_proc respectively.
+ *
+ * cmp_infers stores information that is helpful
+ * in discarding redundant inferences. For example,
+ * we do not want to infer abs( x ) >= abs( z ) if
+ * we have already inferred abs( x ) >= abs( y ) and
+ * abs( y ) >= abs( z ).
+ * It stores entries of the form (status,t1,t2)->F,
+ * which indicates that we constructed a lemma F that
+ * showed t1 <status> t2.
+ *
+ * We add lemmas to lem of the form given by the
+ * lemma schema checkMagnitude(...).
+ */
+ bool compareMonomial(
+ Node oa,
+ Node a,
+ NodeMultiset& a_exp_proc,
+ Node ob,
+ Node b,
+ NodeMultiset& b_exp_proc,
+ std::vector<Node>& exp,
+ std::vector<NlLemma>& lem,
+ std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers);
+ /** helper function for above
+ *
+ * The difference is the inputs a_index and b_index, which are the indices of
+ * children (factors) in monomials a and b which we are currently looking at.
+ */
+ bool compareMonomial(
+ Node oa,
+ Node a,
+ unsigned a_index,
+ NodeMultiset& a_exp_proc,
+ Node ob,
+ Node b,
+ unsigned b_index,
+ NodeMultiset& b_exp_proc,
+ int status,
+ std::vector<Node>& exp,
+ std::vector<NlLemma>& lem,
+ std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers);
+ /** Get factor skolem for n, add resulting lemmas to lemmas */
+ Node getFactorSkolem(Node n, std::vector<NlLemma>& lemmas);
+}; /* class NlSolver */
+
+} // namespace nl
+} // namespace arith
+} // namespace theory
+} // namespace CVC4
+
+#endif /* CVC4__THEORY__ARITH__NL_SOLVER_H */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback