6#include "delpi/symbolic/ExpressionCell.h"
9#include <unordered_map>
13#include "delpi/util/error.h"
14#include "delpi/util/hash.hpp"
19 return intrusive_ptr(
new ExpressionCell{std::move(var)});
22 return intrusive_ptr(
new ExpressionCell{std::move(linear_monomial)});
25 return intrusive_ptr(
new ExpressionCell{std::move(addends)});
28 return {intrusive_ptr(
new ExpressionCell{o.addends_})};
31ExpressionCell::ExpressionCell(
Variable var) : hash_{0} { addends_.emplace(std::move(var), 1); }
32ExpressionCell::ExpressionCell(Addend linear_monomial) : hash_{0} {
33 addends_.emplace(std::move(linear_monomial.first), std::move(linear_monomial.second));
35ExpressionCell::ExpressionCell(Addends addends) : hash_{0}, addends_{std::move(addends)} {}
37std::vector<Variable> ExpressionCell::variables()
const {
38 std::vector<Variable> vars;
39 vars.reserve(addends_.size());
40 for (
auto& [var, coeff] : addends_) vars.emplace_back(var);
44bool ExpressionCell::equal_to(
const ExpressionCell& o)
const noexcept {
45 if (
this == &o)
return true;
46 return std::ranges::equal(
48 [](
const std::pair<const Variable, mpq_class>& p1,
const std::pair<const Variable, mpq_class>& p2) {
49 return p1.first.equal_to(p2.first) && p1.second == p2.second;
52bool ExpressionCell::less(
const ExpressionCell& o)
const noexcept {
54 if (
this == &o)
return false;
55 return std::ranges::lexicographical_compare(
57 [](
const std::pair<const Variable, mpq_class>& p1,
const std::pair<const Variable, mpq_class>& p2) {
58 const auto& [var1, val1] = p1;
59 const auto& [var2, val2] = p2;
60 if (var1.less(var2)) return true;
61 if (var2.less(var1)) return false;
65std::size_t ExpressionCell::hash() const noexcept {
66 if (hash_ == 0) hash_ = hash::hash_value<Addends>{}(addends_);
71 if (coeff == 0)
return *
this;
76 mpq_class new_coeff{coeff + it->second};
80 it->second = std::move(new_coeff);
86 if (coeff == 1)
return *
this;
89 for (
auto& it :
addends_) it.second *= coeff;
93 if (coeff == 1)
return *
this;
94 if (coeff == 0) DELPI_RUNTIME_ERROR(
"Division by 0");
96 for (
auto& it :
addends_) it.second /= coeff;
100template <MapFromTo<Variable, mpq_
class> T>
103 [&env](
const mpq_class& init,
const std::pair<const Variable, mpq_class>& p) {
105 return static_cast<mpq_class>(init + env.at(p.first) * p.second);
110 for (
const auto& [var, coeff] :
addends_) {
111 ret.
Add(s.contains(var) ? s.at(var) : var, coeff);
116std::ostream& ExpressionCell::Print(std::ostream& os)
const {
117 bool print_plus{
false};
119 for (
auto& [var, coeff] : addends_) {
120 PrintAddend(os, print_plus, var, coeff);
126std::ostream& ExpressionCell::PrintAddend(std::ostream& os,
const bool print_plus,
const Variable& var,
127 const mpq_class& coeff) {
134 os << coeff <<
" * ";
140 os << (-coeff) <<
" * ";
146template mpq_class ExpressionCell::Evaluate(
const std::map<Variable, mpq_class>& env)
const;
147template mpq_class ExpressionCell::Evaluate(
const std::unordered_map<Variable, mpq_class>& env)
const;
Symbolic expression representing an addition between linear monomials.
std::size_t hash_
Cached hash of the object.
ExpressionCell & Add(const Variable &var, const mpq_class &coeff)
Add a linear monomial , where is a constant and is a Variable, to the current expression.
mpq_class Evaluate(const T &env={}) const
Evaluates using a given environment (by default, an empty environment).
Expression::Addends addends_
Map between each variable and it coefficient as terms of the summation.
ExpressionCell & Divide(const mpq_class &coeff)
Divide all terms of the summation by a coeff.
ExpressionCell & Multiply(const mpq_class &coeff)
Multiply all terms of the summation by a coeff.
Expression Substitute(const SubstitutionMap &s) const
Create a copy of this expression, replacing all occurrences of the variables in s with corresponding ...
Represents a symbolic form of an expression.
Expression & Add(const Variable &var, const mpq_class &coeff)
Add a linear monomial , where is a constant and is a Variable, to the current expression.
Pointer to a generic object that supports intrusive reference counting.
Global namespace for the delpi library.