-
Notifications
You must be signed in to change notification settings - Fork 0
/
Dijkstra_Find.h
executable file
·194 lines (180 loc) · 4.4 KB
/
Dijkstra_Find.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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#pragma once
#include <vector>
#include <iostream>
#include "Dijkstra_label.h"
//template <typename state>
//struct Node
//{
// state c;
// int gcost;
// int hcost;
// int fcost;
// uint64_t rank;
//};
template<typename state, typename action, typename environment>
class Dijkstra_find
{
public:
int nodesExpanded = 0;
state getPath(environment &e, std::vector<pivot_info> &pivots);
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, int i);
int getDuplicateIndex(Node<state> &s);
Node<state> removeBest();
std::vector<Node<state>> open;
std::vector<Node<state>> closed;
};
template<typename state, typename action, typename environment>
state Dijkstra_find<state, action, environment>::getPath(environment &e, std::vector<pivot_info> &pivots)
{
Node<state> s;
for (auto &i : pivots)
{
s.c = i.pivot;
//set up start node
s.gcost = 0;
s.hcost = 0;
s.fcost = s.gcost + s.hcost;
//put start node on the open list
addOpen(s);
}
//initialize actions and state so we dont create them on every iteration
std::vector<action> actions;
//keep searching as long as there are nodes on the open list
while (!open.empty())
{
//remove node with lowest fcost from the open list
s = removeBest();
nodesExpanded++;
//generate successors of best available node from open list
e.GetActions(s.c, actions);
//add node to closed list
addClosed(s);
//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);
//if (!onClosed(s) && onOpen(s))
//{
// //if on open already, then update cost if needed
// s.gcost++;
// s.hcost = 0;
// s.fcost = s.gcost + s.hcost;
// int i = getDuplicateIndex(s);
// updateCost(s, i);
// e.UndoAction(s.c, a);
// s.gcost--;
//}
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 = 0;
s.fcost = s.gcost + s.hcost;
addOpen(s);
e.UndoAction(s.c, a);
s.gcost--;
}
else
{
//node is on closed
//skip this node
e.UndoAction(s.c, a);
}
}
}
return s.c;
}
template<typename state, typename action, typename environment>
void Dijkstra_find<state, action, environment>::addOpen(Node<state> &s)
{
open.push_back(s);
}
template<typename state, typename action, typename environment>
void Dijkstra_find<state, action, environment>::addClosed(Node<state> &s)
{
closed.push_back(s);
}
template<typename state, typename action, typename environment>
bool Dijkstra_find<state, action, environment>::onOpen(Node<state> &s)
{
for (int i = 0; i < open.size(); i++)
{
if (s.c == open[i].c)
{
return true;
}
}
return false;
}
template<typename state, typename action, typename environment>
bool Dijkstra_find<state, action, environment>::onClosed(Node<state> &s)
{
for (int i = 0; i < closed.size(); i++)
{
if (s.c == closed[i].c)
{
return true;
}
}
return false;
}
template<typename state, typename action, typename environment>
int Dijkstra_find<state, action, environment>::getDuplicateIndex(Node<state> &s)
{
for (int i = 0; i < open.size(); i++)
{
if (s.c == open[i].c)
{
return i;
}
}
std::cout << "Error: getDuplicateIndex() couldn't find a duplicate" << std::endl;
return -1;
}
template<typename state, typename action, typename environment>
Node<state> Dijkstra_find<state, action, environment>::removeBest()
{
Node<state> best = open[0];
if (open.size() == 1)
{
open.erase(open.begin());
return best;
}
int index = 0;
for (int i = 1; i < open.size(); i++)
{
if (open[i].fcost < best.fcost)
{
index = i;
best = open[i];
}
else if (open[i].fcost == best.fcost)
{
//ties go to high g cost
if (open[i].gcost >= best.gcost)
{
index = i;
best = open[i];
}
}
}
open.erase(open.begin() + index);
return best;
}
template<typename state, typename action, typename environment>
void Dijkstra_find<state, action, environment>::updateCost(Node<state> &s, int i)
{
if (s.fcost < open[i].fcost)
{
open[i].fcost = s.fcost;
open[i].gcost = s.gcost;
open[i].hcost = s.hcost;
}
}