HOG2
BurnedPancakePuzzle.cpp
Go to the documentation of this file.
1 #include "BurnedPancakePuzzle.h"
2 #include <cstdlib>
3 
5 {
6  assert(s >= 2);
7  size = s;
8 
9  // assign the default operator ordering
10  for (unsigned i = s; i >= 2; i--)
11  operators.push_back(i);
12 
13  goal_stored = false;
14  use_memory_free = true;
15 }
16 
17 BurnedPancakePuzzle::BurnedPancakePuzzle(unsigned s, const std::vector<unsigned> op_order)
18 {
19  size = s;
20 
21  Change_Op_Order(op_order);
22 
23  goal_stored = false;
24  use_memory_free = false;
25 }
26 
28 {
29  ClearGoal();
30 }
31 
32 //const std::string BurnedPancakePuzzle::GetName()
33 //{
34 // std::stringstream name;
35 // name << size;
36 // name << " BurnedPancake Puzzle";
37 //
38 // if (PDB_distincts.size() > 0)
39 // {
40 // name << ", PDBS:";
41 // for (unsigned i = 0; i < PDB_distincts.size(); i++)
42 // {
43 // name << " <";
44 // for (unsigned j = 0; j < PDB_distincts[i].size() - 1; j++)
45 // {
46 // name << PDB_distincts[i][j];
47 // name << ", ";
48 // }
49 // name << PDB_distincts[i].back();
50 // name << ">";
51 // }
52 // if (use_memory_free)
53 // name << ", Memory-Free Heuristic";
54 // }
55 // else if (use_memory_free)
56 // {
57 // name << ", Memory-Free Heuristic";
58 // }
59 // else {
60 // name << ",No Heuristic";
61 // }
62 //
63 // name << ", Op Order: ";
64 // for (unsigned op_num = 0; op_num < operators.size() - 1; op_num++)
65 // {
66 // name << operators[op_num];
67 // name << ", ";
68 // }
69 // name << operators.back();
70 // return name.str();
71 //}
72 
74  std::vector<BurnedPancakePuzzleState> &children) const
75 {
76  children.resize(0);
77 
78  // all operators are applicable in all states
79  for (unsigned i = 0; i < operators.size(); i++)
80  {
81  children.push_back(parent); // adds a copy of the state to the stack
82  ApplyAction(children.back(), operators[i]);
83  }
84 }
85 
86 void BurnedPancakePuzzle::GetActions(const BurnedPancakePuzzleState &, std::vector<unsigned> &actions) const
87 {
88  actions.resize(0);
89 
90  // all operators are applicable in all states
91  for (unsigned i = 0; i < operators.size(); i++)
92  {
93  actions.push_back(operators[i]);
94  }
95 }
96 
98 {
99  unsigned current_action;
100  bool are_equal = false;
101 
102  assert(child.puzzle.size() == size);
103  assert(parent.puzzle.size() == size);
104  BurnedPancakePuzzleState parentCopy = parent;
105  for (unsigned i = 0; i < operators.size(); i++)
106  {
107  current_action = operators[i];
108  ApplyAction(parentCopy, current_action);
109  if (parentCopy == child)
110  are_equal = true;
111  InvertAction(current_action);
112  ApplyAction(parentCopy, current_action);
113 
114  if (are_equal)
115  return operators[i];
116  }
117  fprintf(stderr, "ERROR: GetAction called with non-adjacent states\n");
118  exit(1);
119  return 0;
120 }
121 
123 {
124  assert(s.puzzle.size() == size);
125  assert(action > 1 && action <= size);
126 
127  int upper = 0;
128  int lower = action - 1;
129  int temp;
130  // performs pancake flipping -- burned side switches
131  while(upper < lower)
132  {
133  temp = s.puzzle[upper];
134  s.puzzle[upper] = -s.puzzle[lower];
135  s.puzzle[lower] = -temp;
136  upper++;
137  lower--;
138  }
139  if (upper == lower)
140  s.puzzle[lower] = -s.puzzle[lower];
141 }
142 
143 bool BurnedPancakePuzzle::InvertAction(unsigned &a) const
144 {
145  // ever action is self-inverse
146  assert(a > 1 && a <= size);
147  return true;
148 }
149 
151 {
152  if (!goal_stored)
153  {
154  fprintf(stderr, "ERROR: HCost called with a single state and goal is not stored.\n");
155  exit(1);
156  }
157  if (state.puzzle.size() != size)
158  {
159  fprintf(stderr, "ERROR: HCost called with a single state with wrong size.\n");
160  exit(1);
161  }
162  double h_cost = 0;
163 
164 // // use PDB heuristic
165 // if (PDB.size() > 0)
166 // {
167 // if (PDB.size() != PDB_distincts.size())
168 // {
169 // fprintf(stderr, "ERROR: HCost called with a single state, no use of memory free heuristic, and invalid setup of pattern databases.\n");
170 // exit(1);
171 // }
172 // h_cost = std::max(Regular_PDB_Lookup(state), h_cost);
173 // }
174 
175  // use memory-free heuristic
176  if (use_memory_free)
177  {
178  h_cost = std::max(Memory_Free_HCost(state, goal_locations), h_cost);
179  }
180  // if no heuristic
181  else //if (PDB.size()==0)
182  {
183  if (goal == state)
184  return 0;
185  else
186  return 1;
187  }
188 
189  return h_cost;
190 }
191 
193 {
194  if (state.puzzle.size() != size)
195  {
196  fprintf(stderr, "ERROR: HCost called with state with wrong size.\n");
197  exit(1);
198  }
199  if (goal_state.puzzle.size() != size)
200  {
201  fprintf(stderr, "ERROR: HCost called with goal with wrong size.\n");
202  exit(1);
203  }
204 
205  if (use_memory_free)
206  {
207  std::vector<int> goal_locs(size);
208  for (unsigned i = 0; i < size; i++)
209  {
210  int theSign = abs(goal_state.puzzle[i])/goal_state.puzzle[i];
211  goal_locs[abs(goal_state.puzzle[i])-1] = (i+1)*theSign;
212 // std::cout << "goal array: ";
213 // for (unsigned int x = 0; x < size; x++)
214 // std::cout << goal_locs[x] << " ";
215 // std::cout << std::endl;
216  }
217  return Memory_Free_HCost(state, goal_locs);
218  }
219 
220  if (state == goal_state)
221  return 0.0;
222  return 1.0;
223 }
224 //#define GetDualEntry(s, r, i) (r[abs(s.puzzle[i])-1])
225 //#define GetDualEntry(s, r, i) (s.puzzle[r[i]-1])
226 int GetDualEntryLoc(const BurnedPancakePuzzleState &state, const std::vector<int> &goal_locs, int index)
227 {
228  int theSign = abs(state.puzzle[index])/state.puzzle[index];
229  int loc = goal_locs[abs(state.puzzle[index])-1];
230  return loc*theSign;
231 }
232 
233 double BurnedPancakePuzzle::Memory_Free_HCost(const BurnedPancakePuzzleState &state, const std::vector<int> &goal_locs) const
234 {
235  if (state.puzzle.size() != size)
236  {
237  fprintf(stderr, "ERROR: HCost called with state with wrong size.\n");
238  exit(1);
239  }
240 
241  double h_count = 0.0;
242  unsigned i = 0;
243  for (; i < size - 1; i++)
244  {
245 // int diff = abs(goal_locs[abs(state.puzzle[i])-1]) - abs(goal_locs[abs(state.puzzle[i+1])-1]);
246  int curr = GetDualEntryLoc(state, goal_locs, i);
247  int next = GetDualEntryLoc(state, goal_locs, i+1);
248  int diff = (abs(abs(curr)-abs(next)));
249  if (diff > 1 || diff < - 1)
250  {
251  h_count++;
252  }
253  else if ((curr < 0 && next > 0) ||// sign is different
254  (curr > 0 && next < 0))
255  {
256  h_count+=2;
257  }
258  }
259  int last = GetDualEntryLoc(state, goal_locs, i);
260  //if ((unsigned) goal_locs[abs(state.puzzle[i])-1] != size -1)
261  if (last != (int)size)
262  h_count++;
263  else if (-last == (int)size)
264  h_count+=2;
265 // else if (state.puzzle[i] < 0) // in place but must switch out
266 // h_count+=2;
267 
268 // std::cout << "goal array: ";
269 // for (unsigned int x = 0; x < size; x++)
270 // std::cout << goal_locs[x] << " ";
271 // std::cout << std::endl;
272  return h_count;
273 }
274 
276 {
277  return (state == theGoal);
278 }
279 
281 {
282  if (!goal_stored)
283  {
284  fprintf(stderr, "ERROR: GoalTest called with a single state and goal is not stored.\n");
285  exit(1);
286  }
287  if (s.puzzle.size() != size)
288  {
289  fprintf(stderr, "ERROR: GoalTest called with a single state with wrong size.\n");
290  exit(1);
291  }
292  return (s == goal);
293 }
294 
295 uint64_t BurnedPancakePuzzle::GetActionHash(unsigned act) const
296 {
297  return (uint64_t) act;
298 }
299 
301 {
302  assert(g.puzzle.size() == size);
303 
304  goal = g;
305  goal_stored = true;
306 
307  goal_locations.resize(size);
308  for (unsigned i = 0; i < size; i++)
309  {
310  goal_locations[goal.puzzle[i]] = i;
311  }
312 }
313 
314 void BurnedPancakePuzzle::Change_Op_Order(const std::vector<unsigned> op_order)
315 {
316  operators.clear();
317 
318  if (op_order.size() != size - 1)
319  {
320  fprintf(stderr, "ERROR: Not enough operators in operator sequence for construction of BurnedPancakePuzzle\n");
321  exit(1);
322  }
323 
324  bool all_ops[op_order.size()];
325 
326  for (unsigned i = 0; i < size; i++)
327  {
328  all_ops[i] = false;
329  }
330 
331  for (unsigned i = 0; i < op_order.size(); i++)
332  {
333  if (op_order[i] < 2 || op_order[i] > size)
334  {
335  fprintf(stderr, "ERROR: Invalid operator included in construction of BurnedPancakePuzzle\n");
336  exit(1);
337  }
338  all_ops[op_order[i] - 2] = true;
339  }
340 
341  for (unsigned i = 0; i < op_order.size(); i++)
342  {
343  assert(false);
344  // code here was originally problematic
345  // (!all_ops[i])
346  if (all_ops[i] == false)
347  {
348  fprintf(stderr, "ERROR: Missing operator %u in construction of BurnedPancakePuzzle\n", i+2);
349  exit(1);
350  }
351  }
352  // assign the default operator ordering
353  for (unsigned i = 0; i < op_order.size(); i++)
354  operators.push_back(op_order[i]);
355 }
356 
357 
358 //void BurnedPancakePuzzle::Create_Random_BurnedPancake_Puzzles(std::vector<BurnedPancakePuzzleState> &puzzle_vector, unsigned size, unsigned num_puzzles)
359 //{
360 // std::map<uint64_t, uint64_t> puzzle_map; // used to ensure uniqueness
361 //
362 // BurnedPancakePuzzle my_puzz(size);
363 //
364 // unsigned count = 0;
365 //
366 // std::vector<int> perm;
367 // BurnedPancakePuzzleState potential_puzz(size);
368 // while (count < num_puzzles)
369 // {
370 // perm = Get_Random_Permutation(size);
371 //
372 // // construct puzzle
373 // for (unsigned i = 0; i < size; i++)
374 // {
375 // potential_puzz.puzzle[i] = perm[i];
376 // }
377 //
378 // uint64_t next_hash = my_puzz.GetStateHash(potential_puzz);
379 //
380 // // make sure is not a duplicate
381 // if (puzzle_map.find(next_hash) != puzzle_map.end())
382 // {
383 // continue;
384 // }
385 //
386 // puzzle_map[next_hash] = next_hash;
387 // puzzle_vector.push_back(potential_puzz);
388 // count++;
389 // }
390 //}
391 
392 //int BurnedPancakePuzzle::read_in_pancake_puzzles(const char *filename, bool puzz_num_start, unsigned size, unsigned max_puzzles, std::vector<BurnedPancakePuzzleState> &puzzles)
393 //{
394 // std::vector<std::vector<int> > permutations;
395 // Read_In_Permutations(filename, size, max_puzzles, permutations, puzz_num_start);
396 //
397 // // convert permutations into BurnedPancakePuzzleStates
398 // for (unsigned i = 0; i < permutations.size(); i++)
399 // {
400 // BurnedPancakePuzzleState new_state(size);
401 //
402 // for (unsigned j = 0; j < size; j++)
403 // {
404 // new_state.puzzle[j] = permutations[i][j];
405 // }
406 // puzzles.push_back(new_state);
407 // }
408 // return 0;
409 //}
410 //
411 //bool BurnedPancakePuzzle::Path_Check(BurnedPancakePuzzleState start, BurnedPancakePuzzleState theGoal, std::vector<unsigned> &actions)
412 //{
413 // if (start.puzzle.size() != size || theGoal.puzzle.size() != size)
414 // return false;
415 //
416 // for (unsigned i = 0; i < actions.size(); i++)
417 // {
418 // if (actions[i] < 2 || actions[i] > size)
419 // return false;
420 // ApplyAction(start, actions[i]);
421 // }
422 //
423 // if (start == theGoal)
424 // return true;
425 //
426 // return false;
427 //}
428 //
429 //std::vector<unsigned> BurnedPancakePuzzle::Get_Puzzle_Order(int64_t order_num, unsigned num_pancakes)
430 //{
431 // std::vector<unsigned> ops;
432 // assert(order_num >= 0);
433 // assert(num_pancakes > 0);
434 //
435 // std::vector<int64_t> op_nums(num_pancakes -1);
436 //
437 // int64_t num_left = 1;
438 // for (int64_t x = num_pancakes - 2; x >= 0; x--)
439 // {
440 // op_nums[x] = order_num % num_left;
441 // order_num /= num_left;
442 // num_left++;
443 //
444 // for (int64_t y = x+1; y < num_pancakes-1; y++)
445 // {
446 // if (op_nums[y] >= op_nums[x])
447 // {
448 // op_nums[y]++;
449 // }
450 // }
451 // }
452 //
453 // std::vector<bool> actions;
454 //
455 // for (unsigned i = 0; i < num_pancakes - 1; i++)
456 // {
457 // actions.push_back(false);
458 // }
459 //
460 // for (unsigned i = 0; i < num_pancakes - 1; i++)
461 // {
462 // ops.push_back(op_nums[i] + 2);
463 // actions[op_nums[i]] = true;
464 // }
465 //
466 // for (unsigned i = 0; i < num_pancakes - 1; i++)
467 // {
468 // assert(actions[i]);
469 // }
470 // return ops;
471 //}
472 
474 {
475  std::vector<int> puzzle = s.puzzle;
476  uint64_t hashVal = 0;
477  int numEntriesLeft = (int)s.puzzle.size();
478  for (unsigned int x = 0; x < s.puzzle.size(); x++)
479  {
480  hashVal += puzzle[x]*Factorial(numEntriesLeft-1);
481  numEntriesLeft--;
482  for (unsigned y = x; y < puzzle.size(); y++)
483  {
484  if (puzzle[y] > puzzle[x])
485  puzzle[y]--;
486  }
487  }
488  return hashVal;
489 }
BurnedPancakePuzzle::InvertAction
bool InvertAction(unsigned &a) const
Definition: BurnedPancakePuzzle.cpp:143
BurnedPancakePuzzle::operators
std::vector< unsigned > operators
Definition: BurnedPancakePuzzle.h:124
BurnedPancakePuzzle::Factorial
uint64_t Factorial(int val) const
Definition: BurnedPancakePuzzle.h:133
BurnedPancakePuzzle::Change_Op_Order
void Change_Op_Order(const std::vector< unsigned > op_order)
Changes the ordering of operators to the new inputted order.
Definition: BurnedPancakePuzzle.cpp:314
BurnedPancakePuzzle::HCost
double HCost(const BurnedPancakePuzzleState &state1, const BurnedPancakePuzzleState &state2) const
Heuristic value between two arbitrary nodes.
Definition: BurnedPancakePuzzle.cpp:192
BurnedPancakePuzzle::BurnedPancakePuzzle
BurnedPancakePuzzle(unsigned s)
Definition: BurnedPancakePuzzle.cpp:4
BurnedPancakePuzzle::goal_stored
bool goal_stored
Definition: BurnedPancakePuzzle.h:125
BurnedPancakePuzzle::GetActions
void GetActions(const BurnedPancakePuzzleState &state, std::vector< unsigned > &actions) const
Definition: BurnedPancakePuzzle.cpp:86
BurnedPancakePuzzle::use_memory_free
bool use_memory_free
Definition: BurnedPancakePuzzle.h:126
loc
Definition: MapGenerators.cpp:296
BurnedPancakePuzzle.h
BurnedPancakePuzzle::goal_locations
std::vector< int > goal_locations
Definition: BurnedPancakePuzzle.h:129
BurnedPancakePuzzleState
Definition: BurnedPancakePuzzle.h:9
BurnedPancakePuzzle::GetSuccessors
void GetSuccessors(const BurnedPancakePuzzleState &state, std::vector< BurnedPancakePuzzleState > &neighbors) const
Definition: BurnedPancakePuzzle.cpp:73
BurnedPancakePuzzle::StoreGoal
void StoreGoal(BurnedPancakePuzzleState &)
Stores the goal for use by single-state HCost.
Definition: BurnedPancakePuzzle.cpp:300
BurnedPancakePuzzle::GetActionHash
uint64_t GetActionHash(unsigned act) const
Definition: BurnedPancakePuzzle.cpp:295
BurnedPancakePuzzleState::puzzle
std::vector< int > puzzle
Definition: BurnedPancakePuzzle.h:18
max
#define max(a, b)
Definition: MinimalSectorAbstraction.cpp:40
BurnedPancakePuzzle::~BurnedPancakePuzzle
~BurnedPancakePuzzle()
Definition: BurnedPancakePuzzle.cpp:27
BurnedPancakePuzzle::GoalTest
bool GoalTest(const BurnedPancakePuzzleState &state, const BurnedPancakePuzzleState &goal) const
Definition: BurnedPancakePuzzle.cpp:275
BurnedPancakePuzzle::size
unsigned size
Definition: BurnedPancakePuzzle.h:130
BurnedPancakePuzzle::goal
BurnedPancakePuzzleState goal
Definition: BurnedPancakePuzzle.h:128
BurnedPancakePuzzle::GetAction
unsigned GetAction(const BurnedPancakePuzzleState &s1, const BurnedPancakePuzzleState &s2) const
Definition: BurnedPancakePuzzle.cpp:97
BurnedPancakePuzzle::Memory_Free_HCost
double Memory_Free_HCost(const BurnedPancakePuzzleState &state1, const std::vector< int > &goal_locs) const
Definition: BurnedPancakePuzzle.cpp:233
BurnedPancakePuzzle::ClearGoal
void ClearGoal()
Clears the goal from memory.
Definition: BurnedPancakePuzzle.h:81
BurnedPancakePuzzle::GetStateHash
virtual uint64_t GetStateHash(const BurnedPancakePuzzleState &s) const
Definition: BurnedPancakePuzzle.cpp:473
BurnedPancakePuzzle::ApplyAction
void ApplyAction(BurnedPancakePuzzleState &s, unsigned a) const
Definition: BurnedPancakePuzzle.cpp:122
GetDualEntryLoc
int GetDualEntryLoc(const BurnedPancakePuzzleState &state, const std::vector< int > &goal_locs, int index)
Definition: BurnedPancakePuzzle.cpp:226