HOG2
TOH.h
Go to the documentation of this file.
1 //
2 // TOH.hpp
3 // hog2 glut
4 //
5 // Created by Nathan Sturtevant on 10/20/15.
6 // Copyright © 2015 University of Denver. All rights reserved.
7 //
8 
9 #ifndef TOH_hpp
10 #define TOH_hpp
11 
12 #include <stdio.h>
13 #include <cstdint>
14 #include <math.h>
15 #include "SearchEnvironment.h"
16 #include "PDBHeuristic.h"
17 
18 struct TOHMove {
19  TOHMove(uint8_t s, uint8_t d) :source(s), dest(d) {}
20  TOHMove() {}
21  uint8_t source;
22  uint8_t dest;
23 };
24 
25 template <int numDisks>
26 struct TOHState {
28  {
29  for (int x = 0; x < 4; x++)
30  {
31  counts[x] = 0;
32  }
33  for (int x = 0; x < numDisks; x++)
34  {
35  disks[3][x] = numDisks-x;
36  }
37  counts[3] = numDisks;
38  }
39 
40  void Reset()
41  {
42  for (int x = 0; x < 4; x++)
43  {
44  counts[x] = 0;
45  }
46  for (int x = 0; x < numDisks; x++)
47  {
48  disks[3][x] = numDisks-x;
49  }
50  counts[3] = numDisks;
51  }
53  {
54  for (int x = 0; x < 4; x++)
55  {
56  counts[x] = 0;
57  }
58  for (int x = 0; x < numDisks; x++)
59  {
60  disks[0][x] = numDisks-x;
61  }
62  counts[0] = numDisks;
63  }
64 
65  int GetDiskCountOnPeg(int whichPeg) const
66  {
67  return counts[whichPeg];
68  }
69 
70  int GetDiskOnPeg(int whichPeg, int whichDisk) const
71  {
72  return disks[whichPeg][whichDisk];
73  }
74 
75  // if this is slow, we can add a "big" disk to every peg to
76  // avoid the "if" statement.
77  int GetSmallestDiskOnPeg(int whichPeg) const
78  {
79  int count = GetDiskCountOnPeg(whichPeg);
80  if (count == 0)
81  return numDisks+1;
82  return GetDiskOnPeg(whichPeg, count-1);
83  }
84 
85  uint8_t disks[4][numDisks];
86  uint8_t counts[4];
87 };
88 
89 template <int D>
90 static std::ostream &operator<<(std::ostream &out, const TOHState<D> &s)
91 {
92  for (int x = 0; x < 4; x++)
93  {
94  out << "(" << x << ") ";
95  for (int y = 0; y < s.GetDiskCountOnPeg(x); y++)
96  out << s.GetDiskOnPeg(x, y) << " ";
97  }
98  return out;
99 }
100 
101 template <int D>
102 static bool operator==(const TOHState<D> &l1, const TOHState<D> &l2) {
103  for (int x = 0; x < 4; x++)
104  {
105  if (l1.GetDiskCountOnPeg(x) != l2.GetDiskCountOnPeg(x))
106  return false;
107  for (int y = 0; y < l1.GetDiskCountOnPeg(x); y++)
108  {
109  if (l1.GetDiskOnPeg(x, y)!= l2.GetDiskOnPeg(x, y))
110  return false;
111  }
112  }
113  return true;
114 }
115 
116 template <int D>
117 static bool operator!=(const TOHState<D> &l1, const TOHState<D> &l2) {
118  return !(l1 == l2);
119 }
120 
121 static std::ostream &operator<<(std::ostream &out, const TOHMove &m)
122 {
123  out << "(" << +m.source << ", " << +m.dest << ")";
124  return out;
125 }
126 
127 static bool operator==(const TOHMove &m1, const TOHMove &m2) {
128  return m1.source == m2.source && m1.dest == m2.dest;
129 }
130 
131 
132 template <int disks>
133 class TOH : public SearchEnvironment<TOHState<disks>, TOHMove> {
134 public:
135  TOH() :pruneActions(false) {}
136  ~TOH() {}
137  void GetSuccessors(const TOHState<disks> &nodeID, std::vector<TOHState<disks>> &neighbors) const;
138  void GetActions(const TOHState<disks> &nodeID, std::vector<TOHMove> &actions) const;
139  void ApplyAction(TOHState<disks> &s, TOHMove a) const;
140  bool InvertAction(TOHMove &a) const;
141 
143  double HCost(const TOHState<disks> &node1, const TOHState<disks> &node2) const;
144  double GCost(const TOHState<disks> &node1, const TOHState<disks> &node2) const { return 1; }
145  double GCost(const TOHState<disks> &node, const TOHMove &act) const { return 1; }
146  bool GoalTest(const TOHState<disks> &node, const TOHState<disks> &goal) const;
147 
148  uint64_t GetStateHash(const TOHState<disks> &node) const;
149  void GetStateFromHash(uint64_t parent, TOHState<disks> &s) const;
150  uint64_t GetMaxHash() const { return (1ull)<<(disks*2ull); }
151  uint64_t GetNumStates(TOHState<disks> &s) const;
152  uint64_t GetActionHash(TOHMove act) const;
153 
154  std::string GetName() { return "TOH("+std::to_string(disks)+")"; }
155  void OpenGLDraw() const;
156  void OpenGLDraw(const TOHState<disks>&) const;
158  void OpenGLDraw(const TOHState<disks>&, const TOHState<disks>&, float) const;
159  void OpenGLDraw(const TOHState<disks>&, const TOHMove&) const;
160 
162 protected:
163 private:
164  // caches
165  mutable std::vector<TOHMove> acts;
167 
168 };
169 
170 
171 
172 template <int disks>
173 void TOH<disks>::GetSuccessors(const TOHState<disks> &nodeID, std::vector<TOHState<disks>> &neighbors) const
174 {
175  neighbors.resize(0);
176  GetActions(nodeID, acts);
177  for (auto act : acts)
178  {
179  this->GetNextState(nodeID, act, tmp);
180  neighbors.push_back(tmp);
181  }
182 }
183 
184 template <int disks>
185 void TOH<disks>::GetActions(const TOHState<disks> &s, std::vector<TOHMove> &actions) const
186 {
187  bool goalOrdered = false;
188  if (pruneActions)
189  {
190  goalOrdered = true;
191  for (int x = 0; x < s.GetDiskCountOnPeg(3); x++)
192  {
193  if (s.GetDiskOnPeg(3, x) != disks-x)
194  {
195  goalOrdered = false;
196  break;
197  }
198  }
199  }
200 
201  actions.resize(0);
203  {
204  if (s.GetDiskCountOnPeg(0) > 0)
205  actions.push_back(TOHMove(0, 1));
206  }
207  else {
208  if (s.GetDiskCountOnPeg(1) > 0)
209  actions.push_back(TOHMove(1, 0));
210  }
212  {
213  if (s.GetDiskCountOnPeg(0) > 0)
214  actions.push_back(TOHMove(0, 2));
215  }
216  else {
217  if (s.GetDiskCountOnPeg(2) > 0)
218  actions.push_back(TOHMove(2, 0));
219  }
220 
222  {
223  if (s.GetDiskCountOnPeg(0) > 0)
224  actions.push_back(TOHMove(0, 3));
225  }
226  else {
227  if (s.GetDiskCountOnPeg(3) > 0 && !goalOrdered)
228  actions.push_back(TOHMove(3, 0));
229  }
231  {
232  if (s.GetDiskCountOnPeg(1) > 0)
233  actions.push_back(TOHMove(1, 2));
234  }
235  else {
236  if (s.GetDiskCountOnPeg(2) > 0)
237  actions.push_back(TOHMove(2, 1));
238  }
240  {
241  if (s.GetDiskCountOnPeg(1) > 0)
242  actions.push_back(TOHMove(1, 3));
243  }
244  else {
245  if (s.GetDiskCountOnPeg(3) > 0 && !goalOrdered)
246  actions.push_back(TOHMove(3, 1));
247  }
249  {
250  if (s.GetDiskCountOnPeg(2) > 0)
251  actions.push_back(TOHMove(2, 3));
252  }
253  else {
254  if (s.GetDiskCountOnPeg(3) > 0 && !goalOrdered)
255  actions.push_back(TOHMove(3, 2));
256  }
257 }
258 
259 
260 template <int disks>
262 {
263  s.disks[m.dest][s.counts[m.dest]] = s.disks[m.source][s.counts[m.source]-1];
264  s.counts[m.dest]++;
265  s.counts[m.source]--;
266 }
267 
268 template <int disks>
270 {
271  uint8_t tmp = a.source;
272  a.source = a.dest;
273  a.dest = tmp;
274  return true;
275 }
276 
277 
279 template <int disks>
280 double TOH<disks>::HCost(const TOHState<disks> &node1, const TOHState<disks> &node2) const
281 {
282  // NOTE: this is using the standard goal state; arbitrary goal states
283  // are more expensive to check
284  return disks - node1.GetDiskCountOnPeg(3);
285 }
286 
287 template <int disks>
289 {
290  // NOTE: this is using the standard goal state; arbitrary goal states
291  // are more expensive to check
292  return (node == goal);
293  //return (node.GetDiskCountOnPeg(3)==disks);
294 }
295 
296 
297 template <int disks>
299 {
300  uint64_t hash = 0;
301  for (int x = 0; x < 4; x++)
302  {
303  for (int y = 0; y < node.GetDiskCountOnPeg(x); y++)
304  {
305  hash |= (uint64_t(x)<<(2*(node.GetDiskOnPeg(x, y)-1)));
306  }
307  }
308  return hash;
309 }
310 
311 template <int disks>
313 {
314  return 1ull<<(2*disks);
315 }
316 
317 template <int disks>
318 void TOH<disks>::GetStateFromHash(uint64_t hash, TOHState<disks> &s) const
319 {
320  for (int x = 0; x < 4; x++)
321  s.counts[x] = 0;
322  for (int x = disks-1; x >= 0; x--)
323  {
324  int nextPeg = (hash>>(2*x))&0x3;
325  s.disks[nextPeg][s.counts[nextPeg]] = x+1;
326  s.counts[nextPeg]++;
327  }
328 }
329 
330 template <int disks>
332 {
333  return (act.source<<8)|act.dest;
334 }
335 
336 template <int disks>
338 {
339  glColor3f(0.5, 0.5, 0.5);
340  DrawCylinder(-0.75, 0, 0, 0, 0.01, 0.8);
341  DrawCylinder(-0.25, 0, 0, 0, 0.01, 0.8);
342  DrawCylinder( 0.25, 0, 0, 0, 0.01, 0.8);
343  DrawCylinder( 0.75, 0, 0, 0, 0.01, 0.8);
344  glColor3f(0.6, 0.4, 0.2);
345  glPushMatrix();
346  glScalef(1.0, 0.05, 0.25);
347  DrawBox(0, 0.4/0.05+1, 0, 1.0);
348  glPopMatrix();
349  // DrawBox(0, 0, 0, 0.5);
350 }
351 
352 template <int disks>
354 {
355  glColor3f(0.0, 0.0, 1.0);
356  double offset[4] = {-0.75, -0.25, 0.25, 0.75};
357  for (int x = 0; x < 4; x++)
358  {
359  for (int y = 0; y < s.GetDiskCountOnPeg(x); y++)
360  {
361  int which = s.GetDiskOnPeg(x, y);
362  glColor3f(0.0, 1.0-float(which)/float(disks), 1.0);
363  DrawCylinder(offset[x], 0.4-0.4/(1+float(disks))-y*0.8/(1+float(disks)), 0,
364  0.02, 0.04+0.2*which/float(disks), 0.8/(1+float(disks)));
365  }
366  }
367 }
368 
370 template <int disks>
371 void TOH<disks>::OpenGLDraw(const TOHState<disks>&s, const TOHState<disks>&s2, float interval) const
372 {
373  TOHMove m = this->GetAction(s, s2);
374  int animatingDisk = s.GetSmallestDiskOnPeg(m.source);
375  int initialHeight = s.GetDiskCountOnPeg(m.source)-1;
376  int finalHeight = s.GetDiskCountOnPeg(m.dest);
377 
378  glColor3f(0.0, 0.0, 1.0);
379  double offset[4] = {-0.75, -0.25, 0.25, 0.75};
380  for (int x = 0; x < 4; x++)
381  {
382  for (int y = 0; y < s.GetDiskCountOnPeg(x); y++)
383  {
384  int which = s.GetDiskOnPeg(x, y);
385  if (which != animatingDisk)
386  {
387  glColor3f(0.0, 1.0-float(which)/float(disks), 1.0);
388  DrawCylinder(offset[x], 0.4-0.4/(1+float(disks))-y*0.8/(1+float(disks)), 0,
389  0.02, 0.04+0.2*which/float(disks), 0.8/(1+float(disks)));
390  }
391  }
392  }
393  glColor3f(0.0, 1.0-float(animatingDisk)/float(disks), 1.0);
394  if (interval <= 0.333)
395  {
396  interval *= 3;
397  DrawCylinder(offset[m.source], 0.4-0.4/(1+float(disks))-initialHeight*0.8/(1+float(disks)) - (interval)*(disks+1-initialHeight)*0.8/(1+float(disks)), 0,
398  0.02, 0.04+0.2*animatingDisk/float(disks), 0.8/(1+float(disks)));
399  }
400  else if (interval <= 0.666)
401  {
402  interval *= 3;
403  DrawCylinder((2-interval)*offset[m.source]+(interval-1)*offset[m.dest], 0.4-0.4/(1+float(disks))-0.8-0.2*sin((interval-1)*PI), 0,
404  0.02, 0.04+0.2*animatingDisk/float(disks), 0.8/(1+float(disks)));
405  }
406  else {
407  DrawCylinder(offset[m.dest], 0.4-0.4/(1+float(disks))-finalHeight*0.8/(1+float(disks)) -
408  ((1.0-interval)/0.334)*(disks+1-finalHeight)*0.8/(1+float(disks)), 0,
409  0.02, 0.04+0.2*animatingDisk/float(disks), 0.8/(1+float(disks)));
410  }
411 }
412 
413 template <int disks>
415 {
416 
417 }
418 
419 template <int patternDisks, int totalDisks, int offset=0>
420 class TOHPDB : public PDBHeuristic<TOHState<patternDisks>, TOHMove, TOH<patternDisks>, TOHState<totalDisks>> {
421 public:
423  :PDBHeuristic<TOHState<patternDisks>, TOHMove, TOH<patternDisks>, TOHState<totalDisks>>(e) { this->SetGoal(s); }
424  virtual ~TOHPDB() {}
425 
427  {
428  int diff = totalDisks - patternDisks;
429 
431  for (int x = 0; x < 4; x++)
432  {
433  tmp.counts[x] = start.counts[x];
434  for (int y = 0; y < tmp.counts[x]; y++)
435  {
436  tmp.disks[x][y] = start.disks[x][y]+diff-offset;
437  }
438  }
439  return tmp;
440  }
441  //
442  // 6 5
443  //
444  // 4 3
445  //
446  // 2
447  //
448  // 1
449  virtual uint64_t GetAbstractHash(const TOHState<totalDisks> &s, int threadID = 0) const
450  {
451  int diff = totalDisks - patternDisks;
452  uint64_t hash = 0;
453  for (int x = 0; x < 4; x++)
454  {
455  for (int y = 0; y < s.GetDiskCountOnPeg(x); y++)
456  {
457  // 6 total 2 pattern
458  if ((s.GetDiskOnPeg(x, y) > diff-offset) && (s.GetDiskOnPeg(x, y) <= totalDisks-offset))
459  hash |= (uint64_t(x)<<(2*(s.GetDiskOnPeg(x, y)-1-diff+offset)));
460  }
461  }
462  return hash;
463  }
464 
465  virtual uint64_t GetPDBSize() const
466  {
467  return 1ull<<(2*patternDisks);
468  }
469  virtual uint64_t GetPDBHash(const TOHState<patternDisks> &s, int threadID = 0) const
470  {
471  return this->env->GetStateHash(s);
472  }
473  virtual void GetStateFromPDBHash(uint64_t hash, TOHState<patternDisks> &s, int threadID = 0) const
474  {
475  this->env->GetStateFromHash(hash, s);
476  }
477 
478  virtual bool Load(const char *prefix)
479  {
480  return false;
481  }
482  virtual void Save(const char *prefix)
483  {
484  FILE *f = fopen(GetFileName(prefix).c_str(), "w+");
485  if (f == 0)
486  {
487  fprintf(stderr, "Error saving");
488  return;
489  }
491  fclose(f);
492  }
493 
494  virtual std::string GetFileName(const char *prefix)
495  {
496  std::string s = prefix;
497  s += "TOH4+"+std::to_string(patternDisks)+"+"+std::to_string(totalDisks)+".pdb";
498  return s;
499  }
500 };
501 
502 #endif /* TOH_hpp */
TOHState::TOHState
TOHState()
Definition: TOH.h:27
TOHPDB::GetStateFromPDBHash
virtual void GetStateFromPDBHash(uint64_t hash, TOHState< patternDisks > &s, int threadID=0) const
Definition: TOH.h:473
TOH::TOH
TOH()
Definition: TOH.h:135
TOHState::GetDiskCountOnPeg
int GetDiskCountOnPeg(int whichPeg) const
Definition: TOH.h:65
TOHPDB
Definition: TOH.h:420
TOHMove::TOHMove
TOHMove(uint8_t s, uint8_t d)
Definition: TOH.h:19
operator<<
static std::ostream & operator<<(std::ostream &out, const TOHState< D > &s)
Definition: TOH.h:90
TOHState::StandardStart
void StandardStart()
Definition: TOH.h:52
TOH::OpenGLDraw
void OpenGLDraw() const
Definition: TOH.h:337
TOHPDB::TOHPDB
TOHPDB(TOH< patternDisks > *e, const TOHState< totalDisks > &s)
Definition: TOH.h:422
TOH::GetSuccessors
void GetSuccessors(const TOHState< disks > &nodeID, std::vector< TOHState< disks >> &neighbors) const
Definition: TOH.h:173
TOHPDB::GetPDBHash
virtual uint64_t GetPDBHash(const TOHState< patternDisks > &s, int threadID=0) const
Definition: TOH.h:469
DrawCylinder
void DrawCylinder(GLfloat xx, GLfloat yy, GLfloat zz, GLfloat innerRad, GLfloat outerRad, GLfloat height)
Definition: GLUtil.cpp:309
d
mcData d[]
Definition: MotionCaptureMovement.cpp:21
TOHState::counts
uint8_t counts[4]
Definition: TOH.h:86
TOH::GetNumStates
uint64_t GetNumStates(TOHState< disks > &s) const
Definition: TOH.h:312
TOH::GetActionHash
uint64_t GetActionHash(TOHMove act) const
Definition: TOH.h:331
TOH::GCost
double GCost(const TOHState< disks > &node1, const TOHState< disks > &node2) const
Definition: TOH.h:144
TOHPDB::GetAbstractHash
virtual uint64_t GetAbstractHash(const TOHState< totalDisks > &s, int threadID=0) const
Definition: TOH.h:449
TOHPDB::GetPDBSize
virtual uint64_t GetPDBSize() const
Definition: TOH.h:465
TOH::HCost
double HCost(const TOHState< disks > &node1, const TOHState< disks > &node2) const
Heuristic value between two arbitrary nodes.
Definition: TOH.h:280
TOH::GetStateFromHash
void GetStateFromHash(uint64_t parent, TOHState< disks > &s) const
Definition: TOH.h:318
TOH
Definition: TOH.h:133
TOHState::GetSmallestDiskOnPeg
int GetSmallestDiskOnPeg(int whichPeg) const
Definition: TOH.h:77
TOH::tmp
TOHState< disks > tmp
Definition: TOH.h:166
TOHPDB::GetFileName
virtual std::string GetFileName(const char *prefix)
Definition: TOH.h:494
TOHMove::source
uint8_t source
Definition: TOH.h:21
PI
static const double PI
Definition: GLUtil.h:66
TOHMove
Definition: TOH.h:18
TOH::pruneActions
bool pruneActions
Definition: TOH.h:161
PDBHeuristic
Definition: PDBHeuristic.h:39
TOHState::Reset
void Reset()
Definition: TOH.h:40
TOH::acts
std::vector< TOHMove > acts
Definition: TOH.h:165
TOH::GetName
std::string GetName()
Definition: TOH.h:154
TOH::GetActions
void GetActions(const TOHState< disks > &nodeID, std::vector< TOHMove > &actions) const
Definition: TOH.h:185
TOHPDB::Save
virtual void Save(const char *prefix)
Definition: TOH.h:482
TOHPDB::Load
virtual bool Load(const char *prefix)
Definition: TOH.h:478
TOHPDB::GetStateFromAbstractState
TOHState< totalDisks > GetStateFromAbstractState(TOHState< patternDisks > &start) const
Definition: TOH.h:426
PDBHeuristic< TOHState< patternDisks >, TOHMove, TOH< patternDisks >, TOHState< totalDisks > >::env
TOH< patternDisks > * env
Definition: PDBHeuristic.h:128
TOHMove::dest
uint8_t dest
Definition: TOH.h:22
TOH::GCost
double GCost(const TOHState< disks > &node, const TOHMove &act) const
Definition: TOH.h:145
TOHState::disks
uint8_t disks[4][numDisks]
Definition: TOH.h:85
PDBHeuristic< TOHState< patternDisks >, TOHMove, TOH< patternDisks >, TOHState< totalDisks > >::SetGoal
void SetGoal(const TOHState< totalDisks > &goal)
Definition: PDBHeuristic.h:45
TOH::~TOH
~TOH()
Definition: TOH.h:136
DrawBox
void DrawBox(GLfloat xx, GLfloat yy, GLfloat zz, GLfloat rad)
Definition: GLUtil.cpp:285
operator==
static bool operator==(const TOHState< D > &l1, const TOHState< D > &l2)
Definition: TOH.h:102
TOH::GetMaxHash
uint64_t GetMaxHash() const
Definition: TOH.h:150
TOH::GoalTest
bool GoalTest(const TOHState< disks > &node, const TOHState< disks > &goal) const
Definition: TOH.h:288
TOHState
Definition: TOH.h:26
operator!=
static bool operator!=(const TOHState< D > &l1, const TOHState< D > &l2)
Definition: TOH.h:117
TOH::GetStateHash
uint64_t GetStateHash(const TOHState< disks > &node) const
Definition: TOH.h:298
TOH::ApplyAction
void ApplyAction(TOHState< disks > &s, TOHMove a) const
Definition: TOH.h:261
PDBHeuristic.h
TOHState::GetDiskOnPeg
int GetDiskOnPeg(int whichPeg, int whichDisk) const
Definition: TOH.h:70
TOHMove::TOHMove
TOHMove()
Definition: TOH.h:20
SearchEnvironment
Definition: SearchEnvironment.h:30
node
Nodes to be stored within a Graph.
Definition: Graph.h:170
SearchEnvironment.h
TOH::InvertAction
bool InvertAction(TOHMove &a) const
Definition: TOH.h:269
TOHPDB::~TOHPDB
virtual ~TOHPDB()
Definition: TOH.h:424