-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
218 lines (197 loc) · 7.53 KB
/
main.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
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
209
210
211
212
213
214
215
216
217
218
#include <iostream>
#include <fstream>
#include <filesystem>
#include <vector>
#include <assert.h>
#include "P2D/P2D.hpp"
#include "VG2/VG2.hpp"
#include "ANYA2/ANYA2.hpp"
#include "TS2/TS2.hpp"
#include "R2/R2.hpp"
struct Args
{
std::filesystem::path result_dir = "", map_dir = "", scen_dir = "";
std::vector<std::filesystem::path> names, algs;
std::vector<int> ids;
int num_expts = 1;
};
inline bool isOption(const std::string &test) { return test.size() > 2 && test.substr(0, 2) == "--"; }
bool isValidOption(const std::string &option)
{
return (option == "--num_expts" || option == "--result_dir" || option == "--map_dir" || option == "--scen_dir" || option == "--names" || option == "--algs" || option == "--ids");
}
void parseOption(Args &args, const std::string &option, int &arg_idx, const int &argc, char **&argv)
{
assert(isOption(option));
bool specified = false;
while (1)
{
if (arg_idx >= argc)
break;
std::string arg(argv[arg_idx]);
if (isOption(arg) == true)
{
if (isValidOption(arg) == false)
throw std::runtime_error("Invalid option: " + arg);
parseOption(args, arg, ++arg_idx, argc, argv);
break;
}
if (specified == true)
std::cout << "[WARN]: " << option << " is specified more than once. The last value will be used." << std::endl;
if (option == "--num_expts")
{
args.num_expts = std::stoi(arg);
if (args.num_expts <= 0)
throw std::out_of_range("--num_expts must be at least 1");
}
else if (option == "--result_dir")
{
args.result_dir = arg;
specified = true;
}
else if (option == "--map_dir")
{
args.map_dir = arg;
specified = true;
}
else if (option == "--scen_dir")
{
args.scen_dir = arg;
specified = true;
}
else if (option == "--names")
{
args.names.emplace_back(arg);
}
else if (option == "--algs")
{
if (arg == "VG2B" || arg == "VG2N" || arg == "TS2B" || arg == "TS2N" || arg == "ANYA2B" || arg == "ANYA2N" || arg == "R2")
args.algs.emplace_back(arg);
else
throw std::out_of_range("--algs must be one of the following: VG2B, VG2N, TS2B, TS2N, ANYA2B, ANYA2N, R2");
}
else if (option == "--ids")
{
if (args.ids.empty() == true || args.ids.back() != -1)
{
int id = std::stoi(arg);
if (id < 0)
args.ids = {-1};
else
args.ids.push_back(id);
}
}
++arg_idx;
}
}
void parseOptions(Args &args, const int &argc, char **&argv)
{
int arg_idx = 1;
std::string option(argv[arg_idx]);
if (isOption(option) == true)
{
if (isValidOption(option) == false)
throw std::runtime_error("Invalid option: " + option);
parseOption(args, option, ++arg_idx, argc, argv);
}
else
throw std::runtime_error(std::string("Must start with a '--' option, and not '") + option + "'");
}
int main(int argc, char *argv[])
{
Args args;
parseOptions(args, argc, argv);
if (args.names.empty() == true)
throw std::out_of_range("At least one file must be specified for --names. If a pair of scenario file 'arena.map.scen' and map file 'arena.map' are to be run, and the files are located in the sub-directory 'dao', then the argument is: '--name dao/arena'. Specify other pairs with spaces: '--name dao/arena da2/ht_mansion2b sc1/Aurora'");
if (args.algs.empty() == true)
throw std::out_of_range("At least one file must be specified for --algs. If 'TS2B' is to be run, the argument is '--algs TS2B'. Multiple algorithms can be specified: '--algs TS2B ANYA2B VG2B'");
if (args.ids.empty() == true)
args.ids = {-1};
// check if scen file and map file exists
std::vector<std::array<std::filesystem::path, 3>> fpaths;
for (const std::filesystem::path name : args.names)
{
std::filesystem::path fp_map = args.map_dir / name;
fp_map.replace_extension("map");
if (std::filesystem::exists(fp_map) == false)
throw std::out_of_range("Map file " + fp_map.string() + " does not exist!");
std::filesystem::path fp_scen = args.map_dir / name;
fp_scen.replace_extension("map.scen");
if (std::filesystem::exists(fp_scen) == false)
throw std::out_of_range("Scen file " + fp_scen.string() + " does not exist!");
fpaths.push_back({fp_map, fp_scen, name});
}
for (int i = 0; i < args.num_expts; ++i)
{
std::string suffix_expt_num = args.num_expts > 1 ? "." + std::to_string(i) : "";
for (const auto &fpath : fpaths)
{
P2D::Grid grid;
P2D::getMap(grid, fpath[0]);
for (const auto &alg : args.algs)
{
P2D::Scenarios scens;
scens.fp_map = fpath[0];
scens.fp_scen = fpath[1];
scens.fp_name = fpath[2];
scens.fp_alg = alg;
scens.fp_results = args.result_dir / scens.fp_name;
scens.fp_results.replace_extension(alg.string() + suffix_expt_num + ".results");
P2D::getScenarios(scens);
if (alg == "TS2B")
{
P2D::TS2::TS2<true> alg(&grid);
for (int id : args.ids)
P2D::run(&alg, scens, id);
}
else if (alg == "TS2N")
{
P2D::TS2::TS2<false> alg(&grid);
for (int id : args.ids)
P2D::run(&alg, scens, id);
}
else if (alg == "VG2B")
{
std::filesystem::path fp_vg = "VG2/combinations";
fp_vg = fp_vg / scens.fp_name;
fp_vg.replace_extension(".VG2B.combinations");
P2D::VG2::VG2<true> alg(&grid, fp_vg);
for (int id : args.ids)
P2D::run(&alg, scens, id);
}
else if (alg == "VG2N")
{
std::filesystem::path fp_vg = "VG2/combinations";
fp_vg = fp_vg / scens.fp_name;
fp_vg.replace_extension(".VG2N.combinations");
P2D::VG2::VG2<false> alg(&grid, fp_vg);
for (int id : args.ids)
P2D::run(&alg, scens, id);
}
else if (alg == "ANYA2B")
{
P2D::ANYA2::ANYA2<true> alg(&grid);
for (int id : args.ids)
P2D::run(&alg, scens, id);
}
else if (alg == "ANYA2N")
{
P2D::ANYA2::ANYA2<false> alg(&grid);
for (int id : args.ids)
P2D::run(&alg, scens, id);
}
else if (alg == "R2")
{
P2D::R2::R2 alg(&grid);
for (int id : args.ids)
P2D::run(&alg, scens, id);
}
else
throw std::out_of_range("Invalid algorithm: " + alg.string());
if (args.ids.front() == -1)
P2D::writeResults(scens);
}
}
}
return 0;
}