EasyLocalpp  3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tester.hh
Go to the documentation of this file.
1 #if !defined(_TESTER_HH_)
2 #define _TESTER_HH_
3 
4 #include <stdexcept>
5 #include <fstream>
6 #include <chrono>
7 #include <future>
8 #include <iomanip>
9 
14 #include "easylocal/utils/types.hh"
15 
16 namespace EasyLocal {
17 
18  namespace Debug {
19 
20  using namespace EasyLocal::Core;
21 
22  template <class Input, class State, typename CFtype>
24  {
25  protected:
27  int ReadChoice(std::istream& is);
28  };
29 
30  template <class Input, class State, typename CFtype>
32  {
33  std::string c;
34  std::cin >> c;
35  try
36  {
37 #ifdef HAVE_STD_STOI
38  return std::stoi(c);
39 #else
40  int value;
41  std::istringstream iss(c);
42  iss >> value;
43  if (is.fail())
44  throw std::invalid_argument("Not an integer value");
45  return value;
46 #endif
47  }
48  catch (std::invalid_argument)
49  {
50  return -1;
51  }
52  }
53 
54 
55  template <class Input, class State, typename CFtype>
56  class AbstractTester
57  {
58  public:
59  virtual ~AbstractTester() {};
60  protected:
63  {
65  AddSearchEngine(*p_r);
66  }
67  };
68 
74  template <class Input, class Output, class State, typename CFtype = int>
75  class Tester : public AbstractTester<Input, State, CFtype>, public ChoiceReader<Input, State, CFtype>
76  {
77  public:
78  Tester(const Input& in, StateManager<Input, State, CFtype>& e_sm,
79  Core::OutputManager<Input, Output, State, CFtype>& e_om, std::ostream& o = std::cout);
80  Tester(const Input& in, State st, StateManager<Input, State, CFtype>& e_sm,
81  Core::OutputManager<Input, Output, State, CFtype>& e_om, std::ostream& o = std::cout);
83  virtual ~Tester() {}
84  void RunMainMenu(std::string file_name = "");
85  void AddMoveTester(ComponentTester<Input, Output, State, CFtype>& amt);
86  void AddKickerTester(ComponentTester<Input, Output, State, CFtype>& kt);
87  void RunInputMenu();
88  void RunStateTestMenu();
89  void SetState(const State& st){test_state = st;}
90  protected:
91  void AddSearchEngine(Core::SearchEngine<Input, State, CFtype>& r);
92  void ShowStateMenu();
93  void ShowReducedStateMenu();
94  bool ExecuteStateChoice();
95  void ShowMainMenu();
96  void ShowMovesMenu();
97  void ShowKickersMenu();
98  void ShowRunMenu();
99  void ShowSolverMenu();
100  void ShowDebuggingMenu();
101  void ExecuteMainChoice();
102  void ExecuteMovesChoice();
103  void ExecuteKickersChoice();
104  void ExecuteRunChoice();
105  void ExecuteSolverChoice();
106  void ExecuteDebuggingMenu();
107  std::vector<ComponentTester<Input, Output, State, CFtype>* > move_testers;
108  std::vector<ComponentTester<Input, Output, State, CFtype>* > kicker_testers;
110  std::vector<Core::SearchEngine<Input, State, CFtype>* > searchengines;
112  const Input& in;
113  std::ostream& os;
116  State test_state;
117  Output out;
118  int choice,
119  sub_choice;
120  };
121 
122  /*************************************************************************
123  * Implementation
124  *************************************************************************/
125 
134  template <class Input, class Output, class State, typename CFtype>
138  : in(i), os(o), sm(e_sm), om(e_om),
139  test_state(i), out(i)
140  { this->AddSearchEngines(); }
141 
142 
148  template <class Input, class Output, class State, typename CFtype>
150  { move_testers.push_back(&amt); }
151 
157  template <class Input, class Output, class State, typename CFtype>
159  { kicker_testers.push_back(&kt); }
160 
166  template <class Input, class Output, class State, typename CFtype>
168  {
169  searchengines.push_back(&r);
170  }
171 
176  template <class Input, class Output, class State, typename CFtype>
178  {
179  if (file_name == "")
180  {
181  RunInputMenu();
182  }
183  else if (file_name == "random")
184  {
185  this->sm.RandomState(test_state);
186  }
187  else
188  {
189  std::ifstream is(file_name.c_str());
190  if (is.fail())
191  throw std::runtime_error("Cannot open file!");
192  om.ReadState(test_state, is);
193  om.OutputState(test_state, out);
194  os << "SOLUTION IMPORTED " << std::endl << out << std::endl;
195  os << "IMPORTED SOLUTION COST : " << sm.CostFunctionComponents(test_state) << std::endl;
196  }
197 
198  do
199  {
200  ShowMainMenu();
201  if (this->choice != 0)
202  ExecuteMainChoice();
203  }
204  while (this->choice != 0);
205  os << "Bye bye..." << std::endl;
206  }
207 
211  template <class Input, class Output, class State, typename CFtype>
213  {
214  os << "MAIN MENU:" << std::endl
215  << " (1) Move menu" << std::endl
216  << " (2) Kicker menu" << std::endl
217  << " (3) Run menu" << std::endl
218  << " (4) State menu" << std::endl
219  << " (0) Exit" << std::endl
220  << " Your choice: ";
221  this->choice = this->ReadChoice(std::cin);
222  }
223 
227  template <class Input, class Output, class State, typename CFtype>
229  {
230  switch(this->choice)
231  {
232  case 1:
233  ShowMovesMenu();
234  ExecuteMovesChoice();
235  break;
236  case 2:
237  ShowKickersMenu();
238  ExecuteKickersChoice();
239  break;
240  case 3:
241  ShowRunMenu();
242  ExecuteRunChoice();
243  break;
244  case 4:
245  RunStateTestMenu();
246  break;
247  case 0:
248  break;
249  default:
250  os << "Invalid choice" << std::endl;
251  }
252  }
253 
257  template <class Input, class Output, class State, typename CFtype>
259  {
260  unsigned int i;
261  os << "MOVE MENU: " << std::endl;
262  for (i = 0; i < move_testers.size(); i++)
263  os << " (" << i+1 << ") " << move_testers[i]->name << " [" << move_testers[i]->Modality() << "-modal]" << std::endl;
264  os << " (0) Return to Main Menu" << std::endl;
265  os << " Your choice: ";
266  this->sub_choice = this->ReadChoice(std::cin);
267  }
268 
269 
270  template <class Input, class Output, class State, typename CFtype>
272  {
273  os << "SOLVER MENU: " << std::endl;
274  os << " (1) Simple solver" << std::endl;
275  os << " (2) Token ring solver" << std::endl;
276  os << " (0) Return to Main Menu" << std::endl;
277  os << " Your choice: ";
278  this->sub_choice = this->ReadChoice(std::cin);
279  }
280 
284  template <class Input, class Output, class State, typename CFtype>
286  {
287  unsigned int i;
288  os << "KICK MENU: " << std::endl;
289  for (i = 0; i < kicker_testers.size(); i++)
290  os << " (" << i+1 << ") " << kicker_testers[i]->name << std::endl;
291  os << " (0) Return to Main Menu" << std::endl;
292  os << " Your choice: ";
293  this->sub_choice = this->ReadChoice(std::cin);
294  }
295 
299  template <class Input, class Output, class State, typename CFtype>
301  {
302  unsigned int i;
303  do
304  {
305  os << "RUN MENU: " << std::endl;
306  for (i = 0; i < searchengines.size(); i++)
307  os << " (" << (i + 1) << ") " << searchengines[i]->name << std::endl;
308  os << " (0) Return to Main Menu" << std::endl;
309  os << " Your choice: ";
310  this->sub_choice = this->ReadChoice(std::cin);
311  if (sub_choice == -1 || sub_choice >= static_cast<int>(searchengines.size()))
312  os << "Invalid choice" << std::endl;
313  }
314  while (sub_choice == -1 || sub_choice > static_cast<int>(searchengines.size()));
315  }
316 
320  template <class Input, class Output, class State, typename CFtype>
322  {
323  if (sub_choice > 0 && sub_choice <= static_cast<int>(move_testers.size()))
324  move_testers[sub_choice-1]->RunMainMenu(test_state);
325  }
326 
330  template <class Input, class Output, class State, typename CFtype>
332  {
333  if (sub_choice > 0)
334  kicker_testers[sub_choice-1]->RunMainMenu(test_state);
335  }
336 
340  template <class Input, class Output, class State, typename CFtype>
342  {
343  if (sub_choice > 0)
344  {
345  SearchEngine<Input, State, CFtype>& r = *searchengines[sub_choice-1];
346  r.ReadParameters();
347 
348  // Ask for timeout
349  double timeout;
350  os << " Timeout: ";
351  std::cin >> timeout;
352  os << std::endl;
353  auto to = std::chrono::milliseconds((long long)(timeout * 1000));
354 
355  auto start = std::chrono::high_resolution_clock::now();
356  CostStructure<CFtype> result = r.SyncRun(to, this->test_state);
357  auto end = std::chrono::high_resolution_clock::now();
358 
359  auto duration = end - start;
360  om.OutputState(test_state, out);
361 
362  os << "CURRENT SOLUTION " << std::endl << out << std::endl;
363  os << "CURRENT COST : " << result << std::endl;
364  os << "ELAPSED TIME : " << std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() / 1000.0 << " s" << std::endl;
365  os << "NUMBER OF ITERATIONS : " << r.Iteration() << std::endl;
366  }
367  }
368 
372  template <class Input, class Output, class State, typename CFtype>
374  {
375  bool show_state;
376  ShowReducedStateMenu();
377  std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
378  show_state = ExecuteStateChoice();
379  std::chrono::milliseconds duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start);
380  if (show_state)
381  {
382  this->om.OutputState(test_state, this->out);
383  os << "INITIAL SOLUTION " << std::endl << this->out << std::endl;
384  os << "INITIAL COST : " << this->sm.CostFunctionComponents(test_state) << std::endl;
385  }
386  os << "ELAPSED TIME : " << duration.count() / 1000.0 << "s" << std::endl;
387  }
388 
392  template <class Input, class Output, class State, typename CFtype>
394  {
395  os << "STATE MENU: " << std::endl
396  << " (1) Random state " << std::endl
397  << " (2) Read from file" << std::endl
398  << " (3) Greedy state " << std::endl
399  << " (4) Sample state" << std::endl
400  << " (5) Write to file" << std::endl
401  << " (6) Show state" << std::endl
402  << " (7) Show input" << std::endl
403  << " (8) Show cost function components" << std::endl
404  << " (9) Show cost elements" << std::endl
405  << " (10) Check state consistency" << std::endl
406  << " (11) Pretty print output" << std::endl
407  << " (0) Return to Main Menu" << std::endl
408  << "Your choice : ";
409  this->sub_choice = this->ReadChoice(std::cin);
410  }
411 
415  template <class Input, class Output, class State, typename CFtype>
417  {
418  os << "INITIAL STATE MENU: " << std::endl
419  << " (1) Random state " << std::endl
420  << " (2) Read from file" << std::endl
421  << " (3) Greedy state " << std::endl
422  << "Your choice : ";
423  this->sub_choice = this->ReadChoice(std::cin);
424  if (sub_choice >= 4)
425  sub_choice = -1;
426  }
427 
433  template <class Input, class Output, class State, typename CFtype>
435  {
436  unsigned int i;
437  std::string file_name;
438  switch(sub_choice)
439  {
440  case 1:
441  this->sm.RandomState(test_state);
442  break;
443  case 2:
444  {
445  bool read_failed;
446  std::ifstream is;
447  do
448  {
449  read_failed = false;
450  os << "File name : ";
451  std::cin >> file_name;
452  is.open(file_name.c_str());
453  if (is.fail())
454  {
455  os << "File " << file_name << " does not exist!" << std::endl;
456  read_failed = true;
457  is.clear();
458  }
459  }
460  while (read_failed);
461  this->om.ReadState(test_state, is);
462  break;
463  }
464  case 3:
465  {
466  unsigned int lenght;
467  double randomness;
468  os << "Lenght of the restricted candidate list: ";
469  std::cin >> lenght;
470  os << "Level of randomness (0 <= alpha <= 1): ";
471  std::cin >> randomness;
472  this->sm.GreedyState(test_state, randomness, lenght);
473  break;
474  }
475  case 4:
476  {
477  unsigned int samples;
478  os << "How many samples : ";
479  std::cin >> samples;
480  this->sm.SampleState(test_state, samples);
481  break;
482  }
483  case 5:
484  {
485  os << "File name : ";
486  std::cin >> file_name;
487  std::ofstream os(file_name.c_str());
488  this->om.WriteState(test_state, os);
489  break;
490  }
491  case 6:
492  {
493  os << test_state << std::endl;
494  os << "Total cost: " << this->sm.CostFunctionComponents(test_state) << std::endl;
495  break;
496  }
497  case 7:
498  {
499  os << in;
500  break;
501  }
502  case 8:
503  {
504  os << "Cost Components: " << std::endl;
505  CostStructure<CFtype> cost = this->sm.CostFunctionComponents(test_state);
506  for (i = 0; i < CostComponent<Input, State, CFtype>::CostComponents(); i++)
507  {
509  os << i << ". " << cc.name << " : "
510  << cost.all_components[i] << (cc.IsHard() ? '*' : ' ') << std::endl;
511  }
512  os << "Total Violations: " << cost.violations << std::endl;
513  os << "Total Objective: " << cost.objective << std::endl;
514  os << "Total Cost: " << cost.total << std::endl;
515  break;
516  }
517  case 9:
518  {
519  os << "Detailed Violations: " << std::endl;
520  CostStructure<CFtype> cost = this->sm.CostFunctionComponents(test_state);
521  for (i = 0; i < CostComponent<Input, State, CFtype>::CostComponents(); i++)
522  {
524  cc.PrintViolations(test_state);
525  }
526  os << std::endl << "Summary of Cost Components: " << std::endl;
527  for (i = 0; i < CostComponent<Input, State, CFtype>::CostComponents(); i++)
528  {
530  os << i << ". " << cc.name << " : "
531  << cost.all_components[i] << (cc.IsHard() ? '*' : ' ') << std::endl;
532  }
533  os << "Total Violations: " << cost.violations << std::endl;
534  os << "Total Objective: " << cost.objective << std::endl;
535  os << "Total Cost: " << cost.total << std::endl;
536  break;
537  }
538  case 10:
539  {
540  os << "Checking state consistency: " << std::endl;
541  bool consistent = this->sm.CheckConsistency(test_state);
542  if (consistent)
543  os << "The state is consistent" << std::endl;
544  else
545  os << "The state is not consistent" << std::endl;
546  break;
547  }
548  case 11:
549  {
550  os << "File name : ";
551  std::cin >> file_name;
552  this->om.PrettyPrintOutput(test_state, file_name);
553  std::cout << "Output pretty-printed in file " << file_name << std::endl;
554  break;
555  }
556  default:
557  os << "Invalid choice" << std::endl;
558  }
559  return (sub_choice >= 1 && sub_choice <= 4);
560  }
561 
566  template <class Input, class Output, class State, typename CFtype>
568  {
569  bool show_state;
570  do
571  {
572  ShowStateMenu();
573  if (sub_choice != 0)
574  {
575  std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
576  show_state = ExecuteStateChoice();
577  std::chrono::milliseconds duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start);
578  if (show_state)
579  {
580  om.OutputState(test_state, out);
581  os << "CURRENT SOLUTION " << std::endl << out << std::endl;
582  os << "CURRENT COST : " << sm.CostFunctionComponents(test_state) << std::endl;
583  }
584  os << "ELAPSED TIME : " << duration.count() / 1000.0 << "s" << std::endl;
585  }
586  }
587  while (sub_choice != 0);
588  os << "Leaving state menu" << std::endl;
589  }
590 
591  }
592 }
593 
594 #endif // _TESTER_HH_
Tester(const Input &in, StateManager< Input, State, CFtype > &e_sm, Core::OutputManager< Input, Output, State, CFtype > &e_om, std::ostream &o=std::cout)
Definition: tester.hh:135
void AddKickerTester(ComponentTester< Input, Output, State, CFtype > &kt)
Definition: tester.hh:158
CostStructure< CFtype > SyncRun(std::chrono::milliseconds timeout, Args...args)
void AddMoveTester(ComponentTester< Input, Output, State, CFtype > &amt)
Definition: tester.hh:149
std::vector< CFtype > all_components
Definition: statemanager.hh:25
virtual void ReadParameters(std::istream &is=std::cin, std::ostream &os=std::cout)
void RunMainMenu(std::string file_name="")
Definition: tester.hh:177
Core::OutputManager< Input, Output, State, CFtype > & om
Definition: tester.hh:115
void AddSearchEngine(Core::SearchEngine< Input, State, CFtype > &r)
Definition: tester.hh:167
std::ostream & os
Definition: tester.hh:113
std::vector< ComponentTester< Input, Output, State, CFtype > * > kicker_testers
Definition: tester.hh:108
int ReadChoice(std::istream &is)
Definition: tester.hh:31
unsigned long int Iteration() const
Definition: searchengine.hh:81
void SetState(const State &st)
Definition: tester.hh:89
Core::StateManager< Input, State, CFtype > & sm
Definition: tester.hh:114
The class CostComponent manages one single component of the cost, either hard or soft.
const Input & in
Definition: tester.hh:112
std::vector< Core::SearchEngine< Input, State, CFtype > * > searchengines
Definition: tester.hh:110
std::vector< ComponentTester< Input, Output, State, CFtype > * > move_testers
Definition: tester.hh:107
virtual void AddSearchEngine(Core::SearchEngine< Input, State, CFtype > &r)
Definition: tester.hh:61
This component is responsible for all operations on the state which are independent of the neighborho...
static const CostComponent< Input, State, CFtype > & Component(size_t i)
virtual void PrintViolations(const State &st, std::ostream &os=std::cout) const =0