GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/booleans/proof_checker.cpp Lines: 419 534 78.5 %
Date: 2021-05-22 Branches: 932 3332 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
3600
void BoolProofRuleChecker::registerTo(ProofChecker* pc)
25
{
26
3600
  pc->registerChecker(PfRule::SPLIT, this);
27
3600
  pc->registerChecker(PfRule::RESOLUTION, this);
28
3600
  pc->registerChecker(PfRule::CHAIN_RESOLUTION, this);
29
3600
  pc->registerTrustedChecker(PfRule::MACRO_RESOLUTION_TRUST, this, 3);
30
3600
  pc->registerChecker(PfRule::MACRO_RESOLUTION, this);
31
3600
  pc->registerChecker(PfRule::FACTORING, this);
32
3600
  pc->registerChecker(PfRule::REORDERING, this);
33
3600
  pc->registerChecker(PfRule::EQ_RESOLVE, this);
34
3600
  pc->registerChecker(PfRule::MODUS_PONENS, this);
35
3600
  pc->registerChecker(PfRule::NOT_NOT_ELIM, this);
36
3600
  pc->registerChecker(PfRule::CONTRA, this);
37
3600
  pc->registerChecker(PfRule::AND_ELIM, this);
38
3600
  pc->registerChecker(PfRule::AND_INTRO, this);
39
3600
  pc->registerChecker(PfRule::NOT_OR_ELIM, this);
40
3600
  pc->registerChecker(PfRule::IMPLIES_ELIM, this);
41
3600
  pc->registerChecker(PfRule::NOT_IMPLIES_ELIM1, this);
42
3600
  pc->registerChecker(PfRule::NOT_IMPLIES_ELIM2, this);
43
3600
  pc->registerChecker(PfRule::EQUIV_ELIM1, this);
44
3600
  pc->registerChecker(PfRule::EQUIV_ELIM2, this);
45
3600
  pc->registerChecker(PfRule::NOT_EQUIV_ELIM1, this);
46
3600
  pc->registerChecker(PfRule::NOT_EQUIV_ELIM2, this);
47
3600
  pc->registerChecker(PfRule::XOR_ELIM1, this);
48
3600
  pc->registerChecker(PfRule::XOR_ELIM2, this);
49
3600
  pc->registerChecker(PfRule::NOT_XOR_ELIM1, this);
50
3600
  pc->registerChecker(PfRule::NOT_XOR_ELIM2, this);
51
3600
  pc->registerChecker(PfRule::ITE_ELIM1, this);
52
3600
  pc->registerChecker(PfRule::ITE_ELIM2, this);
53
3600
  pc->registerChecker(PfRule::NOT_ITE_ELIM1, this);
54
3600
  pc->registerChecker(PfRule::NOT_ITE_ELIM2, this);
55
3600
  pc->registerChecker(PfRule::NOT_AND, this);
56
3600
  pc->registerChecker(PfRule::CNF_AND_POS, this);
57
3600
  pc->registerChecker(PfRule::CNF_AND_NEG, this);
58
3600
  pc->registerChecker(PfRule::CNF_OR_POS, this);
59
3600
  pc->registerChecker(PfRule::CNF_OR_NEG, this);
60
3600
  pc->registerChecker(PfRule::CNF_IMPLIES_POS, this);
61
3600
  pc->registerChecker(PfRule::CNF_IMPLIES_NEG1, this);
62
3600
  pc->registerChecker(PfRule::CNF_IMPLIES_NEG2, this);
63
3600
  pc->registerChecker(PfRule::CNF_EQUIV_POS1, this);
64
3600
  pc->registerChecker(PfRule::CNF_EQUIV_POS2, this);
65
3600
  pc->registerChecker(PfRule::CNF_EQUIV_NEG1, this);
66
3600
  pc->registerChecker(PfRule::CNF_EQUIV_NEG2, this);
67
3600
  pc->registerChecker(PfRule::CNF_XOR_POS1, this);
68
3600
  pc->registerChecker(PfRule::CNF_XOR_POS2, this);
69
3600
  pc->registerChecker(PfRule::CNF_XOR_NEG1, this);
70
3600
  pc->registerChecker(PfRule::CNF_XOR_NEG2, this);
71
3600
  pc->registerChecker(PfRule::CNF_ITE_POS1, this);
72
3600
  pc->registerChecker(PfRule::CNF_ITE_POS2, this);
73
3600
  pc->registerChecker(PfRule::CNF_ITE_POS3, this);
74
3600
  pc->registerChecker(PfRule::CNF_ITE_NEG1, this);
75
3600
  pc->registerChecker(PfRule::CNF_ITE_NEG2, this);
76
3600
  pc->registerChecker(PfRule::CNF_ITE_NEG3, this);
77
3600
  pc->registerTrustedChecker(PfRule::SAT_REFUTATION, this, 1);
78
3600
}
79
80
3796454
Node BoolProofRuleChecker::checkInternal(PfRule id,
81
                                         const std::vector<Node>& children,
82
                                         const std::vector<Node>& args)
83
{
84
3796454
  if (id == PfRule::RESOLUTION)
85
  {
86
23957
    Assert(children.size() == 2);
87
23957
    Assert(args.size() == 2);
88
23957
    NodeManager* nm = NodeManager::currentNM();
89
47914
    std::vector<Node> disjuncts;
90
47914
    Node pivots[2];
91
23957
    if (args[0] == nm->mkConst(true))
92
    {
93
21658
      pivots[0] = args[1];
94
21658
      pivots[1] = args[1].notNode();
95
    }
96
    else
97
    {
98
2299
      Assert(args[0] == nm->mkConst(false));
99
2299
      pivots[0] = args[1].notNode();
100
2299
      pivots[1] = args[1];
101
    }
102
71871
    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
95828
      std::vector<Node> lits;
108
47914
      if (children[i].getKind() == kind::OR && pivots[i] != children[i])
109
      {
110
44540
        lits.insert(lits.end(), children[i].begin(), children[i].end());
111
      }
112
      else
113
      {
114
3374
        lits.push_back(children[i]);
115
      }
116
275819
      for (unsigned j = 0, size = lits.size(); j < size; ++j)
117
      {
118
227905
        if (pivots[i] != lits[j])
119
        {
120
179991
          disjuncts.push_back(lits[j]);
121
        }
122
        else
123
        {
124
          // just eliminate first occurrence
125
47914
          pivots[i] = Node::null();
126
        }
127
      }
128
    }
129
23957
    return disjuncts.empty()
130
               ? nm->mkConst(false)
131
27331
               : disjuncts.size() == 1 ? disjuncts[0]
132
51288
                                       : nm->mkNode(kind::OR, disjuncts);
133
  }
134
3772497
  if (id == PfRule::FACTORING)
135
  {
136
333114
    Assert(children.size() == 1);
137
333114
    Assert(args.empty());
138
333114
    if (children[0].getKind() != kind::OR)
139
    {
140
      return Node::null();
141
    }
142
    // remove duplicates while keeping the order of children
143
666228
    std::unordered_set<TNode> clauseSet;
144
666228
    std::vector<Node> disjuncts;
145
333114
    unsigned size = children[0].getNumChildren();
146
10528653
    for (unsigned i = 0; i < size; ++i)
147
    {
148
10195539
      if (clauseSet.count(children[0][i]))
149
      {
150
2776600
        continue;
151
      }
152
7418939
      disjuncts.push_back(children[0][i]);
153
7418939
      clauseSet.insert(children[0][i]);
154
    }
155
333114
    if (disjuncts.size() == size)
156
    {
157
      return Node::null();
158
    }
159
333114
    NodeManager* nm = NodeManager::currentNM();
160
333114
    return nm->mkOr(disjuncts);
161
  }
162
3439383
  if (id == PfRule::REORDERING)
163
  {
164
1176842
    Assert(children.size() == 1);
165
1176842
    Assert(args.size() == 1);
166
2353684
    std::unordered_set<Node> clauseSet1, clauseSet2;
167
1176842
    if (children[0].getKind() == kind::OR)
168
    {
169
1176842
      clauseSet1.insert(children[0].begin(), children[0].end());
170
    }
171
    else
172
    {
173
      clauseSet1.insert(children[0]);
174
    }
175
1176842
    if (args[0].getKind() == kind::OR)
176
    {
177
1176842
      clauseSet2.insert(args[0].begin(), args[0].end());
178
    }
179
    else
180
    {
181
      clauseSet2.insert(args[0]);
182
    }
183
1176842
    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
1176842
    return args[0];
190
  }
191
2262541
  if (id == PfRule::CHAIN_RESOLUTION)
192
  {
193
414613
    Assert(children.size() > 1);
194
414613
    Assert(args.size() == 2 * (children.size() - 1));
195
414613
    Trace("bool-pfcheck") << "chain_res:\n" << push;
196
414613
    NodeManager* nm = NodeManager::currentNM();
197
829226
    Node trueNode = nm->mkConst(true);
198
829226
    Node falseNode = nm->mkConst(false);
199
829226
    std::vector<Node> clauseNodes;
200
    // literals to be removed from the virtual lhs clause of the resolution
201
829226
    std::unordered_map<Node, unsigned> lhsElim;
202
2903080
    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
2488467
      if (args[i] == trueNode)
207
      {
208
1250406
        lhsElim[args[i + 1]]++;
209
      }
210
      else
211
      {
212
1238061
        Assert(args[i] == falseNode);
213
1238061
        lhsElim[args[i + 1].notNode()]++;
214
      }
215
    }
216
414613
    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
3317693
    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
5806160
      Node rhsElim = Node::null();
231
2903080
      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
2903080
      if (i > 0)
241
      {
242
2488467
        std::size_t index = 2 * (i - 1);
243
3726528
        rhsElim = args[index] == trueNode ? args[index + 1].notNode()
244
1238061
                                          : args[index + 1];
245
2488467
        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
5806160
      std::vector<Node> lits;
260
8080056
      if (children[i].getKind() == kind::OR && lhsElim.count(children[i]) == 0
261
5176976
          && children[i] != rhsElim)
262
      {
263
2269915
        lits.insert(lits.end(), children[i].begin(), children[i].end());
264
      }
265
      else
266
      {
267
633165
        lits.push_back(children[i]);
268
      }
269
2903080
      Trace("bool-pfcheck") << i << ": clause lits: " << lits << "\n";
270
5806160
      std::vector<Node> added;
271
20938643
      for (std::size_t j = 0, size = lits.size(); j < size; ++j)
272
      {
273
20524030
        if (lits[j] == rhsElim)
274
        {
275
2488467
          rhsElim = Node::null();
276
2488467
          continue;
277
        }
278
15547096
        auto it = lhsElim.find(lits[j]);
279
15547096
        if (it == lhsElim.end())
280
        {
281
13058629
          clauseNodes.push_back(lits[j]);
282
13058629
          added.push_back(lits[j]);
283
        }
284
        else
285
        {
286
          // remove occurrence
287
2488467
          it->second--;
288
2488467
          if (it->second == 0)
289
          {
290
2384278
            lhsElim.erase(it);
291
          }
292
        }
293
      }
294
2903080
      Trace("bool-pfcheck") << i << ": added lits: " << added << "\n\n";
295
    }
296
414613
    Trace("bool-pfcheck") << "clause: " << clauseNodes << "\n" << pop;
297
414613
    return nm->mkOr(clauseNodes);
298
  }
299
1847928
  if (id == PfRule::MACRO_RESOLUTION_TRUST)
300
  {
301
300191
    Assert(children.size() > 1);
302
300191
    Assert(args.size() == 2 * (children.size() - 1) + 1);
303
300191
    return args[0];
304
  }
305
1547737
  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
1547737
  if (id == PfRule::SPLIT)
416
  {
417
10019
    Assert(children.empty());
418
10019
    Assert(args.size() == 1);
419
    return NodeManager::currentNM()->mkNode(
420
10019
        kind::OR, args[0], args[0].notNode());
421
  }
422
1537718
  if (id == PfRule::CONTRA)
423
  {
424
11566
    Assert(children.size() == 2);
425
11566
    if (children[1].getKind() == Kind::NOT && children[0] == children[1][0])
426
    {
427
11566
      return NodeManager::currentNM()->mkConst(false);
428
    }
429
    return Node::null();
430
  }
431
1526152
  if (id == PfRule::EQ_RESOLVE)
432
  {
433
298520
    Assert(children.size() == 2);
434
298520
    Assert(args.empty());
435
298520
    if (children[1].getKind() != kind::EQUAL || children[0] != children[1][0])
436
    {
437
      return Node::null();
438
    }
439
298520
    return children[1][1];
440
  }
441
1227632
  if (id == PfRule::MODUS_PONENS)
442
  {
443
97702
    Assert(children.size() == 2);
444
97702
    Assert(args.empty());
445
97702
    if (children[1].getKind() != kind::IMPLIES || children[0] != children[1][0])
446
    {
447
      return Node::null();
448
    }
449
97702
    return children[1][1];
450
  }
451
1129930
  if (id == PfRule::NOT_NOT_ELIM)
452
  {
453
2639
    Assert(children.size() == 1);
454
2639
    Assert(args.empty());
455
2639
    if (children[0].getKind() != kind::NOT || children[0][0].getKind() != kind::NOT)
456
    {
457
      return Node::null();
458
    }
459
2639
    return children[0][0][0];
460
  }
461
  // natural deduction rules
462
1127291
  if (id == PfRule::AND_ELIM)
463
  {
464
472768
    Assert(children.size() == 1);
465
472768
    Assert(args.size() == 1);
466
    uint32_t i;
467
472768
    if (children[0].getKind() != kind::AND || !getUInt32(args[0], i))
468
    {
469
      return Node::null();
470
    }
471
472768
    if (i >= children[0].getNumChildren())
472
    {
473
      return Node::null();
474
    }
475
472768
    return children[0][i];
476
  }
477
654523
  if (id == PfRule::AND_INTRO)
478
  {
479
112160
    Assert(children.size() >= 1);
480
112160
    return children.size() == 1
481
               ? children[0]
482
112160
               : NodeManager::currentNM()->mkNode(kind::AND, children);
483
  }
484
542363
  if (id == PfRule::NOT_OR_ELIM)
485
  {
486
6699
    Assert(children.size() == 1);
487
6699
    Assert(args.size() == 1);
488
    uint32_t i;
489
13398
    if (children[0].getKind() != kind::NOT
490
13398
        || children[0][0].getKind() != kind::OR || !getUInt32(args[0], i))
491
    {
492
      return Node::null();
493
    }
494
6699
    if (i >= children[0][0].getNumChildren())
495
    {
496
      return Node::null();
497
    }
498
6699
    return children[0][0][i].notNode();
499
  }
500
535664
  if (id == PfRule::IMPLIES_ELIM)
501
  {
502
54070
    Assert(children.size() == 1);
503
54070
    Assert(args.empty());
504
54070
    if (children[0].getKind() != kind::IMPLIES)
505
    {
506
      return Node::null();
507
    }
508
    return NodeManager::currentNM()->mkNode(
509
54070
        kind::OR, children[0][0].notNode(), children[0][1]);
510
  }
511
481594
  if (id == PfRule::NOT_IMPLIES_ELIM1)
512
  {
513
665
    Assert(children.size() == 1);
514
665
    Assert(args.empty());
515
1330
    if (children[0].getKind() != kind::NOT
516
1330
        || children[0][0].getKind() != kind::IMPLIES)
517
    {
518
      return Node::null();
519
    }
520
665
    return children[0][0][0];
521
  }
522
480929
  if (id == PfRule::NOT_IMPLIES_ELIM2)
523
  {
524
462
    Assert(children.size() == 1);
525
462
    Assert(args.empty());
526
924
    if (children[0].getKind() != kind::NOT
527
924
        || children[0][0].getKind() != kind::IMPLIES)
528
    {
529
      return Node::null();
530
    }
531
462
    return children[0][0][1].notNode();
532
  }
533
480467
  if (id == PfRule::EQUIV_ELIM1)
534
  {
535
2236
    Assert(children.size() == 1);
536
2236
    Assert(args.empty());
537
2236
    if (children[0].getKind() != kind::EQUAL)
538
    {
539
      return Node::null();
540
    }
541
    return NodeManager::currentNM()->mkNode(
542
2236
        kind::OR, children[0][0].notNode(), children[0][1]);
543
  }
544
478231
  if (id == PfRule::EQUIV_ELIM2)
545
  {
546
2905
    Assert(children.size() == 1);
547
2905
    Assert(args.empty());
548
2905
    if (children[0].getKind() != kind::EQUAL)
549
    {
550
      return Node::null();
551
    }
552
    return NodeManager::currentNM()->mkNode(
553
2905
        kind::OR, children[0][0], children[0][1].notNode());
554
  }
555
475326
  if (id == PfRule::NOT_EQUIV_ELIM1)
556
  {
557
107
    Assert(children.size() == 1);
558
107
    Assert(args.empty());
559
214
    if (children[0].getKind() != kind::NOT
560
214
        || children[0][0].getKind() != kind::EQUAL)
561
    {
562
      return Node::null();
563
    }
564
    return NodeManager::currentNM()->mkNode(
565
107
        kind::OR, children[0][0][0], children[0][0][1]);
566
  }
567
475219
  if (id == PfRule::NOT_EQUIV_ELIM2)
568
  {
569
137
    Assert(children.size() == 1);
570
137
    Assert(args.empty());
571
274
    if (children[0].getKind() != kind::NOT
572
274
        || children[0][0].getKind() != kind::EQUAL)
573
    {
574
      return Node::null();
575
    }
576
    return NodeManager::currentNM()->mkNode(
577
137
        kind::OR, children[0][0][0].notNode(), children[0][0][1].notNode());
578
  }
579
475082
  if (id == PfRule::XOR_ELIM1)
580
  {
581
36
    Assert(children.size() == 1);
582
36
    Assert(args.empty());
583
36
    if (children[0].getKind() != kind::XOR)
584
    {
585
      return Node::null();
586
    }
587
    return NodeManager::currentNM()->mkNode(
588
36
        kind::OR, children[0][0], children[0][1]);
589
  }
590
475046
  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
475012
  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
475007
  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
475004
  if (id == PfRule::ITE_ELIM1)
626
  {
627
13409
    Assert(children.size() == 1);
628
13409
    Assert(args.empty());
629
13409
    if (children[0].getKind() != kind::ITE)
630
    {
631
      return Node::null();
632
    }
633
    return NodeManager::currentNM()->mkNode(
634
13409
        kind::OR, children[0][0].notNode(), children[0][1]);
635
  }
636
461595
  if (id == PfRule::ITE_ELIM2)
637
  {
638
41982
    Assert(children.size() == 1);
639
41982
    Assert(args.empty());
640
41982
    if (children[0].getKind() != kind::ITE)
641
    {
642
      return Node::null();
643
    }
644
    return NodeManager::currentNM()->mkNode(
645
41982
        kind::OR, children[0][0], children[0][2]);
646
  }
647
419613
  if (id == PfRule::NOT_ITE_ELIM1)
648
  {
649
71
    Assert(children.size() == 1);
650
71
    Assert(args.empty());
651
142
    if (children[0].getKind() != kind::NOT
652
142
        || children[0][0].getKind() != kind::ITE)
653
    {
654
      return Node::null();
655
    }
656
    return NodeManager::currentNM()->mkNode(
657
71
        kind::OR, children[0][0][0].notNode(), children[0][0][1].notNode());
658
  }
659
419542
  if (id == PfRule::NOT_ITE_ELIM2)
660
  {
661
107
    Assert(children.size() == 1);
662
107
    Assert(args.empty());
663
214
    if (children[0].getKind() != kind::NOT
664
214
        || children[0][0].getKind() != kind::ITE)
665
    {
666
      return Node::null();
667
    }
668
    return NodeManager::currentNM()->mkNode(
669
107
        kind::OR, children[0][0][0], children[0][0][2].notNode());
670
  }
671
  // De Morgan
672
419435
  if (id == PfRule::NOT_AND)
673
  {
674
43556
    Assert(children.size() == 1);
675
43556
    Assert(args.empty());
676
87112
    if (children[0].getKind() != kind::NOT
677
87112
        || children[0][0].getKind() != kind::AND)
678
    {
679
      return Node::null();
680
    }
681
87112
    std::vector<Node> disjuncts;
682
297038
    for (std::size_t i = 0, size = children[0][0].getNumChildren(); i < size;
683
         ++i)
684
    {
685
253482
      disjuncts.push_back(children[0][0][i].notNode());
686
    }
687
43556
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
688
  }
689
  // valid clauses rules for Tseitin CNF transformation
690
375879
  if (id == PfRule::CNF_AND_POS)
691
  {
692
153423
    Assert(children.empty());
693
153423
    Assert(args.size() == 2);
694
    uint32_t i;
695
153423
    if (args[0].getKind() != kind::AND || !getUInt32(args[1], i))
696
    {
697
      return Node::null();
698
    }
699
153423
    if (i >= args[0].getNumChildren())
700
    {
701
      return Node::null();
702
    }
703
    return NodeManager::currentNM()->mkNode(
704
153423
        kind::OR, args[0].notNode(), args[0][i]);
705
  }
706
222456
  if (id == PfRule::CNF_AND_NEG)
707
  {
708
46762
    Assert(children.empty());
709
46762
    Assert(args.size() == 1);
710
46762
    if (args[0].getKind() != kind::AND)
711
    {
712
      return Node::null();
713
    }
714
93524
    std::vector<Node> disjuncts{args[0]};
715
365831
    for (unsigned i = 0, size = args[0].getNumChildren(); i < size; ++i)
716
    {
717
319069
      disjuncts.push_back(args[0][i].notNode());
718
    }
719
46762
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
720
  }
721
175694
  if (id == PfRule::CNF_OR_POS)
722
  {
723
14707
    Assert(children.empty());
724
14707
    Assert(args.size() == 1);
725
14707
    if (args[0].getKind() != kind::OR)
726
    {
727
      return Node::null();
728
    }
729
29414
    std::vector<Node> disjuncts{args[0].notNode()};
730
243268
    for (unsigned i = 0, size = args[0].getNumChildren(); i < size; ++i)
731
    {
732
228561
      disjuncts.push_back(args[0][i]);
733
    }
734
14707
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
735
  }
736
160987
  if (id == PfRule::CNF_OR_NEG)
737
  {
738
56663
    Assert(children.empty());
739
56663
    Assert(args.size() == 2);
740
    uint32_t i;
741
56663
    if (args[0].getKind() != kind::OR || !getUInt32(args[1], i))
742
    {
743
      return Node::null();
744
    }
745
56663
    if (i >= args[0].getNumChildren())
746
    {
747
      return Node::null();
748
    }
749
    return NodeManager::currentNM()->mkNode(
750
56663
        kind::OR, args[0], args[0][i].notNode());
751
  }
752
104324
  if (id == PfRule::CNF_IMPLIES_POS)
753
  {
754
2391
    Assert(children.empty());
755
2391
    Assert(args.size() == 1);
756
2391
    if (args[0].getKind() != kind::IMPLIES)
757
    {
758
      return Node::null();
759
    }
760
    std::vector<Node> disjuncts{
761
4782
        args[0].notNode(), args[0][0].notNode(), args[0][1]};
762
2391
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
763
  }
764
101933
  if (id == PfRule::CNF_IMPLIES_NEG1)
765
  {
766
1968
    Assert(children.empty());
767
1968
    Assert(args.size() == 1);
768
1968
    if (args[0].getKind() != kind::IMPLIES)
769
    {
770
      return Node::null();
771
    }
772
3936
    std::vector<Node> disjuncts{args[0], args[0][0]};
773
1968
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
774
  }
775
99965
  if (id == PfRule::CNF_IMPLIES_NEG2)
776
  {
777
67711
    Assert(children.empty());
778
67711
    Assert(args.size() == 1);
779
67711
    if (args[0].getKind() != kind::IMPLIES)
780
    {
781
      return Node::null();
782
    }
783
135422
    std::vector<Node> disjuncts{args[0], args[0][1].notNode()};
784
67711
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
785
  }
786
32254
  if (id == PfRule::CNF_EQUIV_POS1)
787
  {
788
1571
    Assert(children.empty());
789
1571
    Assert(args.size() == 1);
790
1571
    if (args[0].getKind() != kind::EQUAL)
791
    {
792
      return Node::null();
793
    }
794
    std::vector<Node> disjuncts{
795
3142
        args[0].notNode(), args[0][0].notNode(), args[0][1]};
796
1571
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
797
  }
798
30683
  if (id == PfRule::CNF_EQUIV_POS2)
799
  {
800
1162
    Assert(children.empty());
801
1162
    Assert(args.size() == 1);
802
1162
    if (args[0].getKind() != kind::EQUAL)
803
    {
804
      return Node::null();
805
    }
806
    std::vector<Node> disjuncts{
807
2324
        args[0].notNode(), args[0][0], args[0][1].notNode()};
808
1162
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
809
  }
810
29521
  if (id == PfRule::CNF_EQUIV_NEG1)
811
  {
812
1265
    Assert(children.empty());
813
1265
    Assert(args.size() == 1);
814
1265
    if (args[0].getKind() != kind::EQUAL)
815
    {
816
      return Node::null();
817
    }
818
2530
    std::vector<Node> disjuncts{args[0], args[0][0], args[0][1]};
819
1265
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
820
  }
821
28256
  if (id == PfRule::CNF_EQUIV_NEG2)
822
  {
823
3536
    Assert(children.empty());
824
3536
    Assert(args.size() == 1);
825
3536
    if (args[0].getKind() != kind::EQUAL)
826
    {
827
      return Node::null();
828
    }
829
    std::vector<Node> disjuncts{
830
7072
        args[0], args[0][0].notNode(), args[0][1].notNode()};
831
3536
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
832
  }
833
24720
  if (id == PfRule::CNF_XOR_POS1)
834
  {
835
158
    Assert(children.empty());
836
158
    Assert(args.size() == 1);
837
158
    if (args[0].getKind() != kind::XOR)
838
    {
839
      return Node::null();
840
    }
841
316
    std::vector<Node> disjuncts{args[0].notNode(), args[0][0], args[0][1]};
842
158
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
843
  }
844
24562
  if (id == PfRule::CNF_XOR_POS2)
845
  {
846
163
    Assert(children.empty());
847
163
    Assert(args.size() == 1);
848
163
    if (args[0].getKind() != kind::XOR)
849
    {
850
      return Node::null();
851
    }
852
    std::vector<Node> disjuncts{
853
326
        args[0].notNode(), args[0][0].notNode(), args[0][1].notNode()};
854
163
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
855
  }
856
24399
  if (id == PfRule::CNF_XOR_NEG1)
857
  {
858
158
    Assert(children.empty());
859
158
    Assert(args.size() == 1);
860
158
    if (args[0].getKind() != kind::XOR)
861
    {
862
      return Node::null();
863
    }
864
316
    std::vector<Node> disjuncts{args[0], args[0][0].notNode(), args[0][1]};
865
158
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
866
  }
867
24241
  if (id == PfRule::CNF_XOR_NEG2)
868
  {
869
164
    Assert(children.empty());
870
164
    Assert(args.size() == 1);
871
164
    if (args[0].getKind() != kind::XOR)
872
    {
873
      return Node::null();
874
    }
875
328
    std::vector<Node> disjuncts{args[0], args[0][0], args[0][1].notNode()};
876
164
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
877
  }
878
24077
  if (id == PfRule::CNF_ITE_POS1)
879
  {
880
3795
    Assert(children.empty());
881
3795
    Assert(args.size() == 1);
882
3795
    if (args[0].getKind() != kind::ITE)
883
    {
884
      return Node::null();
885
    }
886
    std::vector<Node> disjuncts{
887
7590
        args[0].notNode(), args[0][0].notNode(), args[0][1]};
888
3795
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
889
  }
890
20282
  if (id == PfRule::CNF_ITE_POS2)
891
  {
892
3517
    Assert(children.empty());
893
3517
    Assert(args.size() == 1);
894
3517
    if (args[0].getKind() != kind::ITE)
895
    {
896
      return Node::null();
897
    }
898
7034
    std::vector<Node> disjuncts{args[0].notNode(), args[0][0], args[0][2]};
899
3517
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
900
  }
901
16765
  if (id == PfRule::CNF_ITE_POS3)
902
  {
903
3835
    Assert(children.empty());
904
3835
    Assert(args.size() == 1);
905
3835
    if (args[0].getKind() != kind::ITE)
906
    {
907
      return Node::null();
908
    }
909
7670
    std::vector<Node> disjuncts{args[0].notNode(), args[0][1], args[0][2]};
910
3835
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
911
  }
912
12930
  if (id == PfRule::CNF_ITE_NEG1)
913
  {
914
4246
    Assert(children.empty());
915
4246
    Assert(args.size() == 1);
916
4246
    if (args[0].getKind() != kind::ITE)
917
    {
918
      return Node::null();
919
    }
920
    std::vector<Node> disjuncts{
921
8492
        args[0], args[0][0].notNode(), args[0][1].notNode()};
922
4246
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
923
  }
924
8684
  if (id == PfRule::CNF_ITE_NEG2)
925
  {
926
3513
    Assert(children.empty());
927
3513
    Assert(args.size() == 1);
928
3513
    if (args[0].getKind() != kind::ITE)
929
    {
930
      return Node::null();
931
    }
932
7026
    std::vector<Node> disjuncts{args[0], args[0][0], args[0][2].notNode()};
933
3513
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
934
  }
935
5171
  if (id == PfRule::CNF_ITE_NEG3)
936
  {
937
3853
    Assert(children.empty());
938
3853
    Assert(args.size() == 1);
939
3853
    if (args[0].getKind() != kind::ITE)
940
    {
941
      return Node::null();
942
    }
943
    std::vector<Node> disjuncts{
944
7706
        args[0], args[0][1].notNode(), args[0][2].notNode()};
945
3853
    return NodeManager::currentNM()->mkNode(kind::OR, disjuncts);
946
  }
947
1318
  if (id == PfRule::SAT_REFUTATION)
948
  {
949
1318
    Assert(args.empty());
950
1318
    return NodeManager::currentNM()->mkConst(false);
951
  }
952
  // no rule
953
  return Node::null();
954
}
955
956
}  // namespace booleans
957
}  // namespace theory
958
28191
}  // namespace cvc5