Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
HyperplaneEnumeration.cpp
Go to the documentation of this file.
2
6
7namespace storm {
8namespace storage {
9namespace geometry {
10
11template<typename ValueType>
13 bool generateRelevantHyperplanesAndVertexSets) {
14 STORM_LOG_DEBUG("Invoked Hyperplane enumeration with " << constraintMatrix.rows() << " constraints.");
15 Eigen::Index dimension = constraintMatrix.cols();
16 if (dimension == 0) {
17 // No halfspaces means no vertices
18 resultVertices.clear();
19 relevantMatrix = constraintMatrix;
20 relevantVector = constraintVector;
21 vertexSets.clear();
22 return;
23 }
24 std::unordered_map<EigenVector, std::set<uint_fast64_t>> vertexCollector;
25 storm::storage::geometry::SubsetEnumerator<EigenMatrix> subsetEnum(constraintMatrix.rows(), dimension, constraintMatrix,
27 if (subsetEnum.setToFirstSubset()) {
28 do {
29 std::vector<uint_fast64_t> const& subset = subsetEnum.getCurrentSubset();
30
31 EigenMatrix subMatrix(dimension, dimension);
32 EigenVector subVector(dimension);
33 for (Eigen::Index i = 0; i < dimension; ++i) {
34 subMatrix.row(i) = constraintMatrix.row(subset[i]);
35 subVector(i) = constraintVector(subset[i]);
36 }
37
38 EigenVector point = subMatrix.fullPivLu().solve(subVector);
39 bool pointContained = true;
40 for (Eigen::Index row = 0; row < constraintMatrix.rows(); ++row) {
41 if ((constraintMatrix.row(row) * point)(0) > constraintVector(row)) {
42 pointContained = false;
43 break;
44 }
45 }
46 if (pointContained) {
47 // Note that the map avoids duplicates.
48 auto hyperplaneIndices =
49 vertexCollector
50 .insert(typename std::unordered_map<EigenVector, std::set<uint_fast64_t>>::value_type(std::move(point), std::set<uint_fast64_t>()))
51 .first;
52 if (generateRelevantHyperplanesAndVertexSets) {
53 hyperplaneIndices->second.insert(subset.begin(), subset.end());
54 }
55 }
56 } while (subsetEnum.incrementSubset());
57 }
58
59 if (generateRelevantHyperplanesAndVertexSets) {
60 // For each hyperplane, get the number of (unique) vertices that lie on it.
61 std::vector<Eigen::Index> verticesOnHyperplaneCounter(constraintMatrix.rows(), 0);
62 for (auto const& mapEntry : vertexCollector) {
63 for (auto const& hyperplaneIndex : mapEntry.second) {
64 ++verticesOnHyperplaneCounter[hyperplaneIndex];
65 }
66 }
67
68 // Only keep the hyperplanes on which at least dimension() vertices lie.
69 // Note that this will change the indices of the Hyperplanes.
70 // Therefore, we additionally store the old indices for every hyperplane to be able to translate from old to new indices
72 for (uint_fast64_t hyperplaneIndex = 0; hyperplaneIndex < verticesOnHyperplaneCounter.size(); ++hyperplaneIndex) {
73 if (verticesOnHyperplaneCounter[hyperplaneIndex] >= dimension) {
74 std::vector<uint_fast64_t> oldIndex;
75 oldIndex.push_back(hyperplaneIndex);
76 hyperplaneCollector.insert(constraintMatrix.row(hyperplaneIndex), constraintVector(hyperplaneIndex), &oldIndex);
77 }
78 }
79 auto matrixVector = hyperplaneCollector.getCollectedHyperplanesAsMatrixVector();
80 relevantMatrix = std::move(matrixVector.first);
81 relevantVector = std::move(matrixVector.second);
82
83 // Get the mapping from old to new indices
84 std::vector<uint_fast64_t> oldToNewIndexMapping(constraintMatrix.rows(), constraintMatrix.rows()); // Initialize with some illegal value
85 std::vector<std::vector<uint_fast64_t>> newToOldIndexMapping(hyperplaneCollector.getIndexLists());
86 for (uint_fast64_t newIndex = 0; newIndex < newToOldIndexMapping.size(); ++newIndex) {
87 for (auto const& oldIndex : newToOldIndexMapping[newIndex]) {
88 oldToNewIndexMapping[oldIndex] = newIndex;
89 }
90 }
91
92 // Insert the resulting vertices and get the set of vertices that lie on each hyperplane
93 std::vector<std::set<uint_fast64_t>> vertexSets(relevantMatrix.rows());
94 resultVertices.clear();
95 resultVertices.reserve(vertexCollector.size());
96 for (auto const& mapEntry : vertexCollector) {
97 for (auto const& oldHyperplaneIndex : mapEntry.second) {
98 // ignore the hyperplanes which are redundant, i.e. for which there is no new index
99 if ((Eigen::Index)oldToNewIndexMapping[oldHyperplaneIndex] < relevantVector.rows()) {
100 vertexSets[oldToNewIndexMapping[oldHyperplaneIndex]].insert(resultVertices.size());
101 }
102 }
103 resultVertices.push_back(mapEntry.first);
104 }
105 this->vertexSets.clear();
106 this->vertexSets.reserve(vertexSets.size());
107 for (auto const& vertexSet : vertexSets) {
108 this->vertexSets.emplace_back(vertexSet.begin(), vertexSet.end());
109 }
110
111 } else {
112 resultVertices.clear();
113 resultVertices.reserve(vertexCollector.size());
114 for (auto const& mapEntry : vertexCollector) {
115 resultVertices.push_back(mapEntry.first);
116 }
117 this->vertexSets.clear();
118 relevantMatrix = EigenMatrix();
119 relevantVector = EigenVector();
120 }
121}
122
123template<typename ValueType>
124bool HyperplaneEnumeration<ValueType>::linearDependenciesFilter(std::vector<uint_fast64_t> const& subset, uint_fast64_t const& item, EigenMatrix const& A) {
125 EigenMatrix subMatrix(subset.size() + 1, A.cols());
126 for (uint_fast64_t i = 0; i < subset.size(); ++i) {
127 subMatrix.row((Eigen::Index)i) = A.row(Eigen::Index(subset[i]));
128 }
129 subMatrix.row(subset.size()) = A.row(item);
130 Eigen::FullPivLU<EigenMatrix> lUMatrix(subMatrix);
131 if (lUMatrix.rank() < subMatrix.rows()) {
132 // Linear dependent!
133 return false;
134 } else {
135 return true;
136 }
137}
138
139template<typename ValueType>
140std::vector<typename HyperplaneEnumeration<ValueType>::EigenVector>& HyperplaneEnumeration<ValueType>::getResultVertices() {
141 return resultVertices;
142}
143
144template<typename ValueType>
148
149template<typename ValueType>
153
154template<typename ValueType>
155std::vector<std::vector<uint_fast64_t>>& HyperplaneEnumeration<ValueType>::getVertexSets() {
156 return this->vertexSets;
157}
158
159template class HyperplaneEnumeration<double>;
161
162} // namespace geometry
163} // namespace storage
164} // namespace storm
This class can be used to collect a set of hyperplanes (without duplicates).
bool insert(EigenVector const &normal, ValueType const &offset, std::vector< uint_fast64_t > const *indexList=nullptr)
std::vector< std::vector< uint_fast64_t > > getIndexLists() const
std::pair< EigenMatrix, EigenVector > getCollectedHyperplanesAsMatrixVector() const
static bool linearDependenciesFilter(std::vector< uint_fast64_t > const &subset, uint_fast64_t const &item, EigenMatrix const &A)
void generateVerticesFromConstraints(EigenMatrix const &constraintMatrix, EigenVector const &constraintVector, bool generateRelevantHyperplanesAndVertexSets)
EigenMatrix & getRelevantMatrix()
Returns the set of halfspaces which are not redundant.
std::vector< std::vector< uint_fast64_t > > & getVertexSets()
Returns for each hyperplane the set of vertices that lie on that hyperplane.
Eigen::Matrix< ValueType, Eigen::Dynamic, Eigen::Dynamic > EigenMatrix
Eigen::Matrix< ValueType, Eigen::Dynamic, 1 > EigenVector
This class can be used to enumerate all k-sized subsets of {0,...,n-1}.
std::vector< uint_fast64_t > const & getCurrentSubset()
#define STORM_LOG_DEBUG(message)
Definition logging.h:21