GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/normal_form.cpp Lines: 642 793 81.0 %
Date: 2021-05-22 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
137651048
Constant Constant::mkConstant(const Rational& rat) {
33
137651048
  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
198422762
bool Variable::isLeafMember(Node n){
69
595268286
  return (!isRelationOperator(n.getKind())) &&
70
595268286
    (Theory::isLeafOf(n, theory::THEORY_ARITH));
71
}
72
73
172612416
VarList::VarList(Node n) : NodeWrapper(n) { Assert(isSorted(begin(), end())); }
74
75
342223
bool Variable::isIAndMember(Node n)
76
{
77
1026669
  return n.getKind() == kind::IAND && Polynomial::isMember(n[0])
78
1368892
         && Polynomial::isMember(n[1]);
79
}
80
81
218952
bool Variable::isDivMember(Node n){
82
218952
  switch(n.getKind()){
83
141313
  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
141313
    return Polynomial::isMember(n[0]) && Polynomial::isMember(n[1]);
90
77639
  default:
91
77639
    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
177122566
bool VarList::isSorted(iterator start, iterator end) {
120
177122566
  return std::is_sorted(start, end);
121
}
122
123
131998724
bool VarList::isMember(Node n) {
124
131998724
  if(Variable::isMember(n)) {
125
96236725
    return true;
126
  }
127
35761999
  if(n.getKind() == kind::NONLINEAR_MULT) {
128
4751234
    Node::iterator curr = n.begin(), end = n.end();
129
9502468
    Node prev = *curr;
130
4751234
    if(!Variable::isMember(prev)) return false;
131
132
    Variable::VariableNodeCmp cmp;
133
134
16374948
    while( (++curr) != end) {
135
5811857
      if(!Variable::isMember(*curr)) return false;
136
      // prev <= curr : accept
137
      // !(prev <= curr) : reject
138
      // !(!(prev > curr)) : reject
139
      // curr < prev : reject
140
5811857
      if((cmp(*curr, prev))) return false;
141
5811857
      prev = *curr;
142
    }
143
4751234
    return true;
144
  } else {
145
31010765
    return false;
146
  }
147
}
148
149
119077741
int VarList::cmp(const VarList& vl) const {
150
119077741
  int dif = this->size() - vl.size();
151
119077741
  if (dif == 0) {
152
89121239
    if(this->getNode() == vl.getNode()) {
153
12838886
      return 0;
154
    }
155
156
76282353
    Assert(!empty());
157
76282353
    Assert(!vl.empty());
158
76282353
    if(this->size() == 1){
159
71848869
      return Variable::VariableNodeCmp::cmp(this->getNode(), vl.getNode());
160
    }
161
162
163
8866968
    internal_iterator ii=this->internalBegin(), ie=this->internalEnd();
164
8866968
    internal_iterator ci=vl.internalBegin(), ce=vl.internalEnd();
165
17201091
    for(; ii != ie; ++ii, ++ci){
166
12945222
      Node vi = *ii;
167
12945222
      Node vc = *ci;
168
8689353
      int tmp = Variable::VariableNodeCmp::cmp(vi, vc);
169
8689353
      if(tmp != 0){
170
4433484
        return tmp;
171
      }
172
    }
173
    Unreachable();
174
29956502
  } else if(dif < 0) {
175
16795828
    return -1;
176
  } else {
177
13160674
    return 1;
178
  }
179
}
180
181
172612416
VarList VarList::parseVarList(Node n) {
182
172612416
  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
1189834
VarList VarList::operator*(const VarList& other) const {
195
1189834
  if(this->empty()) {
196
1131985
    return other;
197
57849
  } else if(other.empty()) {
198
12756
    return *this;
199
  } else {
200
90186
    vector<Node> result;
201
202
    internal_iterator
203
90186
      thisBegin = this->internalBegin(),
204
90186
      thisEnd = this->internalEnd(),
205
90186
      otherBegin = other.internalBegin(),
206
90186
      otherEnd = other.internalEnd();
207
208
    Variable::VariableNodeCmp cmp;
209
45093
    std::merge(thisBegin, thisEnd, otherBegin, otherEnd, std::back_inserter(result), cmp);
210
211
45093
    Assert(result.size() >= 2);
212
90186
    Node mult = NodeManager::currentNM()->mkNode(kind::NONLINEAR_MULT, result);
213
45093
    return VarList::parseVarList(mult);
214
  }
215
}
216
217
149121720
bool Monomial::isMember(TNode n){
218
149121720
  if(n.getKind() == kind::CONST_RATIONAL) {
219
20676640
    return true;
220
128445080
  } else if(multStructured(n)) {
221
24957029
    return VarList::isMember(n[1]);
222
  } else {
223
103488051
    return VarList::isMember(n);
224
  }
225
}
226
227
71043532
Monomial Monomial::mkMonomial(const Constant& c, const VarList& vl) {
228
71043532
  if(c.isZero() || vl.empty() ) {
229
4220072
    return Monomial(c);
230
66823460
  } else if(c.isOne()) {
231
1572284
    return Monomial(vl);
232
  } else {
233
65251176
    return Monomial(c, vl);
234
  }
235
}
236
237
70858
Monomial Monomial::mkMonomial(const VarList& vl) {
238
  // acts like Monomial::mkMonomial( 1, vl)
239
70858
  if( vl.empty() ) {
240
    return Monomial::mkOne();
241
  } else if(true){
242
70858
    return Monomial(vl);
243
  }
244
}
245
246
206636497
Monomial Monomial::parseMonomial(Node n) {
247
206636497
  if(n.getKind() == kind::CONST_RATIONAL) {
248
34069218
    return Monomial(Constant(n));
249
172567279
  } else if(multStructured(n)) {
250
61252872
    return Monomial::mkMonomial(Constant(n[0]),VarList::parseVarList(n[1]));
251
  } else {
252
111314407
    return Monomial(VarList::parseVarList(n));
253
  }
254
}
255
7243691
Monomial Monomial::operator*(const Rational& q) const {
256
7243691
  if(q.isZero()){
257
    return mkZero();
258
  }else{
259
14487382
    Constant newConstant = this->getConstant() * q;
260
7243691
    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
1189834
Monomial Monomial::operator*(const Monomial& mono) const {
275
2379668
  Constant newConstant = this->getConstant() * mono.getConstant();
276
2379668
  VarList newVL = this->getVarList() * mono.getVarList();
277
278
2379668
  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
2514709
void Monomial::sort(std::vector<Monomial>& m){
307
2514709
  if(!isSorted(m)){
308
114733
    std::sort(m.begin(), m.end());
309
  }
310
2514709
}
311
312
8577728
void Monomial::combineAdjacentMonomials(std::vector<Monomial>& monos) {
313
8577728
  Assert(isSorted(monos));
314
  size_t writePos, readPos, N;
315
27993085
  for(writePos = 0, readPos = 0, N = monos.size(); readPos < N;){
316
19415357
    Monomial& atRead = monos[readPos];
317
19415357
    const VarList& varList  = atRead.getVarList();
318
319
19415357
    size_t rangeEnd = readPos+1;
320
27905013
    for(; rangeEnd < N; rangeEnd++){
321
15091712
      if(!(varList == monos[rangeEnd].getVarList())){ break; }
322
    }
323
    // monos[i] for i in [readPos, rangeEnd) has the same var list
324
19415357
    if(readPos+1 == rangeEnd){ // no addition needed
325
15291468
      if(!atRead.getConstant().isZero()){
326
26633522
        Monomial cpy = atRead; // being paranoid here
327
13316761
        monos[writePos] = cpy;
328
13316761
        writePos++;
329
      }
330
    }else{
331
8247778
      Rational constant(monos[readPos].getConstant().getValue());
332
8368717
      for(size_t i=readPos+1; i < rangeEnd; ++i){
333
4244828
        constant += monos[i].getConstant().getValue();
334
      }
335
4123889
      if(!constant.isZero()){
336
2711766
        Constant asConstant = Constant::mkConstant(constant);
337
2711766
        Monomial nonZero = Monomial::mkMonomial(asConstant, varList);
338
1355883
        monos[writePos] = nonZero;
339
1355883
        writePos++;
340
      }
341
    }
342
19415357
    Assert(rangeEnd > readPos);
343
19415357
    readPos = rangeEnd;
344
  }
345
8577728
  if(writePos > 0 ){
346
14333814
    Monomial cp = monos[0];
347
7166907
    Assert(writePos <= N);
348
7166907
    monos.resize(writePos, cp);
349
  }else{
350
1410821
    monos.clear();
351
  }
352
8577728
  Assert(isStrictlySorted(monos));
353
8577728
}
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
7124728
Polynomial Polynomial::operator+(const Polynomial& vl) const {
366
367
14249456
  std::vector<Monomial> sortedMonos;
368
7124728
  std::merge(begin(), end(), vl.begin(), vl.end(), std::back_inserter(sortedMonos));
369
370
7124728
  Monomial::combineAdjacentMonomials(sortedMonos);
371
  //std::vector<Monomial> combined = Monomial::sumLikeTerms(sortedMonos);
372
373
7124728
  Polynomial result = mkPolynomial(sortedMonos);
374
14249456
  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
1462508
Polynomial Polynomial::sumPolynomials(const std::vector<Polynomial>& ps){
390
1462508
  if(ps.empty()){
391
    return mkZero();
392
1462508
  }else if(ps.size() <= 4){
393
    // if there are few enough polynomials just add them
394
2906506
    Polynomial p = ps[0];
395
1618272
    for(size_t i = 1; i < ps.size(); ++i){
396
165019
      p = p + ps[i];
397
    }
398
1453253
    return p;
399
  }else{
400
    // general case
401
18510
    std::map<Node, Rational> coeffs;
402
75551
    for(size_t i = 0, N = ps.size(); i<N; ++i){
403
66296
      const Polynomial& p = ps[i];
404
238689
      for(iterator pi = p.begin(), pend = p.end(); pi != pend; ++pi) {
405
344786
        Monomial m = *pi;
406
172393
        coeffs[m.getVarList().getNode()] += m.getConstant().getValue();
407
      }
408
    }
409
18510
    std::vector<Monomial> monos;
410
9255
    std::map<Node, Rational>::const_iterator ci = coeffs.begin(), cend = coeffs.end();
411
149811
    for(; ci != cend; ++ci){
412
70278
      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
9255
    Monomial::sort(monos);
420
9255
    Monomial::combineAdjacentMonomials(monos);
421
422
18510
    Polynomial result = mkPolynomial(monos);
423
9255
    return result;
424
  }
425
}
426
427
2387525
Polynomial Polynomial::operator-(const Polynomial& vl) const {
428
4775050
  Constant negOne = Constant::mkConstant(Rational(-1));
429
430
4775050
  return *this + (vl*negOne);
431
}
432
433
6902849
Polynomial Polynomial::operator*(const Rational& q) const{
434
6902849
  if(q.isZero()){
435
    return Polynomial::mkZero();
436
6902849
  }else if(q.isOne()){
437
2404136
    return *this;
438
  }else{
439
8997426
    std::vector<Monomial> newMonos;
440
10973173
    for(iterator i = this->begin(), end = this->end(); i != end; ++i) {
441
6474460
      newMonos.push_back((*i)*q);
442
    }
443
444
4498713
    Assert(Monomial::isStrictlySorted(newMonos));
445
4498713
    return Polynomial::mkPolynomial(newMonos);
446
  }
447
}
448
449
3630712
Polynomial Polynomial::operator*(const Constant& c) const{
450
3630712
  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
1061920
Polynomial Polynomial::operator*(const Monomial& mono) const {
467
1061920
  if(mono.isZero()) {
468
211
    return Polynomial(mono); //Don't multiply by zero
469
  } else {
470
2123418
    std::vector<Monomial> newMonos;
471
2251543
    for(iterator i = this->begin(), end = this->end(); i != end; ++i) {
472
1189834
      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
1061709
    Monomial::sort(newMonos);
480
1061709
    return Polynomial::mkPolynomial(newMonos);
481
  }
482
}
483
484
1055195
Polynomial Polynomial::operator*(const Polynomial& poly) const {
485
1055195
  Polynomial res = Polynomial::mkZero();
486
2117115
  for(iterator i = this->begin(), end = this->end(); i != end; ++i) {
487
2123840
    Monomial curr = *i;
488
2123840
    Polynomial prod = poly * curr;
489
2123840
    Polynomial sum  = res + prod;
490
1061920
    res = sum;
491
  }
492
1055195
  return res;
493
}
494
495
3731379
Monomial Polynomial::selectAbsMinimum() const {
496
7462758
  iterator iter = begin(), myend = end();
497
3731379
  Assert(iter != myend);
498
499
3731379
  Monomial min = *iter;
500
3731379
  ++iter;
501
6437895
  for(; iter != end(); ++iter){
502
2706516
    Monomial curr = *iter;
503
1353258
    if(curr.absCmp(min) < 0){
504
74359
      min = curr;
505
    }
506
  }
507
7462758
  return min;
508
}
509
510
1942061
bool Polynomial::leadingCoefficientIsAbsOne() const {
511
1942061
  return getHead().absCoefficientIsOne();
512
}
513
5751453
bool Polynomial::leadingCoefficientIsPositive() const {
514
5751453
  return getHead().getConstant().isPositive();
515
}
516
517
3224042
bool Polynomial::denominatorLCMIsOne() const {
518
3224042
  return denominatorLCM().isOne();
519
}
520
521
3224042
bool Polynomial::numeratorGCDIsOne() const {
522
3224042
  return gcd().isOne();
523
}
524
525
3471304
Integer Polynomial::gcd() const {
526
3471304
  Assert(isIntegral());
527
3471304
  return numeratorGCD();
528
}
529
530
7515160
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
15030320
  iterator i=begin(), e=end();
534
7515160
  Assert(i != e);
535
536
7515160
  Integer d = (*i).getConstant().getValue().getNumerator().abs();
537
7515160
  if(d.isOne()){
538
7228951
    return d;
539
  }
540
286209
  ++i;
541
465563
  for(; i!=e; ++i){
542
377089
    Integer c = (*i).getConstant().getValue().getNumerator();
543
287412
    d = d.gcd(c);
544
287412
    if(d.isOne()){
545
197735
      return d;
546
    }
547
  }
548
88474
  return d;
549
}
550
551
7267898
Integer Polynomial::denominatorLCM() const {
552
7267898
  Integer tmp(1);
553
17981065
  for (iterator i = begin(), e = end(); i != e; ++i) {
554
21426334
    const Integer denominator = (*i).getConstant().getValue().getDenominator();
555
10713167
    tmp = tmp.lcm(denominator);
556
  }
557
7267898
  return tmp;
558
}
559
560
4496488
Constant Polynomial::getCoefficient(const VarList& vl) const{
561
  //TODO improve to binary search...
562
11799748
  for(iterator iter=begin(), myend=end(); iter != myend; ++iter){
563
14668375
    Monomial m = *iter;
564
14668375
    VarList curr = m.getVarList();
565
7365115
    if(curr == vl){
566
61855
      return m.getConstant();
567
    }
568
  }
569
4434633
  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
737926
Monomial Polynomial::minimumVariableMonomial() const{
601
737926
  Assert(!isConstant());
602
737926
  if(singleton()){
603
455802
    return getHead();
604
  }else{
605
564248
    iterator i = begin();
606
564248
    Monomial first = *i;
607
282124
    if( first.isConstant() ){
608
197852
      ++i;
609
197852
      Assert(i != end());
610
197852
      return *i;
611
    }else{
612
84272
      return first;
613
    }
614
  }
615
}
616
617
1134778
bool Polynomial::variableMonomialAreStrictlyGreater(const Monomial& m) const{
618
1134778
  if(isConstant()){
619
467710
    return true;
620
  }else{
621
1334136
    Monomial minimum = minimumVariableMonomial();
622
667068
    Debug("nf::tmp") << "minimum " << minimum.getNode() << endl;
623
667068
    Debug("nf::tmp") << "m " << m.getNode() << endl;
624
667068
    return m < minimum;
625
  }
626
}
627
628
56211353
bool Polynomial::isMember(TNode n) {
629
56211353
  if(Monomial::isMember(n)){
630
39976018
    return true;
631
16235335
  }else if(n.getKind() == kind::PLUS){
632
16235335
    Assert(n.getNumChildren() >= 2);
633
16235335
    Node::iterator currIter = n.begin(), end = n.end();
634
32470670
    Node prev = *currIter;
635
16235335
    if(!Monomial::isMember(prev)){
636
      return false;
637
    }
638
639
32470670
    Monomial mprev = Monomial::parseMonomial(prev);
640
16235335
    ++currIter;
641
63296687
    for(; currIter != end; ++currIter){
642
47061352
      Node curr = *currIter;
643
23530676
      if(!Monomial::isMember(curr)){
644
        return false;
645
      }
646
47061352
      Monomial mcurr = Monomial::parseMonomial(curr);
647
23530676
      if(!(mprev < mcurr)){
648
        return false;
649
      }
650
23530676
      mprev = mcurr;
651
    }
652
16235335
    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
1361420
SumPair SumPair::mkSumPair(const Polynomial& p){
680
1361420
  if(p.isConstant()){
681
    Constant leadingConstant = p.getHead().getConstant();
682
    return SumPair(Polynomial::mkZero(), leadingConstant);
683
1361420
  }else if(p.containsConstant()){
684
834779
    Assert(!p.singleton());
685
834779
    return SumPair(p.getTail(), p.getHead().getConstant());
686
  }else{
687
526641
    return SumPair(p, Constant::mkZero());
688
  }
689
}
690
691
4260176
Comparison::Comparison(TNode n) : NodeWrapper(n) { Assert(isNormalForm()); }
692
693
38998
SumPair Comparison::toSumPair() const {
694
38998
  Kind cmpKind = comparisonKind();
695
38998
  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
38998
  case kind::EQUAL:
712
  case kind::DISTINCT:
713
    {
714
77996
      Polynomial left = getLeft();
715
77996
      Polynomial right = getRight();
716
38998
      Debug("nf::tmp") << "left: " << left.getNode() << endl;
717
38998
      Debug("nf::tmp") << "right: " << right.getNode() << endl;
718
38998
      if(right.isConstant()){
719
14506
        return SumPair(left, -right.getHead().getConstant());
720
24492
      }else if(right.containsConstant()){
721
10656
        Assert(!right.singleton());
722
723
21312
        Polynomial noConstant = right.getTail();
724
10656
        return SumPair(left - noConstant, -right.getHead().getConstant());
725
      }else{
726
13836
        return SumPair(left - right, Constant::mkZero());
727
      }
728
    }
729
    default: Unhandled() << cmpKind;
730
  }
731
}
732
733
970497
Polynomial Comparison::normalizedVariablePart() const {
734
970497
  Kind cmpKind = comparisonKind();
735
970497
  switch(cmpKind){
736
548305
  case kind::LT:
737
  case kind::LEQ:
738
  case kind::GT:
739
  case kind::GEQ:
740
    {
741
1096610
      TNode lit = getNode();
742
1096610
      TNode atom = (cmpKind == kind::LT || cmpKind == kind::LEQ) ? lit[0] : lit;
743
1096610
      Polynomial p = Polynomial::parsePolynomial(atom[0]);
744
548305
      if(p.leadingCoefficientIsPositive()){
745
448308
        return p;
746
      }else{
747
99997
        return -p;
748
      }
749
    }
750
422192
  case kind::EQUAL:
751
  case kind::DISTINCT:
752
    {
753
844384
      Polynomial left = getLeft();
754
844384
      Polynomial right = getRight();
755
422192
      if(right.isConstant()){
756
192176
        return left;
757
      }else{
758
460032
        Polynomial noConstant = right.containsConstant() ? right.getTail() : right;
759
460032
        Polynomial diff = left - noConstant;
760
230016
        if(diff.leadingCoefficientIsPositive()){
761
227304
          return diff;
762
        }else{
763
2712
          return -diff;
764
        }
765
      }
766
    }
767
    default: Unhandled() << cmpKind;
768
  }
769
}
770
771
969086
DeltaRational Comparison::normalizedDeltaRational() const {
772
969086
  Kind cmpKind = comparisonKind();
773
969086
  int delta = deltaCoeff(cmpKind);
774
969086
  switch(cmpKind){
775
547098
  case kind::LT:
776
  case kind::LEQ:
777
  case kind::GT:
778
  case kind::GEQ:
779
    {
780
1094196
      Node lit = getNode();
781
1094196
      Node atom = (cmpKind == kind::LT || cmpKind == kind::LEQ) ? lit[0] : lit;
782
1094196
      Polynomial left = Polynomial::parsePolynomial(atom[0]);
783
547098
      const Rational& q = atom[1].getConst<Rational>();
784
547098
      if(left.leadingCoefficientIsPositive()){
785
447314
        return DeltaRational(q, delta);
786
      }else{
787
99784
        return DeltaRational(-q, -delta);
788
      }
789
    }
790
421988
  case kind::EQUAL:
791
  case kind::DISTINCT:
792
    {
793
843976
      Polynomial right = getRight();
794
843976
      Monomial firstRight = right.getHead();
795
421988
      if(firstRight.isConstant()){
796
465112
        DeltaRational c = DeltaRational(firstRight.getConstant().getValue(), 0);
797
465112
        Polynomial left = getLeft();
798
232556
        if(!left.allIntegralVariables()){
799
22368
          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
420376
          Polynomial diff = right.singleton() ? left : left - right.getTail();
806
210188
          if(diff.leadingCoefficientIsPositive()){
807
209716
            return c;
808
          }else{
809
472
            return -c;
810
          }
811
        }
812
      }else{ // The constant is 0 sign cannot change
813
189432
        return DeltaRational(0, 0);
814
      }
815
    }
816
    default: Unhandled() << cmpKind;
817
  }
818
}
819
820
316986
std::tuple<Polynomial, Kind, Constant> Comparison::decompose(
821
    bool split_constant) const
822
{
823
316986
  Kind rel = getNode().getKind();
824
316986
  if (rel == Kind::NOT)
825
  {
826
147783
    switch (getNode()[0].getKind())
827
    {
828
      case kind::LEQ: rel = Kind::GT; break;
829
      case kind::LT: rel = Kind::GEQ; break;
830
48471
      case kind::EQUAL: rel = Kind::DISTINCT; break;
831
      case kind::DISTINCT: rel = Kind::EQUAL; break;
832
99312
      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
633972
  Polynomial poly = getLeft() - getRight();
840
841
316986
  if (!split_constant)
842
  {
843
    return std::tuple<Polynomial, Kind, Constant>{
844
80
        poly, rel, Constant::mkZero()};
845
  }
846
847
633812
  Constant right = Constant::mkZero();
848
316906
  if (poly.containsConstant())
849
  {
850
132201
    right = -poly.getHead().getConstant();
851
132201
    poly = poly + Polynomial::mkPolynomial(right);
852
  }
853
854
633812
  Constant lcoeff = poly.getHead().getConstant();
855
316906
  if (!lcoeff.isOne())
856
  {
857
92258
    Constant invlcoeff = lcoeff.inverse();
858
46129
    if (lcoeff.isNegative())
859
    {
860
39772
      switch (rel)
861
      {
862
        case kind::LEQ: rel = Kind::GEQ; break;
863
20850
        case kind::LT: rel = Kind::GT; break;
864
486
        case kind::EQUAL: break;
865
376
        case kind::DISTINCT: break;
866
18060
        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
46129
    poly = poly * invlcoeff;
872
46129
    right = right * invlcoeff;
873
  }
874
875
316906
  return std::tuple<Polynomial, Kind, Constant>{poly, rel, right};
876
}
877
878
2259204
Comparison Comparison::parseNormalForm(TNode n) {
879
2259204
  Debug("polynomial") << "Comparison::parseNormalForm(" << n << ")";
880
2259204
  Comparison result(n);
881
2259204
  Assert(result.isNormalForm());
882
2259204
  return result;
883
}
884
885
696166
Node Comparison::toNode(Kind k, const Polynomial& l, const Constant& r) {
886
696166
  Assert(isRelationOperator(k));
887
696166
  switch(k) {
888
696166
  case kind::GEQ:
889
  case kind::GT:
890
1392332
    return NodeManager::currentNM()->mkNode(k, l.getNode(), r.getNode());
891
  default: Unhandled() << k;
892
  }
893
}
894
895
1304308
Node Comparison::toNode(Kind k, const Polynomial& l, const Polynomial& r) {
896
1304308
  Assert(isRelationOperator(k));
897
1304308
  switch(k) {
898
1304308
  case kind::GEQ:
899
  case kind::EQUAL:
900
  case kind::GT:
901
1304308
    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
8927050
bool Comparison::rightIsConstant() const {
914
8927050
  if(getNode().getKind() == kind::NOT){
915
1405156
    return getNode()[0][1].getKind() == kind::CONST_RATIONAL;
916
  }else{
917
7521894
    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
17433749
Polynomial Comparison::getLeft() const {
936
34867498
  TNode left;
937
17433749
  Kind k = comparisonKind();
938
17433749
  switch(k){
939
3581375
  case kind::LT:
940
  case kind::LEQ:
941
  case kind::DISTINCT:
942
3581375
    left = getNode()[0][0];
943
3581375
    break;
944
13852374
  case kind::EQUAL:
945
  case kind::GT:
946
  case kind::GEQ:
947
13852374
    left = getNode()[0];
948
13852374
    break;
949
  default: Unhandled() << k;
950
  }
951
34867498
  return Polynomial::parsePolynomial(left);
952
}
953
954
11616057
Polynomial Comparison::getRight() const {
955
23232114
  TNode right;
956
11616057
  Kind k = comparisonKind();
957
11616057
  switch(k){
958
2030465
  case kind::LT:
959
  case kind::LEQ:
960
  case kind::DISTINCT:
961
2030465
    right = getNode()[0][1];
962
2030465
    break;
963
9585592
  case kind::EQUAL:
964
  case kind::GT:
965
  case kind::GEQ:
966
9585592
    right = getNode()[1];
967
9585592
    break;
968
  default: Unhandled() << k;
969
  }
970
23232114
  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
10916906
bool Comparison::isNormalForm() const {
986
21833812
  Node n = getNode();
987
10916906
  Kind cmpKind = comparisonKind(n);
988
10916906
  Debug("nf::tmp") << "isNormalForm " << n << " " << cmpKind << endl;
989
10916906
  switch(cmpKind){
990
279635
  case kind::CONST_BOOLEAN:
991
279635
    return true;
992
  case kind::GT:
993
    return isNormalGT();
994
3760947
  case kind::GEQ:
995
3760947
    return isNormalGEQ();
996
4635798
  case kind::EQUAL:
997
4635798
    return isNormalEquality();
998
1405156
  case kind::LT:
999
1405156
    return isNormalLT();
1000
  case kind::LEQ:
1001
    return isNormalLEQ();
1002
835370
  case kind::DISTINCT:
1003
835370
    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
3760947
bool Comparison::isNormalGEQ() const {
1050
7521894
  Node n = getNode();
1051
3760947
  Assert(n.getKind() == kind::GEQ);
1052
1053
3760947
  Debug("nf::tmp") << "isNormalGEQ " << n << " " << rightIsConstant() << endl;
1054
1055
3760947
  if(!rightIsConstant()){
1056
    return false;
1057
  }else{
1058
7521894
    Polynomial left = getLeft();
1059
3760947
    if(left.containsConstant()){
1060
      return false;
1061
    }else{
1062
3760947
      if(left.isIntegral()){
1063
2258624
        return left.signNormalizedReducedSum();
1064
      }else{
1065
1502323
        return left.leadingCoefficientIsAbsOne();
1066
      }
1067
    }
1068
  }
1069
}
1070
1071
/** This must be (not (>= qpolynomial constant)) or (not (>= zpolynomial constant)) */
1072
1405156
bool Comparison::isNormalLT() const {
1073
2810312
  Node n = getNode();
1074
1405156
  Assert(n.getKind() == kind::NOT);
1075
1405156
  Assert(n[0].getKind() == kind::GEQ);
1076
1077
1405156
  if(!rightIsConstant()){
1078
    return false;
1079
  }else{
1080
2810312
    Polynomial left = getLeft();
1081
1405156
    if(left.containsConstant()){
1082
      return false;
1083
    }else{
1084
1405156
      if(left.isIntegral()){
1085
965418
        return left.signNormalizedReducedSum();
1086
      }else{
1087
439738
        return left.leadingCoefficientIsAbsOne();
1088
      }
1089
    }
1090
  }
1091
}
1092
1093
1094
5471168
bool Comparison::isNormalEqualityOrDisequality() const {
1095
10942336
  Polynomial pleft = getLeft();
1096
1097
5471168
  if(pleft.numMonomials() == 1){
1098
10942336
    Monomial mleft = pleft.getHead();
1099
5471168
    if(mleft.isConstant()){
1100
      return false;
1101
    }else{
1102
10942336
      Polynomial pright = getRight();
1103
5471168
      if(allIntegralVariables()){
1104
4903779
        const Rational& lcoeff = mleft.getConstant().getValue();
1105
4903779
        if(pright.isConstant()){
1106
1960201
          return pright.isIntegral() && lcoeff.isOne();
1107
        }
1108
5887156
        Polynomial varRight = pright.containsConstant() ? pright.getTail() : pright;
1109
2943578
        if(lcoeff.sgn() <= 0){
1110
          return false;
1111
        }else{
1112
5887156
          Integer lcm = lcoeff.getDenominator().lcm(varRight.denominatorLCM());
1113
5887156
          Integer g = lcoeff.getNumerator().gcd(varRight.numeratorGCD());
1114
2943578
          Debug("nf::tmp") << lcm << " " << g << endl;
1115
2943578
          if(!lcm.isOne()){
1116
            return false;
1117
2943578
          }else if(!g.isOne()){
1118
            return false;
1119
          }else{
1120
5887156
            Monomial absMinRight = varRight.selectAbsMinimum();
1121
2943578
            Debug("nf::tmp") << mleft.getNode() << " " << absMinRight.getNode() << endl;
1122
2943578
            if( mleft.absCmp(absMinRight) < 0){
1123
77662
              return true;
1124
            }else{
1125
2865916
              return (!(absMinRight.absCmp(mleft)< 0)) && mleft < absMinRight;
1126
            }
1127
          }
1128
        }
1129
      }else{
1130
567389
        if(mleft.coefficientIsOne()){
1131
1134778
          Debug("nf::tmp")
1132
567389
            << "dfklj " << mleft.getNode() << endl
1133
567389
            << pright.getNode() << endl
1134
1134778
            << pright.variableMonomialAreStrictlyGreater(mleft)
1135
567389
            << endl;
1136
567389
          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
4635798
bool Comparison::isNormalEquality() const {
1149
4635798
  Assert(getNode().getKind() == kind::EQUAL);
1150
13907394
  return Theory::theoryOf(getNode()[0].getType()) == THEORY_ARITH &&
1151
13907394
         isNormalEqualityOrDisequality();
1152
}
1153
1154
/**
1155
 * This must be (not (= qvarlist qpolynomial)) or
1156
 * (not (= zmonomial zpolynomial)).
1157
 */
1158
835370
bool Comparison::isNormalDistinct() const {
1159
835370
  Assert(getNode().getKind() == kind::NOT);
1160
835370
  Assert(getNode()[0].getKind() == kind::EQUAL);
1161
1162
2506110
  return Theory::theoryOf(getNode()[0][0].getType()) == THEORY_ARITH &&
1163
2506110
         isNormalEqualityOrDisequality();
1164
}
1165
1166
70858
Node Comparison::mkRatEquality(const Polynomial& p){
1167
70858
  Assert(!p.isConstant());
1168
70858
  Assert(!p.allIntegralVariables());
1169
1170
141716
  Monomial minimalVList = p.minimumVariableMonomial();
1171
141716
  Constant coeffInv = -(minimalVList.getConstant().inverse());
1172
1173
141716
  Polynomial newRight = (p - minimalVList) * coeffInv;
1174
141716
  Polynomial newLeft(Monomial::mkMonomial(minimalVList.getVarList()));
1175
1176
141716
  return toNode(kind::EQUAL, newLeft, newRight);
1177
}
1178
1179
261142
Node Comparison::mkRatInequality(Kind k, const Polynomial& p){
1180
261142
  Assert(k == kind::GEQ || k == kind::GT);
1181
261142
  Assert(!p.isConstant());
1182
261142
  Assert(!p.allIntegralVariables());
1183
1184
522284
  SumPair sp = SumPair::mkSumPair(p);
1185
522284
  Polynomial left = sp.getPolynomial();
1186
522284
  Constant right = - sp.getConstant();
1187
1188
522284
  Monomial minimalVList = left.getHead();
1189
261142
  Assert(!minimalVList.isConstant());
1190
1191
522284
  Constant coeffInv = minimalVList.getConstant().inverse().abs();
1192
522284
  Polynomial newLeft = left * coeffInv;
1193
522284
  Constant newRight = right * (coeffInv);
1194
1195
522284
  return toNode(k, newLeft, newRight);
1196
}
1197
1198
435024
Node Comparison::mkIntInequality(Kind k, const Polynomial& p){
1199
435024
  Assert(kind::GT == k || kind::GEQ == k);
1200
435024
  Assert(!p.isConstant());
1201
435024
  Assert(p.allIntegralVariables());
1202
1203
870048
  SumPair sp = SumPair::mkSumPair(p);
1204
870048
  Polynomial left = sp.getPolynomial();
1205
870048
  Rational right = - (sp.getConstant().getValue());
1206
1207
1208
870048
  Monomial m = left.getHead();
1209
435024
  Assert(!m.isConstant());
1210
1211
870048
  Integer lcm = left.denominatorLCM();
1212
870048
  Integer g = left.numeratorGCD();
1213
870048
  Rational mult(lcm,g);
1214
1215
870048
  Polynomial newLeft = left * mult;
1216
870048
  Rational rightMult = right * mult;
1217
1218
435024
  bool negateResult = false;
1219
435024
  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
83594
    newLeft = -newLeft;
1226
83594
    rightMult = -rightMult;
1227
83594
    k = (kind::GT == k) ? kind::GEQ : kind::GT;
1228
83594
    negateResult = true;
1229
    // the later stages handle:
1230
    // a: not (-left >= -right + 1) or b: (not -left >= -right)
1231
  }
1232
1233
870048
  Node result = Node::null();
1234
435024
  if(rightMult.isIntegral()){
1235
430871
    if(k == kind::GT){
1236
      // (> p z)
1237
      // (>= p (+ z 1))
1238
163116
      Constant rightMultPlusOne = Constant::mkConstant(rightMult + 1);
1239
81558
      result = toNode(kind::GEQ, newLeft, rightMultPlusOne);
1240
    }else{
1241
698626
      Constant newRight = Constant::mkConstant(rightMult);
1242
349313
      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
8306
    Integer ceilr = rightMult.ceiling();
1249
8306
    Constant ceilRight = Constant::mkConstant(ceilr);
1250
4153
    result = toNode(kind::GEQ, newLeft, ceilRight);
1251
  }
1252
435024
  Assert(!result.isNull());
1253
435024
  if(negateResult){
1254
83594
    return result.notNode();
1255
  }else{
1256
351430
    return result;
1257
  }
1258
}
1259
1260
665254
Node Comparison::mkIntEquality(const Polynomial& p){
1261
665254
  Assert(!p.isConstant());
1262
665254
  Assert(p.allIntegralVariables());
1263
1264
1330508
  SumPair sp = SumPair::mkSumPair(p);
1265
1330508
  Polynomial varPart = sp.getPolynomial();
1266
1330508
  Constant constPart = sp.getConstant();
1267
1268
1330508
  Integer lcm = varPart.denominatorLCM();
1269
1330508
  Integer g = varPart.numeratorGCD();
1270
1330508
  Constant mult = Constant::mkConstant(Rational(lcm,g));
1271
1272
1330508
  Constant constMult = constPart * mult;
1273
1274
665254
  if(constMult.isIntegral()){
1275
1329512
    Polynomial varPartMult = varPart * mult;
1276
1277
1329512
    Monomial m = varPartMult.selectAbsMinimum();
1278
664756
    bool mIsPositive =  m.getConstant().isPositive();
1279
1280
1329512
    Polynomial noM = (varPartMult + (- m)) + Polynomial::mkPolynomial(constMult);
1281
1282
    // m + noM = 0
1283
1329512
    Polynomial newRight = mIsPositive ? -noM : noM;
1284
1329512
    Polynomial newLeft  = mIsPositive ? m  : -m;
1285
1286
664756
    Assert(newRight.isIntegral());
1287
664756
    return toNode(kind::EQUAL, newLeft, newRight);
1288
  }else{
1289
498
    return mkBoolNode(false);
1290
  }
1291
}
1292
1293
2279113
Comparison Comparison::mkComparison(Kind k, const Polynomial& l, const Polynomial& r){
1294
1295
  //Make this special case fast for sharing!
1296
2279113
  if((k == kind::EQUAL || k == kind::DISTINCT) && l.isVarList() && r.isVarList()){
1297
1138924
    VarList vLeft = l.asVarList();
1298
1138924
    VarList vRight = r.asVarList();
1299
1300
569462
    if(vLeft == vRight){
1301
      // return true for equalities and false for disequalities
1302
768
      return Comparison(k == kind::EQUAL);
1303
    }else{
1304
1137388
      Node eqNode = vLeft < vRight ? toNode( kind::EQUAL, l, r) : toNode( kind::EQUAL, r, l);
1305
1137388
      Node forK = (k == kind::DISTINCT) ? eqNode.notNode() : eqNode;
1306
568694
      return Comparison(forK);
1307
    }
1308
  }
1309
1310
  //General case
1311
3419302
  Polynomial diff = l - r;
1312
1709651
  if(diff.isConstant()){
1313
277373
    bool res = evaluateConstantPredicate(k, diff.asConstant(), Rational(0));
1314
277373
    return Comparison(res);
1315
  }else{
1316
2864556
    Node result = Node::null();
1317
1432278
    bool isInteger = diff.allIntegralVariables();
1318
1432278
    switch(k){
1319
736112
    case kind::EQUAL:
1320
736112
      result = isInteger ? mkIntEquality(diff) : mkRatEquality(diff);
1321
736112
      break;
1322
    case kind::DISTINCT:
1323
      {
1324
        Node eq = isInteger ? mkIntEquality(diff) : mkRatEquality(diff);
1325
        result = eq.notNode();
1326
      }
1327
      break;
1328
108684
    case kind::LEQ:
1329
    case kind::LT:
1330
      {
1331
217368
        Polynomial neg = - diff;
1332
108684
        Kind negKind = (k == kind::LEQ ? kind::GEQ : kind::GT);
1333
108684
        result = isInteger ?
1334
108684
          mkIntInequality(negKind, neg) : mkRatInequality(negKind, neg);
1335
      }
1336
108684
      break;
1337
587482
    case kind::GEQ:
1338
    case kind::GT:
1339
587482
      result = isInteger ?
1340
        mkIntInequality(k, diff) : mkRatInequality(k, diff);
1341
587482
      break;
1342
    default: Unhandled() << k;
1343
    }
1344
1432278
    Assert(!result.isNull());
1345
1432278
    if(result.getKind() == kind::NOT && result[0].getKind() == kind::CONST_BOOLEAN){
1346
      return Comparison(!(result[0].getConst<bool>()));
1347
    }else{
1348
2864556
      Comparison cmp(result);
1349
1432278
      Assert(cmp.isNormalForm());
1350
1432278
      return cmp;
1351
    }
1352
  }
1353
}
1354
1355
38998
bool Comparison::isBoolean() const {
1356
38998
  return getNode().getKind() == kind::CONST_BOOLEAN;
1357
}
1358
1359
1360
38998
bool Comparison::debugIsIntegral() const{
1361
38998
  return getLeft().isIntegral() && getRight().isIntegral();
1362
}
1363
1364
47919680
Kind Comparison::comparisonKind(TNode literal){
1365
47919680
  switch(literal.getKind()){
1366
36713966
  case kind::CONST_BOOLEAN:
1367
  case kind::GT:
1368
  case kind::GEQ:
1369
  case kind::EQUAL:
1370
36713966
    return literal.getKind();
1371
11205714
  case  kind::NOT:
1372
    {
1373
22411428
      TNode negatedAtom = literal[0];
1374
11205714
      switch(negatedAtom.getKind()){
1375
      case kind::GT: //(not (GT x c)) <=> (LEQ x c)
1376
        return kind::LEQ;
1377
5354567
      case kind::GEQ: //(not (GEQ x c)) <=> (LT x c)
1378
5354567
        return kind::LT;
1379
5851147
      case kind::EQUAL:
1380
5851147
        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
38998
bool Polynomial::isNonlinear() const {
1404
1405
113109
  for(iterator i=begin(), iend =end(); i != iend; ++i){
1406
150075
    Monomial m = *i;
1407
75964
    if(m.isNonlinear()){
1408
1853
      return true;
1409
    }
1410
  }
1411
37145
  return false;
1412
}
1413
1414
} //namespace arith
1415
} //namespace theory
1416
28191
}  // namespace cvc5