GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/nl/ext/monomial_check.cpp Lines: 359 370 97.0 %
Date: 2021-05-22 Branches: 748 1484 50.4 %

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 "expr/proof.h"
20
#include "theory/arith/arith_msum.h"
21
#include "theory/arith/inference_manager.h"
22
#include "theory/arith/nl/nl_model.h"
23
#include "theory/arith/nl/nl_lemma_utils.h"
24
#include "theory/arith/nl/ext/ext_state.h"
25
26
namespace cvc5 {
27
namespace theory {
28
namespace arith {
29
namespace nl {
30
31
4914
MonomialCheck::MonomialCheck(ExtState* data) : d_data(data)
32
{
33
4914
  d_order_points.push_back(d_data->d_neg_one);
34
4914
  d_order_points.push_back(d_data->d_zero);
35
4914
  d_order_points.push_back(d_data->d_one);
36
4914
}
37
38
2829
void MonomialCheck::init(const std::vector<Node>& xts)
39
{
40
2829
  d_ms_proc.clear();
41
2829
  d_m_nconst_factor.clear();
42
43
24354
  for (unsigned i = 0, xsize = xts.size(); i < xsize; i++)
44
  {
45
43050
    Node a = xts[i];
46
21525
    if (a.getKind() == Kind::NONLINEAR_MULT)
47
    {
48
14887
      const std::vector<Node>& varList = d_data->d_mdb.getVariableList(a);
49
43641
      for (const Node& v : varList)
50
      {
51
57508
        Node mvk = d_data->d_model.computeAbstractModelValue(v);
52
28754
        if (!mvk.isConst())
53
        {
54
          d_m_nconst_factor[a] = true;
55
        }
56
      }
57
    }
58
  }
59
60
11316
  for (unsigned j = 0; j < d_order_points.size(); j++)
61
  {
62
16974
    Node c = d_order_points[j];
63
8487
    d_data->d_model.computeConcreteModelValue(c);
64
8487
    d_data->d_model.computeAbstractModelValue(c);
65
  }
66
2829
}
67
68
2436
void MonomialCheck::checkSign()
69
{
70
4872
  std::map<Node, int> signs;
71
2436
  Trace("nl-ext") << "Get monomial sign lemmas..." << std::endl;
72
16291
  for (unsigned j = 0; j < d_data->d_ms.size(); j++)
73
  {
74
27710
    Node a = d_data->d_ms[j];
75
13855
    if (d_ms_proc.find(a) == d_ms_proc.end())
76
    {
77
27710
      std::vector<Node> exp;
78
13855
      if (Trace.isOn("nl-ext-debug"))
79
      {
80
        Node cmva = d_data->d_model.computeConcreteModelValue(a);
81
        Trace("nl-ext-debug")
82
            << "  process " << a << ", mv=" << cmva << "..." << std::endl;
83
      }
84
13855
      if (d_m_nconst_factor.find(a) == d_m_nconst_factor.end())
85
      {
86
13855
        signs[a] = compareSign(a, a, 0, 1, exp);
87
13855
        if (signs[a] == 0)
88
        {
89
2145
          d_ms_proc[a] = true;
90
4290
          Trace("nl-ext-debug")
91
2145
              << "...mark " << a << " reduced since its value is 0."
92
2145
              << std::endl;
93
        }
94
      }
95
      else
96
      {
97
        Trace("nl-ext-debug")
98
            << "...can't conclude sign lemma for " << a
99
            << " since model value of a factor is non-constant." << std::endl;
100
      }
101
    }
102
  }
103
2436
}
104
105
3466
void MonomialCheck::checkMagnitude(unsigned c)
106
{
107
  // ensure information is setup
108
3466
  if (c == 0)
109
  {
110
    // sort by absolute values of abstract model values
111
1608
    assignOrderIds(d_data->d_ms_vars, d_order_vars, false, true);
112
113
    // sort individual variable lists
114
1608
    Trace("nl-ext-proc") << "Assign order var lists..." << std::endl;
115
1608
    d_data->d_mdb.sortVariablesByModel(d_data->d_ms, d_data->d_model);
116
  }
117
118
3466
  unsigned r = 1;
119
6932
  std::vector<SimpleTheoryLemma> lemmas;
120
  // if (x,y,L) in cmp_infers, then x > y inferred as conclusion of L
121
  // in lemmas
122
6932
  std::map<int, std::map<Node, std::map<Node, Node> > > cmp_infers;
123
6932
  Trace("nl-ext") << "Get monomial comparison lemmas (order=" << r
124
3466
                  << ", compare=" << c << ")..." << std::endl;
125
25425
  for (unsigned j = 0; j < d_data->d_ms.size(); j++)
126
  {
127
43918
    Node a = d_data->d_ms[j];
128
43918
    if (d_ms_proc.find(a) == d_ms_proc.end()
129
21959
        && d_m_nconst_factor.find(a) == d_m_nconst_factor.end())
130
    {
131
19895
      if (c == 0)
132
      {
133
        // compare magnitude against 1
134
17894
        std::vector<Node> exp;
135
17894
        NodeMultiset a_exp_proc;
136
17894
        NodeMultiset b_exp_proc;
137
17894
        compareMonomial(a,
138
                        a,
139
                        a_exp_proc,
140
8947
                        d_data->d_one,
141
8947
                        d_data->d_one,
142
                        b_exp_proc,
143
                        exp,
144
                        lemmas,
145
                        cmp_infers);
146
      }
147
      else
148
      {
149
10948
        const NodeMultiset& mea = d_data->d_mdb.getMonomialExponentMap(a);
150
10948
        if (c == 1)
151
        {
152
          // could compare not just against containing variables?
153
          // compare magnitude against variables
154
55112
          for (unsigned k = 0; k < d_data->d_ms_vars.size(); k++)
155
          {
156
97284
            Node v = d_data->d_ms_vars[k];
157
97284
            Node mvcv = d_data->d_model.computeConcreteModelValue(v);
158
48642
            if (mvcv.isConst())
159
            {
160
96828
              std::vector<Node> exp;
161
96828
              NodeMultiset a_exp_proc;
162
96828
              NodeMultiset b_exp_proc;
163
48414
              if (mea.find(v) != mea.end())
164
              {
165
11567
                a_exp_proc[v] = 1;
166
11567
                b_exp_proc[v] = 1;
167
11567
                setMonomialFactor(a, v, a_exp_proc);
168
11567
                setMonomialFactor(v, a, b_exp_proc);
169
11567
                compareMonomial(a,
170
                                a,
171
                                a_exp_proc,
172
                                v,
173
                                v,
174
                                b_exp_proc,
175
                                exp,
176
                                lemmas,
177
                                cmp_infers);
178
              }
179
            }
180
          }
181
        }
182
        else
183
        {
184
          // compare magnitude against other non-linear monomials
185
34613
          for (unsigned k = (j + 1); k < d_data->d_ms.size(); k++)
186
          {
187
60270
            Node b = d_data->d_ms[k];
188
            //(signs[a]==signs[b])==(r==0)
189
60270
            if (d_ms_proc.find(b) == d_ms_proc.end()
190
30135
                && d_m_nconst_factor.find(b) == d_m_nconst_factor.end())
191
            {
192
28516
              const NodeMultiset& meb = d_data->d_mdb.getMonomialExponentMap(b);
193
194
57032
              std::vector<Node> exp;
195
              // take common factors of monomials, set minimum of
196
              // common exponents as processed
197
57032
              NodeMultiset a_exp_proc;
198
57032
              NodeMultiset b_exp_proc;
199
81649
              for (NodeMultiset::const_iterator itmea2 = mea.begin();
200
81649
                   itmea2 != mea.end();
201
                   ++itmea2)
202
              {
203
53133
                NodeMultiset::const_iterator itmeb2 = meb.find(itmea2->first);
204
53133
                if (itmeb2 != meb.end())
205
                {
206
13999
                  unsigned min_exp = itmea2->second > itmeb2->second
207
26700
                                         ? itmeb2->second
208
26700
                                         : itmea2->second;
209
13999
                  a_exp_proc[itmea2->first] = min_exp;
210
13999
                  b_exp_proc[itmea2->first] = min_exp;
211
27998
                  Trace("nl-ext-comp") << "Common exponent : " << itmea2->first
212
13999
                                       << " : " << min_exp << std::endl;
213
                }
214
              }
215
28516
              if (!a_exp_proc.empty())
216
              {
217
13717
                setMonomialFactor(a, b, a_exp_proc);
218
13717
                setMonomialFactor(b, a, b_exp_proc);
219
              }
220
              /*
221
              if( !a_exp_proc.empty() ){
222
                //reduction based on common exponents a > 0 => ( a * b
223
              <> a * c <=> b <> c ), a < 0 => ( a * b <> a * c <=> b
224
              !<> c )  ? }else{ compareMonomial( a, a, a_exp_proc, b,
225
              b, b_exp_proc, exp, lemmas );
226
              }
227
              */
228
28516
              compareMonomial(
229
                  a, a, a_exp_proc, b, b, b_exp_proc, exp, lemmas, cmp_infers);
230
            }
231
          }
232
        }
233
      }
234
    }
235
  }
236
  // remove redundant lemmas, e.g. if a > b, b > c, a > c were
237
  // inferred, discard lemma with conclusion a > c
238
6932
  Trace("nl-ext-comp") << "Compute redundancies for " << lemmas.size()
239
3466
                       << " lemmas." << std::endl;
240
  // naive
241
6932
  std::unordered_set<Node> r_lemmas;
242
1108
  for (std::map<int, std::map<Node, std::map<Node, Node> > >::iterator itb =
243
3466
           cmp_infers.begin();
244
4574
       itb != cmp_infers.end();
245
       ++itb)
246
  {
247
1975
    for (std::map<Node, std::map<Node, Node> >::iterator itc =
248
1108
             itb->second.begin();
249
3083
         itc != itb->second.end();
250
         ++itc)
251
    {
252
4956
      for (std::map<Node, Node>::iterator itc2 = itc->second.begin();
253
4956
           itc2 != itc->second.end();
254
           ++itc2)
255
      {
256
5962
        std::map<Node, bool> visited;
257
9527
        for (std::map<Node, Node>::iterator itc3 = itc->second.begin();
258
9527
             itc3 != itc->second.end();
259
             ++itc3)
260
        {
261
6811
          if (itc3->first != itc2->first)
262
          {
263
7651
            std::vector<Node> exp;
264
3958
            if (cmp_holds(itc3->first, itc2->first, itb->second, exp, visited))
265
            {
266
265
              r_lemmas.insert(itc2->second);
267
530
              Trace("nl-ext-comp")
268
265
                  << "...inference of " << itc->first << " > " << itc2->first
269
265
                  << " was redundant." << std::endl;
270
265
              break;
271
            }
272
          }
273
        }
274
      }
275
    }
276
  }
277
6447
  for (unsigned i = 0; i < lemmas.size(); i++)
278
  {
279
2981
    if (r_lemmas.find(lemmas[i].d_node) == r_lemmas.end())
280
    {
281
2716
      d_data->d_im.addPendingLemma(lemmas[i]);
282
    }
283
  }
284
  // could only take maximal lower/minimial lower bounds?
285
3466
}
286
287
// show a <> 0 by inequalities between variables in monomial a w.r.t 0
288
37532
int MonomialCheck::compareSign(
289
    Node oa, Node a, unsigned a_index, int status, std::vector<Node>& exp)
290
{
291
75064
  Trace("nl-ext-debug") << "Process " << a << " at index " << a_index
292
37532
                        << ", status is " << status << std::endl;
293
37532
  NodeManager* nm = NodeManager::currentNM();
294
75064
  Node mvaoa = d_data->d_model.computeAbstractModelValue(oa);
295
37532
  const std::vector<Node>& vla = d_data->d_mdb.getVariableList(a);
296
37532
  if (a_index == vla.size())
297
  {
298
11710
    if (mvaoa.getConst<Rational>().sgn() != status)
299
    {
300
      Node lemma =
301
1868
          nm->mkAnd(exp).impNode(mkLit(oa, d_data->d_zero, status * 2));
302
934
      CDProof* proof = nullptr;
303
934
      if (d_data->isProofEnabled())
304
      {
305
180
        proof = d_data->getProof();
306
360
        std::vector<Node> args = exp;
307
180
        args.emplace_back(oa);
308
180
        proof->addStep(lemma, PfRule::ARITH_MULT_SIGN, {}, args);
309
      }
310
934
      d_data->d_im.addPendingLemma(lemma, InferenceId::ARITH_NL_SIGN, proof);
311
    }
312
11710
    return status;
313
  }
314
25822
  Assert(a_index < vla.size());
315
51644
  Node av = vla[a_index];
316
25822
  unsigned aexp = d_data->d_mdb.getExponent(a, av);
317
  // take current sign in model
318
51644
  Node mvaav = d_data->d_model.computeAbstractModelValue(av);
319
25822
  int sgn = mvaav.getConst<Rational>().sgn();
320
51644
  Trace("nl-ext-debug") << "Process var " << av << "^" << aexp
321
25822
                        << ", model sign = " << sgn << std::endl;
322
25822
  if (sgn == 0)
323
  {
324
2145
    if (mvaoa.getConst<Rational>().sgn() != 0)
325
    {
326
1050
      Node prem = av.eqNode(d_data->d_zero);
327
1050
      Node conc = oa.eqNode(d_data->d_zero);
328
1050
      Node lemma = prem.impNode(conc);
329
525
      CDProof* proof = nullptr;
330
525
      if (d_data->isProofEnabled())
331
      {
332
77
        proof = d_data->getProof();
333
77
        proof->addStep(conc, PfRule::MACRO_SR_PRED_INTRO, {prem}, {conc});
334
77
        proof->addStep(lemma, PfRule::SCOPE, {conc}, {prem});
335
      }
336
525
      d_data->d_im.addPendingLemma(lemma, InferenceId::ARITH_NL_SIGN, proof);
337
    }
338
2145
    return 0;
339
  }
340
23677
  if (aexp % 2 == 0)
341
  {
342
2657
    exp.push_back(av.eqNode(d_data->d_zero).negate());
343
2657
    return compareSign(oa, a, a_index + 1, status, exp);
344
  }
345
21020
  exp.push_back(nm->mkNode(sgn == 1 ? Kind::GT : Kind::LT, av, d_data->d_zero));
346
21020
  return compareSign(oa, a, a_index + 1, status * sgn, exp);
347
}
348
349
49030
bool MonomialCheck::compareMonomial(
350
    Node oa,
351
    Node a,
352
    NodeMultiset& a_exp_proc,
353
    Node ob,
354
    Node b,
355
    NodeMultiset& b_exp_proc,
356
    std::vector<Node>& exp,
357
    std::vector<SimpleTheoryLemma>& lem,
358
    std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers)
359
{
360
98060
  Trace("nl-ext-comp-debug")
361
49030
      << "Check |" << a << "| >= |" << b << "|" << std::endl;
362
49030
  unsigned pexp_size = exp.size();
363
49030
  if (compareMonomial(
364
          oa, a, 0, a_exp_proc, ob, b, 0, b_exp_proc, 0, exp, lem, cmp_infers))
365
  {
366
34590
    return true;
367
  }
368
14440
  exp.resize(pexp_size);
369
28880
  Trace("nl-ext-comp-debug")
370
14440
      << "Check |" << b << "| >= |" << a << "|" << std::endl;
371
14440
  if (compareMonomial(
372
          ob, b, 0, b_exp_proc, oa, a, 0, a_exp_proc, 0, exp, lem, cmp_infers))
373
  {
374
8248
    return true;
375
  }
376
6192
  return false;
377
}
378
379
// trying to show a ( >, = ) b   by inequalities between variables in
380
// monomials a,b
381
249566
bool MonomialCheck::compareMonomial(
382
    Node oa,
383
    Node a,
384
    unsigned a_index,
385
    NodeMultiset& a_exp_proc,
386
    Node ob,
387
    Node b,
388
    unsigned b_index,
389
    NodeMultiset& b_exp_proc,
390
    int status,
391
    std::vector<Node>& exp,
392
    std::vector<SimpleTheoryLemma>& lem,
393
    std::map<int, std::map<Node, std::map<Node, Node> > >& cmp_infers)
394
{
395
499132
  Trace("nl-ext-comp-debug")
396
249566
      << "compareMonomial " << oa << " and " << ob << ", indices = " << a_index
397
249566
      << " " << b_index << std::endl;
398
249566
  Assert(status == 0 || status == 2);
399
249566
  const std::vector<Node>& vla = d_data->d_mdb.getVariableList(a);
400
249566
  const std::vector<Node>& vlb = d_data->d_mdb.getVariableList(b);
401
249566
  if (a_index == vla.size() && b_index == vlb.size())
402
  {
403
    // finished, compare absolute value of abstract model values
404
42838
    int modelStatus = d_data->d_model.compare(oa, ob, false, true) * -2;
405
85676
    Trace("nl-ext-comp") << "...finished comparison with " << oa << " <"
406
42838
                         << status << "> " << ob
407
42838
                         << ", model status = " << modelStatus << std::endl;
408
42838
    if (status != modelStatus)
409
    {
410
5962
      Trace("nl-ext-comp-infer")
411
2981
          << "infer : " << oa << " <" << status << "> " << ob << std::endl;
412
2981
      if (status == 2)
413
      {
414
        // must state that all variables are non-zero
415
6924
        for (unsigned j = 0; j < vla.size(); j++)
416
        {
417
4429
          exp.push_back(vla[j].eqNode(d_data->d_zero).negate());
418
        }
419
      }
420
2981
      NodeManager* nm = NodeManager::currentNM();
421
      Node clem = nm->mkNode(
422
5962
          Kind::IMPLIES, nm->mkAnd(exp), mkLit(oa, ob, status, true));
423
2981
      Trace("nl-ext-comp-lemma") << "comparison lemma : " << clem << std::endl;
424
2981
      lem.emplace_back(
425
5962
          InferenceId::ARITH_NL_COMPARISON, clem, LemmaProperty::NONE, nullptr);
426
2981
      cmp_infers[status][oa][ob] = clem;
427
    }
428
42838
    return true;
429
  }
430
  // get a/b variable information
431
413456
  Node av;
432
206728
  unsigned aexp = 0;
433
206728
  unsigned avo = 0;
434
206728
  if (a_index < vla.size())
435
  {
436
177212
    av = vla[a_index];
437
177212
    unsigned aexpTotal = d_data->d_mdb.getExponent(a, av);
438
177212
    Assert(a_exp_proc[av] <= aexpTotal);
439
177212
    aexp = aexpTotal - a_exp_proc[av];
440
177212
    if (aexp == 0)
441
    {
442
122544
      return compareMonomial(oa,
443
                             a,
444
                             a_index + 1,
445
                             a_exp_proc,
446
                             ob,
447
                             b,
448
                             b_index,
449
                             b_exp_proc,
450
                             status,
451
                             exp,
452
                             lem,
453
61272
                             cmp_infers);
454
    }
455
115940
    Assert(d_order_vars.find(av) != d_order_vars.end());
456
115940
    avo = d_order_vars[av];
457
  }
458
290912
  Node bv;
459
145456
  unsigned bexp = 0;
460
145456
  unsigned bvo = 0;
461
145456
  if (b_index < vlb.size())
462
  {
463
116469
    bv = vlb[b_index];
464
116469
    unsigned bexpTotal = d_data->d_mdb.getExponent(b, bv);
465
116469
    Assert(b_exp_proc[bv] <= bexpTotal);
466
116469
    bexp = bexpTotal - b_exp_proc[bv];
467
116469
    if (bexp == 0)
468
    {
469
118038
      return compareMonomial(oa,
470
                             a,
471
                             a_index,
472
                             a_exp_proc,
473
                             ob,
474
                             b,
475
                             b_index + 1,
476
                             b_exp_proc,
477
                             status,
478
                             exp,
479
                             lem,
480
59019
                             cmp_infers);
481
    }
482
57450
    Assert(d_order_vars.find(bv) != d_order_vars.end());
483
57450
    bvo = d_order_vars[bv];
484
  }
485
  // get "one" information
486
86437
  Assert(d_order_vars.find(d_data->d_one) != d_order_vars.end());
487
86437
  unsigned ovo = d_order_vars[d_data->d_one];
488
172874
  Trace("nl-ext-comp-debug") << "....vars : " << av << "^" << aexp << " " << bv
489
86437
                             << "^" << bexp << std::endl;
490
491
  //--- cases
492
86437
  if (av.isNull())
493
  {
494
3488
    if (bvo <= ovo)
495
    {
496
2019
      Trace("nl-ext-comp-debug") << "...take leading " << bv << std::endl;
497
      // can multiply b by <=1
498
2019
      exp.push_back(mkLit(d_data->d_one, bv, bvo == ovo ? 0 : 2, true));
499
4038
      return compareMonomial(oa,
500
                             a,
501
                             a_index,
502
                             a_exp_proc,
503
                             ob,
504
                             b,
505
                             b_index + 1,
506
                             b_exp_proc,
507
                             bvo == ovo ? status : 2,
508
                             exp,
509
                             lem,
510
2019
                             cmp_infers);
511
    }
512
2938
    Trace("nl-ext-comp-debug")
513
1469
        << "...failure, unmatched |b|>1 component." << std::endl;
514
1469
    return false;
515
  }
516
82949
  else if (bv.isNull())
517
  {
518
28987
    if (avo >= ovo)
519
    {
520
26672
      Trace("nl-ext-comp-debug") << "...take leading " << av << std::endl;
521
      // can multiply a by >=1
522
26672
      exp.push_back(mkLit(av, d_data->d_one, avo == ovo ? 0 : 2, true));
523
53344
      return compareMonomial(oa,
524
                             a,
525
                             a_index + 1,
526
                             a_exp_proc,
527
                             ob,
528
                             b,
529
                             b_index,
530
                             b_exp_proc,
531
                             avo == ovo ? status : 2,
532
                             exp,
533
                             lem,
534
26672
                             cmp_infers);
535
    }
536
4630
    Trace("nl-ext-comp-debug")
537
2315
        << "...failure, unmatched |a|<1 component." << std::endl;
538
2315
    return false;
539
  }
540
53962
  Assert(!av.isNull() && !bv.isNull());
541
53962
  if (avo >= bvo)
542
  {
543
37006
    if (bvo < ovo && avo >= ovo)
544
    {
545
272
      Trace("nl-ext-comp-debug") << "...take leading " << av << std::endl;
546
      // do avo>=1 instead
547
272
      exp.push_back(mkLit(av, d_data->d_one, avo == ovo ? 0 : 2, true));
548
544
      return compareMonomial(oa,
549
                             a,
550
                             a_index + 1,
551
                             a_exp_proc,
552
                             ob,
553
                             b,
554
                             b_index,
555
                             b_exp_proc,
556
                             avo == ovo ? status : 2,
557
                             exp,
558
                             lem,
559
272
                             cmp_infers);
560
    }
561
36734
    unsigned min_exp = aexp > bexp ? bexp : aexp;
562
36734
    a_exp_proc[av] += min_exp;
563
36734
    b_exp_proc[bv] += min_exp;
564
73468
    Trace("nl-ext-comp-debug") << "...take leading " << min_exp << " from "
565
36734
                               << av << " and " << bv << std::endl;
566
36734
    exp.push_back(mkLit(av, bv, avo == bvo ? 0 : 2, true));
567
73468
    bool ret = compareMonomial(oa,
568
                               a,
569
                               a_index,
570
                               a_exp_proc,
571
                               ob,
572
                               b,
573
                               b_index,
574
                               b_exp_proc,
575
                               avo == bvo ? status : 2,
576
                               exp,
577
                               lem,
578
36734
                               cmp_infers);
579
36734
    a_exp_proc[av] -= min_exp;
580
36734
    b_exp_proc[bv] -= min_exp;
581
36734
    return ret;
582
  }
583
16956
  if (bvo <= ovo)
584
  {
585
108
    Trace("nl-ext-comp-debug") << "...take leading " << bv << std::endl;
586
    // try multiply b <= 1
587
108
    exp.push_back(mkLit(d_data->d_one, bv, bvo == ovo ? 0 : 2, true));
588
216
    return compareMonomial(oa,
589
                           a,
590
                           a_index,
591
                           a_exp_proc,
592
                           ob,
593
                           b,
594
                           b_index + 1,
595
                           b_exp_proc,
596
                           bvo == ovo ? status : 2,
597
                           exp,
598
                           lem,
599
108
                           cmp_infers);
600
  }
601
33696
  Trace("nl-ext-comp-debug")
602
16848
      << "...failure, leading |b|>|a|>1 component." << std::endl;
603
16848
  return false;
604
}
605
606
5772
bool MonomialCheck::cmp_holds(Node x,
607
                              Node y,
608
                              std::map<Node, std::map<Node, Node> >& cmp_infers,
609
                              std::vector<Node>& exp,
610
                              std::map<Node, bool>& visited)
611
{
612
5772
  if (x == y)
613
  {
614
265
    return true;
615
  }
616
5507
  else if (visited.find(x) != visited.end())
617
  {
618
1312
    return false;
619
  }
620
4195
  visited[x] = true;
621
4195
  std::map<Node, std::map<Node, Node> >::iterator it = cmp_infers.find(x);
622
4195
  if (it != cmp_infers.end())
623
  {
624
2514
    for (std::map<Node, Node>::iterator itc = it->second.begin();
625
2514
         itc != it->second.end();
626
         ++itc)
627
    {
628
1814
      exp.push_back(itc->second);
629
1814
      if (cmp_holds(itc->first, y, cmp_infers, exp, visited))
630
      {
631
277
        return true;
632
      }
633
1537
      exp.pop_back();
634
    }
635
  }
636
3918
  return false;
637
}
638
639
1608
void MonomialCheck::assignOrderIds(std::vector<Node>& vars,
640
                                   NodeMultiset& order,
641
                                   bool isConcrete,
642
                                   bool isAbsolute)
643
{
644
1608
  SortNlModel smv;
645
1608
  smv.d_nlm = &d_data->d_model;
646
1608
  smv.d_isConcrete = isConcrete;
647
1608
  smv.d_isAbsolute = isAbsolute;
648
1608
  smv.d_reverse_order = false;
649
1608
  std::sort(vars.begin(), vars.end(), smv);
650
651
1608
  order.clear();
652
  // assign ordering id's
653
1608
  unsigned counter = 0;
654
1608
  unsigned order_index = isConcrete ? 0 : 1;
655
3216
  Node prev;
656
9532
  for (unsigned j = 0; j < vars.size(); j++)
657
  {
658
15848
    Node x = vars[j];
659
15848
    Node v = d_data->d_model.computeModelValue(x, isConcrete);
660
7924
    if (!v.isConst())
661
    {
662
      Trace("nl-ext-mvo") << "..do not assign order to " << x << " : " << v
663
                          << std::endl;
664
      // don't assign for non-constant values (transcendental function apps)
665
      break;
666
    }
667
7924
    Trace("nl-ext-mvo") << "  order " << x << " : " << v << std::endl;
668
7924
    if (v != prev)
669
    {
670
      // builtin points
671
      bool success;
672
8527
      do
673
      {
674
8527
        success = false;
675
8527
        if (order_index < d_order_points.size())
676
        {
677
3819
          Node vv = d_data->d_model.computeModelValue(
678
7638
              d_order_points[order_index], isConcrete);
679
3819
          if (d_data->d_model.compareValue(v, vv, isAbsolute) <= 0)
680
          {
681
2879
            counter++;
682
5758
            Trace("nl-ext-mvo") << "O[" << d_order_points[order_index]
683
2879
                                << "] = " << counter << std::endl;
684
2879
            order[d_order_points[order_index]] = counter;
685
2879
            prev = vv;
686
2879
            order_index++;
687
2879
            success = true;
688
          }
689
        }
690
      } while (success);
691
    }
692
7924
    if (prev.isNull() || d_data->d_model.compareValue(v, prev, isAbsolute) != 0)
693
    {
694
3864
      counter++;
695
    }
696
7924
    Trace("nl-ext-mvo") << "O[" << x << "] = " << counter << std::endl;
697
7924
    order[x] = counter;
698
7924
    prev = v;
699
  }
700
2282
  while (order_index < d_order_points.size())
701
  {
702
337
    counter++;
703
674
    Trace("nl-ext-mvo") << "O[" << d_order_points[order_index]
704
337
                        << "] = " << counter << std::endl;
705
337
    order[d_order_points[order_index]] = counter;
706
337
    order_index++;
707
  }
708
1608
}
709
70123
Node MonomialCheck::mkLit(Node a, Node b, int status, bool isAbsolute) const
710
{
711
70123
  if (status == 0)
712
  {
713
13160
    Node a_eq_b = a.eqNode(b);
714
6580
    if (!isAbsolute)
715
    {
716
      return a_eq_b;
717
    }
718
13160
    Node negate_b = NodeManager::currentNM()->mkNode(Kind::UMINUS, b);
719
6580
    return a_eq_b.orNode(a.eqNode(negate_b));
720
  }
721
63543
  else if (status < 0)
722
  {
723
403
    return mkLit(b, a, -status);
724
  }
725
63140
  Assert(status == 1 || status == 2);
726
63140
  NodeManager* nm = NodeManager::currentNM();
727
63140
  Kind greater_op = status == 1 ? Kind::GEQ : Kind::GT;
728
63140
  if (!isAbsolute)
729
  {
730
934
    return nm->mkNode(greater_op, a, b);
731
  }
732
  // return nm->mkNode( greater_op, mkAbs( a ), mkAbs( b ) );
733
124412
  Node a_is_nonnegative = nm->mkNode(Kind::GEQ, a, d_data->d_zero);
734
124412
  Node b_is_nonnegative = nm->mkNode(Kind::GEQ, b, d_data->d_zero);
735
124412
  Node negate_a = nm->mkNode(Kind::UMINUS, a);
736
124412
  Node negate_b = nm->mkNode(Kind::UMINUS, b);
737
  return a_is_nonnegative.iteNode(
738
124412
      b_is_nonnegative.iteNode(nm->mkNode(greater_op, a, b),
739
124412
                               nm->mkNode(greater_op, a, negate_b)),
740
124412
      b_is_nonnegative.iteNode(nm->mkNode(greater_op, negate_a, b),
741
186618
                               nm->mkNode(greater_op, negate_a, negate_b)));
742
}
743
744
50568
void MonomialCheck::setMonomialFactor(Node a,
745
                                      Node b,
746
                                      const NodeMultiset& common)
747
{
748
  // Could not tell if this was being inserted intentionally or not.
749
50568
  std::map<Node, Node>& mono_diff_a = d_data->d_mono_diff[a];
750
50568
  if (mono_diff_a.find(b) == mono_diff_a.end())
751
  {
752
12300
    Trace("nl-ext-mono-factor")
753
6150
        << "Set monomial factor for " << a << "/" << b << std::endl;
754
6150
    mono_diff_a[b] = d_data->d_mdb.mkMonomialRemFactor(a, common);
755
  }
756
50568
}
757
758
}  // namespace nl
759
}  // namespace arith
760
}  // namespace theory
761
28191
}  // namespace cvc5