1 #ifndef AI_TOOLBOX_UTILS_POLYTOPE_HEADER_FILE
2 #define AI_TOOLBOX_UTILS_POLYTOPE_HEADER_FILE
30 using PointSurface = std::pair<std::vector<Point>, std::vector<double>>;
64 template <
typename Iterator,
typename P = std::
identity>
65 Iterator
findBestAtPoint(
const Point & point, Iterator begin, Iterator end,
double * value =
nullptr, P p = P{}) {
66 auto bestMatch = begin;
67 double bestValue = point.dot(std::invoke(p, *bestMatch));
69 while ( (++begin) < end ) {
70 const double currValue = point.dot(std::invoke(p, *begin));
71 if ( currValue > bestValue || ( currValue == bestValue &&
veccmp(std::invoke(p, *begin), std::invoke(p, *bestMatch)) > 0 ) ) {
73 bestValue = currValue;
76 if ( value ) *value = bestValue;
94 template <
typename Iterator,
typename P = std::
identity>
95 Iterator
findBestAtSimplexCorner(
const size_t corner, Iterator begin, Iterator end,
double * value =
nullptr, P p = P{}) {
96 auto bestMatch = begin;
97 double bestValue = std::invoke(p, *bestMatch)[corner];
99 while ( (++begin) < end ) {
100 const double currValue = std::invoke(p, *begin)[corner];
101 if ( currValue > bestValue || ( currValue == bestValue &&
veccmp(std::invoke(p, *begin), std::invoke(p, *bestMatch)) > 0 ) ) {
103 bestValue = currValue;
106 if ( value ) *value = bestValue;
137 template <
typename Iterator,
typename P = std::
identity>
142 double maxVal = point.dot(*maxPlane);
144 for (
auto it = begin; it < end; ++it) {
145 const Hyperplane * newPlane = &std::invoke(p, *it);
146 const double newVal = point.dot(*newPlane);
147 if (newVal > maxVal) {
148 const double deltaValue = (newVal - maxVal) / (*newPlane - *maxPlane).norm();
149 if (deltaValue > delta) {
176 template <
typename Iterator,
typename P = std::
identity>
180 if ( bestMatch >= bound )
181 std::iter_swap(bestMatch, bound++);
208 template <
typename Iterator,
typename P = std::
identity>
210 if ( end == bound )
return bound;
213 for (
size_t s = 0; s < S; ++s ) {
216 if ( bestMatch >= bound )
217 std::iter_swap(bestMatch, bound++);
247 template <
typename PIterator,
typename VIterator,
typename P = std::
identity>
249 const auto pointsN = std::distance(pbegin, pend);
250 const auto entriesN = std::distance(begin, end);
252 std::vector<std::pair<PIterator, double>> bestValues(entriesN, {pend, std::numeric_limits<double>::lowest()});
253 const auto maxBound = pointsN < entriesN ? pend : pbegin + entriesN;
266 while (it < bound && it < maxBound) {
268 const auto vId = std::distance(begin,
findBestAtPoint(*it, begin, end, &value, p));
269 if (bestValues[vId].second < value) {
270 if (bestValues[vId].first == pend) {
271 bestValues[vId] = {it++, value};
274 bestValues[vId].second = value;
275 std::iter_swap(bestValues[vId].first, it);
278 std::iter_swap(it, --bound);
280 if (it == bound)
return it;
291 const auto vId = std::distance(begin,
findBestAtPoint(*it, begin, end, &value, p));
292 if (bestValues[vId].second < value) {
293 bestValues[vId].second = value;
294 std::iter_swap(bestValues[vId].first, it);
339 template <
typename NewIt,
typename OldIt,
typename P1 = std::
identity,
typename P2 = std::
identity>
343 const size_t alphasSize = std::distance(alphasBegin, alphasEnd);
344 if (alphasSize == 0)
return vertices;
345 const size_t S = std::invoke(p2, *alphasBegin).size();
350 SubsetEnumerator enumerator(S - 1, 0ul, alphasSize + S);
360 Vector b(S+1); b.setZero();
366 for (
auto newVIt = beginNew; newVIt != endNew; ++newVIt) {
367 m.row(0).head(S) = std::invoke(p1, *newVIt);
373 while (enumerator.isValid()) {
375 boundary.head(S).fill(1.0);
376 size_t counter = last + 1;
379 for (
auto i = last; i < enumerator->size(); ++i) {
383 const auto index = (*enumerator)[i];
384 if (index < alphasSize) {
386 m.row(counter).head(S) = std::invoke(p2, *std::next(alphasBegin, index));
387 m.row(counter)[S] = -1;
391 boundary[index - alphasSize] = 0.0;
394 m.row(counter) = boundary;
400 result = m.topRows(counter).colPivHouseholderQr().solve(b.head(counter));
405 const double max = result.head(S).maxCoeff();
407 vertices.first.emplace_back(result.head(S));
408 vertices.second.emplace_back(result[S]);
413 last = enumerator.advance();
419 if ((*enumerator)[0] >= alphasSize)
break;
436 template <
typename Range,
typename P = std::
identity>
440 std::array<size_t, 1> indexToSkip;
442 auto goodBegin = range.cbegin();
443 for (
size_t i = 0; i < range.size(); ++i, ++goodBegin) {
448 const auto cbegin = map.cbegin();
449 const auto cend = map.cend();
452 auto newVertices =
findVerticesNaive(goodBegin, goodBegin + 1, cbegin, cend, p, p);
454 retval.first.insert(std::end(retval.first),
455 std::make_move_iterator(std::begin(newVertices.first)),
456 std::make_move_iterator(std::end(newVertices.first))
458 retval.second.insert(std::end(retval.second),
459 std::make_move_iterator(std::begin(newVertices.second)),
460 std::make_move_iterator(std::end(newVertices.second))