1#include "storm-config.h"
17using Coeff = storm::RationalFunctionCoefficient;
23 std::int64_t numerator;
24 std::int64_t denominator;
25 std::vector<Variable> factors;
28using Terms = std::vector<Term>;
43storm::RationalNumber rational(std::int64_t value) {
44 return storm::RationalNumber{
static_cast<long>(value)};
48Coeff coefficientOf(Term
const& term) {
49 return Coeff(term.numerator) / Coeff(term.denominator);
56 for (
auto const& term : terms) {
57 if (term.numerator == 0) {
61 for (
auto const& factor : term.factors) {
70storm::RationalNumber evaluateConverted(
storm::RawPolynomial const& polynomial, storm::RationalNumber
const& pValue, storm::RationalNumber
const& qValue) {
71 auto manager = std::make_shared<storm::expressions::ExpressionManager>();
75 if (
manager->hasVariable(
"p")) {
76 evaluator.setRationalValue(
manager->getVariable(
"p"), pValue);
78 if (
manager->hasVariable(
"q")) {
79 evaluator.setRationalValue(
manager->getVariable(
"q"), qValue);
82 return evaluator.asRational(expression);
87storm::RationalNumber evaluateDirectly(Terms
const& terms, storm::RationalNumber
const& pValue, storm::RationalNumber
const& qValue) {
88 storm::RationalNumber result{0};
89 for (
auto const& term : terms) {
90 if (term.numerator == 0) {
93 storm::RationalNumber value = rational(term.numerator);
94 value /= rational(term.denominator);
95 for (
auto const& factor : term.factors) {
96 value *= factor == p() ? pValue : qValue;
105std::vector<std::pair<storm::RationalNumber, storm::RationalNumber>>
const& sampleValues() {
106 static std::vector<std::pair<storm::RationalNumber, storm::RationalNumber>>
const values = {
107 {storm::RationalNumber(0), storm::RationalNumber(0)},
108 {storm::RationalNumber(1), storm::RationalNumber(1)},
109 {storm::RationalNumber(-1), storm::RationalNumber(2)},
110 {storm::RationalNumber(2), storm::RationalNumber(-3)},
111 {storm::RationalNumber(1) / storm::RationalNumber(3), storm::RationalNumber(-5) / storm::RationalNumber(7)},
112 {storm::RationalNumber(-4), storm::RationalNumber(1) / storm::RationalNumber(5)},
113 {storm::RationalNumber(7) / storm::RationalNumber(2), storm::RationalNumber(-3) / storm::RationalNumber(4)},
119void expectValuesPreserved(Terms
const& terms) {
120 auto polynomial = buildPolynomial(terms);
122 for (
auto const& values : sampleValues()) {
123 auto expected = evaluateDirectly(terms, values.first, values.second);
124 auto actual = evaluateConverted(polynomial, values.first, values.second);
126 EXPECT_EQ(expected, actual) <<
"at p = " << values.first <<
" and q = " << values.second;
132TEST(PolynomialToExpressionTest, ConvertsPowers) {
135 expectValuesPreserved({{1, 1, {p(), p()}}});
136 expectValuesPreserved({{1, 1, {p(), p(), p()}}});
137 expectValuesPreserved({{1, 1, {q(), q()}}});
138 expectValuesPreserved({{1, 1, {p(), p(), q()}}});
139 expectValuesPreserved({{2, 1, {p(), p()}}, {1, 1, {}}});
140 expectValuesPreserved({{1, 1, {q(), q(), q(), q()}}});
143TEST(PolynomialToExpressionTest, ConvertsMixedVariableProducts) {
145 expectValuesPreserved({{1, 1, {p(), q()}}});
146 expectValuesPreserved({{1, 1, {p(), q()}}, {1, 1, {p()}}, {1, 1, {q()}}});
147 expectValuesPreserved({{2, 1, {p(), q()}}});
148 expectValuesPreserved({{3, 1, {p(), q()}}, {2, 1, {p()}}, {1, 1, {q()}}});
149 expectValuesPreserved({{1, 1, {p(), q()}}, {1, 1, {p(), p(), q()}}});
152TEST(PolynomialToExpressionTest, ConvertsNonUnitRationalCoefficients) {
154 expectValuesPreserved({{1, 2, {p()}}});
155 expectValuesPreserved({{1, 3, {p()}}, {5, 8, {}}});
156 expectValuesPreserved({{1, 3, {p()}}, {5, 8, {p(), q()}}});
157 expectValuesPreserved({{7, 2, {p(), p()}}});
158 expectValuesPreserved({{-1, 2, {q()}}, {1, 4, {p()}}});
159 expectValuesPreserved({{3, 4, {p()}}, {-7, 2, {q()}}});
160 expectValuesPreserved({{1, 1, {p()}}, {1, 1, {q()}}, {-11, 6, {p(), q()}}});
163TEST(PolynomialToExpressionTest, ConvertsZeroAndConstants) {
165 EXPECT_TRUE(buildPolynomial(Terms{}).isZero());
166 expectValuesPreserved(Terms{});
169 expectValuesPreserved({{1, 1, {p(), q()}}, {-1, 1, {p(), q()}}});
170 expectValuesPreserved({{0, 1, {p()}}});
171 expectValuesPreserved({{0, 1, {p(), p()}}, {0, 1, {q()}}});
174 expectValuesPreserved({{1, 1, {}}});
175 expectValuesPreserved({{-1, 1, {}}});
176 expectValuesPreserved({{5, 3, {}}});
177 expectValuesPreserved({{5, 3, {}}, {1, 1, {p()}}, {-1, 2, {p(), q()}}});
180TEST(PolynomialToExpressionTest, ConvertsNegativeCoefficients) {
183 expectValuesPreserved({{1, 1, {p()}}, {-1, 1, {}}});
184 expectValuesPreserved({{-1, 1, {p(), p()}}});
185 expectValuesPreserved({{1, 2, {p()}}, {-3, 4, {q()}}});
186 expectValuesPreserved({{-1, 1, {p(), q()}}, {1, 1, {p()}}, {1, 1, {q()}}});
187 expectValuesPreserved({{-1, 1, {p(), p(), q()}}, {1, 3, {q()}}});
190TEST(PolynomialToExpressionTest, ConvertsTermsIndependentlyOfTheirOrder) {
192 expectValuesPreserved({{2, 1, {p()}}, {3, 1, {q()}}, {4, 1, {p(), q()}}});
193 expectValuesPreserved({{4, 1, {p(), q()}}, {3, 1, {q()}}, {2, 1, {p()}}});
196TEST(PolynomialToExpressionTest, DeclaresTheVariablesItNeeds) {
197 auto manager = std::make_shared<storm::expressions::ExpressionManager>();
198 auto polynomial = buildPolynomial({{1, 1, {p(), p(), q()}}, {1, 2, {p()}}});
201 EXPECT_FALSE(manager->hasVariable(
"p"));
202 EXPECT_FALSE(manager->hasVariable(
"q"));
206 EXPECT_TRUE(manager->hasVariable(
"p"));
207 EXPECT_TRUE(manager->hasVariable(
"q"));
208 EXPECT_EQ(expression.getVariables().size(), 2ul);
211TEST(PolynomialToExpressionTest, DoesNotDeclareUnusedVariables) {
212 auto manager = std::make_shared<storm::expressions::ExpressionManager>();
213 auto polynomial = buildPolynomial({{1, 1, {p()}}});
217 EXPECT_TRUE(manager->hasVariable(
"p"));
218 EXPECT_FALSE(manager->hasVariable(
"q"));
219 EXPECT_EQ(expression.getVariables().size(), 1ul);
222TEST(PolynomialToExpressionTest, ReusesPreviouslyDeclaredVariables) {
224 auto manager = std::make_shared<storm::expressions::ExpressionManager>();
225 auto declaredP = manager->declareRationalVariable(
"p");
226 auto declaredQ = manager->declareRationalVariable(
"q");
228 auto polynomial = buildPolynomial({{1, 1, {p(), p(), q()}}});
232 EXPECT_TRUE(expression.containsVariable({declaredP, declaredQ}));
233 EXPECT_EQ(expression.getVariables(), (std::set<storm::expressions::Variable>{declaredP, declaredQ}));
236TEST(PolynomialToExpressionTest, ConvertsAPolynomialWithoutVariablesToAConstant) {
237 auto manager = std::make_shared<storm::expressions::ExpressionManager>();
238 auto polynomial = buildPolynomial({{5, 3, {}}});
243 EXPECT_FALSE(manager->hasVariable(
"p"));
244 EXPECT_FALSE(manager->hasVariable(
"q"));
245 EXPECT_FALSE(expression.containsVariables());
246 EXPECT_TRUE(expression.isLiteral());
TEST(PolynomialToExpressionTest, ConvertsPowers)
Expression polynomialToExpression(PolynomialType const &polynomial, std::shared_ptr< ExpressionManager > const &manager)
Converts the given polynomial into a Storm expression.
SettingsManager const & manager()
Retrieves the settings manager.
RationalFunctionVariable createRFVariable(std::string const &name)
carl::Variable RationalFunctionVariable
carl::MultivariatePolynomial< RationalFunctionCoefficient > RawPolynomial