GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/normal_form.h Lines: 375 382 98.2 %
Date: 2021-11-08 Branches: 421 1107 38.0 %

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