dlinear  0.0.1
Delta-complete SMT solver for linear programming
Loading...
Searching...
No Matches
LinearFormulaFlattener.cpp
1
6#include "LinearFormulaFlattener.h"
7
8#include <map>
9#include <utility>
10
11#include "dlinear/libs/libgmp.h"
12#include "dlinear/util/exception.h"
13
14namespace dlinear {
15
17 // If the formula is not relational, return it as is.
18 if (!is_relational(formula)) return formula;
19 // If the formula is already flattened, return it.
20 auto it = flattened_formulas_.find(formula);
21 if (it != flattened_formulas_.end()) return it->second;
22
23 const bool needs_expansion_{config_.needs_expansion()};
24 const Expression& lhs = get_lhs_expression(formula);
25 const Expression& rhs = get_rhs_expression(formula);
26 const Expression expr{needs_expansion_ ? (lhs - rhs).Expand() : lhs - rhs};
27 DLINEAR_ASSERT_FMT(expr.EqualTo(expr.Expand()), "Expression {} must be expanded to {}", expr, expr.Expand());
28 DLINEAR_ASSERT_FMT(is_addition(expr) || is_multiplication(expr) || is_variable(expr),
29 "Expression must be an addition, multiplication or a variable. Instead found {}", expr);
30
31 const mpq_class constant{is_addition(expr) ? get_constant_in_addition(expr) : 0};
32 const Formula f = BuildFlatteredFormula(expr - constant, Expression{-constant}, formula.get_kind());
33 flattened_formulas_.emplace(formula, f);
34 return f;
35}
36
38 FormulaKind kind) const {
39 // Remove multiplication from the left-hand-side of the formula if they are of the form a*x <=> b
40 if (is_multiplication(lhs) && get_base_to_exponent_map_in_multiplication(lhs).size() == 1 &&
41 is_variable(get_base_to_exponent_map_in_multiplication(lhs).begin()->first)) {
42 const mpq_class& constant{get_constant_in_multiplication(lhs)};
43 // If the constant is 1, we can just return the formula as is, removing the multiplication.
44 if (constant == 1)
45 return BuildFlatteredFormula(get_base_to_exponent_map_in_multiplication(lhs).begin()->first, rhs, kind);
46 DLINEAR_ASSERT(constant != 0, "Multiplication constant must be non-zero");
47 const Expression coefficient{1 / constant};
48 return BuildFlatteredFormula(lhs * coefficient, rhs * coefficient, coefficient >= 0 ? kind : -kind);
49 }
50
51 // Ensure the first term in the addition of the left-hand-side has a positive coefficient
52 if (is_addition(lhs) && !get_expr_to_coeff_map_in_addition(lhs).empty() &&
53 is_variable(get_expr_to_coeff_map_in_addition(lhs).begin()->first) &&
54 get_expr_to_coeff_map_in_addition(lhs).begin()->second < 0) {
55 return BuildFlatteredFormula(lhs * -1, rhs * -1, -kind);
56 }
57
58 DLINEAR_ASSERT_FMT(!is_multiplication(lhs) || get_base_to_exponent_map_in_multiplication(lhs).size() != 1 ||
59 !is_variable(get_base_to_exponent_map_in_multiplication(lhs).begin()->first),
60 "lhs {} should have been modified by a previous call as a mult", lhs);
61 DLINEAR_ASSERT_FMT(!is_addition(lhs) || get_expr_to_coeff_map_in_addition(lhs).empty() ||
62 !is_variable(get_expr_to_coeff_map_in_addition(lhs).begin()->first) ||
63 get_expr_to_coeff_map_in_addition(lhs).begin()->second >= 0,
64 "lhs {} should have been modified by a previous call as an addition", lhs);
65
66 switch (kind) {
67 case FormulaKind::Eq:
68 return lhs == rhs;
69 case FormulaKind::Neq:
70 return !(lhs == rhs);
71 case FormulaKind::Leq:
72 return lhs <= rhs;
73 case FormulaKind::Lt:
74 return lhs < rhs;
75 case FormulaKind::Geq:
76 return !(lhs < rhs);
77 case FormulaKind::Gt:
78 return !(lhs <= rhs);
79 default:
80 DLINEAR_UNREACHABLE();
81 }
82}
83
84} // namespace dlinear
bool needs_expansion() const
Definition Config.cpp:20
Formula BuildFlatteredFormula(const Expression &lhs, const Expression &rhs, FormulaKind kind) const
Use the updated expressions to build a new formula, also removing any mult expression from the left-h...
const Config & config_
Configuration.
Formula Flatten(const Formula &formula)
Flatten the given formula.
std::unordered_map< Formula, Formula > flattened_formulas_
Cache for the flattered formulas.
Represents a symbolic form of an expression.
Represents a symbolic form of a first-order logic formula.
Global namespace for the dlinear library.