GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/nl/ext/monomial_check.cpp Lines: 359 370 97.0 %
Date: 2021-08-20 Branches: 748 1482 50.5 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Gereon Kremer, Tim King
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
 * Check for some monomial lemmas.
14
 */
15
16
#include "theory/arith/nl/ext/monomial_check.h"
17
18
#include "expr/node.h"
19
#include "proof/proof.h"
20
#include "theory/arith/arith_msum.h"
21
#include "theory/arith/inference_manager.h"
22
#include "theory/arith/nl/ext/ext_state.h"
23
#include "theory/arith/nl/nl_lemma_utils.h"
24
#include "theory/arith/nl/nl_model.h"
25
#include "util/rational.h"
26
27
namespace cvc5 {
28
namespace theory {
29
namespace arith {
30
namespace nl {
31
32
5150
MonomialCheck::MonomialCheck(ExtState* data) : d_data(data)
33
{
34
5150
  d_order_points.push_back(d_data->d_neg_one);
35
5150
  d_order_points.push_back(d_data->d_zero);
36
5150
  d_order_points.push_back(d_data->d_one);
37
5150
}
38
39
2775
void MonomialCheck::init(const std::vector<Node>& xts)
40
{
41
2775
  d_ms_proc.clear();
42
2775
  d_m_nconst_factor.clear();
43
44
22621
  for (unsigned i = 0, xsize = xts.size(); i < xsize; i++)
45
  {
46
39692
    Node a = xts[i];
47
19846
    if (a.getKind() == Kind::NONLINEAR_MULT)
48
    {
49
13112
      const std::vector<Node>& varList = d_data->d_mdb.getVariableList(a);
50
38751
      for (const Node& v : varList)
51
      {
52
51278
        Node mvk = d_data->d_model.computeAbstractModelValue(v);
53
25639
        if (!mvk.isConst())
54
        {
55
          d_m_nconst_factor[a] = true;
56
        }
57
      }
58
    }
59
  }
60
61
11100
  for (unsigned j = 0; j < d_order_points.size(); j++)
62
  {
63
16650
    Node c = d_order_points[j];
64
8325
    d_data->d_model.computeConcreteModelValue(c);
65
8325
    d_data->d_model.computeAbstractModelValue(c);
66
  }
67
2775
}
68
69
2362
void MonomialCheck::checkSign()
70
{
71
4724
  std::map<Node, int> signs;
72
2362
  Trace("nl-ext") << "Get monomial sign lemmas..." << std::endl;
73
14442
  for (unsigned j = 0; j < d_data->d_ms.size(); j++)
74
  {
75
24160
    Node a = d_data->d_ms[j];
76
12080
    if (d_ms_proc.find(a) == d_ms_proc.end())
77
    {
78
24160
      std::vector<Node> exp;
79
12080
      if (Trace.isOn("nl-ext-debug"))
80
      {
81
        Node cmva = d_data->d_model.computeConcreteModelValue(a);
82
        Trace("nl-ext-debug")
83
            << "  process " << a << ", mv=" << cmva << "..." << std::endl;
84
      }
85
12080
      if (d_m_nconst_factor.find(a) == d_m_nconst_factor.end())
86
      {
87
12080
        signs[a] = compareSign(a, a, 0, 1, exp);
88
12080
        if (signs[a] == 0)
89
        {
90
1920
          d_ms_proc[a] = true;
91
3840
          Trace("nl-ext-debug")
92
1920
              << "...mark " << a << " reduced since its value is 0."
93
1920
              << std::endl;
94
        }
95
      }
96
      else
97
      {
98
        Trace("nl-ext-debug")
99
            << "...can't conclude sign lemma for " << a
100
            << " since model value of a factor is non-constant." << std::endl;
101
      }
102
    }
103
  }
104
2362
}
105
106
3301
void MonomialCheck::checkMagnitude(unsigned c)
107
{
108
  // ensure information is setup
109
3301
  if (c == 0)
110
  {
111
    // sort by absolute values of abstract model values
112
1526
    assignOrderIds(d_data->d_ms_vars, d_order_vars, false, true);
113
114
    // sort individual variable lists
115
1526
    Trace("nl-ext-proc") << "Assign order var lists..." << std::endl;
116
1526
    d_data->d_mdb.sortVariablesByModel(d_data->d_ms, d_data->d_model);
117
  }
118
119
3301
  unsigned r = 1;
120
6602
  std::vector<SimpleTheoryLemma> lemmas;
121
  // if (x,y,L) in cmp_infers, then x > y inferred as conclusion of L
122
  // in lemmas
123
6602
  std::map<int, std::map<Node, std::map<Node, Node> > > cmp_infers;
124
6602
  Trace("nl-ext") << "Get monomial comparison lemmas (order=" << r
125
3301
                  << ", compare=" << c << ")..." << std::endl;
126
21829
  for (unsigned j = 0; j < d_data->d_ms.size(); j++)
127
  {
128
37056
    Node a = d_data->d_ms[j];
129
37056
    if (d_ms_proc.find(a) == d_ms_proc.end()
130
18528
        && d_m_nconst_factor.find(a) == d_m_nconst_factor.end())
131
    {
132
16747
      if (c == 0)
133
      {
134
        // compare magnitude against 1
135
15224
        std::vector<Node> exp;
136
15224
        NodeMultiset a_exp_proc;
137
15224
        NodeMultiset b_exp_proc;
138
15224
        compareMonomial(a,
139
                        a,
140
                        a_exp_proc,
141
7612
                        d_data->d_one,
142
7612
                        d_data->d_one,
143
                        b_exp_proc,
144
                        exp,
145
                        lemmas,
146
                        cmp_infers);
147
      }
148
      else
149
      {
150
9135
        const NodeMultiset& mea = d_data->d_mdb.getMonomialExponentMap(a);
151
9135
        if (c == 1)
152
        {
153
          // could compare not just against containing variables?
154
          // compare magnitude against variables
155
43206
          for (unsigned k = 0; k < d_data->d_ms_vars.size(); k++)
156
          {
157
75538
            Node v = d_data->d_ms_vars[k];
158
75538
            Node mvcv = d_data->d_model.computeConcreteModelValue(v);
159
37769
            if (mvcv.isConst())
160
            {
161
75082
              std::vector<Node> exp;
162
75082
              NodeMultiset a_exp_proc;
163
75082
              NodeMultiset b_exp_proc;
164
37541
              if (mea.find(v) != mea.end())
165
              {
166
9734
                a_exp_proc[v] = 1;
167
9734
                b_exp_proc[v] = 1;
168
9734
                setMonomialFactor(a, v, a_exp_proc);
169
9734
                setMonomialFactor(v, a, b_exp_proc);
170
9734
                compareMonomial(a,
171
                                a,
172
                                a_exp_proc,
173
                                v,
174
                                v,
175
                                b_exp_proc,
176
                                exp,
177
                                lemmas,
178
                                cmp_infers);
179
              }
180
            }
181
          }
182
        }
183
        else
184
        {
185
          // compare magnitude against other non-linear monomials
186
28343
          for (unsigned k = (j + 1); k < d_data->d_ms.size(); k++)
187
          {
188
49290
            Node b = d_data->d_ms[k];
189
            //(signs[a]==signs[b])==(r==0)
190
49290
            if (d_ms_proc.find(b) == d_ms_proc.end()
191
24645
                && d_m_nconst_factor.find(b) == d_m_nconst_factor.end())
192
            {
193
23216
              const NodeMultiset& meb = d_data->d_mdb.getMonomialExponentMap(b);
194
195
46432
              std::vector<Node> exp;
196
              // take common factors of monomials, set minimum of
197
              // common exponents as processed
198
46432
              NodeMultiset a_exp_proc;
199
46432
              NodeMultiset b_exp_proc;
200
66616
              for (NodeMultiset::const_iterator itmea2 = mea.begin();
201
66616
                   itmea2 != mea.end();
202
                   ++itmea2)
203
              {
204
43400
                NodeMultiset::const_iterator itmeb2 = meb.find(itmea2->first);
205
43400
                if (itmeb2 != meb.end())
206
                {
207
11469
                  unsigned min_exp = itmea2->second > itmeb2->second
208
22028
                                         ? itmeb2->second
209
22028
                                         : itmea2->second;
210
11469
                  a_exp_proc[itmea2->first] = min_exp;
211
11469
                  b_exp_proc[itmea2->first] = min_exp;
212
22938
                  Trace("nl-ext-comp") << "Common exponent : " << itmea2->first
213
11469
                                       << " : " << min_exp << std::endl;
214
                }
215
              }
216
23216
              if (!a_exp_proc.empty())
217
              {
218
11145
                setMonomialFactor(a, b, a_exp_proc);
219
11145
                setMonomialFactor(b, a, b_exp_proc);
220
              }
221
              /*
222
              if( !a_exp_proc.empty() ){
223
                //reduction based on common exponents a > 0 => ( a * b
224
              <> a * c <=> b <> c ), a < 0 => ( a * b <> a * c <=> b
225
              !<> c )  ? }else{ compareMonomial( a, a, a_exp_proc, b,
226
              b, b_exp_proc, exp, lemmas );
227
              }
228
              */
229
23216
              compareMonomial(
230
                  a, a, a_exp_proc, b, b, b_exp_proc, exp, lemmas, cmp_infers);
231
            }
232
          }
233
        }
234
      }
235
    }
236
  }
237
  // remove redundant lemmas, e.g. if a > b, b > c, a > c were
238
  // inferred, discard lemma with conclusion a > c
239
6602
  Trace("nl-ext-comp") << "Compute redundancies for " << lemmas.size()
240
3301
                       << " lemmas." << std::endl;
241
  // naive
242
6602
  std::unordered_set<Node> r_lemmas;
243
1015
  for (std::map<int, std::map<Node, std::map<Node, Node> > >::iterator itb =
244
3301
           cmp_infers.begin();
245
4316
       itb != cmp_infers.end();
246
       ++itb)
247
  {
248
1749
    for (std::map<Node, std::map<Node, Node> >::iterator itc =
249
1015
             itb->second.begin();
250
2764
         itc != itb->second.end();
251
         ++itc)
252
    {
253
4174
      for (std::map<Node, Node>::iterator itc2 = itc->second.begin();
254
4174
           itc2 != itc->second.end();
255
           ++itc2)
256
      {
257
4850
        std::map<Node, bool> visited;
258
7253
        for (std::map<Node, Node>::iterator itc3 = itc->second.begin();
259
7253
             itc3 != itc->second.end();
260
             ++itc3)
261
        {
262
4969
          if (itc3->first != itc2->first)
263
          {
264
5051
            std::vector<Node> exp;
265
2596
            if (cmp_holds(itc3->first, itc2->first, itb->second, exp, visited))
266
            {
267
141
              r_lemmas.insert(itc2->second);
268
282
              Trace("nl-ext-comp")
269
141
                  << "...inference of " << itc->first << " > " << itc2->first
270
141
                  << " was redundant." << std::endl;
271
141
              break;
272
            }
273
          }
274
        }
275
      }
276
    }
277
  }
278
5726
  for (unsigned i = 0; i < lemmas.size(); i++)
279
  {
280
2425
    if (r_lemmas.find(lemmas[i].d_node) == r_lemmas.end())
281
    {
282
2284
      d_data->d_im.addPendingLemma(lemmas[i]);
283
    }
284
  }
285
  // could only take maximal lower/minimial lower bounds?
286
3301
}
287
288
// show a <> 0 by inequalities between variables in monomial a w.r.t 0
289
32863
int MonomialCheck::compareSign(
290
    Node oa, Node a, unsigned a_index, int status, std::vector<Node>& exp)
291
{
292
65726
  Trace("nl-ext-debug") << "Process " << a << " at index " << a_index
293
32863
                        << ", status is " << status << std::endl;
294
32863
  NodeManager* nm = NodeManager::currentNM();
295
65726
  Node mvaoa = d_data->d_model.computeAbstractModelValue(oa);
296
32863
  const std::vector<Node>& vla = d_data->d_mdb.getVariableList(a);
297
32863
  if (a_index == vla.size())
298
  {
299
10160
    if (mvaoa.getConst<Rational>().sgn() != status)
300
    {
301
      Node lemma =
302
1832
          nm->mkAnd(exp).impNode(mkLit(oa, d_data->d_zero, status * 2));
303
916
      CDProof* proof = nullptr;
304
916
      if (d_data->isProofEnabled())
305
      {
306
176
        proof = d_data->getProof();
307
352
        std::vector<Node> args = exp;
308
176
        args.emplace_back(oa);
309
176
        proof->addStep(lemma, PfRule::ARITH_MULT_SIGN, {}, args);
310
      }
311
916
      d_data->d_im.addPendingLemma(lemma, InferenceId::ARITH_NL_SIGN, proof);
312
    }
313
10160
    return status;
314
  }
315
22703
  Assert(a_index < vla.size());
316
45406
  Node av = vla[a_index];
317
22703
  unsigned aexp = d_data->d_mdb.getExponent(a, av);
318
  // take current sign in model
319
45406
  Node mvaav = d_data->d_model.computeAbstractModelValue(av);
320
22703
  int sgn = mvaav.getConst<Rational>().sgn();
321
45406
  Trace("nl-ext-debug") << "Process var " << av << "^" << aexp
322
22703
                        << ", model sign = " << sgn << std::endl;
323
22703
  if (sgn == 0)
324
  {
325
1920
    if (mvaoa.getConst<Rational>().sgn() != 0)
326
    {
327
1032
      Node prem = av.eqNode(d_data->d_zero);
328
1032
      Node conc = oa.eqNode(d_data->d_zero);
329
1032
      Node lemma = prem.impNode(conc);
330
516
      CDProof* proof = nullptr;
331
516
      if (d_data->isProofEnabled())
332
      {
333
80
        proof = d_data->getProof();
334
80
        proof->addStep(conc, PfRule::MACRO_SR_PRED_INTRO, {prem}, {conc});
335
80
        proof->addStep(lemma, PfRule::SCOPE, {conc}, {prem});
336
      }
337
516
      d_data->d_im.addPendingLemma(lemma, InferenceId::ARITH_NL_SIGN, proof);
338
    }
339
1920
    return 0;
340
  }
341
20783
  if (aexp % 2 == 0)
342
  {
343
2337
    exp.push_back(av.eqNode(d_data->d_zero).negate());
344
2337
    return compareSign(oa, a, a_index + 1, status, exp);
345
  }
346
18446
  exp.push_back(nm->mkNode(sgn == 1 ? Kind::GT : Kind::LT, av, d_data->d_zero));
347
18446
  return compareSign(oa, a, a_index + 1, status * sgn, exp);
348
}
349
350
40562
bool MonomialCheck::compareMonomial(
351
    Node oa,
352
    Node a,
353
    NodeMultiset& a_exp_proc,
354
    Node ob,
355
    Node b,
356
    NodeMultiset& b_exp_proc,
357
    std::vector<Node>& exp,
358
    std::vector<SimpleTheoryLemma>& lem,
359
    std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers)
360
{
361
81124
  Trace("nl-ext-comp-debug")
362
40562
      << "Check |" << a << "| >= |" << b << "|" << std::endl;
363
40562
  unsigned pexp_size = exp.size();
364
40562
  if (compareMonomial(
365
          oa, a, 0, a_exp_proc, ob, b, 0, b_exp_proc, 0, exp, lem, cmp_infers))
366
  {
367
28798
    return true;
368
  }
369
11764
  exp.resize(pexp_size);
370
23528
  Trace("nl-ext-comp-debug")
371
11764
      << "Check |" << b << "| >= |" << a << "|" << std::endl;
372
11764
  if (compareMonomial(
373
          ob, b, 0, b_exp_proc, oa, a, 0, a_exp_proc, 0, exp, lem, cmp_infers))
374
  {
375
6793
    return true;
376
  }
377
4971
  return false;
378
}
379
380
// trying to show a ( >, = ) b   by inequalities between variables in
381
// monomials a,b
382
205738
bool MonomialCheck::compareMonomial(
383
    Node oa,
384
    Node a,
385
    unsigned a_index,
386
    NodeMultiset& a_exp_proc,
387
    Node ob,
388
    Node b,
389
    unsigned b_index,
390
    NodeMultiset& b_exp_proc,
391
    int status,
392
    std::vector<Node>& exp,
393
    std::vector<SimpleTheoryLemma>& lem,
394
    std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers)
395
{
396
411476
  Trace("nl-ext-comp-debug")
397
205738
      << "compareMonomial " << oa << " and " << ob << ", indices = " << a_index
398
205738
      << " " << b_index << std::endl;
399
205738
  Assert(status == 0 || status == 2);
400
205738
  const std::vector<Node>& vla = d_data->d_mdb.getVariableList(a);
401
205738
  const std::vector<Node>& vlb = d_data->d_mdb.getVariableList(b);
402
205738
  if (a_index == vla.size() && b_index == vlb.size())
403
  {
404
    // finished, compare absolute value of abstract model values
405
35591
    int modelStatus = d_data->d_model.compare(oa, ob, false, true) * -2;
406
71182
    Trace("nl-ext-comp") << "...finished comparison with " << oa << " <"
407
35591
                         << status << "> " << ob
408
35591
                         << ", model status = " << modelStatus << std::endl;
409
35591
    if (status != modelStatus)
410
    {
411
4850
      Trace("nl-ext-comp-infer")
412
2425
          << "infer : " << oa << " <" << status << "> " << ob << std::endl;
413
2425
      if (status == 2)
414
      {
415
        // must state that all variables are non-zero
416
5443
        for (unsigned j = 0; j < vla.size(); j++)
417
        {
418
3484
          exp.push_back(vla[j].eqNode(d_data->d_zero).negate());
419
        }
420
      }
421
2425
      NodeManager* nm = NodeManager::currentNM();
422
      Node clem = nm->mkNode(
423
4850
          Kind::IMPLIES, nm->mkAnd(exp), mkLit(oa, ob, status, true));
424
2425
      Trace("nl-ext-comp-lemma") << "comparison lemma : " << clem << std::endl;
425
2425
      lem.emplace_back(
426
4850
          InferenceId::ARITH_NL_COMPARISON, clem, LemmaProperty::NONE, nullptr);
427
2425
      cmp_infers[status][oa][ob] = clem;
428
    }
429
35591
    return true;
430
  }
431
  // get a/b variable information
432
340294
  Node av;
433
170147
  unsigned aexp = 0;
434
170147
  unsigned avo = 0;
435
170147
  if (a_index < vla.size())
436
  {
437
145441
    av = vla[a_index];
438
145441
    unsigned aexpTotal = d_data->d_mdb.getExponent(a, av);
439
145441
    Assert(a_exp_proc[av] <= aexpTotal);
440
145441
    aexp = aexpTotal - a_exp_proc[av];
441
145441
    if (aexp == 0)
442
    {
443
100652
      return compareMonomial(oa,
444
                             a,
445
                             a_index + 1,
446
                             a_exp_proc,
447
                             ob,
448
                             b,
449
                             b_index,
450
                             b_exp_proc,
451
                             status,
452
                             exp,
453
                             lem,
454
50326
                             cmp_infers);
455
    }
456
95115
    Assert(d_order_vars.find(av) != d_order_vars.end());
457
95115
    avo = d_order_vars[av];
458
  }
459
239642
  Node bv;
460
119821
  unsigned bexp = 0;
461
119821
  unsigned bvo = 0;
462
119821
  if (b_index < vlb.size())
463
  {
464
95418
    bv = vlb[b_index];
465
95418
    unsigned bexpTotal = d_data->d_mdb.getExponent(b, bv);
466
95418
    Assert(b_exp_proc[bv] <= bexpTotal);
467
95418
    bexp = bexpTotal - b_exp_proc[bv];
468
95418
    if (bexp == 0)
469
    {
470
96966
      return compareMonomial(oa,
471
                             a,
472
                             a_index,
473
                             a_exp_proc,
474
                             ob,
475
                             b,
476
                             b_index + 1,
477
                             b_exp_proc,
478
                             status,
479
                             exp,
480
                             lem,
481
48483
                             cmp_infers);
482
    }
483
46935
    Assert(d_order_vars.find(bv) != d_order_vars.end());
484
46935
    bvo = d_order_vars[bv];
485
  }
486
  // get "one" information
487
71338
  Assert(d_order_vars.find(d_data->d_one) != d_order_vars.end());
488
71338
  unsigned ovo = d_order_vars[d_data->d_one];
489
142676
  Trace("nl-ext-comp-debug") << "....vars : " << av << "^" << aexp << " " << bv
490
71338
                             << "^" << bexp << std::endl;
491
492
  //--- cases
493
71338
  if (av.isNull())
494
  {
495
2994
    if (bvo <= ovo)
496
    {
497
2064
      Trace("nl-ext-comp-debug") << "...take leading " << bv << std::endl;
498
      // can multiply b by <=1
499
2064
      exp.push_back(mkLit(d_data->d_one, bv, bvo == ovo ? 0 : 2, true));
500
4128
      return compareMonomial(oa,
501
                             a,
502
                             a_index,
503
                             a_exp_proc,
504
                             ob,
505
                             b,
506
                             b_index + 1,
507
                             b_exp_proc,
508
                             bvo == ovo ? status : 2,
509
                             exp,
510
                             lem,
511
2064
                             cmp_infers);
512
    }
513
1860
    Trace("nl-ext-comp-debug")
514
930
        << "...failure, unmatched |b|>1 component." << std::endl;
515
930
    return false;
516
  }
517
68344
  else if (bv.isNull())
518
  {
519
24403
    if (avo >= ovo)
520
    {
521
22062
      Trace("nl-ext-comp-debug") << "...take leading " << av << std::endl;
522
      // can multiply a by >=1
523
22062
      exp.push_back(mkLit(av, d_data->d_one, avo == ovo ? 0 : 2, true));
524
44124
      return compareMonomial(oa,
525
                             a,
526
                             a_index + 1,
527
                             a_exp_proc,
528
                             ob,
529
                             b,
530
                             b_index,
531
                             b_exp_proc,
532
                             avo == ovo ? status : 2,
533
                             exp,
534
                             lem,
535
22062
                             cmp_infers);
536
    }
537
4682
    Trace("nl-ext-comp-debug")
538
2341
        << "...failure, unmatched |a|<1 component." << std::endl;
539
2341
    return false;
540
  }
541
43941
  Assert(!av.isNull() && !bv.isNull());
542
43941
  if (avo >= bvo)
543
  {
544
30383
    if (bvo < ovo && avo >= ovo)
545
    {
546
324
      Trace("nl-ext-comp-debug") << "...take leading " << av << std::endl;
547
      // do avo>=1 instead
548
324
      exp.push_back(mkLit(av, d_data->d_one, avo == ovo ? 0 : 2, true));
549
648
      return compareMonomial(oa,
550
                             a,
551
                             a_index + 1,
552
                             a_exp_proc,
553
                             ob,
554
                             b,
555
                             b_index,
556
                             b_exp_proc,
557
                             avo == ovo ? status : 2,
558
                             exp,
559
                             lem,
560
324
                             cmp_infers);
561
    }
562
30059
    unsigned min_exp = aexp > bexp ? bexp : aexp;
563
30059
    a_exp_proc[av] += min_exp;
564
30059
    b_exp_proc[bv] += min_exp;
565
60118
    Trace("nl-ext-comp-debug") << "...take leading " << min_exp << " from "
566
30059
                               << av << " and " << bv << std::endl;
567
30059
    exp.push_back(mkLit(av, bv, avo == bvo ? 0 : 2, true));
568
60118
    bool ret = compareMonomial(oa,
569
                               a,
570
                               a_index,
571
                               a_exp_proc,
572
                               ob,
573
                               b,
574
                               b_index,
575
                               b_exp_proc,
576
                               avo == bvo ? status : 2,
577
                               exp,
578
                               lem,
579
30059
                               cmp_infers);
580
30059
    a_exp_proc[av] -= min_exp;
581
30059
    b_exp_proc[bv] -= min_exp;
582
30059
    return ret;
583
  }
584
13558
  if (bvo <= ovo)
585
  {
586
94
    Trace("nl-ext-comp-debug") << "...take leading " << bv << std::endl;
587
    // try multiply b <= 1
588
94
    exp.push_back(mkLit(d_data->d_one, bv, bvo == ovo ? 0 : 2, true));
589
188
    return compareMonomial(oa,
590
                           a,
591
                           a_index,
592
                           a_exp_proc,
593
                           ob,
594
                           b,
595
                           b_index + 1,
596
                           b_exp_proc,
597
                           bvo == ovo ? status : 2,
598
                           exp,
599
                           lem,
600
94
                           cmp_infers);
601
  }
602
26928
  Trace("nl-ext-comp-debug")
603
13464
      << "...failure, leading |b|>|a|>1 component." << std::endl;
604
13464
  return false;
605
}
606
607
3540
bool MonomialCheck::cmp_holds(Node x,
608
                              Node y,
609
                              std::map<Node, std::map<Node, Node> >& cmp_infers,
610
                              std::vector<Node>& exp,
611
                              std::map<Node, bool>& visited)
612
{
613
3540
  if (x == y)
614
  {
615
141
    return true;
616
  }
617
3399
  else if (visited.find(x) != visited.end())
618
  {
619
722
    return false;
620
  }
621
2677
  visited[x] = true;
622
2677
  std::map<Node, std::map<Node, Node> >::iterator it = cmp_infers.find(x);
623
2677
  if (it != cmp_infers.end())
624
  {
625
1374
    for (std::map<Node, Node>::iterator itc = it->second.begin();
626
1374
         itc != it->second.end();
627
         ++itc)
628
    {
629
944
      exp.push_back(itc->second);
630
944
      if (cmp_holds(itc->first, y, cmp_infers, exp, visited))
631
      {
632
153
        return true;
633
      }
634
791
      exp.pop_back();
635
    }
636
  }
637
2524
  return false;
638
}
639
640
1526
void MonomialCheck::assignOrderIds(std::vector<Node>& vars,
641
                                   NodeMultiset& order,
642
                                   bool isConcrete,
643
                                   bool isAbsolute)
644
{
645
1526
  SortNlModel smv;
646
1526
  smv.d_nlm = &d_data->d_model;
647
1526
  smv.d_isConcrete = isConcrete;
648
1526
  smv.d_isAbsolute = isAbsolute;
649
1526
  smv.d_reverse_order = false;
650
1526
  std::sort(vars.begin(), vars.end(), smv);
651
652
1526
  order.clear();
653
  // assign ordering id's
654
1526
  unsigned counter = 0;
655
1526
  unsigned order_index = isConcrete ? 0 : 1;
656
3052
  Node prev;
657
8385
  for (unsigned j = 0; j < vars.size(); j++)
658
  {
659
13718
    Node x = vars[j];
660
13718
    Node v = d_data->d_model.computeModelValue(x, isConcrete);
661
6859
    if (!v.isConst())
662
    {
663
      Trace("nl-ext-mvo") << "..do not assign order to " << x << " : " << v
664
                          << std::endl;
665
      // don't assign for non-constant values (transcendental function apps)
666
      break;
667
    }
668
6859
    Trace("nl-ext-mvo") << "  order " << x << " : " << v << std::endl;
669
6859
    if (v != prev)
670
    {
671
      // builtin points
672
      bool success;
673
7643
      do
674
      {
675
7643
        success = false;
676
7643
        if (order_index < d_order_points.size())
677
        {
678
3533
          Node vv = d_data->d_model.computeModelValue(
679
7066
              d_order_points[order_index], isConcrete);
680
3533
          if (d_data->d_model.compareValue(v, vv, isAbsolute) <= 0)
681
          {
682
2688
            counter++;
683
5376
            Trace("nl-ext-mvo") << "O[" << d_order_points[order_index]
684
2688
                                << "] = " << counter << std::endl;
685
2688
            order[d_order_points[order_index]] = counter;
686
2688
            prev = vv;
687
2688
            order_index++;
688
2688
            success = true;
689
          }
690
        }
691
      } while (success);
692
    }
693
6859
    if (prev.isNull() || d_data->d_model.compareValue(v, prev, isAbsolute) != 0)
694
    {
695
3346
      counter++;
696
    }
697
6859
    Trace("nl-ext-mvo") << "O[" << x << "] = " << counter << std::endl;
698
6859
    order[x] = counter;
699
6859
    prev = v;
700
  }
701
2254
  while (order_index < d_order_points.size())
702
  {
703
364
    counter++;
704
728
    Trace("nl-ext-mvo") << "O[" << d_order_points[order_index]
705
364
                        << "] = " << counter << std::endl;
706
364
    order[d_order_points[order_index]] = counter;
707
364
    order_index++;
708
  }
709
1526
}
710
58346
Node MonomialCheck::mkLit(Node a, Node b, int status, bool isAbsolute) const
711
{
712
58346
  if (status == 0)
713
  {
714
11340
    Node a_eq_b = a.eqNode(b);
715
5670
    if (!isAbsolute)
716
    {
717
      return a_eq_b;
718
    }
719
11340
    Node negate_b = NodeManager::currentNM()->mkNode(Kind::UMINUS, b);
720
5670
    return a_eq_b.orNode(a.eqNode(negate_b));
721
  }
722
52676
  else if (status < 0)
723
  {
724
402
    return mkLit(b, a, -status);
725
  }
726
52274
  Assert(status == 1 || status == 2);
727
52274
  NodeManager* nm = NodeManager::currentNM();
728
52274
  Kind greater_op = status == 1 ? Kind::GEQ : Kind::GT;
729
52274
  if (!isAbsolute)
730
  {
731
916
    return nm->mkNode(greater_op, a, b);
732
  }
733
  // return nm->mkNode( greater_op, mkAbs( a ), mkAbs( b ) );
734
102716
  Node a_is_nonnegative = nm->mkNode(Kind::GEQ, a, d_data->d_zero);
735
102716
  Node b_is_nonnegative = nm->mkNode(Kind::GEQ, b, d_data->d_zero);
736
102716
  Node negate_a = nm->mkNode(Kind::UMINUS, a);
737
102716
  Node negate_b = nm->mkNode(Kind::UMINUS, b);
738
  return a_is_nonnegative.iteNode(
739
102716
      b_is_nonnegative.iteNode(nm->mkNode(greater_op, a, b),
740
102716
                               nm->mkNode(greater_op, a, negate_b)),
741
102716
      b_is_nonnegative.iteNode(nm->mkNode(greater_op, negate_a, b),
742
154074
                               nm->mkNode(greater_op, negate_a, negate_b)));
743
}
744
745
41758
void MonomialCheck::setMonomialFactor(Node a,
746
                                      Node b,
747
                                      const NodeMultiset& common)
748
{
749
  // Could not tell if this was being inserted intentionally or not.
750
41758
  std::map<Node, Node>& mono_diff_a = d_data->d_mono_diff[a];
751
41758
  if (mono_diff_a.find(b) == mono_diff_a.end())
752
  {
753
10980
    Trace("nl-ext-mono-factor")
754
5490
        << "Set monomial factor for " << a << "/" << b << std::endl;
755
5490
    mono_diff_a[b] = d_data->d_mdb.mkMonomialRemFactor(a, common);
756
  }
757
41758
}
758
759
}  // namespace nl
760
}  // namespace arith
761
}  // namespace theory
762
29358
}  // namespace cvc5