carl  24.04
Computer ARithmetic Library
PNF.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "../Formula.h"
4 #include "Substitution.h"
5 #include "aux.h"
6 
7 namespace carl {
8 
9 enum class Quantifier {
10  EXISTS,
11  FORALL,
12  FREE
13 };
14 inline std::ostream& operator<<(std::ostream& os, const Quantifier& type) {
15  switch (type) {
16  case Quantifier::EXISTS:
17  os << "exists";
18  return os;
19  case Quantifier::FORALL:
20  os << "forall";
21  return os;
22  case Quantifier::FREE:
23  os << "free";
24  return os;
25  }
26 }
27 
28 using QuantifierPrefix = std::vector<std::pair<Quantifier, carl::Variable>>;
29 
30 template<typename Poly>
31 Formula<Poly> to_pnf(const Formula<Poly>& f, QuantifierPrefix& prefix, boost::container::flat_set<Variable>& used_vars, bool negated = false) {
32  switch (f.type()) {
33  case FormulaType::AND:
34  case FormulaType::IFF:
35  case FormulaType::OR:
36  case FormulaType::XOR: {
37  if (!negated) {
38  Formulas<Poly> subs;
39  for (auto& sub : f.subformulas()) {
40  subs.push_back(to_pnf(sub, prefix, used_vars, false));
41  }
42  return Formula<Poly>(f.type(), std::move(subs));
43  } else if (f.type() == FormulaType::AND || f.type() == FormulaType::OR) {
44  Formulas<Poly> subs;
45  for (auto& sub : f.subformulas()) {
46  subs.push_back(to_pnf(sub, prefix, used_vars, true));
47  }
48  if (f.type() == FormulaType::AND) {
49  return Formula<Poly>(FormulaType::OR, std::move(subs));
50  } else {
51  return Formula<Poly>(FormulaType::AND, std::move(subs));
52  }
53  } else if (f.type() == FormulaType::IFF) {
54  Formulas<Poly> sub1;
55  Formulas<Poly> sub2;
56  for (auto& sub : f.subformulas()) {
57  sub1.push_back(to_pnf(sub, prefix, used_vars, true));
58  sub2.push_back(to_pnf(sub, prefix, used_vars, false));
59  }
60  return Formula<Poly>(FormulaType::AND, {Formula<Poly>(FormulaType::OR, std::move(sub1)), Formula<Poly>(FormulaType::OR, std::move(sub2))});
61  } else if (f.type() == FormulaType::XOR) {
62  auto lhs = to_pnf(f, prefix, used_vars, false);
63  auto rhs = to_pnf(formula::aux::connectPrecedingSubformulas(f), prefix, used_vars, false);
64  return Formula<Poly>(FormulaType::IFF, std::vector<Formula<Poly>>({lhs, rhs}));
65  }
66  assert(false);
67  }
68  case FormulaType::BOOL:
70  case FormulaType::FALSE:
71  case FormulaType::UEQ:
73  case FormulaType::TRUE:
76  if (negated)
77  return f.negated();
78  else
79  return f;
80  }
82  case FormulaType::FORALL: {
85  for (auto v : f.quantified_variables()) {
86  if (used_vars.contains(v)) {
87  auto new_v = fresh_variable(v.type());
88  std::stringstream ss; ss << v.name() << "_" << new_v.id();
89  VariablePool::getInstance().set_name(new_v, ss.str());
90  sub = substitute(sub, v, Poly(new_v));
91  v = new_v;
92  } else {
93  used_vars.insert(v);
94  }
95  prefix.push_back(std::make_pair(q, v));
96  }
97  return to_pnf(sub, prefix, used_vars, negated);
98  }
100  if (negated) {
101  return Formula<Poly>(FormulaType::AND, {to_pnf(f.premise(), prefix, used_vars, false), to_pnf(f.conclusion(), prefix, used_vars, true)});
102  } else {
103  return Formula<Poly>(FormulaType::IMPLIES, {to_pnf(f.premise(), prefix, used_vars, false), to_pnf(f.conclusion(), prefix, used_vars, false)});
104  }
105  case FormulaType::ITE:
106  return Formula<Poly>(FormulaType::ITE, {to_pnf(f.condition(), prefix, used_vars, negated), to_pnf(f.first_case(), prefix, used_vars, negated), to_pnf(f.second_case(), prefix, used_vars, negated)});
107  case FormulaType::NOT:
108  return to_pnf(f.subformula(), prefix, used_vars, !negated);
109  default:
110  assert(false);
112  }
113 }
114 
115 template<typename Poly>
116 void free_variables(const Formula<Poly>& f, boost::container::flat_set<Variable>& current_quantified_vars, boost::container::flat_set<Variable>& free_vars) {
117  switch (f.type()) {
118  case FormulaType::AND:
119  case FormulaType::IFF:
120  case FormulaType::OR:
121  case FormulaType::XOR: {
122  for (auto& sub : f.subformulas()) {
123  free_variables(sub, current_quantified_vars, free_vars);
124  }
125  break;
126  }
127  case FormulaType::BOOL:
130  case FormulaType::UEQ:
132  for (auto v : variables(f)) {
133  if (!current_quantified_vars.contains(v)) {
134  free_vars.insert(v);
135  }
136  }
137  break;
138  }
139  case FormulaType::VARASSIGN: {
140  assert(false);
141  break;
142  }
143  case FormulaType::EXISTS:
144  case FormulaType::FORALL: {
145  auto old = current_quantified_vars;
146  current_quantified_vars.insert(f.quantified_variables().begin(), f.quantified_variables().end());
147  free_variables(f.quantified_formula(), current_quantified_vars, free_vars);
148  current_quantified_vars = old;
149  break;
150  }
152  free_variables(f.premise(), current_quantified_vars, free_vars);
153  free_variables(f.conclusion(), current_quantified_vars, free_vars);
154  break;
155  case FormulaType::ITE:
156  free_variables(f.condition(), current_quantified_vars, free_vars);
157  free_variables(f.first_case(), current_quantified_vars, free_vars);
158  free_variables(f.second_case(), current_quantified_vars, free_vars);
159  break;
160  case FormulaType::NOT:
161  free_variables(f.subformula(), current_quantified_vars, free_vars);
162  break;
163  case FormulaType::FALSE:
164  case FormulaType::TRUE: {
165  break;
166  }
167  default:
168  assert(false);
169  }
170 }
171 
172 template<typename Poly>
174  boost::container::flat_set<Variable> current_quantified_vars;
175  boost::container::flat_set<Variable> free_vars;
176  free_variables(f, current_quantified_vars, free_vars);
177  return free_vars;
178 }
179 
180 /**
181  * Transforms this formula to its equivalent in prenex normal form.
182  * @param negated Used for internal recursion.
183  * @return A pair of the prefix and the matrix.
184  */
185 template<typename Poly>
186 std::pair<QuantifierPrefix, Formula<Poly>> to_pnf(const Formula<Poly>& f) {
188  boost::container::flat_set<Variable> used_vars = free_variables(f);
189  auto m = to_pnf(f, p, used_vars, false);
190  return std::make_pair(p, m);
191 }
192 
193 template<typename Poly>
194 inline Formula<Poly> to_formula(const QuantifierPrefix& prefix, const Formula<Poly>& matrix) {
195  Formula<Poly> res = matrix;
196  for (auto p = prefix.rbegin(); p != prefix.rend(); p++) {
197  assert(p->first != Quantifier::FREE);
198  res = Formula<Poly>(p->first == Quantifier::EXISTS ? FormulaType::EXISTS : FormulaType::FORALL, std::vector<Variable>({p->second}), res);
199  }
200  return res;
201 }
202 
203 } // namespace carl
carl is the main namespace for the library.
@ CONSTRAINT
@ BITVECTOR
@ VARCOMPARE
@ VARASSIGN
std::vector< std::pair< Quantifier, carl::Variable > > QuantifierPrefix
Definition: PNF.h:28
Quantifier
Definition: PNF.h:9
void free_variables(const Formula< Poly > &f, boost::container::flat_set< Variable > &current_quantified_vars, boost::container::flat_set< Variable > &free_vars)
Definition: PNF.h:116
Formula< Poly > to_pnf(const Formula< Poly > &f, QuantifierPrefix &prefix, boost::container::flat_set< Variable > &used_vars, bool negated=false)
Definition: PNF.h:31
std::ostream & operator<<(std::ostream &os, const BasicConstraint< Poly > &c)
Prints the given constraint on the given stream.
Formula< Poly > to_formula(const QuantifierPrefix &prefix, const Formula< Poly > &matrix)
Definition: PNF.h:194
std::vector< Formula< Poly > > Formulas
Variable fresh_variable(VariableType vt) noexcept
Definition: VariablePool.h:179
Coeff substitute(const Monomial &m, const std::map< Variable, Coeff > &substitutions)
Applies the given substitutions to a monomial.
Definition: Substitution.h:19
void variables(const BasicConstraint< Pol > &c, carlVariables &vars)
Formula< Pol > connectPrecedingSubformulas(const Formula< Pol > &f)
[Auxiliary method]
Definition: aux.h:13
void set_name(Variable v, const std::string &name)
Add a name for a given Variable.
static VariablePool & getInstance()
Returns the single instance of this class by reference.
Definition: Singleton.h:45
const Formula & subformula() const
Definition: Formula.h:327
const Formula & premise() const
Definition: Formula.h:336
const Formula & conclusion() const
Definition: Formula.h:345
const Formula & quantified_formula() const
Definition: Formula.h:390
const std::vector< carl::Variable > & quantified_variables() const
Definition: Formula.h:381
const Formulas< Pol > & subformulas() const
Definition: Formula.h:400
const Formula & first_case() const
Definition: Formula.h:363
const Formula & second_case() const
Definition: Formula.h:372
FormulaType type() const
Definition: Formula.h:254
Formula negated() const
Definition: Formula.h:308
const Formula & condition() const
Definition: Formula.h:354