CBMC
bdd_expr.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Conversion between exprt and miniBDD
4 
5 Author: Michael Tautschnig, michael.tautschnig@qmul.ac.uk
6 
7 \*******************************************************************/
8 
11 
12 #include "bdd_expr.h"
13 
14 #include <util/expr_util.h>
15 #include <util/invariant.h>
16 #include <util/narrow.h>
17 #include <util/std_expr.h>
18 
20 {
21  PRECONDITION(expr.type().id() == ID_bool);
22 
23  if(expr.is_constant())
24  return expr.is_false() ? bdd_mgr.bdd_false() : bdd_mgr.bdd_true();
25  else if(expr.id()==ID_not)
26  return from_expr_rec(to_not_expr(expr).op()).bdd_not();
27  else if(expr.id()==ID_and ||
28  expr.id()==ID_or ||
29  expr.id()==ID_xor)
30  {
32  expr.operands().size() >= 2,
33  "logical and, or, and xor expressions have at least two operands");
34  exprt bin_expr=make_binary(expr);
35 
36  bddt lhs = from_expr_rec(to_binary_expr(bin_expr).lhs());
37  bddt rhs = from_expr_rec(to_binary_expr(bin_expr).rhs());
38 
39  return expr.id() == ID_and
40  ? lhs.bdd_and(rhs)
41  : (expr.id() == ID_or ? lhs.bdd_or(rhs) : lhs.bdd_xor(rhs));
42  }
43  else if(expr.id()==ID_implies)
44  {
45  const implies_exprt &imp_expr=to_implies_expr(expr);
46 
47  bddt n_lhs = from_expr_rec(imp_expr.lhs()).bdd_not();
48  bddt rhs = from_expr_rec(imp_expr.rhs());
49 
50  return n_lhs.bdd_or(rhs);
51  }
52  else if(
53  expr.id() == ID_equal && to_equal_expr(expr).lhs().type().id() == ID_bool)
54  {
55  const equal_exprt &eq_expr=to_equal_expr(expr);
56 
57  bddt op0 = from_expr_rec(eq_expr.op0());
58  bddt op1 = from_expr_rec(eq_expr.op1());
59 
60  return op0.bdd_xor(op1).bdd_not();
61  }
62  else if(expr.id()==ID_if)
63  {
64  const if_exprt &if_expr=to_if_expr(expr);
65 
66  bddt cond = from_expr_rec(if_expr.cond());
67  bddt t_case = from_expr_rec(if_expr.true_case());
68  bddt f_case = from_expr_rec(if_expr.false_case());
69 
70  return bddt::bdd_ite(cond, t_case, f_case);
71  }
72  else
73  {
74  std::pair<expr_mapt::iterator, bool> entry =
75  expr_map.emplace(expr, bdd_mgr.bdd_true());
76 
77  if(entry.second)
78  {
79  node_map.push_back(expr);
80  const unsigned index = (unsigned)node_map.size() - 1;
81  entry.first->second = bdd_mgr.bdd_variable(index);
82  }
83 
84  return entry.first->second;
85  }
86 }
87 
89 {
90  return from_expr_rec(expr);
91 }
92 
95 static exprt make_or(exprt a, exprt b)
96 {
97  if(b.id() == ID_or)
98  {
99  b.add_to_operands(std::move(a));
100  return b;
101  }
102  return or_exprt{std::move(a), std::move(b)};
103 }
104 
109  const bdd_nodet &r,
110  std::unordered_map<bdd_nodet::idt, exprt> &cache) const
111 {
112  if(r.is_constant())
113  {
114  if(r.is_complement())
115  return false_exprt();
116  else
117  return true_exprt();
118  }
119 
120  auto index = narrow<std::size_t>(r.index());
121  INVARIANT(index < node_map.size(), "Index should be in node_map");
122  const exprt &n_expr = node_map[index];
123 
124  // Look-up cache for already computed value
125  auto insert_result = cache.emplace(r.id(), nil_exprt());
126  if(insert_result.second)
127  {
128  auto result_ignoring_complementation = [&]() -> exprt {
129  if(r.else_branch().is_constant())
130  {
131  if(r.then_branch().is_constant())
132  {
133  if(r.else_branch().is_complement()) // else is false
134  return n_expr;
135  return not_exprt(n_expr); // else is true
136  }
137  else
138  {
139  if(r.else_branch().is_complement()) // else is false
140  {
141  exprt then_case = as_expr(r.then_branch(), cache);
142  return make_and(n_expr, then_case);
143  }
144  exprt then_case = as_expr(r.then_branch(), cache);
145  return make_or(not_exprt(n_expr), then_case);
146  }
147  }
148  else if(r.then_branch().is_constant())
149  {
150  if(r.then_branch().is_complement()) // then is false
151  {
152  exprt else_case = as_expr(r.else_branch(), cache);
153  return make_and(not_exprt(n_expr), else_case);
154  }
155  exprt else_case = as_expr(r.else_branch(), cache);
156  return make_or(n_expr, else_case);
157  }
158 
159  exprt then_branch = as_expr(r.then_branch(), cache);
160  exprt else_branch = as_expr(r.else_branch(), cache);
161  return if_exprt(n_expr, then_branch, else_branch);
162  }();
163 
164  insert_result.first->second =
165  r.is_complement()
166  ? boolean_negate(std::move(result_ignoring_complementation))
167  : result_ignoring_complementation;
168  }
169  return insert_result.first->second;
170 }
171 
172 exprt bdd_exprt::as_expr(const bddt &root) const
173 {
174  std::unordered_map<bdd_nodet::idt, exprt> cache;
175  bdd_nodet node = bdd_mgr.bdd_node(root);
176  return as_expr(node, cache);
177 }
make_and
exprt make_and(exprt a, exprt b)
Conjunction of two expressions.
Definition: expr_util.cpp:292
bdd_exprt::from_expr
bddt from_expr(const exprt &expr)
Definition: bdd_expr.cpp:88
binary_exprt::rhs
exprt & rhs()
Definition: std_expr.h:623
bddt::bdd_or
bddt bdd_or(const bddt &other) const
Definition: bdd_cudd.h:100
bdd_exprt::expr_map
expr_mapt expr_map
Definition: bdd_expr.h:44
to_if_expr
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition: std_expr.h:2403
bdd_exprt::node_map
std::vector< exprt > node_map
Mapping from BDD variables to expressions: the expression at index i of node_map corresponds to the i...
Definition: bdd_expr.h:48
if_exprt
The trinary if-then-else operator.
Definition: std_expr.h:2322
bddt::bdd_not
bddt bdd_not() const
Definition: bdd_cudd.h:95
invariant.h
exprt
Base class for all expressions.
Definition: expr.h:55
binary_exprt::lhs
exprt & lhs()
Definition: std_expr.h:613
bdd_nodet
Low level access to the structure of the BDD, read-only.
Definition: bdd_cudd.h:27
make_binary
exprt make_binary(const exprt &expr)
splits an expression with >=3 operands into nested binary expressions
Definition: expr_util.cpp:36
equal_exprt
Equality.
Definition: std_expr.h:1305
if_exprt::false_case
exprt & false_case()
Definition: std_expr.h:2360
exprt::is_false
bool is_false() const
Return whether the expression is a constant representing false.
Definition: expr.cpp:43
to_binary_expr
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition: std_expr.h:660
narrow.h
bdd_exprt::bdd_mgr
bdd_managert bdd_mgr
Definition: bdd_expr.h:40
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
or_exprt
Boolean OR.
Definition: std_expr.h:2178
bddt::bdd_ite
static bddt bdd_ite(const bddt &i, const bddt &t, const bddt &e)
Definition: bdd_cudd.h:115
bdd_managert::bdd_true
bddt bdd_true()
Definition: bdd_cudd.h:145
DATA_INVARIANT
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:510
bdd_managert::bdd_node
bdd_nodet bdd_node(const bddt &bdd) const
Definition: bdd_cudd.h:160
bdd_managert::bdd_variable
bddt bdd_variable(bdd_nodet::indext index)
Definition: bdd_cudd.h:155
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
nil_exprt
The NIL expression.
Definition: std_expr.h:3025
boolean_negate
exprt boolean_negate(const exprt &src)
negate a Boolean expression, possibly removing a not_exprt, and swapping false and true
Definition: expr_util.cpp:127
bdd_exprt::as_expr
exprt as_expr(const bddt &root) const
Definition: bdd_expr.cpp:172
irept::id
const irep_idt & id() const
Definition: irep.h:396
false_exprt
The Boolean constant false.
Definition: std_expr.h:3016
bdd_managert::bdd_false
bddt bdd_false()
Definition: bdd_cudd.h:150
bdd_expr.h
Binary decision diagram.
expr_util.h
Deprecated expression utility functions.
bdd_exprt::from_expr_rec
bddt from_expr_rec(const exprt &expr)
Definition: bdd_expr.cpp:19
if_exprt::true_case
exprt & true_case()
Definition: std_expr.h:2350
bddt::bdd_and
bddt bdd_and(const bddt &other) const
Definition: bdd_cudd.h:105
to_not_expr
const not_exprt & to_not_expr(const exprt &expr)
Cast an exprt to an not_exprt.
Definition: std_expr.h:2303
to_implies_expr
const implies_exprt & to_implies_expr(const exprt &expr)
Cast an exprt to a implies_exprt.
Definition: std_expr.h:2159
exprt::is_constant
bool is_constant() const
Return whether the expression is a constant.
Definition: expr.cpp:27
if_exprt::cond
exprt & cond()
Definition: std_expr.h:2340
to_equal_expr
const equal_exprt & to_equal_expr(const exprt &expr)
Cast an exprt to an equal_exprt.
Definition: std_expr.h:1347
exprt::add_to_operands
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition: expr.h:162
implies_exprt
Boolean implication.
Definition: std_expr.h:2133
exprt::operands
operandst & operands()
Definition: expr.h:94
r
static int8_t r
Definition: irep_hash.h:60
bddt
Logical operations on BDDs.
Definition: bdd_cudd.h:77
true_exprt
The Boolean constant true.
Definition: std_expr.h:3007
binary_exprt::op1
exprt & op1()
Definition: expr.h:128
std_expr.h
bddt::bdd_xor
bddt bdd_xor(const bddt &other) const
Definition: bdd_cudd.h:110
make_or
static exprt make_or(exprt a, exprt b)
Disjunction of two expressions.
Definition: bdd_expr.cpp:95
binary_exprt::op0
exprt & op0()
Definition: expr.h:125
validation_modet::INVARIANT
@ INVARIANT
not_exprt
Boolean negation.
Definition: std_expr.h:2277