this repo has no description
at develop 30 kB view raw
1 2/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 3 4/* 5 * Main authors: 6 * Guido Tack <guido.tack@monash.edu> 7 * Gleb Belov <gleb.belov@monash.edu> 8 */ 9 10/* This Source Code Form is subject to the terms of the Mozilla Public 11 * License, v. 2.0. If a copy of the MPL was not distributed with this 12 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 13 14/* This (main) file coordinates flattening and solving. 15 * The corresponding modules are flexibly plugged in 16 * as derived classes, prospectively from DLLs. 17 * A flattening module should provide MinZinc::GetFlattener() 18 * A solving module should provide an object of a class derived from SolverFactory. 19 * Need to get more flexible for multi-pass & multi-solving stuff TODO 20 */ 21 22#ifdef _MSC_VER 23#define _CRT_SECURE_NO_WARNINGS 24#endif 25 26#include <chrono> 27#include <cstdlib> 28#include <ctime> 29#include <fstream> 30#include <iomanip> 31#include <iostream> 32#include <ratio> 33 34using namespace std; 35 36#include <minizinc/file_utils.hh> 37#include <minizinc/model.hh> 38#include <minizinc/parser.hh> 39#include <minizinc/prettyprinter.hh> 40#include <minizinc/reader.hh> 41#include <minizinc/utils.hh> 42 43namespace MiniZinc { 44 45MznReader::MznReader(std::ostream& os0, std::ostream& log0) 46 : solver_configs(log0), /*flt(os0,log0,solver_configs.mznlibDir()), */ os(os0), log(log0) {} 47 48MznReader::~MznReader() { GC::trigger(); } 49 50void MznReader::printUsage() { 51 os << "TODO: print usage" << std::endl; 52 /* 53 os << executable_name << ": "; 54 if ( ifMzn2Fzn() ) { 55 os 56 << "MiniZinc to FlatZinc converter.\n" 57 << "Usage: " << executable_name 58 << " [<options>] [-I <include path>] <model>.mzn [<data>.dzn ...]" << std::endl; 59 } else if (ifSolns2out()) { 60 os 61 << "Solutions to output translator.\n" 62 << "Usage: " << executable_name 63 << " [<options>] <model>.ozn" << std::endl; 64 } else { 65 os 66 << "MiniZinc driver.\n" 67 << "Usage: " << executable_name 68 << " [<options>] [-I <include path>] <model>.mzn [<data>.dzn ...] or just <flat>.fzn" << 69 std::endl; 70 } 71 */ 72} 73 74void MznReader::printHelp(const std::string& selectedSolver) { 75 printUsage(); 76 os << "TODO: print help" << std::endl; 77 /* 78 os 79 << "General options:" << std::endl 80 << " --help, -h\n Print this help message." << std::endl 81 << " --version\n Print version information." << std::endl 82 << " --solvers\n Print list of available solvers." << std::endl 83 << " --time-limit <ms>\n Stop after <ms> milliseconds (includes compilation and solving)." 84 << std::endl 85 << " --solver <solver id>, --solver <solver config file>.msc\n Select solver to use." << 86 std::endl 87 << " --help <solver id>\n Print help for a particular solver." << std::endl 88 << " -v, -l, --verbose\n Print progress/log statements. Note that some solvers may log to 89 stdout." << std::endl 90 << " --verbose-compilation\n Print progress/log statements for compilation." << std::endl 91 << " -s, --statistics\n Print statistics." << std::endl 92 << " --compiler-statistics\n Print statistics for compilation." << std::endl 93 << " -c, --compile\n Compile only (do not run solver)." << std::endl 94 << " --config-dirs\n Output configuration directories." << std::endl; 95 96 if (selectedSolver.empty()) { 97 flt.printHelp(os); 98 os << endl; 99 if ( !ifMzn2Fzn() ) { 100 s2out.printHelp(os); 101 os << endl; 102 } 103 os << "Available solvers (get help using --help <solver id>):" << endl; 104 std::vector<std::string> solvers = solver_configs.solvers(); 105 if (solvers.size()==0) 106 cout << " none.\n"; 107 for (unsigned int i=0; i<solvers.size(); i++) { 108 cout << " " << solvers[i] << endl; 109 } 110 } else { 111 const SolverConfig& sc = solver_configs.config(selectedSolver); 112 string solverId = sc.executable().empty() ? sc.id() : (sc.supportsMzn() ? 113 string("org.minizinc.mzn-mzn") : string("org.minizinc.mzn-fzn")); bool found = false; for (auto it 114 = getGlobalSolverRegistry()->getSolverFactories().rbegin(); it != 115 getGlobalSolverRegistry()->getSolverFactories().rend(); ++it) { if ((*it)->getId()==solverId) { os 116 << endl; 117 (*it)->printHelp(os); 118 if (!sc.executable().empty() && !sc.extraFlags().empty()) { 119 os << "Extra solver flags (use with "; 120 os << (sc.supportsMzn() ? "--mzn-flags" : "--fzn-flags") << ")" << endl; 121 for (const SolverConfig::ExtraFlag& ef: sc.extraFlags()) { 122 os << " " << ef.flag << endl << " " << ef.description << endl; 123 } 124 } 125 found = true; 126 } 127 } 128 if (!found) { 129 os << "No help found for solver " << selectedSolver << endl; 130 } 131 } 132 */ 133} 134 135bool MznReader::processOption(int& i, std::vector<std::string>& argv) { 136 CLOParser cop(i, argv); 137 string buffer; 138 139 if (cop.getOption("-I --search-dir", &buffer)) { 140 includePaths.push_back(buffer + string("/")); 141 } else if (cop.getOption("--ignore-stdlib")) { 142 flag_ignoreStdlib = true; 143 /* 144 } else if ( cop.getOption( "--instance-check-only") ) { 145 flag_instance_check_only = true; 146 } else if ( cop.getOption( "-e --model-check-only") ) { 147 flag_model_check_only = true; 148 } else if ( cop.getOption( "--model-interface-only") ) { 149 flag_model_interface_only = true; 150 } else if ( cop.getOption( "--model-types-only") ) { 151 flag_model_types_only = true; 152 */ 153 } else if (cop.getOption("-v --verbose")) { 154 flag_verbose = true; 155 /* 156 } else if ( cop.getOption( "--no-optimize --no-optimise") ) { 157 flag_optimize = false; 158 } else if ( cop.getOption( "--no-output-ozn -O-") ) { 159 flag_no_output_ozn = true; 160 } else if ( cop.getOption( "--output-base", &flag_output_base ) ) { 161 } else if ( cop.getOption( 162 fOutputByDefault ? 163 "-o --fzn --output-to-file --output-fzn-to-file" 164 : "--fzn --output-fzn-to-file", &flag_output_fzn) ) { 165 } else if ( cop.getOption( "--output-paths-to-file", &flag_output_paths) ) { 166 fopts.collect_mzn_paths = true; 167 } else if ( cop.getOption( "--output-paths") ) { 168 fopts.collect_mzn_paths = true; 169 */ 170 /* 171 } else if ( cop.getOption( "--output-to-stdout --output-fzn-to-stdout" ) ) { 172 flag_output_fzn_stdout = true; 173 } else if ( cop.getOption( "--output-ozn-to-stdout" ) ) { 174 flag_output_ozn_stdout = true; 175 } else if ( cop.getOption( "--output-paths-to-stdout" ) ) { 176 fopts.collect_mzn_paths = true; 177 flag_output_paths_stdout = true; 178 } else if ( cop.getOption( "--output-mode", &buffer ) ) { 179 if (buffer == "dzn") { 180 flag_output_mode = FlatteningOptions::OUTPUT_DZN; 181 } else if (buffer == "json") { 182 flag_output_mode = FlatteningOptions::OUTPUT_JSON; 183 } else if (buffer == "item") { 184 flag_output_mode = FlatteningOptions::OUTPUT_ITEM; 185 } else { 186 return false; 187 } 188 } else if ( cop.getOption( "--output-objective" ) ) { 189 flag_output_objective = true; 190 } else if ( cop.getOption( "- --input-from-stdin" ) ) { 191 flag_stdinInput = true; 192 */ 193 } else if (cop.getOption("-d --data", &buffer)) { 194 if (buffer.length() <= 4 || buffer.substr(buffer.length() - 4, string::npos) != ".dzn") 195 return false; 196 datafiles.push_back(buffer); 197 } else if (cop.getOption("--stdlib-dir", &std_lib_dir)) { 198 } else if (cop.getOption("-G --globals-dir --mzn-globals-dir", &globals_dir)) { 199 } else if (cop.getOption("-D --cmdline-data", &buffer)) { 200 datafiles.push_back("cmd:/" + buffer); 201 } else if (cop.getOption("--allow-unbounded-vars")) { 202 flag_allow_unbounded_vars = true; 203 } else if (cop.getOption("--only-range-domains")) { 204 flag_only_range_domains = true; 205 /* 206 } else if ( cop.getOption( "--no-MIPdomains" ) ) { // internal 207 flag_noMIPdomains = true; 208 } else if ( cop.getOption( "--MIPDMaxIntvEE", &opt_MIPDmaxIntvEE ) ) { 209 } else if ( cop.getOption( "--MIPDMaxDensEE", &opt_MIPDmaxDensEE ) ) { 210 */ 211 } else if (cop.getOption("-Werror")) { 212 flag_werror = true; 213 /* 214 } else if (string(argv[i])=="--use-gecode") { 215#ifdef HAS_GECODE 216 flag_two_pass = true; 217 flag_gecode = true; 218#else 219 log << "warning: Gecode not available. Ignoring '--use-gecode'\n"; 220#endif 221 } else if (string(argv[i])=="--sac") { 222#ifdef HAS_GECODE 223 flag_two_pass = true; 224 flag_gecode = true; 225 flag_sac = true; 226#else 227 log << "warning: Gecode not available. Ignoring '--sac'\n"; 228#endif 229 230 } else if (string(argv[i])=="--shave") { 231#ifdef HAS_GECODE 232 flag_two_pass = true; 233 flag_gecode = true; 234 flag_shave = true; 235#else 236 log << "warning: Gecode not available. Ignoring '--shave'\n"; 237#endif 238 } else if (string(argv[i])=="--two-pass") { 239 flag_two_pass = true; 240 } else if (string(argv[i])=="--npass") { 241 i++; 242 if (i==argv.size()) return false; 243 log << "warning: --npass option is deprecated --two-pass\n"; 244 int passes = atoi(argv[i].c_str()); 245 if(passes == 1) flag_two_pass = false; 246 else if(passes == 2) flag_two_pass = true; 247 } else if (string(argv[i])=="--pre-passes") { 248 i++; 249 if (i==argv.size()) return false; 250 int passes = atoi(argv[i].c_str()); 251 if(passes >= 0) { 252 flag_pre_passes = static_cast<unsigned int>(passes); 253 } 254 } else if (string(argv[i])=="-O0") { 255 flag_optimize = false; 256 } else if (string(argv[i])=="-O1") { 257 // Default settings 258 } else if (string(argv[i])=="-O2") { 259 flag_two_pass = true; 260#ifdef HAS_GECODE 261 } else if (string(argv[i])=="-O3") { 262 flag_two_pass = true; 263 flag_gecode = true; 264 } else if (string(argv[i])=="-O4") { 265 flag_two_pass = true; 266 flag_gecode = true; 267 flag_shave = true; 268 } else if (string(argv[i])=="-O5") { 269 flag_two_pass = true; 270 flag_gecode = true; 271 flag_sac = true; 272#else 273 } else if (string(argv[i])=="-O3" || string(argv[i])=="-O4" || string(argv[i])=="-O5") { 274 log << "% Warning: This compiler does not have Gecode builtin, cannot process -O3,-O4,-O5.\n"; 275 return false; 276#endif 277 */ 278 // ozn options must be after the -O<n> optimisation options 279 /* 280 } else if ( cop.getOption( "-O --ozn --output-ozn-to-file", &flag_output_ozn) ) { 281 } else if (string(argv[i])=="--keep-paths") { 282 flag_keep_mzn_paths = true; 283 fopts.collect_mzn_paths = true; 284 } else if (string(argv[i])=="--only-toplevel-presolve") { 285 fopts.only_toplevel_paths = true; 286 } else if ( cop.getOption( "--allow-multiple-assignments" ) ) { 287 flag_allow_multi_assign = true; 288 } else if (string(argv[i])=="--input-is-flatzinc") { 289 is_flatzinc = true; 290 } else if ( cop.getOption( "--compile-solution-checker", &buffer) ) { 291 if (buffer.length()>=8 && buffer.substr(buffer.length()-8,string::npos) == ".mzc.mzn") { 292 flag_compile_solution_check_model = true; 293 flag_model_check_only = true; 294 filenames.push_back(buffer); 295 } else { 296 log << "Error: solution checker model must have extension .mzc.mzn" << std::endl; 297 return false; 298 } 299 */ 300 } else { 301 std::string input_file(argv[i]); 302 if (input_file.length() <= 4) { 303 return false; 304 } 305 size_t last_dot = input_file.find_last_of('.'); 306 if (last_dot == string::npos) { 307 return false; 308 } 309 std::string extension = input_file.substr(last_dot, string::npos); 310 /* 311 if ( extension == ".mzc" || (input_file.length()>=8 && 312 input_file.substr(input_file.length()-8,string::npos) == ".mzc.mzn") ) { 313 flag_solution_check_model = input_file; 314 } else */ 315 if (extension == ".mzn" || extension == ".fzn") { 316 /* 317 if ( extension == ".fzn" ) { 318 is_flatzinc = true; 319 if ( fOutputByDefault ) // mzn2fzn mode 320 return false; 321 } 322 */ 323 filenames.push_back(input_file); 324 } else if (extension == ".dzn" || extension == ".json") { 325 datafiles.push_back(input_file); 326 } else { 327 // if ( fOutputByDefault ) 328 log << "Error: cannot handle file extension " << extension << "." << std::endl; 329 return false; 330 } 331 } 332 return true; 333} 334 335MznReader::OptionStatus MznReader::processOptions(std::vector<std::string>& argv) { 336 std_lib_dir = solver_configs.mznlibDir(); 337 338 int i(0); 339 int argc(argv.size()); 340 for (; i < argv.size(); ++i) { 341 if (argv[i] == "-h" || argv[i] == "--help") { 342 if (argc > i + 1) { 343 printHelp(argv[i + 1]); 344 } else { 345 printHelp(); 346 } 347 return OPTION_FINISH; 348 } 349 if (argv[i] == "--version") { 350 // flt.printVersion(cout); 351 cout << "MiniZinc model reader. Version EXTREMELY-ALPHA." << endl; 352 return OPTION_FINISH; 353 } 354 if (argv[i] == "--solvers") { 355 cout << "MiniZinc driver.\nAvailable solver configurations:\n"; 356 std::vector<std::string> solvers = solver_configs.solvers(); 357 if (solvers.size() == 0) cout << " none.\n"; 358 for (unsigned int i = 0; i < solvers.size(); i++) { 359 cout << " " << solvers[i] << endl; 360 } 361 cout << "Search path for solver configurations:\n"; 362 for (const string& p : solver_configs.solverConfigsPath()) { 363 cout << " " << p << endl; 364 } 365 return OPTION_FINISH; 366 } 367 /* 368 if (argv[i]=="--solvers-json") { 369 cout << solver_configs.solverConfigsJSON(); 370 return OPTION_FINISH; 371 } 372 */ 373 if (argv[i] == "--config-dirs") { 374 GCLock lock; 375 cout << "{\n"; 376 cout << " \"globalConfigFile\" : \"" 377 << Printer::escapeStringLit(FileUtils::global_config_file()) << "\",\n"; 378 cout << " \"userConfigFile\" : \"" << Printer::escapeStringLit(FileUtils::user_config_file()) 379 << "\",\n"; 380 cout << " \"userSolverConfigDir\" : \"" 381 << Printer::escapeStringLit(FileUtils::user_config_dir()) << "/solvers\",\n"; 382 cout << " \"mznStdlibDir\" : \"" << Printer::escapeStringLit(solver_configs.mznlibDir()) 383 << "\"\n"; 384 cout << "}\n"; 385 return OPTION_FINISH; 386 } 387 if (!processOption(i, argv)) return OPTION_ERROR; 388 } 389 return OPTION_OK; 390} 391 392Model* MznReader::read(const std::string& modelString, const std::string& modelName) { 393 Env env(NULL, os, log); 394 395 if (std_lib_dir == "") { 396 throw Error( 397 "Error: unknown minizinc standard library directory.\n" 398 "Specify --stdlib-dir on the command line or set the\n" 399 "MZN_STDLIB_DIR environment variable."); 400 } 401 if (globals_dir != "") { 402 includePaths.insert(includePaths.begin(), std_lib_dir + "/" + globals_dir + "/"); 403 } 404 includePaths.push_back(std_lib_dir + "/std/"); 405 406 for (unsigned int i = 0; i < includePaths.size(); i++) { 407 if (!FileUtils::directory_exists(includePaths[i])) { 408 throw Error("Cannot access include directory " + includePaths[i]); 409 } 410 } 411 412 Model* m(nullptr); 413 414 m = parse(env, filenames, datafiles, modelString, modelName.empty() ? "stdin" : modelName, 415 includePaths, flag_ignoreStdlib, false, flag_verbose, log); 416 return m; 417} 418 419#if 0 420void addFlags(const std::string& sep, 421 const std::vector<std::string>& in_args, 422 std::vector<std::string>& out_args) { 423 for(const std::string& arg : in_args) { 424 out_args.push_back(sep); 425 out_args.push_back(arg); 426 } 427} 428 429MznReader::OptionStatus MznReader::processOptions(std::vector<std::string>& argv) 430{ 431 /* 432 executable_name = argv[0]; 433 executable_name = executable_name.substr(executable_name.find_last_of("/\\") + 1); 434 size_t lastdot = executable_name.find_last_of('.'); 435 if (lastdot != std::string::npos) { 436 executable_name = executable_name.substr(0, lastdot); 437 } 438 */ 439 string solver; 440 /* 441 bool mzn2fzn_exe = (executable_name=="mzn2fzn"); 442 if (mzn2fzn_exe) { 443 is_mzn2fzn=true; 444 } else if (executable_name=="solns2out") { 445 s2out._opt.flag_standaloneSolns2Out=true; 446 } 447 bool compileSolutionChecker = false; 448 */ 449 int i=1, j=1; 450 int argc = static_cast<int>(argv.size()); 451 if (argc < 2) 452 return OPTION_ERROR; 453 for (i=1; i<argc; ++i) { 454 if (argv[i]=="-h" || argv[i]=="--help") { 455 if (argc > i+1) { 456 printHelp(argv[i+1]); 457 } else { 458 printHelp(); 459 } 460 return OPTION_FINISH; 461 } 462 if (argv[i]=="--version") { 463 flt.printVersion(cout); 464 return OPTION_FINISH; 465 } 466 if (argv[i]=="--solvers") { 467 cout << "MiniZinc driver.\nAvailable solver configurations:\n"; 468 std::vector<std::string> solvers = solver_configs.solvers(); 469 if (solvers.size()==0) 470 cout << " none.\n"; 471 for (unsigned int i=0; i<solvers.size(); i++) { 472 cout << " " << solvers[i] << endl; 473 } 474 cout << "Search path for solver configurations:\n"; 475 for (const string& p : solver_configs.solverConfigsPath()) { 476 cout << " " << p << endl; 477 } 478 return OPTION_FINISH; 479 } 480 if (argv[i]=="--solvers-json") { 481 cout << solver_configs.solverConfigsJSON(); 482 return OPTION_FINISH; 483 } 484 if (argv[i]=="--config-dirs") { 485 GCLock lock; 486 cout << "{\n"; 487 cout << " \"globalConfigFile\" : \"" << Printer::escapeStringLit(FileUtils::global_config_file()) << "\",\n"; 488 cout << " \"userConfigFile\" : \"" << Printer::escapeStringLit(FileUtils::user_config_file()) << "\",\n"; 489 cout << " \"userSolverConfigDir\" : \"" << Printer::escapeStringLit(FileUtils::user_config_dir()) << "/solvers\",\n"; 490 cout << " \"mznStdlibDir\" : \"" << Printer::escapeStringLit(solver_configs.mznlibDir()) << "\"\n"; 491 cout << "}\n"; 492 return OPTION_FINISH; 493 } 494 if (argv[i]=="--time-limit") { 495 ++i; 496 if (i==argc) { 497 log << "Argument required for --time-limit" << endl; 498 return OPTION_ERROR; 499 } 500 flag_overall_time_limit = atoi(argv[i].c_str()); 501 } else if (argv[i]=="--solver") { 502 ++i; 503 if (i==argc) { 504 log << "Argument required for --solver" << endl; 505 return OPTION_ERROR; 506 } 507 if (solver.size()>0 && solver != argv[i]) { 508 log << "Only one --solver option allowed" << endl; 509 return OPTION_ERROR; 510 } 511 solver = argv[i]; 512 } else if (argv[i]=="-c" || argv[i]=="--compile") { 513 is_mzn2fzn = true; 514 } else if (argv[i]=="-v" || argv[i]=="--verbose" || argv[i]=="-l") { 515 flag_verbose = true; 516 flag_compiler_verbose = true; 517 } else if (argv[i]=="--verbose-compilation") { 518 flag_compiler_verbose = true; 519 } else if (argv[i]=="-s" || argv[i]=="--statistics") { 520 flag_statistics = true; 521 flag_compiler_statistics = true; 522 } else if (argv[i]=="--compiler-statistics") { 523 flag_compiler_statistics = true; 524 } else { 525 if ((argv[i]=="--fzn-cmd" || argv[i]=="--flatzinc-cmd") && solver.empty()) { 526 solver = "org.minizinc.mzn-fzn"; 527 } 528 if (argv[i]=="--compile-solution-checker") { 529 compileSolutionChecker = true; 530 } 531 argv[j++] = argv[i]; 532 } 533 } 534 argv.resize(j); 535 argc = j; 536 537 /* 538 if ( (mzn2fzn_exe || compileSolutionChecker) && solver.empty()) { 539 solver = "org.minizinc.mzn-fzn"; 540 } 541 */ 542 543 if (flag_verbose) { 544 argv.push_back("--verbose-solving"); 545 argc++; 546 } 547 if (flag_statistics) { 548 argv.push_back("--solver-statistics"); 549 argc++; 550 } 551 552 // flt.set_flag_output_by_default(ifMzn2Fzn()); 553 554 // bool isMznMzn = false; 555 556 if (/*!ifSolns2out()*/ true) { 557 try { 558 const SolverConfig& sc = solver_configs.config(solver); 559 string solverId = sc.executable().empty() ? sc.id() : (sc.supportsMzn() ? string("org.minizinc.mzn-mzn") : string("org.minizinc.mzn-fzn")); 560 for (auto it = getGlobalSolverRegistry()->getSolverFactories().begin(); 561 it != getGlobalSolverRegistry()->getSolverFactories().end(); ++it) { 562 if ((*it)->getId()==solverId) { /// TODO: also check version (currently assumes all ids are unique) 563 sf = *it; 564 si_opt = sf->createOptions(); 565 if (!sc.executable().empty() || solverId=="org.minizinc.mzn-fzn") { 566 std::vector<MZNFZNSolverFlag> acceptedFlags; 567 for (auto& sf : sc.stdFlags()) 568 acceptedFlags.push_back(MZNFZNSolverFlag::std(sf)); 569 for (auto& ef : sc.extraFlags()) 570 acceptedFlags.push_back(MZNFZNSolverFlag::extra(ef.flag,ef.flag_type)); 571 572 // Collect arguments required for underlying exe 573 vector<string> fzn_mzn_flags; 574 if (sc.needsStdlibDir()) { 575 fzn_mzn_flags.push_back("--stdlib-dir"); 576 fzn_mzn_flags.push_back(FileUtils::share_directory()); 577 } 578 if (sc.needsMznExecutable()) { 579 fzn_mzn_flags.push_back("--minizinc-exe"); 580 fzn_mzn_flags.push_back(FileUtils::progpath() + "/" + executable_name); 581 } 582 583 if (sc.supportsMzn()) { 584 isMznMzn = true; 585 static_cast<MZN_SolverFactory*>(sf)->setAcceptedFlags(si_opt, acceptedFlags); 586 std::vector<std::string> additionalArgs_s; 587 additionalArgs_s.push_back("-m"); 588 if (sc.executable_resolved().size()) { 589 additionalArgs_s.push_back(sc.executable_resolved()); 590 } else { 591 additionalArgs_s.push_back(sc.executable()); 592 } 593 594 if(!fzn_mzn_flags.empty()) { 595 addFlags("--mzn-flag", fzn_mzn_flags, additionalArgs_s); 596 } 597 598 // This should maybe be moved to fill in fzn_mzn_flags when 599 // --find-muses is implemented (these arguments will be passed 600 // through to the subsolver of findMUS) 601 if (!sc.mznlib().empty()) { 602 if (sc.mznlib().substr(0,2)=="-G") { 603 additionalArgs_s.push_back("--mzn-flag"); 604 additionalArgs_s.push_back(sc.mznlib()); 605 } else { 606 additionalArgs_s.push_back("--mzn-flag"); 607 additionalArgs_s.push_back("-I"); 608 additionalArgs_s.push_back("--mzn-flag"); 609 std::string _mznlib; 610 if (sc.mznlib_resolved().size()) { 611 _mznlib = sc.mznlib_resolved(); 612 } else { 613 _mznlib = sc.mznlib(); 614 } 615 additionalArgs_s.push_back(_mznlib); 616 } 617 } 618 619 for (i=0; i<additionalArgs_s.size(); ++i) { 620 bool success = sf->processOption(si_opt, i, additionalArgs_s); 621 if (!success) { 622 log << "Solver backend " << solverId << " does not recognise option " << additionalArgs_s[i] << "." << endl; 623 return OPTION_ERROR; 624 } 625 } 626 } else { 627 static_cast<FZN_SolverFactory*>(sf)->setAcceptedFlags(si_opt, acceptedFlags); 628 std::vector<std::string> additionalArgs; 629 additionalArgs.push_back("--fzn-cmd"); 630 if (sc.executable_resolved().size()) { 631 additionalArgs.push_back(sc.executable_resolved()); 632 } else { 633 additionalArgs.push_back(sc.executable()); 634 } 635 if(!fzn_mzn_flags.empty()) { 636 addFlags("--fzn-flag", fzn_mzn_flags, additionalArgs); 637 } 638 if (sc.needsPathsFile()) { 639 // Instruct flattener to hold onto paths 640 int i=0; 641 vector<string> args {"--keep-paths"}; 642 flt.processOption(i, args); 643 644 // Instruct FznSolverInstance to write a path file 645 // and pass it to the executable with --paths arg 646 additionalArgs.push_back("--fzn-needs-paths"); 647 } 648 if (!sc.needsSolns2Out()) { 649 additionalArgs.push_back("--fzn-output-passthrough"); 650 } 651 int i=0; 652 for (i=0; i<additionalArgs.size(); ++i) { 653 bool success = sf->processOption(si_opt, i, additionalArgs); 654 if (!success) { 655 log << "Solver backend " << solverId << " does not recognise option " << additionalArgs[i] << "." << endl; 656 return OPTION_ERROR; 657 } 658 } 659 } 660 } 661 if (!sc.mznlib().empty()) { 662 if (sc.mznlib().substr(0,2)=="-G") { 663 std::vector<std::string> additionalArgs({sc.mznlib()}); 664 int i=0; 665 if (!flt.processOption(i, additionalArgs)) { 666 log << "Flattener does not recognise option " << sc.mznlib() << endl; 667 return OPTION_ERROR; 668 } 669 } else { 670 std::vector<std::string> additionalArgs(2); 671 additionalArgs[0] = "-I"; 672 if (sc.mznlib_resolved().size()) { 673 additionalArgs[1] = sc.mznlib_resolved(); 674 } else { 675 additionalArgs[1] = sc.mznlib(); 676 } 677 int i=0; 678 if (!flt.processOption(i, additionalArgs)) { 679 log << "Flattener does not recognise option -I." << endl; 680 return OPTION_ERROR; 681 } 682 } 683 } 684 if (!sc.defaultFlags().empty()) { 685 std::vector<std::string> addedArgs; 686 addedArgs.push_back(argv[0]); // excutable name 687 for (auto& df : sc.defaultFlags()) { 688 addedArgs.push_back(df); 689 } 690 for (int i=1; i<argv.size(); i++) { 691 addedArgs.push_back(argv[i]); 692 } 693 argv = addedArgs; 694 argc = addedArgs.size(); 695 } 696 break; 697 } 698 } 699 700 } catch (ConfigException& e) { 701 log << "Config exception: " << e.msg() << endl; 702 return OPTION_ERROR; 703 } 704 705 if (sf==NULL) { 706 log << "Solver " << solver << " not found." << endl; 707 return OPTION_ERROR; 708 } 709 710 for (i=1; i<argc; ++i) { 711 if ( !ifMzn2Fzn() ? s2out.processOption( i, argv ) : false ) { 712 } else if ((!isMznMzn || is_mzn2fzn) && flt.processOption(i, argv)) { 713 } else if (sf != NULL && sf->processOption(si_opt, i, argv)) { 714 } else { 715 std::string executable_name(argv[0]); 716 executable_name = executable_name.substr(executable_name.find_last_of("/\\") + 1); 717 log << executable_name << ": Unrecognized option or bad format `" << argv[i] << "'" << endl; 718 return OPTION_ERROR; 719 } 720 } 721 return OPTION_OK; 722 723 } else { 724 for (i=1; i<argc; ++i) { 725 if ( s2out.processOption( i, argv ) ) { 726 } else { 727 std::string executable_name(argv[0]); 728 executable_name = executable_name.substr(executable_name.find_last_of("/\\") + 1); 729 log << executable_name << ": Unrecognized option or bad format `" << argv[i] << "'" << endl; 730 return OPTION_ERROR; 731 } 732 } 733 return OPTION_OK; 734 735 } 736 737} 738 739/* 740void MznReader::flatten(const std::string& modelString, const std::string& modelName) 741{ 742 flt.set_flag_verbose(flag_compiler_verbose); 743 flt.set_flag_statistics(flag_compiler_statistics); 744 Timer tm01; 745 flt.flatten(modelString, modelName); 746 /// The following message tells mzn-test.py that flattening succeeded. 747 if (flag_compiler_verbose) 748 log << " Flattening done, " << tm01.stoptime() << std::endl; 749} 750*/ 751 752SolverInstance::Status MznSolver::solve() 753{ 754 { // To be able to clean up flatzinc after PrcessFlt() 755 GCLock lock; 756 getSI()->processFlatZinc(); 757 } 758 SolverInstance::Status status = getSI()->solve(); 759 GCLock lock; 760 if (status==SolverInstance::SAT || status==SolverInstance::OPT) { 761 if ( !getSI()->getSolns2Out()->fStatusPrinted ) 762 getSI()->getSolns2Out()->evalStatus( status ); 763 } 764 else { 765 if ( !getSI()->getSolns2Out()->fStatusPrinted ) 766 getSI()->getSolns2Out()->evalStatus( status ); 767 } 768 if (si_opt->printStatistics) 769 printStatistics(); 770 return status; 771} 772 773void MznSolver::printStatistics() 774{ // from flattener too? TODO 775 if (si) 776 getSI()->printStatistics(); 777} 778 779SolverInstance::Status MznSolver::run(const std::vector<std::string>& args0, const std::string& model, 780 const std::string& exeName, const std::string& modelName) { 781 using namespace std::chrono; 782 steady_clock::time_point startTime = steady_clock::now(); 783 std::vector<std::string> args = {exeName}; 784 for (auto a : args0) 785 args.push_back(a); 786 switch (processOptions(args)) { 787 case OPTION_FINISH: 788 return SolverInstance::NONE; 789 case OPTION_ERROR: 790 printUsage(); 791 os << "More info with \"" << exeName << " --help\"\n"; 792 return SolverInstance::ERROR; 793 case OPTION_OK: 794 break; 795 } 796 if (!(!ifMzn2Fzn() && sf!=NULL && sf->getId() == "org.minizinc.mzn-mzn") && !flt.hasInputFiles() && model.empty()) { 797 // We are in solns2out mode 798 while ( std::cin.good() ) { 799 string line; 800 getline( std::cin, line ); 801 line += '\n'; // need eols as in t=raw stream 802 s2out.feedRawDataChunk( line.c_str() ); 803 } 804 return SolverInstance::NONE; 805 } 806 807 if (!ifMzn2Fzn() && sf->getId() == "org.minizinc.mzn-mzn") { 808 Env env; 809 si = sf->createSI(env, log, si_opt); 810 si->setSolns2Out( &s2out ); 811 { // To be able to clean up flatzinc after PrcessFlt() 812 GCLock lock; 813 getSI()->_options->verbose = get_flag_verbose(); 814 getSI()->_options->printStatistics = get_flag_statistics(); 815 } 816 getSI()->solve(); 817 return SolverInstance::NONE; 818 } 819 820 flatten(model,modelName); 821 822 if (!ifMzn2Fzn() && flag_overall_time_limit != 0) { 823 steady_clock::time_point afterFlattening = steady_clock::now(); 824 milliseconds passed = duration_cast<milliseconds>(afterFlattening-startTime); 825 milliseconds time_limit(flag_overall_time_limit); 826 if (passed > time_limit) { 827 s2out.evalStatus( getFltStatus() ); 828 return SolverInstance::UNKNOWN; 829 } 830 int time_left = (time_limit-passed).count(); 831 std::vector<std::string> timeoutArgs(2); 832 timeoutArgs[0] = "--solver-time-limit"; 833 std::ostringstream oss; 834 oss << time_left; 835 timeoutArgs[1] = oss.str(); 836 int i=0; 837 sf->processOption(si_opt, i, timeoutArgs); 838 } 839 840 if (SolverInstance::UNKNOWN == getFltStatus()) 841 { 842 if ( !ifMzn2Fzn() ) { // only then 843 // GCLock lock; // better locally, to enable cleanup after ProcessFlt() 844 addSolverInterface(); 845 return solve(); 846 } 847 return SolverInstance::NONE; 848 } else { 849 if ( !ifMzn2Fzn() ) 850 s2out.evalStatus( getFltStatus() ); 851 return getFltStatus(); 852 } // Add evalOutput() here? TODO 853} 854#endif 855 856}; // namespace MiniZinc