Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
QuickHull.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <unordered_map>
5
13
14namespace storm {
15namespace storage {
16namespace geometry {
17
18template<typename ValueType>
19void QuickHull<ValueType>::generateHalfspacesFromPoints(std::vector<EigenVector>& points, bool generateRelevantVerticesAndVertexSets) {
20 STORM_LOG_ASSERT(!points.empty(), "Invoked QuickHull with empty set of points.");
21 STORM_LOG_DEBUG("Invoked QuickHull on " << points.size() << " points");
22 const uint_fast64_t dimension = points.front().rows();
23
24 if (dimension == 1) {
25 handle1DPoints(points, generateRelevantVerticesAndVertexSets);
26 } else {
27 // Generate initial set of d+1 affine independent points (if such a set exists)
28 std::vector<uint_fast64_t> vertexIndices;
29 if (this->findInitialVertices(points, vertexIndices)) {
30 // compute point inside initial facet
31 EigenVector insidePoint(EigenVector::Zero(dimension));
32 for (uint_fast64_t vertexIndex : vertexIndices) {
33 insidePoint += points[vertexIndex];
34 }
35 insidePoint /= storm::utility::convertNumber<ValueType>(static_cast<uint_fast64_t>(vertexIndices.size()));
36
37 // Create the initial facets from the found vertices.
38 std::vector<Facet> facets = computeInitialFacets(points, vertexIndices, insidePoint);
39
40 // Enlarge the mesh
41 storm::storage::BitVector currentFacets(facets.size(), true);
42 this->extendMesh(points, facets, currentFacets, insidePoint);
43
44 // Finally retrieve the resulting constrants
45 this->getPolytopeFromMesh(points, facets, currentFacets, generateRelevantVerticesAndVertexSets);
46 STORM_LOG_DEBUG("QuickHull invokation yielded " << resultMatrix.rows() << " constraints");
47 } else {
48 // The points are affine dependent. This special case needs to be handled accordingly.
49 handleAffineDependentPoints(points, generateRelevantVerticesAndVertexSets);
50 }
51 }
52}
53
54template<typename ValueType>
56 return this->resultMatrix;
57}
58
59template<typename ValueType>
61 return this->resultVector;
62}
63
64template<typename ValueType>
65std::vector<typename QuickHull<ValueType>::EigenVector>& QuickHull<ValueType>::getRelevantVertices() {
66 return this->relevantVertices;
67}
68
69template<typename ValueType>
70std::vector<std::vector<uint_fast64_t>>& QuickHull<ValueType>::getVertexSets() {
71 return this->vertexSets;
72}
73
74template<typename ValueType>
75void QuickHull<ValueType>::handle1DPoints(std::vector<EigenVector>& points, bool generateRelevantVerticesAndVertexSets) {
76 ValueType minValue = points.front()(0);
77 ValueType maxValue = points.front()(0);
78 uint_fast64_t minIndex = 0;
79 uint_fast64_t maxIndex = 0;
80 for (uint_fast64_t pointIndex = 1; pointIndex < points.size(); ++pointIndex) {
81 ValueType const& pointValue = points[pointIndex](0);
82 if (pointValue < minValue) {
83 minValue = pointValue;
84 minIndex = pointIndex;
85 }
86 if (pointValue > maxValue) {
87 maxValue = pointValue;
88 maxIndex = pointIndex;
89 }
90 }
91 resultMatrix = EigenMatrix(2, 1);
92 resultMatrix(0, 0) = -storm::utility::one<ValueType>();
93 resultMatrix(1, 0) = storm::utility::one<ValueType>();
94 resultVector = EigenVector(2);
95 resultVector(0) = -minValue;
96 resultVector(1) = maxValue;
97 if (generateRelevantVerticesAndVertexSets) {
98 relevantVertices.push_back(points[minIndex]);
99 std::vector<uint_fast64_t> minVertexSet(1, 0);
100 vertexSets.push_back(std::move(minVertexSet));
101 if (minIndex != maxIndex && points[minIndex] != points[maxIndex]) {
102 relevantVertices.push_back(points[maxIndex]);
103 std::vector<uint_fast64_t> maxVertexSet(1, 1);
104 vertexSets.push_back(std::move(maxVertexSet));
105 } else {
106 vertexSets.push_back(vertexSets.front());
107 }
108 }
109}
110
111template<typename ValueType>
112bool QuickHull<ValueType>::affineFilter(std::vector<uint_fast64_t> const& subset, uint_fast64_t const& item, std::vector<EigenVector> const& points) {
113 EigenMatrix vectorMatrix(points[item].rows() + 1, subset.size() + 1);
114 for (uint_fast64_t i = 0; i < subset.size(); ++i) {
115 vectorMatrix.col(i) << points[subset[i]], storm::utility::one<ValueType>();
116 }
117 vectorMatrix.col(subset.size()) << points[item], storm::utility::one<ValueType>();
118 return (vectorMatrix.fullPivLu().rank() > (Eigen::Index)subset.size());
119}
120
121template<typename ValueType>
122void QuickHull<ValueType>::handleAffineDependentPoints(std::vector<EigenVector>& points, bool generateRelevantVerticesAndVertexSets) {
123 bool pointsAffineDependent = true;
124 std::vector<std::pair<EigenVector, ValueType>> additionalConstraints;
125 while (pointsAffineDependent) {
126 // get one hyperplane that holds all points
127 const uint_fast64_t dimension = points.front().rows();
128 EigenVector refPoint = points.front();
129 EigenVector normal;
130 if (points.size() == 1) {
131 normal.resize(dimension);
132 normal(0) = storm::utility::one<ValueType>();
133 } else {
134 EigenMatrix constraints(points.size() - 1, dimension);
135 for (unsigned row = 1; row < points.size(); ++row) {
136 constraints.row(row - 1) = points[row] - refPoint;
137 }
138 normal = constraints.fullPivLu().kernel().col(0);
139 }
140
141 // Eigen returns the column vector 0...0 if the kernel is empty (i.e., there is no such hyperplane)
142 if (normal.isZero()) {
143 pointsAffineDependent = false;
144 } else {
145 points.push_back(refPoint + normal);
146 ValueType offset = normal.dot(refPoint);
147 additionalConstraints.emplace_back(std::move(normal), std::move(offset));
148 }
149 }
150 // Now the points are affine independent so we can relaunch the procedure
151 generateHalfspacesFromPoints(points, generateRelevantVerticesAndVertexSets);
152
153 // Add the constraints obtained above
154 uint_fast64_t numOfAdditionalConstraints = additionalConstraints.size();
155 uint_fast64_t numOfRegularConstraints = resultMatrix.rows();
156 EigenMatrix newA(numOfRegularConstraints + numOfAdditionalConstraints, resultMatrix.cols());
157 EigenVector newb(static_cast<unsigned long int>(numOfRegularConstraints + numOfAdditionalConstraints));
158 uint_fast64_t row = 0;
159 for (; row < numOfRegularConstraints; ++row) {
160 newA.row(row) = resultMatrix.row(row);
161 newb(row) = resultVector(row);
162 }
163 for (; row < numOfRegularConstraints + numOfAdditionalConstraints; ++row) {
164 newA.row(row) = std::move(additionalConstraints[row - numOfRegularConstraints].first);
165 newb(row) = additionalConstraints[row - numOfRegularConstraints].second;
166 }
167 resultMatrix = std::move(newA);
168 resultVector = std::move(newb);
169
170 // clear the additionally added points. Note that the order of the points might have changed
171 storm::storage::BitVector keptPoints(points.size(), true);
172 for (uint_fast64_t pointIndex = 0; pointIndex < points.size(); ++pointIndex) {
173 for (Eigen::Index row = 0; row < resultMatrix.rows(); ++row) {
174 if ((resultMatrix.row(row) * points[pointIndex])(0) > resultVector(row)) {
175 keptPoints.set(pointIndex, false);
176 break;
177 }
178 }
179 }
181
182 if (generateRelevantVerticesAndVertexSets) {
183 storm::storage::BitVector keptVertices(relevantVertices.size(), true);
184 for (uint_fast64_t vertexIndex = 0; vertexIndex < relevantVertices.size(); ++vertexIndex) {
185 for (Eigen::Index row = 0; row < resultMatrix.rows(); ++row) {
186 if ((resultMatrix.row(row) * relevantVertices[vertexIndex])(0) > resultVector(row)) {
187 keptVertices.set(vertexIndex, false);
188 break;
189 }
190 }
191 }
192 storm::utility::vector::filterVectorInPlace(relevantVertices, keptVertices);
193
194 STORM_LOG_WARN("Can not retrieve vertex sets for degenerated polytope (not implemented)");
195 vertexSets.clear();
196 }
197}
198
199template<typename ValueType>
200bool QuickHull<ValueType>::findInitialVertices(std::vector<EigenVector>& points, std::vector<uint_fast64_t>& verticesOfInitialPolytope) const {
201 const uint_fast64_t dimension = points.front().rows();
202 if (points.size() < dimension + 1) {
203 // not enough points to obtain a (non-degenerated) polytope
204 return false;
205 }
206
207 // We first find some good candidates to get a (hopefully) large initial mesh.
208 storm::storage::BitVector notGoodCandidates(points.size(), true);
209 for (uint_fast64_t dim = 0; dim < dimension; ++dim) {
210 if (!notGoodCandidates.empty()) {
211 uint_fast64_t minIndex = *notGoodCandidates.begin();
212 uint_fast64_t maxIndex = *notGoodCandidates.begin();
213 for (uint_fast64_t pointIndex : notGoodCandidates) {
214 if (points[minIndex](dim) > points[pointIndex](dim)) {
215 minIndex = pointIndex;
216 }
217 if (points[maxIndex](dim) < points[pointIndex](dim)) {
218 maxIndex = pointIndex;
219 }
220 }
221 notGoodCandidates.set(minIndex, false);
222 notGoodCandidates.set(maxIndex, false);
223 }
224 }
225 storm::storage::BitVector goodCandidates = ~notGoodCandidates;
226
227 // Found candidates. Now swap them to the front.
228 const uint_fast64_t numOfGoodCandidates = goodCandidates.getNumberOfSetBits();
229 for (auto goodCandidate : goodCandidates) {
230 if (goodCandidate >= numOfGoodCandidates) {
231 uint_fast64_t notGoodCandidate = *notGoodCandidates.begin();
232 assert(notGoodCandidate < numOfGoodCandidates);
233 std::swap(points[notGoodCandidate], points[goodCandidate]);
234 notGoodCandidates.set(notGoodCandidate, false);
235 }
236 }
237
238 storm::storage::geometry::SubsetEnumerator<std::vector<EigenVector>> subsetEnum(points.size(), dimension + 1, points, affineFilter);
239 if (subsetEnum.setToFirstSubset()) {
240 verticesOfInitialPolytope = subsetEnum.getCurrentSubset();
241 return true;
242 } else {
243 return false;
244 }
245}
246
247template<typename ValueType>
248std::vector<typename QuickHull<ValueType>::Facet> QuickHull<ValueType>::computeInitialFacets(std::vector<EigenVector> const& points,
249 std::vector<uint_fast64_t> const& verticesOfInitialPolytope,
250 EigenVector const& insidePoint) const {
251 const uint_fast64_t dimension = points.front().rows();
252 assert(verticesOfInitialPolytope.size() == dimension + 1);
253 std::vector<Facet> result;
254 result.reserve(dimension + 1);
255 storm::storage::geometry::SubsetEnumerator<> subsetEnum(verticesOfInitialPolytope.size(), dimension);
256 if (!subsetEnum.setToFirstSubset()) {
257 STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Could not find an initial subset.");
258 }
259 do {
260 Facet newFacet;
261 // set the points that lie on the new facet
262 std::vector<uint_fast64_t> const& subset(subsetEnum.getCurrentSubset());
263 newFacet.points.reserve(subset.size());
264 for (uint_fast64_t i : subset) {
265 newFacet.points.push_back(verticesOfInitialPolytope[i]);
266 }
267 // neighbors: these are always the remaining facets
268 newFacet.neighbors.reserve(dimension);
269 for (uint_fast64_t i = 0; i < dimension + 1; ++i) {
270 if (i != result.size()) { // initFacets.size() will be the index of this new facet!
271 newFacet.neighbors.push_back(i);
272 }
273 }
274 // normal and offset:
275 computeNormalAndOffsetOfFacet(points, insidePoint, newFacet);
276
277 result.push_back(std::move(newFacet));
278 } while (subsetEnum.incrementSubset());
279 assert(result.size() == dimension + 1);
280 return result;
281}
282
283template<typename ValueType>
284void QuickHull<ValueType>::computeNormalAndOffsetOfFacet(std::vector<EigenVector> const& points, EigenVector const& insidePoint, Facet& facet) const {
285 const uint_fast64_t dimension = points.front().rows();
286 assert(facet.points.size() == dimension);
287 EigenVector const& refPoint = points[facet.points.back()];
288 EigenMatrix constraints(dimension - 1, dimension);
289 for (unsigned row = 0; row < dimension - 1; ++row) {
290 constraints.row(row) = (points[facet.points[row]] - refPoint);
291 }
292 facet.normal = constraints.fullPivLu().kernel().col(0);
293 facet.offset = facet.normal.dot(refPoint);
294
295 // invert the plane if the insidePoint is not contained in it
296 if (facet.normal.dot(insidePoint) > facet.offset) {
297 facet.normal = -facet.normal;
298 facet.offset = -facet.offset;
299 }
300}
301
302template<typename ValueType>
303void QuickHull<ValueType>::extendMesh(std::vector<EigenVector>& points, std::vector<Facet>& facets, storm::storage::BitVector& currentFacets,
304 EigenVector& insidePoint) const {
305 storm::storage::BitVector currentOutsidePoints(points.size(), true);
306 // Compute initial outside Sets
307 for (uint_fast64_t facetIndex : currentFacets) {
308 computeOutsideSetOfFacet(facets[facetIndex], currentOutsidePoints, points);
309 }
310
311 for (uint_fast64_t facetCount = currentFacets.getNextSetIndex(0); facetCount != currentFacets.size();
312 facetCount = currentFacets.getNextSetIndex(facetCount + 1)) {
313 // set all points to false to get rid of points that lie within the polytope after each iteration
314 currentOutsidePoints.clear();
315 // Find a facet with a non-empty outside set
316 if (!facets[facetCount].outsideSet.empty()) {
317 uint_fast64_t numberOfNewFacets = 0;
318 // Now we compute the enlarged mesh
319 uint_fast64_t farAwayPointIndex = facets[facetCount].maxOutsidePointIndex;
320 // get Visible set from maxOutsidePoint of the current facet
321 std::set<uint_fast64_t> visibleSet = getVisibleSet(facets, facetCount, points[farAwayPointIndex]);
322 std::set<uint_fast64_t> invisibleSet = getInvisibleNeighbors(facets, visibleSet);
323 for (auto invisFacetIt = invisibleSet.begin(); invisFacetIt != invisibleSet.end(); ++invisFacetIt) {
324 for (auto visFacetIt = visibleSet.begin(); visFacetIt != visibleSet.end(); ++visFacetIt) {
325 if (std::find(facets[*invisFacetIt].neighbors.begin(), facets[*invisFacetIt].neighbors.end(), *visFacetIt) !=
326 facets[*invisFacetIt].neighbors.end()) {
327 Facet newFacet;
328 // Set points of Facet
329 newFacet.points = getCommonPoints(facets[*invisFacetIt], facets[*visFacetIt]);
330 newFacet.points.push_back(farAwayPointIndex);
331 // replace old facet index by new facet index in the current neighbor
332 replaceFacetNeighbor(facets, *visFacetIt, facets.size(), *invisFacetIt);
333 newFacet.neighbors.push_back(*invisFacetIt);
334 // Compute the normal and the offset
335 computeNormalAndOffsetOfFacet(points, insidePoint, newFacet);
336
337 // add new facet
338 facets.push_back(newFacet);
339 currentFacets.resize(currentFacets.size() + 1, true);
340 // increase Number Of new Facets
341 ++numberOfNewFacets;
342 }
343 }
344 }
345
346 for (auto visibleFacet : visibleSet) {
347 for (uint_fast64_t outsidePoint : facets[visibleFacet].outsideSet) {
348 currentOutsidePoints.set(outsidePoint, true);
349 }
350 currentFacets.set(visibleFacet, false);
351 }
352 // compute new outside sets
353 for (uint_fast64_t facetIndex : currentFacets) {
354 computeOutsideSetOfFacet(facets[facetIndex], currentOutsidePoints, points);
355 }
356
357 // find neighbors in new facets
358 setNeighborhoodOfNewFacets(facets, facets.size() - numberOfNewFacets, points.front().rows());
359 }
360 }
361}
362
363template<typename ValueType>
364void QuickHull<ValueType>::getPolytopeFromMesh(std::vector<EigenVector> const& points, std::vector<Facet> const& facets,
365 storm::storage::BitVector const& currentFacets, bool generateRelevantVerticesAndVertexSets) {
367 for (auto facet : currentFacets) {
368 hyperplaneCollector.insert(std::move(facets[facet].normal), std::move(facets[facet].offset),
369 generateRelevantVerticesAndVertexSets ? &facets[facet].points : nullptr);
370 }
371
372 if (generateRelevantVerticesAndVertexSets) {
373 // Get the mapping from a hyperplane to the set of vertices that lie on that plane, erase the duplicates, and count for each vertex the number of
374 // hyperplanes on which that vertex lies
375 vertexSets = hyperplaneCollector.getIndexLists();
376 std::vector<uint_fast64_t> hyperplanesOnVertexCounter(points.size(), 0);
377 for (auto& vertexVector : vertexSets) {
378 std::set<uint_fast64_t> vertexSet;
379 for (auto const& i : vertexVector) {
380 if (vertexSet.insert(i).second) {
381 ++hyperplanesOnVertexCounter[i];
382 }
383 }
384 vertexVector.assign(vertexSet.begin(), vertexSet.end());
385 }
386 // Now, we can erase all vertices which do not lie on at least dimension hyperplanes.
387 // Note that the indices of the HyperplaneToVerticesMapping needs to be refreshed according to the new set of vertices
388 // Therefore, we additionally store the old indices for every vertex to be able to translate from old to new indices
389 std::unordered_map<EigenVector, std::vector<uint_fast64_t>> relevantVerticesMap;
390 relevantVerticesMap.reserve(points.size());
391 for (uint_fast64_t vertexIndex = 0; vertexIndex < hyperplanesOnVertexCounter.size(); ++vertexIndex) {
392 if ((Eigen::Index)hyperplanesOnVertexCounter[vertexIndex] >= points.front().rows()) {
393 auto mapEntry = relevantVerticesMap
394 .insert(typename std::unordered_map<EigenVector, std::vector<uint_fast64_t>>::value_type(points[vertexIndex],
395 std::vector<uint_fast64_t>()))
396 .first;
397 mapEntry->second.push_back(vertexIndex);
398 }
399 }
400 // Fill in the relevant vertices and create a translation map from old to new indices
401 std::vector<uint_fast64_t> oldToNewIndexMapping(points.size(), points.size()); // Initialize with some illegal value
402 relevantVertices.clear();
403 relevantVertices.reserve(relevantVerticesMap.size());
404 for (auto const& mapEntry : relevantVerticesMap) {
405 for (auto const& oldIndex : mapEntry.second) {
406 oldToNewIndexMapping[oldIndex] = relevantVertices.size();
407 }
408 relevantVertices.push_back(mapEntry.first);
409 }
410 // Actually translate and erase duplicates
411 for (auto& vertexVector : vertexSets) {
412 std::set<uint_fast64_t> vertexSet;
413 for (auto const& oldIndex : vertexVector) {
414 if ((Eigen::Index)hyperplanesOnVertexCounter[oldIndex] >= points.front().rows()) {
415 vertexSet.insert(oldToNewIndexMapping[oldIndex]);
416 }
417 }
418 vertexVector.assign(vertexSet.begin(), vertexSet.end());
419 }
420 } else {
421 relevantVertices.clear();
422 vertexSets.clear();
423 }
424 auto matrixVector = hyperplaneCollector.getCollectedHyperplanesAsMatrixVector();
425 resultMatrix = std::move(matrixVector.first);
426 resultVector = std::move(matrixVector.second);
427}
428
429template<typename ValueType>
430std::set<uint_fast64_t> QuickHull<ValueType>::getVisibleSet(std::vector<Facet> const& facets, uint_fast64_t const& startIndex, EigenVector const& point) const {
431 std::set<uint_fast64_t> facetsToCheck;
432 std::set<uint_fast64_t> facetsChecked;
433 std::set<uint_fast64_t> visibleSet;
434 facetsChecked.insert(startIndex);
435 visibleSet.insert(startIndex);
436 for (uint_fast64_t i = 0; i < facets[startIndex].neighbors.size(); ++i) {
437 facetsToCheck.insert(facets[startIndex].neighbors[i]);
438 }
439 while (!facetsToCheck.empty()) {
440 auto elementIt = facetsToCheck.begin();
441 if (point.dot(facets[*elementIt].normal) > facets[*elementIt].offset) {
442 visibleSet.insert(*elementIt);
443 for (uint_fast64_t i = 0; i < facets[*elementIt].neighbors.size(); ++i) {
444 if (facetsChecked.find(facets[*elementIt].neighbors[i]) == facetsChecked.end()) {
445 facetsToCheck.insert(facets[*elementIt].neighbors[i]);
446 }
447 }
448 }
449 facetsChecked.insert(*elementIt);
450 facetsToCheck.erase(elementIt);
451 }
452 return visibleSet;
453}
454
455template<typename ValueType>
456void QuickHull<ValueType>::setNeighborhoodOfNewFacets(std::vector<Facet>& facets, uint_fast64_t firstNewFacet, uint_fast64_t dimension) const {
457 for (uint_fast64_t currentFacet = firstNewFacet; currentFacet < facets.size(); ++currentFacet) {
458 for (uint_fast64_t otherFacet = currentFacet + 1; otherFacet < facets.size(); ++otherFacet) {
459 if (getCommonPoints(facets[currentFacet], facets[otherFacet]).size() >= dimension - 1) {
460 facets[currentFacet].neighbors.push_back(otherFacet);
461 facets[otherFacet].neighbors.push_back(currentFacet);
462 }
463 }
464 }
465}
466
467template<typename ValueType>
468void QuickHull<ValueType>::replaceFacetNeighbor(std::vector<Facet>& facets, uint_fast64_t oldFacetIndex, uint_fast64_t newFacetIndex,
469 uint_fast64_t neighborIndex) const {
470 auto facetInNeighborListIt = std::find(facets[neighborIndex].neighbors.begin(), facets[neighborIndex].neighbors.end(), oldFacetIndex);
471 if (facetInNeighborListIt != facets[neighborIndex].neighbors.end()) {
472 *facetInNeighborListIt = newFacetIndex;
473 }
474}
475
476template<typename ValueType>
477void QuickHull<ValueType>::computeOutsideSetOfFacet(Facet& facet, storm::storage::BitVector& currentOutsidePoints,
478 std::vector<EigenVector> const& points) const {
479 ValueType maxMultiplicationResult = facet.offset;
480 for (uint_fast64_t pointIndex : currentOutsidePoints) {
481 ValueType multiplicationResult = points[pointIndex].dot(facet.normal);
482 if (multiplicationResult > facet.offset) {
483 currentOutsidePoints.set(pointIndex, false); // we already know that the point lies outside so it can be ignored for future facets
484 facet.outsideSet.push_back(pointIndex);
485 if (multiplicationResult > maxMultiplicationResult) {
486 maxMultiplicationResult = multiplicationResult;
487 facet.maxOutsidePointIndex = pointIndex;
488 }
489 }
490 }
491}
492
493template<typename ValueType>
494std::vector<uint_fast64_t> QuickHull<ValueType>::getCommonPoints(Facet const& lhs, Facet const& rhs) const {
495 std::vector<uint_fast64_t> commonPoints;
496 for (uint_fast64_t lhsPoint : lhs.points) {
497 for (uint_fast64_t rhsPoint : rhs.points) {
498 if (lhsPoint == rhsPoint) {
499 commonPoints.push_back(lhsPoint);
500 }
501 }
502 }
503 return commonPoints;
504}
505
506template<typename ValueType>
507std::set<uint_fast64_t> QuickHull<ValueType>::getInvisibleNeighbors(std::vector<Facet>& facets, std::set<uint_fast64_t> const& visibleSet) const {
508 std::set<uint_fast64_t> invisibleNeighbors;
509 for (auto currentFacetIt = visibleSet.begin(); currentFacetIt != visibleSet.end(); ++currentFacetIt) {
510 for (uint_fast64_t currentNeighbor = 0; currentNeighbor < facets[*currentFacetIt].neighbors.size(); ++currentNeighbor) {
511 if (visibleSet.find(facets[*currentFacetIt].neighbors[currentNeighbor]) == visibleSet.end()) {
512 invisibleNeighbors.insert(facets[*currentFacetIt].neighbors[currentNeighbor]);
513 }
514 }
515 }
516 return invisibleNeighbors;
517}
518
519template class QuickHull<double>;
520template class QuickHull<storm::RationalNumber>;
521
522} // namespace geometry
523} // namespace storage
524} // namespace storm
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
uint64_t getNextSetIndex(uint64_t startingIndex) const
Retrieves the index of the bit that is the next bit set to true in the bit vector.
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
void resize(uint64_t newLength, bool init=false)
Resizes the bit vector to hold the given new number of bits.
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
Eigen::Matrix< ValueType, Eigen::Dynamic, Eigen::Dynamic > EigenMatrix
Definition QuickHull.h:16
std::vector< EigenVector > & getRelevantVertices()
Returns the set of vertices which are not redundant.
Definition QuickHull.cpp:65
Eigen::Matrix< ValueType, Eigen::Dynamic, 1 > EigenVector
Definition QuickHull.h:17
void generateHalfspacesFromPoints(std::vector< EigenVector > &points, bool generateRelevantVerticesAndVertexSets)
Definition QuickHull.cpp:19
std::vector< std::vector< std::uint_fast64_t > > & getVertexSets()
Returns for each hyperplane the set of vertices that lie on that hyperplane.
Definition QuickHull.cpp:70
This class can be used to enumerate all k-sized subsets of {0,...,n-1}.
#define STORM_LOG_WARN(message)
Definition logging.h:25
#define STORM_LOG_DEBUG(message)
Definition logging.h:18
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
SFTBDDChecker::ValueType ValueType
void filterVectorInPlace(std::vector< Type > &v, storm::storage::BitVector const &filter)
Definition vector.h:1075