n-Dimensional Fast Methods  0.7
 All Classes Functions Variables Typedefs Pages
benchmarkcfg.hpp
1 
17 #ifndef BENCHMARKCFG_HPP_
18 #define BENCHMARKCFG_HPP_
19 
20 #include <string>
21 #include <unordered_map>
22 #include <algorithm>
23 
24 #include <boost/program_options.hpp>
25 #include <boost/algorithm/string/case_conv.hpp>
26 
27 #include <fast_methods/benchmark/benchmark.hpp>
28 #include <fast_methods/io/maploader.hpp>
29 
30 #include <fast_methods/fm/fmm.hpp>
31 #include <fast_methods/fm/sfmm.hpp>
32 #include <fast_methods/fm/fmmstar.hpp>
33 #include <fast_methods/fm/sfmmstar.hpp>
34 #include <fast_methods/fm/fim.hpp>
35 #include <fast_methods/fm/gmm.hpp>
36 #include <fast_methods/fm/ufmm.hpp>
37 #include <fast_methods/fm/fsm.hpp>
38 #include <fast_methods/fm/lsm.hpp>
39 #include <fast_methods/fm/ddqm.hpp>
40 
44 
45 class BenchmarkCFG {
46 
47  public:
48 
51  () {}
52 
55  (const char * filename) {
56  readOptions(filename);
57  }
58 
60  bool readOptions(const char * filename)
61  {
62  static const std::vector<std::string> knownSolvers = {
63  "fmm", "fmmstar", "fmmfib", "fmmfibstar", "sfmm", "sfmmstar",
64  "gmm", "fim", "ufmm", "fsm", "lsm", "ddqm" // Add solver here.
65  };
66 
67  std::fstream cfg(filename);
68  if (!cfg.good())
69  {
70  std::string error("Unable to open file: ");
71  error += filename;
72  console::error(error);
73  return 0;
74  }
75 
76  path_ = boost::filesystem::absolute( boost::filesystem::path(filename) );
77  boost::filesystem::path name = path_.filename();
78  name.replace_extension("");
79 
80  boost::program_options::options_description desc;
81  desc.add_options()
82  ("grid.file", boost::program_options::value<std::string>(), "Path to load a velocities map from image.")
83  ("grid.text", boost::program_options::value<std::string>(), "Path to load a velocities map from a .grid file.")
84  ("grid.ndims", boost::program_options::value<std::string>()->default_value("2"), "Number of dimensions.")
85  ("grid.cell", boost::program_options::value<std::string>()->default_value("FMCell"), "Type of cell. FMCell by default.")
86  ("grid.dimsize", boost::program_options::value<std::string>()->default_value("200,200"), "Size of dimensions: N,M,O...")
87  ("grid.leafsize", boost::program_options::value<std::string>()->default_value("1"), "Leafsize (assuming cubic cells).")
88  ("problem.start", boost::program_options::value<std::string>()->required(), "Start point: s1,s2,s3...")
89  ("problem.goal", boost::program_options::value<std::string>()->default_value("nan"), "Goal point: g1,g2,g3... By default no goal point.")
90  ("benchmark.name", boost::program_options::value<std::string>()->default_value(name.string()), "Name of the benchmark.")
91  ("benchmark.runs", boost::program_options::value<std::string>()->default_value("10"), "Number of runs per solver.")
92  ("benchmark.savegrid", boost::program_options::value<std::string>()->default_value("0"), "Save grid values of each run.");
93 
94  boost::program_options::variables_map vm;
95  boost::program_options::parsed_options po = boost::program_options::parse_config_file(cfg, desc, true);
96  boost::program_options::store(po, vm);
97  boost::program_options::notify(vm);
98  cfg.close();
99 
100  // Storing registered options, intended for grid, problem and benchmark configuration.
101  for (const auto& var : vm)
102  options_[var.first] = boost::any_cast<std::string>(var.second.value());
103 
104  // Analyze unregistered options, intended for solvers.
105  std::vector<std::string> unr = boost::program_options::collect_unrecognized(po.options, boost::program_options::exclude_positional);
106  for (std::size_t i = 0 ; i < unr.size()/2 ; ++i)
107  {
108  std::string key = boost::to_lower_copy(unr[i*2]);
109  std::string val = unr[i*2 + 1];
110 
111  if (key.substr(0,8) == "solvers.")
112  {
113  std::string solver = key.substr(8);
114  // If it is a known solver, save it together with its constructor
115  // parameters (if given).
116  for (std::size_t i = 0; i < knownSolvers.size(); ++i)
117  if (solver == knownSolvers[i]) {
118  solverNames_.push_back(knownSolvers[i]);
119  ctorParams_.push_back(val);
120  }
121  }
122  }
123 
124  return 1;
125  }
126 
127  template <class grid_t, class cell_t>
128  void configure
129  (Benchmark<grid_t> & b) {
130  b.setSaveLog(true);
131  b.setName(getValue<std::string>("benchmark.name"));
132  b.setSaveGrid(getValue<unsigned int>("benchmark.savegrid"));
133  b.setNRuns(getValue<unsigned int>("benchmark.runs"));
134  b.setPath(boost::filesystem::path("results"));
135  b.fromCFG(true);
136 
137  for (size_t i = 0; i < solverNames_.size(); ++i)
138  {
139  const std::string & name = solverNames_[i];
140 
141  bool defaultCtor = true;
142  if (!ctorParams_[i].empty())
143  defaultCtor = false;
144 
145  Solver<grid_t> * solver;
146 
147  if (defaultCtor) {
148  if (name == "fmm")
149  solver = new FMM<grid_t>();
150  else if (name == "fmmstar")
151  solver = new FMMStar<grid_t>();
152  else if (name == "fmmfib")
153  solver = new FMM<grid_t, FMFibHeap<cell_t> >("FMMFib");
154  else if (name == "fmmfibstar")
155  solver = new FMMStar<grid_t, FMFibHeap<cell_t> >("FMMFib*");
156  else if (name == "sfmm")
157  solver = new SFMM<grid_t>("SFMM");
158  else if (name == "sfmmstar")
159  solver = new SFMMStar<grid_t>("SFMM*");
160  else if (name == "gmm")
161  solver = new GMM<grid_t>();
162  else if (name == "fim")
163  solver = new FIM<grid_t>();
164  else if (name == "ufmm")
165  solver = new UFMM<grid_t>();
166  else if (name == "fsm")
167  solver = new FSM<grid_t>();
168  else if (name == "lsm")
169  solver = new LSM<grid_t>();
170  else if (name == "ddqm")
171  solver = new DDQM<grid_t>();
172  // Add solver here.
173 
174  else
175  continue;
176  }
177  else { // Create solvers with specified constructor parameters.
178  std::vector<std::string> p(split(ctorParams_[i]));
179 
180  // FMM and FMM*
181  if (name == "fmm")
182  solver = new FMM<grid_t>(ctorParams_[i].c_str());
183  else if (name == "fmmstar") {
184  if (p.size() == 1)
185  solver = new FMMStar<grid_t>(p[0].c_str());
186  else if (p.size() == 2) {
187  if (p[1] == "TIME")
188  solver = new FMMStar<grid_t>(p[0].c_str(), TIME);
189  else if (p[1] == "DISTANCE")
190  solver = new FMMStar<grid_t>(p[0].c_str(), DISTANCE);
191  }
192  }
193  // FMMFib and FMMFib*
194  else if (name == "fmmfib")
195  solver = new FMM<grid_t, FMFibHeap<cell_t> >(ctorParams_[i].c_str());
196  else if (name == "fmmfibstar") {
197  if (p.size() == 1)
198  solver = new FMMStar<grid_t, FMFibHeap<cell_t>>(p[0].c_str());
199  else if (p.size() == 2) {
200  if (p[1] == "TIME")
201  solver = new FMMStar<grid_t, FMFibHeap<cell_t>>(p[0].c_str(), TIME);
202  else if (p[1] == "DISTANCE")
203  solver = new FMMStar<grid_t, FMFibHeap<cell_t>>(p[0].c_str(), DISTANCE);
204  }
205  }
206  // SFMM and SFMM*
207  else if (name == "sfmm")
208  solver = new SFMM<grid_t, cell_t>(ctorParams_[i].c_str());
209  else if (name == "sfmmstar") {
210  if (p.size() == 1)
211  solver = new SFMMStar<grid_t, cell_t>(p[0].c_str());
212  else if (p.size() == 2) {
213  if (p[1] == "TIME")
214  solver = new SFMMStar<grid_t, cell_t>(p[0].c_str(), TIME);
215  else if (p[1] == "DISTANCE")
216  solver = new SFMMStar<grid_t, cell_t>(p[0].c_str(), DISTANCE);
217  }
218  }
219  // GMM
220  else if (name == "gmm") {
221  if (p.size() == 1)
222  solver = new GMM<grid_t>(p[0].c_str());
223  else if (p.size() == 2)
224  solver = new GMM<grid_t>(p[0].c_str(), boost::lexical_cast<double>(p[1]));
225  }
226  // FIM
227  else if (name == "fim") {
228  if (p.size() == 1)
229  solver = new FIM<grid_t>(p[0].c_str());
230  else if (p.size() == 2)
231  solver = new FIM<grid_t>(p[0].c_str(), boost::lexical_cast<double>(p[1]));
232  }
233  // UFMM
234  else if (name == "ufmm") {
235  if (p.size() == 1)
236  solver = new UFMM<grid_t>(p[0].c_str());
237  else if (p.size() == 2)
238  solver = new UFMM<grid_t>(p[0].c_str(), boost::lexical_cast<unsigned>(p[1]));
239  else if (p.size() == 3)
240  solver = new UFMM<grid_t>(p[0].c_str(), boost::lexical_cast<unsigned>(p[1]), boost::lexical_cast<double>(p[2]));
241  }
242  // FSM
243  else if (name == "fsm") {
244  if (p.size() == 1)
245  solver = new FSM<grid_t>(p[0].c_str());
246  else if (p.size() == 2)
247  solver = new FSM<grid_t>(p[0].c_str(), boost::lexical_cast<unsigned>(p[1]));
248  }
249  // LSM
250  else if (name == "lsm") {
251  if (p.size() == 1)
252  solver = new LSM<grid_t>(p[0].c_str());
253  else if (p.size() == 2)
254  solver = new LSM<grid_t>(p[0].c_str(), boost::lexical_cast<unsigned>(p[1]));
255  }
256  // DDQM
257  else if (name == "ddqm") {
258  solver = new LSM<grid_t>(p[0].c_str());
259  }
260  // Add solver here.
261 
262  else
263  continue;
264  }
265 
266  b.addSolver(solver);
267  }
268 
269  constexpr size_t N = grid_t::getNDims();
270  grid_t * grid = new grid_t();
271  if (options_.find("grid.file") != options_.end())
272  MapLoader::loadMapFromImg(options_.find("grid.file")->second.c_str(), *grid);
273  else if (options_.find("grid.text") != options_.end()) {
274  if(!MapLoader::loadMapFromText(options_.find("grid.text")->second.c_str(), *grid))
275  exit(1);
276  }
277  else {
278  const std::string & strToSplit = options_.find("grid.dimsize")->second;
279  std::array<unsigned int, N> dimSize = splitAndCast<unsigned int, N>(strToSplit);
280  grid->resize(dimSize);
281  }
282 
283  grid->setLeafSize(getValue<double>("grid.leafsize"));
284 
285  const std::string & strToSplit2 = options_.find("problem.start")->second;
286  std::array<unsigned int, N> startCoords = splitAndCast<unsigned int, N>(strToSplit2);
287  unsigned int startIdx;
288  std::vector<unsigned int> startIndices;
289  grid->coord2idx(startCoords, startIdx);
290  startIndices.push_back(startIdx);
291 
292  const std::string & strToSplit3 = options_.find("problem.goal")->second;
293  if (strToSplit3 != "nan")
294  {
295  unsigned int goalIdx;
296  std::array<unsigned int, N> goalCoords = splitAndCast<unsigned int, N>(strToSplit3);
297  grid->coord2idx(goalCoords, goalIdx);
298  b.setInitialAndGoalPoints(startIndices, goalIdx);
299  }
300  else
301  b.setInitialPoints(startIndices);
302 
303  b.setEnvironment(grid);
304  }
305 
307  template<typename T>
308  T getValue
309  (const std::string & key) const {
310  std::unordered_map<std::string, std::string>::const_iterator iter = options_.find(key);
311  if (iter != options_.end())
312  return boost::lexical_cast<T>(iter->second);
313  else
314  return boost::lexical_cast<T>(0);
315  }
316 
317  private:
318  // Based on http://stackoverflow.com/a/236803/2283531
320  template <typename T, size_t N>
321  std::array<T,N> splitAndCast
322  (const std::string & s)
323  {
324  std::array<T,N> elems;
325  std::stringstream ss(s);
326  std::string item;
327  for (size_t i = 0; i < N; ++i)
328  {
329  std::getline(ss, item, ',');
330  elems[i] = boost::lexical_cast<T>(item);
331  }
332  return elems;
333  }
334 
336  std::vector<std::string> split
337  (const std::string & s) {
338  std::vector<std::string> elems;
339  std::stringstream ss(s);
340  std::string item;
341  size_t pos = 1, str_size = s.length()-1;
342  while (pos < str_size) {
343  std::getline(ss, item, ',');
344  elems.push_back(item);
345  pos += item.length();
346  }
347  return elems;
348  }
349 
351  std::vector<std::string> solverNames_;
352 
354  std::vector<std::string> ctorParams_;
355 
357  std::unordered_map<std::string, std::string> options_;
358 
360  boost::filesystem::path path_;
361 };
362 
363 #endif /* BENCHMARKCFG_HPP_*/
Implements Fast Sweeping Method.
Definition: fsm.hpp:41
void setPath(const boost::filesystem::path &path)
Set the path where results will be saved.
Definition: benchmark.hpp:84
Fast Marching Method using a untidy priority queue (UFMM).
Definition: ufmm.hpp:37
Configures a Benchmark class from a CFG file. Inspired in the OMPLapp benchmarking software: http://o...
std::unordered_map< std::string, std::string > options_
Option-value map.
std::vector< std::string > split(const std::string &s)
From a string of format XXX,YY,ZZZ,... splis the elements (comma-separated) as a vector of strings...
Encapsulates the calls to FMM with heuristics enabled.
Definition: fmmstar.hpp:61
This class provides the utilities to benchmark Fast Marching Solvers (configuration, running and logging). It works for FMM (any heap and SFMM), FIM and UFMM. It has not been tested with FM2 solvers.
Definition: benchmark.hpp:33
Implements the Simplified Fast Marching Method, encapsulating FMM with a priority queue...
Definition: sfmm.hpp:44
void setEnvironment(grid_t *grid)
Sets the environment (grid map) the benchmark will be run on.
Definition: benchmark.hpp:72
static void error(const std::string &val)
bool readOptions(const char *filename)
Parses the CFG file given.
void addSolver(Solver< grid_t > *solver)
Adds a new solver to be benchmarked.
Definition: benchmark.hpp:60
boost::filesystem::path path_
Stores the absolute path to the CFG file.
void setInitialPoints(const std::vector< unsigned int > &init_points)
Sets the initial points (indices for the solvers).
Definition: benchmark.hpp:102
T getValue(const std::string &key) const
Get the value for a given key (option).
std::vector< std::string > solverNames_
Stores the names of the parsed solvers.
Implements Double Dynamic Queue Method.
Definition: ddqm.hpp:41
std::array< T, N > splitAndCast(const std::string &s)
From a string of format XXX,YY,ZZZ,... splis the N elements and cast as type T (comma-separated) as a...
static int loadMapFromText(const char *filename, nDGridMap< T, ndims > &grid)
Loads the initial binary map for a given grid. It is based on the nDGridMap::setOccupancy() which has...
Definition: maploader.hpp:96
void setSaveGrid(unsigned int s)
Sets the saveGrid_ flag.
Definition: benchmark.hpp:66
Abstract class that serves as interface for the actual solvers implemented. It requires (at least) th...
Definition: solver.hpp:40
static void loadMapFromImg(const char *filename, nDGridMap< T, ndims > &grid)
Loads the initial binary map for a given grid. It is based on the nDGridMap::setOccupancy() which has...
Definition: maploader.hpp:51
Implements Lock Sweeping Method.
Definition: lsm.hpp:40
BenchmarkCFG()
Requires readOptions to be manually called after this constructor.
Implements Fast Iterative Method.
Definition: fim.hpp:36
void setNRuns(unsigned int n)
Set number of runs for each solver.
Definition: benchmark.hpp:78
void fromCFG(bool cfg)
Set true if the benchmark is configured from a cfg file.
Definition: benchmark.hpp:54
Templated class which computes Group Marching Method (GMM).
Definition: gmm.hpp:33
Implements the Fast Marching Method (FMM).
Definition: fmm.hpp:64
void setInitialAndGoalPoints(const std::vector< unsigned int > &init_points, unsigned int goal_idx)
Sets the initial and goal points (indices) for the solvers.
Definition: benchmark.hpp:96
void setSaveLog(bool s)
Sets the flag to save the log to a file (true) or output in terminal (false).
Definition: benchmark.hpp:90
std::vector< std::string > ctorParams_
Stores the constructor parameters for the parsed solvers.
void setName(const std::string &n)
Sets the name of the benchmark.
Definition: benchmark.hpp:189