Shinya Kitaoka 810553
#pragma once
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef TCG_SEQUENCE_OPS_HPP
Toshihiro Shimizu 890ddd
#define TCG_SEQUENCE_OPS_HPP
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "../sequence_ops.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef min
Toshihiro Shimizu 890ddd
#undef min
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace tcg {
Shinya Kitaoka 120a6e
namespace sequence_ops {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************
Toshihiro Shimizu 890ddd
//    Minimal Path Functions
Toshihiro Shimizu 890ddd
//***********************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename containers_reader="" edge_eval,="" ranit_type,="" typename=""></typename>
Shinya Kitaoka 120a6e
bool minimalPath(ranit_type begin, ranit_type end, edge_eval &eval,
Shinya Kitaoka 120a6e
                 containers_reader &output) {
Shinya Kitaoka 120a6e
  typedef typename ranit_type::difference_type diff_type;
Shinya Kitaoka 120a6e
  typedef typename edge_eval::penalty_type penalty_type;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ranit_type a, b;
Shinya Kitaoka 120a6e
  diff_type i, j, m, n = end - begin, last = n - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Precache the longest edge possible from each vertex, imposing that furthest
Shinya Kitaoka 120a6e
  // nodes have increasing indices.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<diff_type> furthest(n);</diff_type>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  diff_type currFurthest = furthest[last] = last;
Shinya Kitaoka 120a6e
  for (i = last - 1; i >= 0; --i) {
Shinya Kitaoka 120a6e
    currFurthest = furthest[i] =
Shinya Kitaoka 120a6e
        std::min(eval.furthestFrom(begin + i) - begin, currFurthest);
Shinya Kitaoka 120a6e
    if (currFurthest == i)
Shinya Kitaoka 120a6e
      return false;  // There exists no path from start to end - quit
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Iterate from begin to end, using the maximum step allowed. The number of
Shinya Kitaoka 120a6e
  // iterations is the number of output edges.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (i = 0, m = 0; i < last; i = furthest[i], ++m)
Shinya Kitaoka 120a6e
    ;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Also, build the iteration sequence. It will define the upper bounds for the
Shinya Kitaoka 120a6e
  // k-th vertex of the output.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<diff_type> upperBound(m + 1);</diff_type>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (i = 0, j = 0; i <= m; j = furthest[j], ++i) upperBound[i] = j;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Now, the body of the algorithm
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<penalty_type> minPenaltyToEnd(n);</penalty_type>
Shinya Kitaoka 120a6e
  std::vector<diff_type> minPenaltyNext(last);</diff_type>
Shinya Kitaoka 120a6e
  diff_type aIdx, bIdx;
Shinya Kitaoka 120a6e
  penalty_type newPenalty;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  minPenaltyToEnd[last] = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  diff_type nextLowerBound;
Shinya Kitaoka 120a6e
  for (j = m - 1, nextLowerBound = last; j >= 0; --j) {
Shinya Kitaoka 120a6e
    // Build the minimal penalty to end (also storing the next iterator
Shinya Kitaoka 120a6e
    // leading to it) from each vertex of the polygon, assuming the minimal
Shinya Kitaoka 120a6e
    // number of edges from the vertex to end.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // The j-th polygon vertex must lie in the [lowerBound, upperBound[j]]
Shinya Kitaoka 120a6e
    // interval, whereas the (j+1)-th will be in [nextLowerBound,
Shinya Kitaoka 120a6e
    // upperBound[j+1]].
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Please, observe that we always have upperBound[j] < nextLowerBound due
Shinya Kitaoka 120a6e
    // to the minimal edge count constraint.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (aIdx = upperBound[j]; aIdx >= 0 && furthest[aIdx] >= nextLowerBound;
Shinya Kitaoka 120a6e
         --aIdx) {
Shinya Kitaoka 120a6e
      a = begin + aIdx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Search the vertex next to a which minimizes the penalty to end - and
Shinya Kitaoka 120a6e
      // store it.
Shinya Kitaoka 120a6e
      minPenaltyToEnd[aIdx] = (std::numeric_limits<penalty_type>::max)();</penalty_type>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      for (bIdx = nextLowerBound, b = begin + nextLowerBound;
Shinya Kitaoka 120a6e
           furthest[aIdx] >= bIdx; ++b, ++bIdx) {
Shinya Kitaoka 120a6e
        assert(minPenaltyToEnd[bIdx] <
Shinya Kitaoka 120a6e
               (std::numeric_limits<penalty_type>::max)());</penalty_type>
Shinya Kitaoka 120a6e
        newPenalty = eval.penalty(a, b) + minPenaltyToEnd[bIdx];
Shinya Kitaoka 120a6e
        if (newPenalty < minPenaltyToEnd[aIdx]) {
Shinya Kitaoka 120a6e
          minPenaltyToEnd[aIdx] = newPenalty;
Shinya Kitaoka 120a6e
          minPenaltyNext[aIdx]  = bIdx;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Update
Shinya Kitaoka 120a6e
    nextLowerBound = aIdx;
Shinya Kitaoka 120a6e
    ++nextLowerBound;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Finally, build the output sequence
Shinya Kitaoka 120a6e
  output.openContainer(begin);
Shinya Kitaoka 120a6e
  for (i = minPenaltyNext[0], j = 1; j < m; i = minPenaltyNext[i], ++j)
Shinya Kitaoka 120a6e
    output.addElement(begin + i);
Shinya Kitaoka 120a6e
  output.addElement(begin + last);
Shinya Kitaoka 120a6e
  output.closeContainer();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
}  // namespace tcg::sequence_ops
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#endif  // TCG_SEQUENCE_OPS_HPP