HOG2
AStarOpenClosed.h
Go to the documentation of this file.
1 /*
2  * $Id: AStarOpenClosed.h
3  * hog2
4  *
5  * Created by Nathan Sturtevant on 5/25/09.
6  * Modified by Nathan Sturtevant on 02/29/20.
7  *
8  * This file is part of HOG2. See https://github.com/nathansttt/hog2 for licensing information.
9  *
10  */
11 
12 #ifndef ASTAROPENCLOSED_H
13 #define ASTAROPENCLOSED_H
14 
15 #include <cassert>
16 #include <cstddef>
17 #include <functional>
18 #include <stdint.h>
19 #include <unordered_map>
20 #include <vector>
21 
22 struct AHash64 {
23  size_t operator()(const uint64_t &x) const
24  { return (size_t)(x); }
25 };
26 
31 };
32 
33 const uint64_t kTAStarNoNode = 0xFFFFFFFFFFFFFFFFull;
34 
35 template<typename state>
37 public:
39  AStarOpenClosedDataWithF(const state &theData, double fCost, double gCost, double hCost, uint64_t parent, uint64_t openLoc, dataLocation location)
40  :data(theData), f(fCost), g(gCost), h(hCost), parentID(parent), openLocation(openLoc), where(location) { reopened = false; }
41  state data;
42  double f;
43  double g;
44  double h;
45  uint64_t parentID;
46  uint64_t openLocation;
47  bool reopened;
49 };
50 
51 template<typename state>
53 public:
55  AStarOpenClosedData(const state &theData, double gCost, double hCost, uint64_t parent, uint64_t openLoc, dataLocation location)
56  :data(theData), g(gCost), h(hCost), parentID(parent), openLocation(openLoc), where(location) { reopened = false; }
57  state data;
58  // Refactor TODO:
59  // Most of the data here is required by the data structure for sorting purposes.
60  // But, the g/h/(f) cost is specific to a given algorithm. So, g/h/(f) should be factored out
61  // and that should be the templat class, not the full data here.
62  // Bonus: for Canonical A* we can then store the parent action directly in the open list
63  // to avoiding re-copying states in the A* implementation
64  double g;
65  double h;
66  uint64_t parentID;
67  uint64_t openLocation;
68  bool reopened;
70 };
71 
72 
73 template<typename state, typename CmpKey, class dataStructure = AStarOpenClosedData<state> >
75 public:
78  void Reset(int val=0);
79  // TODO: replace f/g/h by a different data structure
80  uint64_t AddOpenNode(const state &val, uint64_t hash, double f, double g, double h, uint64_t parent=kTAStarNoNode);
81  uint64_t AddOpenNode(const state &val, uint64_t hash, double g, double h, uint64_t parent=kTAStarNoNode);
82  uint64_t AddClosedNode(state &val, uint64_t hash, double f, double g, double h, uint64_t parent=kTAStarNoNode);
83  uint64_t AddClosedNode(state &val, uint64_t hash, double g, double h, uint64_t parent=kTAStarNoNode);
84  void KeyChanged(uint64_t objKey);
85  dataLocation Lookup(uint64_t hashKey, uint64_t &objKey) const;
86  inline dataStructure &Lookup(uint64_t objKey) { return elements[objKey]; }
87  inline const dataStructure &Lookat(uint64_t objKey) const { return elements[objKey]; }
88  void Remove(uint64_t hash);
89  uint64_t Peek() const;
90  uint64_t Close(uint64_t objKey);
91  uint64_t Close();
92  void Reopen(uint64_t objKey);
93 
95  {
96  for (int x = 0; x < theHeap.size(); x++)
97  elements[theHeap[x]].where = kClosedList;
98  theHeap.resize(0);
99  }
100  uint64_t GetOpenItem(unsigned int which) { return theHeap[which]; }
101  size_t OpenSize() const { return theHeap.size(); }
102  size_t ClosedSize() const { return size()-OpenSize(); }
103  size_t size() const { return elements.size(); }
104  bool empty() const {return (theHeap.size() == 0);}
105  // void verifyData();
106 private:
107  bool HeapifyUp(uint64_t index);
108  void HeapifyDown(uint64_t index);
109  // TODO: don't pass in the hash value any more - use the C++ hash function specialization
110  // std::hash<state> hashFcn;
111 
112  std::vector<uint64_t> theHeap;
113  // storing the element id; looking up with...hash?
114  // TODO: replace this with C++11 data structures
115  typedef std::unordered_map<uint64_t, uint64_t, AHash64> IndexTable;
117  std::vector<dataStructure> elements;
118 };
119 
120 
121 template<typename state, typename CmpKey, class dataStructure>
123 {
124 }
125 
126 template<typename state, typename CmpKey, class dataStructure>
128 {
129 }
130 
134 template<typename state, typename CmpKey, class dataStructure>
136 {
137  table.clear();
138  elements.clear();
139  theHeap.resize(0);
140 }
141 
145 template<typename state, typename CmpKey, class dataStructure>
146 uint64_t AStarOpenClosed<state, CmpKey, dataStructure>::AddOpenNode(const state &val, uint64_t hash, double f, double g, double h, uint64_t parent)
147 {
148  //size_t hash = hashFcn(val);
149  // Change to behavior: if we have a duplicate state instead throwing and error,
150  // we update if the path is shorter, otherwise return the old state
151  auto i = table.find(hash);
152  if (i != table.end())
153  {
154  //return -1; // TODO: find correct id and return
155  //assert(false);
156  uint64_t index = i->second;
157  if (fless(g, elements[index].g))
158  {
159  elements[index].parentID = parent;
160  elements[index].g = g;
161  elements[index].f = f;
162  KeyChanged(index);
163  }
164  return index;
165  }
166  elements.push_back(dataStructure(val, f, g, h, parent, theHeap.size(), kOpenList));
167  if (parent == kTAStarNoNode)
168  elements.back().parentID = elements.size()-1;
169  table[hash] = elements.size()-1; // hashing to element list location
170  theHeap.push_back(elements.size()-1); // adding element id to back of heap
171  HeapifyUp(theHeap.size()-1); // heapify from back of the heap
172  return elements.size()-1;
173 }
174 
178 template<typename state, typename CmpKey, class dataStructure>
179 uint64_t AStarOpenClosed<state, CmpKey, dataStructure>::AddOpenNode(const state &val, uint64_t hash, double g, double h, uint64_t parent)
180 {
181  // Change to behavior: if we have a duplicate state instead throwing and error,
182  // we update if the path is shorter, otherwise return the old state
183  auto i = table.find(hash);
184  if (i != table.end())
185  {
186  //return -1; // TODO: find correct id and return
187  //assert(false);
188  uint64_t index = i->second;
189  if (fless(g, elements[index].g))
190  {
191  elements[index].parentID = parent;
192  elements[index].g = g;
193  KeyChanged(index);
194  }
195  return index;
196  }
197  elements.push_back(dataStructure(val, g, h, parent, theHeap.size(), kOpenList));
198  if (parent == kTAStarNoNode)
199  elements.back().parentID = elements.size()-1;
200  table[hash] = elements.size()-1; // hashing to element list location
201  theHeap.push_back(elements.size()-1); // adding element id to back of heap
202  HeapifyUp(theHeap.size()-1); // heapify from back of the heap
203  return elements.size()-1;
204 }
205 
209 template<typename state, typename CmpKey, class dataStructure>
210 uint64_t AStarOpenClosed<state, CmpKey, dataStructure>::AddClosedNode(state &val, uint64_t hash, double f, double g, double h, uint64_t parent)
211 {
212  // should do lookup here...
213  assert(table.find(hash) == table.end());
214  elements.push_back(dataStructure(val, f, g, h, parent, 0, kClosedList));
215  if (parent == kTAStarNoNode)
216  elements.back().parentID = elements.size()-1;
217  table[hash] = elements.size()-1; // hashing to element list location
218  return elements.size()-1;
219 }
220 
221 template<typename state, typename CmpKey, class dataStructure>
222 uint64_t AStarOpenClosed<state, CmpKey, dataStructure>::AddClosedNode(state &val, uint64_t hash, double g, double h, uint64_t parent)
223 {
224  // should do lookup here...
225  assert(table.find(hash) == table.end());
226  elements.push_back(dataStructure(val, g, h, parent, 0, kClosedList));
227  if (parent == kTAStarNoNode)
228  elements.back().parentID = elements.size()-1;
229  table[hash] = elements.size()-1; // hashing to element list location
230  return elements.size()-1;
231 }
232 
236 template<typename state, typename CmpKey, class dataStructure>
238 {
239  uint64_t index = table[hash];
240  uint64_t openLoc = elements[index].openLocation;
241  uint64_t swappedItem = theHeap.back();
242  table.erase(table.find(hash));
243  theHeap[openLoc] = theHeap.back();
244  theHeap.pop_back();
245  elements[swappedItem].openLocation = openLoc;
246  KeyChanged(index);
247 }
248 
252 template<typename state, typename CmpKey, class dataStructure>
254 {
255  if (!HeapifyUp(elements[val].openLocation))
256  HeapifyDown(elements[val].openLocation);
257 }
258 
262 template<typename state, typename CmpKey, class dataStructure>
264 {
265  typename IndexTable::const_iterator it;
266  it = table.find(hashKey);
267  if (it != table.end())
268  {
269  objKey = (*it).second;
270  return elements[objKey].where;
271  }
272  return kNotFound;
273 }
274 
275 
279 template<typename state, typename CmpKey, class dataStructure>
281 {
282  assert(OpenSize() != 0);
283 
284  return theHeap[0];
285 }
286 
290 template<typename state, typename CmpKey, class dataStructure>
292 {
293  assert(OpenSize() != 0);
294  uint64_t index = elements[objKey].openLocation;
295  uint64_t ans = theHeap[index];
296  assert(ans == objKey);
297  elements[ans].where = kClosedList;
298  theHeap[index] = theHeap[theHeap.size()-1];
299  elements[theHeap[index]].openLocation = index;
300  theHeap.pop_back();
301  if (!HeapifyUp(index))
302  HeapifyDown(index);
303 
304  return ans;
305 }
306 
310 template<typename state, typename CmpKey, class dataStructure>
312 {
313  assert(OpenSize() != 0);
314 
315  uint64_t ans = theHeap[0];
316  elements[ans].where = kClosedList;
317  theHeap[0] = theHeap[theHeap.size()-1];
318  elements[theHeap[0]].openLocation = 0;
319  theHeap.pop_back();
320  HeapifyDown(0);
321 
322  return ans;
323 }
324 
328 template<typename state, typename CmpKey, class dataStructure>
330 {
331  assert(elements[objKey].where == kClosedList);
332  elements[objKey].reopened = true;
333  elements[objKey].where = kOpenList;
334  elements[objKey].openLocation = theHeap.size();
335  theHeap.push_back(objKey);
336  HeapifyUp(theHeap.size()-1);
337 }
338 
342 template<typename state, typename CmpKey, class dataStructure>
344 {
345  if (index == 0) return false;
346  int parent = (index-1)/2;
347  CmpKey compare;
348 
349  if (compare(elements[theHeap[parent]], elements[theHeap[index]]))
350  {
351  unsigned int tmp = theHeap[parent];
352  theHeap[parent] = theHeap[index];
353  theHeap[index] = tmp;
354  elements[theHeap[parent]].openLocation = parent;
355  elements[theHeap[index]].openLocation = index;
356  HeapifyUp(parent);
357  return true;
358  }
359  return false;
360 }
361 
362 template<typename state, typename CmpKey, class dataStructure>
364 {
365  CmpKey compare;
366  unsigned int child1 = index*2+1;
367  unsigned int child2 = index*2+2;
368  int which;
369  unsigned int count = theHeap.size();
370  // find smallest child
371  if (child1 >= count)
372  return;
373  else if (child2 >= count)
374  which = child1;
375  else if (!(compare(elements[theHeap[child1]], elements[theHeap[child2]])))
376  which = child1;
377  else
378  which = child2;
379 
380  if (!(compare(elements[theHeap[which]], elements[theHeap[index]])))
381  {
382  unsigned int tmp = theHeap[which];
383  theHeap[which] = theHeap[index];
384  theHeap[index] = tmp;
385  elements[theHeap[which]].openLocation = which;
386  elements[theHeap[index]].openLocation = index;
387  HeapifyDown(which);
388  }
389 }
390 
391 
392 #endif
AStarOpenClosed::KeyChanged
void KeyChanged(uint64_t objKey)
Indicate that the key for a particular object has changed.
Definition: AStarOpenClosed.h:253
AStarOpenClosed::AStarOpenClosed
AStarOpenClosed()
Definition: AStarOpenClosed.h:122
AStarOpenClosedData::reopened
bool reopened
Definition: AStarOpenClosed.h:68
AStarOpenClosed::~AStarOpenClosed
~AStarOpenClosed()
Definition: AStarOpenClosed.h:127
AStarOpenClosed::Lookup
dataStructure & Lookup(uint64_t objKey)
Definition: AStarOpenClosed.h:86
AStarOpenClosedData::data
state data
Definition: AStarOpenClosed.h:57
AStarOpenClosedDataWithF::where
dataLocation where
Definition: AStarOpenClosed.h:48
AStarOpenClosedDataWithF::h
double h
Definition: AStarOpenClosed.h:44
AHash64
Definition: AStarOpenClosed.h:22
AHash64::operator()
size_t operator()(const uint64_t &x) const
Definition: AStarOpenClosed.h:23
AStarOpenClosed::Lookat
const dataStructure & Lookat(uint64_t objKey) const
Definition: AStarOpenClosed.h:87
AStarOpenClosedDataWithF
Definition: AStarOpenClosed.h:36
AStarOpenClosed::theHeap
std::vector< uint64_t > theHeap
Definition: AStarOpenClosed.h:112
AStarOpenClosed::Remove
void Remove(uint64_t hash)
Remove item from open/closed.
Definition: AStarOpenClosed.h:237
AStarOpenClosedData::parentID
uint64_t parentID
Definition: AStarOpenClosed.h:66
AStarOpenClosedDataWithF::openLocation
uint64_t openLocation
Definition: AStarOpenClosed.h:46
AStarOpenClosed::size
size_t size() const
Definition: AStarOpenClosed.h:103
AStarOpenClosedData::AStarOpenClosedData
AStarOpenClosedData(const state &theData, double gCost, double hCost, uint64_t parent, uint64_t openLoc, dataLocation location)
Definition: AStarOpenClosed.h:55
AStarOpenClosed::CloseAllOnOpen
void CloseAllOnOpen()
Definition: AStarOpenClosed.h:94
AStarOpenClosedData::where
dataLocation where
Definition: AStarOpenClosed.h:69
AStarOpenClosedDataWithF::parentID
uint64_t parentID
Definition: AStarOpenClosed.h:45
AStarOpenClosedData::g
double g
Definition: AStarOpenClosed.h:64
kTAStarNoNode
const uint64_t kTAStarNoNode
Definition: AStarOpenClosed.h:33
AStarOpenClosed::Reopen
void Reopen(uint64_t objKey)
Move item off the closed list and back onto the open list.
Definition: AStarOpenClosed.h:329
AStarOpenClosed::ClosedSize
size_t ClosedSize() const
Definition: AStarOpenClosed.h:102
AStarOpenClosed::Close
uint64_t Close()
Move the best item to the closed list and return key.
Definition: AStarOpenClosed.h:311
AStarOpenClosed
Definition: AStarOpenClosed.h:74
AStarOpenClosed::AddClosedNode
uint64_t AddClosedNode(state &val, uint64_t hash, double f, double g, double h, uint64_t parent=kTAStarNoNode)
Add object into closed list.
Definition: AStarOpenClosed.h:210
fless
bool fless(double a, double b)
Definition: FPUtil.h:28
AStarOpenClosed::AddOpenNode
uint64_t AddOpenNode(const state &val, uint64_t hash, double f, double g, double h, uint64_t parent=kTAStarNoNode)
Add object into open list.
Definition: AStarOpenClosed.h:146
AStarOpenClosed::table
IndexTable table
Definition: AStarOpenClosed.h:116
AStarOpenClosedData
Definition: AStarOpenClosed.h:52
dataLocation
dataLocation
Definition: AStarOpenClosed.h:27
AStarOpenClosedDataWithF::data
state data
Definition: AStarOpenClosed.h:41
AStarOpenClosedDataWithF::AStarOpenClosedDataWithF
AStarOpenClosedDataWithF(const state &theData, double fCost, double gCost, double hCost, uint64_t parent, uint64_t openLoc, dataLocation location)
Definition: AStarOpenClosed.h:39
AStarOpenClosed::empty
bool empty() const
Definition: AStarOpenClosed.h:104
AStarOpenClosedDataWithF::AStarOpenClosedDataWithF
AStarOpenClosedDataWithF()
Definition: AStarOpenClosed.h:38
AStarOpenClosedDataWithF::reopened
bool reopened
Definition: AStarOpenClosed.h:47
AStarOpenClosed::HeapifyUp
bool HeapifyUp(uint64_t index)
Moves a node up the heap.
Definition: AStarOpenClosed.h:343
AStarOpenClosed::Peek
uint64_t Peek() const
Peek at the next item to be expanded.
Definition: AStarOpenClosed.h:280
AStarOpenClosedData::openLocation
uint64_t openLocation
Definition: AStarOpenClosed.h:67
AStarOpenClosed::OpenSize
size_t OpenSize() const
Definition: AStarOpenClosed.h:101
kOpenList
@ kOpenList
Definition: AStarOpenClosed.h:28
AStarOpenClosed::GetOpenItem
uint64_t GetOpenItem(unsigned int which)
Definition: AStarOpenClosed.h:100
AStarOpenClosed::HeapifyDown
void HeapifyDown(uint64_t index)
Definition: AStarOpenClosed.h:363
AStarOpenClosedDataWithF::g
double g
Definition: AStarOpenClosed.h:43
AStarOpenClosed::Lookup
dataLocation Lookup(uint64_t hashKey, uint64_t &objKey) const
Returns location of object as well as object key.
Definition: AStarOpenClosed.h:263
AStarOpenClosedData::h
double h
Definition: AStarOpenClosed.h:65
AStarOpenClosedDataWithF::f
double f
Definition: AStarOpenClosed.h:42
AStarOpenClosed::IndexTable
std::unordered_map< uint64_t, uint64_t, AHash64 > IndexTable
Definition: AStarOpenClosed.h:115
AStarOpenClosed::Reset
void Reset(int val=0)
Remove all objects from queue.
Definition: AStarOpenClosed.h:135
kNotFound
@ kNotFound
Definition: AStarOpenClosed.h:30
AStarOpenClosedData::AStarOpenClosedData
AStarOpenClosedData()
Definition: AStarOpenClosed.h:54
AStarOpenClosed::elements
std::vector< dataStructure > elements
Definition: AStarOpenClosed.h:117
kClosedList
@ kClosedList
Definition: AStarOpenClosed.h:29