20 #include <tensor/jobs.h>
26 bool is_separator(
char c)
28 return (c ==
' ') || (c ==
'\t') || (c ==
'\n') || (c ==
',') || (c ==
';');
31 std::vector<std::string>
32 split_string(
const std::string &s)
34 std::vector<std::string> output;
35 size_t i = 0, l = s.size();
37 while (is_separator(s[i])) {
42 for (j = i+1; (j < l) && !is_separator(s[j]); j++) {
45 output.push_back(s.substr(i, j-i));
51 const Job::Variable Job::no_variable;
54 Job::parse_line(
const std::string &s)
56 std::vector<std::string> data = split_string(s);
66 if (data.size() == 1) {
67 std::cerr <<
"Missing minimum value for variable " << data[0] << std::endl;
70 double max, min = atof(data[1].c_str());
72 if (data.size() == 2) {
76 max = atof(data[2].c_str());
77 if (data.size() == 3) {
79 }
else if (data.size() > 4) {
80 std::cerr <<
"Too many arguments for variable " << data[0] << std::endl;
83 nsteps = atoi(data[3].c_str());
86 return Variable(data[0], min, max, nsteps);
90 Job::parse_file(std::istream &s, var_list &data)
94 for (line = 0; 1; line++) {
95 const Variable v = parse_line(buffer);
96 if (v.name().size() == 0)
104 Job::Job(
int argc,
const char **argv) :
108 bool print_jobs =
false;
109 bool first_job_found =
false;
110 bool last_job_found =
false;
111 bool job_blocks_found =
false;
112 bool this_job_found =
false;
113 tensor::index blocks;
114 tensor::index current_job;
116 for (i = 0; i < argc; i++) {
117 if (!strcmp(argv[i],
"--job")) {
119 std::cerr <<
"Missing argument after --job" << std::endl;
122 filename_ = std::string(argv[i]);
123 std::ifstream s(argv[i]);
124 int line = parse_file(s, variables_);
126 std::cerr <<
"Syntax error in line " << line <<
" of job file " << filename_
131 }
else if (!strcmp(argv[i],
"--print-jobs")) {
133 }
else if (!strcmp(argv[i],
"--this-job")) {
135 std::cerr <<
"Missing argument to --this-job" << std::endl;
138 current_job = atoi(argv[i]);
139 this_job_found =
true;
140 }
else if (!strcmp(argv[i],
"--job-blocks")) {
142 std::cerr <<
"Missing argument to --job-blocks" << std::endl;
145 blocks = atoi(argv[i]);
146 job_blocks_found =
true;
147 }
else if (!strcmp(argv[i],
"--first-job")) {
148 if (this_job_found) {
149 std::cerr <<
"Cannot use --first-job and --this-job simultaneously." << std::endl;
153 std::cerr <<
"Missing argument to --first-job" << std::endl;
156 first_job_ = atoi(argv[i]);
157 first_job_found =
true;
158 }
else if (!strcmp(argv[i],
"--last-job")) {
159 if (!first_job_found) {
160 std::cerr <<
"--last-job without preceding --first-job" << std::endl;
164 std::cerr <<
"Missing argument to --last-job" << std::endl;
167 last_job_ = atoi(argv[i]);
168 last_job_found =
true;
169 }
else if (!strcmp(argv[i],
"--variable")) {
171 std::cerr <<
"Missing argument after --variable" << std::endl;
174 Variable v = parse_line(argv[i]);
175 if (v.name().size() == 0) {
176 std::cerr <<
"Syntax error parsing --variable argument:" << std::endl
177 << argv[i] << std::endl;
180 variables_.push_back(v);
182 }
else if (!strcmp(argv[i],
"--help")) {
183 std::cout <<
"Arguments:\n"
185 "\tShow this message and exit.\n"
187 "\tShow number of jobs and exit.\n"
188 "--first-job / --last-job n\n"
189 "\tRun this program completing the selected interval of jobs.\n"
191 "\tSelect to run one job or one job block.\n"
193 "\tSplit the number of blocks into 'n' blocks and run the jobs in the\n"
194 "\tblock selected by --this-job.\n"
195 "--variable name,min[,max[,nsteps]]\n"
196 "\tDefine variable and the range it runs, including number of steps.\n"
197 "\t'min' and 'max' are floating point numbers; 'name' is a string\n"
198 "\twithout spaces; 'nsteps' is a positive (>0) integer denoting how\n"
199 "\tmany values in the interval [min,max] are used. There can be many\n"
200 "\t--variable arguments, as a substitute for a job file. If both 'max'\n"
201 "\tand 'nsteps' are missing, the variable takes a unique, constant\n"
204 "\tParse file, loading variable ranges from them using the syntax above,\n"
205 "\tbut allowing spaces or tabs instead of commas as separators."
210 number_of_jobs_ = compute_number_of_jobs();
212 std::cout << number_of_jobs_;
215 if (job_blocks_found) {
220 if (first_job_found || last_job_found) {
221 std::cerr <<
"The options --job-blocks and --first/last-job cannot be used together."
226 std::cerr <<
"The number of job blocks cannot be zero or negative.";
229 tensor::index delta = (number_of_jobs_ + blocks - 1) / blocks;
230 first_job_ = current_job = std::min(current_job * delta, number_of_jobs_);
231 last_job_ = std::min(number_of_jobs_ - 1, first_job_ + delta - 1);
232 }
else if (first_job_found) {
236 if (first_job_ < 0) {
237 std::cerr <<
"--first-job is negative" << std::endl;
239 }
else if (first_job_ >= number_of_jobs_) {
240 std::cerr <<
"--first-job exceeds the number of jobs" << std::endl;
243 if (last_job_found) {
244 if (last_job_ >= number_of_jobs_) {
245 std::cerr <<
"warning: --last-job exceeds the number of jobs" << std::endl;
246 last_job_ = std::max<tensor::index>(0, number_of_jobs_ - 1);
248 if (last_job_ < first_job_) {
249 std::cerr <<
"--last-job is smaller than --first-job" << std::endl;
253 current_job = first_job_;
254 }
else if (this_job_found) {
258 first_job_ = last_job_ = current_job;
263 first_job_ = current_job = 0;
264 last_job_ = number_of_jobs_ - 1;
266 select_job(current_job);
270 Job::compute_number_of_jobs()
const
273 for (var_list::const_iterator it = variables_.begin();
274 it != variables_.end();
282 Job::select_job(tensor::index which)
285 tensor::index i = this_job_ = which;
286 if (which <= number_of_jobs_) {
287 for (var_list::iterator it = variables_.begin();
288 it != variables_.end();
290 tensor::index n = it->size();
300 select_job(this_job_ + 1);
306 return (this_job_ >= 0) &&
307 (this_job_ < number_of_jobs_) &&
308 (this_job_ >= first_job_) &&
309 (this_job_ <= last_job_);
312 const Job::Variable *
313 Job::find_variable(
const std::string &name)
const
315 for (var_list::const_iterator it = variables_.begin(); it != variables_.end(); it++) {
316 if (it->name() == name) {
324 Job::get_value(
const std::string &name)
const
326 const Variable *which = find_variable(name);
328 std::cerr <<
"Variable " << name <<
" not found in job file "
329 << filename_ << std::endl;
332 return which->value();
337 Job::get_value_with_default(
const std::string &name,
double def)
const
339 const Variable *which = find_variable(name);
340 return which? which->value() : def;