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