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))