GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/normal_form.cpp Lines: 644 795 81.0 %
Date: 2021-09-07 Branches: 1099 2972 37.0 %

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
159479468
Constant Constant::mkConstant(const Rational& rat) {
33
159479468
  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
227968175
bool Variable::isLeafMember(Node n){
69
683904525
  return (!isRelationOperator(n.getKind())) &&
70
683904525
    (Theory::isLeafOf(n, theory::THEORY_ARITH));
71
}
72
73
198709813
VarList::VarList(Node n) : NodeWrapper(n) { Assert(isSorted(begin(), end())); }
74
75
377705
bool Variable::isIAndMember(Node n)
76
{
77
1133115
  return n.getKind() == kind::IAND && Polynomial::isMember(n[0])
78
1510820
         && Polynomial::isMember(n[1]);
79
}
80
81
57987
bool Variable::isPow2Member(Node n)
82
{
83
57987
  return n.getKind() == kind::POW2 && Polynomial::isMember(n[0]);
84
}
85
86
245098
bool Variable::isDivMember(Node n){
87
245098
  switch(n.getKind()){
88
156584
  case kind::DIVISION:
89
  case kind::INTS_DIVISION:
90
  case kind::INTS_MODULUS:
91
  case kind::DIVISION_TOTAL:
92
  case kind::INTS_DIVISION_TOTAL:
93
  case kind::INTS_MODULUS_TOTAL:
94
156584
    return Polynomial::isMember(n[0]) && Polynomial::isMember(n[1]);
95
88514
  default:
96
88514
    return false;
97
  }
98
}
99
100
3168901
bool Variable::isTranscendentalMember(Node n) {
101
3168901
  switch(n.getKind()){
102
1483320
  case kind::EXPONENTIAL:
103
  case kind::SINE:
104
  case kind::COSINE:
105
  case kind::TANGENT:
106
  case kind::COSECANT:
107
  case kind::SECANT:
108
  case kind::COTANGENT:
109
  case kind::ARCSINE:
110
  case kind::ARCCOSINE:
111
  case kind::ARCTANGENT:
112
  case kind::ARCCOSECANT:
113
  case kind::ARCSECANT:
114
  case kind::ARCCOTANGENT:
115
1483320
  case kind::SQRT: return Polynomial::isMember(n[0]);
116
1685581
  case kind::PI:
117
1685581
    return true;
118
  default:
119
    return false;
120
  }
121
}
122
123
124
203041014
bool VarList::isSorted(iterator start, iterator end) {
125
203041014
  return std::is_sorted(start, end);
126
}
127
128
149661935
bool VarList::isMember(Node n) {
129
149661935
  if(Variable::isMember(n)) {
130
109408723
    return true;
131
  }
132
40253212
  if(n.getKind() == kind::NONLINEAR_MULT) {
133
6015476
    Node::iterator curr = n.begin(), end = n.end();
134
12030952
    Node prev = *curr;
135
6015476
    if(!Variable::isMember(prev)) return false;
136
137
    Variable::VariableNodeCmp cmp;
138
139
19503850
    while( (++curr) != end) {
140
6744187
      if(!Variable::isMember(*curr)) return false;
141
      // prev <= curr : accept
142
      // !(prev <= curr) : reject
143
      // !(!(prev > curr)) : reject
144
      // curr < prev : reject
145
6744187
      if((cmp(*curr, prev))) return false;
146
6744187
      prev = *curr;
147
    }
148
6015476
    return true;
149
  } else {
150
34237736
    return false;
151
  }
152
}
153
154
137735551
int VarList::cmp(const VarList& vl) const {
155
137735551
  int dif = this->size() - vl.size();
156
137735551
  if (dif == 0) {
157
100744130
    if(this->getNode() == vl.getNode()) {
158
15174094
      return 0;
159
    }
160
161
85570036
    Assert(!empty());
162
85570036
    Assert(!vl.empty());
163
85570036
    if(this->size() == 1){
164
80016855
      return Variable::VariableNodeCmp::cmp(this->getNode(), vl.getNode());
165
    }
166
167
168
11106362
    internal_iterator ii=this->internalBegin(), ie=this->internalEnd();
169
11106362
    internal_iterator ci=vl.internalBegin(), ce=vl.internalEnd();
170
19793674
    for(; ii != ie; ++ii, ++ci){
171
15046843
      Node vi = *ii;
172
15046843
      Node vc = *ci;
173
10300012
      int tmp = Variable::VariableNodeCmp::cmp(vi, vc);
174
10300012
      if(tmp != 0){
175
5553181
        return tmp;
176
      }
177
    }
178
    Unreachable();
179
36991421
  } else if(dif < 0) {
180
20828211
    return -1;
181
  } else {
182
16163210
    return 1;
183
  }
184
}
185
186
198709813
VarList VarList::parseVarList(Node n) {
187
198709813
  return VarList(n);
188
  // if(Variable::isMember(n)) {
189
  //   return VarList(Variable(n));
190
  // } else {
191
  //   Assert(n.getKind() == kind::MULT);
192
  //   for(Node::iterator i=n.begin(), end = n.end(); i!=end; ++i) {
193
  //     Assert(Variable::isMember(*i));
194
  //   }
195
  //   return VarList(n);
196
  // }
197
}
198
199
1410217
VarList VarList::operator*(const VarList& other) const {
200
1410217
  if(this->empty()) {
201
1334794
    return other;
202
75423
  } else if(other.empty()) {
203
17566
    return *this;
204
  } else {
205
115714
    vector<Node> result;
206
207
    internal_iterator
208
115714
      thisBegin = this->internalBegin(),
209
115714
      thisEnd = this->internalEnd(),
210
115714
      otherBegin = other.internalBegin(),
211
115714
      otherEnd = other.internalEnd();
212
213
    Variable::VariableNodeCmp cmp;
214
57857
    std::merge(thisBegin, thisEnd, otherBegin, otherEnd, std::back_inserter(result), cmp);
215
216
57857
    Assert(result.size() >= 2);
217
115714
    Node mult = NodeManager::currentNM()->mkNode(kind::NONLINEAR_MULT, result);
218
57857
    return VarList::parseVarList(mult);
219
  }
220
}
221
222
170422984
bool Monomial::isMember(TNode n){
223
170422984
  if(n.getKind() == kind::CONST_RATIONAL) {
224
24625398
    return true;
225
145797586
  } else if(multStructured(n)) {
226
27335236
    return VarList::isMember(n[1]);
227
  } else {
228
118462350
    return VarList::isMember(n);
229
  }
230
}
231
232
81437280
Monomial Monomial::mkMonomial(const Constant& c, const VarList& vl) {
233
81437280
  if(c.isZero() || vl.empty() ) {
234
4995299
    return Monomial(c);
235
76441981
  } else if(c.isOne()) {
236
1894391
    return Monomial(vl);
237
  } else {
238
74547590
    return Monomial(c, vl);
239
  }
240
}
241
242
77760
Monomial Monomial::mkMonomial(const VarList& vl) {
243
  // acts like Monomial::mkMonomial( 1, vl)
244
77760
  if( vl.empty() ) {
245
    return Monomial::mkOne();
246
  } else if(true){
247
77760
    return Monomial(vl);
248
  }
249
}
250
251
239600938
Monomial Monomial::parseMonomial(Node n) {
252
239600938
  if(n.getKind() == kind::CONST_RATIONAL) {
253
40949026
    return Monomial(Constant(n));
254
198651912
  } else if(multStructured(n)) {
255
69674112
    return Monomial::mkMonomial(Constant(n[0]),VarList::parseVarList(n[1]));
256
  } else {
257
128977800
    return Monomial(VarList::parseVarList(n));
258
  }
259
}
260
8781532
Monomial Monomial::operator*(const Rational& q) const {
261
8781532
  if(q.isZero()){
262
    return mkZero();
263
  }else{
264
17563064
    Constant newConstant = this->getConstant() * q;
265
8781532
    return Monomial::mkMonomial(newConstant, getVarList());
266
  }
267
}
268
269
Monomial Monomial::operator*(const Constant& c) const {
270
  return (*this) * c.getValue();
271
  // if(c.isZero()){
272
  //   return mkZero();
273
  // }else{
274
  //   Constant newConstant = this->getConstant() * c;
275
  //   return Monomial::mkMonomial(newConstant, getVarList());
276
  // }
277
}
278
279
1410217
Monomial Monomial::operator*(const Monomial& mono) const {
280
2820434
  Constant newConstant = this->getConstant() * mono.getConstant();
281
2820434
  VarList newVL = this->getVarList() * mono.getVarList();
282
283
2820434
  return Monomial::mkMonomial(newConstant, newVL);
284
}
285
286
// vector<Monomial> Monomial::sumLikeTerms(const std::vector<Monomial> & monos)
287
// {
288
//   Assert(isSorted(monos));
289
//   vector<Monomial> outMonomials;
290
//   typedef vector<Monomial>::const_iterator iterator;
291
//   for(iterator rangeIter = monos.begin(), end=monos.end(); rangeIter != end;)
292
//   {
293
//     Rational constant = (*rangeIter).getConstant().getValue();
294
//     VarList varList  = (*rangeIter).getVarList();
295
//     ++rangeIter;
296
//     while(rangeIter != end && varList == (*rangeIter).getVarList()) {
297
//       constant += (*rangeIter).getConstant().getValue();
298
//       ++rangeIter;
299
//     }
300
//     if(constant != 0) {
301
//       Constant asConstant = Constant::mkConstant(constant);
302
//       Monomial nonZero = Monomial::mkMonomial(asConstant, varList);
303
//       outMonomials.push_back(nonZero);
304
//     }
305
//   }
306
307
//   Assert(isStrictlySorted(outMonomials));
308
//   return outMonomials;
309
// }
310
311
2824407
void Monomial::sort(std::vector<Monomial>& m){
312
2824407
  if(!isSorted(m)){
313
106067
    std::sort(m.begin(), m.end());
314
  }
315
2824407
}
316
317
10246642
void Monomial::combineAdjacentMonomials(std::vector<Monomial>& monos) {
318
10246642
  Assert(isSorted(monos));
319
  size_t writePos, readPos, N;
320
33189386
  for(writePos = 0, readPos = 0, N = monos.size(); readPos < N;){
321
22942744
    Monomial& atRead = monos[readPos];
322
22942744
    const VarList& varList  = atRead.getVarList();
323
324
22942744
    size_t rangeEnd = readPos+1;
325
32991588
    for(; rangeEnd < N; rangeEnd++){
326
17730953
      if(!(varList == monos[rangeEnd].getVarList())){ break; }
327
    }
328
    // monos[i] for i in [readPos, rangeEnd) has the same var list
329
22942744
    if(readPos+1 == rangeEnd){ // no addition needed
330
18072898
      if(!atRead.getConstant().isZero()){
331
31165040
        Monomial cpy = atRead; // being paranoid here
332
15582520
        monos[writePos] = cpy;
333
15582520
        writePos++;
334
      }
335
    }else{
336
9739692
      Rational constant(monos[readPos].getConstant().getValue());
337
9894268
      for(size_t i=readPos+1; i < rangeEnd; ++i){
338
5024422
        constant += monos[i].getConstant().getValue();
339
      }
340
4869846
      if(!constant.isZero()){
341
3140334
        Constant asConstant = Constant::mkConstant(constant);
342
3140334
        Monomial nonZero = Monomial::mkMonomial(asConstant, varList);
343
1570167
        monos[writePos] = nonZero;
344
1570167
        writePos++;
345
      }
346
    }
347
22942744
    Assert(rangeEnd > readPos);
348
22942744
    readPos = rangeEnd;
349
  }
350
10246642
  if(writePos > 0 ){
351
17063418
    Monomial cp = monos[0];
352
8531709
    Assert(writePos <= N);
353
8531709
    monos.resize(writePos, cp);
354
  }else{
355
1714933
    monos.clear();
356
  }
357
10246642
  Assert(isStrictlySorted(monos));
358
10246642
}
359
360
void Monomial::print() const {
361
  Debug("normal-form") <<  getNode() << std::endl;
362
}
363
364
void Monomial::printList(const std::vector<Monomial>& list) {
365
  for(vector<Monomial>::const_iterator i = list.begin(), end = list.end(); i != end; ++i) {
366
    const Monomial& m =*i;
367
    m.print();
368
  }
369
}
370
8676600
Polynomial Polynomial::operator+(const Polynomial& vl) const {
371
372
17353200
  std::vector<Monomial> sortedMonos;
373
8676600
  std::merge(begin(), end(), vl.begin(), vl.end(), std::back_inserter(sortedMonos));
374
375
8676600
  Monomial::combineAdjacentMonomials(sortedMonos);
376
  //std::vector<Monomial> combined = Monomial::sumLikeTerms(sortedMonos);
377
378
8676600
  Polynomial result = mkPolynomial(sortedMonos);
379
17353200
  return result;
380
}
381
382
Polynomial Polynomial::exactDivide(const Integer& z) const {
383
  Assert(isIntegral());
384
  if(z.isOne()){
385
    return (*this);
386
  }else {
387
    Constant invz = Constant::mkConstant(Rational(1,z));
388
    Polynomial prod = (*this) * Monomial::mkMonomial(invz);
389
    Assert(prod.isIntegral());
390
    return prod;
391
  }
392
}
393
394
1575937
Polynomial Polynomial::sumPolynomials(const std::vector<Polynomial>& ps){
395
1575937
  if(ps.empty()){
396
    return mkZero();
397
1575937
  }else if(ps.size() <= 4){
398
    // if there are few enough polynomials just add them
399
3131016
    Polynomial p = ps[0];
400
1715729
    for(size_t i = 1; i < ps.size(); ++i){
401
150221
      p = p + ps[i];
402
    }
403
1565508
    return p;
404
  }else{
405
    // general case
406
20858
    std::map<Node, Rational> coeffs;
407
86871
    for(size_t i = 0, N = ps.size(); i<N; ++i){
408
76442
      const Polynomial& p = ps[i];
409
272270
      for(iterator pi = p.begin(), pend = p.end(); pi != pend; ++pi) {
410
391656
        Monomial m = *pi;
411
195828
        coeffs[m.getVarList().getNode()] += m.getConstant().getValue();
412
      }
413
    }
414
20858
    std::vector<Monomial> monos;
415
10429
    std::map<Node, Rational>::const_iterator ci = coeffs.begin(), cend = coeffs.end();
416
176637
    for(; ci != cend; ++ci){
417
83104
      if(!(*ci).second.isZero()){
418
        Constant c = Constant::mkConstant((*ci).second);
419
        Node n = (*ci).first;
420
        VarList vl = VarList::parseVarList(n);
421
        monos.push_back(Monomial::mkMonomial(c, vl));
422
      }
423
    }
424
10429
    Monomial::sort(monos);
425
10429
    Monomial::combineAdjacentMonomials(monos);
426
427
20858
    Polynomial result = mkPolynomial(monos);
428
10429
    return result;
429
  }
430
}
431
432
2868977
Polynomial Polynomial::operator-(const Polynomial& vl) const {
433
5737954
  Constant negOne = Constant::mkConstant(Rational(-1));
434
435
5737954
  return *this + (vl*negOne);
436
}
437
438
8355846
Polynomial Polynomial::operator*(const Rational& q) const{
439
8355846
  if(q.isZero()){
440
    return Polynomial::mkZero();
441
8355846
  }else if(q.isOne()){
442
2903481
    return *this;
443
  }else{
444
10904730
    std::vector<Monomial> newMonos;
445
13357092
    for(iterator i = this->begin(), end = this->end(); i != end; ++i) {
446
7904727
      newMonos.push_back((*i)*q);
447
    }
448
449
5452365
    Assert(Monomial::isStrictlySorted(newMonos));
450
5452365
    return Polynomial::mkPolynomial(newMonos);
451
  }
452
}
453
454
4252009
Polynomial Polynomial::operator*(const Constant& c) const{
455
4252009
  return (*this) * c.getValue();
456
  // if(c.isZero()){
457
  //   return Polynomial::mkZero();
458
  // }else if(c.isOne()){
459
  //   return *this;
460
  // }else{
461
  //   std::vector<Monomial> newMonos;
462
  //   for(iterator i = this->begin(), end = this->end(); i != end; ++i) {
463
  //     newMonos.push_back((*i)*c);
464
  //   }
465
466
  //   Assert(Monomial::isStrictlySorted(newMonos));
467
  //   return Polynomial::mkPolynomial(newMonos);
468
  // }
469
}
470
471
1254672
Polynomial Polynomial::operator*(const Monomial& mono) const {
472
1254672
  if(mono.isZero()) {
473
307
    return Polynomial(mono); //Don't multiply by zero
474
  } else {
475
2508730
    std::vector<Monomial> newMonos;
476
2664582
    for(iterator i = this->begin(), end = this->end(); i != end; ++i) {
477
1410217
      newMonos.push_back(mono * (*i));
478
    }
479
480
    // We may need to sort newMonos.
481
    // Suppose this = (+ x y), mono = x, (* x y).getId() < (* x x).getId()
482
    // newMonos = <(* x x), (* x y)> after this loop.
483
    // This is not sorted according to the current VarList order.
484
1254365
    Monomial::sort(newMonos);
485
1254365
    return Polynomial::mkPolynomial(newMonos);
486
  }
487
}
488
489
1247084
Polynomial Polynomial::operator*(const Polynomial& poly) const {
490
1247084
  Polynomial res = Polynomial::mkZero();
491
2501756
  for(iterator i = this->begin(), end = this->end(); i != end; ++i) {
492
2509344
    Monomial curr = *i;
493
2509344
    Polynomial prod = poly * curr;
494
2509344
    Polynomial sum  = res + prod;
495
1254672
    res = sum;
496
  }
497
1247084
  return res;
498
}
499
500
4473194
Monomial Polynomial::selectAbsMinimum() const {
501
8946388
  iterator iter = begin(), myend = end();
502
4473194
  Assert(iter != myend);
503
504
4473194
  Monomial min = *iter;
505
4473194
  ++iter;
506
8254160
  for(; iter != end(); ++iter){
507
3780966
    Monomial curr = *iter;
508
1890483
    if(curr.absCmp(min) < 0){
509
89554
      min = curr;
510
    }
511
  }
512
8946388
  return min;
513
}
514
515
2074517
bool Polynomial::leadingCoefficientIsAbsOne() const {
516
2074517
  return getHead().absCoefficientIsOne();
517
}
518
6472732
bool Polynomial::leadingCoefficientIsPositive() const {
519
6472732
  return getHead().getConstant().isPositive();
520
}
521
522
3700565
bool Polynomial::denominatorLCMIsOne() const {
523
3700565
  return denominatorLCM().isOne();
524
}
525
526
3700565
bool Polynomial::numeratorGCDIsOne() const {
527
3700565
  return gcd().isOne();
528
}
529
530
3946566
Integer Polynomial::gcd() const {
531
3946566
  Assert(isIntegral());
532
3946566
  return numeratorGCD();
533
}
534
535
8802683
Integer Polynomial::numeratorGCD() const {
536
  //We'll use the standardization that gcd(0, 0) = 0
537
  //So that the gcd of the zero polynomial is gcd{0} = 0
538
17605366
  iterator i=begin(), e=end();
539
8802683
  Assert(i != e);
540
541
8802683
  Integer d = (*i).getConstant().getValue().getNumerator().abs();
542
8802683
  if(d.isOne()){
543
8436900
    return d;
544
  }
545
365783
  ++i;
546
545079
  for(; i!=e; ++i){
547
433950
    Integer c = (*i).getConstant().getValue().getNumerator();
548
344302
    d = d.gcd(c);
549
344302
    if(d.isOne()){
550
254654
      return d;
551
    }
552
  }
553
111129
  return d;
554
}
555
556
8556682
Integer Polynomial::denominatorLCM() const {
557
8556682
  Integer tmp(1);
558
21463958
  for (iterator i = begin(), e = end(); i != e; ++i) {
559
25814552
    const Integer denominator = (*i).getConstant().getValue().getDenominator();
560
12907276
    tmp = tmp.lcm(denominator);
561
  }
562
8556682
  return tmp;
563
}
564
565
4317550
Constant Polynomial::getCoefficient(const VarList& vl) const{
566
  //TODO improve to binary search...
567
11211330
  for(iterator iter=begin(), myend=end(); iter != myend; ++iter){
568
13845242
    Monomial m = *iter;
569
13845242
    VarList curr = m.getVarList();
570
6951462
    if(curr == vl){
571
57682
      return m.getConstant();
572
    }
573
  }
574
4259868
  return Constant::mkConstant(0);
575
}
576
577
334
Node Polynomial::computeQR(const Polynomial& p, const Integer& div){
578
334
  Assert(p.isIntegral());
579
668
  std::vector<Monomial> q_vec, r_vec;
580
668
  Integer tmp_q, tmp_r;
581
1138
  for(iterator iter = p.begin(), pend = p.end(); iter != pend; ++iter){
582
1608
    Monomial curr = *iter;
583
1608
    VarList vl = curr.getVarList();
584
1608
    Constant c = curr.getConstant();
585
586
1608
    const Integer& a = c.getValue().getNumerator();
587
804
    Integer::floorQR(tmp_q, tmp_r, a, div);
588
1608
    Constant q=Constant::mkConstant(tmp_q);
589
1608
    Constant r=Constant::mkConstant(tmp_r);
590
804
    if(!q.isZero()){
591
804
      q_vec.push_back(Monomial::mkMonomial(q, vl));
592
    }
593
804
    if(!r.isZero()){
594
448
      r_vec.push_back(Monomial::mkMonomial(r, vl));
595
    }
596
  }
597
598
668
  Polynomial p_q = Polynomial::mkPolynomial(q_vec);
599
668
  Polynomial p_r = Polynomial::mkPolynomial(r_vec);
600
601
668
  return NodeManager::currentNM()->mkNode(kind::PLUS, p_q.getNode(), p_r.getNode());
602
}
603
604
605
811668
Monomial Polynomial::minimumVariableMonomial() const{
606
811668
  Assert(!isConstant());
607
811668
  if(singleton()){
608
485464
    return getHead();
609
  }else{
610
652408
    iterator i = begin();
611
652408
    Monomial first = *i;
612
326204
    if( first.isConstant() ){
613
218910
      ++i;
614
218910
      Assert(i != end());
615
218910
      return *i;
616
    }else{
617
107294
      return first;
618
    }
619
  }
620
}
621
622
1235386
bool Polynomial::variableMonomialAreStrictlyGreater(const Monomial& m) const{
623
1235386
  if(isConstant()){
624
501478
    return true;
625
  }else{
626
1467816
    Monomial minimum = minimumVariableMonomial();
627
733908
    Debug("nf::tmp") << "minimum " << minimum.getNode() << endl;
628
733908
    Debug("nf::tmp") << "m " << m.getNode() << endl;
629
733908
    return m < minimum;
630
  }
631
}
632
633
64903853
bool Polynomial::isMember(TNode n) {
634
64903853
  if(Monomial::isMember(n)){
635
46941437
    return true;
636
17962416
  }else if(n.getKind() == kind::PLUS){
637
17962416
    Assert(n.getNumChildren() >= 2);
638
17962416
    Node::iterator currIter = n.begin(), end = n.end();
639
35924832
    Node prev = *currIter;
640
17962416
    if(!Monomial::isMember(prev)){
641
      return false;
642
    }
643
644
35924832
    Monomial mprev = Monomial::parseMonomial(prev);
645
17962416
    ++currIter;
646
71673962
    for(; currIter != end; ++currIter){
647
53711546
      Node curr = *currIter;
648
26855773
      if(!Monomial::isMember(curr)){
649
        return false;
650
      }
651
53711546
      Monomial mcurr = Monomial::parseMonomial(curr);
652
26855773
      if(!(mprev < mcurr)){
653
        return false;
654
      }
655
26855773
      mprev = mcurr;
656
    }
657
17962416
    return true;
658
  } else {
659
    return false;
660
  }
661
}
662
663
334
Node SumPair::computeQR(const SumPair& sp, const Integer& div){
664
334
  Assert(sp.isIntegral());
665
666
668
  const Integer& constant = sp.getConstant().getValue().getNumerator();
667
668
668
  Integer constant_q, constant_r;
669
334
  Integer::floorQR(constant_q, constant_r, constant, div);
670
671
668
  Node p_qr = Polynomial::computeQR(sp.getPolynomial(), div);
672
334
  Assert(p_qr.getKind() == kind::PLUS);
673
334
  Assert(p_qr.getNumChildren() == 2);
674
675
668
  Polynomial p_q = Polynomial::parsePolynomial(p_qr[0]);
676
668
  Polynomial p_r = Polynomial::parsePolynomial(p_qr[1]);
677
678
668
  SumPair sp_q(p_q, Constant::mkConstant(constant_q));
679
668
  SumPair sp_r(p_r, Constant::mkConstant(constant_r));
680
681
668
  return NodeManager::currentNM()->mkNode(kind::PLUS, sp_q.getNode(), sp_r.getNode());
682
}
683
684
1546627
SumPair SumPair::mkSumPair(const Polynomial& p){
685
1546627
  if(p.isConstant()){
686
    Constant leadingConstant = p.getHead().getConstant();
687
    return SumPair(Polynomial::mkZero(), leadingConstant);
688
1546627
  }else if(p.containsConstant()){
689
970253
    Assert(!p.singleton());
690
970253
    return SumPair(p.getTail(), p.getHead().getConstant());
691
  }else{
692
576374
    return SumPair(p, Constant::mkZero());
693
  }
694
}
695
696
4892598
Comparison::Comparison(TNode n) : NodeWrapper(n) { Assert(isNormalForm()); }
697
698
38655
SumPair Comparison::toSumPair() const {
699
38655
  Kind cmpKind = comparisonKind();
700
38655
  switch(cmpKind){
701
  case kind::LT:
702
  case kind::LEQ:
703
  case kind::GT:
704
  case kind::GEQ:
705
    {
706
      TNode lit = getNode();
707
      TNode atom = (cmpKind == kind::LT || cmpKind == kind::LEQ) ? lit[0] : lit;
708
      Polynomial p = Polynomial::parsePolynomial(atom[0]);
709
      Constant c = Constant::mkConstant(atom[1]);
710
      if(p.leadingCoefficientIsPositive()){
711
        return SumPair(p, -c);
712
      }else{
713
        return SumPair(-p, c);
714
      }
715
    }
716
38655
  case kind::EQUAL:
717
  case kind::DISTINCT:
718
    {
719
77310
      Polynomial left = getLeft();
720
77310
      Polynomial right = getRight();
721
38655
      Debug("nf::tmp") << "left: " << left.getNode() << endl;
722
38655
      Debug("nf::tmp") << "right: " << right.getNode() << endl;
723
38655
      if(right.isConstant()){
724
15136
        return SumPair(left, -right.getHead().getConstant());
725
23519
      }else if(right.containsConstant()){
726
10871
        Assert(!right.singleton());
727
728
21742
        Polynomial noConstant = right.getTail();
729
10871
        return SumPair(left - noConstant, -right.getHead().getConstant());
730
      }else{
731
12648
        return SumPair(left - right, Constant::mkZero());
732
      }
733
    }
734
    default: Unhandled() << cmpKind;
735
  }
736
}
737
738
1085345
Polynomial Comparison::normalizedVariablePart() const {
739
1085345
  Kind cmpKind = comparisonKind();
740
1085345
  switch(cmpKind){
741
572853
  case kind::LT:
742
  case kind::LEQ:
743
  case kind::GT:
744
  case kind::GEQ:
745
    {
746
1145706
      TNode lit = getNode();
747
1145706
      TNode atom = (cmpKind == kind::LT || cmpKind == kind::LEQ) ? lit[0] : lit;
748
1145706
      Polynomial p = Polynomial::parsePolynomial(atom[0]);
749
572853
      if(p.leadingCoefficientIsPositive()){
750
472280
        return p;
751
      }else{
752
100573
        return -p;
753
      }
754
    }
755
512492
  case kind::EQUAL:
756
  case kind::DISTINCT:
757
    {
758
1024984
      Polynomial left = getLeft();
759
1024984
      Polynomial right = getRight();
760
512492
      if(right.isConstant()){
761
235476
        return left;
762
      }else{
763
554032
        Polynomial noConstant = right.containsConstant() ? right.getTail() : right;
764
554032
        Polynomial diff = left - noConstant;
765
277016
        if(diff.leadingCoefficientIsPositive()){
766
273228
          return diff;
767
        }else{
768
3788
          return -diff;
769
        }
770
      }
771
    }
772
    default: Unhandled() << cmpKind;
773
  }
774
}
775
776
1083852
DeltaRational Comparison::normalizedDeltaRational() const {
777
1083852
  Kind cmpKind = comparisonKind();
778
1083852
  int delta = deltaCoeff(cmpKind);
779
1083852
  switch(cmpKind){
780
571586
  case kind::LT:
781
  case kind::LEQ:
782
  case kind::GT:
783
  case kind::GEQ:
784
    {
785
1143172
      Node lit = getNode();
786
1143172
      Node atom = (cmpKind == kind::LT || cmpKind == kind::LEQ) ? lit[0] : lit;
787
1143172
      Polynomial left = Polynomial::parsePolynomial(atom[0]);
788
571586
      const Rational& q = atom[1].getConst<Rational>();
789
571586
      if(left.leadingCoefficientIsPositive()){
790
471210
        return DeltaRational(q, delta);
791
      }else{
792
100376
        return DeltaRational(-q, -delta);
793
      }
794
    }
795
512266
  case kind::EQUAL:
796
  case kind::DISTINCT:
797
    {
798
1024532
      Polynomial right = getRight();
799
1024532
      Monomial firstRight = right.getHead();
800
512266
      if(firstRight.isConstant()){
801
571488
        DeltaRational c = DeltaRational(firstRight.getConstant().getValue(), 0);
802
571488
        Polynomial left = getLeft();
803
285744
        if(!left.allIntegralVariables()){
804
23904
          return c;
805
          //this is a qpolynomial and the sign of the leading
806
          //coefficient will not change after the diff below
807
        } else{
808
          // the polynomial may be a z polynomial in which case
809
          // taking the diff is the simplest and obviously correct means
810
523680
          Polynomial diff = right.singleton() ? left : left - right.getTail();
811
261840
          if(diff.leadingCoefficientIsPositive()){
812
260772
            return c;
813
          }else{
814
1068
            return -c;
815
          }
816
        }
817
      }else{ // The constant is 0 sign cannot change
818
226522
        return DeltaRational(0, 0);
819
      }
820
    }
821
    default: Unhandled() << cmpKind;
822
  }
823
}
824
825
482964
std::tuple<Polynomial, Kind, Constant> Comparison::decompose(
826
    bool split_constant) const
827
{
828
482964
  Kind rel = getNode().getKind();
829
482964
  if (rel == Kind::NOT)
830
  {
831
226748
    switch (getNode()[0].getKind())
832
    {
833
      case kind::LEQ: rel = Kind::GT; break;
834
      case kind::LT: rel = Kind::GEQ; break;
835
78274
      case kind::EQUAL: rel = Kind::DISTINCT; break;
836
      case kind::DISTINCT: rel = Kind::EQUAL; break;
837
148474
      case kind::GEQ: rel = Kind::LT; break;
838
      case kind::GT: rel = Kind::LEQ; break;
839
      default:
840
        Assert(false) << "Unsupported relation: " << getNode()[0].getKind();
841
    }
842
  }
843
844
965928
  Polynomial poly = getLeft() - getRight();
845
846
482964
  if (!split_constant)
847
  {
848
    return std::tuple<Polynomial, Kind, Constant>{
849
92
        poly, rel, Constant::mkZero()};
850
  }
851
852
965744
  Constant right = Constant::mkZero();
853
482872
  if (poly.containsConstant())
854
  {
855
201166
    right = -poly.getHead().getConstant();
856
201166
    poly = poly + Polynomial::mkPolynomial(right);
857
  }
858
859
965744
  Constant lcoeff = poly.getHead().getConstant();
860
482872
  if (!lcoeff.isOne())
861
  {
862
144266
    Constant invlcoeff = lcoeff.inverse();
863
72133
    if (lcoeff.isNegative())
864
    {
865
57260
      switch (rel)
866
      {
867
        case kind::LEQ: rel = Kind::GEQ; break;
868
28147
        case kind::LT: rel = Kind::GT; break;
869
1233
        case kind::EQUAL: break;
870
3374
        case kind::DISTINCT: break;
871
24506
        case kind::GEQ: rel = Kind::LEQ; break;
872
        case kind::GT: rel = Kind::LT; break;
873
        default: Assert(false) << "Unsupported relation: " << rel;
874
      }
875
    }
876
72133
    poly = poly * invlcoeff;
877
72133
    right = right * invlcoeff;
878
  }
879
880
482872
  return std::tuple<Polynomial, Kind, Constant>{poly, rel, right};
881
}
882
883
2654851
Comparison Comparison::parseNormalForm(TNode n) {
884
2654851
  Debug("polynomial") << "Comparison::parseNormalForm(" << n << ")";
885
2654851
  Comparison result(n);
886
2654851
  Assert(result.isNormalForm());
887
2654851
  return result;
888
}
889
890
783414
Node Comparison::toNode(Kind k, const Polynomial& l, const Constant& r) {
891
783414
  Assert(isRelationOperator(k));
892
783414
  switch(k) {
893
783414
  case kind::GEQ:
894
  case kind::GT:
895
1566828
    return NodeManager::currentNM()->mkNode(k, l.getNode(), r.getNode());
896
  default: Unhandled() << k;
897
  }
898
}
899
900
1453829
Node Comparison::toNode(Kind k, const Polynomial& l, const Polynomial& r) {
901
1453829
  Assert(isRelationOperator(k));
902
1453829
  switch(k) {
903
1453829
  case kind::GEQ:
904
  case kind::EQUAL:
905
  case kind::GT:
906
1453829
    return NodeManager::currentNM()->mkNode(k, l.getNode(), r.getNode());
907
  case kind::LEQ:
908
    return toNode(kind::GEQ, r, l).notNode();
909
  case kind::LT:
910
    return toNode(kind::GT, r, l).notNode();
911
  case kind::DISTINCT:
912
    return toNode(kind::EQUAL, r, l).notNode();
913
  default:
914
    Unreachable();
915
  }
916
}
917
918
9945659
bool Comparison::rightIsConstant() const {
919
9945659
  if(getNode().getKind() == kind::NOT){
920
1604505
    return getNode()[0][1].getKind() == kind::CONST_RATIONAL;
921
  }else{
922
8341154
    return getNode()[1].getKind() == kind::CONST_RATIONAL;
923
  }
924
}
925
926
size_t Comparison::getComplexity() const{
927
  switch(comparisonKind()){
928
  case kind::CONST_BOOLEAN: return 1;
929
  case kind::LT:
930
  case kind::LEQ:
931
  case kind::DISTINCT:
932
  case kind::EQUAL:
933
  case kind::GT:
934
  case kind::GEQ:
935
    return getLeft().getComplexity() +  getRight().getComplexity();
936
  default: Unhandled() << comparisonKind(); return -1;
937
  }
938
}
939
940
20232291
Polynomial Comparison::getLeft() const {
941
40464582
  TNode left;
942
20232291
  Kind k = comparisonKind();
943
20232291
  switch(k){
944
4350109
  case kind::LT:
945
  case kind::LEQ:
946
  case kind::DISTINCT:
947
4350109
    left = getNode()[0][0];
948
4350109
    break;
949
15882182
  case kind::EQUAL:
950
  case kind::GT:
951
  case kind::GEQ:
952
15882182
    left = getNode()[0];
953
15882182
    break;
954
  default: Unhandled() << k;
955
  }
956
40464582
  return Polynomial::parsePolynomial(left);
957
}
958
959
13780188
Polynomial Comparison::getRight() const {
960
27560376
  TNode right;
961
13780188
  Kind k = comparisonKind();
962
13780188
  switch(k){
963
2601247
  case kind::LT:
964
  case kind::LEQ:
965
  case kind::DISTINCT:
966
2601247
    right = getNode()[0][1];
967
2601247
    break;
968
11178941
  case kind::EQUAL:
969
  case kind::GT:
970
  case kind::GEQ:
971
11178941
    right = getNode()[1];
972
11178941
    break;
973
  default: Unhandled() << k;
974
  }
975
27560376
  return Polynomial::parsePolynomial(right);
976
}
977
978
// Polynomial Comparison::getLeft() const {
979
//   Node n = getNode();
980
//   Node left = (n.getKind() == kind::NOT ? n[0]: n)[0];
981
//   return Polynomial::parsePolynomial(left);
982
// }
983
984
// Polynomial Comparison::getRight() const {
985
//   Node n = getNode();
986
//   Node right = (n.getKind() == kind::NOT ? n[0]: n)[1];
987
//   return Polynomial::parsePolynomial(right);
988
// }
989
990
12521279
bool Comparison::isNormalForm() const {
991
25042558
  Node n = getNode();
992
12521279
  Kind cmpKind = comparisonKind(n);
993
12521279
  Debug("nf::tmp") << "isNormalForm " << n << " " << cmpKind << endl;
994
12521279
  switch(cmpKind){
995
340772
  case kind::CONST_BOOLEAN:
996
340772
    return true;
997
  case kind::GT:
998
    return isNormalGT();
999
4170577
  case kind::GEQ:
1000
4170577
    return isNormalGEQ();
1001
5352468
  case kind::EQUAL:
1002
5352468
    return isNormalEquality();
1003
1604505
  case kind::LT:
1004
1604505
    return isNormalLT();
1005
  case kind::LEQ:
1006
    return isNormalLEQ();
1007
1052957
  case kind::DISTINCT:
1008
1052957
    return isNormalDistinct();
1009
  default:
1010
    return false;
1011
  }
1012
}
1013
1014
/** This must be (> qpolynomial constant) */
1015
bool Comparison::isNormalGT() const {
1016
  Node n = getNode();
1017
  Assert(n.getKind() == kind::GT);
1018
  if(!rightIsConstant()){
1019
    return false;
1020
  }else{
1021
    Polynomial left = getLeft();
1022
    if(left.containsConstant()){
1023
      return false;
1024
    }else if(!left.leadingCoefficientIsAbsOne()){
1025
      return false;
1026
    }else{
1027
      return !left.isIntegral();
1028
    }
1029
  }
1030
}
1031
1032
/** This must be (not (> qpolynomial constant)) */
1033
bool Comparison::isNormalLEQ() const {
1034
  Node n = getNode();
1035
  Debug("nf::tmp") << "isNormalLEQ " << n << endl;
1036
  Assert(n.getKind() == kind::NOT);
1037
  Assert(n[0].getKind() == kind::GT);
1038
  if(!rightIsConstant()){
1039
    return false;
1040
  }else{
1041
    Polynomial left = getLeft();
1042
    if(left.containsConstant()){
1043
      return false;
1044
    }else if(!left.leadingCoefficientIsAbsOne()){
1045
      return false;
1046
    }else{
1047
      return !left.isIntegral();
1048
    }
1049
  }
1050
}
1051
1052
1053
/** This must be (>= qpolynomial constant) or  (>= zpolynomial constant) */
1054
4170577
bool Comparison::isNormalGEQ() const {
1055
8341154
  Node n = getNode();
1056
4170577
  Assert(n.getKind() == kind::GEQ);
1057
1058
4170577
  Debug("nf::tmp") << "isNormalGEQ " << n << " " << rightIsConstant() << endl;
1059
1060
4170577
  if(!rightIsConstant()){
1061
    return false;
1062
  }else{
1063
8341154
    Polynomial left = getLeft();
1064
4170577
    if(left.containsConstant()){
1065
      return false;
1066
    }else{
1067
4170577
      if(left.isIntegral()){
1068
2563506
        return left.signNormalizedReducedSum();
1069
      }else{
1070
1607071
        return left.leadingCoefficientIsAbsOne();
1071
      }
1072
    }
1073
  }
1074
}
1075
1076
/** This must be (not (>= qpolynomial constant)) or (not (>= zpolynomial constant)) */
1077
1604505
bool Comparison::isNormalLT() const {
1078
3209010
  Node n = getNode();
1079
1604505
  Assert(n.getKind() == kind::NOT);
1080
1604505
  Assert(n[0].getKind() == kind::GEQ);
1081
1082
1604505
  if(!rightIsConstant()){
1083
    return false;
1084
  }else{
1085
3209010
    Polynomial left = getLeft();
1086
1604505
    if(left.containsConstant()){
1087
      return false;
1088
    }else{
1089
1604505
      if(left.isIntegral()){
1090
1137059
        return left.signNormalizedReducedSum();
1091
      }else{
1092
467446
        return left.leadingCoefficientIsAbsOne();
1093
      }
1094
    }
1095
  }
1096
}
1097
1098
1099
6405425
bool Comparison::isNormalEqualityOrDisequality() const {
1100
12810850
  Polynomial pleft = getLeft();
1101
1102
6405425
  if(pleft.numMonomials() == 1){
1103
12810850
    Monomial mleft = pleft.getHead();
1104
6405425
    if(mleft.isConstant()){
1105
      return false;
1106
    }else{
1107
12810850
      Polynomial pright = getRight();
1108
6405425
      if(allIntegralVariables()){
1109
5787732
        const Rational& lcoeff = mleft.getConstant().getValue();
1110
5787732
        if(pright.isConstant()){
1111
2195058
          return pright.isIntegral() && lcoeff.isOne();
1112
        }
1113
7185348
        Polynomial varRight = pright.containsConstant() ? pright.getTail() : pright;
1114
3592674
        if(lcoeff.sgn() <= 0){
1115
          return false;
1116
        }else{
1117
7185348
          Integer lcm = lcoeff.getDenominator().lcm(varRight.denominatorLCM());
1118
7185348
          Integer g = lcoeff.getNumerator().gcd(varRight.numeratorGCD());
1119
3592674
          Debug("nf::tmp") << lcm << " " << g << endl;
1120
3592674
          if(!lcm.isOne()){
1121
            return false;
1122
3592674
          }else if(!g.isOne()){
1123
            return false;
1124
          }else{
1125
7185348
            Monomial absMinRight = varRight.selectAbsMinimum();
1126
3592674
            Debug("nf::tmp") << mleft.getNode() << " " << absMinRight.getNode() << endl;
1127
3592674
            if( mleft.absCmp(absMinRight) < 0){
1128
98979
              return true;
1129
            }else{
1130
3493695
              return (!(absMinRight.absCmp(mleft)< 0)) && mleft < absMinRight;
1131
            }
1132
          }
1133
        }
1134
      }else{
1135
617693
        if(mleft.coefficientIsOne()){
1136
1235386
          Debug("nf::tmp")
1137
617693
            << "dfklj " << mleft.getNode() << endl
1138
617693
            << pright.getNode() << endl
1139
1235386
            << pright.variableMonomialAreStrictlyGreater(mleft)
1140
617693
            << endl;
1141
617693
          return pright.variableMonomialAreStrictlyGreater(mleft);
1142
        }else{
1143
          return false;
1144
        }
1145
      }
1146
    }
1147
  }else{
1148
    return false;
1149
  }
1150
}
1151
1152
/** This must be (= qvarlist qpolynomial) or (= zmonomial zpolynomial)*/
1153
5352468
bool Comparison::isNormalEquality() const {
1154
5352468
  Assert(getNode().getKind() == kind::EQUAL);
1155
16057404
  return Theory::theoryOf(getNode()[0].getType()) == THEORY_ARITH &&
1156
16057404
         isNormalEqualityOrDisequality();
1157
}
1158
1159
/**
1160
 * This must be (not (= qvarlist qpolynomial)) or
1161
 * (not (= zmonomial zpolynomial)).
1162
 */
1163
1052957
bool Comparison::isNormalDistinct() const {
1164
1052957
  Assert(getNode().getKind() == kind::NOT);
1165
1052957
  Assert(getNode()[0].getKind() == kind::EQUAL);
1166
1167
3158871
  return Theory::theoryOf(getNode()[0][0].getType()) == THEORY_ARITH &&
1168
3158871
         isNormalEqualityOrDisequality();
1169
}
1170
1171
77760
Node Comparison::mkRatEquality(const Polynomial& p){
1172
77760
  Assert(!p.isConstant());
1173
77760
  Assert(!p.allIntegralVariables());
1174
1175
155520
  Monomial minimalVList = p.minimumVariableMonomial();
1176
155520
  Constant coeffInv = -(minimalVList.getConstant().inverse());
1177
1178
155520
  Polynomial newRight = (p - minimalVList) * coeffInv;
1179
155520
  Polynomial newLeft(Monomial::mkMonomial(minimalVList.getVarList()));
1180
1181
155520
  return toNode(kind::EQUAL, newLeft, newRight);
1182
}
1183
1184
283184
Node Comparison::mkRatInequality(Kind k, const Polynomial& p){
1185
283184
  Assert(k == kind::GEQ || k == kind::GT);
1186
283184
  Assert(!p.isConstant());
1187
283184
  Assert(!p.allIntegralVariables());
1188
1189
566368
  SumPair sp = SumPair::mkSumPair(p);
1190
566368
  Polynomial left = sp.getPolynomial();
1191
566368
  Constant right = - sp.getConstant();
1192
1193
566368
  Monomial minimalVList = left.getHead();
1194
283184
  Assert(!minimalVList.isConstant());
1195
1196
566368
  Constant coeffInv = minimalVList.getConstant().inverse().abs();
1197
566368
  Polynomial newLeft = left * coeffInv;
1198
566368
  Constant newRight = right * (coeffInv);
1199
1200
566368
  return toNode(k, newLeft, newRight);
1201
}
1202
1203
500230
Node Comparison::mkIntInequality(Kind k, const Polynomial& p){
1204
500230
  Assert(kind::GT == k || kind::GEQ == k);
1205
500230
  Assert(!p.isConstant());
1206
500230
  Assert(p.allIntegralVariables());
1207
1208
1000460
  SumPair sp = SumPair::mkSumPair(p);
1209
1000460
  Polynomial left = sp.getPolynomial();
1210
1000460
  Rational right = - (sp.getConstant().getValue());
1211
1212
1213
1000460
  Monomial m = left.getHead();
1214
500230
  Assert(!m.isConstant());
1215
1216
1000460
  Integer lcm = left.denominatorLCM();
1217
1000460
  Integer g = left.numeratorGCD();
1218
1000460
  Rational mult(lcm,g);
1219
1220
1000460
  Polynomial newLeft = left * mult;
1221
1000460
  Rational rightMult = right * mult;
1222
1223
500230
  bool negateResult = false;
1224
500230
  if(!newLeft.leadingCoefficientIsPositive()){
1225
    // multiply by -1
1226
    // a: left >= right or b: left > right
1227
    // becomes
1228
    // a: -left <= -right or b: -left < -right
1229
    // a: not (-left > -right) or b: (not -left >= -right)
1230
103019
    newLeft = -newLeft;
1231
103019
    rightMult = -rightMult;
1232
103019
    k = (kind::GT == k) ? kind::GEQ : kind::GT;
1233
103019
    negateResult = true;
1234
    // the later stages handle:
1235
    // a: not (-left >= -right + 1) or b: (not -left >= -right)
1236
  }
1237
1238
1000460
  Node result = Node::null();
1239
500230
  if(rightMult.isIntegral()){
1240
495328
    if(k == kind::GT){
1241
      // (> p z)
1242
      // (>= p (+ z 1))
1243
201228
      Constant rightMultPlusOne = Constant::mkConstant(rightMult + 1);
1244
100614
      result = toNode(kind::GEQ, newLeft, rightMultPlusOne);
1245
    }else{
1246
789428
      Constant newRight = Constant::mkConstant(rightMult);
1247
394714
      result = toNode(kind::GEQ, newLeft, newRight);
1248
    }
1249
  }else{
1250
    //(>= l (/ n d))
1251
    //(>= l (ceil (/ n d)))
1252
    //This also hold for GT as (ceil (/ n d)) > (/ n d)
1253
9804
    Integer ceilr = rightMult.ceiling();
1254
9804
    Constant ceilRight = Constant::mkConstant(ceilr);
1255
4902
    result = toNode(kind::GEQ, newLeft, ceilRight);
1256
  }
1257
500230
  Assert(!result.isNull());
1258
500230
  if(negateResult){
1259
103019
    return result.notNode();
1260
  }else{
1261
397211
    return result;
1262
  }
1263
}
1264
1265
763213
Node Comparison::mkIntEquality(const Polynomial& p){
1266
763213
  Assert(!p.isConstant());
1267
763213
  Assert(p.allIntegralVariables());
1268
1269
1526426
  SumPair sp = SumPair::mkSumPair(p);
1270
1526426
  Polynomial varPart = sp.getPolynomial();
1271
1526426
  Constant constPart = sp.getConstant();
1272
1273
1526426
  Integer lcm = varPart.denominatorLCM();
1274
1526426
  Integer g = varPart.numeratorGCD();
1275
1526426
  Constant mult = Constant::mkConstant(Rational(lcm,g));
1276
1277
1526426
  Constant constMult = constPart * mult;
1278
1279
763213
  if(constMult.isIntegral()){
1280
1525418
    Polynomial varPartMult = varPart * mult;
1281
1282
1525418
    Monomial m = varPartMult.selectAbsMinimum();
1283
762709
    bool mIsPositive =  m.getConstant().isPositive();
1284
1285
1525418
    Polynomial noM = (varPartMult + (- m)) + Polynomial::mkPolynomial(constMult);
1286
1287
    // m + noM = 0
1288
1525418
    Polynomial newRight = mIsPositive ? -noM : noM;
1289
1525418
    Polynomial newLeft  = mIsPositive ? m  : -m;
1290
1291
762709
    Assert(newRight.isIntegral());
1292
762709
    return toNode(kind::EQUAL, newLeft, newRight);
1293
  }else{
1294
504
    return mkBoolNode(false);
1295
  }
1296
}
1297
1298
2577007
Comparison Comparison::mkComparison(Kind k, const Polynomial& l, const Polynomial& r){
1299
1300
  //Make this special case fast for sharing!
1301
2577007
  if((k == kind::EQUAL || k == kind::DISTINCT) && l.isVarList() && r.isVarList()){
1302
1228310
    VarList vLeft = l.asVarList();
1303
1228310
    VarList vRight = r.asVarList();
1304
1305
614155
    if(vLeft == vRight){
1306
      // return true for equalities and false for disequalities
1307
795
      return Comparison(k == kind::EQUAL);
1308
    }else{
1309
1226720
      Node eqNode = vLeft < vRight ? toNode( kind::EQUAL, l, r) : toNode( kind::EQUAL, r, l);
1310
1226720
      Node forK = (k == kind::DISTINCT) ? eqNode.notNode() : eqNode;
1311
613360
      return Comparison(forK);
1312
    }
1313
  }
1314
1315
  //General case
1316
3925704
  Polynomial diff = l - r;
1317
1962852
  if(diff.isConstant()){
1318
338465
    bool res = evaluateConstantPredicate(k, diff.asConstant(), Rational(0));
1319
338465
    return Comparison(res);
1320
  }else{
1321
3248774
    Node result = Node::null();
1322
1624387
    bool isInteger = diff.allIntegralVariables();
1323
1624387
    switch(k){
1324
840973
    case kind::EQUAL:
1325
840973
      result = isInteger ? mkIntEquality(diff) : mkRatEquality(diff);
1326
840973
      break;
1327
    case kind::DISTINCT:
1328
      {
1329
        Node eq = isInteger ? mkIntEquality(diff) : mkRatEquality(diff);
1330
        result = eq.notNode();
1331
      }
1332
      break;
1333
124366
    case kind::LEQ:
1334
    case kind::LT:
1335
      {
1336
248732
        Polynomial neg = - diff;
1337
124366
        Kind negKind = (k == kind::LEQ ? kind::GEQ : kind::GT);
1338
124366
        result = isInteger ?
1339
124366
          mkIntInequality(negKind, neg) : mkRatInequality(negKind, neg);
1340
      }
1341
124366
      break;
1342
659048
    case kind::GEQ:
1343
    case kind::GT:
1344
659048
      result = isInteger ?
1345
        mkIntInequality(k, diff) : mkRatInequality(k, diff);
1346
659048
      break;
1347
    default: Unhandled() << k;
1348
    }
1349
1624387
    Assert(!result.isNull());
1350
1624387
    if(result.getKind() == kind::NOT && result[0].getKind() == kind::CONST_BOOLEAN){
1351
      return Comparison(!(result[0].getConst<bool>()));
1352
    }else{
1353
3248774
      Comparison cmp(result);
1354
1624387
      Assert(cmp.isNormalForm());
1355
1624387
      return cmp;
1356
    }
1357
  }
1358
}
1359
1360
38655
bool Comparison::isBoolean() const {
1361
38655
  return getNode().getKind() == kind::CONST_BOOLEAN;
1362
}
1363
1364
1365
38655
bool Comparison::debugIsIntegral() const{
1366
38655
  return getLeft().isIntegral() && getRight().isIntegral();
1367
}
1368
1369
55722222
Kind Comparison::comparisonKind(TNode literal){
1370
55722222
  switch(literal.getKind()){
1371
42222568
  case kind::CONST_BOOLEAN:
1372
  case kind::GT:
1373
  case kind::GEQ:
1374
  case kind::EQUAL:
1375
42222568
    return literal.getKind();
1376
13499654
  case  kind::NOT:
1377
    {
1378
26999308
      TNode negatedAtom = literal[0];
1379
13499654
      switch(negatedAtom.getKind()){
1380
      case kind::GT: //(not (GT x c)) <=> (LEQ x c)
1381
        return kind::LEQ;
1382
6069173
      case kind::GEQ: //(not (GEQ x c)) <=> (LT x c)
1383
6069173
        return kind::LT;
1384
7430481
      case kind::EQUAL:
1385
7430481
        return kind::DISTINCT;
1386
      default:
1387
        return  kind::UNDEFINED_KIND;
1388
      }
1389
    }
1390
  default:
1391
    return kind::UNDEFINED_KIND;
1392
  }
1393
}
1394
1395
1396
Node Polynomial::makeAbsCondition(Variable v, Polynomial p){
1397
  Polynomial zerop = Polynomial::mkZero();
1398
1399
  Polynomial varp = Polynomial::mkPolynomial(v);
1400
  Comparison pLeq0 = Comparison::mkComparison(kind::LEQ, p, zerop);
1401
  Comparison negP = Comparison::mkComparison(kind::EQUAL, varp, -p);
1402
  Comparison posP = Comparison::mkComparison(kind::EQUAL, varp, p);
1403
1404
  Node absCnd = (pLeq0.getNode()).iteNode(negP.getNode(), posP.getNode());
1405
  return absCnd;
1406
}
1407
1408
38655
bool Polynomial::isNonlinear() const {
1409
1410
112282
  for(iterator i=begin(), iend =end(); i != iend; ++i){
1411
149731
    Monomial m = *i;
1412
76104
    if(m.isNonlinear()){
1413
2477
      return true;
1414
    }
1415
  }
1416
36178
  return false;
1417
}
1418
1419
} //namespace arith
1420
} //namespace theory
1421
29502
}  // namespace cvc5