OR-Tools  8.2
fz.cc
Go to the documentation of this file.
1// Copyright 2010-2018 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// This is the skeleton for the official flatzinc interpreter. Much
15// of the funcionalities are fixed (name of parameters, format of the
16// input): see http://www.minizinc.org/downloads/doc-1.6/flatzinc-spec.pdf
17
18#if defined(__GNUC__) // Linux or Mac OS X.
19#include <signal.h>
20#endif // __GNUC__
21
22#include <csignal>
23#include <iostream>
24#include <string>
25#include <vector>
26
27#include "absl/flags/flag.h"
28#include "absl/flags/parse.h"
29#include "absl/flags/usage.h"
34#include "ortools/base/timer.h"
40
41ABSL_FLAG(double, time_limit, 0, "time limit in seconds.");
42ABSL_FLAG(bool, all_solutions, false, "Search for all solutions.");
43ABSL_FLAG(int, num_solutions, 0,
44 "Maximum number of solution to search for, 0 means unspecified.");
45ABSL_FLAG(bool, free_search, false,
46 "If false, the solver must follow the defined search."
47 "If true, other search are allowed.");
48ABSL_FLAG(int, threads, 0, "Number of threads the solver will use.");
49ABSL_FLAG(bool, presolve, true, "Presolve the model to simplify it.");
50ABSL_FLAG(bool, statistics, false, "Print solver statistics after search.");
51ABSL_FLAG(bool, read_from_stdin, false,
52 "Read the FlatZinc from stdin, not from a file.");
53ABSL_FLAG(int, fz_seed, 0, "Random seed");
54ABSL_FLAG(std::string, fz_model_name, "stdin",
55 "Define problem name when reading from stdin.");
56ABSL_FLAG(std::string, params, "", "SatParameters as a text proto.");
57
58ABSL_DECLARE_FLAG(bool, log_prefix);
59
60namespace operations_research {
61namespace fz {
62
63std::vector<char*> FixAndParseParameters(int* argc, char*** argv) {
64 absl::SetFlag(&FLAGS_log_prefix, false);
65
66 char all_param[] = "--all_solutions";
67 char free_param[] = "--free_search";
68 char threads_param[] = "--threads";
69 char solutions_param[] = "--num_solutions";
70 char logging_param[] = "--fz_logging";
71 char statistics_param[] = "--statistics";
72 char seed_param[] = "--fz_seed";
73 char verbose_param[] = "--fz_verbose";
74 char debug_param[] = "--fz_debug";
75 char time_param[] = "--time_limit";
76 bool use_time_param = false;
77 for (int i = 1; i < *argc; ++i) {
78 if (strcmp((*argv)[i], "-a") == 0) {
79 (*argv)[i] = all_param;
80 }
81 if (strcmp((*argv)[i], "-f") == 0) {
82 (*argv)[i] = free_param;
83 }
84 if (strcmp((*argv)[i], "-p") == 0) {
85 (*argv)[i] = threads_param;
86 }
87 if (strcmp((*argv)[i], "-n") == 0) {
88 (*argv)[i] = solutions_param;
89 }
90 if (strcmp((*argv)[i], "-l") == 0) {
91 (*argv)[i] = logging_param;
92 }
93 if (strcmp((*argv)[i], "-s") == 0) {
94 (*argv)[i] = statistics_param;
95 }
96 if (strcmp((*argv)[i], "-r") == 0) {
97 (*argv)[i] = seed_param;
98 }
99 if (strcmp((*argv)[i], "-v") == 0) {
100 (*argv)[i] = verbose_param;
101 }
102 if (strcmp((*argv)[i], "-d") == 0) {
103 (*argv)[i] = debug_param;
104 }
105 if (strcmp((*argv)[i], "-t") == 0) {
106 (*argv)[i] = time_param;
107 use_time_param = true;
108 }
109 }
110 const char kUsage[] =
111 "Usage: see flags.\nThis program parses and solve a flatzinc problem.";
112
113 absl::SetProgramUsageMessage(kUsage);
114 const std::vector<char*> residual_flags =
115 absl::ParseCommandLine(*argc, *argv);
116 google::InitGoogleLogging((*argv)[0]);
117
118 // Fix time limit if -t was used.
119 if (use_time_param) {
120 absl::SetFlag(&FLAGS_time_limit, absl::GetFlag(FLAGS_time_limit) / 1000.0);
121 }
122 return residual_flags;
123}
124
125Model ParseFlatzincModel(const std::string& input, bool input_is_filename) {
126 WallTimer timer;
127 timer.Start();
128 // Read model.
129 std::string problem_name =
130 input_is_filename ? input : absl::GetFlag(FLAGS_fz_model_name);
131 if (input_is_filename || absl::EndsWith(problem_name, ".fzn")) {
132 CHECK(absl::EndsWith(problem_name, ".fzn"))
133 << "Unrecognized flatzinc file: `" << problem_name << "'";
134 problem_name.resize(problem_name.size() - 4);
135 const size_t found = problem_name.find_last_of("/\\");
136 if (found != std::string::npos) {
137 problem_name = problem_name.substr(found + 1);
138 }
139 }
140 Model model(problem_name);
141 if (input_is_filename) {
143 } else {
145 }
146
147 FZLOG << "File " << (input_is_filename ? input : "stdin") << " parsed in "
148 << timer.GetInMs() << " ms" << FZENDL;
149
150 // Presolve the model.
151 Presolver presolve;
152 FZLOG << "Presolve model" << FZENDL;
153 timer.Reset();
154 timer.Start();
155 presolve.Run(&model);
156 FZLOG << " - done in " << timer.GetInMs() << " ms" << FZENDL;
157
158 // Print statistics.
159 ModelStatistics stats(model);
160 stats.BuildStatistics();
161 stats.PrintStatistics();
162 return model;
163}
164
165} // namespace fz
166} // namespace operations_research
167
168int main(int argc, char** argv) {
169 // Flatzinc specifications require single dash parameters (-a, -f, -p).
170 // We need to fix parameters before parsing them.
171 const std::vector<char*> residual_flags =
173 // We allow piping model through stdin.
174 std::string input;
175 if (absl::GetFlag(FLAGS_read_from_stdin)) {
176 std::string currentLine;
177 while (std::getline(std::cin, currentLine)) {
178 input.append(currentLine);
179 }
180 } else {
181 if (residual_flags.empty()) {
182 LOG(ERROR) << "Usage: " << argv[0] << " <file>";
183 return EXIT_FAILURE;
184 }
185 input = residual_flags.back();
186 }
187
190 input, !absl::GetFlag(FLAGS_read_from_stdin));
192 parameters.display_all_solutions = absl::GetFlag(FLAGS_all_solutions);
193 parameters.use_free_search = absl::GetFlag(FLAGS_free_search);
194 parameters.verbose_logging = absl::GetFlag(FLAGS_fz_logging);
195 if (absl::GetFlag(FLAGS_num_solutions) == 0) {
196 absl::SetFlag(&FLAGS_num_solutions,
197 absl::GetFlag(FLAGS_all_solutions) ? kint32max : 1);
198 }
199 parameters.max_number_of_solutions = absl::GetFlag(FLAGS_num_solutions);
200 parameters.random_seed = absl::GetFlag(FLAGS_fz_seed);
201 parameters.display_statistics = absl::GetFlag(FLAGS_statistics);
202 parameters.number_of_threads = absl::GetFlag(FLAGS_threads);
203 parameters.max_time_in_seconds = absl::GetFlag(FLAGS_time_limit);
204
206 model, parameters, absl::GetFlag(FLAGS_params));
207 return EXIT_SUCCESS;
208}
#define CHECK(condition)
Definition: base/logging.h:495
#define LOG(severity)
Definition: base/logging.h:420
void Start()
Definition: timer.h:31
void Reset()
Definition: timer.h:26
int64 GetInMs() const
Definition: timer.h:46
SatParameters parameters
SharedTimeLimit * time_limit
#define FZLOG
#define FZENDL
ABSL_FLAG(double, time_limit, 0, "time limit in seconds.")
ABSL_DECLARE_FLAG(bool, log_prefix)
int main(int argc, char **argv)
Definition: fz.cc:168
GRBmodel * model
static const int32 kint32max
const int ERROR
Definition: log_severity.h:32
void InitGoogleLogging(const char *argv0)
bool ParseFlatzincString(const std::string &input, Model *model)
Definition: parser.cc:60
Model ParseFlatzincModel(const std::string &input, bool input_is_filename)
Definition: fz.cc:125
std::vector< char * > FixAndParseParameters(int *argc, char ***argv)
Definition: fz.cc:63
bool ParseFlatzincFile(const std::string &filename, Model *model)
Definition: parser.cc:38
void SolveFzWithCpModelProto(const fz::Model &fz_model, const fz::FlatzincSatParameters &p, const std::string &sat_params)
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
static int input(yyscan_t yyscanner)