7b9db4beb6507f863c410e613089f3ae20f76d51
1 /******************************************************************************
2 * Top contributors (to current version):
3 * Andrew Reynolds, Alex Ozdemir, Tim King
5 * This file is part of the cvc5 project.
7 * Copyright (c) 2009-2022 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 * Implementation of common functions for dealing with nodes.
16 #include "arith_utilities.h"
20 using namespace cvc5::internal::kind
;
22 namespace cvc5::internal
{
26 Kind
joinKinds(Kind k1
, Kind k2
)
30 return joinKinds(k2
, k1
);
36 Assert(isRelationOperator(k1
));
37 Assert(isRelationOperator(k2
));
40 if (k2
== LEQ
|| k2
== GEQ
)
66 return UNDEFINED_KIND
;
69 Kind
transKinds(Kind k1
, Kind k2
)
73 return transKinds(k2
, k1
);
79 Assert(isRelationOperator(k1
));
80 Assert(isRelationOperator(k2
));
99 return UNDEFINED_KIND
;
102 bool isTranscendentalKind(Kind k
)
104 // many operators are eliminated during rewriting
105 Assert(k
!= TANGENT
&& k
!= COSINE
&& k
!= COSECANT
106 && k
!= SECANT
&& k
!= COTANGENT
);
107 return k
== EXPONENTIAL
|| k
== SINE
|| k
== PI
;
110 Node
getApproximateConstant(Node c
, bool isLower
, unsigned prec
)
114 Assert(false) << "getApproximateConstant: non-constant input " << c
;
117 Rational cr
= c
.getConst
<Rational
>();
120 unsigned upper
= std::pow(10, prec
);
122 Rational den
= Rational(upper
);
123 if (cr
.getDenominator() < den
.getNumerator())
125 // denominator is not more than precision, we return it
129 int csign
= cr
.sgn();
135 Rational one
= Rational(1);
136 Rational ten
= Rational(10);
137 Rational pow_ten
= Rational(1);
138 // inefficient for large numbers
142 pow_ten
= pow_ten
* ten
;
144 Rational allow_err
= one
/ den
;
146 // now do binary search
147 Rational two
= Rational(2);
148 NodeManager
* nm
= NodeManager::currentNM();
152 unsigned curr
= (lower
+ upper
) / 2;
153 Rational curr_r
= Rational(curr
) / den
;
154 Rational err
= cr
- curr_r
;
155 int esign
= err
.sgn();
156 if (err
.abs() <= allow_err
)
158 if (esign
== 1 && !isLower
)
160 curr_r
= Rational(curr
+ 1) / den
;
162 else if (esign
== -1 && isLower
)
164 curr_r
= Rational(curr
- 1) / den
;
166 curr_r
= curr_r
* pow_ten
;
167 cret
= nm
->mkConst(CONST_RATIONAL
, csign
== 1 ? curr_r
: -curr_r
);
172 // update lower/upper
182 } while (cret
.isNull());
186 void printRationalApprox(const char* c
, Node cr
, unsigned prec
)
190 Assert(false) << "printRationalApprox: non-constant input " << cr
;
194 Node ca
= getApproximateConstant(cr
, true, prec
);
202 Trace(c
) << " [0,10^" << prec
<< "])";
206 Node
arithSubstitute(Node n
, const Subs
& sub
)
208 NodeManager
* nm
= NodeManager::currentNM();
209 std::unordered_map
<TNode
, Node
> visited
;
210 std::vector
<TNode
> visit
;
214 TNode cur
= visit
.back();
216 auto it
= visited
.find(cur
);
218 if (it
== visited
.end())
220 visited
[cur
] = Node::null();
221 Kind ck
= cur
.getKind();
222 auto s
= sub
.find(cur
);
227 else if (cur
.getNumChildren() == 0)
233 TheoryId ctid
= theory::kindToTheoryId(ck
);
234 if ((ctid
!= THEORY_ARITH
&& ctid
!= THEORY_BOOL
235 && ctid
!= THEORY_BUILTIN
)
236 || isTranscendentalKind(ck
))
238 // Do not traverse beneath applications that belong to another theory
239 // besides (core) arithmetic. Notice that transcendental function
240 // applications are also not traversed here.
245 visit
.push_back(cur
);
246 for (const Node
& cn
: cur
)
253 else if (it
->second
.isNull())
256 bool childChanged
= false;
257 std::vector
<Node
> children
;
258 if (cur
.getMetaKind() == kind::metakind::PARAMETERIZED
)
260 children
.push_back(cur
.getOperator());
262 for (const Node
& cn
: cur
)
264 it
= visited
.find(cn
);
265 Assert(it
!= visited
.end());
266 Assert(!it
->second
.isNull());
267 childChanged
= childChanged
|| cn
!= it
->second
;
268 children
.push_back(it
->second
);
272 ret
= nm
->mkNode(cur
.getKind(), children
);
276 } while (!visit
.empty());
277 Assert(visited
.find(n
) != visited
.end());
278 Assert(!visited
.find(n
)->second
.isNull());
282 Node
mkBounded(Node l
, Node a
, Node u
)
284 NodeManager
* nm
= NodeManager::currentNM();
285 return nm
->mkNode(AND
, nm
->mkNode(GEQ
, a
, l
), nm
->mkNode(LEQ
, a
, u
));
288 Rational
leastIntGreaterThan(const Rational
& q
) { return q
.floor() + 1; }
290 Rational
greatestIntLessThan(const Rational
& q
) { return q
.ceiling() - 1; }
292 Node
negateProofLiteral(TNode n
)
294 auto nm
= NodeManager::currentNM();
299 return nm
->mkNode(Kind::LEQ
, n
[0], n
[1]);
303 return nm
->mkNode(Kind::GEQ
, n
[0], n
[1]);
307 return nm
->mkNode(Kind::GT
, n
[0], n
[1]);
311 return nm
->mkNode(Kind::LT
, n
[0], n
[1]);
318 default: Unhandled() << n
;
322 Node
multConstants(const Node
& c1
, const Node
& c2
)
324 Assert(!c1
.isNull() && c1
.isConst());
325 Assert(!c2
.isNull() && c2
.isConst());
326 NodeManager
* nm
= NodeManager::currentNM();
327 // real type if either has type real
328 TypeNode tn
= c1
.getType();
333 Assert(tn
.isRealOrInt());
334 return nm
->mkConstRealOrInt(
335 tn
, Rational(c1
.getConst
<Rational
>() * c2
.getConst
<Rational
>()));
339 } // namespace theory
340 } // namespace cvc5::internal