HOG2
CorridorAStar.cpp
Go to the documentation of this file.
1 /*
2  * $Id: corridorAStar.cpp
3  * hog2
4  *
5  * Created by Nathan Sturtevant on 6/22/05.
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 #include "CorridorAStar.h"
13 #include "FPUtil.h"
14 
15 using namespace GraphAbstractionConstants;
16 const static int verbose = 0;
17 
19 {
20  corridor = &emptyCorridor;
21 }
22 
23 void corridorAStar::setCorridor(const std::vector<node *> *c)
24 {
25  corridor = c;
26 }
27 
29 {
30  return getBestPath(aMap, from, to, to, rp);
31 }
32 
34 {
35  nodesExpanded = 0;
36  nodesTouched = 0;
37 
38  node *n=0;
39  Heap *nodeHeap = new Heap(corridor->size());
40  std::vector<node *> expandedNodes(100);
42  bool exactGoal = true;
43 
45  exactGoal = false;
46 
47  // get current layer & abstract corridor layer
48  int absLayer = from->GetLabelL(kAbstractionLevel);
49  int corridorLayer = absLayer;
50  if (corridor->size() > 0)
51  corridorLayer = (*corridor)[0]->GetLabelL(kAbstractionLevel);
52  Graph *absGraph = aMap->GetAbstractGraph(absLayer);
53 
54  // mark location of eligible nodes
55  for (unsigned int x = 0; x < corridor->size(); x++)
56  ((*corridor)[x])->key = x;
57 
58  // label start node cost 0
59  n = from;
60  n->SetLabelF(kTemporaryLabel, aMap->h(n, hGoal));
61  n->markEdge(0);
62  if (verbose) printf("Starting on %d with cost %1.2f\n", from->GetNum(), n->GetLabelF(kTemporaryLabel));
63  nodesExpanded++;
64  while (1) {
65  expandedNodes.push_back(n);
66  n->key = expandedNodes.size()-1;
67 
68  if (verbose)
69  printf("really working on %d with cost %1.2f\n", n->GetNum(), n->GetLabelF(kTemporaryLabel));
70 
71  ni = n->getNeighborIter();
72 
73  for (node *currNode = absGraph->GetNode(n->nodeNeighborNext(ni));
74  currNode; currNode = absGraph->GetNode(n->nodeNeighborNext(ni)))
75  {
76  nodesTouched++;
77  if (verbose) printf("considering neighbor %d\n", currNode->GetNum());
78  if (nodeHeap->IsIn(currNode))
79  {
80  nodesExpanded++;
81  relaxEdge(nodeHeap, absGraph, aMap,
82  absGraph->FindEdge(n->GetNum(), currNode->GetNum()),
83  n, currNode, hGoal);
84  }
85  else if (rp && (absLayer==0) && (currNode != to) && rp->nodeOccupied(currNode))
86  {
87  if (verbose) printf("Can't path to %d, %d (occupied)\n", (unsigned int)currNode->GetLabelL(kFirstData), (unsigned int)currNode->GetLabelL(kFirstData+1));
88  expandedNodes.push_back(currNode);
89  currNode->key = expandedNodes.size()-1;
90  // ignore this tile if occupied.
91  }
92  // this node is unexpanded if (1) it isn't on the expanded list
93  else if ((currNode->key >= expandedNodes.size()) ||
94  (expandedNodes[currNode->key] != currNode))
95  {
96  node *par = aMap->GetNthParent(currNode, corridorLayer);
97  unsigned int parentKey = par->key;
98 
99  // this node is unexpanded if (2) it's parent is in the eligible parent list
100  // (3) or having no eligible parents means we can search anywhere!
101  if ((corridor->size() == 0) ||
102  ((parentKey < corridor->size()) && ((*corridor)[parentKey] == par)))
103  {
104  currNode->SetLabelF(kTemporaryLabel, MAXINT);
105  currNode->SetKeyLabel(kTemporaryLabel);
106  currNode->markEdge(0);
107  nodeHeap->Add(currNode);
108  if (verbose) printf("Adding neighbor %d\n", currNode->GetNum());
109  nodesExpanded++;
110  relaxEdge(nodeHeap, absGraph, aMap,
111  absGraph->FindEdge(n->GetNum(), currNode->GetNum()),
112  n, currNode, hGoal);
113  }
114  else { if (verbose) printf("%d not eligible\n", currNode->GetNum()); }
115  }
116  else { if (verbose) printf("%d already expanded\n", currNode->GetNum()); }
117  }
118 
119  n = (node*)nodeHeap->Remove();
120  if (n == 0)
121  {
122  if (verbose) printf("Error: We expanded every possible node!\n");
123  break;
124  }
125 
126  // found a node who's nth parent is inside our target
127  if ((!exactGoal) &&
128  (aMap->GetNthParent(n, to->GetLabelL(kAbstractionLevel)) == to))
129  break;
130 
131  if (n == to) { /*printf("Found goal %d\n", dest);*/ break; }
132 
133  if (verbose) printf("working on %d with cost %1.2f\n", n->GetNum(), n->GetLabelF(kTemporaryLabel));
134  }
135 
136  if ((n != to) && (exactGoal))
137  {
138  if (verbose)
139  printf("Corridor A* ran and didn't find goal in corridor!\n");
140  }
141  delete nodeHeap;
142  corridor = &emptyCorridor;
143  if (n != 0) // we found a goal
144  return extractBestPath(absGraph, n->GetNum());
145  return 0;
146 }
147 
149 {
150  nodesExpanded = 0;
151  nodesTouched = 0;
152 
153  node *n=0;
154  Heap *nodeHeap = new Heap(corridor->size());
155  std::vector<node *> expandedNodes(100);
157  bool exactGoal = true;
158 
160  exactGoal = false;
161 
162  // get current layer & abstract corridor layer
163  int absLayer = afrom->GetLabelL(kAbstractionLevel);
164  int corridorLayer = absLayer;
165  if (corridor->size() > 0)
166  corridorLayer = (*corridor)[0]->GetLabelL(kAbstractionLevel);
167  Graph *absGraph = aMap->GetAbstractGraph(absLayer);
168 
169  // mark location of eligible nodes
170  for (unsigned int x = 0; x < corridor->size(); x++)
171  ((*corridor)[x])->key = x;
172 
173  // label start node cost 0
174  n = afrom;
175  n->SetLabelF(kTemporaryLabel, aMap->h(n, ato));
176  n->markEdge(0);
177  if (verbose) printf("Starting on %d with cost %1.2f\n", afrom->GetNum(), n->GetLabelF(kTemporaryLabel));
178  nodesExpanded++;
179  while (1)
180  {
181  expandedNodes.push_back(n);
182  n->key = expandedNodes.size()-1;
183 
184  if (verbose)
185  printf("really working on %d with cost %1.2f\n", n->GetNum(), n->GetLabelF(kTemporaryLabel));
186 
187  ni = n->getNeighborIter();
188 
189  for (node *currNode = absGraph->GetNode(n->nodeNeighborNext(ni));
190  currNode; currNode = absGraph->GetNode(n->nodeNeighborNext(ni)))
191  {
192  nodesTouched++;
193  if (verbose) printf("considering neighbor %d\n", currNode->GetNum());
194  if (nodeHeap->IsIn(currNode))
195  {
196  nodesExpanded++;
197  if (n == afrom)
198  relaxFirstEdge(nodeHeap, absGraph, aMap,
199  absGraph->FindEdge(n->GetNum(), currNode->GetNum()),
200  from, n, currNode, ato);
201  if (currNode == ato)
202  relaxFinalEdge(nodeHeap, absGraph, aMap,
203  absGraph->FindEdge(n->GetNum(), currNode->GetNum()),
204  n, currNode, ato);
205  else
206  relaxEdge(nodeHeap, absGraph, aMap,
207  absGraph->FindEdge(n->GetNum(), currNode->GetNum()),
208  n, currNode, ato);
209  }
210  else if (rp && (absLayer==0) && (currNode != ato) && rp->nodeOccupied(currNode))
211  {
212  if (verbose) printf("Can't path to %d, %d (occupied)\n", (unsigned int)currNode->GetLabelL(kFirstData), (unsigned int)currNode->GetLabelL(kFirstData+1));
213  expandedNodes.push_back(currNode);
214  currNode->key = expandedNodes.size()-1;
215  // ignore this tile if occupied.
216  }
217  // this node is unexpanded if (1) it isn't on the expanded list
218  else if ((currNode->key >= expandedNodes.size()) ||
219  (expandedNodes[currNode->key] != currNode))
220  {
221  node *par = aMap->GetNthParent(currNode, corridorLayer);
222  unsigned int parentKey = par->key;
223 
224  // this node is unexpanded if (2) it's parent is in the eligible parent list
225  // (3) or having no eligible parents means we can search anywhere!
226  if ((corridor->size() == 0) ||
227  ((parentKey < corridor->size()) && ((*corridor)[parentKey] == par)))
228  {
229  currNode->SetLabelF(kTemporaryLabel, MAXINT);
230  currNode->SetKeyLabel(kTemporaryLabel);
231  currNode->markEdge(0);
232  nodeHeap->Add(currNode);
233  if (verbose) printf("Adding neighbor %d\n", currNode->GetNum());
234  nodesExpanded++;
235 
236  if (n == afrom)
237  relaxFirstEdge(nodeHeap, absGraph, aMap,
238  absGraph->FindEdge(n->GetNum(), currNode->GetNum()),
239  from, n, currNode, ato);
240  if (currNode == ato)
241  relaxFinalEdge(nodeHeap, absGraph, aMap,
242  absGraph->FindEdge(n->GetNum(), currNode->GetNum()),
243  n, currNode, ato);
244  else
245  relaxEdge(nodeHeap, absGraph, aMap,
246  absGraph->FindEdge(n->GetNum(), currNode->GetNum()),
247  n, currNode, ato);
248 // relaxEdge(nodeHeap, absGraph, aMap,
249 // absGraph->FindEdge(n->GetNum(), currNode->GetNum()),
250 // n, currNode, hGoal);
251  }
252  else { if (verbose) printf("%d not eligible\n", currNode->GetNum()); }
253  }
254  else { if (verbose) printf("%d already expanded\n", currNode->GetNum()); }
255  }
256 
257  n = (node*)nodeHeap->Remove();
258  if (n == 0)
259  {
260  if (verbose) printf("Error: We expanded every possible node!\n");
261  break;
262  }
263 
264  // found a node who's nth parent is inside our target
265  if ((!exactGoal) &&
266  (aMap->GetNthParent(n, ato->GetLabelL(kAbstractionLevel)) == ato))
267  break;
268 
269  if (n == ato) { /*printf("Found goal %d\n", dest);*/ break; }
270 
271  if (verbose) printf("working on %d with cost %1.2f\n", n->GetNum(), n->GetLabelF(kTemporaryLabel));
272  }
273 
274  if ((n != ato) && (exactGoal))
275  {
276  if (verbose)
277  printf("Corridor A* ran and didn't find goal in corridor!\n");
278  }
279  delete nodeHeap;
280  corridor = &emptyCorridor;
281  if (n != 0) // we found a goal
282  return extractBestPath(absGraph, n->GetNum());
283  return 0;
284 }
285 
287  edge *e, node *from, node *to, node *dest)
288 {
289  double weight;
290  weight = from->GetLabelF(kTemporaryLabel)-aMap->h(from, dest)+aMap->h(to, dest)+e->GetWeight();
291  if (fless(weight, to->GetLabelF(kTemporaryLabel)))
292  {
293  if (verbose)
294  printf("Updating %d to %1.2f from %1.2f\n", to->GetNum(), weight, to->GetLabelF(kTemporaryLabel));
295  //weight -= 0.001*(weight-map->h(to, d)); // always lower g-cost slightly so that we tie break in favor of higher g cost
296  to->SetLabelF(kTemporaryLabel, weight);
297  nodeHeap->DecreaseKey(to);
298  // this is the edge used to get to this node in the min. path tree
299  to->markEdge(e);
300  }
301 }
302 
304  edge *e, node *from, node *afrom, node *ato, node *dest)
305 {
306  double weight;
307  weight = afrom->GetLabelF(kTemporaryLabel)-aMap->h(afrom, dest)+aMap->h(ato, dest)+aMap->h(from, ato);
308  if (fless(weight, ato->GetLabelF(kTemporaryLabel)))
309  {
310  if (verbose)
311  printf("Updating %d to %1.2f from %1.2f\n", ato->GetNum(), weight, ato->GetLabelF(kTemporaryLabel));
312  //weight -= 0.001*(weight-map->h(ato, d)); // always lower g-cost slightly so that we tie break in favor of higher g cost
313  ato->SetLabelF(kTemporaryLabel, weight);
314  nodeHeap->DecreaseKey(ato);
315  // this is the edge used to get to this node in the min. path tree
316  ato->markEdge(e);
317  }
318 }
319 
321  edge *e, node *from, node *to, node *realDest)
322 {
323  double weight;
324  weight = from->GetLabelF(kTemporaryLabel)-aMap->h(from, to)+aMap->h(from, realDest);
325  if (fless(weight, to->GetLabelF(kTemporaryLabel)))
326  {
327  if (verbose)
328  printf("Updating %d to %1.2f from %1.2f\n", to->GetNum(), weight, to->GetLabelF(kTemporaryLabel));
329  //weight -= 0.001*(weight-map->h(to, d)); // always lower g-cost slightly so that we tie break in favor of higher g cost
330  to->SetLabelF(kTemporaryLabel, weight);
331  nodeHeap->DecreaseKey(to);
332  // this is the edge used to get to this node in the min. path tree
333  to->markEdge(e);
334  }
335 }
336 
337 path *corridorAStar::extractBestPath(Graph *g, unsigned int current)
338 {
339  path *p = 0;
340  edge *e;
341  // extract best path from Graph -- each node has a single parent in the Graph which is the marked edge
342  // for visuallization purposes, an edge can be marked meaning it will be drawn in white
343  while ((e = g->GetNode(current)->getMarkedEdge()))
344  {
345  if (verbose) printf("%d <- ", current);
346 
347  p = new path(g->GetNode(current), p);
348 
349  e->setMarked(true);
350 
351  if (e->getFrom() == current)
352  current = e->getTo();
353  else
354  current = e->getFrom();
355  }
356  p = new path(g->GetNode(current), p);
357  if (verbose) printf("%d\n", current);
358  return p;
359 }
GraphAbstraction
A generic class for basic operations on Graph abstractions.
Definition: GraphAbstraction.h:63
GraphAbstractionConstants
Definition: GraphAbstraction.h:22
edge::GetWeight
double GetWeight()
Definition: Graph.h:140
node::getMarkedEdge
edge * getMarkedEdge()
Definition: Graph.h:228
node::SetLabelF
void SetLabelF(unsigned int index, double val) const
Definition: Graph.cpp:687
edge::getFrom
unsigned int getFrom() const
Definition: Graph.h:146
edge::getTo
unsigned int getTo() const
Definition: Graph.h:147
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
neighbor_iterator
unsigned int neighbor_iterator
Definition: Graph.h:34
GraphAbstraction::GetAbstractGraph
Graph * GetAbstractGraph(int level)
return the abstract Graph at the given level
Definition: GraphAbstraction.h:74
graph_object::key
unsigned int key
Definition: Graph.h:54
edge::setMarked
void setMarked(bool marked)
Definition: Graph.h:149
FPUtil.h
Heap::DecreaseKey
void DecreaseKey(graph_object *val)
Indicate that the key for a particular object has decreased.
Definition: Heap.cpp:47
Graph
A generic Graph class.
Definition: Graph.h:66
Graph::GetNode
node * GetNode(unsigned long num)
Definition: Graph.cpp:152
node::markEdge
void markEdge(edge *e)
Definition: Graph.h:227
corridorAStar::relaxFirstEdge
void relaxFirstEdge(Heap *nodeHeap, Graph *g, GraphAbstraction *aMap, edge *e, node *from, node *afrom, node *ato, node *dest)
Definition: CorridorAStar.cpp:303
GraphAbstraction::h
virtual double h(node *a, node *b)=0
heuristic cost between any two nodes
GraphAbstractionConstants::kFirstData
@ kFirstData
Definition: GraphAbstraction.h:34
fless
bool fless(double a, double b)
Definition: FPUtil.h:28
verbose
const static int verbose
Definition: CorridorAStar.cpp:16
GraphAbstractionConstants::kAbstractionLevel
@ kAbstractionLevel
Definition: GraphAbstraction.h:25
Heap::Remove
graph_object * Remove()
Remove the item with the lowest key from the Heap & re-heapify.
Definition: Heap.cpp:66
node::nodeNeighborNext
int nodeNeighborNext(neighbor_iterator &) const
Definition: Graph.cpp:807
Heap::Add
void Add(graph_object *val)
Add object into Heap.
Definition: Heap.cpp:36
path
std::vector< xyLoc > path
Definition: Sample.cpp:43
CorridorAStar.h
corridorAStar::extractBestPath
path * extractBestPath(Graph *g, unsigned int current)
Definition: CorridorAStar.cpp:337
node::GetLabelF
double GetLabelF(unsigned int index) const
Definition: Graph.h:215
corridorAStar::GetPath
path * GetPath(GraphAbstraction *aMap, node *from, node *to, reservationProvider *rp=0)
Definition: CorridorAStar.cpp:28
corridorAStar::relaxFinalEdge
void relaxFinalEdge(Heap *nodeHeap, Graph *g, GraphAbstraction *aMap, edge *e, node *from, node *to, node *realDest)
Definition: CorridorAStar.cpp:320
Heap
A simple & efficient Heap class which uses Graph objects.
Definition: Heap.h:27
node::GetNum
unsigned int GetNum() const
Definition: Graph.h:176
corridorAStar::getBestPath
path * getBestPath(GraphAbstraction *aMap, node *from, node *to, node *hGoal, reservationProvider *rp=0)
get the best path from FROM to TO.
Definition: CorridorAStar.cpp:33
MAXINT
#define MAXINT
Definition: Graph.h:24
GraphAbstractionConstants::kTemporaryLabel
@ kTemporaryLabel
Definition: GraphAbstraction.h:29
reservationProvider
Definition: ReservationProvider.h:33
corridorAStar::setCorridor
void setCorridor(const std::vector< node * > *)
Definition: CorridorAStar.cpp:23
node::GetLabelL
long GetLabelL(unsigned int index) const
Definition: Graph.h:220
path
A linked list of nodes which form a continuous path.
Definition: Path.h:20
node::getNeighborIter
neighbor_iterator getNeighborIter() const
Definition: Graph.cpp:802
reservationProvider::nodeOccupied
virtual bool nodeOccupied(node *)=0
corridorAStar::relaxEdge
void relaxEdge(Heap *nodeHeap, Graph *g, GraphAbstraction *aMap, edge *e, node *from, node *to, node *dest)
Definition: CorridorAStar.cpp:286
corridorAStar::corridorAStar
corridorAStar()
Definition: CorridorAStar.cpp:18
GraphAbstraction::GetNthParent
node * GetNthParent(node *which, int n)
return nth level parent of which or null if it doesn't exist
Definition: GraphAbstraction.cpp:67
node
Nodes to be stored within a Graph.
Definition: Graph.h:170
Heap::IsIn
bool IsIn(graph_object *val)
Returns true if the object is in the Heap.
Definition: Heap.cpp:55
edge
Edge class for connections between node in a Graph.
Definition: Graph.h:129