dlinear  0.0.1
Delta-complete SMT solver for linear programming
Loading...
Searching...
No Matches
Nnfizer.cpp
1
7#include "Nnfizer.h"
8
9#include <set>
10
11#include "dlinear/util/logging.h"
12
13namespace dlinear {
14
15Nnfizer::Nnfizer(const dlinear::Config &config) : FormulaVisitor<bool, bool>{config, "Nnfizer"} {}
16
17Formula Nnfizer::Process(const Formula &f, bool push_negation_into_relationals) const {
18 DLINEAR_TRACE_FMT("Nnfizer::Convert({}, {})", f, push_negation_into_relationals);
19 const TimerGuard timer_guard{&stats_.m_timer(), stats_.enabled()};
20 stats_.Increase();
21 return VisitFormula(f, true, push_negation_into_relationals);
22}
23Formula Nnfizer::operator()(const Formula &f, const bool push_negation_into_relationals) const {
24 return Process(f, push_negation_into_relationals);
25}
26
27Formula Nnfizer::VisitFalse(const Formula &, const bool polarity, const bool) const {
28 // NNF(False) = False
29 // NNF(¬False) = True
30 return polarity ? Formula::False() : Formula::True();
31}
32
33Formula Nnfizer::VisitTrue(const Formula &, const bool polarity, const bool) const {
34 // NNF(True) = True
35 // NNF(¬True) = False
36 return polarity ? Formula::True() : Formula::False();
37}
38
39Formula Nnfizer::VisitVariable(const Formula &f, const bool polarity, const bool) const {
40 // NNF(b) = b
41 // NNF(¬b) = ¬b
42 return polarity ? f : !f;
43}
44
45Formula Nnfizer::VisitEqualTo(const Formula &f, const bool polarity, const bool push_negation_into_relationals) const {
46 if (polarity) return f;
47 // push_negation_into_relationals ? ¬(e₁ = e₂) ↦ (e₁ ≠ e₂) : ¬f
48 return push_negation_into_relationals ? get_lhs_expression(f) != get_rhs_expression(f) : !f;
49}
50
51Formula Nnfizer::VisitNotEqualTo(const Formula &f, const bool polarity,
52 const bool push_negation_into_relationals) const {
53 if (polarity) return f;
54 // push_negation_into_relationals ? ¬(e₁ ≠ e₂) ↦ (e₁ = e₂) : ¬f
55 return push_negation_into_relationals ? get_lhs_expression(f) == get_rhs_expression(f) : !f;
56}
57
58Formula Nnfizer::VisitGreaterThan(const Formula &f, const bool polarity,
59 const bool push_negation_into_relationals) const {
60 if (polarity) return f;
61 // push_negation_into_relationals ? ¬(e₁ > e₂) ↦ (e₁ <= e₂) : ¬f
62 return push_negation_into_relationals ? get_lhs_expression(f) <= get_rhs_expression(f) : !f;
63}
64
65Formula Nnfizer::VisitGreaterThanOrEqualTo(const Formula &f, const bool polarity,
66 const bool push_negation_into_relationals) const {
67 if (polarity) return f;
68 // push_negation_into_relationals ? ¬(e₁ >= e₂) ↦ (e₁ < e₂) : ¬f
69 return push_negation_into_relationals ? get_lhs_expression(f) < get_rhs_expression(f) : !f;
70}
71
72Formula Nnfizer::VisitLessThan(const Formula &f, const bool polarity, const bool push_negation_into_relationals) const {
73 if (polarity) return f;
74 // push_negation_into_relationals ? ¬(e₁ < e₂) ↦ (e₁ >= e₂) : ¬f
75 return push_negation_into_relationals ? get_lhs_expression(f) >= get_rhs_expression(f) : !f;
76}
77
78Formula Nnfizer::VisitLessThanOrEqualTo(const Formula &f, const bool polarity,
79 const bool push_negation_into_relationals) const {
80 if (polarity) return f;
81 // push_negation_into_relationals ? ¬(e₁ <= e₂) ↦ (e₁ > e₂) : ¬f
82 return push_negation_into_relationals ? get_lhs_expression(f) > get_rhs_expression(f) : !f;
83}
84
85Formula Nnfizer::VisitConjunction(const Formula &f, const bool polarity,
86 const bool push_negation_into_relationals) const {
87 // NNF(f₁ ∧ ... ∨ fₙ) = NNF(f₁) ∧ ... ∧ NNF(fₙ)
88 // NNF(¬(f₁ ∧ ... ∨ fₙ)) = NNF(¬f₁) ∨ ... ∨ NNF(¬fₙ)
89 const std::set<Formula> new_operands{
90 map(get_operands(f), [this, polarity, push_negation_into_relationals](const Formula &formula) {
91 return this->VisitFormula(formula, polarity, push_negation_into_relationals);
92 })};
93 return polarity ? make_conjunction(new_operands) : make_disjunction(new_operands);
94}
95
96Formula Nnfizer::VisitDisjunction(const Formula &f, const bool polarity,
97 const bool push_negation_into_relationals) const {
98 // NNF(f₁ ∨ ... ∨ fₙ) = NNF(f₁) ∨ ... ∨ NNF(fₙ)
99 // NNF(¬(f₁ ∨ ... ∨ fₙ)) = NNF(¬f₁) ∧ ... ∧ NNF(¬fₙ)
100 const std::set<Formula> new_operands{
101 map(get_operands(f), [this, polarity, push_negation_into_relationals](const Formula &formula) {
102 return this->VisitFormula(formula, polarity, push_negation_into_relationals);
103 })};
104 return polarity ? make_disjunction(new_operands) : make_conjunction(new_operands);
105}
106
107Formula Nnfizer::VisitNegation(const Formula &f, const bool polarity, const bool push_negation_into_relationals) const {
108 // NNF(¬f, ⊤) = NNF(f, ⊥)
109 // NNF(¬f, ⊥) = NNF(f, ⊤)
110 return VisitFormula(get_operand(f), !polarity, push_negation_into_relationals);
111}
112
113Formula Nnfizer::VisitForall(const Formula &f, const bool polarity, const bool) const {
114 // NNF(∀v₁...vₙ. f) = ∀v₁...vₙ. f
115 // NNF(¬(∀v₁...vₙ. f)) = ¬∀v₁...vₙ. f
116 //
117 // TODO(soonho-tri): The second case can be further reduced into
118 // ∃v₁...vₙ. NNF(¬f). However, we do not have a representation
119 // FormulaExists(∃) yet. Revisit this when we add FormulaExists.
120 return polarity ? f : !f;
121}
122
123} // namespace dlinear
Simple dataclass used to store the configuration of the program.
Definition Config.h:38
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.
Global namespace for the dlinear library.
Formula make_conjunction(const std::vector< Formula > &formulas)
Make conjunction of formulas.
Definition symbolic.cpp:485
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
Formula make_disjunction(const std::vector< Formula > &formulas)
Make disjunction of formulas.
Definition symbolic.cpp:493