dlinear  0.0.1
Delta-complete SMT solver for linear programming
Loading...
Searching...
No Matches
PlaistedGreenbaumCnfizer.cpp
1
6#include "PlaistedGreenbaumCnfizer.h"
7
8#include <cstddef>
9#include <set>
10#include <string>
11
12#include "dlinear/util/Stats.h"
13#include "dlinear/util/Timer.h"
14#include "dlinear/util/exception.h"
15
16namespace dlinear {
17std::pair<std::vector<Formula>, std::vector<Variable>> PlaistedGreenbaumCnfizer::Process(const Formula &f) const {
18 TimerGuard timer_guard(&stats_.m_timer(), stats_.enabled());
20 // Put the Formula into negation normal form
21 const Formula &g{nnfizer_.Process(f, true /* push_negation_into_relationals */)};
22 std::vector<Formula> aux;
23 std::vector<Variable> vars;
24 const Formula head{VisitFormula(g, aux, vars)};
25 aux.push_back(head);
26 return {aux, vars};
27}
28std::pair<std::vector<Formula>, std::vector<Variable>> PlaistedGreenbaumCnfizer::operator()(const Formula &f) const {
29 return Process(f);
30}
31
32Formula PlaistedGreenbaumCnfizer::VisitForall(const Formula &f, std::vector<Formula> &aux,
33 std::vector<Variable> &vars) const {
34 // We always need a variable
35 static std::size_t id{0};
36 const Variable bvar{std::string("forall") + std::to_string(id++), Variable::Type::BOOLEAN};
37 vars.push_back(bvar);
38
39 // Given: f := ∀y. φ(x, y), this process CNFizes φ(x, y), pushes the
40 // universal quantifier over conjunctions, and inserts ¬b:
41 //
42 // = ∀y. (clause₁(x, y) ∧ ... ∧ clauseₙ(x, y))
43 // = (∀y. ¬b v clause₁(x, y)) ∧ ... ∧ (∀y. ¬b v clauseₙ(x, y))
44 const Variables &quantified_variables{get_quantified_variables(f)}; // y
45 const Formula &quantified_formula{get_quantified_formula(f)}; // φ(x, y)
46 // clause₁(x, y) ∧ ... ∧ clauseₙ(x, y)
47 const std::set<Formula> clauses{get_clauses(naive_cnfizer_.Process(quantified_formula))};
48 for (const Formula &clause : clauses) {
49 std::set<Formula> new_clause_set{!bvar};
50 if (is_disjunction(clause)) {
51 DLINEAR_ASSERT(is_clause(clause), "Must be a clause");
52 std::set<Formula> temp{get_operands(clause)};
53 new_clause_set.insert(temp.begin(), temp.end());
54 } else {
55 new_clause_set.insert(clause);
56 }
57 Formula new_clause{make_disjunction(new_clause_set)};
58 DLINEAR_ASSERT(is_clause(new_clause), "Must be a clause");
59 // Only the old clause's variables can intersect
60 if (HaveIntersection(clause.GetFreeVariables(), quantified_variables)) {
61 aux.emplace_back(forall(quantified_variables, new_clause));
62 } else {
63 aux.emplace_back(new_clause);
64 }
65 }
66
67 return Formula{bvar};
68}
69
70Formula PlaistedGreenbaumCnfizer::VisitConjunction(const Formula &f, std::vector<Formula> &aux,
71 std::vector<Variable> &vars) const {
72 static std::size_t id{0};
73 // Introduce a new Boolean variable, `bvar` for `f`.
74 const Variable bvar{std::string("conj") + std::to_string(id++), Variable::Type::BOOLEAN};
75 vars.push_back(bvar);
76 for (const Formula &op : get_operands(f)) {
77 aux.emplace_back(!bvar || VisitFormula(op, aux, vars));
78 }
79 return Formula{bvar};
80}
81
82Formula PlaistedGreenbaumCnfizer::VisitDisjunction(const Formula &f, std::vector<Formula> &aux,
83 std::vector<Variable> &vars) const {
84 static std::size_t id{0};
85 // Introduce a new Boolean variable, `bvar` for `f`.
86 const Variable bvar{std::string("disj") + std::to_string(id++), Variable::Type::BOOLEAN};
87 vars.push_back(bvar);
88 std::set<Formula> clause{::dlinear::map(
89 get_operands(f), [this, &aux, &vars](const Formula &formula) { return VisitFormula(formula, aux, vars); })};
90 clause.insert(!bvar);
91 aux.emplace_back(make_disjunction(clause));
92 return Formula{bvar};
93}
94
95Formula PlaistedGreenbaumCnfizer::VisitNegation(const Formula &f, std::vector<Formula> &,
96 std::vector<Variable> &) const {
97 DLINEAR_ASSERT(is_atomic(get_operand(f)), "Must be atomic");
98 return f;
99}
100
101} // namespace dlinear
void Increase()
Increase the iteration counter by one.
Definition Stats.cpp:39
Formula Process(const Formula &f) const
Convert a f into an equivalent formula f' in CNF.
Formula Process(const Formula &f, bool push_negation_into_relationals=false) const
Convert a f into an equivalent formula f' in NNF.
Definition Nnfizer.cpp:17
const NaiveCnfizer naive_cnfizer_
Naive CNFizer. Used to transform nested formulas inside universal quantification.
std::pair< std::vector< Formula >, std::vector< Variable > > Process(const Formula &f) const
Convert a f into an equi-satisfiable formula f' in CNF.
Timer & m_timer()
Get read-write access to the timer of the stats.
Definition Stats.h:50
bool enabled() const
Check whether the stats is enabled.
Definition Stats.h:48
The TimeGuard wraps a timer object and pauses it when the guard object is destructed.
Definition Timer.h:129
Represents a symbolic form of a first-order logic formula.
@ BOOLEAN
A BOOLEAN variable takes a bool value.
Global namespace for the dlinear library.
std::set< Formula > map(const std::set< Formula > &formulas, const std::function< Formula(const Formula &)> &func)
Given formulas = {f₁, ..., fₙ} and a func : Formula → Formula, map(formulas, func) returns a set {fun...
Definition symbolic.cpp:47
std::set< Formula > get_clauses(const Formula &f)
Returns the set of clauses in f.
Definition symbolic.cpp:98
Formula make_disjunction(const std::vector< Formula > &formulas)
Make disjunction of formulas.
Definition symbolic.cpp:493
bool is_clause(const Formula &f)
Check if f is a clause.
Definition symbolic.cpp:78
bool HaveIntersection(const Variables &variables1, const Variables &variables2)
Check if the intersection of variables1 and variables2 is non-empty.
Definition symbolic.cpp:126
bool is_atomic(const Formula &f)
Check if f is atomic.
Definition symbolic.cpp:53