1 #if !defined(_MOVE_TESTER_HH_)
2 #define _MOVE_TESTER_HH_
22 template <
class Input,
class Output,
class State,
class Move,
typename CFtype =
int>
33 std::ostream& o = std::cout);
60 template <
class Input,
class Output,
class State,
class Move,
typename CFtype>
68 :
ComponentTester<Input, Output, State, CFtype>(name), in(i), out(i), sm(sm), om(om), ne(ne), os(o), tolerance(std::numeric_limits<CFtype>::epsilon())
74 template <
class Input,
class Output,
class State,
class Move,
typename CFtype>
83 std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
84 show_state = ExecuteChoice(st);
85 std::chrono::milliseconds duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start);
88 om.OutputState(st, out);
89 os <<
"CURRENT SOLUTION " << std::endl << out << std::endl;
90 os <<
"CURRENT COST : " << sm.CostFunctionComponents(st) << std::endl;
92 os <<
"ELAPSED TIME : " << duration.count() / 1000.0 <<
's' << std::endl;
96 os <<
"Leaving " << this->name <<
" menu" << std::endl;
102 template <
class Input,
class Output,
class State,
class Move,
typename CFtype>
105 os <<
"Move Menu: " << std::endl
106 <<
" (1) Perform Best Move" << std::endl
107 <<
" (2) Perform First Improving Move" << std::endl
108 <<
" (3) Perform Random Move" << std::endl
109 <<
" (4) Perform Input Move" << std::endl
110 <<
" (5) Print All Neighbors" << std::endl
111 <<
" (6) Print Neighborhood Statistics" << std::endl
112 <<
" (7) Print Random Move Cost" << std::endl
113 <<
" (8) Print Input Move Cost" << std::endl
114 <<
" (9) Check Neighborhood Costs" << std::endl
115 <<
" (10) Check Move Independence" << std::endl
116 <<
" (11) Check Random Move Distribution" << std::endl;
117 os <<
" (0) Return to Main Menu" << std::endl
119 choice = this->ReadChoice(std::cin);
127 template <
class Input,
class Output,
class State,
class Move,
typename CFtype>
143 em = ne.RandomFirst(st, 1, explored, [](
const Move& mv,
CostStructure<CFtype> cost) {
return true; });
146 os <<
"Input move : ";
150 PrintAllNeighbors(st);
153 PrintNeighborhoodStatistics(st);
156 em = ne.RandomFirst(st, 1, explored, [](
const Move& mv,
CostStructure<CFtype> cost) {
return true; });
157 PrintMoveCosts(st, em);
160 os <<
"Input move : ";
162 em.
cost = ne.DeltaCostFunctionComponents(st, em.
move);
163 PrintMoveCosts(st, em);
166 CheckNeighborhoodCosts(st);
169 CheckMoveIndependence(st);
172 CheckRandomMoveDistribution(st);
175 os <<
"Invalid choice" << std::endl;
177 if (choice == 1 || choice == 2 || choice == 3 || choice == 4)
179 os <<
"Move : " << em.
move << std::endl;
180 if (!ne.FeasibleMove(st, em.
move))
181 os <<
"Move not feasible" << std::endl;
183 ne.MakeMove(st, em.
move);
189 os <<
"Empty neighborhood" << std::endl;
195 template <
class Input,
class Output,
class State,
class Move,
typename CFtype>
199 os <<
"Move : " << em.
move << std::endl;
202 for (
size_t i = 0; i < CostComponent<Input, State, CFtype>::CostComponents(); i++)
205 os <<
" " << i <<
". " << cc.name <<
" : " << em.
cost;
213 os <<
"Total Delta Violations : " << em.
cost.violations << std::endl;
214 os <<
"Total Delta Objective : " << em.
cost.objective << std::endl;
215 os <<
"Total Delta Cost : " << em.
cost.total << std::endl;
218 template <
class Input,
class Output,
class State,
class Move,
typename CFtype>
222 unsigned int move_count = 0;
226 bool error_found =
false, not_last_move =
true;
227 ne.FirstMove(st, em.
move);
232 ne.MakeMove(st1, em.
move);
233 em.
cost = ne.DeltaCostFunctionComponents(st, em.
move);
234 st1_cost = this->sm.CostFunctionComponents(st1);
235 error = st1_cost - em.
cost - st_cost;
236 for (
size_t i = 0; i < CostComponent<Input, State, CFtype>::CostComponents(); i++)
242 << st1_cost.all_components[i] <<
" (error = " << std::showpos << error.
all_components[i] <<
")" << std::noshowpos << std::endl;
243 os <<
"Press enter to continue " << std::endl;
248 if (move_count % 100 == 0)
250 not_last_move = ne.NextMove(st, em.
move);
254 while (not_last_move);
257 os << std::endl <<
"No error found (for " << move_count <<
" moves)!" << std::endl;
267 template <
class Input,
class Output,
class State,
class Move,
typename CFtype>
270 unsigned int neighbors = 0, improving_neighbors = 0,
271 worsening_neighbors = 0, non_improving_neighbors = 0;
273 double total_positive_cost = 0.0;
278 ne.FirstMove(st, em.
move);
283 em.
cost = ne.DeltaCostFunctionComponents(st, em.
move);
285 if (em.
cost.total < 0)
286 improving_neighbors++;
287 else if (em.
cost.total > 0)
289 worsening_neighbors++;
290 total_positive_cost += em.
cost.total;
293 non_improving_neighbors++;
294 for (
size_t i = 0; i < CostComponent<Input, State, CFtype>::CostComponents(); i++)
296 if (em.
cost.all_components[i] < min_max_costs[i].first)
297 min_max_costs[i].first = em.
cost.all_components[i];
298 else if (em.
cost.all_components[i] > min_max_costs[i].second)
299 min_max_costs[i].second = em.
cost.all_components[i];
302 while (ne.NextMove(st, em.
move));
304 os <<
"Neighborhood size: " << neighbors << std::endl
305 <<
" improving moves: " << improving_neighbors <<
" ("
306 << (100.0 * improving_neighbors) / neighbors <<
"%)" << std::endl
307 <<
" worsening moves: " << worsening_neighbors <<
" ("
308 << (100.0 * worsening_neighbors) / neighbors <<
"%), average cost: " << total_positive_cost / neighbors << std::endl
309 <<
" sideways moves: " << non_improving_neighbors <<
" ("
310 << (100.0 * non_improving_neighbors) /neighbors <<
"%)" << std::endl;
312 os <<
"Min and max component costs:" << std::endl;
313 for (
size_t i = 0; i < CostComponent<Input, State, CFtype>::CostComponents(); i++)
317 template <
class Input,
class Output,
class State,
class Move,
typename CFtype>
321 ne.FirstMove(st, mv);
324 os << mv <<
" " << ne.DeltaCostFunctionComponents(st, mv) << std::endl;
326 while (ne.NextMove(st, mv));
329 template <
class Input,
class Output,
class State,
class Move,
typename CFtype>
333 std::map<Move, unsigned int> frequency;
334 typename std::map<Move, unsigned int>:: iterator it;
336 unsigned long int trials = 0, tot_trials, rounds;
339 ne.FirstMove(st, mv);
344 while (ne.NextMove(st, mv));
346 os <<
"The neighborhood has " << frequency.size() <<
" members." << std::endl;
347 os <<
"How many rounds do you want to test: ";
350 tot_trials = frequency.size() * rounds;
351 while (trials < tot_trials)
353 ne.RandomMove(st, mv);
354 if (frequency.find(mv) != frequency.end())
359 os <<
"Random move not in neighborhood " << mv << std::endl;
361 if (trials % frequency.size() == 0)
366 for (it = frequency.begin(); it != frequency.end(); ++it)
368 dev += pow((
double)(*it).second, 2);
371 dev = sqrt(fabs(dev/frequency.size() - pow(
double(rounds), 2)));
375 os <<
"Outlier moves [move frequency]:" << std::endl;
376 for (it = frequency.begin(); it != frequency.end(); ++it)
378 if (fabs((*it).second -
double(rounds)) > 3*dev || (*it).second == 0)
381 os << it->first <<
" " << it->second/double(rounds) << std::endl;
384 std::cerr <<
"Deviation of move frequency: " << dev << std::endl;
385 std::cerr <<
"Percentage of outliers " << 100 * error/frequency.size() <<
'%' << std::endl;
388 template <
class Input,
class Output,
class State,
class Move,
typename CFtype>
392 std::vector<std::pair<Move, State> > reached_states;
393 unsigned int repeat_states = 0, null_moves = 0, all_moves = 1, i;
396 ne.FirstMove(st1, mv);
397 ne.MakeMove(st1, mv);
400 os <<
"Null move " << mv << std::endl;
405 reached_states.push_back(std::make_pair(mv, st1));
407 while (ne.NextMove(st, mv))
410 ne.MakeMove(st1, mv);
413 os <<
"Null move " << mv << std::endl;
418 repeated_state =
false;
419 for (i = 0; i < reached_states.size(); i++)
420 if (st1 == reached_states[i].second)
422 repeated_state =
true;
427 os <<
"Repeated state for moves " << reached_states[i].first <<
" and " << mv << std::endl;
432 reached_states.push_back(std::make_pair(mv, st1));
435 if (all_moves % 100 == 0)
440 os << std::endl <<
"Number of moves: " << all_moves << std::endl;
441 if (repeat_states == 0)
442 os <<
"No repeated states" << std::endl;
444 os <<
"There are " << repeat_states <<
" repeated states" << std::endl;
446 os <<
"No null moves" << std::endl;
448 os <<
"There are " << null_moves <<
" null moves" << std::endl;
451 template <
class Input,
class Output,
class State,
class Move,
typename CFtype>
454 return ne.Modality();
457 template <
class Input,
class Output,
class State,
class Move,
typename CFtype>
466 #endif // _MOVE_TESTER_HH_
CostStructure< CFtype > cost
void AddMoveTester(ComponentTester< Input, Output, State, CFtype > &amt)
std::vector< CFtype > all_components
Core::NeighborhoodExplorer< Input, State, Move, CFtype > & ne
Core::OutputManager< Input, Output, State, CFtype > & om
Core::StateManager< Input, State, CFtype > & sm
void CheckRandomMoveDistribution(const State &st) const
void PrintMoveCosts(const State &st, const EvaluatedMove< Move, CFtype > &em) const
void PrintAllNeighbors(const State &st) const
void SetTolerance(double t)
void RunMainMenu(State &st)
void CheckMoveIndependence(const State &st) const
void CheckNeighborhoodCosts(const State &st) const
The class CostComponent manages one single component of the cost, either hard or soft.
bool ExecuteChoice(State &st)
bool IsZero(CFtype value)
MoveTester(const Input &in, Core::StateManager< Input, State, CFtype > &sm, Core::OutputManager< Input, Output, State, CFtype > &om, Core::NeighborhoodExplorer< Input, State, Move, CFtype > &ne, std::string name, Tester< Input, Output, State, CFtype > &t, std::ostream &o=std::cout)
void PrintNeighborhoodStatistics(const State &st) const
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)