Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
ValuationsStorage.h
Go to the documentation of this file.
1#pragma once
2
3#include <bit>
4#include <concepts>
5#include <cstdint>
6#include <memory>
7#include <optional>
8#include <set>
9#include <span>
10#include <sstream>
11#include <typeinfo>
12
19
23
24namespace storm::expressions {
25template<typename T>
27}
28
29namespace storm::storage::sparse {
30
37template<typename F>
39 std::invocable<F, uint64_t, storm::expressions::Variable const&, bool> || std::invocable<F, uint64_t, storm::expressions::Variable const&, int64_t> ||
40 std::invocable<F, uint64_t, storm::expressions::Variable const&, uint64_t> || std::invocable<F, uint64_t, storm::expressions::Variable const&, double> ||
41 std::invocable<F, uint64_t, storm::expressions::Variable const&, storm::RationalNumber> ||
42 std::invocable<F, uint64_t, storm::expressions::Variable const&, storm::NumberTraits<storm::RationalNumber>::IntegerType> ||
43 std::invocable<F, uint64_t, storm::expressions::Variable const&, std::string_view> ||
44 std::invocable<F, uint64_t, storm::expressions::Variable const&, std::string> ||
45 std::invocable<F, uint64_t, storm::expressions::Variable const&, std::nullopt_t>;
46
53template<typename F>
55 std::invocable<F, uint64_t, storm::expressions::Variable const&, bool&> || std::invocable<F, uint64_t, storm::expressions::Variable const&, int64_t&> ||
56 std::invocable<F, uint64_t, storm::expressions::Variable const&, uint64_t&> || std::invocable<F, uint64_t, storm::expressions::Variable const&, double&> ||
57 std::invocable<F, uint64_t, storm::expressions::Variable const&, storm::RationalNumber&> ||
58 std::invocable<F, uint64_t, storm::expressions::Variable const&, storm::NumberTraits<storm::RationalNumber>::IntegerType&> ||
59 std::invocable<F, uint64_t, storm::expressions::Variable const&, std::string&>;
60
70 public:
72
81 uint64_t const bitOffset; // The first bit holding the variable's data within the valuation.
82 // If the variable is optional, the optional bit is located at bitOffset - 1
83 bool const fits64Bit;
84 };
85
92 std::vector<VariableInformation> const variables;
93 std::shared_ptr<storm::expressions::ExpressionManager const> const expressionManager;
94 uint64_t const sizeInBytes;
95 };
96
101
118 ValuationsStorage(uint64_t numEntities, std::vector<ValuationClassDescription> const& descriptions, std::vector<char> valuations,
119 std::vector<uint64_t> stringMapping, std::vector<char> strings, std::optional<std::vector<uint32_t>> classes = {},
120 std::vector<std::shared_ptr<storm::expressions::ExpressionManager const>> expressionManagers = {});
121
131 ValuationsStorage(uint64_t numEntities, ValuationClassDescription const& description, std::vector<char> valuations,
132 std::shared_ptr<storm::expressions::ExpressionManager const> expressionManager = {});
133
140 ValuationsStorage(std::vector<ValuationClassDescription> const& descriptions,
141 std::vector<std::shared_ptr<storm::expressions::ExpressionManager const>> expressionManagers = {});
142
149 ValuationsStorage(ValuationClassDescription const& description, std::shared_ptr<storm::expressions::ExpressionManager const> expressionManager = {});
150
154 uint64_t size() const;
155
160 uint64_t numClasses() const;
161
165 uint64_t numStrings() const;
166
171 bool hasStrings() const;
172
178 uint64_t getClassOfEntity(uint64_t entity) const;
179
185 ValuationClassDescription getClassDescription(uint64_t classIndex = 0) const;
186
191 storm::expressions::ExpressionManager const& getManager() const;
192
197 storm::expressions::ExpressionManager const& getManager(uint64_t classIndex) const;
198
202 std::set<storm::expressions::Variable> getAllVariables() const;
203
207 bool entityHasVariable(uint64_t entity, storm::expressions::Variable const& variable) const;
208
215 VariableInformation const& getVariableInformation(uint64_t entity, storm::expressions::Variable const& variable) const;
216
222 VariableInformation const& getVariableInformation(storm::expressions::Variable const& variable) const;
223
228 typename storm::umb::UmbModel::Valuation getRawUmbData() const;
229
238 void resize(uint64_t newEntityCount, uint64_t classIndex = 0);
239
252 template<bool AllowOptional = false, typename... AllowedTypes, ValuationWriteCallback Callback>
253 void emplaceBack(uint64_t classIndex, Callback const& callback) {
254 STORM_LOG_ASSERT(classIndex < variableClasses.size(),
255 "Class index " << classIndex << " out of bounds. Only " << variableClasses.size() << "classes known.");
256 valuations.resize(valuations.size() + variableClasses[classIndex].sizeInBytes, 0);
257 if (entityClassMappings) {
258 entityClassMappings->toClassMapping.push_back(classIndex);
259 entityClassMappings->toValuationsMapping.push_back(valuations.size());
260 }
261 ++numEntities;
262 writeCallback<false, AllowOptional, AllowedTypes...>(size() - 1, callback);
263 }
264
272 template<bool AllowOptional = false, typename... AllowedTypes, ValuationWriteCallback Callback>
273 void emplaceBack(Callback const& callback) {
274 STORM_LOG_ASSERT(variableClasses.size() == 1, "Trying to add a valuation but the class is not unique.");
275 emplaceBack<AllowOptional, AllowedTypes...>(0, callback);
276 }
277
285 template<typename T>
286 ValuationsStorage selectEntities(T const& selectedEntities) const;
287
296 template<typename... AllowedTypes, ValuationReadCallback Callback>
297 void readCallback(uint64_t entity, Callback const& callback) const {
298 for (auto const& varInfo : info(entity).variables) {
299 read<AllowedTypes...>(entity, varInfo, callback);
300 }
301 }
302
311 template<typename... AllowedTypes, ValuationReadCallback Callback>
312 void readCallback(uint64_t entity, storm::expressions::Variable const& variable, Callback const& callback) const {
313 read<AllowedTypes...>(entity, getVariableInformation(entity, variable), callback);
314 }
315
324 template<typename... AllowedTypes, ValuationReadCallback Callback>
325 void readCallback(storm::expressions::Variable const& variable, Callback const& callback) const {
326 if (numClasses() == 1) {
327 // We have only one class, so we can look up the variable info once and use it for all entities
328 auto const& varInfo = getVariableInformation(variable);
329 for (uint64_t entity = 0; entity < size(); ++entity) {
330 read<AllowedTypes...>(entity, varInfo, callback);
331 }
332 } else {
333 for (uint64_t entity = 0; entity < size(); ++entity) {
334 readCallback<AllowedTypes...>(entity, variable, callback);
335 }
336 }
337 }
338
346 template<typename... AllowedTypes, ValuationReadCallback Callback>
347 void readCallback(Callback const& callback) const {
348 for (uint64_t entity = 0; entity < size(); ++entity) {
349 readCallback<AllowedTypes...>(entity, callback);
350 }
351 }
352
362 template<typename ValueType>
363 ValueType readValue(uint64_t entity, storm::expressions::Variable const& variable) const {
364 ValueType result;
365 readCallback<ValueType>(entity, variable, [&](auto, auto, ValueType value) { result = std::move(value); });
366 return result;
367 }
368
375 template<typename RationalValueType>
377
393 template<bool InitializeWithCurrent = false, bool AllowOptional = false, typename... AllowedTypes, ValuationWriteCallback Callback>
394 void writeCallback(uint64_t entity, Callback const& callback) {
395 for (auto const& varInfo : info(entity).variables) {
396 write<InitializeWithCurrent, AllowOptional, AllowedTypes...>(entity, varInfo, callback);
397 }
398 }
399
410 template<bool InitializeWithCurrent = false, bool AllowOptional = false, typename... AllowedTypes, ValuationWriteCallback Callback>
411 void writeCallback(uint64_t entity, storm::expressions::Variable const& variable, Callback const& callback) {
412 write<InitializeWithCurrent, AllowOptional, AllowedTypes...>(entity, getVariableInformation(entity, variable), callback);
413 }
414
424 template<bool InitializeWithCurrent = false, bool AllowOptional = false, typename... AllowedTypes, ValuationWriteCallback Callback>
425 void writeCallback(Callback const& callback) {
426 for (uint64_t entity = 0; entity < size(); ++entity) {
427 writeCallback<InitializeWithCurrent, AllowOptional, AllowedTypes...>(entity, callback);
428 }
429 }
430
440 template<typename ValueType>
441 void writeValue(uint64_t entity, storm::expressions::Variable const& variable, ValueType const& value) {
442 if constexpr (std::is_same_v<ValueType, std::nullopt_t>) {
443 writeCallback<false, true>(entity, variable, [](auto, auto, auto&) { /* intentionally empty */ });
444 } else if constexpr (std::is_same_v<ValueType, std::string_view>) {
445 writeCallback<false, false, std::string>(entity, variable, [&value](auto, auto, std::string& val) { val = value; });
446 } else {
447 writeCallback<false, false, ValueType>(entity, variable, [&value](auto, auto, ValueType& val) { val = value; });
448 }
449 }
450
456 std::size_t hash() const;
457
458 private:
463 template<typename T>
464 static std::string typeName() {
465 if constexpr (std::is_same_v<T, bool>) {
466 return "bool";
467 } else if constexpr (std::is_same_v<T, int64_t>) {
468 return "int64_t";
469 } else if constexpr (std::is_same_v<T, uint64_t>) {
470 return "uint64_t";
471 } else if constexpr (std::is_same_v<T, double>) {
472 return "double";
473 } else if constexpr (std::is_same_v<T, storm::RationalNumber>) {
474 return "storm::RationalNumber";
475 } else if constexpr (std::is_same_v<T, Integer>) {
476 return "Integer (arbitrary-precision)";
477 } else if constexpr (std::is_same_v<T, std::string>) {
478 return "std::string";
479 } else if constexpr (std::is_same_v<T, std::string_view>) {
480 return "std::string_view";
481 } else if constexpr (std::is_same_v<T, std::nullopt_t>) {
482 return "std::nullopt_t";
483 } else {
484 return typeid(T).name();
485 }
486 }
487
492 template<typename... Types>
493 static std::string typeNames() {
494 std::ostringstream oss;
495 [[maybe_unused]] bool first = true;
496 ((oss << (first ? "" : ", ") << typeName<Types>(), first = false), ...);
497 return oss.str();
498 }
499
500 uint64_t numEntities;
501 std::vector<VariablesInformation> variableClasses;
502
503 struct ClassData {
504 std::vector<uint32_t> toClassMapping; // mapping from entity index to class index (size equals number of entities)
505 std::vector<uint64_t> toValuationsMapping; // CSR mapping from entity index to valuations
506 };
507 std::optional<ClassData> entityClassMappings; // present iff there are multiple classes
508
509 std::vector<char> valuations;
510 std::vector<uint64_t> stringMapping;
511 std::vector<char> strings;
512
513 explicit ValuationsStorage(std::vector<VariablesInformation> const& variableClasses);
514
515 VariablesInformation const& info(uint64_t entity) const;
516
523 template<typename ValueType>
524 requires(std::is_same_v<ValueType, int64_t> || std::is_same_v<ValueType, uint64_t> || std::is_same_v<ValueType, Integer>)
525 bool fitsIntoStoredType(ValueType const& value, VariableInformation const& varInfo) const;
526
527 std::span<char const> getRawBytes(uint64_t entity) const;
528 std::span<char> getRawBytes(uint64_t entity);
529
530 bool readBit(std::span<char const> bytes, uint64_t position) const;
531 void writeBit(std::span<char> bytes, uint64_t position, bool value) const;
532 uint64_t readUint64(std::span<char const> bytes, uint64_t bitOffset, uint64_t bitSize) const;
533 void writeUint64(std::span<char> bytes, uint64_t bitOffset, uint64_t bitSize, uint64_t value) const;
534
535 template<bool Signed>
536 Integer readInteger(std::span<char const> bytes, uint64_t bitOffset, uint64_t bitSize) const;
537
538 template<bool Signed>
539 void writeInteger(std::span<char> bytes, uint64_t bitOffset, uint64_t bitSize, Integer const& value) const;
540
541 template<typename ValueType>
542 void writeValue(std::span<char> bytes, uint64_t bitOffset, uint64_t bitSize, ValueType const& value);
543
551 template<typename... AllowedTypes, ValuationReadCallback Callback>
552 void read(uint64_t entity, VariableInformation const& varInfo, Callback const& callback) const {
553 auto invokeCallback = [&entity, &varInfo, &callback](auto&& value) -> bool {
554 using ValueType = std::remove_cvref_t<decltype(value)>;
555 bool constexpr IsAllowed = (sizeof...(AllowedTypes) == 0) || std::disjunction_v<std::is_same<ValueType, AllowedTypes>...>;
556 if constexpr (IsAllowed) {
557 callback(entity, varInfo.expressionVariable, std::forward<decltype(value)>(value));
558 }
559 return IsAllowed;
560 };
561
562 if (varInfo.description.isOptional.value_or(false)) {
563 STORM_LOG_ASSERT(varInfo.bitOffset > 0, "Invalid variable information: optional variable must have a preceding presence bit.");
564 if (bool const hasValue = readBit(getRawBytes(entity), varInfo.bitOffset - 1); !hasValue) {
565 if (invokeCallback(std::nullopt)) {
566 return;
567 }
568 }
569 }
570 auto const bitSize = varInfo.description.type.bitSize();
571 using enum storm::umb::Type;
572 if (varInfo.fits64Bit) {
573 STORM_LOG_ASSERT(bitSize <= 64, "Invalid bit size for 64 bit fast path.");
574 uint64_t const rawContent = readUint64(getRawBytes(entity), varInfo.bitOffset, bitSize);
575 switch (varInfo.description.type.type) {
576 case Bool:
577 if (invokeCallback(rawContent != 0)) {
578 return;
579 }
580 break;
581 case Uint:
582 if (int64_t offset = varInfo.description.offset.value_or(0); offset < 0) {
583 // negative offset, output type is int64_t
584 if (invokeCallback(static_cast<int64_t>(rawContent) + offset)) {
585 return;
586 }
587 } else {
588 // non-negative offset, output type is uint64_t but we also try int64_t if uint64_t is not allowed
589 uint64_t const value = rawContent + offset;
590 uint64_t constexpr maxInt64 = std::numeric_limits<int64_t>::max();
591 if (invokeCallback(value) || (value <= maxInt64 && invokeCallback(static_cast<int64_t>(value)))) {
592 return;
593 }
594 }
595 break;
596 case Int: {
597 uint64_t const mostSignificantBitMask = 1ull << (bitSize - 1);
598 bool const isNegative = rawContent & mostSignificantBitMask;
599 // For negative value, take the two's complement (e.g. 1111...1101 is -3)
600 int64_t const value =
601 isNegative ? (-static_cast<int64_t>(~rawContent & (mostSignificantBitMask - 1)) - 1) : static_cast<int64_t>(rawContent);
602 if (invokeCallback(value)) {
603 return;
604 }
605 break;
606 }
607 case Double:
608 if (invokeCallback(std::bit_cast<double>(rawContent))) {
609 return;
610 }
611 break;
612 case Rational:
613 // Reaching this part should not be possible as varInfo.fits64Bit would be false
614 STORM_LOG_ASSERT(false, "Handling of rational values in 64 bit fast path is not implemented.");
615 break;
616 case String:
617 STORM_LOG_ASSERT(rawContent < numStrings(), "String index " << rawContent << " out of bounds (> " << numStrings() << ").");
618 // Prefer the string_view callback
619 if (std::string_view const sv = storm::umb::stringVectorView(strings, stringMapping)[rawContent];
620 invokeCallback(sv) || invokeCallback(std::string(sv))) {
621 return;
622 }
623 break;
624 default:
625 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException,
626 "ValuationsStorage for variable type '" << varInfo.description.type.toString() << "' are not supported.");
627 }
628 }
629 // reaching this point means that we could not handle the value in the fast path
630 switch (varInfo.description.type.type) {
631 case Bool:
632 // Bools could be encoded with more than 64 bits (which is not reasonable, but possible..)
633 if (invokeCallback(readInteger<false>(getRawBytes(entity), varInfo.bitOffset, bitSize) != Integer(0))) {
634 return;
635 }
636 break;
637 case Uint:
638 case Int: {
639 Integer value = varInfo.description.type.type == Int ? readInteger<true>(getRawBytes(entity), varInfo.bitOffset, bitSize)
640 : readInteger<false>(getRawBytes(entity), varInfo.bitOffset, bitSize);
641 value += storm::utility::convertNumber<Integer>(varInfo.description.offset.value_or(0));
642 if (invokeCallback(value)) {
643 return;
644 }
645 break;
646 }
647 case Double:
648 // Reaching this line happens for two different reasons that are otherwise indistinguishable
649 // here: (a) the field is a compliant 64-bit double but the caller's AllowedTypes didn't
650 // include double (a type mismatch, e.g. reading a double-encoded variable via
651 // getRationalValue/getInt64Value/...) -- fits64Bit is true in this case, and we fall through
652 // to the "not handled" throw below, matching how a mismatched read of any other type is
653 // handled; or (b) the field's declared bit size exceeds 64, which violates the UMB spec for
654 // Double and should be impossible: ValuationDescriptionBuilder::addVariable rejects such
655 // descriptions at construction time (see validateTypeDeclaration).
656 STORM_LOG_ASSERT(varInfo.fits64Bit, "Double variables with more than 64 bits are not compliant.");
657 break;
658 case Rational: {
659 STORM_LOG_ASSERT(bitSize % 2 == 0, "Rational number bit size must be even.");
660 uint64_t const b = bitSize / 2;
661 storm::RationalNumber const numerator = readInteger<true>(getRawBytes(entity), varInfo.bitOffset, b);
662 storm::RationalNumber const denominator = readInteger<false>(getRawBytes(entity), varInfo.bitOffset + b, b);
663 if (invokeCallback(storm::RationalNumber(numerator / denominator))) {
664 return;
665 }
666 break;
667 }
668 case String:
669 // Same reasoning as the Double case above: fits64Bit distinguishes a type mismatch (falls
670 // through to the "not handled" throw below) from a genuine >64-bit violation (asserted
671 // against here, since construction-time validation should now make it impossible).
672 STORM_LOG_ASSERT(varInfo.fits64Bit, "String variables with more than 64 bits are not compliant.");
673 break;
674 default:
675 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException,
676 "ValuationsStorage for variable type '" << varInfo.description.type.toString() << "' are not supported.");
677 }
678
679 STORM_LOG_THROW(false, storm::exceptions::UnexpectedException,
680 "Variable " << varInfo.description.name << " is stored as " << varInfo.description.type.toString()
681 << ", which cannot be read as any of the requested C++ type(s) [" << typeNames<AllowedTypes...>()
682 << "]. Check that you are using the accessor matching the variable's declared storage type (e.g. "
683 "getDoubleValue instead of getRationalValue for a variable added via addDoubleVariable).");
684 }
685
686 template<bool InitializeWithCurrent = false, bool AllowOptional = false, typename... AllowedTypes, ValuationWriteCallback Callback>
687 void write(uint64_t entity, VariableInformation const& varInfo, Callback const& callback) {
688 auto invokeCallback = [this, &entity, &varInfo, &callback]<typename ValueType>() -> bool {
689 bool constexpr IsAllowed = (sizeof...(AllowedTypes) == 0) || std::disjunction_v<std::is_same<ValueType, AllowedTypes>...>;
690 if constexpr (IsAllowed) {
691 ValueType value{}; // value-initialize so that types like bool and double have a defined default
692 bool isOptional = varInfo.description.isOptional.value_or(false);
693 bool initializeAsUnsetOptional = false;
694 if constexpr (InitializeWithCurrent) {
695 // Initialize with current value (if requested)
696 read<std::nullopt_t, ValueType>(entity, varInfo, [&value, &initializeAsUnsetOptional](auto..., auto&& currentValue) {
697 using CurrentVT = std::remove_cvref_t<decltype(currentValue)>;
698 if constexpr (std::is_same_v<CurrentVT, ValueType>) {
699 value = currentValue;
700 } else {
701 static_assert(std::is_same_v<CurrentVT, std::nullopt_t>);
702 initializeAsUnsetOptional = true;
703 }
704 });
705 } else {
706 initializeAsUnsetOptional = isOptional;
707 if constexpr (std::is_same_v<ValueType, uint64_t> || std::is_same_v<ValueType, int64_t> || std::is_same_v<ValueType, Integer>) {
708 // Explicitly initialize integer values to the lower bound, 0, or the upper bound (in that order)
709 if (varInfo.description.lower && (!std::is_same_v<ValueType, uint64_t> || varInfo.description.lower.value() >= 0)) {
710 value = storm::utility::convertNumber<ValueType>(varInfo.description.lower.value());
711 } else if (!varInfo.description.upper || varInfo.description.upper >= 0) {
713 } else {
714 value = storm::utility::convertNumber<ValueType>(varInfo.description.upper.value());
715 }
716 }
717 }
718 // Invoke the callback. Determine if we need to write a value and ensure that `value` holds the value to write.
719 bool haveToWriteValue = false;
720 bool setPresenceBit = false; // The presence bit of an optional variable is only set once the value is validated.
721 if (isOptional) {
722 if constexpr (AllowOptional) {
723 std::optional<ValueType> optionalValue = initializeAsUnsetOptional ? std::optional<ValueType>() : value;
724 callback(entity, varInfo.expressionVariable, optionalValue);
725 if (optionalValue.has_value()) {
726 value = std::move(optionalValue.value());
727 haveToWriteValue = true;
728 setPresenceBit = true;
729 }
730 STORM_LOG_ASSERT(varInfo.bitOffset > 0, "Invalid variable information: optional variable must have a preceding presence bit.");
731 if (!optionalValue.has_value()) {
732 writeBit(getRawBytes(entity), varInfo.bitOffset - 1, false);
733 }
734 } else {
735 STORM_LOG_THROW(false, storm::exceptions::UnexpectedException,
736 "Writing to optional variable " << varInfo.description.name << " was not expected.");
737 }
738 } else {
739 callback(entity, varInfo.expressionVariable, value);
740 haveToWriteValue = true;
741 }
742 if (haveToWriteValue) {
743 // Check bounds and apply the offset for integer variables
744 if constexpr (std::is_same_v<ValueType, uint64_t> || std::is_same_v<ValueType, int64_t> || std::is_same_v<ValueType, Integer>) {
745 if constexpr (std::is_same_v<ValueType, uint64_t> || std::is_same_v<ValueType, int64_t>) {
746 STORM_LOG_THROW(!varInfo.description.lower || std::cmp_greater_equal(value, varInfo.description.lower.value()),
747 storm::exceptions::OutOfRangeException,
748 "Value " << value << " is out of range for variable " << varInfo.description.name
749 << ": value is smaller than lower bound " << varInfo.description.lower.value() << ".");
750 STORM_LOG_THROW(!varInfo.description.upper || std::cmp_less_equal(value, varInfo.description.upper.value()),
751 storm::exceptions::OutOfRangeException,
752 "Value " << value << " is out of range for variable " << varInfo.description.name
753 << ": value is greater than upper bound " << varInfo.description.upper.value() << ".");
754 } else {
755 if (varInfo.description.lower) {
756 STORM_LOG_THROW(value >= storm::utility::convertNumber<Integer>(varInfo.description.lower.value()),
757 storm::exceptions::OutOfRangeException,
758 "Value " << value << " is out of range for variable " << varInfo.description.name
759 << ": value is smaller than lower bound " << varInfo.description.lower.value() << ".");
760 }
761 if (varInfo.description.upper) {
762 STORM_LOG_THROW(value <= storm::utility::convertNumber<Integer>(varInfo.description.upper.value()),
763 storm::exceptions::OutOfRangeException,
764 "Value " << value << " is out of range for variable " << varInfo.description.name
765 << ": value is greater than upper bound " << varInfo.description.upper.value() << ".");
766 }
767 }
768 if (auto offset = varInfo.description.offset.value_or(0); offset != 0) {
769 if constexpr (std::is_same_v<ValueType, uint64_t>) {
770 STORM_LOG_ASSERT(std::cmp_greater_equal(value, offset),
771 "Set negative value " << value << "-" << offset << " to unsigned variable.");
772 value -= offset;
773 } else {
775 }
776 }
777 STORM_LOG_THROW(fitsIntoStoredType(value, varInfo), storm::exceptions::OutOfRangeException,
778 "Value " << value << " does not fit into the " << varInfo.description.type.toString() << " variable "
779 << varInfo.description.name << ".");
780 }
781 // Write the value (and the presence bit for optional variables)
782 if (setPresenceBit) {
783 writeBit(getRawBytes(entity), varInfo.bitOffset - 1, true);
784 }
785 writeValue(getRawBytes(entity), varInfo.bitOffset, varInfo.description.type.bitSize(), value);
786 }
787 }
788 return IsAllowed;
789 };
790
791 using enum storm::umb::Type;
792 switch (varInfo.description.type.type) {
793 case Bool:
794 if (invokeCallback.template operator()<bool>()) {
795 return;
796 }
797 break;
798 case Uint:
799 if (varInfo.fits64Bit) {
800 if (varInfo.description.offset.value_or(0) >= 0) {
801 // non-negative offset, default output type is uint64_t
802 if (invokeCallback.template operator()<uint64_t>()) {
803 return;
804 }
805 }
806 // take int64_t if uint64_t is not allowed or we have a negative offset
807 if (invokeCallback.template operator()<int64_t>()) {
808 return;
809 }
810 }
811 // finally take Integer if the 64 bit types are not allowed or insufficient
812 if (invokeCallback.template operator()<Integer>()) {
813 return;
814 }
815 break;
816 case Int:
817 // Prefer int64_t if it fits and is allowed.
818 if ((varInfo.fits64Bit && invokeCallback.template operator()<int64_t>()) || invokeCallback.template operator()<Integer>()) {
819 return;
820 }
821 break;
822 case Double:
823 if (invokeCallback.template operator()<double>()) {
824 return;
825 }
826 break;
827 case Rational:
828 if (invokeCallback.template operator()<storm::RationalNumber>()) {
829 return;
830 }
831 break;
832 case String:
833 if (invokeCallback.template operator()<std::string>()) {
834 return;
835 }
836 break;
837 default:
838 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException,
839 "ValuationsStorage for variable type '" << varInfo.description.type.toString() << "' are not supported.");
840 }
841 STORM_LOG_THROW(false, storm::exceptions::UnexpectedException,
842 "Variable " << varInfo.description.name << " is stored as " << varInfo.description.type.toString()
843 << ", which cannot be written as any of the requested C++ type(s) [" << typeNames<AllowedTypes...>()
844 << "]. Check that you are using the accessor matching the variable's declared storage type (e.g. "
845 "writeDoubleValue instead of writeRationalValue for a variable added via addDoubleVariable).");
846 }
847};
848} // namespace storm::storage::sparse
Stores valuations of variables for a set of entities (e.g.
ValuationsStorage(ValuationsStorage const &)=default
void writeCallback(uint64_t entity, storm::expressions::Variable const &variable, Callback const &callback)
Writes a single variable of the given entity by invoking callback.
ValueType readValue(uint64_t entity, storm::expressions::Variable const &variable) const
Reads a single variable of the given entity and returns its value directly.
storm::umb::UmbModel::Valuation getRawUmbData() const
Exports a snapshot of the raw UMB model valuation data (packed bytes, optional class mapping,...
bool entityHasVariable(uint64_t entity, storm::expressions::Variable const &variable) const
Returns true iff the variable is relevant for the given entity's class, i.e.
ValuationsStorage selectEntities(T const &selectedEntities) const
Constructs a new ValuationsStorage containing only the selected entities, in the order they appear in...
void resize(uint64_t newEntityCount, uint64_t classIndex=0)
Resizes the entity count to newEntityCount.
std::set< storm::expressions::Variable > getAllVariables() const
Returns all expression variables that this valuation assigns values to for at least one class.
void readCallback(uint64_t entity, Callback const &callback) const
Reads all variables of the given entity and invokes callback for each one.
void writeValue(uint64_t entity, storm::expressions::Variable const &variable, ValueType const &value)
Directly writes value to the given variable of entity.
std::size_t hash() const
Computes a hash of the entire valuation data.
uint64_t getClassOfEntity(uint64_t entity) const
Returns the class index of the given entity.
storm::expressions::ExpressionManager const & getManager() const
Returns the expression manager shared by all classes.
void setValuesInEvaluator(uint64_t entity, storm::expressions::ExpressionEvaluator< RationalValueType > &evaluator) const
Reads the variable values for the given entity and sets them into the given expression evaluator.
void emplaceBack(Callback const &callback)
Convenience overload of emplaceBack for single-class ValuationsStorage (asserts numClasses() == 1).
void writeCallback(uint64_t entity, Callback const &callback)
Writes all variables of the given entity by invoking callback for each one.
void writeCallback(Callback const &callback)
Writes all variables of every entity by invoking callback for each (entity, variable) pair.
VariableInformation const & getVariableInformation(uint64_t entity, storm::expressions::Variable const &variable) const
Looks up compiled variable information for the given entity and variable.
void readCallback(Callback const &callback) const
Reads all variables of every entity and invokes callback for each (entity, variable) pair.
ValuationsStorage & operator=(ValuationsStorage &&)=default
ValuationsStorage(ValuationsStorage &&)=default
storm::NumberTraits< storm::RationalNumber >::IntegerType Integer
ValuationsStorage & operator=(ValuationsStorage const &)=default
void readCallback(storm::expressions::Variable const &variable, Callback const &callback) const
Reads the given variable for every entity and invokes callback for each one.
void emplaceBack(uint64_t classIndex, Callback const &callback)
Appends a new entity of the given class and populates its variables via callback.
ValuationClassDescription getClassDescription(uint64_t classIndex=0) const
Reconstructs the ValuationClassDescription for the given class from the stored compiled variable info...
void readCallback(uint64_t entity, storm::expressions::Variable const &variable, Callback const &callback) const
Reads a single variable of the given entity and invokes callback with its value.
Concept for a callback used in readCallback / readValue.
Concept for a callback used in writeCallback / writeValue.
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:39
SFTBDDChecker::ValueType ValueType
auto stringVectorView(SEQ< char >::value_type const &strings, CSR::value_type const &stringMapping)
NumberTraits< RationalType >::IntegerType denominator(RationalType const &number)
NumberTraits< RationalType >::IntegerType numerator(RationalType const &number)
ValueType zero()
Definition constants.cpp:26
TargetType convertNumber(SourceType const &number)
Compiled information about a single variable within a valuation class.
Compiled information about all variables belonging to one valuation class.
std::shared_ptr< storm::expressions::ExpressionManager const > const expressionManager