GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/booleans/proof_checker.cpp Lines: 419 534 78.5 %
Date: 2021-09-10 Branches: 932 3330 28.0 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Haniel Barbosa, Andrew Reynolds, Mathias Preiner
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
 * Implementation of equality proof checker.
14
 */
15
16
#include "theory/booleans/proof_checker.h"
17
#include "expr/skolem_manager.h"
18
#include "theory/rewriter.h"
19
20
namespace cvc5 {
21
namespace theory {
22
namespace booleans {
23
24
3781
void BoolProofRuleChecker::registerTo(ProofChecker* pc)
25
{
26
3781
  pc->registerChecker(PfRule::SPLIT, this);
27
3781
  pc->registerChecker(PfRule::RESOLUTION, this);
28
3781
  pc->registerChecker(PfRule::CHAIN_RESOLUTION, this);
29
3781
  pc->registerTrustedChecker(PfRule::MACRO_RESOLUTION_TRUST, this, 3);
30
3781
  pc->registerChecker(PfRule::MACRO_RESOLUTION, this);
31
3781
  pc->registerChecker(PfRule::FACTORING, this);
32
3781
  pc->registerChecker(PfRule::REORDERING, this);
33
3781
  pc->registerChecker(PfRule::EQ_RESOLVE, this);
34
3781
  pc->registerChecker(PfRule::MODUS_PONENS, this);
35
3781
  pc->registerChecker(PfRule::NOT_NOT_ELIM, this);
36
3781
  pc->registerChecker(PfRule::CONTRA, this);
37
3781
  pc->registerChecker(PfRule::AND_ELIM, this);
38
3781
  pc->registerChecker(PfRule::AND_INTRO, this);
39
3781
  pc->registerChecker(PfRule::NOT_OR_ELIM, this);
40
3781
  pc->registerChecker(PfRule::IMPLIES_ELIM, this);
41
3781
  pc->registerChecker(PfRule::NOT_IMPLIES_ELIM1, this);
42
3781
  pc->registerChecker(PfRule::NOT_IMPLIES_ELIM2, this);
43
3781
  pc->registerChecker(PfRule::EQUIV_ELIM1, this);
44
3781
  pc->registerChecker(PfRule::EQUIV_ELIM2, this);
45
3781
  pc->registerChecker(PfRule::NOT_EQUIV_ELIM1, this);
46
3781
  pc->registerChecker(PfRule::NOT_EQUIV_ELIM2, this);
47
3781
  pc->registerChecker(PfRule::XOR_ELIM1, this);
48
3781
  pc->registerChecker(PfRule::XOR_ELIM2, this);
49
3781
  pc->registerChecker(PfRule::NOT_XOR_ELIM1, this);
50
3781
  pc->registerChecker(PfRule::NOT_XOR_ELIM2, this);
51
3781
  pc->registerChecker(PfRule::ITE_ELIM1, this);
52
3781
  pc->registerChecker(PfRule::ITE_ELIM2, this);
53
3781
  pc->registerChecker(PfRule::NOT_ITE_ELIM1, this);
54
3781
  pc->registerChecker(PfRule::NOT_ITE_ELIM2, this);
55
3781
  pc->registerChecker(PfRule::NOT_AND, this);
56
3781
  pc->registerChecker(PfRule::CNF_AND_POS, this);
57
3781
  pc->registerChecker(PfRule::CNF_AND_NEG, this);
58
3781
  pc->registerChecker(PfRule::CNF_OR_POS, this);
59
3781
  pc->registerChecker(PfRule::CNF_OR_NEG, this);
60
3781
  pc->registerChecker(PfRule::CNF_IMPLIES_POS, this);
61
3781
  pc->registerChecker(PfRule::CNF_IMPLIES_NEG1, this);
62
3781
  pc->registerChecker(PfRule::CNF_IMPLIES_NEG2, this);
63
3781
  pc->registerChecker(PfRule::CNF_EQUIV_POS1, this);
64
3781
  pc->registerChecker(PfRule::CNF_EQUIV_POS2, this);
65
3781
  pc->registerChecker(PfRule::CNF_EQUIV_NEG1, this);
66
3781
  pc->registerChecker(PfRule::CNF_EQUIV_NEG2, this);
67
3781
  pc->registerChecker(PfRule::CNF_XOR_POS1, this);
68
3781
  pc->registerChecker(PfRule::CNF_XOR_POS2, this);
69
3781
  pc->registerChecker(PfRule::CNF_XOR_NEG1, this);
70
3781
  pc->registerChecker(PfRule::CNF_XOR_NEG2, this);
71
3781
  pc->registerChecker(PfRule::CNF_ITE_POS1, this);
72
3781
  pc->registerChecker(PfRule::CNF_ITE_POS2, this);
73
3781
  pc->registerChecker(PfRule::CNF_ITE_POS3, this);
74
3781
  pc->registerChecker(PfRule::CNF_ITE_NEG1, this);
75
3781
  pc->registerChecker(PfRule::CNF_ITE_NEG2, this);
76
3781
  pc->registerChecker(PfRule::CNF_ITE_NEG3, this);
77
3781
  pc->registerTrustedChecker(PfRule::SAT_REFUTATION, this, 1);
78
3781
}
79
80
3854141
Node BoolProofRuleChecker::checkInternal(PfRule id,
81
                                         const std::vector<Node>& children,
82
                                         const std::vector<Node>& args)
83
{
84
3854141
  if (id == PfRule::RESOLUTION)
85
  {
86
19020
    Assert(children.size() == 2);
87
19020
    Assert(args.size() == 2);
88
19020
    NodeManager* nm = NodeManager::currentNM();
89
38040
    std::vector<Node> disjuncts;
90
38040
    Node pivots[2];
91
19020
    if (args[0] == nm->mkConst(true))
92
    {
93
16761
      pivots[0] = args[1];
94
16761
      pivots[1] = args[1].notNode();
95
    }
96
    else
97
    {
98
2259
      Assert(args[0] == nm->mkConst(false));
99
2259
      pivots[0] = args[1].notNode();
100
2259
      pivots[1] = args[1];
101
    }
102
57060
    for (unsigned i = 0; i < 2; ++i)
103
    {
104
      // determine whether the clause is a singleton for effects of resolution,
105
      // which is the case if it's not an OR node or it is an OR node but it is
106
      // equal to the pivot
107
76080
      std::vector<Node> lits;
108
38040
      if (children[i].getKind() == kind::OR && pivots[i] != children[i])
109
      {
110
34790
        lits.insert(lits.end(), children[i].begin(), children[i].end());
111
      }
112
      else
113
      {
114
3250
        lits.push_back(children[i]);
115
      }
116
205057
      for (unsigned j = 0, size = lits.size(); j < size; ++j)
117
      {
118
167017
        if (pivots[i] != lits[j])
119
        {
120
128977
          disjuncts.push_back(lits[j]);
121
        }
122
        else
123
        {
124
          // just eliminate first occurrence
125
38040
          pivots[i] = Node::null();
126
        }
127
      }
128
    }
129
19020
    return disjuncts.empty()
130
               ? nm->mkConst(false)
131
22270
               : disjuncts.size() == 1 ? disjuncts[0]
132
41290
                                       : nm->mkNode(kind::OR, disjuncts);
133
  }
134
3835121
  if (id == PfRule::FACTORING)
135
  {
136
466402
    Assert(children.size() == 1);
137
466402
    Assert(args.empty());
138
466402
    if (children[0].getKind() != kind::OR)
139
    {
140
      return Node::null();
141
    }
142
    // remove duplicates while keeping the order of children
143
932804
    std::unordered_set<TNode> clauseSet;
144
932804
    std::vector<Node> disjuncts;
145
466402
    unsigned size = children[0].getNumChildren();
146
9233171
    for (unsigned i = 0; i < size; ++i)
147
    {
148
8766769
      if (clauseSet.count(children[0][i]))
149
      {
150
2830381
        continue;
151
      }
152
5936388
      disjuncts.push_back(children[0][i]);
153
5936388
      clauseSet.insert(children[0][i]);
154
    }
155
466402
    if (disjuncts.size() == size)
156
    {
157
      return Node::null();
158
    }
159
466402
    NodeManager* nm = NodeManager::currentNM();
160
466402
    return nm->mkOr(disjuncts);
161
  }
162
3368719
  if (id == PfRule::REORDERING)
163
  {
164
1155062
    Assert(children.size() == 1);
165
1155062
    Assert(args.size() == 1);
166
2310124
    std::unordered_set<Node> clauseSet1, clauseSet2;
167
1155062
    if (children[0].getKind() == kind::OR)
168
    {
169
1155062
      clauseSet1.insert(children[0].begin(), children[0].end());
170
    }
171
    else
172
    {
173
      clauseSet1.insert(children[0]);
174
    }
175
1155062
    if (args[0].getKind() == kind::OR)
176
    {
177
1155062
      clauseSet2.insert(args[0].begin(), args[0].end());
178
    }
179
    else
180
    {
181
      clauseSet2.insert(args[0]);
182
    }
183
1155062
    if (clauseSet1 != clauseSet2)
184
    {
185
      Trace("bool-pfcheck") << id << ": clause set1: " << clauseSet1 << "\n"
186
                            << id << ": clause set2: " << clauseSet2 << "\n";
187
      return Node::null();
188
    }
189
1155062
    return args[0];
190
  }
191
2213657
  if (id == PfRule::CHAIN_RESOLUTION)
192
  {
193
623542
    Assert(children.size() > 1);
194
623542
    Assert(args.size() == 2 * (children.size() - 1));
195
623542
    Trace("bool-pfcheck") << "chain_res:\n" << push;
196
623542
    NodeManager* nm = NodeManager::currentNM();
197
1247084
    Node trueNode = nm->mkConst(true);
198
1247084
    Node falseNode = nm->mkConst(false);
199
1247084
    std::vector<Node> clauseNodes;
200
    // literals to be removed from the virtual lhs clause of the resolution
201
1247084
    std::unordered_map<Node, unsigned> lhsElim;
202
4455054
    for (std::size_t i = 0, argsSize = args.size(); i < argsSize; i = i + 2)
203
    {
204
      // whether pivot should occur as is or negated depends on the polarity of
205
      // each step in the chain
206
3831512
      if (args[i] == trueNode)
207
      {
208
1945424
        lhsElim[args[i + 1]]++;
209
      }
210
      else
211
      {
212
1886088
        Assert(args[i] == falseNode);
213
1886088
        lhsElim[args[i + 1].notNode()]++;
214
      }
215
    }
216
623542
    if (Trace.isOn("bool-pfcheck"))
217
    {
218
      Trace("bool-pfcheck")
219
          << "Original elimination multiset for lhs clause:\n";
220
      for (const auto& pair : lhsElim)
221
      {
222
        Trace("bool-pfcheck")
223
            << "\t- " << pair.first << " {" << pair.second << "}\n";
224
      }
225
    }
226
5078596
    for (std::size_t i = 0, childrenSize = children.size(); i < childrenSize;
227
         ++i)
228
    {
229
      // literal to be removed from rhs clause. They will be negated
230
8910108
      Node rhsElim = Node::null();
231
4455054
      if (Trace.isOn("bool-pfcheck"))
232
      {
233
        Trace("bool-pfcheck") << i << ": current lhsElim:\n";
234
        for (const auto& pair : lhsElim)
235
        {
236
          Trace("bool-pfcheck")
237
              << "\t- " << pair.first << " {" << pair.second << "}\n";
238
        }
239
      }
240
4455054
      if (i > 0)
241
      {
242
3831512
        std::size_t index = 2 * (i - 1);
243
5717600
        rhsElim = args[index] == trueNode ? args[index + 1].notNode()
244
1886088
                                          : args[index + 1];
245
3831512
        Trace("bool-pfcheck") << i << ": rhs elim: " << rhsElim << "\n";
246
      }
247
      // Only add to conclusion nodes that are not in elimination set. First get
248
      // the nodes.
249
      //
250
      // Since a Node cannot hold an OR with a single child we need to
251
      // disambiguate singleton clauses that are OR nodes from non-singleton
252
      // clauses (i.e. unit clauses in the SAT solver).
253
      //
254
      // If the child is not an OR, it is a singleton clause and we take the
255
      // child itself as the clause. Otherwise the child can only be a singleton
256
      // clause if the child itself is used as a resolution literal, i.e. if the
257
      // child is in lhsElim or is equal to rhsElim (which means that the
258
      // negation of the child is in lhsElim).
259
8910108
      std::vector<Node> lits;
260
12026910
      if (children[i].getKind() == kind::OR && lhsElim.count(children[i]) == 0
261
7571856
          && children[i] != rhsElim)
262
      {
263
3102463
        lits.insert(lits.end(), children[i].begin(), children[i].end());
264
      }
265
      else
266
      {
267
1352591
        lits.push_back(children[i]);
268
      }
269
4455054
      Trace("bool-pfcheck") << i << ": clause lits: " << lits << "\n";
270
8910108
      std::vector<Node> added;
271
23598660
      for (std::size_t j = 0, size = lits.size(); j < size; ++j)
272
      {
273
22975118
        if (lits[j] == rhsElim)
274
        {
275
3831512
          rhsElim = Node::null();
276
3831512
          continue;
277
        }
278
15312094
        auto it = lhsElim.find(lits[j]);
279
15312094
        if (it == lhsElim.end())
280
        {
281
11480582
          clauseNodes.push_back(lits[j]);
282
11480582
          added.push_back(lits[j]);
283
        }
284
        else
285
        {
286
          // remove occurrence
287
3831512
          it->second--;
288
3831512
          if (it->second == 0)
289
          {
290
3578760
            lhsElim.erase(it);
291
          }
292
        }
293
      }
294
4455054
      Trace("bool-pfcheck") << i << ": added lits: " << added << "\n\n";
295
    }
296
623542
    Trace("bool-pfcheck") << "clause: " << clauseNodes << "\n" << pop;
297
623542
    return nm->mkOr(clauseNodes);
298
  }
299
1590115
  if (id == PfRule::MACRO_RESOLUTION_TRUST)
300
  {
301
96364
    Assert(children.size() > 1);
302
96364
    Assert(args.size() == 2 * (children.size() - 1) + 1);
303
96364
    return args[0];
304
  }
305
1493751
  if (id == PfRule::MACRO_RESOLUTION)
306
  {
307
    Assert(children.size() > 1);
308
    Assert(args.size() == 2 * (children.size() - 1) + 1);
309
    Trace("bool-pfcheck") << "macro_res: " << args[0] << "\n" << push;
310
    NodeManager* nm = NodeManager::currentNM();
311
    Node trueNode = nm->mkConst(true);
312
    Node falseNode = nm->mkConst(false);
313
    std::vector<Node> clauseNodes;
314
    for (std::size_t i = 0, childrenSize = children.size(); i < childrenSize;
315
         ++i)
316
    {
317
      std::unordered_set<Node> elim;
318
      // literals to be removed from "first" clause
319
      if (i < childrenSize - 1)
320
      {
321
        for (std::size_t j = (2 * i) + 1, argsSize = args.size(); j < argsSize;
322
             j = j + 2)
323
        {
324
          // whether pivot should occur as is or negated depends on the polarity
325
          // of each step in the macro
326
          if (args[j] == trueNode)
327
          {
328
            elim.insert(args[j + 1]);
329
          }
330
          else
331
          {
332
            Assert(args[j] == falseNode);
333
            elim.insert(args[j + 1].notNode());
334
          }
335
        }
336
      }
337
      // literal to be removed from "second" clause. They will be negated
338
      if (i > 0)
339
      {
340
        std::size_t index = 2 * (i - 1) + 1;
341
        Node pivot = args[index] == trueNode ? args[index + 1].notNode()
342
                                             : args[index + 1];
343
        elim.insert(pivot);
344
      }
345
      Trace("bool-pfcheck") << i << ": elimination set: " << elim << "\n";
346
      // only add to conclusion nodes that are not in elimination set. First get
347
      // the nodes.
348
      //
349
      // Since a Node cannot hold an OR with a single child we need to
350
      // disambiguate singleton clauses that are OR nodes from non-singleton
351
      // clauses (i.e. unit clauses in the SAT solver).
352
      //
353
      // If the child is not an OR, it is a singleton clause and we take the
354
      // child itself as the clause. Otherwise the child can only be a singleton
355
      // clause if the child itself is used as a resolution literal, i.e. if the
356
      // child is in lhsElim or is equal to rhsElim (which means that the
357
      // negation of the child is in lhsElim).
358
      std::vector<Node> lits;
359
      if (children[i].getKind() == kind::OR && !elim.count(children[i]))
360
      {
361
        lits.insert(lits.end(), children[i].begin(), children[i].end());
362
      }
363
      else
364
      {
365
        lits.push_back(children[i]);
366
      }
367
      Trace("bool-pfcheck") << i << ": clause lits: " << lits << "\n";
368
      std::vector<Node> added;
369
      for (std::size_t j = 0, size = lits.size(); j < size; ++j)
370
      {
371
        // only add if literal does not occur in elimination set
372
        if (elim.count(lits[j]) == 0)
373
        {
374
          clauseNodes.push_back(lits[j]);
375
          added.push_back(lits[j]);
376
          // eliminate duplicates
377
          elim.insert(lits[j]);
378
        }
379
      }
380
      Trace("bool-pfcheck") << i << ": added lits: " << added << "\n\n";
381
    }
382
    Trace("bool-pfcheck") << "clause: " << clauseNodes << "\n";
383
    // check that set representation is the same as of the given conclusion
384
    std::unordered_set<Node> clauseComputed{clauseNodes.begin(),
385
                                            clauseNodes.end()};
386
    Trace("bool-pfcheck") << "clauseSet: " << clauseComputed << "\n" << pop;
387
    if (clauseComputed.empty())
388
    {
389
      // conclusion differ
390
      if (args[0] != falseNode)
391
      {
392
        return Node::null();
393
      }
394
      return args[0];
395
    }
396
    if (clauseComputed.size() == 1)
397
    {
398
      // conclusion differ
399
      if (args[0] != *clauseComputed.begin())
400
      {
401
        return Node::null();
402
      }
403
      return args[0];
404
    }
405
    // At this point, should amount to them differing only on order. So the
406
    // original result can't be a singleton clause
407
    if (args[0].getKind() != kind::OR
408
        || clauseComputed.size() != args[0].getNumChildren())
409
    {
410
      return Node::null();
411
    }
412
    std::unordered_set<Node> clauseGiven{args[0].begin(), args[0].end()};
413
    return clauseComputed == clauseGiven ? args[0] : Node::null();
414
  }
415
1493751
  if (id == PfRule::SPLIT)
416
  {
417
12
    Assert(children.empty());
418
12
    Assert(args.size() == 1);
419
    return NodeManager::currentNM()->mkNode(
420
12
        kind::OR, args[0], args[0].notNode());
421
  }
422
1493739
  if (id == PfRule::CONTRA)
423
  {
424
13511
    Assert(children.size() == 2);
425
13511
    if (children[1].getKind() == Kind::NOT && children[0] == children[1][0])
426
    {
427
13511
      return NodeManager::currentNM()->mkConst(false);
428
    }
429
    return Node::null();
430
  }
431
1480228
  if (id == PfRule::EQ_RESOLVE)
432
  {
433
370713
    Assert(children.size() == 2);
434
370713
    Assert(args.empty());
435
370713
    if (children[1].getKind() != kind::EQUAL || children[0] != children[1][0])
436
    {
437
      return Node::null();
438
    }
439
370713
    return children[1][1];
440
  }
441
1109515
  if (id == PfRule::MODUS_PONENS)
442
  {
443
66509
    Assert(children.size() == 2);
444
66509
    Assert(args.empty());
445
66509
    if (children[1].getKind() != kind::IMPLIES || children[0] != children[1][0])
446
    {
447
      return Node::null();
448
    }
449
66509
    return children[1][1];
450
  }
451
1043006
  if (id == PfRule::NOT_NOT_ELIM)
452
  {
453
2960
    Assert(children.size() == 1);
454
2960
    Assert(args.empty());
455
2960
    if (children[0].getKind() != kind::NOT || children[0][0].getKind() != kind::NOT)
456
    {
457
      return Node::null();
458
    }
459
2960
    return children[0][0][0];
460
  }
461
  // natural deduction rules
462
1040046
  if (id == PfRule::AND_ELIM)
463
  {
464
747662
    Assert(children.size() == 1);
465
747662
    Assert(args.size() == 1);
466
    uint32_t i;
467
747662
    if (children[0].getKind() != kind::AND || !getUInt32(args[0], i))
468
    {
469
      return Node::null();
470
    }
471
747662
    if (i >= children[0].getNumChildren())
472
    {
473
      return Node::null();
474
    }
475
747662
    return children[0][i];
476
  }
477
292384
  if (id == PfRule::AND_INTRO)
478
  {
479
72201
    Assert(children.size() >= 1);
480
72201
    return children.size() == 1
481
               ? children[0]
482
72201
               : NodeManager::currentNM()->mkNode(kind::AND, children);
483
  }
484
220183
  if (id == PfRule::NOT_OR_ELIM)
485
  {
486
1820
    Assert(children.size() == 1);
487
1820
    Assert(args.size() == 1);
488
    uint32_t i;
489
3640
    if (children[0].getKind() != kind::NOT
490
3640
        || children[0][0].getKind() != kind::OR || !getUInt32(args[0], i))
491
    {
492
      return Node::null();
493
    }
494
1820
    if (i >= children[0][0].getNumChildren())
495
    {
496
      return Node::null();
497
    }
498
1820
    return children[0][0][i].notNode();
499
  }
500
218363
  if (id == PfRule::IMPLIES_ELIM)
501
  {
502
37339
    Assert(children.size() == 1);
503
37339
    Assert(args.empty());
504
37339
    if (children[0].getKind() != kind::IMPLIES)
505
    {
506
      return Node::null();
507
    }
508
    return NodeManager::currentNM()->mkNode(
509
37339
        kind::OR, children[0][0].notNode(), children[0][1]);
510
  }
511
181024
  if (id == PfRule::NOT_IMPLIES_ELIM1)
512
  {
513
700
    Assert(children.size() == 1);
514
700
    Assert(args.empty());
515
1400
    if (children[0].getKind() != kind::NOT
516
1400
        || children[0][0].getKind() != kind::IMPLIES)
517
    {
518
      return Node::null();
519
    }
520
700
    return children[0][0][0];
521
  }
522
180324
  if (id == PfRule::NOT_IMPLIES_ELIM2)
523
  {
524
393
    Assert(children.size() == 1);
525
393
    Assert(args.empty());
526
786
    if (children[0].getKind() != kind::NOT
527
786
        || children[0][0].getKind() != kind::IMPLIES)
528
    {
529
      return Node::null();
530
    }
531
393
    return children[0][0][1].notNode();
532
  }
533
179931
  if (id == PfRule::EQUIV_ELIM1)
534
  {
535
18629
    Assert(children.size() == 1);
536
18629
    Assert(args.empty());
537
18629
    if (children[0].getKind() != kind::EQUAL)
538
    {
539
      return Node::null();
540
    }
541
    return NodeManager::currentNM()->mkNode(
542
18629
        kind::OR, children[0][0].notNode(), children[0][1]);
543
  }
544
161302
  if (id == PfRule::EQUIV_ELIM2)
545
  {
546
14609
    Assert(children.size() == 1);
547
14609
    Assert(args.empty());
548
14609
    if (children[0].getKind() != kind::EQUAL)
549
    {
550
      return Node::null();
551
    }
552
    return NodeManager::currentNM()->mkNode(
553
14609
        kind::OR, children[0][0], children[0][1].notNode());
554
  }
555
146693
  if (id == PfRule::NOT_EQUIV_ELIM1)
556
  {
557
278
    Assert(children.size() == 1);
558
278
    Assert(args.empty());
559
556
    if (children[0].getKind() != kind::NOT
560
556
        || children[0][0].getKind() != kind::EQUAL)
561
    {
562
      return Node::null();
563
    }
564
    return NodeManager::currentNM()->mkNode(
565
278
        kind::OR, children[0][0][0], children[0][0][1]);
566
  }
567
146415
  if (id == PfRule::NOT_EQUIV_ELIM2)
568
  {
569
198
    Assert(children.size() == 1);
570
198
    Assert(args.empty());
571
396
    if (children[0].getKind() != kind::NOT
572
396
        || children[0][0].getKind() != kind::EQUAL)
573
    {
574
      return Node::null();
575
    }
576
    return NodeManager::currentNM()->mkNode(
577
198
        kind::OR, children[0][0][0].notNode(), children[0][0][1].notNode());
578
  }
579
146217
  if (id == PfRule::XOR_ELIM1)
580
  {
581
22
    Assert(children.size() == 1);
582
22
    Assert(args.empty());
583
22
    if (children[0].getKind() != kind::XOR)
584
    {
585
      return Node::null();
586
    }
587
    return NodeManager::currentNM()->mkNode(
588
22
        kind::OR, children[0][0], children[0][1]);
589
  }
590
146195
  if (id == PfRule::XOR_ELIM2)
591
  {
592
34
    Assert(children.size() == 1);
593
34
    Assert(args.empty());
594
34
    if (children[0].getKind() != kind::XOR)
595
    {
596
      return Node::null();
597
    }
598
    return NodeManager::currentNM()->mkNode(
599
34
        kind::OR, children[0][0].notNode(), children[0][1].notNode());
600
  }
601
146161
  if (id == PfRule::NOT_XOR_ELIM1)
602
  {
603
5
    Assert(children.size() == 1);
604
5
    Assert(args.empty());
605
10
    if (children[0].getKind() != kind::NOT
606
10
        || children[0][0].getKind() != kind::XOR)
607
    {
608
      return Node::null();
609
    }
610
    return NodeManager::currentNM()->mkNode(
611
5
        kind::OR, children[0][0][0], children[0][0][1].notNode());
612
  }
613
146156
  if (id == PfRule::NOT_XOR_ELIM2)
614
  {
615
3
    Assert(children.size() == 1);
616
3
    Assert(args.empty());
617
6
    if (children[0].getKind() != kind::NOT
618
6
        || children[0][0].getKind() != kind::XOR)
619
    {
620
      return Node::null();
621
    }
622
    return NodeManager::currentNM()->mkNode(
623
3
        kind::OR, children[0][0][0].notNode(), children[0][0][1]);
624
  }
625
146153
  if (id == PfRule::ITE_ELIM1)
626
  {
627
7489
    Assert(children.size() == 1);
628
7489
    Assert(args.empty());
629
7489
    if (children[0].getKind() != kind::ITE)
630
    {
631
      return Node::null();
632
    }
633
    return NodeManager::currentNM()->mkNode(
634
7489
        kind::OR, children[0][0].notNode(), children[0][1]);
635
  }
636
138664
  if (id == PfRule::ITE_ELIM2)
637
  {
638
21384
    Assert(children.size() == 1);
639
21384
    Assert(args.empty());
640
21384
    if (children[0].getKind() != kind::ITE)
641
    {
642
      return Node::null();
643
    }
644
    return NodeManager::currentNM()->mkNode(
645
21384
        kind::OR, children[0][0], children[0][2]);
646
  }
647
117280
  if (id == PfRule::NOT_ITE_ELIM1)
648
  {
649
6
    Assert(children.size() == 1);
650
6
    Assert(args.empty());
651
12
    if (children[0].getKind() != kind::NOT
652
12
        || children[0][0].getKind() != kind::ITE)
653
    {
654
      return Node::null();
655
    }
656
    return NodeManager::currentNM()->mkNode(
657
6
        kind::OR, children[0][0][0].notNode(), children[0][0][1].notNode());
658
  }
659
117274
  if (id == PfRule::NOT_ITE_ELIM2)
660
  {
661
5
    Assert(children.size() == 1);
662
5
    Assert(args.empty());
663
10
    if (children[0].getKind() != kind::NOT
664
10
        || children[0][0].getKind() != kind::ITE)
665
    {
666
      return Node::null();
667
    }
668
    return NodeManager::currentNM()->mkNode(
669
5
        kind::OR, children[0][0][0], children[0][0][2].notNode());
670
  }
671
  // De Morgan
672
117269
  if (id == PfRule::NOT_AND)
673
  {
674
37667
    Assert(children.size() == 1);
675
37667
    Assert(args.empty());
676
75334
    if (children[0].getKind() != kind::NOT
677
75334
        || children[0][0].getKind() != kind::AND)
678
    {
679
      return Node::null();
680
    }
681
75334
    std::vector<Node> disjuncts;
682
203841
    for (std::size_t i = 0, size = children[0][0].getNumChildren(); i < size;
683
         ++i)
684
    {
685
166174
      disjuncts.push_back(children[0][0][i].notNode());
686
    }
687
37667
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
688
  }
689
  // valid clauses rules for Tseitin CNF transformation
690
79602
  if (id == PfRule::CNF_AND_POS)
691
  {
692
15806
    Assert(children.empty());
693
15806
    Assert(args.size() == 2);
694
    uint32_t i;
695
15806
    if (args[0].getKind() != kind::AND || !getUInt32(args[1], i))
696
    {
697
      return Node::null();
698
    }
699
15806
    if (i >= args[0].getNumChildren())
700
    {
701
      return Node::null();
702
    }
703
    return NodeManager::currentNM()->mkNode(
704
15806
        kind::OR, args[0].notNode(), args[0][i]);
705
  }
706
63796
  if (id == PfRule::CNF_AND_NEG)
707
  {
708
24595
    Assert(children.empty());
709
24595
    Assert(args.size() == 1);
710
24595
    if (args[0].getKind() != kind::AND)
711
    {
712
      return Node::null();
713
    }
714
49190
    std::vector<Node> disjuncts{args[0]};
715
162108
    for (unsigned i = 0, size = args[0].getNumChildren(); i < size; ++i)
716
    {
717
137513
      disjuncts.push_back(args[0][i].notNode());
718
    }
719
24595
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
720
  }
721
39201
  if (id == PfRule::CNF_OR_POS)
722
  {
723
4165
    Assert(children.empty());
724
4165
    Assert(args.size() == 1);
725
4165
    if (args[0].getKind() != kind::OR)
726
    {
727
      return Node::null();
728
    }
729
8330
    std::vector<Node> disjuncts{args[0].notNode()};
730
194804
    for (unsigned i = 0, size = args[0].getNumChildren(); i < size; ++i)
731
    {
732
190639
      disjuncts.push_back(args[0][i]);
733
    }
734
4165
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
735
  }
736
35036
  if (id == PfRule::CNF_OR_NEG)
737
  {
738
23721
    Assert(children.empty());
739
23721
    Assert(args.size() == 2);
740
    uint32_t i;
741
23721
    if (args[0].getKind() != kind::OR || !getUInt32(args[1], i))
742
    {
743
      return Node::null();
744
    }
745
23721
    if (i >= args[0].getNumChildren())
746
    {
747
      return Node::null();
748
    }
749
    return NodeManager::currentNM()->mkNode(
750
23721
        kind::OR, args[0], args[0][i].notNode());
751
  }
752
11315
  if (id == PfRule::CNF_IMPLIES_POS)
753
  {
754
449
    Assert(children.empty());
755
449
    Assert(args.size() == 1);
756
449
    if (args[0].getKind() != kind::IMPLIES)
757
    {
758
      return Node::null();
759
    }
760
    std::vector<Node> disjuncts{
761
898
        args[0].notNode(), args[0][0].notNode(), args[0][1]};
762
449
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
763
  }
764
10866
  if (id == PfRule::CNF_IMPLIES_NEG1)
765
  {
766
122
    Assert(children.empty());
767
122
    Assert(args.size() == 1);
768
122
    if (args[0].getKind() != kind::IMPLIES)
769
    {
770
      return Node::null();
771
    }
772
244
    std::vector<Node> disjuncts{args[0], args[0][0]};
773
122
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
774
  }
775
10744
  if (id == PfRule::CNF_IMPLIES_NEG2)
776
  {
777
1127
    Assert(children.empty());
778
1127
    Assert(args.size() == 1);
779
1127
    if (args[0].getKind() != kind::IMPLIES)
780
    {
781
      return Node::null();
782
    }
783
2254
    std::vector<Node> disjuncts{args[0], args[0][1].notNode()};
784
1127
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
785
  }
786
9617
  if (id == PfRule::CNF_EQUIV_POS1)
787
  {
788
716
    Assert(children.empty());
789
716
    Assert(args.size() == 1);
790
716
    if (args[0].getKind() != kind::EQUAL)
791
    {
792
      return Node::null();
793
    }
794
    std::vector<Node> disjuncts{
795
1432
        args[0].notNode(), args[0][0].notNode(), args[0][1]};
796
716
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
797
  }
798
8901
  if (id == PfRule::CNF_EQUIV_POS2)
799
  {
800
706
    Assert(children.empty());
801
706
    Assert(args.size() == 1);
802
706
    if (args[0].getKind() != kind::EQUAL)
803
    {
804
      return Node::null();
805
    }
806
    std::vector<Node> disjuncts{
807
1412
        args[0].notNode(), args[0][0], args[0][1].notNode()};
808
706
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
809
  }
810
8195
  if (id == PfRule::CNF_EQUIV_NEG1)
811
  {
812
624
    Assert(children.empty());
813
624
    Assert(args.size() == 1);
814
624
    if (args[0].getKind() != kind::EQUAL)
815
    {
816
      return Node::null();
817
    }
818
1248
    std::vector<Node> disjuncts{args[0], args[0][0], args[0][1]};
819
624
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
820
  }
821
7571
  if (id == PfRule::CNF_EQUIV_NEG2)
822
  {
823
2380
    Assert(children.empty());
824
2380
    Assert(args.size() == 1);
825
2380
    if (args[0].getKind() != kind::EQUAL)
826
    {
827
      return Node::null();
828
    }
829
    std::vector<Node> disjuncts{
830
4760
        args[0], args[0][0].notNode(), args[0][1].notNode()};
831
2380
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
832
  }
833
5191
  if (id == PfRule::CNF_XOR_POS1)
834
  {
835
1486
    Assert(children.empty());
836
1486
    Assert(args.size() == 1);
837
1486
    if (args[0].getKind() != kind::XOR)
838
    {
839
      return Node::null();
840
    }
841
2972
    std::vector<Node> disjuncts{args[0].notNode(), args[0][0], args[0][1]};
842
1486
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
843
  }
844
3705
  if (id == PfRule::CNF_XOR_POS2)
845
  {
846
668
    Assert(children.empty());
847
668
    Assert(args.size() == 1);
848
668
    if (args[0].getKind() != kind::XOR)
849
    {
850
      return Node::null();
851
    }
852
    std::vector<Node> disjuncts{
853
1336
        args[0].notNode(), args[0][0].notNode(), args[0][1].notNode()};
854
668
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
855
  }
856
3037
  if (id == PfRule::CNF_XOR_NEG1)
857
  {
858
375
    Assert(children.empty());
859
375
    Assert(args.size() == 1);
860
375
    if (args[0].getKind() != kind::XOR)
861
    {
862
      return Node::null();
863
    }
864
750
    std::vector<Node> disjuncts{args[0], args[0][0].notNode(), args[0][1]};
865
375
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
866
  }
867
2662
  if (id == PfRule::CNF_XOR_NEG2)
868
  {
869
300
    Assert(children.empty());
870
300
    Assert(args.size() == 1);
871
300
    if (args[0].getKind() != kind::XOR)
872
    {
873
      return Node::null();
874
    }
875
600
    std::vector<Node> disjuncts{args[0], args[0][0], args[0][1].notNode()};
876
300
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
877
  }
878
2362
  if (id == PfRule::CNF_ITE_POS1)
879
  {
880
180
    Assert(children.empty());
881
180
    Assert(args.size() == 1);
882
180
    if (args[0].getKind() != kind::ITE)
883
    {
884
      return Node::null();
885
    }
886
    std::vector<Node> disjuncts{
887
360
        args[0].notNode(), args[0][0].notNode(), args[0][1]};
888
180
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
889
  }
890
2182
  if (id == PfRule::CNF_ITE_POS2)
891
  {
892
134
    Assert(children.empty());
893
134
    Assert(args.size() == 1);
894
134
    if (args[0].getKind() != kind::ITE)
895
    {
896
      return Node::null();
897
    }
898
268
    std::vector<Node> disjuncts{args[0].notNode(), args[0][0], args[0][2]};
899
134
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
900
  }
901
2048
  if (id == PfRule::CNF_ITE_POS3)
902
  {
903
159
    Assert(children.empty());
904
159
    Assert(args.size() == 1);
905
159
    if (args[0].getKind() != kind::ITE)
906
    {
907
      return Node::null();
908
    }
909
318
    std::vector<Node> disjuncts{args[0].notNode(), args[0][1], args[0][2]};
910
159
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
911
  }
912
1889
  if (id == PfRule::CNF_ITE_NEG1)
913
  {
914
350
    Assert(children.empty());
915
350
    Assert(args.size() == 1);
916
350
    if (args[0].getKind() != kind::ITE)
917
    {
918
      return Node::null();
919
    }
920
    std::vector<Node> disjuncts{
921
700
        args[0], args[0][0].notNode(), args[0][1].notNode()};
922
350
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
923
  }
924
1539
  if (id == PfRule::CNF_ITE_NEG2)
925
  {
926
100
    Assert(children.empty());
927
100
    Assert(args.size() == 1);
928
100
    if (args[0].getKind() != kind::ITE)
929
    {
930
      return Node::null();
931
    }
932
200
    std::vector<Node> disjuncts{args[0], args[0][0], args[0][2].notNode()};
933
100
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
934
  }
935
1439
  if (id == PfRule::CNF_ITE_NEG3)
936
  {
937
64
    Assert(children.empty());
938
64
    Assert(args.size() == 1);
939
64
    if (args[0].getKind() != kind::ITE)
940
    {
941
      return Node::null();
942
    }
943
    std::vector<Node> disjuncts{
944
128
        args[0], args[0][1].notNode(), args[0][2].notNode()};
945
64
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
946
  }
947
1375
  if (id == PfRule::SAT_REFUTATION)
948
  {
949
1375
    Assert(args.empty());
950
1375
    return NodeManager::currentNM()->mkConst(false);
951
  }
952
  // no rule
953
  return Node::null();
954
}
955
956
}  // namespace booleans
957
}  // namespace theory
958
29502
}  // namespace cvc5