n-Dimensional Fast Methods  0.7
 All Classes Functions Variables Typedefs Pages
gradientdescent.hpp
1 
20 #ifndef GRADIENTDESCENT_H_
21 #define GRADIENTDESCENT_H_
22 
23 #include <iostream>
24 #include <vector>
25 #include <array>
26 #include <algorithm>
27 #include <cmath>
28 #include <numeric>
29 
30 #include <fast_methods/ndgridmap/ndgridmap.hpp>
31 #include <fast_methods/ndgridmap/fmcell.h>
32 
34 
36 template <typename T>
37 T sgn(T val) {
38  return (T(0) < val) - (val < T(0));
39 }
40 
41 template <class grid_t> class GradientDescent {
42 
44  static constexpr size_t ndims_ = grid_t::getNDims();
45 
47  typedef typename std::array<unsigned int, ndims_> Coord;
48 
50  typedef typename std::array<double, ndims_> Point;
51 
53  typedef typename std::vector <Point> Path;
54 
55  public:
66  static void apply
67  (grid_t & grid, unsigned int & idx, Path & path, std::vector <double> & path_velocity, double step = 1) {
68 
69  Coord current_coord;
70  Point current_point;
71  Coord dimsize = grid.getDimSizes();
72 
73  std::array<unsigned int, ndims_-1> d_; // Same as nDGridMap class auxiliar array d_.
74  d_[0] = dimsize[0];
75  for (size_t i = 1; i < ndims_; ++i)
76  d_[i] = dimsize[i]*d_[i-1];
77 
78  grid.idx2coord(idx, current_coord);
79  std::copy_n( current_coord.begin(), ndims_, current_point.begin() ); // Cast to int.
80  path.push_back(current_point);
81  path_velocity.push_back(grid[idx].getVelocity());
82 
83  std::array<double, ndims_> grads;
84 
85  while(grid[idx].getArrivalTime() != 0) {
86  // Every iteration the gradient is computed for all dimensions. If is infinite, we convert it to 1 (keeping the sign).
87  // The static_cast are necessary because the conversion between coordinate (we check the value in coordinates) and points
88  // (the path is composed by continuous points).
89 
90  // First dimension done apart.
91  grads[0] = - grid[idx-1].getValue()/2 + grid[idx+1].getValue()/2;
92  if (isinf(grads[0]))
93  grads[0] = sgn<double>(grads[0]);
94  double max_grad = std::abs(grads[0]);
95 
96  for (size_t i = 1; i < ndims_; ++i) {
97  grads[i] = - grid[idx-d_[i-1]].getValue()/2 + grid[idx+d_[i-1]].getValue()/2;
98  if (isinf(grads[i]))
99  grads[i] = sgn<double>(grads[i]);
100  if (std::abs(max_grad) < std::abs(grads[i]))
101  max_grad = grads[i];
102  }
103 
104  // Updating points
105  for (size_t i = 0; i < ndims_; ++i) {
106  // Moving the point in dim i.
107  current_point[i] = current_point[i] - step*grads[i]/std::abs(max_grad);
108  current_coord[i] = int(current_point[i]+0.5);
109  }
110  path.push_back(current_point);
111  path_velocity.push_back(grid[idx].getVelocity());
112  grid.coord2idx(current_coord,idx);
113  }
114  //Adding exactly the last point at the end.
115  grid.idx2coord(idx, current_coord);
116  std::copy_n( current_coord.begin(), ndims_, current_point.begin() ); // Cast to double.
117  path.push_back(current_point);
118  path_velocity.push_back(grid[idx].getVelocity());
119  }
120 };
121 
122 #endif /* GRADIENTDESCENT_H_*/
std::vector< Point > Path
Shorthand for path type of real points.
Implements gradient descent to be used together with nDGridMap and FMCell or derived types...
std::array< double, ndims_ > Point
Shorhand for real points.
std::array< unsigned int, ndims_ > Coord
Shorthand for coordinates.
static void apply(grid_t &grid, unsigned int &idx, Path &path, std::vector< double > &path_velocity, double step=1)
Computes the path over grid from idx to a minimum and extracts the velocity in every point...
static constexpr size_t ndims_
Shorthand for number of dimensions.