GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/nl/ext/monomial_check.cpp Lines: 359 370 97.0 %
Date: 2021-09-16 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
5203
MonomialCheck::MonomialCheck(ExtState* data) : d_data(data)
33
{
34
5203
  d_order_points.push_back(d_data->d_neg_one);
35
5203
  d_order_points.push_back(d_data->d_zero);
36
5203
  d_order_points.push_back(d_data->d_one);
37
5203
}
38
39
3990
void MonomialCheck::init(const std::vector<Node>& xts)
40
{
41
3990
  d_ms_proc.clear();
42
3990
  d_m_nconst_factor.clear();
43
44
35044
  for (unsigned i = 0, xsize = xts.size(); i < xsize; i++)
45
  {
46
62108
    Node a = xts[i];
47
31054
    if (a.getKind() == Kind::NONLINEAR_MULT)
48
    {
49
22456
      const std::vector<Node>& varList = d_data->d_mdb.getVariableList(a);
50
65927
      for (const Node& v : varList)
51
      {
52
86942
        Node mvk = d_data->d_model.computeAbstractModelValue(v);
53
43471
        if (!mvk.isConst())
54
        {
55
          d_m_nconst_factor[a] = true;
56
        }
57
      }
58
    }
59
  }
60
61
15960
  for (unsigned j = 0; j < d_order_points.size(); j++)
62
  {
63
23940
    Node c = d_order_points[j];
64
11970
    d_data->d_model.computeConcreteModelValue(c);
65
11970
    d_data->d_model.computeAbstractModelValue(c);
66
  }
67
3990
}
68
69
3161
void MonomialCheck::checkSign()
70
{
71
6322
  std::map<Node, int> signs;
72
3161
  Trace("nl-ext") << "Get monomial sign lemmas..." << std::endl;
73
21590
  for (unsigned j = 0; j < d_data->d_ms.size(); j++)
74
  {
75
36858
    Node a = d_data->d_ms[j];
76
18429
    if (d_ms_proc.find(a) == d_ms_proc.end())
77
    {
78
36858
      std::vector<Node> exp;
79
18429
      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
18429
      if (d_m_nconst_factor.find(a) == d_m_nconst_factor.end())
86
      {
87
18429
        signs[a] = compareSign(a, a, 0, 1, exp);
88
18429
        if (signs[a] == 0)
89
        {
90
3689
          d_ms_proc[a] = true;
91
7378
          Trace("nl-ext-debug")
92
3689
              << "...mark " << a << " reduced since its value is 0."
93
3689
              << 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
3161
}
105
106
4434
void MonomialCheck::checkMagnitude(unsigned c)
107
{
108
  // ensure information is setup
109
4434
  if (c == 0)
110
  {
111
    // sort by absolute values of abstract model values
112
2005
    assignOrderIds(d_data->d_ms_vars, d_order_vars, false, true);
113
114
    // sort individual variable lists
115
2005
    Trace("nl-ext-proc") << "Assign order var lists..." << std::endl;
116
2005
    d_data->d_mdb.sortVariablesByModel(d_data->d_ms, d_data->d_model);
117
  }
118
119
4434
  unsigned r = 1;
120
8868
  std::vector<SimpleTheoryLemma> lemmas;
121
  // if (x,y,L) in cmp_infers, then x > y inferred as conclusion of L
122
  // in lemmas
123
8868
  std::map<int, std::map<Node, std::map<Node, Node> > > cmp_infers;
124
8868
  Trace("nl-ext") << "Get monomial comparison lemmas (order=" << r
125
4434
                  << ", compare=" << c << ")..." << std::endl;
126
31256
  for (unsigned j = 0; j < d_data->d_ms.size(); j++)
127
  {
128
53644
    Node a = d_data->d_ms[j];
129
53644
    if (d_ms_proc.find(a) == d_ms_proc.end()
130
26822
        && d_m_nconst_factor.find(a) == d_m_nconst_factor.end())
131
    {
132
23654
      if (c == 0)
133
      {
134
        // compare magnitude against 1
135
21006
        std::vector<Node> exp;
136
21006
        NodeMultiset a_exp_proc;
137
21006
        NodeMultiset b_exp_proc;
138
21006
        compareMonomial(a,
139
                        a,
140
                        a_exp_proc,
141
10503
                        d_data->d_one,
142
10503
                        d_data->d_one,
143
                        b_exp_proc,
144
                        exp,
145
                        lemmas,
146
                        cmp_infers);
147
      }
148
      else
149
      {
150
13151
        const NodeMultiset& mea = d_data->d_mdb.getMonomialExponentMap(a);
151
13151
        if (c == 1)
152
        {
153
          // could compare not just against containing variables?
154
          // compare magnitude against variables
155
79621
          for (unsigned k = 0; k < d_data->d_ms_vars.size(); k++)
156
          {
157
143492
            Node v = d_data->d_ms_vars[k];
158
143492
            Node mvcv = d_data->d_model.computeConcreteModelValue(v);
159
71746
            if (mvcv.isConst())
160
            {
161
142880
              std::vector<Node> exp;
162
142880
              NodeMultiset a_exp_proc;
163
142880
              NodeMultiset b_exp_proc;
164
71440
              if (mea.find(v) != mea.end())
165
              {
166
14315
                a_exp_proc[v] = 1;
167
14315
                b_exp_proc[v] = 1;
168
14315
                setMonomialFactor(a, v, a_exp_proc);
169
14315
                setMonomialFactor(v, a, b_exp_proc);
170
14315
                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
43034
          for (unsigned k = (j + 1); k < d_data->d_ms.size(); k++)
187
          {
188
75516
            Node b = d_data->d_ms[k];
189
            //(signs[a]==signs[b])==(r==0)
190
75516
            if (d_ms_proc.find(b) == d_ms_proc.end()
191
37758
                && d_m_nconst_factor.find(b) == d_m_nconst_factor.end())
192
            {
193
34795
              const NodeMultiset& meb = d_data->d_mdb.getMonomialExponentMap(b);
194
195
69590
              std::vector<Node> exp;
196
              // take common factors of monomials, set minimum of
197
              // common exponents as processed
198
69590
              NodeMultiset a_exp_proc;
199
69590
              NodeMultiset b_exp_proc;
200
100759
              for (NodeMultiset::const_iterator itmea2 = mea.begin();
201
100759
                   itmea2 != mea.end();
202
                   ++itmea2)
203
              {
204
65964
                NodeMultiset::const_iterator itmeb2 = meb.find(itmea2->first);
205
65964
                if (itmeb2 != meb.end())
206
                {
207
17072
                  unsigned min_exp = itmea2->second > itmeb2->second
208
32973
                                         ? itmeb2->second
209
32973
                                         : itmea2->second;
210
17072
                  a_exp_proc[itmea2->first] = min_exp;
211
17072
                  b_exp_proc[itmea2->first] = min_exp;
212
34144
                  Trace("nl-ext-comp") << "Common exponent : " << itmea2->first
213
17072
                                       << " : " << min_exp << std::endl;
214
                }
215
              }
216
34795
              if (!a_exp_proc.empty())
217
              {
218
16792
                setMonomialFactor(a, b, a_exp_proc);
219
16792
                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
34795
              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
8868
  Trace("nl-ext-comp") << "Compute redundancies for " << lemmas.size()
240
4434
                       << " lemmas." << std::endl;
241
  // naive
242
8868
  std::unordered_set<Node> r_lemmas;
243
1326
  for (std::map<int, std::map<Node, std::map<Node, Node> > >::iterator itb =
244
4434
           cmp_infers.begin();
245
5760
       itb != cmp_infers.end();
246
       ++itb)
247
  {
248
2396
    for (std::map<Node, std::map<Node, Node> >::iterator itc =
249
1326
             itb->second.begin();
250
3722
         itc != itb->second.end();
251
         ++itc)
252
    {
253
5668
      for (std::map<Node, Node>::iterator itc2 = itc->second.begin();
254
5668
           itc2 != itc->second.end();
255
           ++itc2)
256
      {
257
6544
        std::map<Node, bool> visited;
258
9558
        for (std::map<Node, Node>::iterator itc3 = itc->second.begin();
259
9558
             itc3 != itc->second.end();
260
             ++itc3)
261
        {
262
6454
          if (itc3->first != itc2->first)
263
          {
264
6350
            std::vector<Node> exp;
265
3259
            if (cmp_holds(itc3->first, itc2->first, itb->second, exp, visited))
266
            {
267
168
              r_lemmas.insert(itc2->second);
268
336
              Trace("nl-ext-comp")
269
168
                  << "...inference of " << itc->first << " > " << itc2->first
270
168
                  << " was redundant." << std::endl;
271
168
              break;
272
            }
273
          }
274
        }
275
      }
276
    }
277
  }
278
7706
  for (unsigned i = 0; i < lemmas.size(); i++)
279
  {
280
3272
    if (r_lemmas.find(lemmas[i].d_node) == r_lemmas.end())
281
    {
282
3104
      d_data->d_im.addPendingLemma(lemmas[i]);
283
    }
284
  }
285
  // could only take maximal lower/minimial lower bounds?
286
4434
}
287
288
// show a <> 0 by inequalities between variables in monomial a w.r.t 0
289
48916
int MonomialCheck::compareSign(
290
    Node oa, Node a, unsigned a_index, int status, std::vector<Node>& exp)
291
{
292
97832
  Trace("nl-ext-debug") << "Process " << a << " at index " << a_index
293
48916
                        << ", status is " << status << std::endl;
294
48916
  NodeManager* nm = NodeManager::currentNM();
295
97832
  Node mvaoa = d_data->d_model.computeAbstractModelValue(oa);
296
48916
  const std::vector<Node>& vla = d_data->d_mdb.getVariableList(a);
297
48916
  if (a_index == vla.size())
298
  {
299
14740
    if (mvaoa.getConst<Rational>().sgn() != status)
300
    {
301
      Node lemma =
302
2576
          nm->mkAnd(exp).impNode(mkLit(oa, d_data->d_zero, status * 2));
303
1288
      CDProof* proof = nullptr;
304
1288
      if (d_data->isProofEnabled())
305
      {
306
231
        proof = d_data->getProof();
307
462
        std::vector<Node> args = exp;
308
231
        args.emplace_back(oa);
309
231
        proof->addStep(lemma, PfRule::ARITH_MULT_SIGN, {}, args);
310
      }
311
1288
      d_data->d_im.addPendingLemma(lemma, InferenceId::ARITH_NL_SIGN, proof);
312
    }
313
14740
    return status;
314
  }
315
34176
  Assert(a_index < vla.size());
316
68352
  Node av = vla[a_index];
317
34176
  unsigned aexp = d_data->d_mdb.getExponent(a, av);
318
  // take current sign in model
319
68352
  Node mvaav = d_data->d_model.computeAbstractModelValue(av);
320
34176
  int sgn = mvaav.getConst<Rational>().sgn();
321
68352
  Trace("nl-ext-debug") << "Process var " << av << "^" << aexp
322
34176
                        << ", model sign = " << sgn << std::endl;
323
34176
  if (sgn == 0)
324
  {
325
3689
    if (mvaoa.getConst<Rational>().sgn() != 0)
326
    {
327
1668
      Node prem = av.eqNode(d_data->d_zero);
328
1668
      Node conc = oa.eqNode(d_data->d_zero);
329
1668
      Node lemma = prem.impNode(conc);
330
834
      CDProof* proof = nullptr;
331
834
      if (d_data->isProofEnabled())
332
      {
333
129
        proof = d_data->getProof();
334
129
        proof->addStep(conc, PfRule::MACRO_SR_PRED_INTRO, {prem}, {conc});
335
129
        proof->addStep(lemma, PfRule::SCOPE, {conc}, {prem});
336
      }
337
834
      d_data->d_im.addPendingLemma(lemma, InferenceId::ARITH_NL_SIGN, proof);
338
    }
339
3689
    return 0;
340
  }
341
30487
  if (aexp % 2 == 0)
342
  {
343
2954
    exp.push_back(av.eqNode(d_data->d_zero).negate());
344
2954
    return compareSign(oa, a, a_index + 1, status, exp);
345
  }
346
27533
  exp.push_back(nm->mkNode(sgn == 1 ? Kind::GT : Kind::LT, av, d_data->d_zero));
347
27533
  return compareSign(oa, a, a_index + 1, status * sgn, exp);
348
}
349
350
59613
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
119226
  Trace("nl-ext-comp-debug")
362
59613
      << "Check |" << a << "| >= |" << b << "|" << std::endl;
363
59613
  unsigned pexp_size = exp.size();
364
59613
  if (compareMonomial(
365
          oa, a, 0, a_exp_proc, ob, b, 0, b_exp_proc, 0, exp, lem, cmp_infers))
366
  {
367
41642
    return true;
368
  }
369
17971
  exp.resize(pexp_size);
370
35942
  Trace("nl-ext-comp-debug")
371
17971
      << "Check |" << b << "| >= |" << a << "|" << std::endl;
372
17971
  if (compareMonomial(
373
          ob, b, 0, b_exp_proc, oa, a, 0, a_exp_proc, 0, exp, lem, cmp_infers))
374
  {
375
11268
    return true;
376
  }
377
6703
  return false;
378
}
379
380
// trying to show a ( >, = ) b   by inequalities between variables in
381
// monomials a,b
382
310578
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
621156
  Trace("nl-ext-comp-debug")
397
310578
      << "compareMonomial " << oa << " and " << ob << ", indices = " << a_index
398
310578
      << " " << b_index << std::endl;
399
310578
  Assert(status == 0 || status == 2);
400
310578
  const std::vector<Node>& vla = d_data->d_mdb.getVariableList(a);
401
310578
  const std::vector<Node>& vlb = d_data->d_mdb.getVariableList(b);
402
310578
  if (a_index == vla.size() && b_index == vlb.size())
403
  {
404
    // finished, compare absolute value of abstract model values
405
52910
    int modelStatus = d_data->d_model.compare(oa, ob, false, true) * -2;
406
105820
    Trace("nl-ext-comp") << "...finished comparison with " << oa << " <"
407
52910
                         << status << "> " << ob
408
52910
                         << ", model status = " << modelStatus << std::endl;
409
52910
    if (status != modelStatus)
410
    {
411
6544
      Trace("nl-ext-comp-infer")
412
3272
          << "infer : " << oa << " <" << status << "> " << ob << std::endl;
413
3272
      if (status == 2)
414
      {
415
        // must state that all variables are non-zero
416
6996
        for (unsigned j = 0; j < vla.size(); j++)
417
        {
418
4509
          exp.push_back(vla[j].eqNode(d_data->d_zero).negate());
419
        }
420
      }
421
3272
      NodeManager* nm = NodeManager::currentNM();
422
      Node clem = nm->mkNode(
423
6544
          Kind::IMPLIES, nm->mkAnd(exp), mkLit(oa, ob, status, true));
424
3272
      Trace("nl-ext-comp-lemma") << "comparison lemma : " << clem << std::endl;
425
3272
      lem.emplace_back(
426
6544
          InferenceId::ARITH_NL_COMPARISON, clem, LemmaProperty::NONE, nullptr);
427
3272
      cmp_infers[status][oa][ob] = clem;
428
    }
429
52910
    return true;
430
  }
431
  // get a/b variable information
432
515336
  Node av;
433
257668
  unsigned aexp = 0;
434
257668
  unsigned avo = 0;
435
257668
  if (a_index < vla.size())
436
  {
437
221151
    av = vla[a_index];
438
221151
    unsigned aexpTotal = d_data->d_mdb.getExponent(a, av);
439
221151
    Assert(a_exp_proc[av] <= aexpTotal);
440
221151
    aexp = aexpTotal - a_exp_proc[av];
441
221151
    if (aexp == 0)
442
    {
443
155164
      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
77582
                             cmp_infers);
455
    }
456
143569
    Assert(d_order_vars.find(av) != d_order_vars.end());
457
143569
    avo = d_order_vars[av];
458
  }
459
360172
  Node bv;
460
180086
  unsigned bexp = 0;
461
180086
  unsigned bvo = 0;
462
180086
  if (b_index < vlb.size())
463
  {
464
145629
    bv = vlb[b_index];
465
145629
    unsigned bexpTotal = d_data->d_mdb.getExponent(b, bv);
466
145629
    Assert(b_exp_proc[bv] <= bexpTotal);
467
145629
    bexp = bexpTotal - b_exp_proc[bv];
468
145629
    if (bexp == 0)
469
    {
470
148824
      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
74412
                             cmp_infers);
482
    }
483
71217
    Assert(d_order_vars.find(bv) != d_order_vars.end());
484
71217
    bvo = d_order_vars[bv];
485
  }
486
  // get "one" information
487
105674
  Assert(d_order_vars.find(d_data->d_one) != d_order_vars.end());
488
105674
  unsigned ovo = d_order_vars[d_data->d_one];
489
211348
  Trace("nl-ext-comp-debug") << "....vars : " << av << "^" << aexp << " " << bv
490
105674
                             << "^" << bexp << std::endl;
491
492
  //--- cases
493
105674
  if (av.isNull())
494
  {
495
3869
    if (bvo <= ovo)
496
    {
497
2824
      Trace("nl-ext-comp-debug") << "...take leading " << bv << std::endl;
498
      // can multiply b by <=1
499
2824
      exp.push_back(mkLit(d_data->d_one, bv, bvo == ovo ? 0 : 2, true));
500
5648
      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
2824
                             cmp_infers);
512
    }
513
2090
    Trace("nl-ext-comp-debug")
514
1045
        << "...failure, unmatched |b|>1 component." << std::endl;
515
1045
    return false;
516
  }
517
101805
  else if (bv.isNull())
518
  {
519
34457
    if (avo >= ovo)
520
    {
521
31657
      Trace("nl-ext-comp-debug") << "...take leading " << av << std::endl;
522
      // can multiply a by >=1
523
31657
      exp.push_back(mkLit(av, d_data->d_one, avo == ovo ? 0 : 2, true));
524
63314
      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
31657
                             cmp_infers);
536
    }
537
5600
    Trace("nl-ext-comp-debug")
538
2800
        << "...failure, unmatched |a|<1 component." << std::endl;
539
2800
    return false;
540
  }
541
67348
  Assert(!av.isNull() && !bv.isNull());
542
67348
  if (avo >= bvo)
543
  {
544
46239
    if (bvo < ovo && avo >= ovo)
545
    {
546
496
      Trace("nl-ext-comp-debug") << "...take leading " << av << std::endl;
547
      // do avo>=1 instead
548
496
      exp.push_back(mkLit(av, d_data->d_one, avo == ovo ? 0 : 2, true));
549
992
      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
496
                             cmp_infers);
561
    }
562
45743
    unsigned min_exp = aexp > bexp ? bexp : aexp;
563
45743
    a_exp_proc[av] += min_exp;
564
45743
    b_exp_proc[bv] += min_exp;
565
91486
    Trace("nl-ext-comp-debug") << "...take leading " << min_exp << " from "
566
45743
                               << av << " and " << bv << std::endl;
567
45743
    exp.push_back(mkLit(av, bv, avo == bvo ? 0 : 2, true));
568
91486
    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
45743
                               cmp_infers);
580
45743
    a_exp_proc[av] -= min_exp;
581
45743
    b_exp_proc[bv] -= min_exp;
582
45743
    return ret;
583
  }
584
21109
  if (bvo <= ovo)
585
  {
586
280
    Trace("nl-ext-comp-debug") << "...take leading " << bv << std::endl;
587
    // try multiply b <= 1
588
280
    exp.push_back(mkLit(d_data->d_one, bv, bvo == ovo ? 0 : 2, true));
589
560
    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
280
                           cmp_infers);
601
  }
602
41658
  Trace("nl-ext-comp-debug")
603
20829
      << "...failure, leading |b|>|a|>1 component." << std::endl;
604
20829
  return false;
605
}
606
607
4144
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
4144
  if (x == y)
614
  {
615
168
    return true;
616
  }
617
3976
  else if (visited.find(x) != visited.end())
618
  {
619
634
    return false;
620
  }
621
3342
  visited[x] = true;
622
3342
  std::map<Node, std::map<Node, Node> >::iterator it = cmp_infers.find(x);
623
3342
  if (it != cmp_infers.end())
624
  {
625
1313
    for (std::map<Node, Node>::iterator itc = it->second.begin();
626
1313
         itc != it->second.end();
627
         ++itc)
628
    {
629
885
      exp.push_back(itc->second);
630
885
      if (cmp_holds(itc->first, y, cmp_infers, exp, visited))
631
      {
632
179
        return true;
633
      }
634
706
      exp.pop_back();
635
    }
636
  }
637
3163
  return false;
638
}
639
640
2005
void MonomialCheck::assignOrderIds(std::vector<Node>& vars,
641
                                   NodeMultiset& order,
642
                                   bool isConcrete,
643
                                   bool isAbsolute)
644
{
645
2005
  SortNlModel smv;
646
2005
  smv.d_nlm = &d_data->d_model;
647
2005
  smv.d_isConcrete = isConcrete;
648
2005
  smv.d_isAbsolute = isAbsolute;
649
2005
  smv.d_reverse_order = false;
650
2005
  std::sort(vars.begin(), vars.end(), smv);
651
652
2005
  order.clear();
653
  // assign ordering id's
654
2005
  unsigned counter = 0;
655
2005
  unsigned order_index = isConcrete ? 0 : 1;
656
4010
  Node prev;
657
12298
  for (unsigned j = 0; j < vars.size(); j++)
658
  {
659
20586
    Node x = vars[j];
660
20586
    Node v = d_data->d_model.computeModelValue(x, isConcrete);
661
10293
    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
10293
    Trace("nl-ext-mvo") << "  order " << x << " : " << v << std::endl;
669
10293
    if (v != prev)
670
    {
671
      // builtin points
672
      bool success;
673
10303
      do
674
      {
675
10303
        success = false;
676
10303
        if (order_index < d_order_points.size())
677
        {
678
4515
          Node vv = d_data->d_model.computeModelValue(
679
9030
              d_order_points[order_index], isConcrete);
680
4515
          if (d_data->d_model.compareValue(v, vv, isAbsolute) <= 0)
681
          {
682
3361
            counter++;
683
6722
            Trace("nl-ext-mvo") << "O[" << d_order_points[order_index]
684
3361
                                << "] = " << counter << std::endl;
685
3361
            order[d_order_points[order_index]] = counter;
686
3361
            prev = vv;
687
3361
            order_index++;
688
3361
            success = true;
689
          }
690
        }
691
      } while (success);
692
    }
693
10293
    if (prev.isNull() || d_data->d_model.compareValue(v, prev, isAbsolute) != 0)
694
    {
695
4520
      counter++;
696
    }
697
10293
    Trace("nl-ext-mvo") << "O[" << x << "] = " << counter << std::endl;
698
10293
    order[x] = counter;
699
10293
    prev = v;
700
  }
701
3303
  while (order_index < d_order_points.size())
702
  {
703
649
    counter++;
704
1298
    Trace("nl-ext-mvo") << "O[" << d_order_points[order_index]
705
649
                        << "] = " << counter << std::endl;
706
649
    order[d_order_points[order_index]] = counter;
707
649
    order_index++;
708
  }
709
2005
}
710
86097
Node MonomialCheck::mkLit(Node a, Node b, int status, bool isAbsolute) const
711
{
712
86097
  if (status == 0)
713
  {
714
20938
    Node a_eq_b = a.eqNode(b);
715
10469
    if (!isAbsolute)
716
    {
717
      return a_eq_b;
718
    }
719
20938
    Node negate_b = NodeManager::currentNM()->mkNode(Kind::UMINUS, b);
720
10469
    return a_eq_b.orNode(a.eqNode(negate_b));
721
  }
722
75628
  else if (status < 0)
723
  {
724
537
    return mkLit(b, a, -status);
725
  }
726
75091
  Assert(status == 1 || status == 2);
727
75091
  NodeManager* nm = NodeManager::currentNM();
728
75091
  Kind greater_op = status == 1 ? Kind::GEQ : Kind::GT;
729
75091
  if (!isAbsolute)
730
  {
731
1288
    return nm->mkNode(greater_op, a, b);
732
  }
733
  // return nm->mkNode( greater_op, mkAbs( a ), mkAbs( b ) );
734
147606
  Node a_is_nonnegative = nm->mkNode(Kind::GEQ, a, d_data->d_zero);
735
147606
  Node b_is_nonnegative = nm->mkNode(Kind::GEQ, b, d_data->d_zero);
736
147606
  Node negate_a = nm->mkNode(Kind::UMINUS, a);
737
147606
  Node negate_b = nm->mkNode(Kind::UMINUS, b);
738
  return a_is_nonnegative.iteNode(
739
147606
      b_is_nonnegative.iteNode(nm->mkNode(greater_op, a, b),
740
147606
                               nm->mkNode(greater_op, a, negate_b)),
741
147606
      b_is_nonnegative.iteNode(nm->mkNode(greater_op, negate_a, b),
742
221409
                               nm->mkNode(greater_op, negate_a, negate_b)));
743
}
744
745
62214
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
62214
  std::map<Node, Node>& mono_diff_a = d_data->d_mono_diff[a];
751
62214
  if (mono_diff_a.find(b) == mono_diff_a.end())
752
  {
753
14100
    Trace("nl-ext-mono-factor")
754
7050
        << "Set monomial factor for " << a << "/" << b << std::endl;
755
7050
    mono_diff_a[b] = d_data->d_mdb.mkMonomialRemFactor(a, common);
756
  }
757
62214
}
758
759
}  // namespace nl
760
}  // namespace arith
761
}  // namespace theory
762
29577
}  // namespace cvc5