-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
208 lines (168 loc) · 7.7 KB
/
main.cpp
File metadata and controls
208 lines (168 loc) · 7.7 KB
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// main.cpp
#include "CityGraph.h"
#include "BreadthFirstSearch.h"
#include "DepthFirstSearch.h"
#include "IDDFS.h"
#include "BestFirstSearch.h"
#include "AStarSearch.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <chrono>
string citiesFilename = "coordinates.csv";
string adjacenciesFilename = "Adjacencies.txt";
void parseCities(const string& filename, CityGraph& graph);
void parseAdjacencies(const string& filename, CityGraph& graph);
void validateCityName(const CityGraph& graph, string& cityName);
void displayResult(const string& algorithmName, const vector<string>& path, double totalDistance, chrono::microseconds duration) {
if (!path.empty()) {
cout << "Path found using " << algorithmName << ": ";
for (const auto& city : path) {
cout << city << " -> ";
}
cout << "end\n";
cout << "Total Distance: " << totalDistance << endl;
cout << "Time taken to find the route: " << duration.count() << " microseconds" << endl;
}
else {
cout << "No path found using " << algorithmName << "." << endl;
cout << "Time taken to find the route: NaN microseconds" << endl;
}
}
int main() {
// Variable used for user selection of algorithms
int selection = 0;
// Variable used for calculating drive time, can be adjusted for better modularity
double speed = 60;
// Initialize the graph structure
CityGraph graph;
// Call functions to parse cities from CSV & txt files
parseCities(citiesFilename, graph);
parseAdjacencies(adjacenciesFilename, graph);
// Rest of your main function (user interaction, algorithm selection, etc.)
std::cout << "Welcome to the Search Method Program! Please select your preferred search algorithm/technique"
" by the number indicated to the left of the option (numbers only, no symbols):\n"
"[1] Breath First Search\n"
"[2] Depth First Search\n"
"[3] Iterative Deepening Depth First Search\n"
"[4] Best-First Search\n"
"[5] A* Search\n"
"[6] Quit" << endl;
std::cin >> selection;
while (selection != 6) {
string start = "";
string goal = "";
double totalDistance = 0.0;
std::cout << "Submit the starting point name: ";
std::cin >> start;
validateCityName(graph, start);
std::cout << "Submit the objective name: ";
std::cin >> goal;
validateCityName(graph, goal);
/* Note: While yes the following time durations could be calcuated using some level of abstraction,
a concern with isolating the operation to explicitly only algorithmic operation persists from segment to segment. Therefore,
to eliminate any potential added operation time for explicitly this circumstance I am violating the DRY Principle only for
this specific use case. */
switch (selection) {
case 1: {
// System Timer Begins
chrono::time_point<chrono::high_resolution_clock> timeStart = chrono::high_resolution_clock::now();
vector <string> path = breadthFirstSearch(graph, start, goal, totalDistance);
// System Timer Ends
chrono::time_point<chrono::high_resolution_clock> timeStop = chrono::high_resolution_clock::now();
// Calculate duration
chrono::microseconds duration = chrono::duration_cast<chrono::microseconds>(timeStop - timeStart);
displayResult("BFS", path, totalDistance, duration);
break;
}
case 2: {
// System Timer Begins
chrono::time_point<chrono::high_resolution_clock> timeStart = chrono::high_resolution_clock::now();
const vector <string> path = depthFirstSearch(graph, start, goal, totalDistance);
// System Timer Ends
chrono::time_point<chrono::high_resolution_clock> timeStop = chrono::high_resolution_clock::now();
// Calculate duration
chrono::microseconds duration = chrono::duration_cast<chrono::microseconds>(timeStop - timeStart);
displayResult("DFS", path, totalDistance, duration);
break;
}
case 3: {
// System Timer Begins
chrono::time_point<chrono::high_resolution_clock> timeStart = chrono::high_resolution_clock::now();
const vector<string> path = IDDFS(graph, start, goal, totalDistance);
// System Timer Ends
chrono::time_point<chrono::high_resolution_clock> timeStop = chrono::high_resolution_clock::now();
// Calculate Duration
chrono::microseconds duration = chrono::duration_cast<chrono::microseconds>(timeStop - timeStart);
displayResult("IDDFS", path, totalDistance, duration);
break;
}
case 4: {
// System Timer Begins
chrono::time_point<chrono::high_resolution_clock> timeStart = chrono::high_resolution_clock::now();
const vector<string> path = bestFirstSearch(graph, start, goal, totalDistance);
// System Timer Ends
chrono::time_point<chrono::high_resolution_clock> timeStop = chrono::high_resolution_clock::now();
// Calculate Duration
chrono::microseconds duration = chrono::duration_cast<chrono::microseconds>(timeStop - timeStart);
displayResult("Best-First Search", path, totalDistance, duration);
}
case 5: {
std::cout << "Algorithm incomplete" << endl;
break;
}
case 6: {
break;
}
default:
std::cout << "Input not recognized. Try again." << endl;
}
std::cout << "For another algorithm, select a different number than your previous entry. Else, enter 6 to quit the program:" << endl
<< "[1] Breath First Search" << endl
<< "[2] Depth First Search" << endl
<< "[3] Iterative Deepening Depth First Search" << endl
<< "[4] Best-First Search" << endl
<< "[5] A* Search" << endl
<< "[6] Quit" << endl;
std::cin >> selection;
}
}
// Function intended to begin reading and processing the cities within Coordinates.csv
void parseCities(const string& filename, CityGraph& graph) {
ifstream file(filename);
ifstream adjFile(adjacenciesFilename);
string line;
/* As of typing, there is NO header line within the csv file. For this to work,
there cannot be a header line within the csv else this breaks the program reading */
while (getline(file, line)) {
stringstream linestream(line);
string cityName, lat, lon;
getline(linestream, cityName, ',');
getline(linestream, lat, ',');
getline(linestream, lon, ',');
City city(cityName, std::stod(lat), std::stod(lon));
graph[cityName] = city;
}
}
// Function intended to begin reading and processing city adjacency from Adjacencies.txt
void parseAdjacencies(const string& filename, CityGraph& graph) {
ifstream file(filename);
ifstream adjFile(adjacenciesFilename);
string line;
while (getline(adjFile, line)) {
istringstream iss(line);
string city1, city2;
iss >> city1 >> city2;
// Assuming symmetric adjacency
graph[city1].adjacents.push_back(city2);
graph[city2].adjacents.push_back(city1);
}
}
// Function to validate city names upon input
void validateCityName(const CityGraph& graph, string& cityName) {
while (graph.find(cityName) == graph.end()) {
std::cout << "City name '" << cityName << "' does not exist within 'Coordinates.csv'. Please enter a valid city name: ";
std::cin >> cityName;
}
}