GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/normal_form.cpp Lines: 642 793 81.0 %
Date: 2021-05-21 Branches: 1091 2958 36.9 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Tim King, Gereon Kremer, Andrew Reynolds
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
#include "theory/arith/normal_form.h"
19
20
#include <list>
21
22
#include "base/output.h"
23
#include "theory/arith/arith_utilities.h"
24
#include "theory/theory.h"
25
26
using namespace std;
27
28
namespace cvc5 {
29
namespace theory {
30
namespace arith {
31
32
134107156
Constant Constant::mkConstant(const Rational& rat) {
33
134107156
  return Constant(mkRationalNode(rat));
34
}
35
36
size_t Variable::getComplexity() const{
37
  return 1u;
38
}
39
40
size_t VarList::getComplexity() const{
41
  if(empty()){
42
    return 1;
43
  }else if(singleton()){
44
    return 1;
45
  }else{
46
    return size() + 1;
47
  }
48
}
49
50
size_t Monomial::getComplexity() const{
51
  return getConstant().getComplexity() + getVarList().getComplexity();
52
}
53
54
size_t Polynomial::getComplexity() const{
55
  size_t cmp = 0;
56
  iterator i = begin(), e = end();
57
  for(; i != e; ++i){
58
    Monomial m = *i;
59
    cmp += m.getComplexity();
60
  }
61
  return cmp;
62
}
63
64
size_t Constant::getComplexity() const{
65
  return getValue().complexity();
66
}
67
68
193003774
bool Variable::isLeafMember(Node n){
69
579011322
  return (!isRelationOperator(n.getKind())) &&
70
579011322
    (Theory::isLeafOf(n, theory::THEORY_ARITH));
71
}
72
73
167093200
VarList::VarList(Node n) : NodeWrapper(n) { Assert(isSorted(begin(), end())); }
74
75
329793
bool Variable::isIAndMember(Node n)
76
{
77
989379
  return n.getKind() == kind::IAND && Polynomial::isMember(n[0])
78
1319172
         && Polynomial::isMember(n[1]);
79
}
80
81
207225
bool Variable::isDivMember(Node n){
82
207225
  switch(n.getKind()){
83
131842
  case kind::DIVISION:
84
  case kind::INTS_DIVISION:
85
  case kind::INTS_MODULUS:
86
  case kind::DIVISION_TOTAL:
87
  case kind::INTS_DIVISION_TOTAL:
88
  case kind::INTS_MODULUS_TOTAL:
89
131842
    return Polynomial::isMember(n[0]) && Polynomial::isMember(n[1]);
90
75383
  default:
91
75383
    return false;
92
  }
93
}
94
95
2694064
bool Variable::isTranscendentalMember(Node n) {
96
2694064
  switch(n.getKind()){
97
1393366
  case kind::EXPONENTIAL:
98
  case kind::SINE:
99
  case kind::COSINE:
100
  case kind::TANGENT:
101
  case kind::COSECANT:
102
  case kind::SECANT:
103
  case kind::COTANGENT:
104
  case kind::ARCSINE:
105
  case kind::ARCCOSINE:
106
  case kind::ARCTANGENT:
107
  case kind::ARCCOSECANT:
108
  case kind::ARCSECANT:
109
  case kind::ARCCOTANGENT:
110
1393366
  case kind::SQRT: return Polynomial::isMember(n[0]);
111
1300698
  case kind::PI:
112
1300698
    return true;
113
  default:
114
    return false;
115
  }
116
}
117
118
119
171355204
bool VarList::isSorted(iterator start, iterator end) {
120
171355204
  return std::is_sorted(start, end);
121
}
122
123
127493537
bool VarList::isMember(Node n) {
124
127493537
  if(Variable::isMember(n)) {
125
92938946
    return true;
126
  }
127
34554591
  if(n.getKind() == kind::NONLINEAR_MULT) {
128
4723681
    Node::iterator curr = n.begin(), end = n.end();
129
9447362
    Node prev = *curr;
130
4723681
    if(!Variable::isMember(prev)) return false;
131
132
    Variable::VariableNodeCmp cmp;
133
134
16292089
    while( (++curr) != end) {
135
5784204
      if(!Variable::isMember(*curr)) return false;
136
      // prev <= curr : accept
137
      // !(prev <= curr) : reject
138
      // !(!(prev > curr)) : reject
139
      // curr < prev : reject
140
5784204
      if((cmp(*curr, prev))) return false;
141
5784204
      prev = *curr;
142
    }
143
4723681
    return true;
144
  } else {
145
29830910
    return false;
146
  }
147
}
148
149
115252251
int VarList::cmp(const VarList& vl) const {
150
115252251
  int dif = this->size() - vl.size();
151
115252251
  if (dif == 0) {
152
85665373
    if(this->getNode() == vl.getNode()) {
153
12500663
      return 0;
154
    }
155
156
73164710
    Assert(!empty());
157
73164710
    Assert(!vl.empty());
158
73164710
    if(this->size() == 1){
159
68737064
      return Variable::VariableNodeCmp::cmp(this->getNode(), vl.getNode());
160
    }
161
162
163
8855292
    internal_iterator ii=this->internalBegin(), ie=this->internalEnd();
164
8855292
    internal_iterator ci=vl.internalBegin(), ce=vl.internalEnd();
165
17194419
    for(; ii != ie; ++ii, ++ci){
166
12938828
      Node vi = *ii;
167
12938828
      Node vc = *ci;
168
8683237
      int tmp = Variable::VariableNodeCmp::cmp(vi, vc);
169
8683237
      if(tmp != 0){
170
4427646
        return tmp;
171
      }
172
    }
173
    Unreachable();
174
29586878
  } else if(dif < 0) {
175
16595748
    return -1;
176
  } else {
177
12991130
    return 1;
178
  }
179
}
180
181
167093200
VarList VarList::parseVarList(Node n) {
182
167093200
  return VarList(n);
183
  // if(Variable::isMember(n)) {
184
  //   return VarList(Variable(n));
185
  // } else {
186
  //   Assert(n.getKind() == kind::MULT);
187
  //   for(Node::iterator i=n.begin(), end = n.end(); i!=end; ++i) {
188
  //     Assert(Variable::isMember(*i));
189
  //   }
190
  //   return VarList(n);
191
  // }
192
}
193
194
1162097
VarList VarList::operator*(const VarList& other) const {
195
1162097
  if(this->empty()) {
196
1104355
    return other;
197
57742
  } else if(other.empty()) {
198
12716
    return *this;
199
  } else {
200
90052
    vector<Node> result;
201
202
    internal_iterator
203
90052
      thisBegin = this->internalBegin(),
204
90052
      thisEnd = this->internalEnd(),
205
90052
      otherBegin = other.internalBegin(),
206
90052
      otherEnd = other.internalEnd();
207
208
    Variable::VariableNodeCmp cmp;
209
45026
    std::merge(thisBegin, thisEnd, otherBegin, otherEnd, std::back_inserter(result), cmp);
210
211
45026
    Assert(result.size() >= 2);
212
90052
    Node mult = NodeManager::currentNM()->mkNode(kind::NONLINEAR_MULT, result);
213
45026
    return VarList::parseVarList(mult);
214
  }
215
}
216
217
144321203
bool Monomial::isMember(TNode n){
218
144321203
  if(n.getKind() == kind::CONST_RATIONAL) {
219
20329579
    return true;
220
123991624
  } else if(multStructured(n)) {
221
23698797
    return VarList::isMember(n[1]);
222
  } else {
223
100292827
    return VarList::isMember(n);
224
  }
225
}
226
227
68037386
Monomial Monomial::mkMonomial(const Constant& c, const VarList& vl) {
228
68037386
  if(c.isZero() || vl.empty() ) {
229
4148035
    return Monomial(c);
230
63889351
  } else if(c.isOne()) {
231
1550430
    return Monomial(vl);
232
  } else {
233
62338921
    return Monomial(c, vl);
234
  }
235
}
236
237
70188
Monomial Monomial::mkMonomial(const VarList& vl) {
238
  // acts like Monomial::mkMonomial( 1, vl)
239
70188
  if( vl.empty() ) {
240
    return Monomial::mkOne();
241
  } else if(true){
242
70188
    return Monomial(vl);
243
  }
244
}
245
246
200551553
Monomial Monomial::parseMonomial(Node n) {
247
200551553
  if(n.getKind() == kind::CONST_RATIONAL) {
248
33503423
    return Monomial(Constant(n));
249
167048130
  } else if(multStructured(n)) {
250
58508185
    return Monomial::mkMonomial(Constant(n[0]),VarList::parseVarList(n[1]));
251
  } else {
252
108539945
    return Monomial(VarList::parseVarList(n));
253
  }
254
}
255
7043802
Monomial Monomial::operator*(const Rational& q) const {
256
7043802
  if(q.isZero()){
257
    return mkZero();
258
  }else{
259
14087604
    Constant newConstant = this->getConstant() * q;
260
7043802
    return Monomial::mkMonomial(newConstant, getVarList());
261
  }
262
}
263
264
Monomial Monomial::operator*(const Constant& c) const {
265
  return (*this) * c.getValue();
266
  // if(c.isZero()){
267
  //   return mkZero();
268
  // }else{
269
  //   Constant newConstant = this->getConstant() * c;
270
  //   return Monomial::mkMonomial(newConstant, getVarList());
271
  // }
272
}
273
274
1162097
Monomial Monomial::operator*(const Monomial& mono) const {
275
2324194
  Constant newConstant = this->getConstant() * mono.getConstant();
276
2324194
  VarList newVL = this->getVarList() * mono.getVarList();
277
278
2324194
  return Monomial::mkMonomial(newConstant, newVL);
279
}
280
281
// vector<Monomial> Monomial::sumLikeTerms(const std::vector<Monomial> & monos)
282
// {
283
//   Assert(isSorted(monos));
284
//   vector<Monomial> outMonomials;
285
//   typedef vector<Monomial>::const_iterator iterator;
286
//   for(iterator rangeIter = monos.begin(), end=monos.end(); rangeIter != end;)
287
//   {
288
//     Rational constant = (*rangeIter).getConstant().getValue();
289
//     VarList varList  = (*rangeIter).getVarList();
290
//     ++rangeIter;
291
//     while(rangeIter != end && varList == (*rangeIter).getVarList()) {
292
//       constant += (*rangeIter).getConstant().getValue();
293
//       ++rangeIter;
294
//     }
295
//     if(constant != 0) {
296
//       Constant asConstant = Constant::mkConstant(constant);
297
//       Monomial nonZero = Monomial::mkMonomial(asConstant, varList);
298
//       outMonomials.push_back(nonZero);
299
//     }
300
//   }
301
302
//   Assert(isStrictlySorted(outMonomials));
303
//   return outMonomials;
304
// }
305
306
2478203
void Monomial::sort(std::vector<Monomial>& m){
307
2478203
  if(!isSorted(m)){
308
113519
    std::sort(m.begin(), m.end());
309
  }
310
2478203
}
311
312
8399338
void Monomial::combineAdjacentMonomials(std::vector<Monomial>& monos) {
313
8399338
  Assert(isSorted(monos));
314
  size_t writePos, readPos, N;
315
27348887
  for(writePos = 0, readPos = 0, N = monos.size(); readPos < N;){
316
18949549
    Monomial& atRead = monos[readPos];
317
18949549
    const VarList& varList  = atRead.getVarList();
318
319
18949549
    size_t rangeEnd = readPos+1;
320
27222961
    for(; rangeEnd < N; rangeEnd++){
321
14696176
      if(!(varList == monos[rangeEnd].getVarList())){ break; }
322
    }
323
    // monos[i] for i in [readPos, rangeEnd) has the same var list
324
18949549
    if(readPos+1 == rangeEnd){ // no addition needed
325
14933089
      if(!atRead.getConstant().isZero()){
326
26002304
        Monomial cpy = atRead; // being paranoid here
327
13001152
        monos[writePos] = cpy;
328
13001152
        writePos++;
329
      }
330
    }else{
331
8032920
      Rational constant(monos[readPos].getConstant().getValue());
332
8153166
      for(size_t i=readPos+1; i < rangeEnd; ++i){
333
4136706
        constant += monos[i].getConstant().getValue();
334
      }
335
4016460
      if(!constant.isZero()){
336
2644100
        Constant asConstant = Constant::mkConstant(constant);
337
2644100
        Monomial nonZero = Monomial::mkMonomial(asConstant, varList);
338
1322050
        monos[writePos] = nonZero;
339
1322050
        writePos++;
340
      }
341
    }
342
18949549
    Assert(rangeEnd > readPos);
343
18949549
    readPos = rangeEnd;
344
  }
345
8399338
  if(writePos > 0 ){
346
14033226
    Monomial cp = monos[0];
347
7016613
    Assert(writePos <= N);
348
7016613
    monos.resize(writePos, cp);
349
  }else{
350
1382725
    monos.clear();
351
  }
352
8399338
  Assert(isStrictlySorted(monos));
353
8399338
}
354
355
void Monomial::print() const {
356
  Debug("normal-form") <<  getNode() << std::endl;
357
}
358
359
void Monomial::printList(const std::vector<Monomial>& list) {
360
  for(vector<Monomial>::const_iterator i = list.begin(), end = list.end(); i != end; ++i) {
361
    const Monomial& m =*i;
362
    m.print();
363
  }
364
}
365
6955364
Polynomial Polynomial::operator+(const Polynomial& vl) const {
366
367
13910728
  std::vector<Monomial> sortedMonos;
368
6955364
  std::merge(begin(), end(), vl.begin(), vl.end(), std::back_inserter(sortedMonos));
369
370
6955364
  Monomial::combineAdjacentMonomials(sortedMonos);
371
  //std::vector<Monomial> combined = Monomial::sumLikeTerms(sortedMonos);
372
373
6955364
  Polynomial result = mkPolynomial(sortedMonos);
374
13910728
  return result;
375
}
376
377
Polynomial Polynomial::exactDivide(const Integer& z) const {
378
  Assert(isIntegral());
379
  if(z.isOne()){
380
    return (*this);
381
  }else {
382
    Constant invz = Constant::mkConstant(Rational(1,z));
383
    Polynomial prod = (*this) * Monomial::mkMonomial(invz);
384
    Assert(prod.isIntegral());
385
    return prod;
386
  }
387
}
388
389
1453481
Polynomial Polynomial::sumPolynomials(const std::vector<Polynomial>& ps){
390
1453481
  if(ps.empty()){
391
    return mkZero();
392
1453481
  }else if(ps.size() <= 4){
393
    // if there are few enough polynomials just add them
394
2888444
    Polynomial p = ps[0];
395
1609147
    for(size_t i = 1; i < ps.size(); ++i){
396
164925
      p = p + ps[i];
397
    }
398
1444222
    return p;
399
  }else{
400
    // general case
401
18518
    std::map<Node, Rational> coeffs;
402
75579
    for(size_t i = 0, N = ps.size(); i<N; ++i){
403
66320
      const Polynomial& p = ps[i];
404
238769
      for(iterator pi = p.begin(), pend = p.end(); pi != pend; ++pi) {
405
344898
        Monomial m = *pi;
406
172449
        coeffs[m.getVarList().getNode()] += m.getConstant().getValue();
407
      }
408
    }
409
18518
    std::vector<Monomial> monos;
410
9259
    std::map<Node, Rational>::const_iterator ci = coeffs.begin(), cend = coeffs.end();
411
149871
    for(; ci != cend; ++ci){
412
70306
      if(!(*ci).second.isZero()){
413
        Constant c = Constant::mkConstant((*ci).second);
414
        Node n = (*ci).first;
415
        VarList vl = VarList::parseVarList(n);
416
        monos.push_back(Monomial::mkMonomial(c, vl));
417
      }
418
    }
419
9259
    Monomial::sort(monos);
420
9259
    Monomial::combineAdjacentMonomials(monos);
421
422
18518
    Polynomial result = mkPolynomial(monos);
423
9259
    return result;
424
  }
425
}
426
427
2344391
Polynomial Polynomial::operator-(const Polynomial& vl) const {
428
4688782
  Constant negOne = Constant::mkConstant(Rational(-1));
429
430
4688782
  return *this + (vl*negOne);
431
}
432
433
6724659
Polynomial Polynomial::operator*(const Rational& q) const{
434
6724659
  if(q.isZero()){
435
    return Polynomial::mkZero();
436
6724659
  }else if(q.isOne()){
437
2343399
    return *this;
438
  }else{
439
8762520
    std::vector<Monomial> newMonos;
440
10667461
    for(iterator i = this->begin(), end = this->end(); i != end; ++i) {
441
6286201
      newMonos.push_back((*i)*q);
442
    }
443
444
4381260
    Assert(Monomial::isStrictlySorted(newMonos));
445
4381260
    return Polynomial::mkPolynomial(newMonos);
446
  }
447
}
448
449
3543427
Polynomial Polynomial::operator*(const Constant& c) const{
450
3543427
  return (*this) * c.getValue();
451
  // if(c.isZero()){
452
  //   return Polynomial::mkZero();
453
  // }else if(c.isOne()){
454
  //   return *this;
455
  // }else{
456
  //   std::vector<Monomial> newMonos;
457
  //   for(iterator i = this->begin(), end = this->end(); i != end; ++i) {
458
  //     newMonos.push_back((*i)*c);
459
  //   }
460
461
  //   Assert(Monomial::isStrictlySorted(newMonos));
462
  //   return Polynomial::mkPolynomial(newMonos);
463
  // }
464
}
465
466
1034440
Polynomial Polynomial::operator*(const Monomial& mono) const {
467
1034440
  if(mono.isZero()) {
468
211
    return Polynomial(mono); //Don't multiply by zero
469
  } else {
470
2068458
    std::vector<Monomial> newMonos;
471
2196326
    for(iterator i = this->begin(), end = this->end(); i != end; ++i) {
472
1162097
      newMonos.push_back(mono * (*i));
473
    }
474
475
    // We may need to sort newMonos.
476
    // Suppose this = (+ x y), mono = x, (* x y).getId() < (* x x).getId()
477
    // newMonos = <(* x x), (* x y)> after this loop.
478
    // This is not sorted according to the current VarList order.
479
1034229
    Monomial::sort(newMonos);
480
1034229
    return Polynomial::mkPolynomial(newMonos);
481
  }
482
}
483
484
1027719
Polynomial Polynomial::operator*(const Polynomial& poly) const {
485
1027719
  Polynomial res = Polynomial::mkZero();
486
2062159
  for(iterator i = this->begin(), end = this->end(); i != end; ++i) {
487
2068880
    Monomial curr = *i;
488
2068880
    Polynomial prod = poly * curr;
489
2068880
    Polynomial sum  = res + prod;
490
1034440
    res = sum;
491
  }
492
1027719
  return res;
493
}
494
495
3633436
Monomial Polynomial::selectAbsMinimum() const {
496
7266872
  iterator iter = begin(), myend = end();
497
3633436
  Assert(iter != myend);
498
499
3633436
  Monomial min = *iter;
500
3633436
  ++iter;
501
6277800
  for(; iter != end(); ++iter){
502
2644364
    Monomial curr = *iter;
503
1322182
    if(curr.absCmp(min) < 0){
504
68479
      min = curr;
505
    }
506
  }
507
7266872
  return min;
508
}
509
510
1895174
bool Polynomial::leadingCoefficientIsAbsOne() const {
511
1895174
  return getHead().absCoefficientIsOne();
512
}
513
5602932
bool Polynomial::leadingCoefficientIsPositive() const {
514
5602932
  return getHead().getConstant().isPositive();
515
}
516
517
3147816
bool Polynomial::denominatorLCMIsOne() const {
518
3147816
  return denominatorLCM().isOne();
519
}
520
521
3147816
bool Polynomial::numeratorGCDIsOne() const {
522
3147816
  return gcd().isOne();
523
}
524
525
3359734
Integer Polynomial::gcd() const {
526
3359734
  Assert(isIntegral());
527
3359734
  return numeratorGCD();
528
}
529
530
7316670
Integer Polynomial::numeratorGCD() const {
531
  //We'll use the standardization that gcd(0, 0) = 0
532
  //So that the gcd of the zero polynomial is gcd{0} = 0
533
14633340
  iterator i=begin(), e=end();
534
7316670
  Assert(i != e);
535
536
7316670
  Integer d = (*i).getConstant().getValue().getNumerator().abs();
537
7316670
  if(d.isOne()){
538
7051186
    return d;
539
  }
540
265484
  ++i;
541
438624
  for(; i!=e; ++i){
542
358326
    Integer c = (*i).getConstant().getValue().getNumerator();
543
271756
    d = d.gcd(c);
544
271756
    if(d.isOne()){
545
185186
      return d;
546
    }
547
  }
548
80298
  return d;
549
}
550
551
7104752
Integer Polynomial::denominatorLCM() const {
552
7104752
  Integer tmp(1);
553
17584176
  for (iterator i = begin(), e = end(); i != e; ++i) {
554
20958848
    const Integer denominator = (*i).getConstant().getValue().getDenominator();
555
10479424
    tmp = tmp.lcm(denominator);
556
  }
557
7104752
  return tmp;
558
}
559
560
4250744
Constant Polynomial::getCoefficient(const VarList& vl) const{
561
  //TODO improve to binary search...
562
11128995
  for(iterator iter=begin(), myend=end(); iter != myend; ++iter){
563
13809486
    Monomial m = *iter;
564
13809486
    VarList curr = m.getVarList();
565
6931235
    if(curr == vl){
566
52984
      return m.getConstant();
567
    }
568
  }
569
4197760
  return Constant::mkConstant(0);
570
}
571
572
334
Node Polynomial::computeQR(const Polynomial& p, const Integer& div){
573
334
  Assert(p.isIntegral());
574
668
  std::vector<Monomial> q_vec, r_vec;
575
668
  Integer tmp_q, tmp_r;
576
1138
  for(iterator iter = p.begin(), pend = p.end(); iter != pend; ++iter){
577
1608
    Monomial curr = *iter;
578
1608
    VarList vl = curr.getVarList();
579
1608
    Constant c = curr.getConstant();
580
581
1608
    const Integer& a = c.getValue().getNumerator();
582
804
    Integer::floorQR(tmp_q, tmp_r, a, div);
583
1608
    Constant q=Constant::mkConstant(tmp_q);
584
1608
    Constant r=Constant::mkConstant(tmp_r);
585
804
    if(!q.isZero()){
586
804
      q_vec.push_back(Monomial::mkMonomial(q, vl));
587
    }
588
804
    if(!r.isZero()){
589
448
      r_vec.push_back(Monomial::mkMonomial(r, vl));
590
    }
591
  }
592
593
668
  Polynomial p_q = Polynomial::mkPolynomial(q_vec);
594
668
  Polynomial p_r = Polynomial::mkPolynomial(r_vec);
595
596
668
  return NodeManager::currentNM()->mkNode(kind::PLUS, p_q.getNode(), p_r.getNode());
597
}
598
599
600
729312
Monomial Polynomial::minimumVariableMonomial() const{
601
729312
  Assert(!isConstant());
602
729312
  if(singleton()){
603
452106
    return getHead();
604
  }else{
605
554412
    iterator i = begin();
606
554412
    Monomial first = *i;
607
277206
    if( first.isConstant() ){
608
193180
      ++i;
609
193180
      Assert(i != end());
610
193180
      return *i;
611
    }else{
612
84026
      return first;
613
    }
614
  }
615
}
616
617
1125522
bool Polynomial::variableMonomialAreStrictlyGreater(const Monomial& m) const{
618
1125522
  if(isConstant()){
619
466398
    return true;
620
  }else{
621
1318248
    Monomial minimum = minimumVariableMonomial();
622
659124
    Debug("nf::tmp") << "minimum " << minimum.getNode() << endl;
623
659124
    Debug("nf::tmp") << "m " << m.getNode() << endl;
624
659124
    return m < minimum;
625
  }
626
}
627
628
54564365
bool Polynomial::isMember(TNode n) {
629
54564365
  if(Monomial::isMember(n)){
630
38954966
    return true;
631
15609399
  }else if(n.getKind() == kind::PLUS){
632
15609399
    Assert(n.getNumChildren() >= 2);
633
15609399
    Node::iterator currIter = n.begin(), end = n.end();
634
31218798
    Node prev = *currIter;
635
15609399
    if(!Monomial::isMember(prev)){
636
      return false;
637
    }
638
639
31218798
    Monomial mprev = Monomial::parseMonomial(prev);
640
15609399
    ++currIter;
641
60564901
    for(; currIter != end; ++currIter){
642
44955502
      Node curr = *currIter;
643
22477751
      if(!Monomial::isMember(curr)){
644
        return false;
645
      }
646
44955502
      Monomial mcurr = Monomial::parseMonomial(curr);
647
22477751
      if(!(mprev < mcurr)){
648
        return false;
649
      }
650
22477751
      mprev = mcurr;
651
    }
652
15609399
    return true;
653
  } else {
654
    return false;
655
  }
656
}
657
658
334
Node SumPair::computeQR(const SumPair& sp, const Integer& div){
659
334
  Assert(sp.isIntegral());
660
661
668
  const Integer& constant = sp.getConstant().getValue().getNumerator();
662
663
668
  Integer constant_q, constant_r;
664
334
  Integer::floorQR(constant_q, constant_r, constant, div);
665
666
668
  Node p_qr = Polynomial::computeQR(sp.getPolynomial(), div);
667
334
  Assert(p_qr.getKind() == kind::PLUS);
668
334
  Assert(p_qr.getNumChildren() == 2);
669
670
668
  Polynomial p_q = Polynomial::parsePolynomial(p_qr[0]);
671
668
  Polynomial p_r = Polynomial::parsePolynomial(p_qr[1]);
672
673
668
  SumPair sp_q(p_q, Constant::mkConstant(constant_q));
674
668
  SumPair sp_r(p_r, Constant::mkConstant(constant_r));
675
676
668
  return NodeManager::currentNM()->mkNode(kind::PLUS, sp_q.getNode(), sp_r.getNode());
677
}
678
679
1337651
SumPair SumPair::mkSumPair(const Polynomial& p){
680
1337651
  if(p.isConstant()){
681
    Constant leadingConstant = p.getHead().getConstant();
682
    return SumPair(Polynomial::mkZero(), leadingConstant);
683
1337651
  }else if(p.containsConstant()){
684
819259
    Assert(!p.singleton());
685
819259
    return SumPair(p.getTail(), p.getHead().getConstant());
686
  }else{
687
518392
    return SumPair(p, Constant::mkZero());
688
  }
689
}
690
691
4164583
Comparison::Comparison(TNode n) : NodeWrapper(n) { Assert(isNormalForm()); }
692
693
32624
SumPair Comparison::toSumPair() const {
694
32624
  Kind cmpKind = comparisonKind();
695
32624
  switch(cmpKind){
696
  case kind::LT:
697
  case kind::LEQ:
698
  case kind::GT:
699
  case kind::GEQ:
700
    {
701
      TNode lit = getNode();
702
      TNode atom = (cmpKind == kind::LT || cmpKind == kind::LEQ) ? lit[0] : lit;
703
      Polynomial p = Polynomial::parsePolynomial(atom[0]);
704
      Constant c = Constant::mkConstant(atom[1]);
705
      if(p.leadingCoefficientIsPositive()){
706
        return SumPair(p, -c);
707
      }else{
708
        return SumPair(-p, c);
709
      }
710
    }
711
32624
  case kind::EQUAL:
712
  case kind::DISTINCT:
713
    {
714
65248
      Polynomial left = getLeft();
715
65248
      Polynomial right = getRight();
716
32624
      Debug("nf::tmp") << "left: " << left.getNode() << endl;
717
32624
      Debug("nf::tmp") << "right: " << right.getNode() << endl;
718
32624
      if(right.isConstant()){
719
11905
        return SumPair(left, -right.getHead().getConstant());
720
20719
      }else if(right.containsConstant()){
721
8400
        Assert(!right.singleton());
722
723
16800
        Polynomial noConstant = right.getTail();
724
8400
        return SumPair(left - noConstant, -right.getHead().getConstant());
725
      }else{
726
12319
        return SumPair(left - right, Constant::mkZero());
727
      }
728
    }
729
    default: Unhandled() << cmpKind;
730
  }
731
}
732
733
940545
Polynomial Comparison::normalizedVariablePart() const {
734
940545
  Kind cmpKind = comparisonKind();
735
940545
  switch(cmpKind){
736
531361
  case kind::LT:
737
  case kind::LEQ:
738
  case kind::GT:
739
  case kind::GEQ:
740
    {
741
1062722
      TNode lit = getNode();
742
1062722
      TNode atom = (cmpKind == kind::LT || cmpKind == kind::LEQ) ? lit[0] : lit;
743
1062722
      Polynomial p = Polynomial::parsePolynomial(atom[0]);
744
531361
      if(p.leadingCoefficientIsPositive()){
745
434640
        return p;
746
      }else{
747
96721
        return -p;
748
      }
749
    }
750
409184
  case kind::EQUAL:
751
  case kind::DISTINCT:
752
    {
753
818368
      Polynomial left = getLeft();
754
818368
      Polynomial right = getRight();
755
409184
      if(right.isConstant()){
756
187972
        return left;
757
      }else{
758
442424
        Polynomial noConstant = right.containsConstant() ? right.getTail() : right;
759
442424
        Polynomial diff = left - noConstant;
760
221212
        if(diff.leadingCoefficientIsPositive()){
761
218572
          return diff;
762
        }else{
763
2640
          return -diff;
764
        }
765
      }
766
    }
767
    default: Unhandled() << cmpKind;
768
  }
769
}
770
771
939238
DeltaRational Comparison::normalizedDeltaRational() const {
772
939238
  Kind cmpKind = comparisonKind();
773
939238
  int delta = deltaCoeff(cmpKind);
774
939238
  switch(cmpKind){
775
530258
  case kind::LT:
776
  case kind::LEQ:
777
  case kind::GT:
778
  case kind::GEQ:
779
    {
780
1060516
      Node lit = getNode();
781
1060516
      Node atom = (cmpKind == kind::LT || cmpKind == kind::LEQ) ? lit[0] : lit;
782
1060516
      Polynomial left = Polynomial::parsePolynomial(atom[0]);
783
530258
      const Rational& q = atom[1].getConst<Rational>();
784
530258
      if(left.leadingCoefficientIsPositive()){
785
433747
        return DeltaRational(q, delta);
786
      }else{
787
96511
        return DeltaRational(-q, -delta);
788
      }
789
    }
790
408980
  case kind::EQUAL:
791
  case kind::DISTINCT:
792
    {
793
817960
      Polynomial right = getRight();
794
817960
      Monomial firstRight = right.getHead();
795
408980
      if(firstRight.isConstant()){
796
455960
        DeltaRational c = DeltaRational(firstRight.getConstant().getValue(), 0);
797
455960
        Polynomial left = getLeft();
798
227980
        if(!left.allIntegralVariables()){
799
22280
          return c;
800
          //this is a qpolynomial and the sign of the leading
801
          //coefficient will not change after the diff below
802
        } else{
803
          // the polynomial may be a z polynomial in which case
804
          // taking the diff is the simplest and obviously correct means
805
411400
          Polynomial diff = right.singleton() ? left : left - right.getTail();
806
205700
          if(diff.leadingCoefficientIsPositive()){
807
205284
            return c;
808
          }else{
809
416
            return -c;
810
          }
811
        }
812
      }else{ // The constant is 0 sign cannot change
813
181000
        return DeltaRational(0, 0);
814
      }
815
    }
816
    default: Unhandled() << cmpKind;
817
  }
818
}
819
820
314292
std::tuple<Polynomial, Kind, Constant> Comparison::decompose(
821
    bool split_constant) const
822
{
823
314292
  Kind rel = getNode().getKind();
824
314292
  if (rel == Kind::NOT)
825
  {
826
146280
    switch (getNode()[0].getKind())
827
    {
828
      case kind::LEQ: rel = Kind::GT; break;
829
      case kind::LT: rel = Kind::GEQ; break;
830
47881
      case kind::EQUAL: rel = Kind::DISTINCT; break;
831
      case kind::DISTINCT: rel = Kind::EQUAL; break;
832
98399
      case kind::GEQ: rel = Kind::LT; break;
833
      case kind::GT: rel = Kind::LEQ; break;
834
      default:
835
        Assert(false) << "Unsupported relation: " << getNode()[0].getKind();
836
    }
837
  }
838
839
628584
  Polynomial poly = getLeft() - getRight();
840
841
314292
  if (!split_constant)
842
  {
843
    return std::tuple<Polynomial, Kind, Constant>{
844
80
        poly, rel, Constant::mkZero()};
845
  }
846
847
628424
  Constant right = Constant::mkZero();
848
314212
  if (poly.containsConstant())
849
  {
850
130920
    right = -poly.getHead().getConstant();
851
130920
    poly = poly + Polynomial::mkPolynomial(right);
852
  }
853
854
628424
  Constant lcoeff = poly.getHead().getConstant();
855
314212
  if (!lcoeff.isOne())
856
  {
857
91944
    Constant invlcoeff = lcoeff.inverse();
858
45972
    if (lcoeff.isNegative())
859
    {
860
39665
      switch (rel)
861
      {
862
        case kind::LEQ: rel = Kind::GEQ; break;
863
20785
        case kind::LT: rel = Kind::GT; break;
864
486
        case kind::EQUAL: break;
865
376
        case kind::DISTINCT: break;
866
18018
        case kind::GEQ: rel = Kind::LEQ; break;
867
        case kind::GT: rel = Kind::LT; break;
868
        default: Assert(false) << "Unsupported relation: " << rel;
869
      }
870
    }
871
45972
    poly = poly * invlcoeff;
872
45972
    right = right * invlcoeff;
873
  }
874
875
314212
  return std::tuple<Polynomial, Kind, Constant>{poly, rel, right};
876
}
877
878
2196710
Comparison Comparison::parseNormalForm(TNode n) {
879
2196710
  Debug("polynomial") << "Comparison::parseNormalForm(" << n << ")";
880
2196710
  Comparison result(n);
881
2196710
  Assert(result.isNormalForm());
882
2196710
  return result;
883
}
884
885
683003
Node Comparison::toNode(Kind k, const Polynomial& l, const Constant& r) {
886
683003
  Assert(isRelationOperator(k));
887
683003
  switch(k) {
888
683003
  case kind::GEQ:
889
  case kind::GT:
890
1366006
    return NodeManager::currentNM()->mkNode(k, l.getNode(), r.getNode());
891
  default: Unhandled() << k;
892
  }
893
}
894
895
1284372
Node Comparison::toNode(Kind k, const Polynomial& l, const Polynomial& r) {
896
1284372
  Assert(isRelationOperator(k));
897
1284372
  switch(k) {
898
1284372
  case kind::GEQ:
899
  case kind::EQUAL:
900
  case kind::GT:
901
1284372
    return NodeManager::currentNM()->mkNode(k, l.getNode(), r.getNode());
902
  case kind::LEQ:
903
    return toNode(kind::GEQ, r, l).notNode();
904
  case kind::LT:
905
    return toNode(kind::GT, r, l).notNode();
906
  case kind::DISTINCT:
907
    return toNode(kind::EQUAL, r, l).notNode();
908
  default:
909
    Unreachable();
910
  }
911
}
912
913
8715511
bool Comparison::rightIsConstant() const {
914
8715511
  if(getNode().getKind() == kind::NOT){
915
1370469
    return getNode()[0][1].getKind() == kind::CONST_RATIONAL;
916
  }else{
917
7345042
    return getNode()[1].getKind() == kind::CONST_RATIONAL;
918
  }
919
}
920
921
size_t Comparison::getComplexity() const{
922
  switch(comparisonKind()){
923
  case kind::CONST_BOOLEAN: return 1;
924
  case kind::LT:
925
  case kind::LEQ:
926
  case kind::DISTINCT:
927
  case kind::EQUAL:
928
  case kind::GT:
929
  case kind::GEQ:
930
    return getLeft().getComplexity() +  getRight().getComplexity();
931
  default: Unhandled() << comparisonKind(); return -1;
932
  }
933
}
934
935
17052662
Polynomial Comparison::getLeft() const {
936
34105324
  TNode left;
937
17052662
  Kind k = comparisonKind();
938
17052662
  switch(k){
939
3487625
  case kind::LT:
940
  case kind::LEQ:
941
  case kind::DISTINCT:
942
3487625
    left = getNode()[0][0];
943
3487625
    break;
944
13565037
  case kind::EQUAL:
945
  case kind::GT:
946
  case kind::GEQ:
947
13565037
    left = getNode()[0];
948
13565037
    break;
949
  default: Unhandled() << k;
950
  }
951
34105324
  return Polynomial::parsePolynomial(left);
952
}
953
954
11362647
Polynomial Comparison::getRight() const {
955
22725294
  TNode right;
956
11362647
  Kind k = comparisonKind();
957
11362647
  switch(k){
958
1972250
  case kind::LT:
959
  case kind::LEQ:
960
  case kind::DISTINCT:
961
1972250
    right = getNode()[0][1];
962
1972250
    break;
963
9390397
  case kind::EQUAL:
964
  case kind::GT:
965
  case kind::GEQ:
966
9390397
    right = getNode()[1];
967
9390397
    break;
968
  default: Unhandled() << k;
969
  }
970
22725294
  return Polynomial::parsePolynomial(right);
971
}
972
973
// Polynomial Comparison::getLeft() const {
974
//   Node n = getNode();
975
//   Node left = (n.getKind() == kind::NOT ? n[0]: n)[0];
976
//   return Polynomial::parsePolynomial(left);
977
// }
978
979
// Polynomial Comparison::getRight() const {
980
//   Node n = getNode();
981
//   Node right = (n.getKind() == kind::NOT ? n[0]: n)[1];
982
//   return Polynomial::parsePolynomial(right);
983
// }
984
985
10683119
bool Comparison::isNormalForm() const {
986
21366238
  Node n = getNode();
987
10683119
  Kind cmpKind = comparisonKind(n);
988
10683119
  Debug("nf::tmp") << "isNormalForm " << n << " " << cmpKind << endl;
989
10683119
  switch(cmpKind){
990
277251
  case kind::CONST_BOOLEAN:
991
277251
    return true;
992
  case kind::GT:
993
    return isNormalGT();
994
3672521
  case kind::GEQ:
995
3672521
    return isNormalGEQ();
996
4551452
  case kind::EQUAL:
997
4551452
    return isNormalEquality();
998
1370469
  case kind::LT:
999
1370469
    return isNormalLT();
1000
  case kind::LEQ:
1001
    return isNormalLEQ();
1002
811426
  case kind::DISTINCT:
1003
811426
    return isNormalDistinct();
1004
  default:
1005
    return false;
1006
  }
1007
}
1008
1009
/** This must be (> qpolynomial constant) */
1010
bool Comparison::isNormalGT() const {
1011
  Node n = getNode();
1012
  Assert(n.getKind() == kind::GT);
1013
  if(!rightIsConstant()){
1014
    return false;
1015
  }else{
1016
    Polynomial left = getLeft();
1017
    if(left.containsConstant()){
1018
      return false;
1019
    }else if(!left.leadingCoefficientIsAbsOne()){
1020
      return false;
1021
    }else{
1022
      return !left.isIntegral();
1023
    }
1024
  }
1025
}
1026
1027
/** This must be (not (> qpolynomial constant)) */
1028
bool Comparison::isNormalLEQ() const {
1029
  Node n = getNode();
1030
  Debug("nf::tmp") << "isNormalLEQ " << n << endl;
1031
  Assert(n.getKind() == kind::NOT);
1032
  Assert(n[0].getKind() == kind::GT);
1033
  if(!rightIsConstant()){
1034
    return false;
1035
  }else{
1036
    Polynomial left = getLeft();
1037
    if(left.containsConstant()){
1038
      return false;
1039
    }else if(!left.leadingCoefficientIsAbsOne()){
1040
      return false;
1041
    }else{
1042
      return !left.isIntegral();
1043
    }
1044
  }
1045
}
1046
1047
1048
/** This must be (>= qpolynomial constant) or  (>= zpolynomial constant) */
1049
3672521
bool Comparison::isNormalGEQ() const {
1050
7345042
  Node n = getNode();
1051
3672521
  Assert(n.getKind() == kind::GEQ);
1052
1053
3672521
  Debug("nf::tmp") << "isNormalGEQ " << n << " " << rightIsConstant() << endl;
1054
1055
3672521
  if(!rightIsConstant()){
1056
    return false;
1057
  }else{
1058
7345042
    Polynomial left = getLeft();
1059
3672521
    if(left.containsConstant()){
1060
      return false;
1061
    }else{
1062
3672521
      if(left.isIntegral()){
1063
2205052
        return left.signNormalizedReducedSum();
1064
      }else{
1065
1467469
        return left.leadingCoefficientIsAbsOne();
1066
      }
1067
    }
1068
  }
1069
}
1070
1071
/** This must be (not (>= qpolynomial constant)) or (not (>= zpolynomial constant)) */
1072
1370469
bool Comparison::isNormalLT() const {
1073
2740938
  Node n = getNode();
1074
1370469
  Assert(n.getKind() == kind::NOT);
1075
1370469
  Assert(n[0].getKind() == kind::GEQ);
1076
1077
1370469
  if(!rightIsConstant()){
1078
    return false;
1079
  }else{
1080
2740938
    Polynomial left = getLeft();
1081
1370469
    if(left.containsConstant()){
1082
      return false;
1083
    }else{
1084
1370469
      if(left.isIntegral()){
1085
942764
        return left.signNormalizedReducedSum();
1086
      }else{
1087
427705
        return left.leadingCoefficientIsAbsOne();
1088
      }
1089
    }
1090
  }
1091
}
1092
1093
1094
5362878
bool Comparison::isNormalEqualityOrDisequality() const {
1095
10725756
  Polynomial pleft = getLeft();
1096
1097
5362878
  if(pleft.numMonomials() == 1){
1098
10725756
    Monomial mleft = pleft.getHead();
1099
5362878
    if(mleft.isConstant()){
1100
      return false;
1101
    }else{
1102
10725756
      Polynomial pright = getRight();
1103
5362878
      if(allIntegralVariables()){
1104
4800117
        const Rational& lcoeff = mleft.getConstant().getValue();
1105
4800117
        if(pright.isConstant()){
1106
1924474
          return pright.isIntegral() && lcoeff.isOne();
1107
        }
1108
5751286
        Polynomial varRight = pright.containsConstant() ? pright.getTail() : pright;
1109
2875643
        if(lcoeff.sgn() <= 0){
1110
          return false;
1111
        }else{
1112
5751286
          Integer lcm = lcoeff.getDenominator().lcm(varRight.denominatorLCM());
1113
5751286
          Integer g = lcoeff.getNumerator().gcd(varRight.numeratorGCD());
1114
2875643
          Debug("nf::tmp") << lcm << " " << g << endl;
1115
2875643
          if(!lcm.isOne()){
1116
            return false;
1117
2875643
          }else if(!g.isOne()){
1118
            return false;
1119
          }else{
1120
5751286
            Monomial absMinRight = varRight.selectAbsMinimum();
1121
2875643
            Debug("nf::tmp") << mleft.getNode() << " " << absMinRight.getNode() << endl;
1122
2875643
            if( mleft.absCmp(absMinRight) < 0){
1123
71047
              return true;
1124
            }else{
1125
2804596
              return (!(absMinRight.absCmp(mleft)< 0)) && mleft < absMinRight;
1126
            }
1127
          }
1128
        }
1129
      }else{
1130
562761
        if(mleft.coefficientIsOne()){
1131
1125522
          Debug("nf::tmp")
1132
562761
            << "dfklj " << mleft.getNode() << endl
1133
562761
            << pright.getNode() << endl
1134
1125522
            << pright.variableMonomialAreStrictlyGreater(mleft)
1135
562761
            << endl;
1136
562761
          return pright.variableMonomialAreStrictlyGreater(mleft);
1137
        }else{
1138
          return false;
1139
        }
1140
      }
1141
    }
1142
  }else{
1143
    return false;
1144
  }
1145
}
1146
1147
/** This must be (= qvarlist qpolynomial) or (= zmonomial zpolynomial)*/
1148
4551452
bool Comparison::isNormalEquality() const {
1149
4551452
  Assert(getNode().getKind() == kind::EQUAL);
1150
13654356
  return Theory::theoryOf(getNode()[0].getType()) == THEORY_ARITH &&
1151
13654356
         isNormalEqualityOrDisequality();
1152
}
1153
1154
/**
1155
 * This must be (not (= qvarlist qpolynomial)) or
1156
 * (not (= zmonomial zpolynomial)).
1157
 */
1158
811426
bool Comparison::isNormalDistinct() const {
1159
811426
  Assert(getNode().getKind() == kind::NOT);
1160
811426
  Assert(getNode()[0].getKind() == kind::EQUAL);
1161
1162
2434278
  return Theory::theoryOf(getNode()[0][0].getType()) == THEORY_ARITH &&
1163
2434278
         isNormalEqualityOrDisequality();
1164
}
1165
1166
70188
Node Comparison::mkRatEquality(const Polynomial& p){
1167
70188
  Assert(!p.isConstant());
1168
70188
  Assert(!p.allIntegralVariables());
1169
1170
140376
  Monomial minimalVList = p.minimumVariableMonomial();
1171
140376
  Constant coeffInv = -(minimalVList.getConstant().inverse());
1172
1173
140376
  Polynomial newRight = (p - minimalVList) * coeffInv;
1174
140376
  Polynomial newLeft(Monomial::mkMonomial(minimalVList.getVarList()));
1175
1176
140376
  return toNode(kind::EQUAL, newLeft, newRight);
1177
}
1178
1179
256358
Node Comparison::mkRatInequality(Kind k, const Polynomial& p){
1180
256358
  Assert(k == kind::GEQ || k == kind::GT);
1181
256358
  Assert(!p.isConstant());
1182
256358
  Assert(!p.allIntegralVariables());
1183
1184
512716
  SumPair sp = SumPair::mkSumPair(p);
1185
512716
  Polynomial left = sp.getPolynomial();
1186
512716
  Constant right = - sp.getConstant();
1187
1188
512716
  Monomial minimalVList = left.getHead();
1189
256358
  Assert(!minimalVList.isConstant());
1190
1191
512716
  Constant coeffInv = minimalVList.getConstant().inverse().abs();
1192
512716
  Polynomial newLeft = left * coeffInv;
1193
512716
  Constant newRight = right * (coeffInv);
1194
1195
512716
  return toNode(k, newLeft, newRight);
1196
}
1197
1198
426645
Node Comparison::mkIntInequality(Kind k, const Polynomial& p){
1199
426645
  Assert(kind::GT == k || kind::GEQ == k);
1200
426645
  Assert(!p.isConstant());
1201
426645
  Assert(p.allIntegralVariables());
1202
1203
853290
  SumPair sp = SumPair::mkSumPair(p);
1204
853290
  Polynomial left = sp.getPolynomial();
1205
853290
  Rational right = - (sp.getConstant().getValue());
1206
1207
1208
853290
  Monomial m = left.getHead();
1209
426645
  Assert(!m.isConstant());
1210
1211
853290
  Integer lcm = left.denominatorLCM();
1212
853290
  Integer g = left.numeratorGCD();
1213
853290
  Rational mult(lcm,g);
1214
1215
853290
  Polynomial newLeft = left * mult;
1216
853290
  Rational rightMult = right * mult;
1217
1218
426645
  bool negateResult = false;
1219
426645
  if(!newLeft.leadingCoefficientIsPositive()){
1220
    // multiply by -1
1221
    // a: left >= right or b: left > right
1222
    // becomes
1223
    // a: -left <= -right or b: -left < -right
1224
    // a: not (-left > -right) or b: (not -left >= -right)
1225
82403
    newLeft = -newLeft;
1226
82403
    rightMult = -rightMult;
1227
82403
    k = (kind::GT == k) ? kind::GEQ : kind::GT;
1228
82403
    negateResult = true;
1229
    // the later stages handle:
1230
    // a: not (-left >= -right + 1) or b: (not -left >= -right)
1231
  }
1232
1233
853290
  Node result = Node::null();
1234
426645
  if(rightMult.isIntegral()){
1235
422871
    if(k == kind::GT){
1236
      // (> p z)
1237
      // (>= p (+ z 1))
1238
161096
      Constant rightMultPlusOne = Constant::mkConstant(rightMult + 1);
1239
80548
      result = toNode(kind::GEQ, newLeft, rightMultPlusOne);
1240
    }else{
1241
684646
      Constant newRight = Constant::mkConstant(rightMult);
1242
342323
      result = toNode(kind::GEQ, newLeft, newRight);
1243
    }
1244
  }else{
1245
    //(>= l (/ n d))
1246
    //(>= l (ceil (/ n d)))
1247
    //This also hold for GT as (ceil (/ n d)) > (/ n d)
1248
7548
    Integer ceilr = rightMult.ceiling();
1249
7548
    Constant ceilRight = Constant::mkConstant(ceilr);
1250
3774
    result = toNode(kind::GEQ, newLeft, ceilRight);
1251
  }
1252
426645
  Assert(!result.isNull());
1253
426645
  if(negateResult){
1254
82403
    return result.notNode();
1255
  }else{
1256
344242
    return result;
1257
  }
1258
}
1259
1260
654648
Node Comparison::mkIntEquality(const Polynomial& p){
1261
654648
  Assert(!p.isConstant());
1262
654648
  Assert(p.allIntegralVariables());
1263
1264
1309296
  SumPair sp = SumPair::mkSumPair(p);
1265
1309296
  Polynomial varPart = sp.getPolynomial();
1266
1309296
  Constant constPart = sp.getConstant();
1267
1268
1309296
  Integer lcm = varPart.denominatorLCM();
1269
1309296
  Integer g = varPart.numeratorGCD();
1270
1309296
  Constant mult = Constant::mkConstant(Rational(lcm,g));
1271
1272
1309296
  Constant constMult = constPart * mult;
1273
1274
654648
  if(constMult.isIntegral()){
1275
1308300
    Polynomial varPartMult = varPart * mult;
1276
1277
1308300
    Monomial m = varPartMult.selectAbsMinimum();
1278
654150
    bool mIsPositive =  m.getConstant().isPositive();
1279
1280
1308300
    Polynomial noM = (varPartMult + (- m)) + Polynomial::mkPolynomial(constMult);
1281
1282
    // m + noM = 0
1283
1308300
    Polynomial newRight = mIsPositive ? -noM : noM;
1284
1308300
    Polynomial newLeft  = mIsPositive ? m  : -m;
1285
1286
654150
    Assert(newRight.isIntegral());
1287
654150
    return toNode(kind::EQUAL, newLeft, newRight);
1288
  }else{
1289
498
    return mkBoolNode(false);
1290
  }
1291
}
1292
1293
2243630
Comparison Comparison::mkComparison(Kind k, const Polynomial& l, const Polynomial& r){
1294
1295
  //Make this special case fast for sharing!
1296
2243630
  if((k == kind::EQUAL || k == kind::DISTINCT) && l.isVarList() && r.isVarList()){
1297
1121616
    VarList vLeft = l.asVarList();
1298
1121616
    VarList vRight = r.asVarList();
1299
1300
560808
    if(vLeft == vRight){
1301
      // return true for equalities and false for disequalities
1302
774
      return Comparison(k == kind::EQUAL);
1303
    }else{
1304
1120068
      Node eqNode = vLeft < vRight ? toNode( kind::EQUAL, l, r) : toNode( kind::EQUAL, r, l);
1305
1120068
      Node forK = (k == kind::DISTINCT) ? eqNode.notNode() : eqNode;
1306
560034
      return Comparison(forK);
1307
    }
1308
  }
1309
1310
  //General case
1311
3365644
  Polynomial diff = l - r;
1312
1682822
  if(diff.isConstant()){
1313
274983
    bool res = evaluateConstantPredicate(k, diff.asConstant(), Rational(0));
1314
274983
    return Comparison(res);
1315
  }else{
1316
2815678
    Node result = Node::null();
1317
1407839
    bool isInteger = diff.allIntegralVariables();
1318
1407839
    switch(k){
1319
724836
    case kind::EQUAL:
1320
724836
      result = isInteger ? mkIntEquality(diff) : mkRatEquality(diff);
1321
724836
      break;
1322
    case kind::DISTINCT:
1323
      {
1324
        Node eq = isInteger ? mkIntEquality(diff) : mkRatEquality(diff);
1325
        result = eq.notNode();
1326
      }
1327
      break;
1328
106636
    case kind::LEQ:
1329
    case kind::LT:
1330
      {
1331
213272
        Polynomial neg = - diff;
1332
106636
        Kind negKind = (k == kind::LEQ ? kind::GEQ : kind::GT);
1333
106636
        result = isInteger ?
1334
106636
          mkIntInequality(negKind, neg) : mkRatInequality(negKind, neg);
1335
      }
1336
106636
      break;
1337
576367
    case kind::GEQ:
1338
    case kind::GT:
1339
576367
      result = isInteger ?
1340
        mkIntInequality(k, diff) : mkRatInequality(k, diff);
1341
576367
      break;
1342
    default: Unhandled() << k;
1343
    }
1344
1407839
    Assert(!result.isNull());
1345
1407839
    if(result.getKind() == kind::NOT && result[0].getKind() == kind::CONST_BOOLEAN){
1346
      return Comparison(!(result[0].getConst<bool>()));
1347
    }else{
1348
2815678
      Comparison cmp(result);
1349
1407839
      Assert(cmp.isNormalForm());
1350
1407839
      return cmp;
1351
    }
1352
  }
1353
}
1354
1355
32624
bool Comparison::isBoolean() const {
1356
32624
  return getNode().getKind() == kind::CONST_BOOLEAN;
1357
}
1358
1359
1360
32624
bool Comparison::debugIsIntegral() const{
1361
32624
  return getLeft().isIntegral() && getRight().isIntegral();
1362
}
1363
1364
46888098
Kind Comparison::comparisonKind(TNode literal){
1365
46888098
  switch(literal.getKind()){
1366
35957396
  case kind::CONST_BOOLEAN:
1367
  case kind::GT:
1368
  case kind::GEQ:
1369
  case kind::EQUAL:
1370
35957396
    return literal.getKind();
1371
10930702
  case  kind::NOT:
1372
    {
1373
21861404
      TNode negatedAtom = literal[0];
1374
10930702
      switch(negatedAtom.getKind()){
1375
      case kind::GT: //(not (GT x c)) <=> (LEQ x c)
1376
        return kind::LEQ;
1377
5241101
      case kind::GEQ: //(not (GEQ x c)) <=> (LT x c)
1378
5241101
        return kind::LT;
1379
5689601
      case kind::EQUAL:
1380
5689601
        return kind::DISTINCT;
1381
      default:
1382
        return  kind::UNDEFINED_KIND;
1383
      }
1384
    }
1385
  default:
1386
    return kind::UNDEFINED_KIND;
1387
  }
1388
}
1389
1390
1391
Node Polynomial::makeAbsCondition(Variable v, Polynomial p){
1392
  Polynomial zerop = Polynomial::mkZero();
1393
1394
  Polynomial varp = Polynomial::mkPolynomial(v);
1395
  Comparison pLeq0 = Comparison::mkComparison(kind::LEQ, p, zerop);
1396
  Comparison negP = Comparison::mkComparison(kind::EQUAL, varp, -p);
1397
  Comparison posP = Comparison::mkComparison(kind::EQUAL, varp, p);
1398
1399
  Node absCnd = (pLeq0.getNode()).iteNode(negP.getNode(), posP.getNode());
1400
  return absCnd;
1401
}
1402
1403
32624
bool Polynomial::isNonlinear() const {
1404
1405
95492
  for(iterator i=begin(), iend =end(); i != iend; ++i){
1406
127585
    Monomial m = *i;
1407
64717
    if(m.isNonlinear()){
1408
1849
      return true;
1409
    }
1410
  }
1411
30775
  return false;
1412
}
1413
1414
} //namespace arith
1415
} //namespace theory
1416
27735
}  // namespace cvc5