GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/nl/ext/monomial_check.cpp Lines: 360 371 97.0 %
Date: 2021-11-07 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
9696
MonomialCheck::MonomialCheck(Env& env, ExtState* data)
33
9696
    : EnvObj(env), d_data(data)
34
{
35
9696
  d_order_points.push_back(d_data->d_neg_one);
36
9696
  d_order_points.push_back(d_data->d_zero);
37
9696
  d_order_points.push_back(d_data->d_one);
38
9696
}
39
40
4364
void MonomialCheck::init(const std::vector<Node>& xts)
41
{
42
4364
  d_ms_proc.clear();
43
4364
  d_m_nconst_factor.clear();
44
45
38804
  for (unsigned i = 0, xsize = xts.size(); i < xsize; i++)
46
  {
47
68880
    Node a = xts[i];
48
34440
    if (a.getKind() == Kind::NONLINEAR_MULT)
49
    {
50
25862
      const std::vector<Node>& varList = d_data->d_mdb.getVariableList(a);
51
75598
      for (const Node& v : varList)
52
      {
53
99472
        Node mvk = d_data->d_model.computeAbstractModelValue(v);
54
49736
        if (!mvk.isConst())
55
        {
56
          d_m_nconst_factor[a] = true;
57
        }
58
      }
59
    }
60
  }
61
62
17456
  for (unsigned j = 0; j < d_order_points.size(); j++)
63
  {
64
26184
    Node c = d_order_points[j];
65
13092
    d_data->d_model.computeConcreteModelValue(c);
66
13092
    d_data->d_model.computeAbstractModelValue(c);
67
  }
68
4364
}
69
70
3486
void MonomialCheck::checkSign()
71
{
72
6972
  std::map<Node, int> signs;
73
3486
  Trace("nl-ext") << "Get monomial sign lemmas..." << std::endl;
74
25366
  for (unsigned j = 0; j < d_data->d_ms.size(); j++)
75
  {
76
43760
    Node a = d_data->d_ms[j];
77
21880
    if (d_ms_proc.find(a) == d_ms_proc.end())
78
    {
79
43760
      std::vector<Node> exp;
80
21880
      if (Trace.isOn("nl-ext-debug"))
81
      {
82
        Node cmva = d_data->d_model.computeConcreteModelValue(a);
83
        Trace("nl-ext-debug")
84
            << "  process " << a << ", mv=" << cmva << "..." << std::endl;
85
      }
86
21880
      if (d_m_nconst_factor.find(a) == d_m_nconst_factor.end())
87
      {
88
21880
        signs[a] = compareSign(a, a, 0, 1, exp);
89
21880
        if (signs[a] == 0)
90
        {
91
4293
          d_ms_proc[a] = true;
92
8586
          Trace("nl-ext-debug")
93
4293
              << "...mark " << a << " reduced since its value is 0."
94
4293
              << std::endl;
95
        }
96
      }
97
      else
98
      {
99
        Trace("nl-ext-debug")
100
            << "...can't conclude sign lemma for " << a
101
            << " since model value of a factor is non-constant." << std::endl;
102
      }
103
    }
104
  }
105
3486
}
106
107
4707
void MonomialCheck::checkMagnitude(unsigned c)
108
{
109
  // ensure information is setup
110
4707
  if (c == 0)
111
  {
112
    // sort by absolute values of abstract model values
113
2170
    assignOrderIds(d_data->d_ms_vars, d_order_vars, false, true);
114
115
    // sort individual variable lists
116
2170
    Trace("nl-ext-proc") << "Assign order var lists..." << std::endl;
117
2170
    d_data->d_mdb.sortVariablesByModel(d_data->d_ms, d_data->d_model);
118
  }
119
120
4707
  unsigned r = 1;
121
9414
  std::vector<SimpleTheoryLemma> lemmas;
122
  // if (x,y,L) in cmp_infers, then x > y inferred as conclusion of L
123
  // in lemmas
124
9414
  std::map<int, std::map<Node, std::map<Node, Node> > > cmp_infers;
125
9414
  Trace("nl-ext") << "Get monomial comparison lemmas (order=" << r
126
4707
                  << ", compare=" << c << ")..." << std::endl;
127
38108
  for (unsigned j = 0; j < d_data->d_ms.size(); j++)
128
  {
129
66802
    Node a = d_data->d_ms[j];
130
66802
    if (d_ms_proc.find(a) == d_ms_proc.end()
131
33401
        && d_m_nconst_factor.find(a) == d_m_nconst_factor.end())
132
    {
133
29543
      if (c == 0)
134
      {
135
        // compare magnitude against 1
136
25494
        std::vector<Node> exp;
137
25494
        NodeMultiset a_exp_proc;
138
25494
        NodeMultiset b_exp_proc;
139
25494
        compareMonomial(a,
140
                        a,
141
                        a_exp_proc,
142
12747
                        d_data->d_one,
143
12747
                        d_data->d_one,
144
                        b_exp_proc,
145
                        exp,
146
                        lemmas,
147
                        cmp_infers);
148
      }
149
      else
150
      {
151
16796
        const NodeMultiset& mea = d_data->d_mdb.getMonomialExponentMap(a);
152
16796
        if (c == 1)
153
        {
154
          // could compare not just against containing variables?
155
          // compare magnitude against variables
156
98361
          for (unsigned k = 0; k < d_data->d_ms_vars.size(); k++)
157
          {
158
177190
            Node v = d_data->d_ms_vars[k];
159
177190
            Node mvcv = d_data->d_model.computeConcreteModelValue(v);
160
88595
            if (mvcv.isConst())
161
            {
162
176578
              std::vector<Node> exp;
163
176578
              NodeMultiset a_exp_proc;
164
176578
              NodeMultiset b_exp_proc;
165
88289
              if (mea.find(v) != mea.end())
166
              {
167
17763
                a_exp_proc[v] = 1;
168
17763
                b_exp_proc[v] = 1;
169
17763
                setMonomialFactor(a, v, a_exp_proc);
170
17763
                setMonomialFactor(v, a, b_exp_proc);
171
17763
                compareMonomial(a,
172
                                a,
173
                                a_exp_proc,
174
                                v,
175
                                v,
176
                                b_exp_proc,
177
                                exp,
178
                                lemmas,
179
                                cmp_infers);
180
              }
181
            }
182
          }
183
        }
184
        else
185
        {
186
          // compare magnitude against other non-linear monomials
187
95430
          for (unsigned k = (j + 1); k < d_data->d_ms.size(); k++)
188
          {
189
176800
            Node b = d_data->d_ms[k];
190
            //(signs[a]==signs[b])==(r==0)
191
176800
            if (d_ms_proc.find(b) == d_ms_proc.end()
192
88400
                && d_m_nconst_factor.find(b) == d_m_nconst_factor.end())
193
            {
194
83497
              const NodeMultiset& meb = d_data->d_mdb.getMonomialExponentMap(b);
195
196
166994
              std::vector<Node> exp;
197
              // take common factors of monomials, set minimum of
198
              // common exponents as processed
199
166994
              NodeMultiset a_exp_proc;
200
166994
              NodeMultiset b_exp_proc;
201
242877
              for (NodeMultiset::const_iterator itmea2 = mea.begin();
202
242877
                   itmea2 != mea.end();
203
                   ++itmea2)
204
              {
205
159380
                NodeMultiset::const_iterator itmeb2 = meb.find(itmea2->first);
206
159380
                if (itmeb2 != meb.end())
207
                {
208
30597
                  unsigned min_exp = itmea2->second > itmeb2->second
209
59470
                                         ? itmeb2->second
210
59470
                                         : itmea2->second;
211
30597
                  a_exp_proc[itmea2->first] = min_exp;
212
30597
                  b_exp_proc[itmea2->first] = min_exp;
213
61194
                  Trace("nl-ext-comp") << "Common exponent : " << itmea2->first
214
30597
                                       << " : " << min_exp << std::endl;
215
                }
216
              }
217
83497
              if (!a_exp_proc.empty())
218
              {
219
30469
                setMonomialFactor(a, b, a_exp_proc);
220
30469
                setMonomialFactor(b, a, b_exp_proc);
221
              }
222
              /*
223
              if( !a_exp_proc.empty() ){
224
                //reduction based on common exponents a > 0 => ( a * b
225
              <> a * c <=> b <> c ), a < 0 => ( a * b <> a * c <=> b
226
              !<> c )  ? }else{ compareMonomial( a, a, a_exp_proc, b,
227
              b, b_exp_proc, exp, lemmas );
228
              }
229
              */
230
83497
              compareMonomial(
231
                  a, a, a_exp_proc, b, b, b_exp_proc, exp, lemmas, cmp_infers);
232
            }
233
          }
234
        }
235
      }
236
    }
237
  }
238
  // remove redundant lemmas, e.g. if a > b, b > c, a > c were
239
  // inferred, discard lemma with conclusion a > c
240
9414
  Trace("nl-ext-comp") << "Compute redundancies for " << lemmas.size()
241
4707
                       << " lemmas." << std::endl;
242
  // naive
243
9414
  std::unordered_set<Node> r_lemmas;
244
1383
  for (std::map<int, std::map<Node, std::map<Node, Node> > >::iterator itb =
245
4707
           cmp_infers.begin();
246
6090
       itb != cmp_infers.end();
247
       ++itb)
248
  {
249
2492
    for (std::map<Node, std::map<Node, Node> >::iterator itc =
250
1383
             itb->second.begin();
251
3875
         itc != itb->second.end();
252
         ++itc)
253
    {
254
5895
      for (std::map<Node, Node>::iterator itc2 = itc->second.begin();
255
5895
           itc2 != itc->second.end();
256
           ++itc2)
257
      {
258
6806
        std::map<Node, bool> visited;
259
10228
        for (std::map<Node, Node>::iterator itc3 = itc->second.begin();
260
10228
             itc3 != itc->second.end();
261
             ++itc3)
262
        {
263
6983
          if (itc3->first != itc2->first)
264
          {
265
7172
            std::vector<Node> exp;
266
3665
            if (cmp_holds(itc3->first, itc2->first, itb->second, exp, visited))
267
            {
268
158
              r_lemmas.insert(itc2->second);
269
316
              Trace("nl-ext-comp")
270
158
                  << "...inference of " << itc->first << " > " << itc2->first
271
158
                  << " was redundant." << std::endl;
272
158
              break;
273
            }
274
          }
275
        }
276
      }
277
    }
278
  }
279
8110
  for (unsigned i = 0; i < lemmas.size(); i++)
280
  {
281
3403
    if (r_lemmas.find(lemmas[i].d_node) == r_lemmas.end())
282
    {
283
3245
      d_data->d_im.addPendingLemma(lemmas[i]);
284
    }
285
  }
286
  // could only take maximal lower/minimial lower bounds?
287
4707
}
288
289
// show a <> 0 by inequalities between variables in monomial a w.r.t 0
290
58053
int MonomialCheck::compareSign(
291
    Node oa, Node a, unsigned a_index, int status, std::vector<Node>& exp)
292
{
293
116106
  Trace("nl-ext-debug") << "Process " << a << " at index " << a_index
294
58053
                        << ", status is " << status << std::endl;
295
58053
  NodeManager* nm = NodeManager::currentNM();
296
116106
  Node mvaoa = d_data->d_model.computeAbstractModelValue(oa);
297
58053
  const std::vector<Node>& vla = d_data->d_mdb.getVariableList(a);
298
58053
  if (a_index == vla.size())
299
  {
300
17587
    if (mvaoa.getConst<Rational>().sgn() != status)
301
    {
302
      Node lemma =
303
2970
          nm->mkAnd(exp).impNode(mkLit(oa, d_data->d_zero, status * 2));
304
1485
      CDProof* proof = nullptr;
305
1485
      if (d_data->isProofEnabled())
306
      {
307
269
        proof = d_data->getProof();
308
538
        std::vector<Node> args = exp;
309
269
        args.emplace_back(oa);
310
269
        proof->addStep(lemma, PfRule::ARITH_MULT_SIGN, {}, args);
311
      }
312
1485
      d_data->d_im.addPendingLemma(lemma, InferenceId::ARITH_NL_SIGN, proof);
313
    }
314
17587
    return status;
315
  }
316
40466
  Assert(a_index < vla.size());
317
80932
  Node av = vla[a_index];
318
40466
  unsigned aexp = d_data->d_mdb.getExponent(a, av);
319
  // take current sign in model
320
80932
  Node mvaav = d_data->d_model.computeAbstractModelValue(av);
321
40466
  int sgn = mvaav.getConst<Rational>().sgn();
322
80932
  Trace("nl-ext-debug") << "Process var " << av << "^" << aexp
323
40466
                        << ", model sign = " << sgn << std::endl;
324
40466
  if (sgn == 0)
325
  {
326
4293
    if (mvaoa.getConst<Rational>().sgn() != 0)
327
    {
328
2050
      Node prem = av.eqNode(d_data->d_zero);
329
2050
      Node conc = oa.eqNode(d_data->d_zero);
330
2050
      Node lemma = prem.impNode(conc);
331
1025
      CDProof* proof = nullptr;
332
1025
      if (d_data->isProofEnabled())
333
      {
334
149
        proof = d_data->getProof();
335
149
        proof->addStep(conc, PfRule::MACRO_SR_PRED_INTRO, {prem}, {conc});
336
149
        proof->addStep(lemma, PfRule::SCOPE, {conc}, {prem});
337
      }
338
1025
      d_data->d_im.addPendingLemma(lemma, InferenceId::ARITH_NL_SIGN, proof);
339
    }
340
4293
    return 0;
341
  }
342
36173
  if (aexp % 2 == 0)
343
  {
344
3167
    exp.push_back(av.eqNode(d_data->d_zero).negate());
345
3167
    return compareSign(oa, a, a_index + 1, status, exp);
346
  }
347
33006
  exp.push_back(nm->mkNode(sgn == 1 ? Kind::GT : Kind::LT, av, d_data->d_zero));
348
33006
  return compareSign(oa, a, a_index + 1, status * sgn, exp);
349
}
350
351
114007
bool MonomialCheck::compareMonomial(
352
    Node oa,
353
    Node a,
354
    NodeMultiset& a_exp_proc,
355
    Node ob,
356
    Node b,
357
    NodeMultiset& b_exp_proc,
358
    std::vector<Node>& exp,
359
    std::vector<SimpleTheoryLemma>& lem,
360
    std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers)
361
{
362
228014
  Trace("nl-ext-comp-debug")
363
114007
      << "Check |" << a << "| >= |" << b << "|" << std::endl;
364
114007
  unsigned pexp_size = exp.size();
365
114007
  if (compareMonomial(
366
          oa, a, 0, a_exp_proc, ob, b, 0, b_exp_proc, 0, exp, lem, cmp_infers))
367
  {
368
82007
    return true;
369
  }
370
32000
  exp.resize(pexp_size);
371
64000
  Trace("nl-ext-comp-debug")
372
32000
      << "Check |" << b << "| >= |" << a << "|" << std::endl;
373
32000
  if (compareMonomial(
374
          ob, b, 0, b_exp_proc, oa, a, 0, a_exp_proc, 0, exp, lem, cmp_infers))
375
  {
376
17045
    return true;
377
  }
378
14955
  return false;
379
}
380
381
// trying to show a ( >, = ) b   by inequalities between variables in
382
// monomials a,b
383
637138
bool MonomialCheck::compareMonomial(
384
    Node oa,
385
    Node a,
386
    unsigned a_index,
387
    NodeMultiset& a_exp_proc,
388
    Node ob,
389
    Node b,
390
    unsigned b_index,
391
    NodeMultiset& b_exp_proc,
392
    int status,
393
    std::vector<Node>& exp,
394
    std::vector<SimpleTheoryLemma>& lem,
395
    std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers)
396
{
397
1274276
  Trace("nl-ext-comp-debug")
398
637138
      << "compareMonomial " << oa << " and " << ob << ", indices = " << a_index
399
637138
      << " " << b_index << std::endl;
400
637138
  Assert(status == 0 || status == 2);
401
637138
  const std::vector<Node>& vla = d_data->d_mdb.getVariableList(a);
402
637138
  const std::vector<Node>& vlb = d_data->d_mdb.getVariableList(b);
403
637138
  if (a_index == vla.size() && b_index == vlb.size())
404
  {
405
    // finished, compare absolute value of abstract model values
406
99052
    int modelStatus = d_data->d_model.compare(oa, ob, false, true) * 2;
407
198104
    Trace("nl-ext-comp") << "...finished comparison with " << oa << " <"
408
99052
                         << status << "> " << ob
409
99052
                         << ", model status = " << modelStatus << std::endl;
410
99052
    if (status != modelStatus)
411
    {
412
6806
      Trace("nl-ext-comp-infer")
413
3403
          << "infer : " << oa << " <" << status << "> " << ob << std::endl;
414
3403
      if (status == 2)
415
      {
416
        // must state that all variables are non-zero
417
7421
        for (unsigned j = 0; j < vla.size(); j++)
418
        {
419
4789
          exp.push_back(vla[j].eqNode(d_data->d_zero).negate());
420
        }
421
      }
422
3403
      NodeManager* nm = NodeManager::currentNM();
423
      Node clem = nm->mkNode(
424
6806
          Kind::IMPLIES, nm->mkAnd(exp), mkLit(oa, ob, status, true));
425
3403
      Trace("nl-ext-comp-lemma") << "comparison lemma : " << clem << std::endl;
426
3403
      lem.emplace_back(
427
6806
          InferenceId::ARITH_NL_COMPARISON, clem, LemmaProperty::NONE, nullptr);
428
3403
      cmp_infers[status][oa][ob] = clem;
429
    }
430
99052
    return true;
431
  }
432
  // get a/b variable information
433
1076172
  Node av;
434
538086
  unsigned aexp = 0;
435
538086
  unsigned avo = 0;
436
538086
  if (a_index < vla.size())
437
  {
438
457620
    av = vla[a_index];
439
457620
    unsigned aexpTotal = d_data->d_mdb.getExponent(a, av);
440
457620
    Assert(a_exp_proc[av] <= aexpTotal);
441
457620
    aexp = aexpTotal - a_exp_proc[av];
442
457620
    if (aexp == 0)
443
    {
444
337096
      return compareMonomial(oa,
445
                             a,
446
                             a_index + 1,
447
                             a_exp_proc,
448
                             ob,
449
                             b,
450
                             b_index,
451
                             b_exp_proc,
452
                             status,
453
                             exp,
454
                             lem,
455
168548
                             cmp_infers);
456
    }
457
289072
    Assert(d_order_vars.find(av) != d_order_vars.end());
458
289072
    avo = d_order_vars[av];
459
  }
460
739076
  Node bv;
461
369538
  unsigned bexp = 0;
462
369538
  unsigned bvo = 0;
463
369538
  if (b_index < vlb.size())
464
  {
465
328184
    bv = vlb[b_index];
466
328184
    unsigned bexpTotal = d_data->d_mdb.getExponent(b, bv);
467
328184
    Assert(b_exp_proc[bv] <= bexpTotal);
468
328184
    bexp = bexpTotal - b_exp_proc[bv];
469
328184
    if (bexp == 0)
470
    {
471
318258
      return compareMonomial(oa,
472
                             a,
473
                             a_index,
474
                             a_exp_proc,
475
                             ob,
476
                             b,
477
                             b_index + 1,
478
                             b_exp_proc,
479
                             status,
480
                             exp,
481
                             lem,
482
159129
                             cmp_infers);
483
    }
484
169055
    Assert(d_order_vars.find(bv) != d_order_vars.end());
485
169055
    bvo = d_order_vars[bv];
486
  }
487
  // get "one" information
488
210409
  Assert(d_order_vars.find(d_data->d_one) != d_order_vars.end());
489
210409
  unsigned ovo = d_order_vars[d_data->d_one];
490
420818
  Trace("nl-ext-comp-debug") << "....vars : " << av << "^" << aexp << " " << bv
491
210409
                             << "^" << bexp << std::endl;
492
493
  //--- cases
494
210409
  if (av.isNull())
495
  {
496
2231
    if (bvo <= ovo)
497
    {
498
1838
      Trace("nl-ext-comp-debug") << "...take leading " << bv << std::endl;
499
      // can multiply b by <=1
500
1838
      exp.push_back(mkLit(d_data->d_one, bv, bvo == ovo ? 0 : 2, true));
501
3676
      return compareMonomial(oa,
502
                             a,
503
                             a_index,
504
                             a_exp_proc,
505
                             ob,
506
                             b,
507
                             b_index + 1,
508
                             b_exp_proc,
509
                             bvo == ovo ? status : 2,
510
                             exp,
511
                             lem,
512
1838
                             cmp_infers);
513
    }
514
786
    Trace("nl-ext-comp-debug")
515
393
        << "...failure, unmatched |b|>1 component." << std::endl;
516
393
    return false;
517
  }
518
208178
  else if (bv.isNull())
519
  {
520
41354
    if (avo >= ovo)
521
    {
522
39784
      Trace("nl-ext-comp-debug") << "...take leading " << av << std::endl;
523
      // can multiply a by >=1
524
39784
      exp.push_back(mkLit(av, d_data->d_one, avo == ovo ? 0 : 2, true));
525
79568
      return compareMonomial(oa,
526
                             a,
527
                             a_index + 1,
528
                             a_exp_proc,
529
                             ob,
530
                             b,
531
                             b_index,
532
                             b_exp_proc,
533
                             avo == ovo ? status : 2,
534
                             exp,
535
                             lem,
536
39784
                             cmp_infers);
537
    }
538
3140
    Trace("nl-ext-comp-debug")
539
1570
        << "...failure, unmatched |a|<1 component." << std::endl;
540
1570
    return false;
541
  }
542
166824
  Assert(!av.isNull() && !bv.isNull());
543
166824
  if (avo >= bvo)
544
  {
545
121772
    if (bvo < ovo && avo >= ovo)
546
    {
547
96
      Trace("nl-ext-comp-debug") << "...take leading " << av << std::endl;
548
      // do avo>=1 instead
549
96
      exp.push_back(mkLit(av, d_data->d_one, avo == ovo ? 0 : 2, true));
550
192
      return compareMonomial(oa,
551
                             a,
552
                             a_index + 1,
553
                             a_exp_proc,
554
                             ob,
555
                             b,
556
                             b_index,
557
                             b_exp_proc,
558
                             avo == ovo ? status : 2,
559
                             exp,
560
                             lem,
561
96
                             cmp_infers);
562
    }
563
121676
    unsigned min_exp = aexp > bexp ? bexp : aexp;
564
121676
    a_exp_proc[av] += min_exp;
565
121676
    b_exp_proc[bv] += min_exp;
566
243352
    Trace("nl-ext-comp-debug") << "...take leading " << min_exp << " from "
567
121676
                               << av << " and " << bv << std::endl;
568
121676
    exp.push_back(mkLit(av, bv, avo == bvo ? 0 : 2, true));
569
243352
    bool ret = compareMonomial(oa,
570
                               a,
571
                               a_index,
572
                               a_exp_proc,
573
                               ob,
574
                               b,
575
                               b_index,
576
                               b_exp_proc,
577
                               avo == bvo ? status : 2,
578
                               exp,
579
                               lem,
580
121676
                               cmp_infers);
581
121676
    a_exp_proc[av] -= min_exp;
582
121676
    b_exp_proc[bv] -= min_exp;
583
121676
    return ret;
584
  }
585
45052
  if (bvo <= ovo)
586
  {
587
60
    Trace("nl-ext-comp-debug") << "...take leading " << bv << std::endl;
588
    // try multiply b <= 1
589
60
    exp.push_back(mkLit(d_data->d_one, bv, bvo == ovo ? 0 : 2, true));
590
120
    return compareMonomial(oa,
591
                           a,
592
                           a_index,
593
                           a_exp_proc,
594
                           ob,
595
                           b,
596
                           b_index + 1,
597
                           b_exp_proc,
598
                           bvo == ovo ? status : 2,
599
                           exp,
600
                           lem,
601
60
                           cmp_infers);
602
  }
603
89984
  Trace("nl-ext-comp-debug")
604
44992
      << "...failure, leading |b|>|a|>1 component." << std::endl;
605
44992
  return false;
606
}
607
608
4581
bool MonomialCheck::cmp_holds(Node x,
609
                              Node y,
610
                              std::map<Node, std::map<Node, Node> >& cmp_infers,
611
                              std::vector<Node>& exp,
612
                              std::map<Node, bool>& visited)
613
{
614
4581
  if (x == y)
615
  {
616
158
    return true;
617
  }
618
4423
  else if (visited.find(x) != visited.end())
619
  {
620
625
    return false;
621
  }
622
3798
  visited[x] = true;
623
3798
  std::map<Node, std::map<Node, Node> >::iterator it = cmp_infers.find(x);
624
3798
  if (it != cmp_infers.end())
625
  {
626
1262
    for (std::map<Node, Node>::iterator itc = it->second.begin();
627
1262
         itc != it->second.end();
628
         ++itc)
629
    {
630
916
      exp.push_back(itc->second);
631
916
      if (cmp_holds(itc->first, y, cmp_infers, exp, visited))
632
      {
633
192
        return true;
634
      }
635
724
      exp.pop_back();
636
    }
637
  }
638
3606
  return false;
639
}
640
641
2170
void MonomialCheck::assignOrderIds(std::vector<Node>& vars,
642
                                   NodeMultiset& order,
643
                                   bool isConcrete,
644
                                   bool isAbsolute)
645
{
646
2170
  SortNlModel smv;
647
2170
  smv.d_nlm = &d_data->d_model;
648
2170
  smv.d_isConcrete = isConcrete;
649
2170
  smv.d_isAbsolute = isAbsolute;
650
2170
  smv.d_reverse_order = false;
651
2170
  std::sort(vars.begin(), vars.end(), smv);
652
653
2170
  order.clear();
654
  // assign ordering id's
655
2170
  unsigned counter = 0;
656
2170
  unsigned order_index = isConcrete ? 0 : 1;
657
4340
  Node prev;
658
12815
  for (unsigned j = 0; j < vars.size(); j++)
659
  {
660
21290
    Node x = vars[j];
661
21290
    Node v = d_data->d_model.computeModelValue(x, isConcrete);
662
10645
    if (!v.isConst())
663
    {
664
      Trace("nl-ext-mvo") << "..do not assign order to " << x << " : " << v
665
                          << std::endl;
666
      // don't assign for non-constant values (transcendental function apps)
667
      break;
668
    }
669
10645
    Trace("nl-ext-mvo") << "  order " << x << " : " << v << std::endl;
670
10645
    if (v != prev)
671
    {
672
      // builtin points
673
      bool success;
674
11153
      do
675
      {
676
11153
        success = false;
677
11153
        if (order_index < d_order_points.size())
678
        {
679
4830
          Node vv = d_data->d_model.computeModelValue(
680
9660
              d_order_points[order_index], isConcrete);
681
4830
          if (d_data->d_model.compareValue(v, vv, isAbsolute) >= 0)
682
          {
683
3711
            counter++;
684
7422
            Trace("nl-ext-mvo") << "O[" << d_order_points[order_index]
685
3711
                                << "] = " << counter << std::endl;
686
3711
            order[d_order_points[order_index]] = counter;
687
3711
            prev = vv;
688
3711
            order_index++;
689
3711
            success = true;
690
          }
691
        }
692
      } while (success);
693
    }
694
10645
    if (prev.isNull() || d_data->d_model.compareValue(v, prev, isAbsolute) != 0)
695
    {
696
4751
      counter++;
697
    }
698
10645
    Trace("nl-ext-mvo") << "O[" << x << "] = " << counter << std::endl;
699
10645
    order[x] = counter;
700
10645
    prev = v;
701
  }
702
3428
  while (order_index < d_order_points.size())
703
  {
704
629
    counter++;
705
1258
    Trace("nl-ext-mvo") << "O[" << d_order_points[order_index]
706
629
                        << "] = " << counter << std::endl;
707
629
    order[d_order_points[order_index]] = counter;
708
629
    order_index++;
709
  }
710
2170
}
711
168962
Node MonomialCheck::mkLit(Node a, Node b, int status, bool isAbsolute) const
712
{
713
168962
  if (status == 0)
714
  {
715
60062
    Node a_eq_b = a.eqNode(b);
716
30031
    if (!isAbsolute)
717
    {
718
      return a_eq_b;
719
    }
720
60062
    Node negate_b = NodeManager::currentNM()->mkNode(Kind::UMINUS, b);
721
30031
    return a_eq_b.orNode(a.eqNode(negate_b));
722
  }
723
138931
  else if (status < 0)
724
  {
725
620
    return mkLit(b, a, -status);
726
  }
727
138311
  Assert(status == 1 || status == 2);
728
138311
  NodeManager* nm = NodeManager::currentNM();
729
138311
  Kind greater_op = status == 1 ? Kind::GEQ : Kind::GT;
730
138311
  if (!isAbsolute)
731
  {
732
1485
    return nm->mkNode(greater_op, a, b);
733
  }
734
  // return nm->mkNode( greater_op, mkAbs( a ), mkAbs( b ) );
735
273652
  Node a_is_nonnegative = nm->mkNode(Kind::GEQ, a, d_data->d_zero);
736
273652
  Node b_is_nonnegative = nm->mkNode(Kind::GEQ, b, d_data->d_zero);
737
273652
  Node negate_a = nm->mkNode(Kind::UMINUS, a);
738
273652
  Node negate_b = nm->mkNode(Kind::UMINUS, b);
739
  return a_is_nonnegative.iteNode(
740
273652
      b_is_nonnegative.iteNode(nm->mkNode(greater_op, a, b),
741
273652
                               nm->mkNode(greater_op, a, negate_b)),
742
273652
      b_is_nonnegative.iteNode(nm->mkNode(greater_op, negate_a, b),
743
410478
                               nm->mkNode(greater_op, negate_a, negate_b)));
744
}
745
746
96464
void MonomialCheck::setMonomialFactor(Node a,
747
                                      Node b,
748
                                      const NodeMultiset& common)
749
{
750
  // Could not tell if this was being inserted intentionally or not.
751
96464
  std::map<Node, Node>& mono_diff_a = d_data->d_mono_diff[a];
752
96464
  if (mono_diff_a.find(b) == mono_diff_a.end())
753
  {
754
20940
    Trace("nl-ext-mono-factor")
755
10470
        << "Set monomial factor for " << a << "/" << b << std::endl;
756
10470
    mono_diff_a[b] = d_data->d_mdb.mkMonomialRemFactor(a, common);
757
  }
758
96464
}
759
760
}  // namespace nl
761
}  // namespace arith
762
}  // namespace theory
763
31137
}  // namespace cvc5