1 /******************************************************************************
2 * Top contributors (to current version):
3 * Tim King, Andrew Reynolds
5 * This file is part of the cvc5 project.
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 * ****************************************************************************
13 * [[ Add one-line brief description here ]]
15 * [[ Add lengthier description here ]]
16 * \todo document this file
19 #include "theory/arith/infer_bounds.h"
20 #include "theory/rewriter.h"
22 using namespace cvc5::kind
;
28 using namespace inferbounds
;
30 InferBoundAlgorithm::InferBoundAlgorithm()
34 InferBoundAlgorithm::InferBoundAlgorithm(Algorithms a
)
40 InferBoundAlgorithm::InferBoundAlgorithm(
41 const std::optional
<int>& simplexRounds
)
45 Algorithms
InferBoundAlgorithm::getAlgorithm() const{
49 const std::optional
<int>& InferBoundAlgorithm::getSimplexRounds() const
51 Assert(getAlgorithm() == Simplex
);
52 return d_simplexRounds
;
55 InferBoundAlgorithm
InferBoundAlgorithm::mkLookup(){
56 return InferBoundAlgorithm(Lookup
);
59 InferBoundAlgorithm
InferBoundAlgorithm::mkRowSum(){
60 return InferBoundAlgorithm(RowSum
);
63 InferBoundAlgorithm
InferBoundAlgorithm::mkSimplex(
64 const std::optional
<int>& rounds
)
66 return InferBoundAlgorithm(rounds
);
69 ArithEntailmentCheckParameters::ArithEntailmentCheckParameters()
73 ArithEntailmentCheckParameters::~ArithEntailmentCheckParameters()
77 void ArithEntailmentCheckParameters::addLookupRowSumAlgorithms(){
78 addAlgorithm(InferBoundAlgorithm::mkLookup());
79 addAlgorithm(InferBoundAlgorithm::mkRowSum());
82 void ArithEntailmentCheckParameters::addAlgorithm(const inferbounds::InferBoundAlgorithm
& alg
){
83 d_algorithms
.push_back(alg
);
86 ArithEntailmentCheckParameters::const_iterator
ArithEntailmentCheckParameters::begin() const{
87 return d_algorithms
.begin();
90 ArithEntailmentCheckParameters::const_iterator
ArithEntailmentCheckParameters::end() const{
91 return d_algorithms
.end();
94 InferBoundsResult::InferBoundsResult()
96 , d_budgetExhausted(false)
97 , d_boundIsProvenOpt(false)
98 , d_inconsistentState(false)
99 , d_reachedThreshold(false)
101 , d_term(Node::null())
103 , d_explanation(Node::null())
106 InferBoundsResult::InferBoundsResult(Node term
, bool ub
)
107 : d_foundBound(false)
108 , d_budgetExhausted(false)
109 , d_boundIsProvenOpt(false)
110 , d_inconsistentState(false)
111 , d_reachedThreshold(false)
115 , d_explanation(Node::null())
118 bool InferBoundsResult::foundBound() const {
121 bool InferBoundsResult::boundIsOptimal() const {
122 return d_boundIsProvenOpt
;
124 bool InferBoundsResult::inconsistentState() const {
125 return d_inconsistentState
;
128 bool InferBoundsResult::boundIsInteger() const{
129 return foundBound() && d_value
.isIntegral();
132 bool InferBoundsResult::boundIsRational() const {
133 return foundBound() && d_value
.infinitesimalIsZero();
136 Integer
InferBoundsResult::valueAsInteger() const{
137 Assert(boundIsInteger());
138 return getValue().floor();
140 const Rational
& InferBoundsResult::valueAsRational() const{
141 Assert(boundIsRational());
142 return getValue().getNoninfinitesimalPart();
145 const DeltaRational
& InferBoundsResult::getValue() const{
149 Node
InferBoundsResult::getTerm() const { return d_term
; }
151 Node
InferBoundsResult::getLiteral() const{
152 const Rational
& q
= getValue().getNoninfinitesimalPart();
153 NodeManager
* nm
= NodeManager::currentNM();
154 Node qnode
= nm
->mkConst(CONST_RATIONAL
, q
);
159 Assert(getValue().infinitesimalSgn() <= 0);
160 k
= boundIsRational() ? kind::LEQ
: kind::LT
;
163 Assert(getValue().infinitesimalSgn() >= 0);
164 k
= boundIsRational() ? kind::GEQ
: kind::GT
;
166 return nm
->mkNode(k
, getTerm(), qnode
);
169 /* If there is a bound, this is a node that explains the bound. */
170 Node
InferBoundsResult::getExplanation() const{
171 return d_explanation
;
175 void InferBoundsResult::setBound(const DeltaRational
& dr
, Node exp
){
181 void InferBoundsResult::setBudgetExhausted() { d_budgetExhausted
= true; }
182 void InferBoundsResult::setReachedThreshold() { d_reachedThreshold
= true; }
183 void InferBoundsResult::setIsOptimal() { d_boundIsProvenOpt
= true; }
184 void InferBoundsResult::setInconsistent() { d_inconsistentState
= true; }
186 bool InferBoundsResult::thresholdWasReached() const{
187 return d_reachedThreshold
;
189 bool InferBoundsResult::budgetIsExhausted() const{
190 return d_budgetExhausted
;
193 std::ostream
& operator<<(std::ostream
& os
, const InferBoundsResult
& ibr
){
194 os
<< "{InferBoundsResult " << std::endl
;
195 os
<< "on " << ibr
.getTerm() << ", ";
196 if(ibr
.findUpperBound()){
197 os
<< "find upper bound, ";
199 os
<< "find lower bound, ";
201 if(ibr
.foundBound()){
202 os
<< "found a bound: ";
203 if(ibr
.boundIsInteger()){
204 os
<< ibr
.valueAsInteger() << "(int), ";
205 }else if(ibr
.boundIsRational()){
206 os
<< ibr
.valueAsRational() << "(rat), ";
208 os
<< ibr
.getValue() << "(extended), ";
211 os
<< "as term " << ibr
.getLiteral() << ", ";
212 os
<< "explanation " << ibr
.getExplanation() << ", ";
214 os
<< "did not find a bound, ";
217 if(ibr
.boundIsOptimal()){
221 if(ibr
.inconsistentState()){
222 os
<< "(inconsistent), ";
224 if(ibr
.budgetIsExhausted()){
225 os
<< "(budget exhausted), ";
227 if(ibr
.thresholdWasReached()){
228 os
<< "(reached threshold), ";
234 ArithEntailmentCheckSideEffects::ArithEntailmentCheckSideEffects()
235 : d_simplexSideEffects(NULL
)
238 ArithEntailmentCheckSideEffects::~ArithEntailmentCheckSideEffects(){
239 if(d_simplexSideEffects
!= NULL
){
240 delete d_simplexSideEffects
;
241 d_simplexSideEffects
= NULL
;
245 InferBoundsResult
& ArithEntailmentCheckSideEffects::getSimplexSideEffects(){
246 if(d_simplexSideEffects
== NULL
){
247 d_simplexSideEffects
= new InferBoundsResult
;
249 return *d_simplexSideEffects
;
252 namespace inferbounds
{ /* namespace arith */
254 std::ostream
& operator<<(std::ostream
& os
, const Algorithms a
){
256 case None
: os
<< "AlgNone"; break;
257 case Lookup
: os
<< "AlgLookup"; break;
258 case RowSum
: os
<< "AlgRowSum"; break;
259 case Simplex
: os
<< "AlgSimplex"; break;
267 } /* namespace inferbounds */
269 } /* namespace arith */
270 } /* namespace theory */