Storm 1.13.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
UmbExport.cpp
Go to the documentation of this file.
2
3#include <boost/pfr.hpp>
4
7
11#include "storm/io/file.h"
14
15namespace storm::umb {
16
17namespace detail {
18
19void createDirectory(storm::io::ArchiveWriter& archiveWriter, std::filesystem::path const& subdirectory) {
20 archiveWriter.addDirectory(subdirectory.string());
21}
22
27template<typename VectorType>
28 requires(!std::is_same_v<std::remove_cvref_t<VectorType>, storm::umb::GenericVector>)
29void writeVector(VectorType const& vector, storm::io::ArchiveWriter& archiveWriter, std::filesystem::path const& filepath) {
30 archiveWriter.addBinaryFile(filepath.string(), vector);
31}
32
33void writeVector(GenericVector const& vector, storm::io::ArchiveWriter& target, std::filesystem::path const& filepath) {
34 if (!vector.hasValue()) {
35 return;
36 }
37 if (vector.template isType<bool>()) {
38 writeVector(vector.template get<bool>(), target, filepath);
39 } else if (vector.template isType<uint64_t>()) {
40 writeVector(vector.template get<uint64_t>(), target, filepath);
41 } else if (vector.template isType<int64_t>()) {
42 writeVector(vector.template get<int64_t>(), target, filepath);
43 } else if (vector.template isType<double>()) {
44 writeVector(vector.template get<double>(), target, filepath);
45 } else {
46 STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Unexpected type.");
47 }
48}
49
50template<typename VectorType>
51void writeVector(std::optional<VectorType> const& vector, storm::io::ArchiveWriter& target, std::filesystem::path const& filepath) {
52 if (vector) {
53 writeVector(*vector, target, filepath);
54 }
55}
56
57void writeIndexFile(storm::umb::ModelIndex const& index, storm::io::ArchiveWriter& archiveWriter, std::filesystem::path const& filepath) {
58 archiveWriter.addTextFile(filepath, storm::dumpJson(storm::json<storm::RationalNumber>(index)));
59}
60
61template<typename T>
62concept HasFileNames = requires { T::FileNames.size(); };
63
64template<typename T>
65concept FileNameMap = std::same_as<std::remove_cvref_t<typename T::key_type>, std::string>;
66
67template<typename T>
68concept IsOptionalWithFileNames = std::same_as<std::remove_cvref_t<T>, std::optional<typename T::value_type>> && HasFileNames<typename T::value_type>;
69
70// Forward declare function so that it can be called recursively
71template<typename UmbStructure>
73void exportFiles(UmbStructure const& umbStructure, storm::io::ArchiveWriter& target, std::filesystem::path const& context);
74
75void exportFiles(FileNameMap auto const& umbStructure, storm::io::ArchiveWriter& target, std::filesystem::path const& context) {
76 for (auto const& [key, value] : umbStructure) {
77 if (!key.empty()) {
78 createDirectory(target, context / key);
79 }
80 exportFiles(value, target, context / key);
81 }
82}
83
84template<typename UmbStructure>
85 requires HasFileNames<UmbStructure>
86void exportFiles(UmbStructure const& umbStructure, storm::io::ArchiveWriter& target, std::filesystem::path const& context) {
87 static_assert(UmbStructure::FileNames.size() == boost::pfr::tuple_size_v<UmbStructure>, "Number of file names does not match number of fields in struct.");
88 boost::pfr::for_each_field(umbStructure, [&](auto const& field, std::size_t fieldIndex) {
89 // potentially create directory for sub-field
90 std::filesystem::path fieldName = std::data(UmbStructure::FileNames)[fieldIndex];
91 // export the field, either with a recursive call or via writeVector
92 using FieldType = std::remove_cvref_t<decltype(field)>;
93 if constexpr (HasFileNames<FieldType>) {
94 if (!fieldName.empty()) {
95 createDirectory(target, context / fieldName);
96 }
97 exportFiles(field, target, context / fieldName);
98 } else if constexpr (IsOptionalWithFileNames<FieldType>) {
99 if (field) {
100 if (!fieldName.empty()) {
101 createDirectory(target, context / fieldName);
102 }
103 exportFiles(*field, target, context / fieldName);
104 }
105 } else if constexpr (FileNameMap<FieldType>) {
106 if (!field.empty() && !fieldName.empty()) {
107 createDirectory(target, context / fieldName);
108 }
109 exportFiles(field, target, context / fieldName);
110 } else if constexpr (std::is_same_v<FieldType, storm::umb::ModelIndex>) {
111 writeIndexFile(field, target, context / fieldName);
112 } else if constexpr (std::is_same_v<FieldType, decltype(UmbModel::nonStandardFiles)>) {
113 for (auto const& [path, data] : field) {
114 if (path.has_parent_path()) {
115 createDirectory(target, context / fieldName / path.parent_path());
116 }
117 writeVector(data, target, context / fieldName / path);
118 }
119 } else if constexpr (std::is_same_v<FieldType, GenericVector>) {
120 if (field.template isType<storm::RationalNumber>() || field.template isType<storm::RationalInterval>()) {
121 // Need to call UMBModel::encodeRationals prior to export
122 STORM_LOG_THROW(false, storm::exceptions::UnexpectedException,
123 "Unable to export rational vector '" << (context / fieldName) << "' to UMB. Rational values must be encoded prior to export");
124 } else if (field.template isType<storm::Interval>()) {
125 writeVector(ValueEncoding::intervalToBaseRangeView<double>(field.template get<storm::Interval>()), target, context / fieldName);
126 } else {
127 writeVector(field, target, context / fieldName);
128 }
129 } else {
130 writeVector(field, target, context / fieldName);
131 }
132 });
133}
134
135} // namespace detail
136
137void toArchive(storm::umb::UmbModel const& umbModel, std::filesystem::path const& archivePath, ExportOptions const& options) {
138 auto compression = options.compression;
139 // Set gzip as default compression
140 if (compression == storm::io::CompressionMode::Default) {
142 }
143 storm::io::ArchiveWriter archiveWriter(archivePath, compression);
144 detail::exportFiles(umbModel, archiveWriter, {});
145}
146
147} // namespace storm::umb
void addBinaryFile(std::filesystem::path const &archivePath, Range &&data)
Add a file to the archive using a binary encoding of the provided data.
void addTextFile(std::filesystem::path const &archivePath, std::string const &data)
Add a text file to the archive.
void addDirectory(std::filesystem::path const &archivePath)
Adds a (sub-) directory to the archive.
Represents a model in the UMB format.
Definition UmbModel.h:21
std::map< std::filesystem::path, std::vector< char > > nonStandardFiles
Definition UmbModel.h:81
static auto intervalToBaseRangeView(InputRange &&input)
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
void writeVector(VectorType const &vector, storm::io::ArchiveWriter &archiveWriter, std::filesystem::path const &filepath)
Write a vector to archive.
Definition UmbExport.cpp:29
void writeIndexFile(storm::umb::ModelIndex const &index, storm::io::ArchiveWriter &archiveWriter, std::filesystem::path const &filepath)
Definition UmbExport.cpp:57
void createDirectory(storm::io::ArchiveWriter &archiveWriter, std::filesystem::path const &subdirectory)
Definition UmbExport.cpp:19
void exportFiles(UmbStructure const &umbStructure, storm::io::ArchiveWriter &target, std::filesystem::path const &context)
Definition UmbExport.cpp:86
std::conditional_t< std::is_same_v< T, bool >, storm::storage::BitVector, std::vector< T > > VectorType
Definition FileTypes.h:18
void toArchive(storm::umb::UmbModel const &umbModel, std::filesystem::path const &archivePath, ExportOptions const &options)
nlohmann::basic_json< std::map, std::vector, std::string, bool, int64_t, uint64_t, ValueType > json
Definition JsonForward.h:10
std::string dumpJson(storm::json< ValueType > const &j, bool compact)
Dumps the given json object, producing a String.
storm::io::CompressionMode compression
The type of compression used for the exported UMB model.