-
Notifications
You must be signed in to change notification settings - Fork 0
/
AStar.cpp
172 lines (155 loc) · 4.34 KB
/
AStar.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#include <algorithm>
#include <stdio.h>
#include "Definitions.h"
/******************************************
* Allocate and delete nodes
******************************************/
Node* AStar::newNode() {
Node *n = new Node;
if (!n)
exit(0);
return n;
}
void AStar::freeNode(Node *n) {
delete n;
}
/******************************************
* Set starting and goal nodes
******************************************/
void AStar::init(State &startState, State &goalState) {
start = newNode();
goal = newNode();
start->state = startState;
goal->state = goalState;
// Starting cost function == heuristic
start->g = 0;
start->h = start->state.H(goal->state);
start->f = start->g + start->h;
start->depth = 0;
// Add start node to frontier
frontier.push(start);
}
/******************************************
* This will be called from State::getChildren
* Adds child node with the passed parameters.
* It's a little obtuse...
******************************************/
bool AStar::addChild(State &s, int srcStack, int dstStack) {
Node *n = newNode();
if (!n) {
return false;
}
n->state = s;
n->state.move(srcStack, dstStack);
children.push_back(n);
return true;
}
/******************************************
* Check if node has been visited and, if so,
* is it better than the previously visited
* node. If so, return true.
******************************************/
bool AStar::isBetterPath(Node *n, int tmpG) {
for (int i=0; i<visited.size(); i++) {
if (n->state.isSame(visited[i]->state)) {
if (n->g < visited[i]->g) {
return true;
}
}
}
return false;
}
/******************************************
* Reconstruct (and print) path from current
* node to root.
******************************************/
void AStar::reconstructPath(Node *current) {
while (current->parent != NULL) {
goalPath.push_back(current);
current = current->parent;
}
// root node will have no parent
goalPath.push_back(current);
std::cout<<"Path:"<<std::endl;
for (int i=goalPath.size()-1; i>=0; i--) {
goalPath[i]->state.printState();
}
}
/******************************************
* Print search parameters associated with
* current node.
******************************************/
void AStar::printSearchState(Node *current) {
std::cout<<"Step="<<step<<", ";
std::cout<<"Queue="<<frontier.size()<<", ";
std::cout<<"f="<<current->f
<<", g="<<current->g
<<", h="<<current->h
<<", depth="<<current->depth
<<std::endl;
}
/******************************************
* Print search stuff to file
******************************************/
void AStar::printFile(Node *current) {
/* gotta love c i/o */
FILE *fp;
fp = fopen("H2.txt", "a");
/* nStacks, nBlocks, depth, steps, queuesize, starting H */
fprintf(fp, "%d %d %d %d %d %d\n",
current->state.nStacks,
current->state.nBlocks,
current->depth,
step,
(int)frontier.size(),
start->h);
fclose(fp);
}
/******************************************
* Main a* search.
******************************************/
int AStar::search(int maxSteps) {
step = 0;
Node *current = NULL;
while (!frontier.empty() && step != maxSteps) {
// clear children list
children.clear();
// current node is best in frontier
current = frontier.top();
// goal test
if (current->state.isSame(goal->state)) {
visited.clear();
std::cout<<"Found goal"<<std::endl;
printSearchState(current);
//printFile(current);
reconstructPath(current);
return step;
}
// at current, so add to visited list
frontier.pop();
visited.push_back(current);
// find possible child nodes
current->state.getChildren(this);
for (int i=0; i<children.size(); i++) {
int tmpG = current->g + current->state.G();
// check visited list if child is on it or has
// more expensive path
if (isBetterPath(children[i], tmpG)) {
continue;
}
// discovered new node
children[i]->parent = current;
children[i]->g = tmpG;
children[i]->h = children[i]->state.H(goal->state);
children[i]->f = children[i]->g + children[i]->h;
children[i]->depth = current->depth + 1;
frontier.push(children[i]);
}
//printSearchState(current);
step++;
}
/*if (current != NULL)
printFile(current);
*/
return -1;
}