-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEfficientAstar.h
176 lines (164 loc) · 5.32 KB
/
EfficientAstar.h
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
173
174
175
176
#pragma once
#include <vector>
#include <iostream>
#include <queue>
#include <map>
#include <cstdint>
//
//template <typename state>
//struct Node
//{
// state c;
// int gcost;
// int hcost;
// int fcost;
// uint64_t rank;
//};
struct tupler{
int fcost;
uint64_t rank;
tupler(int f, uint64_t r){
fcost = f;
rank = r;
}
inline bool operator<(const tupler &c1) const
{
return this->fcost > c1.fcost;
}
};
template<typename state, typename action, typename environment, typename heuristic>
class EfficientAstar
{
public:
int nodesExpanded = 0;
bool getPath(environment &e, state &start, state &goal, heuristic h);
private:
void addOpen(Node<state> &s);
void addClosed(Node<state> &s);
bool onClosed(Node<state> &s);
bool onOpen(Node<state> &s);
void updateCost(Node<state> &c);
Node<state> removeBest();
std::priority_queue<tupler> queue;
std::map<uint64_t, Node<state>> open;
std::map<uint64_t, Node<state>> closed;
};
template<typename state, typename action, typename environment, typename heuristic>
bool EfficientAstar<state, action, environment, heuristic>::getPath(environment &e, state &start, state &goal, heuristic h)
{
//initialize actions and state so we dont create them on every iteration
std::vector<action> actions;
Node<state> s;
s.c = start;
//set up start node
s.gcost = 0;
s.hcost = h.hcost(start, goal);
s.fcost = s.gcost + s.hcost;
s.rank = e.Rank(s.c);
//put start node on the open list
addOpen(s);
//keep searching as long as there are nodes on the open list
while (!queue.empty())
{
s.rank = e.Rank(s.c);
//remove node with lowest fcost from the open list
s = removeBest();
//if lowest f cost node from open list is goal, return found path
if (s.c == goal)
{
std::cout << "Nodes Expanded: "<< nodesExpanded << std::endl;
return true;
}
//generate successors of best available node from open list
e.GetActions(s.c, actions);
nodesExpanded++;
//for each action that can be taken from that node
for (action &a : actions)
{
//apply the action to generate a new state
e.ApplyAction(s.c, a);
s.rank = e.Rank(s.c);
if (!onClosed(s) && onOpen(s))
{
//if on open already, then update cost if needed
s.gcost++;
s.hcost = h.hcost(s.c, goal);
s.fcost = s.gcost + s.hcost;
updateCost(s);
e.UndoAction(s.c, a);
s.gcost--;
}
else if (!onClosed(s) && !onOpen(s))
{
//if not on open or closed, its a newly discovered node
//so set costs and add to open
s.gcost++;
s.hcost = h.hcost(s.c, goal);
s.fcost = s.gcost + s.hcost;
addOpen(s);
e.UndoAction(s.c, a);
s.gcost--;
}
else
{
//node is on closed
//skip this node
//the hashmap is initialized with the goal at the 0th element
//so, goal is always on closed
//have to check if element is goal before we skip it
if(s.c == goal) {
std::cout << nodesExpanded << std::endl;
return true;
}
e.UndoAction(s.c, a);
}
}
}
return false;
}
template<typename state, typename action, typename environment, typename heuristic>
void EfficientAstar<state, action, environment, heuristic>::addOpen(Node<state> &s)
{
//create tuple type for queue
tupler tup(s.fcost, s.rank);
//insert tuple into queue
queue.push(tup);
//insert rank and node into hashmap
open[s.rank] = s;
}
template<typename state, typename action, typename environment, typename heuristic>
void EfficientAstar<state, action, environment, heuristic>::addClosed(Node<state> &s)
{
//insert rank and node into hashmap
closed.insert(std::pair<uint64_t , Node<state>>(s.rank, s));
}
template<typename state, typename action, typename environment, typename heuristic>
bool EfficientAstar<state, action, environment, heuristic>::onOpen(Node<state> &s)
{
return s.c == open[s.rank].c;
}
template<typename state, typename action, typename environment, typename heuristic>
bool EfficientAstar<state, action, environment, heuristic>::onClosed(Node<state> &s)
{
return s.c == closed[s.rank].c;
}
template<typename state, typename action, typename environment, typename heuristic>
Node<state> EfficientAstar<state, action, environment, heuristic>::removeBest()
{
//get top element, pop
tupler tup = queue.top();
queue.pop();
//get element at that rank and remove from map
Node<state> s = open[tup.rank];
open.erase(tup.rank);
//add to closed map
addClosed(s);
return s;
}
template<typename state, typename action, typename environment, typename heuristic>
void EfficientAstar<state, action, environment, heuristic>::updateCost(Node<state> &s)
{
//When we assign things to the hashmap, it will overwrite the object there, so thats the update for the hashmaps
if(onOpen(s) && open[s.rank].fcost > s.fcost)
open[s.rank] = s;
}