Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
constants.cpp
Go to the documentation of this file.
2
3#include <cmath>
4#include <type_traits>
5
13
14namespace storm {
15namespace utility {
16
17template<typename ValueType>
18ValueType one() {
19 return ValueType(1);
20}
21
22template<typename ValueType>
23ValueType zero() {
24 return ValueType(0);
25}
26
27template<typename ValueType>
28ValueType infinity() {
29 return std::numeric_limits<ValueType>::infinity();
30}
31
32template<typename ValueType>
33bool isOne(ValueType const& a) {
34 return a == one<ValueType>();
35}
36
37template<typename ValueType>
38bool isZero(ValueType const& a) {
39 return a == zero<ValueType>();
40}
41
42template<typename ValueType>
43bool isNan(ValueType const&) {
44 return false;
45}
46
47template<>
48bool isNan(double const& value) {
49 return std::isnan(value);
50}
51
52template<typename ValueType>
53bool isApproxEqual(ValueType const& a, ValueType const& b, ValueType const& precision, bool relative) {
54 ValueType const absDiff = abs<ValueType>(a - b);
55 if (relative) {
56 return absDiff <= precision * max(abs(a), abs(b));
57 } else {
58 return absDiff <= precision;
59 }
60}
61
62template<typename ValueType>
63bool isPositive(ValueType const& a) {
64 return a > zero<ValueType>();
65}
66
67template<typename ValueType>
68bool isNonNegative(ValueType const& a) {
69 return a >= zero<ValueType>();
70}
71
80template<typename ValueType>
81bool isBetween(ValueType const& a, ValueType const& b, ValueType const& c, bool strict) {
82 STORM_LOG_ASSERT(isConstant(a), "Checking whether something is between two values is only sensible on constants.");
83 STORM_LOG_ASSERT(isConstant(c), "Checking whether something is between two values is only sensible on constants.");
84 if (strict) {
85 return a < b && b < c;
86 } else {
87 return a <= b && b <= c;
88 }
89}
90
91template<typename ValueType>
92bool isAlmostZero(ValueType const& a) {
93 return a < convertNumber<ValueType>(1e-12) && a > -convertNumber<ValueType>(1e-12);
94}
95
96template<typename ValueType>
97bool isAlmostOne(ValueType const& a) {
98 return a < convertNumber<ValueType>(1.0 + 1e-12) && a > convertNumber<ValueType>(1.0 - 1e-12);
99}
100
101template<typename ValueType>
102bool isConstant(ValueType const&) {
103 return true;
104}
105
106template<typename ValueType>
107bool isInfinity(ValueType const& a) {
108 return a == infinity<ValueType>();
109}
110
111template<typename ValueType>
112bool isInteger(ValueType const& number) {
113 ValueType iPart;
114 ValueType result = std::modf(number, &iPart);
115 return result == zero<ValueType>();
116}
117
118template<>
119bool isInteger(int const&) {
120 return true;
121}
122
123template<>
124bool isInteger(uint32_t const&) {
125 return true;
126}
127
128template<>
130 return true;
131}
132
133template<typename TargetType, typename SourceType>
134TargetType convertNumber(SourceType const& number) {
135 return static_cast<TargetType>(number);
136}
137
138template<>
139uint_fast64_t convertNumber(double const& number) {
140 return std::llround(number);
141}
142
143template<>
144int_fast64_t convertNumber(double const& number) {
145 return std::llround(number);
146}
147
148template<>
149double convertNumber(uint_fast64_t const& number) {
150 return number;
151}
152
153template<>
154double convertNumber(double const& number) {
155 return number;
156}
157
158template<>
159double convertNumber(long long const& number) {
160 return static_cast<double>(number);
161}
162
163template<>
165 return static_cast<storm::storage::sparse::state_type>(number);
166}
167
168template<typename ValueType>
169ValueType simplify(ValueType value) {
170 // In the general case, we don't do anything here, but merely return the value. If something else is
171 // supposed to happen here, the templated function can be specialized for this particular type.
172 return value;
173}
174
175template<typename ValueType>
176std::pair<ValueType, ValueType> minmax(std::vector<ValueType> const& values) {
177 assert(!values.empty());
178 ValueType min = values.front();
179 ValueType max = values.front();
180 for (auto const& vt : values) {
181 if (vt < min) {
182 min = vt;
183 }
184 if (vt > max) {
185 max = vt;
186 }
187 }
188 return std::make_pair(min, max);
189}
190
191template<typename ValueType>
192ValueType minimum(std::vector<ValueType> const& values) {
193 assert(!values.empty());
194 ValueType min = values.front();
195 for (auto const& vt : values) {
196 if (vt < min) {
197 min = vt;
198 }
199 }
200 return min;
201}
202
203template<typename ValueType>
204ValueType maximum(std::vector<ValueType> const& values) {
205 assert(!values.empty());
206 ValueType max = values.front();
207 for (auto const& vt : values) {
208 if (vt > max) {
209 max = vt;
210 }
211 }
212 return max;
213}
214
215template<typename K, typename ValueType>
216std::pair<ValueType, ValueType> minmax(std::map<K, ValueType> const& values) {
217 assert(!values.empty());
218 ValueType min = values.begin()->second;
219 ValueType max = values.begin()->second;
220 for (auto const& vt : values) {
221 if (vt.second < min) {
222 min = vt.second;
223 }
224 if (vt.second > max) {
225 max = vt.second;
226 }
227 }
228 return std::make_pair(min, max);
229}
230
231template<typename K, typename ValueType>
232ValueType minimum(std::map<K, ValueType> const& values) {
233 return minmax(values).first;
234}
235
236template<typename K, typename ValueType>
237ValueType maximum(std::map<K, ValueType> const& values) {
238 return minmax(values).second;
239}
240
241template<typename ValueType>
242ValueType pow(ValueType const& value, int_fast64_t exponent) {
243 return std::pow(value, exponent);
244}
245
246template<typename ValueType>
247ValueType max(ValueType const& first, ValueType const& second) {
248 return std::max(first, second);
249}
250
251template<typename ValueType>
252ValueType min(ValueType const& first, ValueType const& second) {
253 return std::min(first, second);
254}
255
256template<typename ValueType>
257ValueType sqrt(ValueType const& number) {
258 return std::sqrt(number);
259}
260
261template<typename ValueType>
262ValueType abs(ValueType const& number) {
263 return std::fabs(number);
264}
265
266template<typename ValueType>
267ValueType floor(ValueType const& number) {
268 return std::floor(number);
269}
270
271template<typename ValueType>
272ValueType ceil(ValueType const& number) {
273 return std::ceil(number);
274}
275
276template<typename ValueType>
277ValueType round(ValueType const& number) {
278 // Rounding towards infinity
279 return floor<ValueType>(number + storm::utility::convertNumber<ValueType>(0.5));
280}
281
282template<typename ValueType>
283ValueType log(ValueType const& number) {
284 return std::log(number);
285}
286
287template<typename ValueType>
288ValueType log10(ValueType const& number) {
289 return std::log10(number);
290}
291
292template<typename ValueType>
293ValueType cos(ValueType const& number) {
294 return std::cos(number);
295}
296
297template<typename ValueType>
298ValueType sin(ValueType const& number) {
299 return std::sin(number);
300}
301
302template<typename ValueType>
303uint64_t numDigits(ValueType const& number) {
304 auto numDigits = 0;
305 ValueType remaining = storm::utility::one<ValueType>() / number;
306 ValueType ten = storm::utility::convertNumber<ValueType>(10);
307 while (remaining >= storm::utility::one<ValueType>()) {
308 ++numDigits;
309 remaining = storm::utility::floor<ValueType>(remaining / ten);
310 }
311 return numDigits;
312}
313
314template<typename ValueType>
315typename NumberTraits<ValueType>::IntegerType trunc(ValueType const& number) {
316 return static_cast<typename NumberTraits<ValueType>::IntegerType>(std::trunc(number));
317}
318
319template<typename IntegerType>
320IntegerType mod(IntegerType const& first, IntegerType const& second) {
321 return std::fmod(first, second);
322}
323
324template<typename IntegerType>
325std::pair<IntegerType, IntegerType> divide(IntegerType const& dividend, IntegerType const& divisor) {
326 return std::make_pair(dividend / divisor, mod(dividend, divisor));
327}
328
329template<typename ValueType>
330std::string to_string(ValueType const& value) {
331 std::stringstream ss;
332 ss.precision(std::numeric_limits<ValueType>::max_digits10 + 2);
333 ss << value;
334 return ss.str();
335}
336
337#if defined(STORM_HAVE_CARL) && defined(STORM_HAVE_CLN)
338template<>
339storm::ClnRationalNumber infinity() {
340 // FIXME: this should be treated more properly.
341 return storm::ClnRationalNumber(100000000000);
342}
343
344template<>
345bool isOne(storm::ClnRationalNumber const& a) {
346 return carl::isOne(a);
347}
348
349template<>
350bool isZero(storm::ClnRationalNumber const& a) {
351 return carl::isZero(a);
352}
353
354template<>
355bool isInteger(storm::ClnRationalNumber const& number) {
356 return carl::isInteger(number);
357}
358
359template<>
360std::pair<storm::ClnRationalNumber, storm::ClnRationalNumber> minmax(std::vector<storm::ClnRationalNumber> const& values) {
361 assert(!values.empty());
362 storm::ClnRationalNumber min = values.front();
363 storm::ClnRationalNumber max = values.front();
364 for (auto const& vt : values) {
365 if (vt == storm::utility::infinity<storm::ClnRationalNumber>()) {
366 max = vt;
367 } else {
368 if (vt < min) {
369 min = vt;
370 }
371 if (vt > max) {
372 max = vt;
373 }
374 }
375 }
376 return std::make_pair(min, max);
377}
378
379template<>
380uint_fast64_t convertNumber(ClnRationalNumber const& number) {
381 return carl::toInt<carl::uint>(number);
382}
383
384template<>
385int_fast64_t convertNumber(ClnRationalNumber const& number) {
386 return carl::toInt<carl::sint>(number);
387}
388
389template<>
390ClnRationalNumber convertNumber(double const& number) {
391 return carl::rationalize<ClnRationalNumber>(number);
392}
393
394template<>
395ClnRationalNumber convertNumber(int const& number) {
396 return carl::rationalize<ClnRationalNumber>(number);
397}
398
399template<>
400ClnRationalNumber convertNumber(NumberTraits<ClnRationalNumber>::IntegerType const& number) {
401 return ClnRationalNumber(number);
402}
403
404template<>
405ClnRationalNumber convertNumber(uint_fast64_t const& number) {
406 STORM_LOG_ASSERT(static_cast<carl::uint>(number) == number, "Rationalizing failed, because the number is too large.");
407 return carl::rationalize<ClnRationalNumber>(static_cast<carl::uint>(number));
408}
409
410template<>
411typename NumberTraits<ClnRationalNumber>::IntegerType convertNumber(uint_fast64_t const& number) {
412 STORM_LOG_ASSERT(static_cast<unsigned long int>(number) == number, "Conversion failed, because the number is too large.");
413 return NumberTraits<ClnRationalNumber>::IntegerType(static_cast<unsigned long int>(number));
414}
415
416template<>
417typename NumberTraits<ClnRationalNumber>::IntegerType convertNumber(double const& number) {
418 if (number < static_cast<double>(std::numeric_limits<uint64_t>::max())) {
419 return NumberTraits<ClnRationalNumber>::IntegerType(static_cast<uint64_t>(number));
420 } else {
421 return carl::round(carl::rationalize<ClnRationalNumber>(number));
422 }
423}
424
425template<>
426ClnRationalNumber convertNumber(int_fast64_t const& number) {
427 STORM_LOG_ASSERT(static_cast<carl::sint>(number) == number, "Rationalizing failed, because the number is too large.");
428 return carl::rationalize<ClnRationalNumber>(static_cast<carl::sint>(number));
429}
430
431template<>
432double convertNumber(ClnRationalNumber const& number) {
433 return carl::toDouble(number);
434}
435
436template<>
437ClnRationalNumber convertNumber(std::string const& number) {
438 ClnRationalNumber result;
439 if (carl::try_parse<ClnRationalNumber>(number, result)) {
440 return result;
441 }
442 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Unable to parse '" << number << "' as a rational number.");
443}
444
445template<>
446std::pair<ClnRationalNumber, ClnRationalNumber> asFraction(ClnRationalNumber const& number) {
447 return std::make_pair(carl::getNum(number), carl::getDenom(number));
448}
449
450template<>
451ClnRationalNumber sqrt(ClnRationalNumber const& number) {
452 return carl::sqrt(number);
453}
454
455template<>
456ClnRationalNumber abs(storm::ClnRationalNumber const& number) {
457 return carl::abs(number);
458}
459
460template<>
461ClnRationalNumber floor(storm::ClnRationalNumber const& number) {
462 return carl::floor(number);
463}
464
465template<>
466ClnRationalNumber ceil(storm::ClnRationalNumber const& number) {
467 return carl::ceil(number);
468}
469
470template<>
471ClnRationalNumber log(ClnRationalNumber const& number) {
472 return carl::log(number);
473}
474
475template<>
476ClnRationalNumber log10(ClnRationalNumber const& number) {
477 return carl::log10(number);
478}
479
480template<>
481ClnRationalNumber cos(ClnRationalNumber const& number) {
482 return carl::cos(number);
483}
484
485template<>
486ClnRationalNumber sin(ClnRationalNumber const& number) {
487 return carl::sin(number);
488}
489
490template<>
491typename NumberTraits<ClnRationalNumber>::IntegerType trunc(ClnRationalNumber const& number) {
492 return cln::truncate1(number);
493}
494
495template<>
496typename NumberTraits<ClnRationalNumber>::IntegerType mod(NumberTraits<ClnRationalNumber>::IntegerType const& first,
497 NumberTraits<ClnRationalNumber>::IntegerType const& second) {
498 return carl::mod(first, second);
499}
500
501template<>
502std::pair<typename NumberTraits<ClnRationalNumber>::IntegerType, typename NumberTraits<ClnRationalNumber>::IntegerType> divide(
503 typename NumberTraits<ClnRationalNumber>::IntegerType const& dividend, typename NumberTraits<ClnRationalNumber>::IntegerType const& divisor) {
504 std::pair<typename NumberTraits<ClnRationalNumber>::IntegerType, typename NumberTraits<ClnRationalNumber>::IntegerType> result;
505 carl::divide(dividend, divisor, result.first, result.second);
506 return result;
507}
508
509template<>
510typename NumberTraits<ClnRationalNumber>::IntegerType pow(typename NumberTraits<ClnRationalNumber>::IntegerType const& value, int_fast64_t exponent) {
511 STORM_LOG_THROW(exponent >= 0, storm::exceptions::InvalidArgumentException,
512 "Tried to compute the power 'x^y' as an integer, but the exponent 'y' is negative.");
513 return carl::pow(value, exponent);
514}
515
516template<>
517ClnRationalNumber pow(ClnRationalNumber const& value, int_fast64_t exponent) {
518 if (exponent >= 0) {
519 return carl::pow(value, exponent);
520 } else {
521 return storm::utility::one<ClnRationalNumber>() / carl::pow(value, -exponent);
522 }
523}
524
525template<>
526NumberTraits<ClnRationalNumber>::IntegerType numerator(ClnRationalNumber const& number) {
527 return carl::getNum(number);
528}
529
530template<>
531NumberTraits<ClnRationalNumber>::IntegerType denominator(ClnRationalNumber const& number) {
532 return carl::getDenom(number);
533}
534#endif
535
536#if defined(STORM_HAVE_CARL) && defined(STORM_HAVE_GMP)
537template<>
538storm::GmpRationalNumber infinity() {
539 // FIXME: this should be treated more properly.
540 return storm::GmpRationalNumber(100000000000);
541}
542
543template<>
544bool isOne(storm::GmpRationalNumber const& a) {
545 return carl::isOne(a);
546}
547
548template<>
549bool isZero(storm::GmpRationalNumber const& a) {
550 return carl::isZero(a);
551}
552
553template<>
554bool isInteger(storm::GmpRationalNumber const& number) {
555 return carl::isInteger(number);
556}
557
558template<>
559std::pair<storm::GmpRationalNumber, storm::GmpRationalNumber> minmax(std::vector<storm::GmpRationalNumber> const& values) {
560 assert(!values.empty());
561 storm::GmpRationalNumber min = values.front();
562 storm::GmpRationalNumber max = values.front();
563 for (auto const& vt : values) {
564 if (vt == storm::utility::infinity<storm::GmpRationalNumber>()) {
565 max = vt;
566 } else {
567 if (vt < min) {
568 min = vt;
569 }
570 if (vt > max) {
571 max = vt;
572 }
573 }
574 }
575 return std::make_pair(min, max);
576}
577
578template<>
579std::pair<storm::GmpRationalNumber, storm::GmpRationalNumber> minmax(std::map<uint64_t, storm::GmpRationalNumber> const& values) {
580 assert(!values.empty());
581 storm::GmpRationalNumber min = values.begin()->second;
582 storm::GmpRationalNumber max = values.begin()->second;
583 for (auto const& vt : values) {
584 if (vt.second == storm::utility::infinity<storm::GmpRationalNumber>()) {
585 max = vt.second;
586 } else {
587 if (vt.second < min) {
588 min = vt.second;
589 }
590 if (vt.second > max) {
591 max = vt.second;
592 }
593 }
594 }
595 return std::make_pair(min, max);
596}
597
598template<>
599uint_fast64_t convertNumber(GmpRationalNumber const& number) {
600 return carl::toInt<carl::uint>(number);
601}
602
603template<>
604int_fast64_t convertNumber(GmpRationalNumber const& number) {
605 return carl::toInt<carl::sint>(number);
606}
607
608template<>
609GmpRationalNumber convertNumber(double const& number) {
610 return carl::rationalize<GmpRationalNumber>(number);
611}
612
613template<>
614GmpRationalNumber convertNumber(int const& number) {
615 return carl::rationalize<GmpRationalNumber>(number);
616}
617
618template<>
619GmpRationalNumber convertNumber(uint_fast64_t const& number) {
620 STORM_LOG_ASSERT(static_cast<carl::uint>(number) == number, "Rationalizing failed, because the number is too large.");
621 return carl::rationalize<GmpRationalNumber>(static_cast<carl::uint>(number));
622}
623
624template<>
625GmpRationalNumber convertNumber(NumberTraits<GmpRationalNumber>::IntegerType const& number) {
626 return GmpRationalNumber(number);
627}
628
629template<>
630typename NumberTraits<GmpRationalNumber>::IntegerType convertNumber(uint_fast64_t const& number) {
631 STORM_LOG_ASSERT(static_cast<unsigned long int>(number) == number, "Conversion failed, because the number is too large.");
632 return NumberTraits<GmpRationalNumber>::IntegerType(static_cast<unsigned long int>(number));
633}
634
635template<>
636typename NumberTraits<GmpRationalNumber>::IntegerType convertNumber(double const& number) {
637 return NumberTraits<GmpRationalNumber>::IntegerType(number);
638}
639
640template<>
641GmpRationalNumber convertNumber(int_fast64_t const& number) {
642 STORM_LOG_ASSERT(static_cast<carl::sint>(number) == number, "Rationalizing failed, because the number is too large.");
643 return carl::rationalize<GmpRationalNumber>(static_cast<carl::sint>(number));
644}
645
646template<>
647double convertNumber(GmpRationalNumber const& number) {
648 return carl::toDouble(number);
649}
650
651template<>
652GmpRationalNumber convertNumber(std::string const& number) {
653 GmpRationalNumber result;
654 if (carl::try_parse<GmpRationalNumber>(number, result)) {
655 return result;
656 }
657 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Unable to parse '" << number << "' as a rational number.");
658}
659
660template<>
661std::pair<GmpRationalNumber, GmpRationalNumber> asFraction(GmpRationalNumber const& number) {
662 return std::make_pair(carl::getNum(number), carl::getDenom(number));
663}
664
665template<>
666GmpRationalNumber sqrt(GmpRationalNumber const& number) {
667 return carl::sqrt(number);
668}
669
670template<>
671GmpRationalNumber abs(storm::GmpRationalNumber const& number) {
672 return carl::abs(number);
673}
674
675template<>
676GmpRationalNumber floor(storm::GmpRationalNumber const& number) {
677 return carl::floor(number);
678}
679
680template<>
681GmpRationalNumber ceil(storm::GmpRationalNumber const& number) {
682 return carl::ceil(number);
683}
684
685template<>
686GmpRationalNumber log(GmpRationalNumber const& number) {
687 return carl::log(number);
688}
689
690template<>
691GmpRationalNumber log10(GmpRationalNumber const& number) {
692 STORM_LOG_WARN("Using log10 for GMP rational numbers is not exact, it converts to doubles internally! Avoid if possible.");
693 return carl::log10(number);
694}
695
696template<>
697GmpRationalNumber cos(GmpRationalNumber const& number) {
698 return carl::cos(number);
699}
700
701template<>
702GmpRationalNumber sin(GmpRationalNumber const& number) {
703 return carl::sin(number);
704}
705
706template<>
707typename NumberTraits<GmpRationalNumber>::IntegerType trunc(GmpRationalNumber const& number) {
708 return carl::getNum(number) / carl::getDenom(number);
709}
710
711template<>
712typename NumberTraits<GmpRationalNumber>::IntegerType mod(typename NumberTraits<GmpRationalNumber>::IntegerType const& first,
713 typename NumberTraits<GmpRationalNumber>::IntegerType const& second) {
714 return carl::mod(first, second);
715}
716
717template<>
718std::pair<typename NumberTraits<GmpRationalNumber>::IntegerType, typename NumberTraits<GmpRationalNumber>::IntegerType> divide(
719 typename NumberTraits<GmpRationalNumber>::IntegerType const& dividend, typename NumberTraits<GmpRationalNumber>::IntegerType const& divisor) {
720 std::pair<typename NumberTraits<GmpRationalNumber>::IntegerType, typename NumberTraits<GmpRationalNumber>::IntegerType> result;
721 carl::divide(dividend, divisor, result.first, result.second);
722 return result;
723}
724
725template<>
726typename NumberTraits<GmpRationalNumber>::IntegerType pow(typename NumberTraits<GmpRationalNumber>::IntegerType const& value, int_fast64_t exponent) {
727 STORM_LOG_THROW(exponent >= 0, storm::exceptions::InvalidArgumentException,
728 "Tried to compute the power 'x^y' as an integer, but the exponent 'y' is negative.");
729 return carl::pow(value, exponent);
730}
731
732template<>
733GmpRationalNumber pow(GmpRationalNumber const& value, int_fast64_t exponent) {
734 if (exponent >= 0) {
735 return carl::pow(value, exponent);
736 } else {
737 return storm::utility::one<GmpRationalNumber>() / carl::pow(value, -exponent);
738 }
739}
740
741template<>
742typename NumberTraits<GmpRationalNumber>::IntegerType numerator(GmpRationalNumber const& number) {
743 return carl::getNum(number);
744}
745
746template<>
747typename NumberTraits<GmpRationalNumber>::IntegerType denominator(GmpRationalNumber const& number) {
748 return carl::getDenom(number);
749}
750#endif
751
752#if defined(STORM_HAVE_CARL) && defined(STORM_HAVE_GMP) && defined(STORM_HAVE_CLN)
753template<>
754storm::GmpRationalNumber convertNumber(storm::ClnRationalNumber const& number) {
755 return carl::parse<storm::GmpRationalNumber>(to_string(number));
756}
757
758template<>
759storm::ClnRationalNumber convertNumber(storm::GmpRationalNumber const& number) {
760 return carl::parse<storm::ClnRationalNumber>(to_string(number));
761}
762#endif
763
764template<>
766 // FIXME: this should be treated more properly.
767 return storm::RationalFunction(convertNumber<RationalFunctionCoefficient>(100000000000));
768}
769
770template<>
772 return a.isOne();
773}
774
775template<>
776bool isOne(storm::Polynomial const& a) {
777 return a.isOne();
778}
779
780template<>
782 return a.isZero();
783}
784
785template<>
786bool isZero(storm::Polynomial const& a) {
787 return a.isZero();
788}
789
790template<>
792 return a.isConstant();
793}
794
795template<>
797 return a.isConstant();
798}
799
800template<>
801bool isApproxEqual(storm::RationalFunction const& a, storm::RationalFunction const& b, storm::RationalFunction const& precision, bool relative) {
802 STORM_LOG_ASSERT(isZero(precision), "Approx equal on rational functions is only defined for precision zero");
803 return a == b;
804}
805
806template<>
808 return a.isPointInterval();
809}
810
811template<>
813 // FIXME: this should be treated more properly.
814 return a == infinity<storm::RationalFunction>();
815}
816
817template<>
819 return storm::utility::isConstant(func) && storm::utility::isOne(func.denominator());
820}
821
822template<>
823RationalFunction convertNumber(double const& number) {
824 return RationalFunction(carl::rationalize<RationalFunctionCoefficient>(number));
825}
826
827template<>
828RationalFunction convertNumber(int_fast64_t const& number) {
829 STORM_LOG_ASSERT(static_cast<carl::sint>(number) == number, "Rationalizing failed, because the number is too large.");
830 return RationalFunction(carl::rationalize<RationalFunctionCoefficient>(static_cast<carl::sint>(number)));
831}
832
833#if defined(STORM_HAVE_CLN)
834template<>
835RationalFunction convertNumber(ClnRationalNumber const& number) {
836 return RationalFunction(convertNumber<storm::RationalFunctionCoefficient>(number));
837}
838
839template<>
840ClnRationalNumber convertNumber(RationalFunction const& number) {
841 storm::RationalFunctionCoefficient tmp = number.nominatorAsNumber() / number.denominatorAsNumber();
842 return convertNumber<ClnRationalNumber>(tmp);
843}
844#endif
845
846#if defined(STORM_HAVE_GMP)
847template<>
848RationalFunction convertNumber(GmpRationalNumber const& number) {
849 return RationalFunction(convertNumber<storm::RationalFunctionCoefficient>(number));
850}
851
852template<>
853GmpRationalNumber convertNumber(RationalFunction const& number) {
854 return convertNumber<GmpRationalNumber>(number.nominatorAsNumber() / number.denominatorAsNumber());
855}
856#endif
857
858template<>
859carl::uint convertNumber(RationalFunction const& func) {
860 return carl::toInt<carl::uint>(convertNumber<RationalFunctionCoefficient>(func));
861}
862
863template<>
864carl::sint convertNumber(RationalFunction const& func) {
865 return carl::toInt<carl::sint>(convertNumber<RationalFunctionCoefficient>(func));
866}
867
868template<>
869double convertNumber(RationalFunction const& func) {
870 return carl::toDouble(convertNumber<RationalFunctionCoefficient>(func));
871}
872
873template<>
875 return number;
876}
877
878template<>
879RationalFunction convertNumber(std::string const& number) {
880 return RationalFunction(convertNumber<RationalFunctionCoefficient>(number));
881}
882
883template<>
885 return RationalFunction(convertNumber<RationalFunctionCoefficient>(number));
886}
887
888template<>
890
891template<>
893
894template<>
896 value.simplify();
897 return value;
898}
899
900template<>
902 value.simplify();
903 return value;
904}
905
906template<>
908 value.simplify();
909 return std::move(value);
910}
911
912template<>
914 return a.isConstant() && isAlmostZero(convertNumber<RationalFunctionCoefficient>(a));
915}
916
917template<>
919 return a.isConstant() && isAlmostOne(convertNumber<RationalFunctionCoefficient>(a));
920}
921
922template<>
924 return a.isConstant() && isNonNegative(convertNumber<RationalFunctionCoefficient>(a));
925}
926
927template<>
929 return a.isConstant() && isPositive(convertNumber<RationalFunctionCoefficient>(a));
930}
931
932template<>
934 STORM_LOG_ASSERT(a.isConstant(), "lower bound must be a constant");
935 STORM_LOG_ASSERT(c.isConstant(), "upper bound must be a constant");
936 return b.isConstant() && isBetween(convertNumber<RationalFunctionCoefficient>(a), convertNumber<RationalFunctionCoefficient>(b),
937 convertNumber<RationalFunctionCoefficient>(c), strict);
938}
939
940template<>
941std::pair<storm::RationalFunction, storm::RationalFunction> minmax(std::vector<storm::RationalFunction> const&) {
942 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Minimum/maximum for rational functions is not defined.");
943}
944
945template<>
946storm::RationalFunction minimum(std::vector<storm::RationalFunction> const&) {
947 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Minimum for rational functions is not defined.");
948}
949
950template<>
951storm::RationalFunction maximum(std::vector<storm::RationalFunction> const&) {
952 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Maximum for rational functions is not defined.");
953}
954
955template<>
956std::pair<storm::RationalFunction, storm::RationalFunction> minmax(std::map<uint64_t, storm::RationalFunction> const&) {
957 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Maximum/maximum for rational functions is not defined.");
958}
959
960template<>
961storm::RationalFunction minimum(std::map<uint64_t, storm::RationalFunction> const&) {
962 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Minimum for rational functions is not defined.");
963}
964
965template<>
966storm::RationalFunction maximum(std::map<uint64_t, storm::RationalFunction> const&) {
967 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Maximum for rational functions is not defined");
968}
969
970template<>
971RationalFunction pow(RationalFunction const& value, int_fast64_t exponent) {
972 if (exponent >= 0) {
973 return carl::pow(value, exponent);
974 } else {
975 return storm::utility::one<RationalFunction>() / carl::pow(value, -exponent);
976 }
977}
978
979template<>
980std::string to_string(RationalFunction const& f) {
981 std::stringstream ss;
982 if (f.isConstant()) {
983 if (f.denominator().isOne()) {
984 ss << f.nominatorAsNumber();
985 } else {
986 ss << f.nominatorAsNumber() << "/" << f.denominatorAsNumber();
987 }
988 } else if (f.denominator().isOne()) {
989 ss << f.nominatorAsPolynomial().coefficient() * f.nominatorAsPolynomial().polynomial();
990 } else {
991 ss << "(" << f.nominatorAsPolynomial() << ")/(" << f.denominatorAsPolynomial() << ")";
992 }
993 return ss.str();
994}
995
996template<>
997double convertNumber(std::string const& value) {
998 return convertNumber<double>(convertNumber<storm::RationalNumber>(value));
999}
1000
1001template<>
1002storm::Interval convertNumber(double const& number) {
1003 return storm::Interval(number);
1004}
1005
1006template<>
1007storm::Interval convertNumber(uint64_t const& number) {
1008 return storm::Interval(convertNumber<double>(number));
1009}
1010
1011#if defined(STORM_HAVE_GMP)
1012template<>
1013storm::Interval convertNumber(storm::GmpRationalNumber const& n) {
1014 return storm::Interval(convertNumber<double>(n));
1015}
1016
1017template<>
1018storm::GmpRationalNumber convertNumber(storm::Interval const& number) {
1019 STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert");
1020 return convertNumber<storm::GmpRationalNumber>(number.lower());
1021}
1022#endif
1023
1024#if defined(STORM_HAVE_CLN)
1025template<>
1026storm::Interval convertNumber(storm::ClnRationalNumber const& n) {
1027 return storm::Interval(convertNumber<double>(n));
1028}
1029
1030template<>
1031storm::ClnRationalNumber convertNumber(storm::Interval const& number) {
1032 STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert");
1033 return convertNumber<storm::ClnRationalNumber>(number.lower());
1034}
1035#endif
1036
1037template<>
1038double convertNumber(storm::Interval const& number) {
1039 STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert");
1040 return number.lower();
1041}
1042
1043template<>
1045 return interval.abs();
1046}
1047
1048template<>
1049bool isApproxEqual(storm::Interval const& a, storm::Interval const& b, storm::Interval const& precision, bool relative) {
1050 STORM_LOG_ASSERT(precision.isPointInterval(), "Precision must be a point interval");
1051 return isApproxEqual<double>(a.lower(), b.lower(), precision.center(), relative) &&
1052 isApproxEqual<double>(a.upper(), b.upper(), precision.center(), relative);
1053}
1054
1055// Explicit instantiations.
1056
1057// double
1058template double one();
1059template double zero();
1060template double infinity();
1061template bool isOne(double const& value);
1062template bool isZero(double const& value);
1063template bool isNonNegative(double const& value);
1064template bool isPositive(double const& value);
1065template bool isAlmostZero(double const& value);
1066template bool isAlmostOne(double const& value);
1067template bool isConstant(double const& value);
1068template bool isInfinity(double const& value);
1069template bool isInteger(double const& number);
1070template bool isBetween(double const& a, double const& b, double const& c, bool strict);
1071template bool isApproxEqual(double const& a, double const& b, double const& precision, bool relative);
1072template double simplify(double value);
1073template std::pair<double, double> minmax(std::vector<double> const&);
1074template double minimum(std::vector<double> const&);
1075template double maximum(std::vector<double> const&);
1076template std::pair<double, double> minmax(std::map<uint64_t, double> const&);
1077template double minimum(std::map<uint64_t, double> const&);
1078template double maximum(std::map<uint64_t, double> const&);
1079template double pow(double const& value, int_fast64_t exponent);
1080template double max(double const& first, double const& second);
1081template double min(double const& first, double const& second);
1082template double sqrt(double const& number);
1083template double abs(double const& number);
1084template double floor(double const& number);
1085template double ceil(double const& number);
1086template double round(double const& number);
1087template double log(double const& number);
1088template double log10(double const& number);
1089template double cos(double const& number);
1090template double sin(double const& number);
1091template typename NumberTraits<double>::IntegerType trunc(double const& number);
1092template double mod(double const& first, double const& second);
1093template std::string to_string(double const& value);
1094
1095// int
1096template int one();
1097template int zero();
1098template int infinity();
1099template bool isOne(int const& value);
1100template bool isZero(int const& value);
1101template bool isConstant(int const& value);
1102template bool isInfinity(int const& value);
1103template bool isNonNegative(int const& value);
1104template bool isPositive(int const& value);
1105template bool isApproxEqual(int const& a, int const& b, int const& precision, bool relative);
1106template bool isBetween(int const& a, int const& b, int const& c, bool strict);
1107
1108// uint32_t
1109template uint32_t one();
1110template uint32_t zero();
1111template uint32_t infinity();
1112template bool isOne(uint32_t const& value);
1113template bool isZero(uint32_t const& value);
1114template bool isConstant(uint32_t const& value);
1115template bool isNonNegative(uint32_t const& value);
1116template bool isPositive(uint32_t const& value);
1117template bool isInfinity(uint32_t const& value);
1118template bool isBetween(uint32_t const& a, uint32_t const& b, uint32_t const& c, bool strict);
1119
1120// storm::storage::sparse::state_type
1125 storm::storage::sparse::state_type const& precision, bool relative);
1126template bool isOne(storm::storage::sparse::state_type const& value);
1127template bool isZero(storm::storage::sparse::state_type const& value);
1133 bool strict);
1134
1135// other instantiations
1136template unsigned long convertNumber(long const&);
1137template double convertNumber(long const&);
1138
1139#if defined(STORM_HAVE_CLN)
1140// Instantiations for (CLN) rational number.
1141template storm::ClnRationalNumber one();
1143template storm::ClnRationalNumber zero();
1145template bool isConstant(storm::ClnRationalNumber const& value);
1146template bool isPositive(storm::ClnRationalNumber const& value);
1147template bool isNonNegative(storm::ClnRationalNumber const& value);
1148template bool isInfinity(storm::ClnRationalNumber const& value);
1149template bool isNan(storm::ClnRationalNumber const& value);
1150template bool isAlmostZero(storm::ClnRationalNumber const& value);
1151template bool isAlmostOne(storm::ClnRationalNumber const& value);
1152template bool isApproxEqual(storm::ClnRationalNumber const& a, storm::ClnRationalNumber const& b, storm::ClnRationalNumber const& precision, bool relative);
1153template bool isBetween(storm::ClnRationalNumber const& a, storm::ClnRationalNumber const& b, storm::ClnRationalNumber const& c, bool strict);
1155template storm::ClnRationalNumber convertNumber(storm::ClnRationalNumber const& number);
1156template storm::ClnRationalNumber simplify(storm::ClnRationalNumber value);
1157template std::pair<storm::ClnRationalNumber, storm::ClnRationalNumber> minmax(std::map<uint64_t, storm::ClnRationalNumber> const&);
1158template storm::ClnRationalNumber minimum(std::map<uint64_t, storm::ClnRationalNumber> const&);
1159template storm::ClnRationalNumber maximum(std::map<uint64_t, storm::ClnRationalNumber> const&);
1160template storm::ClnRationalNumber minimum(std::vector<storm::ClnRationalNumber> const&);
1161template storm::ClnRationalNumber maximum(std::vector<storm::ClnRationalNumber> const&);
1162template storm::ClnRationalNumber max(storm::ClnRationalNumber const& first, storm::ClnRationalNumber const& second);
1163template storm::ClnRationalNumber min(storm::ClnRationalNumber const& first, storm::ClnRationalNumber const& second);
1164template storm::ClnRationalNumber round(storm::ClnRationalNumber const& number);
1165template std::string to_string(storm::ClnRationalNumber const& value);
1166template uint64_t numDigits(const storm::ClnRationalNumber& number);
1167#endif
1168
1169#if defined(STORM_HAVE_GMP)
1170// Instantiations for (GMP) rational number.
1171template storm::GmpRationalNumber one();
1173template storm::GmpRationalNumber zero();
1175template bool isConstant(storm::GmpRationalNumber const& value);
1176template bool isPositive(storm::GmpRationalNumber const& value);
1177template bool isNonNegative(storm::GmpRationalNumber const& value);
1178template bool isInfinity(storm::GmpRationalNumber const& value);
1179template bool isNan(storm::GmpRationalNumber const& value);
1180template bool isAlmostZero(storm::GmpRationalNumber const& value);
1181template bool isAlmostOne(storm::GmpRationalNumber const& value);
1182template bool isBetween(storm::GmpRationalNumber const&, storm::GmpRationalNumber const&, storm::GmpRationalNumber const&, bool);
1183template bool isApproxEqual(storm::GmpRationalNumber const& a, storm::GmpRationalNumber const& b, storm::GmpRationalNumber const& precision, bool relative);
1185template storm::GmpRationalNumber convertNumber(storm::GmpRationalNumber const& number);
1186template storm::GmpRationalNumber simplify(storm::GmpRationalNumber value);
1187template storm::GmpRationalNumber minimum(std::map<uint64_t, storm::GmpRationalNumber> const&);
1188template storm::GmpRationalNumber maximum(std::map<uint64_t, storm::GmpRationalNumber> const&);
1189template storm::GmpRationalNumber minimum(std::vector<storm::GmpRationalNumber> const&);
1190template storm::GmpRationalNumber maximum(std::vector<storm::GmpRationalNumber> const&);
1191template storm::GmpRationalNumber max(storm::GmpRationalNumber const& first, storm::GmpRationalNumber const& second);
1192template storm::GmpRationalNumber min(storm::GmpRationalNumber const& first, storm::GmpRationalNumber const& second);
1193template storm::GmpRationalNumber round(storm::GmpRationalNumber const& number);
1194template std::string to_string(storm::GmpRationalNumber const& value);
1195template uint64_t numDigits(const storm::GmpRationalNumber& number);
1196#endif
1197
1198// Instantiations for rational function.
1199template RationalFunction one();
1200template RationalFunction zero();
1201
1202template bool isNan(RationalFunction const&);
1203
1204// Instantiations for polynomials.
1205template Polynomial one();
1206template Polynomial zero();
1207
1208// Instantiations for intervals.
1209template Interval one();
1210template Interval zero();
1211template bool isOne(Interval const& value);
1212template bool isZero(Interval const& value);
1213template bool isInfinity(Interval const& value);
1214template bool isAlmostZero(Interval const& value);
1215template bool isNonNegative(Interval const& value);
1216template bool isPositive(Interval const& value);
1217template bool isBetween(Interval const&, Interval const&, Interval const& value, bool);
1218
1219template std::string to_string(storm::Interval const& value);
1220
1221} // namespace utility
1222} // namespace storm
#define STORM_LOG_WARN(message)
Definition logging.h:25
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
ValueType max(ValueType const &first, ValueType const &second)
bool isPositive(ValueType const &a)
Definition constants.cpp:63
bool isOne(ValueType const &a)
Definition constants.cpp:33
NumberTraits< RationalType >::IntegerType denominator(RationalType const &number)
NumberTraits< RationalType >::IntegerType numerator(RationalType const &number)
bool isConstant(ValueType const &)
ValueType simplify(ValueType value)
bool isBetween(ValueType const &a, ValueType const &b, ValueType const &c, bool strict)
Compare whether a <= b <= c or a < b < c, based on the strictness parameter.
Definition constants.cpp:81
ValueType min(ValueType const &first, ValueType const &second)
ValueType sin(ValueType const &number)
bool isApproxEqual(ValueType const &a, ValueType const &b, ValueType const &precision, bool relative)
Definition constants.cpp:53
bool isAlmostZero(ValueType const &a)
Definition constants.cpp:92
bool isAlmostOne(ValueType const &a)
Definition constants.cpp:97
ValueType floor(ValueType const &number)
std::pair< ValueType, ValueType > asFraction(ValueType const &number)
bool isZero(ValueType const &a)
Definition constants.cpp:38
ValueType minimum(std::vector< ValueType > const &values)
ValueType ceil(ValueType const &number)
bool isInteger(ValueType const &number)
ValueType abs(ValueType const &number)
ValueType zero()
Definition constants.cpp:23
ValueType infinity()
Definition constants.cpp:28
bool isNan(ValueType const &)
Definition constants.cpp:43
std::string to_string(ValueType const &value)
std::pair< ValueType, ValueType > minmax(std::vector< ValueType > const &values)
bool isNonNegative(ValueType const &a)
Definition constants.cpp:68
NumberTraits< ValueType >::IntegerType trunc(ValueType const &number)
std::pair< IntegerType, IntegerType > divide(IntegerType const &dividend, IntegerType const &divisor)
(Integer-)Divides the dividend by the divisor and returns the result plus the remainder.
IntegerType mod(IntegerType const &first, IntegerType const &second)
ValueType pow(ValueType const &value, int_fast64_t exponent)
ValueType one()
Definition constants.cpp:18
ValueType log(ValueType const &number)
ValueType maximum(std::vector< ValueType > const &values)
ValueType cos(ValueType const &number)
ValueType sqrt(ValueType const &number)
uint64_t numDigits(ValueType const &number)
bool isInfinity(ValueType const &a)
ValueType log10(ValueType const &number)
ValueType round(ValueType const &number)
TargetType convertNumber(SourceType const &number)
carl::Interval< double > Interval
Interval type.
carl::RationalFunction< Polynomial, true > RationalFunction