3 #include <carl-arith/constraint/BasicConstraint.h>
4 #include <boost/container/flat_map.hpp>
47 if (
m_rating == carl::Variable::NO_VARIABLE)
m_rating = carl::fresh_real_variable();
57 inline carl::BasicConstraint<Poly>
normalize(
const carl::BasicConstraint<Poly>& c) {
58 assert(c.relation() == carl::Relation::LESS || c.relation() == carl::Relation::LEQ || c.relation() ==
carl::Relation::EQ || c.relation() == carl::Relation::NEQ);
59 return carl::BasicConstraint<Poly>(c.lhs().normalize(), carl::is_negative(c.lhs().lcoeff()) ? carl::turn_around(c.relation()) : c.relation());
62 inline std::optional<Direction>
direction(carl::Relation r) {
64 case carl::Relation::GREATER:
65 case carl::Relation::GEQ:
68 case carl::Relation::LESS:
69 case carl::Relation::LEQ:
72 case carl::Relation::NEQ:
93 :
bias(
carl::fresh_real_variable()),
vertices(normalization.begin(), normalization.end()) {}
100 sum_of_coeffs += v.coefficient;
102 if (sum_of_coeffs == 0)
return std::nullopt;
136 for (
const auto& exponent : vertex.
monomial->exponents()) {
137 const auto& moment{
m_moments[exponent.first]};
138 hyperplane += carl::from_int<Rational>(exponent.second) * moment.normal_vector;
139 if (exponent.second % 2 == 1)
140 signChangeSubformulas.emplace_back(moment.sign_variant);
147 totalRating += vertex.
rating();
148 conjunctions.emplace_back(
149 carl::FormulaType::IMPLIES,
150 FormulaT(hyperplane, carl::Relation::LESS),
153 conjunctions.emplace_back(
154 carl::FormulaType::IMPLIES,
159 carl::FormulaType::IMPLIES,
163 carl::FormulaType::IMPLIES,
164 signChangeFormula.negated(),
169 bool positive{carl::is_positive(vertex.
coefficient) != negated};
170 disjunctions.emplace_back(
172 carl::FormulaType::IMPLIES,
173 positive ? signChangeFormula.negated() : signChangeFormula,
176 conjunctions.emplace_back(
177 carl::FormulaType::IMPLIES,
178 positive ? std::move(signChangeFormula) : std::move(signChangeFormula.negated()),
182 conjunctions.emplace_back(totalRating, carl::Relation::GREATER);
192 return FormulaT(
Poly(moment.normal_vector), carl::Relation::GEQ);
198 const carl::Variable& variable;
201 Weight(
const carl::Variable&
var,
const Rational& exp,
const bool sgn)
204 std::vector<Weight> weights;
206 auto used_vars = carl::variables(f);
210 for (
const auto& momentsEntry :
m_moments) {
211 const carl::Variable& variable{momentsEntry.first};
212 const Moment& moment{momentsEntry.second};
213 if (used_vars.has(variable)) {
214 auto signIter{lra_model.find(moment.sign_variant)};
215 weights.emplace_back(variable, lra_model.at(moment.normal_vector).asRational(), signIter != lra_model.end() && signIter->second.asBool());
216 carl::gcd_assign(
gcd, weights.back().exponent);
221 Model lra_model_nonenc;
222 for (
const auto& v : used_vars) {
223 if (lra_model.find(v) != lra_model.end()) {
224 lra_model_nonenc.emplace(v, lra_model.at(v));
229 if (!carl::is_zero(
gcd) && !carl::is_one(
gcd))
230 for (Weight& weight : weights)
231 weight.exponent /=
gcd;
237 result = lra_model_nonenc;
239 for (
const Weight& weight : weights) {
240 Rational value{carl::is_negative(weight.exponent) ? carl::reciprocal(base) : base};
241 carl::pow_assign(value, carl::to_int<carl::uint>(
carl::abs(weight.exponent)));
244 result.emplace(weight.variable, value);
246 }
while (!satisfied_by(f,
result));
259 if (formula.type() == carl::FormulaType::TRUE || formula.type() == carl::FormulaType::FALSE) {
261 }
else if (formula.type() == carl::FormulaType::CONSTRAINT) {
262 carl::Relation relation = formula.constraint().relation();
263 Poly polynomial = formula.constraint().lhs();
267 Poly transformedPolynomial{polynomial};
270 case carl::Relation::GREATER:
274 case carl::Relation::GEQ:
277 case carl::Relation::LESS:
281 case carl::Relation::LEQ:
284 case carl::Relation::NEQ:
295 for (
const auto& subformula : formula.subformulas()) {
297 if (transformed.type() == carl::FormulaType::TRUE) {
299 }
else if (transformed.type() != carl::FormulaType::FALSE) {
300 product *= transformed.constraint().lhs();
305 return FormulaT(carl::FormulaType::FALSE);
308 return FormulaT(carl::FormulaType::FALSE);
320 if (formula.type() == carl::FormulaType::TRUE || formula.type() == carl::FormulaType::FALSE) {
322 }
else if (formula.type() == carl::FormulaType::BOOL) {
325 assert(formula.subformula().type() == carl::FormulaType::BOOL);
327 }
else if (formula.type() == carl::FormulaType::CONSTRAINT) {
329 return FormulaT(carl::FormulaType::FALSE);
331 auto constr =
normalize(formula.constraint().constr());
337 for (
const auto& subformula : formula.subformulas()) {
343 for (
const auto& subformula : formula.subformulas()) {
349 return FormulaT(carl::FormulaType::FALSE);
361 std::vector<FormulaT> constraints;
362 carl::arithmetic_constraints(formula, constraints);
363 std::set<FormulaT> constraint_set(constraints.begin(), constraints.end());
364 auto res_boolean = formula;
365 std::map<Poly, boost::container::flat_map<carl::Relation, std::pair<FormulaT, FormulaT>>> encodings;
366 for (
const auto& c : constraint_set) {
370 auto constr =
normalize(c.constraint().constr());
373 auto& map = encodings.try_emplace(constr.lhs()).first->second;
374 assert(map.find(constr.relation()) == map.end());
375 FormulaT var = map.find(carl::inverse(constr.relation())) == map.end() ?
FormulaT(carl::fresh_boolean_variable()) : map.at(carl::inverse(constr.relation())).first.negated();
376 map.emplace(constr.relation(), std::make_pair(
var, encoding.
encode_separator(separator, dir, separator_type)));
380 std::vector<FormulaT> res({res_boolean});
381 for (
auto& poly : encodings) {
382 for (
auto rel = poly.second.begin(); rel != poly.second.end(); ) {
383 auto& enc = rel->second;
384 bool relevant =
false;
385 carl::visit(res_boolean, [&enc, &relevant](
const FormulaT& f) {
if (f==enc.first) relevant =
true; } );
387 res.emplace_back(carl::FormulaType::IMPLIES, enc.first, enc.second);
391 rel = poly.second.erase(rel);
394 if (poly.second.find(carl::Relation::LESS) != poly.second.end() && poly.second.find(carl::Relation::GREATER) != poly.second.end()) {
395 res.emplace_back(
carl::FormulaType::OR, poly.second.at(carl::Relation::LESS).first.negated(), poly.second.at(carl::Relation::GREATER).first.negated());
397 if (poly.second.find(carl::Relation::LEQ) != poly.second.end() && poly.second.find(carl::Relation::GEQ) != poly.second.end()) {
398 res.emplace_back(
carl::FormulaType::OR, poly.second.at(carl::Relation::LEQ).first.negated(), poly.second.at(carl::Relation::GEQ).first.negated());
std::unordered_map< carl::Variable, Moment > m_moments
Maps a variable to the components of the moment function.
FormulaT encode_separator(const Separator &separator, const Direction direction, const SeparatorType separator_type)
Creates the formula for the hyperplane that linearly separates at least one variant positive frame ve...
Model construct_assignment(const Model &lra_model, const FormulaT &f) const
FormulaT encode_integer(carl::Variable var)
std::pair< CoveringResult< typename op::PropertiesSet >, std::vector< ParameterTree > > parameter(cadcells::datastructures::Projections &proj, FE &f, cadcells::Assignment ass, const VariableQuantification &quantification)
Numeric abs(const Numeric &_value)
Calculates the absolute value of the given Numeric.
Numeric gcd(const Numeric &_valueA, const Numeric &_valueB)
Calculates the greatest common divisor of the two arguments.
carl::Sign sgn(carl::Variable v, const Poly &p, const RAN &r)
bool substitute(const FormulaT &constr, const carl::Variable var, const carl::vs::Term< Poly > &term, FormulaT &result)
Implements data structures and encodings for the subtropical method.
carl::BasicConstraint< Poly > normalize(const carl::BasicConstraint< Poly > &c)
std::optional< Direction > direction(carl::Relation r)
FormulaT encode_as_formula(const FormulaT &formula, Encoding &encoding, SeparatorType separator_type)
Requires a quantifier-free real arithmetic formula with no negations.
FormulaT transform_to_equation(const FormulaT &formula)
Requires a quantifier-free real arithmetic formula with no negations.
Direction
Subdivides the relations into classes with the same linearization result.
std::optional< Direction > direction_for_equality(const Separator &s)
FormulaT encode_as_formula_alt(const FormulaT &formula, Encoding &encoding, SeparatorType separator_type)
Requires a quantifier-free real arithmetic formula with no negations.
carl::Term< Rational > TermT
carl::Formula< Poly > FormulaT
carl::Model< Rational, Poly > Model
carl::MultivariatePolynomial< Rational > Poly
carl::Formulas< Poly > FormulasT
Represents the normal vector component and the sign variable assigned to a variable in an original co...
const carl::Variable normal_vector
Normal vector component of the separating hyperplane.
const carl::Variable sign_variant
Boolean variable representing the sign variant.
Represents the class of all original constraints with the same left hand side after a normalization.
Separator(const Poly &normalization)
const carl::Variable bias
Bias variable of the separating hyperplane.
const std::vector< Vertex > vertices
Vertices for all terms of the normalized left hand side.
Represents a term of an original constraint and assigns him a rating variable if a weak separator is ...
carl::Variable rating() const
const Rational coefficient
Coefficient of the assigned term.
const carl::Monomial::Arg monomial
Monomial of the assigned term.
Vertex(const TermT &term)
carl::Variable m_rating
Rating variable of the term for a weak separator.