GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/nl/ext/monomial_check.cpp Lines: 359 370 97.0 %
Date: 2021-11-05 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
9700
MonomialCheck::MonomialCheck(ExtState* data) : d_data(data)
33
{
34
9700
  d_order_points.push_back(d_data->d_neg_one);
35
9700
  d_order_points.push_back(d_data->d_zero);
36
9700
  d_order_points.push_back(d_data->d_one);
37
9700
}
38
39
4188
void MonomialCheck::init(const std::vector<Node>& xts)
40
{
41
4188
  d_ms_proc.clear();
42
4188
  d_m_nconst_factor.clear();
43
44
35716
  for (unsigned i = 0, xsize = xts.size(); i < xsize; i++)
45
  {
46
63056
    Node a = xts[i];
47
31528
    if (a.getKind() == Kind::NONLINEAR_MULT)
48
    {
49
22930
      const std::vector<Node>& varList = d_data->d_mdb.getVariableList(a);
50
67286
      for (const Node& v : varList)
51
      {
52
88712
        Node mvk = d_data->d_model.computeAbstractModelValue(v);
53
44356
        if (!mvk.isConst())
54
        {
55
          d_m_nconst_factor[a] = true;
56
        }
57
      }
58
    }
59
  }
60
61
16752
  for (unsigned j = 0; j < d_order_points.size(); j++)
62
  {
63
25128
    Node c = d_order_points[j];
64
12564
    d_data->d_model.computeConcreteModelValue(c);
65
12564
    d_data->d_model.computeAbstractModelValue(c);
66
  }
67
4188
}
68
69
3340
void MonomialCheck::checkSign()
70
{
71
6680
  std::map<Node, int> signs;
72
3340
  Trace("nl-ext") << "Get monomial sign lemmas..." << std::endl;
73
21975
  for (unsigned j = 0; j < d_data->d_ms.size(); j++)
74
  {
75
37270
    Node a = d_data->d_ms[j];
76
18635
    if (d_ms_proc.find(a) == d_ms_proc.end())
77
    {
78
37270
      std::vector<Node> exp;
79
18635
      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
18635
      if (d_m_nconst_factor.find(a) == d_m_nconst_factor.end())
86
      {
87
18635
        signs[a] = compareSign(a, a, 0, 1, exp);
88
18635
        if (signs[a] == 0)
89
        {
90
3804
          d_ms_proc[a] = true;
91
7608
          Trace("nl-ext-debug")
92
3804
              << "...mark " << a << " reduced since its value is 0."
93
3804
              << 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
3340
}
105
106
4540
void MonomialCheck::checkMagnitude(unsigned c)
107
{
108
  // ensure information is setup
109
4540
  if (c == 0)
110
  {
111
    // sort by absolute values of abstract model values
112
2093
    assignOrderIds(d_data->d_ms_vars, d_order_vars, false, true);
113
114
    // sort individual variable lists
115
2093
    Trace("nl-ext-proc") << "Assign order var lists..." << std::endl;
116
2093
    d_data->d_mdb.sortVariablesByModel(d_data->d_ms, d_data->d_model);
117
  }
118
119
4540
  unsigned r = 1;
120
9080
  std::vector<SimpleTheoryLemma> lemmas;
121
  // if (x,y,L) in cmp_infers, then x > y inferred as conclusion of L
122
  // in lemmas
123
9080
  std::map<int, std::map<Node, std::map<Node, Node> > > cmp_infers;
124
9080
  Trace("nl-ext") << "Get monomial comparison lemmas (order=" << r
125
4540
                  << ", compare=" << c << ")..." << std::endl;
126
30866
  for (unsigned j = 0; j < d_data->d_ms.size(); j++)
127
  {
128
52652
    Node a = d_data->d_ms[j];
129
52652
    if (d_ms_proc.find(a) == d_ms_proc.end()
130
26326
        && d_m_nconst_factor.find(a) == d_m_nconst_factor.end())
131
    {
132
23210
      if (c == 0)
133
      {
134
        // compare magnitude against 1
135
20960
        std::vector<Node> exp;
136
20960
        NodeMultiset a_exp_proc;
137
20960
        NodeMultiset b_exp_proc;
138
20960
        compareMonomial(a,
139
                        a,
140
                        a_exp_proc,
141
10480
                        d_data->d_one,
142
10480
                        d_data->d_one,
143
                        b_exp_proc,
144
                        exp,
145
                        lemmas,
146
                        cmp_infers);
147
      }
148
      else
149
      {
150
12730
        const NodeMultiset& mea = d_data->d_mdb.getMonomialExponentMap(a);
151
12730
        if (c == 1)
152
        {
153
          // could compare not just against containing variables?
154
          // compare magnitude against variables
155
82131
          for (unsigned k = 0; k < d_data->d_ms_vars.size(); k++)
156
          {
157
149078
            Node v = d_data->d_ms_vars[k];
158
149078
            Node mvcv = d_data->d_model.computeConcreteModelValue(v);
159
74539
            if (mvcv.isConst())
160
            {
161
148466
              std::vector<Node> exp;
162
148466
              NodeMultiset a_exp_proc;
163
148466
              NodeMultiset b_exp_proc;
164
74233
              if (mea.find(v) != mea.end())
165
              {
166
13748
                a_exp_proc[v] = 1;
167
13748
                b_exp_proc[v] = 1;
168
13748
                setMonomialFactor(a, v, a_exp_proc);
169
13748
                setMonomialFactor(v, a, b_exp_proc);
170
13748
                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
41825
          for (unsigned k = (j + 1); k < d_data->d_ms.size(); k++)
187
          {
188
73374
            Node b = d_data->d_ms[k];
189
            //(signs[a]==signs[b])==(r==0)
190
73374
            if (d_ms_proc.find(b) == d_ms_proc.end()
191
36687
                && d_m_nconst_factor.find(b) == d_m_nconst_factor.end())
192
            {
193
33949
              const NodeMultiset& meb = d_data->d_mdb.getMonomialExponentMap(b);
194
195
67898
              std::vector<Node> exp;
196
              // take common factors of monomials, set minimum of
197
              // common exponents as processed
198
67898
              NodeMultiset a_exp_proc;
199
67898
              NodeMultiset b_exp_proc;
200
98198
              for (NodeMultiset::const_iterator itmea2 = mea.begin();
201
98198
                   itmea2 != mea.end();
202
                   ++itmea2)
203
              {
204
64249
                NodeMultiset::const_iterator itmeb2 = meb.find(itmea2->first);
205
64249
                if (itmeb2 != meb.end())
206
                {
207
15950
                  unsigned min_exp = itmea2->second > itmeb2->second
208
30975
                                         ? itmeb2->second
209
30975
                                         : itmea2->second;
210
15950
                  a_exp_proc[itmea2->first] = min_exp;
211
15950
                  b_exp_proc[itmea2->first] = min_exp;
212
31900
                  Trace("nl-ext-comp") << "Common exponent : " << itmea2->first
213
15950
                                       << " : " << min_exp << std::endl;
214
                }
215
              }
216
33949
              if (!a_exp_proc.empty())
217
              {
218
15822
                setMonomialFactor(a, b, a_exp_proc);
219
15822
                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
33949
              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
9080
  Trace("nl-ext-comp") << "Compute redundancies for " << lemmas.size()
240
4540
                       << " lemmas." << std::endl;
241
  // naive
242
9080
  std::unordered_set<Node> r_lemmas;
243
1348
  for (std::map<int, std::map<Node, std::map<Node, Node> > >::iterator itb =
244
4540
           cmp_infers.begin();
245
5888
       itb != cmp_infers.end();
246
       ++itb)
247
  {
248
2376
    for (std::map<Node, std::map<Node, Node> >::iterator itc =
249
1348
             itb->second.begin();
250
3724
         itc != itb->second.end();
251
         ++itc)
252
    {
253
5521
      for (std::map<Node, Node>::iterator itc2 = itc->second.begin();
254
5521
           itc2 != itc->second.end();
255
           ++itc2)
256
      {
257
6290
        std::map<Node, bool> visited;
258
8931
        for (std::map<Node, Node>::iterator itc3 = itc->second.begin();
259
8931
             itc3 != itc->second.end();
260
             ++itc3)
261
        {
262
5930
          if (itc3->first != itc2->first)
263
          {
264
5562
            std::vector<Node> exp;
265
2853
            if (cmp_holds(itc3->first, itc2->first, itb->second, exp, visited))
266
            {
267
144
              r_lemmas.insert(itc2->second);
268
288
              Trace("nl-ext-comp")
269
144
                  << "...inference of " << itc->first << " > " << itc2->first
270
144
                  << " was redundant." << std::endl;
271
144
              break;
272
            }
273
          }
274
        }
275
      }
276
    }
277
  }
278
7685
  for (unsigned i = 0; i < lemmas.size(); i++)
279
  {
280
3145
    if (r_lemmas.find(lemmas[i].d_node) == r_lemmas.end())
281
    {
282
3001
      d_data->d_im.addPendingLemma(lemmas[i]);
283
    }
284
  }
285
  // could only take maximal lower/minimial lower bounds?
286
4540
}
287
288
// show a <> 0 by inequalities between variables in monomial a w.r.t 0
289
49283
int MonomialCheck::compareSign(
290
    Node oa, Node a, unsigned a_index, int status, std::vector<Node>& exp)
291
{
292
98566
  Trace("nl-ext-debug") << "Process " << a << " at index " << a_index
293
49283
                        << ", status is " << status << std::endl;
294
49283
  NodeManager* nm = NodeManager::currentNM();
295
98566
  Node mvaoa = d_data->d_model.computeAbstractModelValue(oa);
296
49283
  const std::vector<Node>& vla = d_data->d_mdb.getVariableList(a);
297
49283
  if (a_index == vla.size())
298
  {
299
14831
    if (mvaoa.getConst<Rational>().sgn() != status)
300
    {
301
      Node lemma =
302
2642
          nm->mkAnd(exp).impNode(mkLit(oa, d_data->d_zero, status * 2));
303
1321
      CDProof* proof = nullptr;
304
1321
      if (d_data->isProofEnabled())
305
      {
306
246
        proof = d_data->getProof();
307
492
        std::vector<Node> args = exp;
308
246
        args.emplace_back(oa);
309
246
        proof->addStep(lemma, PfRule::ARITH_MULT_SIGN, {}, args);
310
      }
311
1321
      d_data->d_im.addPendingLemma(lemma, InferenceId::ARITH_NL_SIGN, proof);
312
    }
313
14831
    return status;
314
  }
315
34452
  Assert(a_index < vla.size());
316
68904
  Node av = vla[a_index];
317
34452
  unsigned aexp = d_data->d_mdb.getExponent(a, av);
318
  // take current sign in model
319
68904
  Node mvaav = d_data->d_model.computeAbstractModelValue(av);
320
34452
  int sgn = mvaav.getConst<Rational>().sgn();
321
68904
  Trace("nl-ext-debug") << "Process var " << av << "^" << aexp
322
34452
                        << ", model sign = " << sgn << std::endl;
323
34452
  if (sgn == 0)
324
  {
325
3804
    if (mvaoa.getConst<Rational>().sgn() != 0)
326
    {
327
1836
      Node prem = av.eqNode(d_data->d_zero);
328
1836
      Node conc = oa.eqNode(d_data->d_zero);
329
1836
      Node lemma = prem.impNode(conc);
330
918
      CDProof* proof = nullptr;
331
918
      if (d_data->isProofEnabled())
332
      {
333
131
        proof = d_data->getProof();
334
131
        proof->addStep(conc, PfRule::MACRO_SR_PRED_INTRO, {prem}, {conc});
335
131
        proof->addStep(lemma, PfRule::SCOPE, {conc}, {prem});
336
      }
337
918
      d_data->d_im.addPendingLemma(lemma, InferenceId::ARITH_NL_SIGN, proof);
338
    }
339
3804
    return 0;
340
  }
341
30648
  if (aexp % 2 == 0)
342
  {
343
2763
    exp.push_back(av.eqNode(d_data->d_zero).negate());
344
2763
    return compareSign(oa, a, a_index + 1, status, exp);
345
  }
346
27885
  exp.push_back(nm->mkNode(sgn == 1 ? Kind::GT : Kind::LT, av, d_data->d_zero));
347
27885
  return compareSign(oa, a, a_index + 1, status * sgn, exp);
348
}
349
350
58177
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
116354
  Trace("nl-ext-comp-debug")
362
58177
      << "Check |" << a << "| >= |" << b << "|" << std::endl;
363
58177
  unsigned pexp_size = exp.size();
364
58177
  if (compareMonomial(
365
          oa, a, 0, a_exp_proc, ob, b, 0, b_exp_proc, 0, exp, lem, cmp_infers))
366
  {
367
41909
    return true;
368
  }
369
16268
  exp.resize(pexp_size);
370
32536
  Trace("nl-ext-comp-debug")
371
16268
      << "Check |" << b << "| >= |" << a << "|" << std::endl;
372
16268
  if (compareMonomial(
373
          ob, b, 0, b_exp_proc, oa, a, 0, a_exp_proc, 0, exp, lem, cmp_infers))
374
  {
375
10394
    return true;
376
  }
377
5874
  return false;
378
}
379
380
// trying to show a ( >, = ) b   by inequalities between variables in
381
// monomials a,b
382
301441
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
602882
  Trace("nl-ext-comp-debug")
397
301441
      << "compareMonomial " << oa << " and " << ob << ", indices = " << a_index
398
301441
      << " " << b_index << std::endl;
399
301441
  Assert(status == 0 || status == 2);
400
301441
  const std::vector<Node>& vla = d_data->d_mdb.getVariableList(a);
401
301441
  const std::vector<Node>& vlb = d_data->d_mdb.getVariableList(b);
402
301441
  if (a_index == vla.size() && b_index == vlb.size())
403
  {
404
    // finished, compare absolute value of abstract model values
405
52303
    int modelStatus = d_data->d_model.compare(oa, ob, false, true) * 2;
406
104606
    Trace("nl-ext-comp") << "...finished comparison with " << oa << " <"
407
52303
                         << status << "> " << ob
408
52303
                         << ", model status = " << modelStatus << std::endl;
409
52303
    if (status != modelStatus)
410
    {
411
6290
      Trace("nl-ext-comp-infer")
412
3145
          << "infer : " << oa << " <" << status << "> " << ob << std::endl;
413
3145
      if (status == 2)
414
      {
415
        // must state that all variables are non-zero
416
6507
        for (unsigned j = 0; j < vla.size(); j++)
417
        {
418
4199
          exp.push_back(vla[j].eqNode(d_data->d_zero).negate());
419
        }
420
      }
421
3145
      NodeManager* nm = NodeManager::currentNM();
422
      Node clem = nm->mkNode(
423
6290
          Kind::IMPLIES, nm->mkAnd(exp), mkLit(oa, ob, status, true));
424
3145
      Trace("nl-ext-comp-lemma") << "comparison lemma : " << clem << std::endl;
425
3145
      lem.emplace_back(
426
6290
          InferenceId::ARITH_NL_COMPARISON, clem, LemmaProperty::NONE, nullptr);
427
3145
      cmp_infers[status][oa][ob] = clem;
428
    }
429
52303
    return true;
430
  }
431
  // get a/b variable information
432
498276
  Node av;
433
249138
  unsigned aexp = 0;
434
249138
  unsigned avo = 0;
435
249138
  if (a_index < vla.size())
436
  {
437
215062
    av = vla[a_index];
438
215062
    unsigned aexpTotal = d_data->d_mdb.getExponent(a, av);
439
215062
    Assert(a_exp_proc[av] <= aexpTotal);
440
215062
    aexp = aexpTotal - a_exp_proc[av];
441
215062
    if (aexp == 0)
442
    {
443
150694
      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
75347
                             cmp_infers);
455
    }
456
139715
    Assert(d_order_vars.find(av) != d_order_vars.end());
457
139715
    avo = d_order_vars[av];
458
  }
459
347582
  Node bv;
460
173791
  unsigned bexp = 0;
461
173791
  unsigned bvo = 0;
462
173791
  if (b_index < vlb.size())
463
  {
464
140627
    bv = vlb[b_index];
465
140627
    unsigned bexpTotal = d_data->d_mdb.getExponent(b, bv);
466
140627
    Assert(b_exp_proc[bv] <= bexpTotal);
467
140627
    bexp = bexpTotal - b_exp_proc[bv];
468
140627
    if (bexp == 0)
469
    {
470
144920
      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
72460
                             cmp_infers);
482
    }
483
68167
    Assert(d_order_vars.find(bv) != d_order_vars.end());
484
68167
    bvo = d_order_vars[bv];
485
  }
486
  // get "one" information
487
101331
  Assert(d_order_vars.find(d_data->d_one) != d_order_vars.end());
488
101331
  unsigned ovo = d_order_vars[d_data->d_one];
489
202662
  Trace("nl-ext-comp-debug") << "....vars : " << av << "^" << aexp << " " << bv
490
101331
                             << "^" << bexp << std::endl;
491
492
  //--- cases
493
101331
  if (av.isNull())
494
  {
495
2215
    if (bvo <= ovo)
496
    {
497
1828
      Trace("nl-ext-comp-debug") << "...take leading " << bv << std::endl;
498
      // can multiply b by <=1
499
1828
      exp.push_back(mkLit(d_data->d_one, bv, bvo == ovo ? 0 : 2, true));
500
3656
      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
1828
                             cmp_infers);
512
    }
513
774
    Trace("nl-ext-comp-debug")
514
387
        << "...failure, unmatched |b|>1 component." << std::endl;
515
387
    return false;
516
  }
517
99116
  else if (bv.isNull())
518
  {
519
33164
    if (avo >= ovo)
520
    {
521
31608
      Trace("nl-ext-comp-debug") << "...take leading " << av << std::endl;
522
      // can multiply a by >=1
523
31608
      exp.push_back(mkLit(av, d_data->d_one, avo == ovo ? 0 : 2, true));
524
63216
      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
31608
                             cmp_infers);
536
    }
537
3112
    Trace("nl-ext-comp-debug")
538
1556
        << "...failure, unmatched |a|<1 component." << std::endl;
539
1556
    return false;
540
  }
541
65952
  Assert(!av.isNull() && !bv.isNull());
542
65952
  if (avo >= bvo)
543
  {
544
45693
    if (bvo < ovo && avo >= ovo)
545
    {
546
96
      Trace("nl-ext-comp-debug") << "...take leading " << av << std::endl;
547
      // do avo>=1 instead
548
96
      exp.push_back(mkLit(av, d_data->d_one, avo == ovo ? 0 : 2, true));
549
192
      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
96
                             cmp_infers);
561
    }
562
45597
    unsigned min_exp = aexp > bexp ? bexp : aexp;
563
45597
    a_exp_proc[av] += min_exp;
564
45597
    b_exp_proc[bv] += min_exp;
565
91194
    Trace("nl-ext-comp-debug") << "...take leading " << min_exp << " from "
566
45597
                               << av << " and " << bv << std::endl;
567
45597
    exp.push_back(mkLit(av, bv, avo == bvo ? 0 : 2, true));
568
91194
    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
45597
                               cmp_infers);
580
45597
    a_exp_proc[av] -= min_exp;
581
45597
    b_exp_proc[bv] -= min_exp;
582
45597
    return ret;
583
  }
584
20259
  if (bvo <= ovo)
585
  {
586
60
    Trace("nl-ext-comp-debug") << "...take leading " << bv << std::endl;
587
    // try multiply b <= 1
588
60
    exp.push_back(mkLit(d_data->d_one, bv, bvo == ovo ? 0 : 2, true));
589
120
    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
60
                           cmp_infers);
601
  }
602
40398
  Trace("nl-ext-comp-debug")
603
20199
      << "...failure, leading |b|>|a|>1 component." << std::endl;
604
20199
  return false;
605
}
606
607
3651
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
3651
  if (x == y)
614
  {
615
144
    return true;
616
  }
617
3507
  else if (visited.find(x) != visited.end())
618
  {
619
579
    return false;
620
  }
621
2928
  visited[x] = true;
622
2928
  std::map<Node, std::map<Node, Node> >::iterator it = cmp_infers.find(x);
623
2928
  if (it != cmp_infers.end())
624
  {
625
1203
    for (std::map<Node, Node>::iterator itc = it->second.begin();
626
1203
         itc != it->second.end();
627
         ++itc)
628
    {
629
798
      exp.push_back(itc->second);
630
798
      if (cmp_holds(itc->first, y, cmp_infers, exp, visited))
631
      {
632
156
        return true;
633
      }
634
642
      exp.pop_back();
635
    }
636
  }
637
2772
  return false;
638
}
639
640
2093
void MonomialCheck::assignOrderIds(std::vector<Node>& vars,
641
                                   NodeMultiset& order,
642
                                   bool isConcrete,
643
                                   bool isAbsolute)
644
{
645
2093
  SortNlModel smv;
646
2093
  smv.d_nlm = &d_data->d_model;
647
2093
  smv.d_isConcrete = isConcrete;
648
2093
  smv.d_isAbsolute = isAbsolute;
649
2093
  smv.d_reverse_order = false;
650
2093
  std::sort(vars.begin(), vars.end(), smv);
651
652
2093
  order.clear();
653
  // assign ordering id's
654
2093
  unsigned counter = 0;
655
2093
  unsigned order_index = isConcrete ? 0 : 1;
656
4186
  Node prev;
657
12992
  for (unsigned j = 0; j < vars.size(); j++)
658
  {
659
21798
    Node x = vars[j];
660
21798
    Node v = d_data->d_model.computeModelValue(x, isConcrete);
661
10899
    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
10899
    Trace("nl-ext-mvo") << "  order " << x << " : " << v << std::endl;
669
10899
    if (v != prev)
670
    {
671
      // builtin points
672
      bool success;
673
10510
      do
674
      {
675
10510
        success = false;
676
10510
        if (order_index < d_order_points.size())
677
        {
678
4572
          Node vv = d_data->d_model.computeModelValue(
679
9144
              d_order_points[order_index], isConcrete);
680
4572
          if (d_data->d_model.compareValue(v, vv, isAbsolute) >= 0)
681
          {
682
3523
            counter++;
683
7046
            Trace("nl-ext-mvo") << "O[" << d_order_points[order_index]
684
3523
                                << "] = " << counter << std::endl;
685
3523
            order[d_order_points[order_index]] = counter;
686
3523
            prev = vv;
687
3523
            order_index++;
688
3523
            success = true;
689
          }
690
        }
691
      } while (success);
692
    }
693
10899
    if (prev.isNull() || d_data->d_model.compareValue(v, prev, isAbsolute) != 0)
694
    {
695
4461
      counter++;
696
    }
697
10899
    Trace("nl-ext-mvo") << "O[" << x << "] = " << counter << std::endl;
698
10899
    order[x] = counter;
699
10899
    prev = v;
700
  }
701
3419
  while (order_index < d_order_points.size())
702
  {
703
663
    counter++;
704
1326
    Trace("nl-ext-mvo") << "O[" << d_order_points[order_index]
705
663
                        << "] = " << counter << std::endl;
706
663
    order[d_order_points[order_index]] = counter;
707
663
    order_index++;
708
  }
709
2093
}
710
84212
Node MonomialCheck::mkLit(Node a, Node b, int status, bool isAbsolute) const
711
{
712
84212
  if (status == 0)
713
  {
714
22104
    Node a_eq_b = a.eqNode(b);
715
11052
    if (!isAbsolute)
716
    {
717
      return a_eq_b;
718
    }
719
22104
    Node negate_b = NodeManager::currentNM()->mkNode(Kind::UMINUS, b);
720
11052
    return a_eq_b.orNode(a.eqNode(negate_b));
721
  }
722
73160
  else if (status < 0)
723
  {
724
557
    return mkLit(b, a, -status);
725
  }
726
72603
  Assert(status == 1 || status == 2);
727
72603
  NodeManager* nm = NodeManager::currentNM();
728
72603
  Kind greater_op = status == 1 ? Kind::GEQ : Kind::GT;
729
72603
  if (!isAbsolute)
730
  {
731
1321
    return nm->mkNode(greater_op, a, b);
732
  }
733
  // return nm->mkNode( greater_op, mkAbs( a ), mkAbs( b ) );
734
142564
  Node a_is_nonnegative = nm->mkNode(Kind::GEQ, a, d_data->d_zero);
735
142564
  Node b_is_nonnegative = nm->mkNode(Kind::GEQ, b, d_data->d_zero);
736
142564
  Node negate_a = nm->mkNode(Kind::UMINUS, a);
737
142564
  Node negate_b = nm->mkNode(Kind::UMINUS, b);
738
  return a_is_nonnegative.iteNode(
739
142564
      b_is_nonnegative.iteNode(nm->mkNode(greater_op, a, b),
740
142564
                               nm->mkNode(greater_op, a, negate_b)),
741
142564
      b_is_nonnegative.iteNode(nm->mkNode(greater_op, negate_a, b),
742
213846
                               nm->mkNode(greater_op, negate_a, negate_b)));
743
}
744
745
59140
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
59140
  std::map<Node, Node>& mono_diff_a = d_data->d_mono_diff[a];
751
59140
  if (mono_diff_a.find(b) == mono_diff_a.end())
752
  {
753
13348
    Trace("nl-ext-mono-factor")
754
6674
        << "Set monomial factor for " << a << "/" << b << std::endl;
755
6674
    mono_diff_a[b] = d_data->d_mdb.mkMonomialRemFactor(a, common);
756
  }
757
59140
}
758
759
}  // namespace nl
760
}  // namespace arith
761
}  // namespace theory
762
31125
}  // namespace cvc5