GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/preprocessing/passes/global_negate.cpp Lines: 48 49 98.0 %
Date: 2021-05-22 Branches: 85 166 51.2 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Yoni Zohar, Aina Niemetz
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 global_negate.
14
 */
15
16
#include "preprocessing/passes/global_negate.h"
17
18
#include <vector>
19
20
#include "expr/node.h"
21
#include "preprocessing/assertion_pipeline.h"
22
#include "theory/rewriter.h"
23
24
using namespace std;
25
using namespace cvc5::kind;
26
using namespace cvc5::theory;
27
28
namespace cvc5 {
29
namespace preprocessing {
30
namespace passes {
31
32
6
Node GlobalNegate::simplify(const std::vector<Node>& assertions,
33
                            NodeManager* nm)
34
{
35
6
  Assert(!assertions.empty());
36
6
  Trace("cegqi-gn") << "Global negate : " << std::endl;
37
  // collect free variables in all assertions
38
12
  std::vector<Node> free_vars;
39
12
  std::vector<TNode> visit;
40
12
  std::unordered_set<TNode> visited;
41
18
  for (const Node& as : assertions)
42
  {
43
12
    Trace("cegqi-gn") << "  " << as << std::endl;
44
24
    TNode cur = as;
45
    // compute free variables
46
12
    visit.push_back(cur);
47
214
    do
48
    {
49
226
      cur = visit.back();
50
226
      visit.pop_back();
51
226
      if (visited.find(cur) == visited.end())
52
      {
53
148
        visited.insert(cur);
54
148
        if (cur.isVar() && cur.getKind() != BOUND_VARIABLE)
55
        {
56
22
          free_vars.push_back(cur);
57
        }
58
362
        for (const TNode& cn : cur)
59
        {
60
214
          visit.push_back(cn);
61
        }
62
      }
63
226
    } while (!visit.empty());
64
  }
65
66
6
  Node body;
67
6
  if (assertions.size() == 1)
68
  {
69
    body = assertions[0];
70
  }
71
  else
72
  {
73
6
    body = nm->mkNode(AND, assertions);
74
  }
75
76
  // do the negation
77
6
  body = body.negate();
78
79
6
  if (!free_vars.empty())
80
  {
81
8
    std::vector<Node> bvs;
82
26
    for (const Node& v : free_vars)
83
    {
84
44
      Node bv = nm->mkBoundVar(v.getType());
85
22
      bvs.push_back(bv);
86
    }
87
88
4
    body = body.substitute(
89
        free_vars.begin(), free_vars.end(), bvs.begin(), bvs.end());
90
91
8
    Node bvl = nm->mkNode(BOUND_VAR_LIST, bvs);
92
93
4
    body = nm->mkNode(FORALL, bvl, body);
94
  }
95
96
6
  Trace("cegqi-gn-debug") << "...got (pre-rewrite) : " << body << std::endl;
97
6
  body = Rewriter::rewrite(body);
98
6
  Trace("cegqi-gn") << "...got (post-rewrite) : " << body << std::endl;
99
12
  return body;
100
}
101
102
9459
GlobalNegate::GlobalNegate(PreprocessingPassContext* preprocContext)
103
9459
    : PreprocessingPass(preprocContext, "global-negate"){};
104
105
6
PreprocessingPassResult GlobalNegate::applyInternal(
106
    AssertionPipeline* assertionsToPreprocess)
107
{
108
6
  NodeManager* nm = NodeManager::currentNM();
109
12
  Node simplifiedNode = simplify(assertionsToPreprocess->ref(), nm);
110
12
  Node trueNode = nm->mkConst(true);
111
18
  for (unsigned i = 0, size = assertionsToPreprocess->size(); i < size; ++i)
112
  {
113
12
    if (i == 0)
114
    {
115
6
      assertionsToPreprocess->replace(i, simplifiedNode);
116
    }
117
    else
118
    {
119
6
      assertionsToPreprocess->replace(i, trueNode);
120
    }
121
  }
122
12
  return PreprocessingPassResult::NO_CONFLICT;
123
}
124
125
126
}  // namespace passes
127
}  // namespace preprocessing
128
28191
}  // namespace cvc5