HOG2
MNPuzzle.h
Go to the documentation of this file.
1 /*
2  * MNPuzzle.h
3  * hog2
4  *
5  * Created by Nathan Sturtevant on 5/9/07.
6  * Copyright 2007 Nathan Sturtevant, University of Alberta. All rights reserved.
7  *
8  */
9 
10 #ifndef MNPUZZLE_H
11 #define MNPUZZLE_H
12 
13 #include <stdint.h>
14 #include <iostream>
15 #include "SearchEnvironment.h"
17 #include "UnitSimulation.h"
18 #include "GraphEnvironment.h"
19 #include "Graph.h"
20 #include "GraphEnvironment.h"
21 #include <sstream>
22 #include <array>
23 
24 template <int width, int height>
26 public:
28  {
29  Reset();
30  }
31  void Reset()
32  {
33  for (size_t x = 0; x < size(); x++)
34  puzzle[x] = x;
35  blank = 0;
36  }
37  size_t size() const { return width*height; }
39  {
40  for (size_t x = 0; x < size(); x++)
41  {
42  if (puzzle[x] == 0)
43  {
44  blank = x;
45  return;
46  }
47  }
48  }
49  bool operator<(const MNPuzzleState &b)
50  {
51  for (size_t x = 0; x < size(); x++)
52  if (puzzle[x] != b.puzzle[x])
53  return puzzle[x] < b.puzzle[x];
54  return false;
55  }
56 
57  unsigned int blank;
58  std::array<int, width*height> puzzle;
59 // int puzzle[width*height];
60 };
61 
62 namespace std {
63 
64  template <int w, int h>
65  struct hash<MNPuzzleState<w, h>>
66  {
67  std::size_t operator()(const MNPuzzleState<w, h>& k) const
68  {
69  size_t hash = 0;
70  for (int x = 0; x < w*h; x++)
71  hash = hash*w*h + k.puzzle[x];
72  return hash;
73  }
74  };
75 
76 }
77 
78 
84 enum slideDir {
86 };
87 
88 template <int width, int height>
89 static std::ostream& operator <<(std::ostream & out, const MNPuzzleState<width, height> &loc)
90 {
91  out << "(" << width << "x" << height << ")";
92  for (size_t x = 0; x < loc.size(); x++)
93  out << loc.puzzle[x] << " ";
94  return out;
95 }
96 
97 static std::ostream& operator <<(std::ostream & out, const slideDir &loc)
98 {
99  switch (loc)
100  {
101  case kLeft: out << "Left"; break;
102  case kRight: out << "Right"; break;
103  case kUp: out << "Up"; break;
104  case kDown: out << "Down"; break;
105  }
106  return out;
107 }
108 
109 
110 template <int width, int height>
112 {
113  for (unsigned int x = 0; x < l1.size(); x++)
114  {
115  if (l1.puzzle[x] > 0 || l2.puzzle[x] > 0) // don't have to check the blank
116  if (l1.puzzle[x] != l2.puzzle[x])
117  return false;
118  }
119  return true;
120 }
121 
122 template <int width, int height>
124 {
125  return !(l1 == l2);
126 }
127 
134 };
135 
136 template <int width, int height>
137 class MNPuzzle : public PermutationPuzzle::PermutationPuzzleEnvironment<MNPuzzleState<width, height>, slideDir> {
138 public:
139  MNPuzzle();
140  MNPuzzle(const std::vector<slideDir> op_order); // used to set action order
141  ~MNPuzzle();
142  void SetWeighted(puzzleWeight w) { weight = w; }
143  puzzleWeight GetWeighted() const { return weight; }
144  void GetSuccessors(const MNPuzzleState<width, height> &stateID, std::vector<MNPuzzleState<width, height>> &neighbors) const;
145  void GetActions(const MNPuzzleState<width, height> &stateID, std::vector<slideDir> &actions) const;
149  bool InvertAction(slideDir &a) const;
150  static unsigned GetParity(const MNPuzzleState<width, height> &state);
151 
153  double HCost(const MNPuzzleState<width, height> &state1, const MNPuzzleState<width, height> &state2) const;
154  double HCost(const MNPuzzleState<width, height> &state1) const;
155  double DefaultH(const MNPuzzleState<width, height> &s) const;
156 
157  double GCost(const MNPuzzleState<width, height> &state1, const MNPuzzleState<width, height> &state2) const;
158  double GCost(const MNPuzzleState<width, height> &, const slideDir &) const;
160 
161  bool GoalTest(const MNPuzzleState<width, height> &s) const;
162 
163  double AdditiveGCost(const MNPuzzleState<width, height> &, const slideDir &) const;
164  bool InPattern(int tile) const;
165  void SetPattern(const std::vector<int> &pattern);
166  void GetStateFromPDBHash(uint64_t hash, MNPuzzleState<width, height> &s,
167  int count, const std::vector<int> &pattern,
168  std::vector<int> &dual);
169  //void LoadPDB(char *fname, const std::vector<int> &tiles, bool additive);
170  //virtual void FinishUnranking(MNPuzzleState<width, height> &s) const { s.FinishUnranking(); }
171 
172  uint64_t GetActionHash(slideDir act) const;
173  void OpenGLDraw() const;
174  void OpenGLDraw(const MNPuzzleState<width, height> &s) const;
175  void OpenGLDraw(const MNPuzzleState<width, height> &l1, const MNPuzzleState<width, height> &l2, float v) const;
176  void OpenGLDraw(const MNPuzzleState<width, height> &, const slideDir &) const { /* currently not drawing moves */ }
177  void Draw(Graphics::Display &display, const MNPuzzleState<width, height>&) const;
178  void Draw(Graphics::Display &display, const MNPuzzleState<width, height> &l1, const MNPuzzleState<width, height> &l2, float v) const;
179 
180 
181  void StoreGoal(MNPuzzleState<width, height> &); // stores the locations for the given goal state
182 
185  if (!goal_stored) {
186  fprintf(stderr, "ERROR: Call to Get_Goal when no goal stored\n");
187  exit(1);
188  }
189  return goal;
190  }
191 
192  virtual const std::string GetName();
193 
194  void ClearGoal(); // clears the current stored information of the goal
195 
196  bool IsGoalStored() const {return goal_stored;} // returns if a goal is stored or not
197  Graph *GetGraph();
198 
202  void Change_Op_Order(const std::vector<slideDir> op_order);
203 
210  static void Create_Random_MN_Puzzles(MNPuzzleState<width, height> &goal, std::vector<MNPuzzleState<width, height>> &puzzle_vector, unsigned num_puzzles);
211 
220  static int read_in_mn_puzzles(const char *filename, bool first_counter, unsigned max_puzzles, std::vector<MNPuzzleState<width, height>> &puzzle_vector);
221 
229  static std::vector<slideDir> Get_Op_Order_From_Hash(int order_num);
230  std::vector<slideDir> Get_Op_Order(){return ops_in_order;}
231 
233 
234  virtual void GetStateFromHash(MNPuzzleState<width, height> &s, uint64_t hash) const;
235  uint64_t GetStateHash(const MNPuzzleState<width, height> &s) const;
236  uint64_t GetMaxStateHash() const;
237 
238  bool State_Check(const MNPuzzleState<width, height> &to_check);
239 
240  unsigned Get_Num_Of_Columns(){return width;}
241  unsigned Get_Num_Of_Rows(){return height;}
242 
243  void Set_Use_Manhattan_Heuristic(bool to_use){use_manhattan = to_use;}
244 private:
246 // double DoPDBLookup(const MNPuzzleState<width, height> &state);
247 // std::vector<std::vector<uint8_t> > PDB;
248 // std::vector<std::vector<int> > PDBkey;
249  std::vector<std::vector<slideDir> > operators; // stores the operators applicable at each blank position
250  std::vector<slideDir> ops_in_order;
251  bool goal_stored; // whether a goal is stored or not
254 
255  // stores the heuristic value of each tile-position pair indexed by the tile value (0th index is empty)
256  std::vector<std::vector<unsigned> > h_increment;
258 };
259 
260 template <int width, int height>
262 public:
264  double HCost(const graphState &state1, const graphState &state2) const;
265 private:
267 };
268 
269 //typedef UnitSimulation<MNPuzzleState, slideDir, MNPuzzle> PuzzleSimulation;
270 
271 template <int width, int height>
273 {
274  weight = kUnitWeight;
275  // stores applicable operators at each of the width*height positions
276  Change_Op_Order(Get_Op_Order_From_Hash(15)); // Right, Left, Down, Up is default operator ordering
277  goal_stored = false;
278  use_manhattan = true;
279 }
280 
281 template <int width, int height>
282 MNPuzzle<width, height>::MNPuzzle(const std::vector<slideDir> op_order)
283 {
284  Change_Op_Order(op_order);
285  goal_stored = false;
286  use_manhattan = true;
287  weight = kUnitWeight;
288 }
289 
290 template <int width, int height>
292 {
293  ClearGoal();
294 }
295 
296 template <int width, int height>
297 void MNPuzzle<width, height>::Change_Op_Order(std::vector<slideDir> op_order)
298 {
299  operators.clear();
300  ops_in_order.clear();
301 
302  bool up_act = false;
303  bool down_act = false;
304  bool left_act = false;
305  bool right_act = false;
306 
307  if (op_order.size() != 4)
308  {
309  fprintf(stderr, "ERROR: Not enough operators in operator sequence for construction of MNPuzzle\n");
310  exit(1);
311  }
312 
313  for (unsigned int op_num = 0; op_num < 4; op_num++)
314  {
315  if (op_order[op_num] == kUp)
316  {
317  up_act = true;
318  }
319  else if (op_order[op_num] == kDown)
320  {
321  down_act = true;
322  }
323  else if (op_order[op_num] == kLeft)
324  {
325  left_act = true;
326  }
327  else if (op_order[op_num] == kRight)
328  {
329  right_act = true;
330  }
331  }
332 
333  if (!up_act || !down_act || !left_act || !right_act)
334  {
335  fprintf(stderr, "ERROR: Invalid operator sequence for construction of MNPuzzle\n");
336  exit(1);
337  }
338 
339  for (unsigned i = 0; i < op_order.size(); i++)
340  {
341  ops_in_order.push_back(op_order[i]);
342  }
343 
344  // stores applicable operators at each of the width*height positions
345  std::vector<slideDir> ops(4);
346  for (unsigned int blank = 0; blank < width*height; blank++) {
347  ops.resize(0);
348 
349  for (unsigned int op_num = 0; op_num < 4; op_num++)
350  {
351  if (op_order[op_num] == kUp && blank > width - 1)
352  {
353  ops.push_back(kUp);
354  }
355  if (op_order[op_num] == kLeft && blank % width > 0)
356  {
357  ops.push_back(kLeft);
358  }
359  if (op_order[op_num] == kRight && (blank % width) < width - 1)// && (blank != 0))
360  {
361  ops.push_back(kRight);
362  }
363  if (op_order[op_num] == kDown && blank < width * height - width)// && (blank != 1))
364  {
365  ops.push_back(kDown);
366  }
367  }
368 
369  operators.push_back(ops);
370  }
371 }
372 
373 template <int width, int height>
375  std::string s = "STP(";
376  s += std::to_string(width);
377  s += ",";
378  s += std::to_string(height);
379  s += ")";
380  return s;
381 // std::stringstream name;
382 // name << width;
383 // name << "x";
384 // name << height;
385 // name << " Sliding Tile Puzzle";
386 //
403 // {
404 // name << ", Manhattan Distance";
405 // }
406 //
407 // name << ", Op Order: ";
408 // for (unsigned op_num = 0; op_num < ops_in_order.size() - 1; op_num++){
409 // name << ops_in_order[op_num];
410 // name << ", ";
411 // }
412 // name << ops_in_order.back();
413 // return name.str();
414 }
415 
416 template <int width, int height>
418 {
419  Graph *g = new Graph();
420  //Factorial(width*height);
421 
422  for (int x = 0; x < 362880; x++)
423  {
424  node *n;
425  g->AddNode(n = new node(""));
426  n->SetLabelF(GraphSearchConstants::kXCoordinate, (32768.0-random()%65536)/32768.0);
427  n->SetLabelF(GraphSearchConstants::kYCoordinate, (32768.0-random()%65536)/32768.0);
428  n->SetLabelF(GraphSearchConstants::kZCoordinate, (32768.0-random()%65536)/32768.0);
429  }
430  for (int x = 0; x < 362880; x++)
431  {
433  GetStateFromHash(t, x);
434  std::vector<slideDir> moves;
435  GetActions(t, moves);
437  for (unsigned int y = 0; y < moves.size(); y++)
438  {
439  ApplyAction(t, moves[y]);
440  uint64_t hash = GetStateHash(t);
441  InvertAction(moves[y]);
442  ApplyAction(t, moves[y]);
443  if (!g->FindEdge(x, hash))
444  g->AddEdge(new edge(x, hash, 1));
445  }
446  }
447  // 362880 states
448  // 2x2 area -- roughly 600x600 states, or distance 1 = 1/600
449  // for (int t = 0; t < 362880; t++)
450  // {
451  // node *n = g->GetNode(t);
452  // neighbor_iterator ni = n->getNeighborIter();
453  // for (long tmp = n->nodeNeighborNext(ni); tmp != -1; tmp = n->nodeNeighborNext(ni))
454  // {
455  // double x, y, z;
456  // x = n->GetLabelF(GraphSearchConstants::kXCoordinate);
457  // y = n->GetLabelF(GraphSearchConstants::kYCoordinate);
458  // z = n->GetLabelF(GraphSearchConstants::kZCoordinate);
459  //
460  // double x1, y1, z1;
461  // node *nb = g->GetNode(tmp);
462  // x1 = nb->GetLabelF(GraphSearchConstants::kXCoordinate);
463  // y1 = nb->GetLabelF(GraphSearchConstants::kYCoordinate);
464  // z1 = nb->GetLabelF(GraphSearchConstants::kZCoordinate);
465  // // now move n to be 1/600 away from nb!
466  // n->SetLabelF(GraphSearchConstants::kXCoordinate, 0.5*x + 0.5*x1);
467  // n->SetLabelF(GraphSearchConstants::kYCoordinate, 0.5*y + 0.5*y1);
468  // n->SetLabelF(GraphSearchConstants::kZCoordinate, 0.5*z + 0.5*z1);
469  //
470  // }
471  // }
472  return g;
473 }
474 
475 template <int width, int height>
477 {
478 // assert(s.height == height);
479 // assert(s.width == width);
480 
481  // makes sure goal contains all legal
482  bool goal_tester[width*height];
483  for (unsigned int i = 0; i < width*height; i++)
484  {
485  goal_tester[i] = false;
486  }
487 
488  for (unsigned int i = 0; i < width*height; i++)
489  {
490  goal_tester[s.puzzle[i]] = true;
491  }
492 
493  for (unsigned int i = 0; i < width*height; i++)
494  {
495  if (!goal_tester[i])
496  {
497  printf("INVALID GOAL\n");
498  assert(goal_tester[i]);
499  }
500  }
501 
502  h_increment.resize(width*height);
503  //h_increment = new unsigned*[width*height];
504 
505  for (unsigned int i = 1; i < width*height; i++)
506  {
507  h_increment[i].resize(width*height);
508  //h_increment[i] = new unsigned [width*height];
509  }
510 
511  for (unsigned goal_pos = 0; goal_pos < width*height; goal_pos++)
512  {
513  unsigned tile = s.puzzle[goal_pos];
514  if (tile == 0)
515  continue;
516 
517  for (unsigned pos = 0; pos < width*height; pos++)
518  {
519  h_increment[tile][pos] = abs((int) (goal_pos % width) - (int)(pos % width)); // difference in column
520  h_increment[tile][pos] += abs((int) (goal_pos / width) - (int)(pos / width)); // difference in row
521  }
522  }
523 
524  goal_stored = true;
525 
526  goal = s;
527 }
528 
529 template <int width, int height>
531 {
532  return (s == goal);
533 }
534 
535 template <int width, int height>
537 {
538  if (goal_stored)
539  {
540  goal_stored = false;
541  // // clears memory allocated for h_increment
542  // for (unsigned int i = 1; i < width*height; i++)
543  // {
544  // delete h_increment[i];
545  // }
546  // delete h_increment;
547  }
548 }
549 
550 template <int width, int height>
552  std::vector<MNPuzzleState<width, height>> &neighbors) const
553 {
554  neighbors.resize(0);
555 
556  for (unsigned int i = 0; i < operators[stateID.blank].size(); i++)
557  {
558  neighbors.push_back(stateID);
559  ApplyAction(neighbors.back(), operators[stateID.blank][i]);
560  }
561 }
562 
563 template <int width, int height>
564 void MNPuzzle<width, height>::GetActions(const MNPuzzleState<width, height> &stateID, std::vector<slideDir> &actions) const
565 {
566  actions.resize(0);
567  for (unsigned int i = 0; i < operators[stateID.blank].size(); i++)
568  {
569  actions.push_back(operators[stateID.blank][i]);
570  }
571 }
572 
573 template <int width, int height>
575 {
576  int row1 = a.blank%width;
577  int col1 = a.blank/height;
578  int row2 = b.blank%width;
579  int col2 = b.blank/height;
580  if (row1 == row2)
581  {
582  if (col1 > col2)
583  return kUp;
584  return kDown;
585  }
586  if (row1 > row2)
587  return kLeft;
588  return kRight;
589 }
590 
591 template <int width, int height>
593 {
594  // we actually do the swap to maintain consistency when using abstract states
595  // (these contain -1 in some positions, including possibly the blank position.)
596  switch (a)
597  {
598  case kUp:
599  if (s.blank >= width)
600  {
601  int tmp = s.puzzle[s.blank];
602  s.puzzle[s.blank] = s.puzzle[s.blank-width];
603  s.blank -= width;
604  s.puzzle[s.blank] = tmp;
605  }
606  else {
607  printf("Invalid up operator\n");
608  assert(false);
609  exit(0);
610  }
611  break;
612  case kDown:
613  if (s.blank < s.size() - width)
614  {
615  int tmp = s.puzzle[s.blank];
616  s.puzzle[s.blank] = s.puzzle[s.blank+width];
617  s.blank += width;
618  s.puzzle[s.blank] = tmp;
619  }
620  else {
621  printf("Invalid down operator\n");
622  assert(false);
623  exit(0);
624  }
625  break;
626  case kRight:
627  if ((s.blank%width) < width-1)
628  {
629  int tmp = s.puzzle[s.blank];
630  s.puzzle[s.blank] = s.puzzle[s.blank+1];
631  s.blank += 1;
632  s.puzzle[s.blank] = tmp;
633  }
634  else {
635  printf("Invalid right operator\n");
636  assert(false);
637  exit(0);
638  }
639  break;
640  case kLeft:
641  if ((s.blank%width) > 0)
642  {
643  int tmp = s.puzzle[s.blank];
644  s.puzzle[s.blank] = s.puzzle[s.blank-1];
645  s.blank -= 1;
646  s.puzzle[s.blank] = tmp;
647  }
648  else {
649  printf("Invalid left operator\n");
650  assert(false);
651  exit(0);
652  }
653  break;
654  }
655 }
656 
657 template <int width, int height>
659 {
660  switch (a)
661  {
662  case kLeft: a = kRight; break;
663  case kUp: a = kDown; break;
664  case kDown: a = kUp; break;
665  case kRight: a = kLeft; break;
666  }
667  return true;
668 }
669 
670 template <int width, int height>
672 {
673  return DefaultH(state1);
674 }
675 
676 template <int width, int height>
678 {
679  if (goal_stored)
680  return HCost(state1);
681 // if (state1.height != height || state1.width != width)
682 // {
683 // fprintf(stderr, "ERROR: HCost called with a state with wrong size.\n");
684 // exit(1);
685 // }
686 // if (state2.height != height || state2.width != width)
687 // {
688 // fprintf(stderr, "ERROR: HCost called with a state with wrong size.\n");
689 // exit(1);
690 // }
691 
692  double hval = 0;
693  // if (PDB.size() != 0)
694  // hval = std::max(hval, PDB_Lookup(state1));
695 
696  if (use_manhattan)
697  {
698  double man_dist = 0;
699  int xloc[width*height];
700  int yloc[width*height];
701 
702  for (unsigned int x = 0; x < width; x++)
703  {
704  for (unsigned int y = 0; y < height; y++)
705  {
706  xloc[state2.puzzle[x + y*width]] = x;
707  yloc[state2.puzzle[x + y*width]] = y;
708  }
709  }
710  for (unsigned int x = 0; x < width; x++)
711  {
712  for (unsigned int y = 0; y < height; y++)
713  {
714  if (state1.puzzle[x + y*width] != 0)
715  {
716  double absDist = (abs((int)(xloc[state1.puzzle[x + y*width]] - x))
717  + abs((int)(yloc[state1.puzzle[x + y*width]] - y)));
718  double movingTile = state1.puzzle[x + y*width];
719  switch (weight)
720  {
721  case kUnitWeight: man_dist += absDist; break;
722  case kUnitPlusFrac: man_dist += absDist*(1.0+1.0/(1.0+movingTile)); break;
723  case kSquared: man_dist += absDist*(movingTile)*(movingTile); break;
724  case kSquareRoot: man_dist += absDist*sqrt(movingTile); break;
725  case kSquarePlusOneRoot:
726  {
727  double tmp = movingTile;
728  tmp = sqrt(tmp*tmp+1);
729  man_dist += tmp*absDist;
730  }
731  }
732 // if (weighted)
733 // man_dist += (abs((int)(xloc[state1.puzzle[x + y*width]] - x))
734 // + abs((int)(yloc[state1.puzzle[x + y*width]] - y)))*state1.puzzle[x + y*width]*state1.puzzle[x + y*width];
735 // else
736 // man_dist += (abs((int)(xloc[state1.puzzle[x + y*width]] - x))
737 // + abs((int)(yloc[state1.puzzle[x + y*width]] - y)));
738  }
739  }
740  }
741  hval = std::max(hval, man_dist);
742  }
743 // // if no heuristic
744 // else if (PDB.size()==0)
745 // {
746 // if (state1 == state2)
747 // return 0;
748 // else
749 // return 1;
750 // }
751 
752  return hval;
753 }
754 
755 template <int width, int height>
757 {
758  double man_dist = 0;
759  // increments amound for each tile location
760  // this calculates the Manhattan distance
761  for (unsigned loc = 0; loc < width*height; loc++)
762  {
763  if (state.puzzle[loc] > 0)
764  man_dist += h_increment[state.puzzle[loc]][loc];
765  }
766  return man_dist;
767 }
768 
769 static int costs[25] =
770 {
771  3, 5, 4, 7, 10, 5, 3, 3, 8, 9, 2, 10, 10, 1, 2, 1, 1, 4, 7, 9, 6, 10, 2, 8, 8
772 };
773 
774 //template <int width, int height>
775 //double MNPuzzle<width, height>::AdditiveGCost(const MNPuzzleState<width, height> &s, const slideDir &d)
776 //{
777 // int tile;
778 // switch (d)
779 // {
780 // case kLeft: tile = s.puzzle[s.blank-1]; break;
781 // case kUp: tile = s.puzzle[s.blank-height]; break;
782 // case kDown: tile = s.puzzle[s.blank+height]; break;
783 // case kRight: tile = s.puzzle[s.blank+1]; break;
784 // }
785 // if (tile == -1)
786 // return 0;
787 // if (weighted)
788 // return costs[s.blank];
789 // return 1;
790 //}
791 
792 template <int width, int height>
794 {
795  // Options:
796  // * tile squared
797  // square root of tile
798  // tile itself
799  switch (weight)
800  {
801  case kUnitWeight: return 1;
802  case kUnitPlusFrac: return (1.0+1.0/(1.0+a.puzzle[b.blank]));
803  case kSquared: return a.puzzle[b.blank]*a.puzzle[b.blank];
804  case kSquareRoot: return sqrt(a.puzzle[b.blank]);
805  case kSquarePlusOneRoot: return sqrt(1+a.puzzle[b.blank]*a.puzzle[b.blank]);
806  }
807 // if (weighted)
808 // return a.puzzle[b.blank]*a.puzzle[b.blank];
810  return 1;
811 }
812 
813 template <int width, int height>
814 void MNPuzzle<width, height>::SetPattern(const std::vector<int> &pattern)
815 {
816  for (int x = 0; x < width*height; x++)
817  this->pattern[x] = false;
818  for (int i : pattern)
819  this->pattern[i] = true;
820 }
821 
822 template <int width, int height>
824 {
825  if (tile == -1)
826  return false;
827  return pattern[tile] == true;
828 }
829 
830 template <int width, int height>
832 {
833  switch (d)
834  {
835  case kLeft: return InPattern(s.puzzle[s.blank-1])?GCost(s,d):0;
836  case kUp: return InPattern(s.puzzle[s.blank-width])?GCost(s,d):0;
837  case kDown: return InPattern(s.puzzle[s.blank+width])?GCost(s,d):0;
838  case kRight: return InPattern(s.puzzle[s.blank+1])?GCost(s,d):0;
839  case kNoSlide: assert(false);
840  }
841  return 0;
842 }
843 
844 template <int width, int height>
846 {
847  switch (weight)
848  {
849  case kUnitWeight: return 1;
850  case kUnitPlusFrac:
851  {
852  switch (d)
853  {
854  case kLeft: return 1.0+1.0/(1.0+s.puzzle[s.blank-1]);
855  case kUp: return 1.0+1.0/(1.0+s.puzzle[s.blank-width]);
856  case kDown: return 1.0+1.0/(1.0+s.puzzle[s.blank+width]);
857  case kRight: return 1.0+1.0/(1.0+s.puzzle[s.blank+1]);
858  }
859  }
860  case kSquared:
861  {
862  switch (d)
863  {
864  case kLeft: return s.puzzle[s.blank-1]*s.puzzle[s.blank-1];
865  case kUp: return s.puzzle[s.blank-width]*s.puzzle[s.blank-width];
866  case kDown: return s.puzzle[s.blank+width]*s.puzzle[s.blank+width];
867  case kRight: return s.puzzle[s.blank+1]*s.puzzle[s.blank+1];
868  }
869  }
870  case kSquareRoot:
871  {
872  switch (d)
873  {
874  case kLeft: return sqrt(s.puzzle[s.blank-1]);
875  case kUp: return sqrt(s.puzzle[s.blank-width]);
876  case kDown: return sqrt(s.puzzle[s.blank+width]);
877  case kRight: return sqrt(s.puzzle[s.blank+1]);
878  }
879  }
880  case kSquarePlusOneRoot:
881  {
882  switch (d)
883  {
884  case kLeft: return sqrt(1+s.puzzle[s.blank-1]*s.puzzle[s.blank-1]);
885  case kUp: return sqrt(1+s.puzzle[s.blank-width]*s.puzzle[s.blank-width]);
886  case kDown: return sqrt(1+s.puzzle[s.blank+width]*s.puzzle[s.blank+width]);
887  case kRight: return sqrt(1+s.puzzle[s.blank+1]*s.puzzle[s.blank+1]);
888  }
889  }
890  }
891 
892  assert(!"Illegal move");
893  return 1;
894 }
895 
896 
897 template <int width, int height>
899 {
900  return (state == theGoal);
901 }
902 
903 template <int width, int height>
905 {
906  switch (act)
907  {
908  case kUp: return 0;
909  case kDown: return 1;
910  case kRight: return 2;
911  case kLeft: return 3;
912  }
913  return 4;
914 }
915 
916 template <int width, int height>
918  int count, const std::vector<int> &pattern,
919  std::vector<int> &dual)
920 {
921  uint64_t hashVal = hash;
922  dual.resize(pattern.size());
923 
924  int numEntriesLeft = count-pattern.size()+1;
925  for (int x = pattern.size()-1; x >= 0; x--)
926  {
927  dual[x] = hashVal%numEntriesLeft;
928  hashVal /= numEntriesLeft;
929  numEntriesLeft++;
930  for (int y = x+1; y < pattern.size(); y++)
931  {
932  if (dual[y] >= dual[x])
933  dual[y]++;
934  }
935  }
936  s.puzzle.resize(count);
937  std::fill(s.puzzle.begin(), s.puzzle.end(), -1);
938  for (int x = 0; x < dual.size(); x++)
939  {
940  s.puzzle[dual[x]] = pattern[x];
941  if (pattern[x] == 0)
942  s.blank = dual[x];
943  }
944 }
945 
946 
947 template <int width, int height>
949 {
950 }
951 
952 void DrawTile(float x, float y, char c1, char c2, int w, int h);
953 void DrawFrame(int w, int h);
954 
955 template <int width, int height>
957 {
958  float squareSize = std::max(width, height)+1;
959  squareSize = 2.0f/squareSize;
960  float xOrigin = (0-((float)width)/2.0f)*squareSize;
961  float yOrigin = (0-((float)height)/2.0f)*squareSize;
962  char txt[10];
963  display.FillRect({xOrigin, yOrigin, xOrigin+(width)*squareSize, yOrigin+(height)*squareSize}, Colors::gray);
964  display.FrameRect({xOrigin, yOrigin, xOrigin+(width)*squareSize, yOrigin+(height)*squareSize}, Colors::lightgray, 0.04*squareSize);
965  for (unsigned int y = 0; y < height; y++)
966  {
967  for (unsigned int x = 0; x < width; x++)
968  {
969  if (s.puzzle[x+y*width] != 0)
970  {
971  sprintf(txt, "%d", s.puzzle[x+y*width]);
972  display.FillRect({xOrigin+x*squareSize, yOrigin+y*squareSize, xOrigin+(x+1)*squareSize, yOrigin+(y+1)*squareSize}, Colors::white);
973  display.FrameRect({xOrigin+x*squareSize, yOrigin+y*squareSize, xOrigin+(x+1)*squareSize, yOrigin+(y+1)*squareSize}, Colors::darkblue, 0.01*squareSize);
974  if (s.puzzle[x+y*width] > 0)
975  display.DrawText(txt,
976  {xOrigin+x*squareSize+squareSize/2.f, yOrigin+y*squareSize+squareSize/2.f},
978  }
979  }
980  }
981 }
982 
983 template <int width, int height>
985 {
986  int hitx=-1, hity=-1;
987  // Find which location was hit
988  {
989  float squareSize = std::max(width, height)+1;
990  squareSize = 2.0f/squareSize;
991  float xOrigin = (0-((float)width)/2.0f)*squareSize;
992  float yOrigin = (0-((float)height)/2.0f)*squareSize;
993  char txt[10];
994  for (unsigned int y = 0; y < height; y++)
995  {
996  for (unsigned int x = 0; x < width; x++)
997  {
998  if (s.puzzle[x+y*width] != 0)
999  {
1000  Graphics::rect r = {xOrigin+x*squareSize, yOrigin+y*squareSize, xOrigin+(x+1)*squareSize, yOrigin+(y+1)*squareSize};
1001  if (Graphics::PointInRect(p, r))
1002  {
1003  hitx = x;
1004  hity = y;
1005  break;
1006  }
1007  }
1008  }
1009  }
1010  }
1011  if (hitx == -1 || hity == -1)
1012  return kNoSlide;
1013 
1014  int x = hitx, y = hity;
1015  if (s.puzzle[x+y*width] == 0)
1016  return kNoSlide;
1017  std::vector<slideDir> acts;
1018  GetActions(s, acts);
1019  auto tmp = s;
1020  for (auto a : acts)
1021  {
1022  ApplyAction(tmp, a);
1023  // If an action makes the place we clicked to be blank, that is the action we want
1024  if (tmp.puzzle[x+y*width] == 0)
1025  {
1026  return a;
1027  }
1028  this->UndoAction(tmp, a);
1029  }
1030  return kNoSlide;
1031 }
1032 
1033 
1034 template <int width, int height>
1036 {
1037  float squareSize = std::max(width, height)+1;
1038  squareSize = 2.0f/squareSize;
1039  float xOrigin = (0-((float)width)/2.0f)*squareSize;
1040  float yOrigin = (0-((float)height)/2.0f)*squareSize;
1041  char txt[10];
1042  display.FillRect({xOrigin, yOrigin, xOrigin+(width)*squareSize, yOrigin+(height)*squareSize}, Colors::gray);
1043  display.FrameRect({xOrigin, yOrigin, xOrigin+(width)*squareSize, yOrigin+(height)*squareSize}, Colors::lightgray, 0.04*squareSize);
1044  for (unsigned int y = 0; y < height; y++)
1045  {
1046  for (unsigned int x = 0; x < width; x++)
1047  {
1048  if (s1.puzzle[x+y*width] == s2.puzzle[x+y*width])
1049  {
1050  if (s1.puzzle[x+y*width] != 0)
1051  {
1052  sprintf(txt, "%d", s1.puzzle[x+y*width]);
1053  display.FillRect({xOrigin+x*squareSize, yOrigin+y*squareSize, xOrigin+(x+1)*squareSize, yOrigin+(y+1)*squareSize}, Colors::white);
1054  display.FrameRect({xOrigin+x*squareSize, yOrigin+y*squareSize, xOrigin+(x+1)*squareSize, yOrigin+(y+1)*squareSize}, Colors::darkblue, 0.01*squareSize);
1055  if (s1.puzzle[x+y*width] > 0)
1056  display.DrawText(txt, {xOrigin+x*squareSize+squareSize/2.f, yOrigin+y*squareSize+squareSize/2.f}, Colors::blue, squareSize/2.0f, Graphics::textAlignCenter, Graphics::textBaselineMiddle);
1057  }
1058  }
1059  else if (s1.puzzle[x+y*width] != 0)
1060  {
1061  Graphics::point p1 = {xOrigin+x*squareSize, yOrigin+y*squareSize};
1062  Graphics::point p2;
1063  switch (GetAction(s1, s2))
1064  {
1065  case kUp:
1066  p2 = {xOrigin+x*squareSize, yOrigin+(y+1)*squareSize};
1067  break;
1068  case kDown:
1069  p2 = {xOrigin+x*squareSize, yOrigin+(y-1)*squareSize};
1070  break;
1071  case kLeft:
1072  p2 = {xOrigin+(x+1)*squareSize, yOrigin+(y)*squareSize};
1073  break;
1074  case kRight:
1075  p2 = {xOrigin+(x-1)*squareSize, yOrigin+(y)*squareSize};
1076  break;
1077 
1078  default: assert(!"action not found");
1079  }
1080  sprintf(txt, "%d", s1.puzzle[x+y*width]);
1081  display.FillRect({p1.x*v+p2.x*(1-v), p1.y*v+p2.y*(1-v), p1.x*v+p2.x*(1-v)+squareSize, p1.y*v+p2.y*(1-v)+squareSize}, Colors::white);
1082  display.FrameRect({p1.x*v+p2.x*(1-v), p1.y*v+p2.y*(1-v), p1.x*v+p2.x*(1-v)+squareSize, p1.y*v+p2.y*(1-v)+squareSize}, Colors::darkblue, 0.01*squareSize);
1083 
1084  if (s1.puzzle[x+y*width] > 0)
1085  display.DrawText(txt, {p1.x*v+p2.x*(1-v)+squareSize/2.f, p1.y*v+p2.y*(1-v)+squareSize/2.f}, Colors::blue, squareSize/2.0f, Graphics::textAlignCenter, Graphics::textBaselineMiddle);
1086  }
1087  }
1088  }
1089 }
1090 
1091 
1092 template <int width, int height>
1094 {
1095  glEnable(GL_LINE_SMOOTH);
1096  for (unsigned int y = 0; y < height; y++)
1097  {
1098  for (unsigned int x = 0; x < width; x++)
1099  {
1100  char c1=0, c2=0;
1101  if (s.puzzle[x+y*width] > 9)
1102  c1 = '0'+(((s.puzzle[x+y*width])/10)%10);
1103  if (s.puzzle[x+y*width] > 0)
1104  c2 = '0'+((s.puzzle[x+y*width])%10);
1105  if (s.puzzle[x+y*width] == -1)
1106  c1 = ' ';
1107  DrawTile(x, y, c1, c2, width, height);
1108  }
1109  }
1111 }
1112 
1113 template <int width, int height>
1115 {
1116  glEnable(GL_LINE_SMOOTH);
1117  for (unsigned int y = 0; y < height; y++)
1118  {
1119  for (unsigned int x = 0; x < width; x++)
1120  {
1121  char c1=0, c2=0;
1122  if (s2.puzzle[x+y*width] > 9)
1123  c1 = '0'+(((s2.puzzle[x+y*width])/10)%10);
1124  if (s2.puzzle[x+y*width] > 0)
1125  c2 = '0'+((s2.puzzle[x+y*width])%10);
1126  if (s2.puzzle[x+y*width] == -1)
1127  c1 = ' ';
1128 
1129  if (s1.puzzle[x+y*width] == s2.puzzle[x+y*width])
1130  {
1131  DrawTile(x, y, c1, c2, width, height);
1132  }
1133  else {
1134  switch (GetAction(s1, s2))
1135  {
1136  case kUp: DrawTile(x, (y-1)*v + (y)*(1-v), c1, c2, width, height); break;
1137  case kDown: DrawTile(x, (y+1)*v + (y)*(1-v), c1, c2, width, height); break;
1138  case kLeft: DrawTile((x)*(1-v)+(x-1)*v, y, c1, c2, width, height); break;
1139  case kRight: DrawTile((x+1)*v+(x)*(1-v), y, c1, c2, width, height); break;
1140  default: assert(!"action not found");
1141  }
1142  }
1143  }
1144  }
1146 }
1147 
1169 template <int width, int height>
1170 int MNPuzzle<width, height>::read_in_mn_puzzles(const char *filename, bool puzz_num_start, unsigned int max_puzzles,
1171  std::vector<MNPuzzleState<width, height>> &puzzles)
1172 {
1173 
1174  std::vector<std::vector<int> > permutations;
1175  PermutationPuzzle::PermutationPuzzleEnvironment<MNPuzzleState<width, height>, slideDir>::Read_In_Permutations(filename, width*height, max_puzzles, permutations, puzz_num_start);
1176 
1177  // convert permutations into MNPuzzleStates
1178  for (unsigned i = 0; i < permutations.size(); i++)
1179  {
1180  MNPuzzleState<width, height> new_state;
1181 
1182  for (unsigned j = 0; j < width*height; j++)
1183  {
1184  new_state.puzzle[j] = permutations[i][j];
1185  if (new_state.puzzle[j] == 0)
1186  new_state.blank = j;
1187  }
1188  puzzles.push_back(new_state);
1189  }
1190  return 0;
1191 }
1192 
1193 template <int width, int height>
1195 :GraphDistanceHeuristic(graph), puzzle(mnp)
1196 {
1197  for (int x = 0; x < count /*10*/; x++)
1198  {
1199  AddHeuristic();
1200  }
1201 }
1202 
1203 template <int width, int height>
1205 {
1206  MNPuzzleState<3, 3> a, b;
1207  puzzle.GetStateFromHash(a, state1);
1208  puzzle.GetStateFromHash(b, state2);
1209  double val = puzzle.HCost(a, b);
1210 
1211  for (unsigned int i=0; i < heuristics.size(); i++)
1212  {
1213  double hval = heuristics[i][state1]-heuristics[i][state2];
1214  if (hval < 0)
1215  hval = -hval;
1216  if (fgreater(hval,val))
1217  val = hval;
1218  }
1219 
1220  return val;
1221 }
1222 
1223 
1228 template <int width, int height>
1230 {
1232  std::vector<int> permutation = PermutationPuzzle::PermutationPuzzleEnvironment<MNPuzzleState<width, height>, slideDir>::Get_Random_Permutation(width*height);
1233 
1234  for (unsigned i = 0; i < permutation.size(); i++)
1235  {
1236  new_puzz.puzzle[i] = permutation[i];
1237  if (permutation[i] == 0)
1238  new_puzz.blank = i;
1239  }
1240 
1241  return new_puzz;
1242 }
1243 
1244 template <int width, int height>
1246 {
1247 // s.puzzle.resize(width*height);
1248  int count = width*height;
1249  int countm2 = width*height-2;
1250  uint64_t hashVal = hash;
1251  std::vector<int> dual(width*height-2);
1252 
1253  // unrank the locations of the first 10 tiles
1254  int numEntriesLeft = count-countm2+1;
1255  for (int x = countm2-1; x >= 0; x--)
1256  {
1257  dual[x] = hashVal%numEntriesLeft;
1258  hashVal /= numEntriesLeft;
1259  numEntriesLeft++;
1260  for (int y = x+1; y < countm2; y++)
1261  {
1262  if (dual[y] >= dual[x])
1263  dual[y]++;
1264  }
1265  }
1266  // clear puzzle locations
1267  for (int x = 0; x < count; x++)
1268  {
1269  s.puzzle[x] = -1;
1270  }
1271  // revert locations of tiles into positions in the puzzle
1272  for (int x = 0; x < countm2; x++)
1273  {
1274  s.puzzle[dual[x]] = x;
1275  }
1276  // reset the cache of the blanks location
1277  s.blank = dual[0];
1278 
1279  // now find the two -1's and assign them
1280  // to ensure the right parity
1281  int x = 0;
1282  int loc1 = -1, loc2 = -1;
1283  for (; x < count; x++)
1284  {
1285  if (s.puzzle[x] == -1)
1286  {
1287  loc1 = x;
1288  x++;
1289  break;
1290  }
1291  }
1292  for (; x < count; x++)
1293  {
1294  if (s.puzzle[x] == -1)
1295  {
1296  loc2 = x;
1297  break;
1298  }
1299  }
1300  assert(loc1 != -1 && loc2 != -1);
1301  // Choose an arbitrary ordering and then
1302  // check the parity. If it's wrong, we just
1303  // swap them and are guaranteed to get the right
1304  // parity.
1305  s.puzzle[loc1] = countm2;
1306  s.puzzle[loc2] = countm2+1;
1307  if (IsGoalStored())
1308  {
1309  if (GetParity(s) != MNPuzzle<width, height>::GetParity(goal))
1310  {
1311  s.puzzle[loc1] = countm2+1;
1312  s.puzzle[loc2] = countm2;
1313  }
1314  }
1315  else if (GetParity(s) == 1)
1316  {
1317  s.puzzle[loc1] = countm2+1;
1318  s.puzzle[loc2] = countm2;
1319  }
1320 }
1321 
1322 //uint64_t Factorial(int val)
1323 //{
1324 // static uint64_t table[21] =
1325 // { 1ll, 1ll, 2ll, 6ll, 24ll, 120ll, 720ll, 5040ll, 40320ll, 362880ll, 3628800ll, 39916800ll, 479001600ll,
1326 // 6227020800ll, 87178291200ll, 1307674368000ll, 20922789888000ll, 355687428096000ll,
1327 // 6402373705728000ll, 121645100408832000ll, 2432902008176640000ll };
1328 // if (val > 20)
1329 // return (uint64_t)-1;
1330 // return table[val];
1331 //}
1332 
1333 template <int width, int height>
1335 {
1336  std::array<int, width*height-2> locs;// We only rank n-2 of n items; last two are fixed by the parity
1337  std::array<int, width*height> dual;
1338 
1339  // build the representation containing the item locations
1340  for (unsigned int x = 0; x < width*height; x++)
1341  {
1342  dual[s.puzzle[x]] = x;
1343  }
1344  // build an array with the locations of the first 10 items
1345  for (int x = 0; x < width*height-2; x++)
1346  {
1347  locs[x] = dual[x];
1348  }
1349 
1350  uint64_t hashVal = 0;
1351  int numEntriesLeft = width*height;
1352 
1353  // compute the lexographical ranking of the locations
1354  // of the first 10 tiles
1355  for (unsigned int x = 0; x < width*height-2; x++)
1356  {
1358  numEntriesLeft--;
1359 
1360  // decrement locations of remaining items
1361  // to keep the numbering compact
1362  for (unsigned y = x; y < width*height-2; y++)
1363  {
1364  if (locs[y] > locs[x])
1365  locs[y]--;
1366  }
1367  }
1368  return hashVal;
1369 }
1370 
1371 template <int width, int height>
1373 {
1374  int val = width*height;
1376 }
1377 
1378 
1379 // if q is odd, the invariant is the parity (odd or even) of the number of pairs of pieces in reverse order (the parity of the permutation). For the order of the 15 pieces consider line 2 after line 1, etc., like words on a page.
1380 // if q is even, the invariant is the parity of the number of pairs of pieces in reverse order plus the row number of the empty square counting from bottom and starting from 0.
1381 template <int width, int height>
1383 {
1384  unsigned swaps = 0; // counts number of swaps
1385  for (unsigned x = 0; x < width*height; x++)
1386  {
1387  if (state.puzzle[x] == 0) // skip blank
1388  continue;
1389  for (unsigned y = x + 1; y < width*height; y++)
1390  {
1391  if (state.puzzle[y] == 0) // skip blank
1392  continue;
1393  if (state.puzzle[y] < state.puzzle[x])
1394  swaps++;
1395  }
1396  }
1397  // if odd num of columns
1398  if ((width % 2) == 1)
1399  {
1400  return swaps % 2;
1401  }
1402 
1403  // if even num of columns
1404  return (swaps + (width*height-state.blank-1)/width)%2;
1405 }
1406 
1407 template <int width, int height>
1409 {
1410  std::map<uint64_t, uint64_t> puzzle_map; // used to ensure uniqueness
1411 
1412  MNPuzzle my_puzz(width, height);
1413 
1414  unsigned count = 0;
1415  unsigned goal_parity = GetParity(goal);
1416 
1417  while (count < num_puzzles)
1418  {
1419  MNPuzzleState<width, height> next = Generate_Random_Puzzle(width, height);
1420  uint64_t next_hash = my_puzz.GetStateHash(next);
1421 
1422  if (puzzle_map.find(next_hash) != puzzle_map.end())
1423  {
1424  continue;
1425  }
1426 
1427  // checks parity to make sure problem is solvable
1428  if (GetParity(next) == goal_parity)
1429  {
1430  puzzle_map[next_hash] = next_hash;
1431  puzzle_vector.push_back(next);
1432  count++;
1433  }
1434 
1435  }
1436 }
1437 
1438 template <int width, int height>
1440 {
1441 // if (to_check.size() != width*height)
1442 // return false;
1443 //
1444 // if (to_check.width != width)
1445 // return false;
1446 //
1447 // if (to_check.height != width)
1448 // return false;
1449 
1450  if (to_check.blank >= width*height)
1451  return false;
1452 
1453  if (to_check.puzzle[to_check.blank] != 0)
1454  return false;
1455 
1456  return true;
1457 }
1458 
1459 template <int width, int height>
1460 std::vector<slideDir> MNPuzzle<width, height>::Get_Op_Order_From_Hash(int order_num)
1461 {
1462  std::vector<slideDir> ops;
1463  assert(order_num <= 23);
1464  assert(order_num >= 0);
1465 
1466 
1467  std::vector<int> op_nums(4);
1468 
1469  int num_left = 1;
1470  for (int x = 3; x >= 0; x--)
1471  {
1472  op_nums[x] = order_num % num_left;
1473  order_num /= num_left;
1474  num_left++;
1475 
1476  for (int y = x+1; y < 4; y++)
1477  {
1478  if (op_nums[y] >= op_nums[x])
1479  {
1480  op_nums[y]++;
1481  }
1482  }
1483  }
1484 
1485  bool up_act = false;
1486  bool down_act = false;
1487  bool left_act = false;
1488  bool right_act = false;
1489 
1490  printf("Op order: ");
1491  for (unsigned i = 0; i < 4; i++)
1492  {
1493  if (op_nums[i] == 0)
1494  {
1495  printf("Up ");
1496  ops.push_back(kUp);
1497  up_act = true;
1498  }
1499  else if (op_nums[i] == 1)
1500  {
1501  printf("Left ");
1502  ops.push_back(kLeft);
1503  left_act = true;
1504  }
1505  else if (op_nums[i] == 2)
1506  {
1507  printf("Right ");
1508  ops.push_back(kRight);
1509  right_act = true;
1510  }
1511  else if (op_nums[i] == 3)
1512  {
1513  printf("Down ");
1514  ops.push_back(kDown);
1515  down_act = true;
1516  }
1517  }
1518  printf("\n");
1519 
1520  assert(up_act);
1521  assert(left_act);
1522  assert(right_act);
1523  assert(down_act);
1524 
1525  return ops;
1526 }
1527 
1528 
1529 
1530 #endif
MNPuzzle
Definition: MNPuzzle.h:137
Graph::AddNode
int AddNode(node *)
Definition: Graph.cpp:136
DrawFrame
void DrawFrame(int w, int h)
Definition: MNPuzzle.cpp:48
Graphics::point
Definition: Graphics.h:32
kSquareRoot
@ kSquareRoot
Definition: MNPuzzle.h:131
Graphics::point::y
float y
Definition: Graphics.h:36
MNPuzzle::Get_Op_Order
std::vector< slideDir > Get_Op_Order()
Definition: MNPuzzle.h:230
GraphDistanceHeuristic::AddHeuristic
void AddHeuristic(node *n=0)
Definition: GraphEnvironment.cpp:1564
UnitSimulation.h
kRight
@ kRight
Definition: MNPuzzle.h:85
Graph.h
MNPuzzle::GetName
virtual const std::string GetName()
Definition: MNPuzzle.h:374
operator!=
static bool operator!=(const MNPuzzleState< width, height > &l1, const MNPuzzleState< width, height > &l2)
Definition: MNPuzzle.h:123
node::SetLabelF
void SetLabelF(unsigned int index, double val) const
Definition: Graph.cpp:687
GraphPuzzleDistanceHeuristic::HCost
double HCost(const graphState &state1, const graphState &state2) const
Definition: MNPuzzle.h:1204
MNPuzzle::Change_Op_Order
void Change_Op_Order(const std::vector< slideDir > op_order)
Changes the ordering of operators to the new inputted order.
Definition: MNPuzzle.h:297
GraphPuzzleDistanceHeuristic
Definition: MNPuzzle.h:261
Graph::FindEdge
edge * FindEdge(unsigned int from, unsigned int to)
Finds an edge between nodes with ids from and to, no matter which direction.
Definition: Graph.cpp:230
graphState
unsigned long graphState
Definition: GraphEnvironment.h:32
MNPuzzle::AdditiveGCost
double AdditiveGCost(const MNPuzzleState< width, height > &, const slideDir &) const
Definition: MNPuzzle.h:831
MNPuzzle::Generate_Random_Puzzle
static MNPuzzleState< width, height > Generate_Random_Puzzle()
Randomly generates a puzzle of the specified dimensions and returns that puzzle.
Definition: MNPuzzle.h:1229
MNPuzzle::SetPattern
void SetPattern(const std::vector< int > &pattern)
Definition: MNPuzzle.h:814
kUp
@ kUp
Definition: MNPuzzle.h:85
kUnitPlusFrac
@ kUnitPlusFrac
Definition: MNPuzzle.h:133
MNPuzzle::GetWeighted
puzzleWeight GetWeighted() const
Definition: MNPuzzle.h:143
d
mcData d[]
Definition: MotionCaptureMovement.cpp:21
Factorial
uint64_t Factorial(int n)
Definition: RubiksCube7Edges.cpp:335
MNPuzzle::GetSuccessors
void GetSuccessors(const MNPuzzleState< width, height > &stateID, std::vector< MNPuzzleState< width, height >> &neighbors) const
Definition: MNPuzzle.h:551
Graph::AddEdge
void AddEdge(edge *)
Definition: Graph.cpp:170
MNPuzzle::Draw
void Draw(Graphics::Display &display, const MNPuzzleState< width, height > &) const
Definition: MNPuzzle.h:956
GraphDistanceHeuristic
Definition: GraphEnvironment.h:222
Graphics::rect
Definition: Graphics.h:94
MNPuzzleState::puzzle
std::array< int, width *height > puzzle
Definition: MNPuzzle.h:58
MNPuzzle::GetMaxStateHash
uint64_t GetMaxStateHash() const
Definition: MNPuzzle.h:1372
width
int width
Definition: SFML_HOG.cpp:54
Colors::darkblue
const rgbColor darkblue
Definition: Colors.h:143
MNPuzzle::goal_stored
bool goal_stored
Definition: MNPuzzle.h:251
GraphSearchConstants::kXCoordinate
@ kXCoordinate
Definition: GraphEnvironment.h:51
MNPuzzle::use_manhattan
bool use_manhattan
Definition: MNPuzzle.h:252
MNPuzzle::GetOccupancyInfo
OccupancyInterface< MNPuzzleState< width, height >, slideDir > * GetOccupancyInfo()
Definition: MNPuzzle.h:152
Graph
A generic Graph class.
Definition: Graph.h:66
MNPuzzle::read_in_mn_puzzles
static int read_in_mn_puzzles(const char *filename, bool first_counter, unsigned max_puzzles, std::vector< MNPuzzleState< width, height >> &puzzle_vector)
Reads in the the desired number of puzzles from the given filename with the given dimensions and stor...
Definition: MNPuzzle.h:1170
MNPuzzle::ApplyAction
void ApplyAction(MNPuzzleState< width, height > &s, slideDir a) const
Definition: MNPuzzle.h:592
Graph::GetNode
node * GetNode(unsigned long num)
Definition: Graph.cpp:152
MNPuzzle::InPattern
bool InPattern(int tile) const
Definition: MNPuzzle.h:823
operator==
static bool operator==(const MNPuzzleState< width, height > &l1, const MNPuzzleState< width, height > &l2)
Definition: MNPuzzle.h:111
Graphics::textBaselineMiddle
@ textBaselineMiddle
Definition: Graphics.h:27
Graphics::PointInRect
bool PointInRect(const point &p, const rect &r)
Definition: Graphics.cpp:17
MNPuzzle::InvertAction
bool InvertAction(slideDir &a) const
Definition: MNPuzzle.h:658
GetStateFromHash
void GetStateFromHash(uint64_t hash, int *pieces, int count)
Definition: LexPermutationPDB.h:123
MNPuzzleState::operator<
bool operator<(const MNPuzzleState &b)
Definition: MNPuzzle.h:49
loc
Definition: MapGenerators.cpp:296
PermutationPuzzleEnvironment.h
MNPuzzleState::blank
unsigned int blank
Definition: MNPuzzle.h:57
kNoSlide
@ kNoSlide
Definition: MNPuzzle.h:85
kUnitWeight
@ kUnitWeight
Definition: MNPuzzle.h:129
MNPuzzle::IsGoalStored
bool IsGoalStored() const
Definition: MNPuzzle.h:196
MNPuzzle::State_Check
bool State_Check(const MNPuzzleState< width, height > &to_check)
Checks that the given state is a valid state for this domain.
Definition: MNPuzzle.h:1439
costs
Definition: FringeSearch.h:15
MNPuzzle::GetStateFromHash
virtual void GetStateFromHash(MNPuzzleState< width, height > &s, uint64_t hash) const
Definition: MNPuzzle.h:1245
slideDir
slideDir
Note, direction "kLeft" indicates that the blank is being moved to the left.
Definition: MNPuzzle.h:84
GraphPuzzleDistanceHeuristic::GraphPuzzleDistanceHeuristic
GraphPuzzleDistanceHeuristic(MNPuzzle< width, height > &mnp, Graph *graph, int count)
Definition: MNPuzzle.h:1194
point3d
#define point3d
Definition: GLUtil.h:123
Graphics::Display
Definition: Graphics.h:146
operator<<
static std::ostream & operator<<(std::ostream &out, const MNPuzzleState< width, height > &loc)
Definition: MNPuzzle.h:89
MNPuzzle::GetActions
void GetActions(const MNPuzzleState< width, height > &stateID, std::vector< slideDir > &actions) const
Definition: MNPuzzle.h:564
MNPuzzle::OpenGLDraw
void OpenGLDraw(const MNPuzzleState< width, height > &, const slideDir &) const
Definition: MNPuzzle.h:176
kLeft
@ kLeft
Definition: MNPuzzle.h:85
MNPuzzle::GetActionHash
uint64_t GetActionHash(slideDir act) const
Definition: MNPuzzle.h:904
MNPuzzle::OpenGLDraw
void OpenGLDraw() const
Definition: MNPuzzle.h:948
MNPuzzle::GetAction
slideDir GetAction(const MNPuzzleState< width, height > &s1, const MNPuzzleState< width, height > &s2) const
Definition: MNPuzzle.h:574
PermutationPuzzle::PermutationPuzzleEnvironment
Note, assumes that state has a public vector<int> called puzzle in which the permutation is held.
Definition: PermutationPuzzleEnvironment.h:26
height
int height
Definition: SFML_HOG.cpp:54
MNPuzzle::~MNPuzzle
~MNPuzzle()
Definition: MNPuzzle.h:291
MNPuzzle::GCost
double GCost(const MNPuzzleState< width, height > &state1, const MNPuzzleState< width, height > &state2) const
Definition: MNPuzzle.h:793
GraphSearchConstants::kYCoordinate
@ kYCoordinate
Definition: GraphEnvironment.h:52
fgreater
bool fgreater(double a, double b)
Definition: FPUtil.h:29
max
#define max(a, b)
Definition: MinimalSectorAbstraction.cpp:40
MNPuzzleState::MNPuzzleState
MNPuzzleState()
Definition: MNPuzzle.h:27
MNPuzzle::Get_Num_Of_Columns
unsigned Get_Num_Of_Columns()
Definition: MNPuzzle.h:240
MNPuzzle::GoalTest
bool GoalTest(const MNPuzzleState< width, height > &state, const MNPuzzleState< width, height > &goal) const
Definition: MNPuzzle.h:898
kSquared
@ kSquared
Definition: MNPuzzle.h:130
Graphics::textAlignCenter
@ textAlignCenter
Definition: Graphics.h:20
MNPuzzle::Create_Random_MN_Puzzles
static void Create_Random_MN_Puzzles(MNPuzzleState< width, height > &goal, std::vector< MNPuzzleState< width, height >> &puzzle_vector, unsigned num_puzzles)
Creates num_puzzles random MN puzzles of the specified size and stores them in puzzle-vector.
Definition: MNPuzzle.h:1408
MNPuzzle::MNPuzzle
MNPuzzle()
Definition: MNPuzzle.h:272
MNPuzzle::Set_Use_Manhattan_Heuristic
void Set_Use_Manhattan_Heuristic(bool to_use)
Definition: MNPuzzle.h:243
std::hash< MNPuzzleState< w, h > >::operator()
std::size_t operator()(const MNPuzzleState< w, h > &k) const
Definition: MNPuzzle.h:67
MNPuzzleState::Reset
void Reset()
Definition: MNPuzzle.h:31
MNPuzzle::GetParity
static unsigned GetParity(const MNPuzzleState< width, height > &state)
Definition: MNPuzzle.h:1382
MNPuzzleState::FinishUnranking
void FinishUnranking()
Definition: MNPuzzle.h:38
kDown
@ kDown
Definition: MNPuzzle.h:85
MNPuzzle::weight
puzzleWeight weight
Definition: MNPuzzle.h:253
MNPuzzle::Get_Goal
MNPuzzleState< width, height > Get_Goal()
Returns stored goal state if it is stored.
Definition: MNPuzzle.h:184
Graphics::point::x
float x
Definition: Graphics.h:36
MNPuzzle::pattern
bool pattern[width *height]
Definition: MNPuzzle.h:245
std
Definition: CanonicalGraphEnvironment.h:26
Graphics::Display::FrameRect
void FrameRect(rect r, rgbColor c, float lineWidth)
Definition: Graphics.cpp:73
MNPuzzle::HCost
double HCost(const MNPuzzleState< width, height > &state1, const MNPuzzleState< width, height > &state2) const
Definition: MNPuzzle.h:677
puzzleWeight
puzzleWeight
Definition: MNPuzzle.h:128
MNPuzzle::DefaultH
double DefaultH(const MNPuzzleState< width, height > &s) const
Definition: MNPuzzle.h:756
Colors::gray
const rgbColor gray
Definition: Colors.h:121
MNPuzzle::GetStateFromPDBHash
void GetStateFromPDBHash(uint64_t hash, MNPuzzleState< width, height > &s, int count, const std::vector< int > &pattern, std::vector< int > &dual)
Definition: MNPuzzle.h:917
Colors::white
const rgbColor white
Definition: Colors.h:120
MNPuzzleState::size
size_t size() const
Definition: MNPuzzle.h:37
Colors::blue
const rgbColor blue
Definition: Colors.h:142
MNPuzzle::ClearGoal
void ClearGoal()
Definition: MNPuzzle.h:536
MNPuzzle::GetGraph
Graph * GetGraph()
Definition: MNPuzzle.h:417
MNPuzzle::operators
std::vector< std::vector< slideDir > > operators
Definition: MNPuzzle.h:249
MNPuzzle::GetStateHash
uint64_t GetStateHash(const MNPuzzleState< width, height > &s) const
Definition: MNPuzzle.h:1334
Graphics::Display::DrawText
void DrawText(const char *text, point location, rgbColor c, float height, const char *typeface=0)
Definition: Graphics.cpp:221
MNPuzzle::h_increment
std::vector< std::vector< unsigned > > h_increment
Definition: MNPuzzle.h:256
Colors::lightgray
const rgbColor lightgray
Definition: Colors.h:125
MNPuzzle::StoreGoal
void StoreGoal(MNPuzzleState< width, height > &)
Definition: MNPuzzle.h:476
GraphSearchConstants::kZCoordinate
@ kZCoordinate
Definition: GraphEnvironment.h:53
Graphics::Display::FillRect
void FillRect(rect r, rgbColor c)
Definition: Graphics.cpp:101
MNPuzzle::SetWeighted
void SetWeighted(puzzleWeight w)
Definition: MNPuzzle.h:142
MNPuzzle::goal
MNPuzzleState< width, height > goal
Definition: MNPuzzle.h:257
MNPuzzle::Get_Num_Of_Rows
unsigned Get_Num_Of_Rows()
Definition: MNPuzzle.h:241
MNPuzzle::ops_in_order
std::vector< slideDir > ops_in_order
Definition: MNPuzzle.h:250
GraphPuzzleDistanceHeuristic::puzzle
MNPuzzle< width, height > puzzle
Definition: MNPuzzle.h:266
node
Nodes to be stored within a Graph.
Definition: Graph.h:170
MNPuzzleState
Definition: MNPuzzle.h:25
SearchEnvironment.h
DrawTile
void DrawTile(float x, float y, char c1, char c2, int w, int h)
Definition: MNPuzzle.cpp:13
MNPuzzle::Get_Op_Order_From_Hash
static std::vector< slideDir > Get_Op_Order_From_Hash(int order_num)
Returns a possible ordering of the operators.
Definition: MNPuzzle.h:1460
GraphEnvironment.h
OccupancyInterface
Definition: OccupancyInterface.h:36
kSquarePlusOneRoot
@ kSquarePlusOneRoot
Definition: MNPuzzle.h:132
edge
Edge class for connections between node in a Graph.
Definition: Graph.h:129