Fix for pre-C++11 is_sorted().
[cvc5.git] / src / theory / arith / normal_form.h
1 /********************* */
2 /*! \file normal_form.h
3 ** \verbatim
4 ** Original author: Tim King
5 ** Major contributors: none
6 ** Minor contributors (to current version): Dejan Jovanovic, Morgan Deters
7 ** This file is part of the CVC4 project.
8 ** Copyright (c) 2009-2013 New York University and The University of Iowa
9 ** See the file COPYING in the top-level source directory for licensing
10 ** information.\endverbatim
11 **
12 ** \brief [[ Add one-line brief description here ]]
13 **
14 ** [[ Add lengthier description here ]]
15 ** \todo document this file
16 **/
17
18 #include "cvc4_private.h"
19
20 #ifndef __CVC4__THEORY__ARITH__NORMAL_FORM_H
21 #define __CVC4__THEORY__ARITH__NORMAL_FORM_H
22
23 #include "expr/node.h"
24 #include "expr/node_self_iterator.h"
25 #include "util/rational.h"
26 #include "theory/arith/delta_rational.h"
27 //#include "theory/arith/arith_utilities.h"
28
29 #include <list>
30 #include <algorithm>
31
32 #if IS_SORTED_IN_GNUCXX_NAMESPACE
33 # include <ext/algorithm>
34 #endif /* IS_SORTED_IN_GNUCXX_NAMESPACE */
35
36 namespace CVC4 {
37 namespace theory {
38 namespace arith {
39
40 /***********************************************/
41 /***************** Normal Form *****************/
42 /***********************************************/
43 /***********************************************/
44
45 /**
46 * Section 1: Languages
47 * The normal form for arithmetic nodes is defined by the language
48 * accepted by the following BNFs with some guard conditions.
49 * (The guard conditions are in Section 3 for completeness.)
50 *
51 * variable := n
52 * where
53 * n.isVar() or is foreign
54 * n.getType() \in {Integer, Real}
55 *
56 * constant := n
57 * where
58 * n.getKind() == kind::CONST_RATIONAL
59 *
60 * var_list := variable | (* [variable])
61 * where
62 * len [variable] >= 2
63 * isSorted varOrder [variable]
64 *
65 * monomial := constant | var_list | (* constant' var_list')
66 * where
67 * \f$ constant' \not\in {0,1} \f$
68 *
69 * polynomial := monomial' | (+ [monomial])
70 * where
71 * len [monomial] >= 2
72 * isStrictlySorted monoOrder [monomial]
73 * forall (\x -> x != 0) [monomial]
74 *
75 * rational_cmp := (|><| qpolynomial constant)
76 * where
77 * |><| is GEQ, or GT
78 * not (exists constantMonomial (monomialList qpolynomial))
79 * (exists realMonomial (monomialList qpolynomial))
80 * abs(monomialCoefficient (head (monomialList qpolynomial))) == 1
81 *
82 * integer_cmp := (>= zpolynomial constant)
83 * where
84 * not (exists constantMonomial (monomialList zpolynomial))
85 * (forall integerMonomial (monomialList zpolynomial))
86 * the gcd of all numerators of coefficients is 1
87 * the denominator of all coefficients and the constant is 1
88 * the leading coefficient is positive
89 *
90 * rational_eq := (= qvarlist qpolynomial)
91 * where
92 * let allMonomials = (cons qvarlist (monomialList zpolynomial))
93 * let variableMonomials = (drop constantMonomial allMonomials)
94 * isStrictlySorted variableMonomials
95 * exists realMonomial variableMonomials
96 * is not empty qvarlist
97 *
98 * integer_eq := (= zmonomial zpolynomial)
99 * where
100 * let allMonomials = (cons zmonomial (monomialList zpolynomial))
101 * let variableMonomials = (drop constantMonomial allMonomials)
102 * not (constantMonomial zmonomial)
103 * (forall integerMonomial allMonomials)
104 * isStrictlySorted variableMonomials
105 * the gcd of all numerators of coefficients is 1
106 * the denominator of all coefficients and the constant is 1
107 * the coefficient of monomial is positive
108 * the value of the coefficient of monomial is minimal in variableMonomials
109 *
110 * comparison := TRUE | FALSE
111 * | rational_cmp | (not rational_cmp)
112 * | rational_eq | (not rational_eq)
113 * | integer_cmp | (not integer_cmp)
114 * | integer_eq | (not integer_eq)
115 *
116 * Normal Form for terms := polynomial
117 * Normal Form for atoms := comparison
118 */
119
120 /**
121 * Section 2: Helper Classes
122 * The langauges accepted by each of these defintions
123 * roughly corresponds to one of the following helper classes:
124 * Variable
125 * Constant
126 * VarList
127 * Monomial
128 * Polynomial
129 * Comparison
130 *
131 * Each of the classes obeys the following contracts/design decisions:
132 * -Calling isMember(Node node) on a node returns true iff that node is a
133 * a member of the language. Note: isMember is O(n).
134 * -Calling isNormalForm() on a helper class object returns true iff that
135 * helper class currently represents a normal form object.
136 * -If isNormalForm() is false, then this object must have been made
137 * using a mk*() factory function.
138 * -If isNormalForm() is true, calling getNode() on all of these classes
139 * returns a node that would be accepted by the corresponding language.
140 * And if isNormalForm() is false, returns Node::null().
141 * -Each of the classes is immutable.
142 * -Public facing constuctors have a 1-to-1 correspondence with one of
143 * production rules in the above grammar.
144 * -Public facing constuctors are required to fail in debug mode when the
145 * guards of the production rule are not strictly met.
146 * For example: Monomial(Constant(1),VarList(Variable(x))) must fail.
147 * -When a class has a Class parseClass(Node node) function,
148 * if isMember(node) is true, the function is required to return an instance
149 * of the helper class, instance, s.t. instance.getNode() == node.
150 * And if isMember(node) is false, this throws an assertion failure in debug
151 * mode and has undefined behaviour if not in debug mode.
152 * -Only public facing constructors, parseClass(node), and mk*() functions are
153 * considered privileged functions for the helper class.
154 * -Only privileged functions may use private constructors, and access
155 * private data members.
156 * -All non-privileged functions are considered utility functions and
157 * must use a privileged function in order to create an instance of the class.
158 */
159
160 /**
161 * Section 3: Guard Conditions Misc.
162 *
163 *
164 * variable_order x y =
165 * if (meta_kind_variable x) and (meta_kind_variable y)
166 * then node_order x y
167 * else if (meta_kind_variable x)
168 * then false
169 * else if (meta_kind_variable y)
170 * then true
171 * else node_order x y
172 *
173 * var_list_len vl =
174 * match vl with
175 * variable -> 1
176 * | (* [variable]) -> len [variable]
177 *
178 * order res =
179 * match res with
180 * Empty -> (0,Node::null())
181 * | NonEmpty(vl) -> (var_list_len vl, vl)
182 *
183 * var_listOrder a b = tuple_cmp (order a) (order b)
184 *
185 * monomialVarList monomial =
186 * match monomial with
187 * constant -> Empty
188 * | var_list -> NonEmpty(var_list)
189 * | (* constant' var_list') -> NonEmpty(var_list')
190 *
191 * monoOrder m0 m1 = var_listOrder (monomialVarList m0) (monomialVarList m1)
192 *
193 * integerMonomial mono =
194 * forall varHasTypeInteger (monomialVarList mono)
195 *
196 * realMonomial mono = not (integerMonomial mono)
197 *
198 * constantMonomial monomial =
199 * match monomial with
200 * constant -> true
201 * | var_list -> false
202 * | (* constant' var_list') -> false
203 *
204 * monomialCoefficient monomial =
205 * match monomial with
206 * constant -> constant
207 * | var_list -> Constant(1)
208 * | (* constant' var_list') -> constant'
209 *
210 * monomialList polynomial =
211 * match polynomial with
212 * monomial -> monomial::[]
213 * | (+ [monomial]) -> [monomial]
214 */
215
216 /**
217 * A NodeWrapper is a class that is a thinly veiled container of a Node object.
218 */
219 class NodeWrapper {
220 private:
221 Node node;
222 public:
223 NodeWrapper(Node n) : node(n) {}
224 const Node& getNode() const { return node; }
225 };/* class NodeWrapper */
226
227
228 class Variable : public NodeWrapper {
229 public:
230 Variable(Node n) : NodeWrapper(n) {
231 Assert(isMember(getNode()));
232 }
233
234 // TODO: check if it's a theory leaf also
235 static bool isMember(Node n) {
236 Kind k = n.getKind();
237 switch(k){
238 case kind::CONST_RATIONAL:
239 return false;
240 case kind::INTS_DIVISION:
241 case kind::INTS_MODULUS:
242 case kind::DIVISION:
243 case kind::INTS_DIVISION_TOTAL:
244 case kind::INTS_MODULUS_TOTAL:
245 case kind::DIVISION_TOTAL:
246 return isDivMember(n);
247 case kind::ABS:
248 case kind::TO_INTEGER:
249 // Treat to_int as a variable; it is replaced in early preprocessing
250 // by a variable.
251 return true;
252 default:
253 return isLeafMember(n);
254 }
255 }
256
257 static bool isLeafMember(Node n);
258 static bool isDivMember(Node n);
259 bool isDivLike() const{
260 return isDivMember(getNode());
261 }
262
263 bool isNormalForm() { return isMember(getNode()); }
264
265 bool isIntegral() const {
266 return getNode().getType().isInteger();
267 }
268
269 bool isMetaKindVariable() const {
270 return getNode().isVar();
271 }
272
273 bool operator<(const Variable& v) const {
274 VariableNodeCmp cmp;
275 return cmp(this->getNode(), v.getNode());
276 }
277
278 struct VariableNodeCmp {
279 static inline int cmp(Node n, Node m) {
280 if ( n == m ) { return 0; }
281
282 // this is now slightly off of the old variable order.
283
284 bool nIsInteger = n.getType().isInteger();
285 bool mIsInteger = m.getType().isInteger();
286
287 if(nIsInteger == mIsInteger){
288 bool nIsVariable = n.isVar();
289 bool mIsVariable = m.isVar();
290
291 if(nIsVariable == mIsVariable){
292 if(n < m){
293 return -1;
294 }else{
295 Assert( n != m );
296 return 1;
297 }
298 }else{
299 if(nIsVariable){
300 return -1; // nIsVariable => !mIsVariable
301 }else{
302 return 1; // !nIsVariable => mIsVariable
303 }
304 }
305 }else{
306 Assert(nIsInteger != mIsInteger);
307 if(nIsInteger){
308 return 1; // nIsInteger => !mIsInteger
309 }else{
310 return -1; // !nIsInteger => mIsInteger
311 }
312 }
313 }
314
315 bool operator()(Node n, Node m) const {
316 return VariableNodeCmp::cmp(n,m) < 0;
317 }
318 };
319
320 bool operator==(const Variable& v) const { return getNode() == v.getNode();}
321
322 size_t getComplexity() const;
323 };/* class Variable */
324
325
326 class Constant : public NodeWrapper {
327 public:
328 Constant(Node n) : NodeWrapper(n) {
329 Assert(isMember(getNode()));
330 }
331
332 static bool isMember(Node n) {
333 return n.getKind() == kind::CONST_RATIONAL;
334 }
335
336 bool isNormalForm() { return isMember(getNode()); }
337
338 static Constant mkConstant(Node n) {
339 Assert(n.getKind() == kind::CONST_RATIONAL);
340 return Constant(n);
341 }
342
343 static Constant mkConstant(const Rational& rat);
344
345 static Constant mkZero() {
346 return mkConstant(Rational(0));
347 }
348
349 static Constant mkOne() {
350 return mkConstant(Rational(1));
351 }
352
353 const Rational& getValue() const {
354 return getNode().getConst<Rational>();
355 }
356
357 static int absCmp(const Constant& a, const Constant& b);
358 bool isIntegral() const { return getValue().isIntegral(); }
359
360 int sgn() const { return getValue().sgn(); }
361
362 bool isZero() const { return sgn() == 0; }
363 bool isNegative() const { return sgn() < 0; }
364 bool isPositive() const { return sgn() > 0; }
365
366 bool isOne() const { return getValue() == 1; }
367
368 Constant operator*(const Rational& other) const {
369 return mkConstant(getValue() * other);
370 }
371
372 Constant operator*(const Constant& other) const {
373 return mkConstant(getValue() * other.getValue());
374 }
375 Constant operator+(const Constant& other) const {
376 return mkConstant(getValue() + other.getValue());
377 }
378 Constant operator-() const {
379 return mkConstant(-getValue());
380 }
381
382 Constant inverse() const{
383 Assert(!isZero());
384 return mkConstant(getValue().inverse());
385 }
386
387 bool operator<(const Constant& other) const {
388 return getValue() < other.getValue();
389 }
390
391 bool operator==(const Constant& other) const {
392 //Rely on node uniqueness.
393 return getNode() == other.getNode();
394 }
395
396 Constant abs() const {
397 if(isNegative()){
398 return -(*this);
399 }else{
400 return (*this);
401 }
402 }
403
404 uint32_t length() const{
405 Assert(isIntegral());
406 return getValue().getNumerator().length();
407 }
408
409 size_t getComplexity() const;
410
411 };/* class Constant */
412
413
414 template <class GetNodeIterator>
415 inline Node makeNode(Kind k, GetNodeIterator start, GetNodeIterator end) {
416 NodeBuilder<> nb(k);
417
418 while(start != end) {
419 nb << (*start).getNode();
420 ++start;
421 }
422
423 return Node(nb);
424 }/* makeNode<GetNodeIterator>(Kind, iterator, iterator) */
425
426
427 template <class GetNodeIterator, class T>
428 static void copy_range(GetNodeIterator begin, GetNodeIterator end, std::vector<T>& result){
429 while(begin != end){
430 result.push_back(*begin);
431 ++begin;
432 }
433 }
434
435 template <class GetNodeIterator, class T>
436 static void merge_ranges(GetNodeIterator first1,
437 GetNodeIterator last1,
438 GetNodeIterator first2,
439 GetNodeIterator last2,
440 std::vector<T>& result) {
441
442 while(first1 != last1 && first2 != last2){
443 if( (*first1) < (*first2) ){
444 result.push_back(*first1);
445 ++ first1;
446 }else{
447 result.push_back(*first2);
448 ++ first2;
449 }
450 }
451 copy_range(first1, last1, result);
452 copy_range(first2, last2, result);
453 }
454
455 template <class GetNodeIterator, class T, class Cmp>
456 static void merge_ranges(GetNodeIterator first1,
457 GetNodeIterator last1,
458 GetNodeIterator first2,
459 GetNodeIterator last2,
460 std::vector<T>& result,
461 const Cmp& cmp) {
462
463 while(first1 != last1 && first2 != last2){
464 if( cmp(*first1, *first2) ){
465 result.push_back(*first1);
466 ++ first1;
467 }else{
468 result.push_back(*first2);
469 ++ first2;
470 }
471 }
472 copy_range(first1, last1, result);
473 copy_range(first2, last2, result);
474 }
475
476 /**
477 * A VarList is a sorted list of variables representing a product.
478 * If the VarList is empty, it represents an empty product or 1.
479 * If the VarList has size 1, it represents a single variable.
480 *
481 * A non-sorted VarList can never be successfully made in debug mode.
482 */
483 class VarList : public NodeWrapper {
484 private:
485
486 static Node multList(const std::vector<Variable>& list) {
487 Assert(list.size() >= 2);
488
489 return makeNode(kind::MULT, list.begin(), list.end());
490 }
491
492 VarList() : NodeWrapper(Node::null()) {}
493
494 VarList(Node n);
495
496 typedef expr::NodeSelfIterator internal_iterator;
497
498 internal_iterator internalBegin() const {
499 if(singleton()){
500 return expr::NodeSelfIterator::self(getNode());
501 }else{
502 return getNode().begin();
503 }
504 }
505
506 internal_iterator internalEnd() const {
507 if(singleton()){
508 return expr::NodeSelfIterator::selfEnd(getNode());
509 }else{
510 return getNode().end();
511 }
512 }
513
514 public:
515
516 class iterator : public std::iterator<std::input_iterator_tag, Variable> {
517 private:
518 internal_iterator d_iter;
519
520 public:
521 explicit iterator(internal_iterator i) : d_iter(i) {}
522
523 inline Variable operator*() {
524 return Variable(*d_iter);
525 }
526
527 bool operator==(const iterator& i) {
528 return d_iter == i.d_iter;
529 }
530
531 bool operator!=(const iterator& i) {
532 return d_iter != i.d_iter;
533 }
534
535 iterator operator++() {
536 ++d_iter;
537 return *this;
538 }
539
540 iterator operator++(int) {
541 return iterator(d_iter++);
542 }
543 };
544
545 iterator begin() const {
546 return iterator(internalBegin());
547 }
548
549 iterator end() const {
550 return iterator(internalEnd());
551 }
552
553 Variable getHead() const {
554 Assert(!empty());
555 return *(begin());
556 }
557
558 VarList(Variable v) : NodeWrapper(v.getNode()) {
559 Assert(isSorted(begin(), end()));
560 }
561
562 VarList(const std::vector<Variable>& l) : NodeWrapper(multList(l)) {
563 Assert(l.size() >= 2);
564 Assert(isSorted(begin(), end()));
565 }
566
567 static bool isMember(Node n);
568
569 bool isNormalForm() const {
570 return !empty();
571 }
572
573 static VarList mkEmptyVarList() {
574 return VarList();
575 }
576
577
578 /** There are no restrictions on the size of l */
579 static VarList mkVarList(const std::vector<Variable>& l) {
580 if(l.size() == 0) {
581 return mkEmptyVarList();
582 } else if(l.size() == 1) {
583 return VarList((*l.begin()).getNode());
584 } else {
585 return VarList(l);
586 }
587 }
588
589 bool empty() const { return getNode().isNull(); }
590 bool singleton() const {
591 return !empty() && getNode().getKind() != kind::MULT;
592 }
593
594 int size() const {
595 if(singleton())
596 return 1;
597 else
598 return getNode().getNumChildren();
599 }
600
601 static VarList parseVarList(Node n);
602
603 VarList operator*(const VarList& vl) const;
604
605 int cmp(const VarList& vl) const;
606
607 bool operator<(const VarList& vl) const { return cmp(vl) < 0; }
608
609 bool operator==(const VarList& vl) const { return cmp(vl) == 0; }
610
611 bool isIntegral() const {
612 for(iterator i = begin(), e=end(); i != e; ++i ){
613 Variable var = *i;
614 if(!var.isIntegral()){
615 return false;
616 }
617 }
618 return true;
619 }
620 size_t getComplexity() const;
621
622 private:
623 bool isSorted(iterator start, iterator end);
624
625 };/* class VarList */
626
627
628 class Monomial : public NodeWrapper {
629 private:
630 Constant constant;
631 VarList varList;
632 Monomial(Node n, const Constant& c, const VarList& vl):
633 NodeWrapper(n), constant(c), varList(vl)
634 {
635 Assert(!c.isZero() || vl.empty() );
636 Assert( c.isZero() || !vl.empty() );
637
638 Assert(!c.isOne() || !multStructured(n));
639 }
640
641 static Node makeMultNode(const Constant& c, const VarList& vl) {
642 Assert(!c.isZero());
643 Assert(!c.isOne());
644 Assert(!vl.empty());
645 return NodeManager::currentNM()->mkNode(kind::MULT, c.getNode(), vl.getNode());
646 }
647
648 static bool multStructured(Node n) {
649 return n.getKind() == kind::MULT &&
650 n[0].getKind() == kind::CONST_RATIONAL &&
651 n.getNumChildren() == 2;
652 }
653
654 public:
655
656 Monomial(const Constant& c):
657 NodeWrapper(c.getNode()), constant(c), varList(VarList::mkEmptyVarList())
658 { }
659
660 Monomial(const VarList& vl):
661 NodeWrapper(vl.getNode()), constant(Constant::mkConstant(1)), varList(vl)
662 {
663 Assert( !varList.empty() );
664 }
665
666 Monomial(const Constant& c, const VarList& vl):
667 NodeWrapper(makeMultNode(c,vl)), constant(c), varList(vl)
668 {
669 Assert( !c.isZero() );
670 Assert( !c.isOne() );
671 Assert( !varList.empty() );
672
673 Assert(multStructured(getNode()));
674 }
675
676 static bool isMember(TNode n);
677
678 /** Makes a monomial with no restrictions on c and vl. */
679 static Monomial mkMonomial(const Constant& c, const VarList& vl);
680
681 static Monomial mkMonomial(const Variable& v){
682 return Monomial(VarList(v));
683 }
684
685 static Monomial parseMonomial(Node n);
686
687 static Monomial mkZero() {
688 return Monomial(Constant::mkConstant(0));
689 }
690 static Monomial mkOne() {
691 return Monomial(Constant::mkConstant(1));
692 }
693 const Constant& getConstant() const { return constant; }
694 const VarList& getVarList() const { return varList; }
695
696 bool isConstant() const {
697 return varList.empty();
698 }
699
700 bool isZero() const {
701 return constant.isZero();
702 }
703
704 bool coefficientIsOne() const {
705 return constant.isOne();
706 }
707
708 bool absCoefficientIsOne() const {
709 return coefficientIsOne() || constant.getValue() == -1;
710 }
711
712 bool constantIsPositive() const {
713 return getConstant().isPositive();
714 }
715
716 Monomial operator*(const Rational& q) const;
717 Monomial operator*(const Constant& c) const;
718 Monomial operator*(const Monomial& mono) const;
719
720 Monomial operator-() const{
721 return (*this) * Rational(-1);
722 }
723
724
725 int cmp(const Monomial& mono) const {
726 return getVarList().cmp(mono.getVarList());
727 }
728
729 bool operator<(const Monomial& vl) const {
730 return cmp(vl) < 0;
731 }
732
733 bool operator==(const Monomial& vl) const {
734 return cmp(vl) == 0;
735 }
736
737 static bool isSorted(const std::vector<Monomial>& m) {
738 #if IS_SORTED_IN_GNUCXX_NAMESPACE
739 return __gnu_cxx::is_sorted(m.begin(), m.end());
740 #else /* IS_SORTED_IN_GNUCXX_NAMESPACE */
741 return std::is_sorted(m.begin(), m.end());
742 #endif /* IS_SORTED_IN_GNUCXX_NAMESPACE */
743 }
744
745 static bool isStrictlySorted(const std::vector<Monomial>& m) {
746 return isSorted(m) && std::adjacent_find(m.begin(),m.end()) == m.end();
747 }
748
749 static void sort(std::vector<Monomial>& m);
750 static void combineAdjacentMonomials(std::vector<Monomial>& m);
751
752 /**
753 * The variable product
754 */
755 bool integralVariables() const {
756 return getVarList().isIntegral();
757 }
758
759 /**
760 * The coefficient of the monomial is integral.
761 */
762 bool integralCoefficient() const {
763 return getConstant().isIntegral();
764 }
765
766 /**
767 * A Monomial is an "integral" monomial if the constant is integral.
768 */
769 bool isIntegral() const {
770 return integralCoefficient() && integralVariables();
771 }
772
773 /** Returns true if the VarList is a product of at least 2 Variables.*/
774 bool isNonlinear() const {
775 return getVarList().size() >= 2;
776 }
777
778 /**
779 * Given a sorted list of monomials, this function transforms this
780 * into a strictly sorted list of monomials that does not contain zero.
781 */
782 //static std::vector<Monomial> sumLikeTerms(const std::vector<Monomial>& monos);
783
784 int absCmp(const Monomial& other) const{
785 return getConstant().getValue().absCmp(other.getConstant().getValue());
786 }
787 // bool absLessThan(const Monomial& other) const{
788 // return getConstant().abs() < other.getConstant().abs();
789 // }
790
791 uint32_t coefficientLength() const{
792 return getConstant().length();
793 }
794
795 void print() const;
796 static void printList(const std::vector<Monomial>& list);
797
798 size_t getComplexity() const;
799 };/* class Monomial */
800
801 class SumPair;
802 class Comparison;;
803
804 class Polynomial : public NodeWrapper {
805 private:
806 bool d_singleton;
807
808 Polynomial(TNode n) : NodeWrapper(n), d_singleton(Monomial::isMember(n)) {
809 Assert(isMember(getNode()));
810 }
811
812 static Node makePlusNode(const std::vector<Monomial>& m) {
813 Assert(m.size() >= 2);
814
815 return makeNode(kind::PLUS, m.begin(), m.end());
816 }
817
818 typedef expr::NodeSelfIterator internal_iterator;
819
820 internal_iterator internalBegin() const {
821 if(singleton()){
822 return expr::NodeSelfIterator::self(getNode());
823 }else{
824 return getNode().begin();
825 }
826 }
827
828 internal_iterator internalEnd() const {
829 if(singleton()){
830 return expr::NodeSelfIterator::selfEnd(getNode());
831 }else{
832 return getNode().end();
833 }
834 }
835
836 bool singleton() const { return d_singleton; }
837
838 public:
839 static bool isMember(TNode n);
840
841 class iterator {
842 private:
843 internal_iterator d_iter;
844
845 public:
846 explicit iterator(internal_iterator i) : d_iter(i) {}
847
848 inline Monomial operator*() {
849 return Monomial::parseMonomial(*d_iter);
850 }
851
852 bool operator==(const iterator& i) {
853 return d_iter == i.d_iter;
854 }
855
856 bool operator!=(const iterator& i) {
857 return d_iter != i.d_iter;
858 }
859
860 iterator operator++() {
861 ++d_iter;
862 return *this;
863 }
864
865 iterator operator++(int) {
866 return iterator(d_iter++);
867 }
868 };
869
870 iterator begin() const { return iterator(internalBegin()); }
871 iterator end() const { return iterator(internalEnd()); }
872
873 Polynomial(const Monomial& m):
874 NodeWrapper(m.getNode()), d_singleton(true)
875 {}
876
877 Polynomial(const std::vector<Monomial>& m):
878 NodeWrapper(makePlusNode(m)), d_singleton(false)
879 {
880 Assert( m.size() >= 2);
881 Assert( Monomial::isStrictlySorted(m) );
882 }
883
884 static Polynomial mkPolynomial(const Variable& v){
885 return Monomial::mkMonomial(v);
886 }
887
888 static Polynomial mkPolynomial(const std::vector<Monomial>& m) {
889 if(m.size() == 0) {
890 return Polynomial(Monomial::mkZero());
891 } else if(m.size() == 1) {
892 return Polynomial((*m.begin()));
893 } else {
894 return Polynomial(m);
895 }
896 }
897
898 static Polynomial parsePolynomial(Node n) {
899 return Polynomial(n);
900 }
901
902 static Polynomial mkZero() {
903 return Polynomial(Monomial::mkZero());
904 }
905 static Polynomial mkOne() {
906 return Polynomial(Monomial::mkOne());
907 }
908 bool isZero() const {
909 return singleton() && (getHead().isZero());
910 }
911
912 bool isConstant() const {
913 return singleton() && (getHead().isConstant());
914 }
915
916 bool containsConstant() const {
917 return getHead().isConstant();
918 }
919
920 uint32_t size() const{
921 if(singleton()){
922 return 1;
923 }else{
924 Assert(getNode().getKind() == kind::PLUS);
925 return getNode().getNumChildren();
926 }
927 }
928
929 Monomial getHead() const {
930 return *(begin());
931 }
932
933 Polynomial getTail() const {
934 Assert(! singleton());
935
936 iterator tailStart = begin();
937 ++tailStart;
938 std::vector<Monomial> subrange;
939 copy_range(tailStart, end(), subrange);
940 return mkPolynomial(subrange);
941 }
942
943 Monomial minimumVariableMonomial() const;
944 bool variableMonomialAreStrictlyGreater(const Monomial& m) const;
945
946 void printList() const {
947 if(Debug.isOn("normal-form")){
948 Debug("normal-form") << "start list" << std::endl;
949 for(iterator i = begin(), oend = end(); i != oend; ++i) {
950 const Monomial& m =*i;
951 m.print();
952 }
953 Debug("normal-form") << "end list" << std::endl;
954 }
955 }
956
957 /** A Polynomial is an "integral" polynomial if all of the monomials are integral. */
958 bool allIntegralVariables() const {
959 for(iterator i = begin(), e=end(); i!=e; ++i){
960 if(!(*i).integralVariables()){
961 return false;
962 }
963 }
964 return true;
965 }
966
967 /**
968 * A Polynomial is an "integral" polynomial if all of the monomials are integral
969 * and all of the coefficients are Integral. */
970 bool isIntegral() const {
971 for(iterator i = begin(), e=end(); i!=e; ++i){
972 if(!(*i).isIntegral()){
973 return false;
974 }
975 }
976 return true;
977 }
978
979 static Polynomial sumPolynomials(const std::vector<Polynomial>& polynomials);
980
981 /** Returns true if the polynomial contains a non-linear monomial.*/
982 bool isNonlinear() const;
983
984
985 /**
986 * Selects a minimal monomial in the polynomial by the absolute value of
987 * the coefficient.
988 */
989 Monomial selectAbsMinimum() const;
990
991 /** Returns true if the absolute value of the head coefficient is one. */
992 bool leadingCoefficientIsAbsOne() const;
993 bool leadingCoefficientIsPositive() const;
994 bool denominatorLCMIsOne() const;
995 bool numeratorGCDIsOne() const;
996
997 bool signNormalizedReducedSum() const {
998 return leadingCoefficientIsPositive() && denominatorLCMIsOne() && numeratorGCDIsOne();
999 }
1000
1001 /**
1002 * Returns the Least Common Multiple of the denominators of the coefficients
1003 * of the monomials.
1004 */
1005 Integer denominatorLCM() const;
1006
1007 /**
1008 * Returns the GCD of the numerators of the monomials.
1009 * Requires this to be an isIntegral() polynomial.
1010 */
1011 Integer numeratorGCD() const;
1012
1013 /**
1014 * Returns the GCD of the coefficients of the monomials.
1015 * Requires this to be an isIntegral() polynomial.
1016 */
1017 Integer gcd() const;
1018
1019 Polynomial exactDivide(const Integer& z) const {
1020 Assert(isIntegral());
1021 Constant invz = Constant::mkConstant(Rational(1,z));
1022 Polynomial prod = (*this) * Monomial(invz);
1023 Assert(prod.isIntegral());
1024 return prod;
1025 }
1026
1027 Polynomial operator+(const Polynomial& vl) const;
1028 Polynomial operator-(const Polynomial& vl) const;
1029 Polynomial operator-() const{
1030 return (*this) * Rational(-1);
1031 }
1032
1033 Polynomial operator*(const Rational& q) const;
1034 Polynomial operator*(const Constant& c) const;
1035 Polynomial operator*(const Monomial& mono) const;
1036
1037 Polynomial operator*(const Polynomial& poly) const;
1038
1039 /**
1040 * Viewing the integer polynomial as a list [(* coeff_i mono_i)]
1041 * The quotient and remainder of p divided by the non-zero integer z is:
1042 * q := [(* floor(coeff_i/z) mono_i )]
1043 * r := [(* rem(coeff_i/z) mono_i)]
1044 * computeQR(p,z) returns the node (+ q r).
1045 *
1046 * q and r are members of the Polynomial class.
1047 * For example:
1048 * computeQR( p = (+ 5 (* 3 x) (* 8 y)) , z = 2) returns
1049 * (+ (+ 2 x (* 4 y)) (+ 1 x))
1050 */
1051 static Node computeQR(const Polynomial& p, const Integer& z);
1052
1053 /** Returns the coefficient associated with the VarList in the polynomial. */
1054 Constant getCoefficient(const VarList& vl) const;
1055
1056 uint32_t maxLength() const{
1057 iterator i = begin(), e=end();
1058 if( i == e){
1059 return 1;
1060 }else{
1061 uint32_t max = (*i).coefficientLength();
1062 ++i;
1063 for(; i!=e; ++i){
1064 uint32_t curr = (*i).coefficientLength();
1065 if(curr > max){
1066 max = curr;
1067 }
1068 }
1069 return max;
1070 }
1071 }
1072
1073 uint32_t numMonomials() const {
1074 if( getNode().getKind() == kind::PLUS ){
1075 return getNode().getNumChildren();
1076 }else if(isZero()){
1077 return 0;
1078 }else{
1079 return 1;
1080 }
1081 }
1082
1083 const Rational& asConstant() const{
1084 Assert(isConstant());
1085 return getNode().getConst<Rational>();
1086 //return getHead().getConstant().getValue();
1087 }
1088
1089 bool isVarList() const {
1090 if(singleton()){
1091 return VarList::isMember(getNode());
1092 }else{
1093 return false;
1094 }
1095 }
1096
1097 VarList asVarList() const {
1098 Assert(isVarList());
1099 return getHead().getVarList();
1100 }
1101
1102 size_t getComplexity() const;
1103
1104 friend class SumPair;
1105 friend class Comparison;
1106
1107 /** Returns a node that if asserted ensures v is the abs of this polynomial.*/
1108 Node makeAbsCondition(Variable v){
1109 return makeAbsCondition(v, *this);
1110 }
1111
1112 /** Returns a node that if asserted ensures v is the abs of p.*/
1113 static Node makeAbsCondition(Variable v, Polynomial p);
1114
1115 };/* class Polynomial */
1116
1117
1118 /**
1119 * SumPair is a utility class that extends polynomials for use in computations.
1120 * A SumPair is always a combination of (+ p c) where
1121 * c is a constant and p is a polynomial such that p = 0 or !p.containsConstant().
1122 *
1123 * These are a useful utility for representing the equation p = c as (+ p -c) where the pair
1124 * is known to implicitly be equal to 0.
1125 *
1126 * SumPairs do not have unique representations due to the potential for p = 0.
1127 * This makes them inappropriate for normal forms.
1128 */
1129 class SumPair : public NodeWrapper {
1130 private:
1131 static Node toNode(const Polynomial& p, const Constant& c){
1132 return NodeManager::currentNM()->mkNode(kind::PLUS, p.getNode(), c.getNode());
1133 }
1134
1135 SumPair(TNode n) :
1136 NodeWrapper(n)
1137 {
1138 Assert(isNormalForm());
1139 }
1140
1141 public:
1142
1143 SumPair(const Polynomial& p):
1144 NodeWrapper(toNode(p, Constant::mkConstant(0)))
1145 {
1146 Assert(isNormalForm());
1147 }
1148
1149 SumPair(const Polynomial& p, const Constant& c):
1150 NodeWrapper(toNode(p, c))
1151 {
1152 Assert(isNormalForm());
1153 }
1154
1155 static bool isMember(TNode n) {
1156 if(n.getKind() == kind::PLUS && n.getNumChildren() == 2){
1157 if(Constant::isMember(n[1])){
1158 if(Polynomial::isMember(n[0])){
1159 Polynomial p = Polynomial::parsePolynomial(n[0]);
1160 return p.isZero() || (!p.containsConstant());
1161 }else{
1162 return false;
1163 }
1164 }else{
1165 return false;
1166 }
1167 }else{
1168 return false;
1169 }
1170 }
1171
1172 bool isNormalForm() const {
1173 return isMember(getNode());
1174 }
1175
1176 Polynomial getPolynomial() const {
1177 return Polynomial::parsePolynomial(getNode()[0]);
1178 }
1179
1180 Constant getConstant() const {
1181 return Constant::mkConstant((getNode())[1]);
1182 }
1183
1184 SumPair operator+(const SumPair& other) const {
1185 return SumPair(getPolynomial() + other.getPolynomial(),
1186 getConstant() + other.getConstant());
1187 }
1188
1189 SumPair operator*(const Constant& c) const {
1190 return SumPair(getPolynomial() * c, getConstant() * c);
1191 }
1192
1193 SumPair operator-(const SumPair& other) const {
1194 return (*this) + (other * Constant::mkConstant(-1));
1195 }
1196
1197 static SumPair mkSumPair(const Polynomial& p);
1198
1199 static SumPair mkSumPair(const Variable& var){
1200 return SumPair(Polynomial::mkPolynomial(var));
1201 }
1202
1203 static SumPair parseSumPair(TNode n){
1204 return SumPair(n);
1205 }
1206
1207 bool isIntegral() const{
1208 return getConstant().isIntegral() && getPolynomial().isIntegral();
1209 }
1210
1211 bool isConstant() const {
1212 return getPolynomial().isZero();
1213 }
1214
1215 bool isZero() const {
1216 return getConstant().isZero() && isConstant();
1217 }
1218
1219 uint32_t size() const{
1220 return getPolynomial().size();
1221 }
1222
1223 bool isNonlinear() const{
1224 return getPolynomial().isNonlinear();
1225 }
1226
1227 /**
1228 * Returns the greatest common divisor of gcd(getPolynomial()) and getConstant().
1229 * The SumPair must be integral.
1230 */
1231 Integer gcd() const {
1232 Assert(isIntegral());
1233 return (getPolynomial().gcd()).gcd(getConstant().getValue().getNumerator());
1234 }
1235
1236 uint32_t maxLength() const {
1237 Assert(isIntegral());
1238 return std::max(getPolynomial().maxLength(), getConstant().length());
1239 }
1240
1241 static SumPair mkZero() {
1242 return SumPair(Polynomial::mkZero(), Constant::mkConstant(0));
1243 }
1244
1245 static Node computeQR(const SumPair& sp, const Integer& div);
1246
1247 };/* class SumPair */
1248
1249 /* class OrderedPolynomialPair { */
1250 /* private: */
1251 /* Polynomial d_first; */
1252 /* Polynomial d_second; */
1253 /* public: */
1254 /* OrderedPolynomialPair(const Polynomial& f, const Polynomial& s) */
1255 /* : d_first(f), */
1256 /* d_second(s) */
1257 /* {} */
1258
1259 /* /\** Returns the first part of the pair. *\/ */
1260 /* const Polynomial& getFirst() const { */
1261 /* return d_first; */
1262 /* } */
1263
1264 /* /\** Returns the second part of the pair. *\/ */
1265 /* const Polynomial& getSecond() const { */
1266 /* return d_second; */
1267 /* } */
1268
1269 /* OrderedPolynomialPair operator*(const Constant& c) const; */
1270 /* OrderedPolynomialPair operator+(const Polynomial& p) const; */
1271
1272 /* /\** Returns true if both of the polynomials are constant. *\/ */
1273 /* bool isConstant() const; */
1274
1275 /* /\** */
1276 /* * Evaluates an isConstant() ordered pair as if */
1277 /* * (k getFirst() getRight()) */
1278 /* *\/ */
1279 /* bool evaluateConstant(Kind k) const; */
1280
1281 /* /\** */
1282 /* * Returns the Least Common Multiple of the monomials */
1283 /* * on the lefthand side and the constant on the right. */
1284 /* *\/ */
1285 /* Integer denominatorLCM() const; */
1286
1287 /* /\** Constructs a SumPair. *\/ */
1288 /* SumPair toSumPair() const; */
1289
1290
1291 /* OrderedPolynomialPair divideByGCD() const; */
1292 /* OrderedPolynomialPair multiplyConstant(const Constant& c) const; */
1293
1294 /* /\** */
1295 /* * Returns true if all of the variables are integers, */
1296 /* * and the coefficients are integers. */
1297 /* *\/ */
1298 /* bool isIntegral() const; */
1299
1300 /* /\** Returns true if all of the variables are integers. *\/ */
1301 /* bool allIntegralVariables() const { */
1302 /* return getFirst().allIntegralVariables() && getSecond().allIntegralVariables(); */
1303 /* } */
1304 /* }; */
1305
1306 class Comparison : public NodeWrapper {
1307 private:
1308
1309 static Node toNode(Kind k, const Polynomial& l, const Constant& c);
1310 static Node toNode(Kind k, const Polynomial& l, const Polynomial& r);
1311
1312 Comparison(TNode n);
1313
1314 /**
1315 * Creates a node in normal form equivalent to (= l 0).
1316 * All variables in l are integral.
1317 */
1318 static Node mkIntEquality(const Polynomial& l);
1319
1320 /**
1321 * Creates a comparison equivalent to (k l 0).
1322 * k is either GT or GEQ.
1323 * All variables in l are integral.
1324 */
1325 static Node mkIntInequality(Kind k, const Polynomial& l);
1326
1327 /**
1328 * Creates a node equivalent to (= l 0).
1329 * It is not the case that all variables in l are integral.
1330 */
1331 static Node mkRatEquality(const Polynomial& l);
1332
1333 /**
1334 * Creates a comparison equivalent to (k l 0).
1335 * k is either GT or GEQ.
1336 * It is not the case that all variables in l are integral.
1337 */
1338 static Node mkRatInequality(Kind k, const Polynomial& l);
1339
1340 public:
1341
1342 Comparison(bool val) :
1343 NodeWrapper(NodeManager::currentNM()->mkConst(val))
1344 { }
1345
1346 /**
1347 * Given a literal to TheoryArith return a single kind to
1348 * to indicate its underlying structure.
1349 * The function returns the following in each case:
1350 * - (K left right) -> K where is either EQUAL, GT, or GEQ
1351 * - (CONST_BOOLEAN b) -> CONST_BOOLEAN
1352 * - (NOT (EQUAL left right)) -> DISTINCT
1353 * - (NOT (GT left right)) -> LEQ
1354 * - (NOT (GEQ left right)) -> LT
1355 * If none of these match, it returns UNDEFINED_KIND.
1356 */
1357 static Kind comparisonKind(TNode literal);
1358
1359 Kind comparisonKind() const { return comparisonKind(getNode()); }
1360
1361 static Comparison mkComparison(Kind k, const Polynomial& l, const Polynomial& r);
1362
1363 /** Returns true if the comparison is a boolean constant. */
1364 bool isBoolean() const;
1365
1366 /**
1367 * Returns true if the comparison is either a boolean term,
1368 * in integer normal form or mixed normal form.
1369 */
1370 bool isNormalForm() const;
1371
1372 private:
1373 bool isNormalGT() const;
1374 bool isNormalGEQ() const;
1375
1376 bool isNormalLT() const;
1377 bool isNormalLEQ() const;
1378
1379 bool isNormalEquality() const;
1380 bool isNormalDistinct() const;
1381 bool isNormalEqualityOrDisequality() const;
1382
1383 bool allIntegralVariables() const {
1384 return getLeft().allIntegralVariables() && getRight().allIntegralVariables();
1385 }
1386 bool rightIsConstant() const;
1387
1388 public:
1389 Polynomial getLeft() const;
1390 Polynomial getRight() const;
1391
1392 /* /\** Normal form check if at least one variable is real. *\/ */
1393 /* bool isMixedCompareNormalForm() const; */
1394
1395 /* /\** Normal form check if at least one variable is real. *\/ */
1396 /* bool isMixedEqualsNormalForm() const; */
1397
1398 /* /\** Normal form check is all variables are integer.*\/ */
1399 /* bool isIntegerCompareNormalForm() const; */
1400
1401 /* /\** Normal form check is all variables are integer.*\/ */
1402 /* bool isIntegerEqualsNormalForm() const; */
1403
1404
1405 /**
1406 * Returns true if all of the variables are integers, the coefficients are integers,
1407 * and the right hand coefficient is an integer.
1408 */
1409 bool debugIsIntegral() const;
1410
1411 static Comparison parseNormalForm(TNode n);
1412
1413 inline static bool isNormalAtom(TNode n){
1414 Comparison parse = Comparison::parseNormalForm(n);
1415 return parse.isNormalForm();
1416 }
1417
1418 size_t getComplexity() const;
1419
1420 SumPair toSumPair() const;
1421
1422 Polynomial normalizedVariablePart() const;
1423 DeltaRational normalizedDeltaRational() const;
1424
1425 };/* class Comparison */
1426
1427 }/* CVC4::theory::arith namespace */
1428 }/* CVC4::theory namespace */
1429 }/* CVC4 namespace */
1430
1431 #endif /* __CVC4__THEORY__ARITH__NORMAL_FORM_H */