OR-Tools  9.1
fz.cc
Go to the documentation of this file.
1// Copyright 2010-2021 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 functionalities are fixed (name of parameters, format of the
16// input): see http://www.minizinc.org/downloads/doc-1.6/flatzinc-spec.pdf
17
18#include <limits>
19
20#include "absl/strings/str_split.h"
21#if defined(__GNUC__) // Linux or Mac OS X.
22#include <signal.h>
23#endif // __GNUC__
24
25#include <csignal>
26#include <iostream>
27#include <string>
28#include <vector>
29
30#include "absl/flags/flag.h"
31#include "absl/flags/parse.h"
32#include "absl/flags/usage.h"
37#include "ortools/base/timer.h"
43
44ABSL_FLAG(double, time_limit, 0, "time limit in seconds.");
45ABSL_FLAG(bool, all_solutions, false, "Search for all solutions.");
46ABSL_FLAG(int, num_solutions, 0,
47 "Maximum number of solution to search for, 0 means unspecified.");
48ABSL_FLAG(bool, free_search, false,
49 "If false, the solver must follow the defined search."
50 "If true, other search are allowed.");
51ABSL_FLAG(int, threads, 0, "Number of threads the solver will use.");
52ABSL_FLAG(bool, presolve, true, "Presolve the model to simplify it.");
53ABSL_FLAG(bool, statistics, false, "Print solver statistics after search.");
54ABSL_FLAG(bool, read_from_stdin, false,
55 "Read the FlatZinc from stdin, not from a file.");
56ABSL_FLAG(int, fz_seed, 0, "Random seed");
57ABSL_FLAG(std::string, fz_model_name, "stdin",
58 "Define problem name when reading from stdin.");
59ABSL_FLAG(std::string, params, "", "SatParameters as a text proto.");
60ABSL_FLAG(bool, fz_logging, false,
61 "Print logging information from the flatzinc interpreter.");
62ABSL_FLAG(bool, use_flatzinc_format, true,
63 "Display solutions in the flatzinc format");
64
65namespace operations_research {
66namespace fz {
67
68std::vector<char*> FixAndParseParameters(int* argc, char*** argv) {
69 char all_param[] = "--all_solutions";
70 char free_param[] = "--free_search";
71 char threads_param[] = "--threads";
72 char solutions_param[] = "--num_solutions";
73 char logging_param[] = "--fz_logging";
74 char statistics_param[] = "--statistics";
75 char seed_param[] = "--fz_seed";
76 char time_param[] = "--time_limit";
77 bool use_time_param = false;
78 for (int i = 1; i < *argc; ++i) {
79 if (strcmp((*argv)[i], "-a") == 0) {
80 (*argv)[i] = all_param;
81 }
82 if (strcmp((*argv)[i], "-f") == 0) {
83 (*argv)[i] = free_param;
84 }
85 if (strcmp((*argv)[i], "-p") == 0) {
86 (*argv)[i] = threads_param;
87 }
88 if (strcmp((*argv)[i], "-n") == 0) {
89 (*argv)[i] = solutions_param;
90 }
91 if (strcmp((*argv)[i], "-l") == 0) {
92 (*argv)[i] = logging_param;
93 }
94 if (strcmp((*argv)[i], "-s") == 0) {
95 (*argv)[i] = statistics_param;
96 }
97 if (strcmp((*argv)[i], "-r") == 0) {
98 (*argv)[i] = seed_param;
99 }
100 if (strcmp((*argv)[i], "-t") == 0) {
101 (*argv)[i] = time_param;
102 use_time_param = true;
103 }
104 }
105 const char kUsage[] =
106 "Usage: see flags.\nThis program parses and solve a flatzinc problem.";
107
108 absl::SetProgramUsageMessage(kUsage);
109 const std::vector<char*> residual_flags =
110 absl::ParseCommandLine(*argc, *argv);
111 google::InitGoogleLogging((*argv)[0]);
112
113 // Fix time limit if -t was used.
114 if (use_time_param) {
115 absl::SetFlag(&FLAGS_time_limit, absl::GetFlag(FLAGS_time_limit) / 1000.0);
116 }
117 return residual_flags;
118}
119
120Model ParseFlatzincModel(const std::string& input, bool input_is_filename,
121 SolverLogger* logger) {
122 WallTimer timer;
123 timer.Start();
124 // Read model.
125 std::string problem_name =
126 input_is_filename ? input : absl::GetFlag(FLAGS_fz_model_name);
127 if (input_is_filename || absl::EndsWith(problem_name, ".fzn")) {
128 CHECK(absl::EndsWith(problem_name, ".fzn"))
129 << "Unrecognized flatzinc file: `" << problem_name << "'";
130 problem_name.resize(problem_name.size() - 4);
131 const size_t found = problem_name.find_last_of("/\\");
132 if (found != std::string::npos) {
133 problem_name = problem_name.substr(found + 1);
134 }
135 }
136 Model model(problem_name);
137 if (input_is_filename) {
139 } else {
141 }
142
143 SOLVER_LOG(logger, "File ", (input_is_filename ? input : "stdin"),
144 " parsed in ", timer.GetInMs(), " ms");
145 SOLVER_LOG(logger, "");
146
147 // Presolve the model.
148 Presolver presolve(logger);
149 SOLVER_LOG(logger, "Presolve model");
150 timer.Reset();
151 timer.Start();
152 presolve.Run(&model);
153 SOLVER_LOG(logger, " - done in ", timer.GetInMs(), " ms");
154 SOLVER_LOG(logger);
155
156 // Print statistics.
157 ModelStatistics stats(model, logger);
158 stats.BuildStatistics();
159 stats.PrintStatistics();
160 return model;
161}
162
163void LogInFlatzincFormat(const std::string& multi_line_input) {
164 if (multi_line_input.empty()) {
165 std::cout << std::endl;
166 return;
167 }
168 const absl::string_view flatzinc_prefix =
169 absl::GetFlag(FLAGS_use_flatzinc_format) ? "%% " : "";
170 const std::vector<absl::string_view> lines =
171 absl::StrSplit(multi_line_input, '\n', absl::SkipEmpty());
172 for (const absl::string_view& line : lines) {
173 std::cout << flatzinc_prefix << line << std::endl;
174 }
175}
176
177} // namespace fz
178} // namespace operations_research
179
180int main(int argc, char** argv) {
181 // Flatzinc specifications require single dash parameters (-a, -f, -p).
182 // We need to fix parameters before parsing them.
183 const std::vector<char*> residual_flags =
185 // We allow piping model through stdin.
186 std::string input;
187 if (absl::GetFlag(FLAGS_read_from_stdin)) {
188 std::string currentLine;
189 while (std::getline(std::cin, currentLine)) {
190 input.append(currentLine);
191 }
192 } else {
193 if (residual_flags.empty()) {
194 LOG(ERROR) << "Usage: " << argv[0] << " <file>";
195 return EXIT_FAILURE;
196 }
197 input = residual_flags.back();
198 }
199
201 logger.EnableLogging(absl::GetFlag(FLAGS_fz_logging));
202 logger.SetLogToStdOut(false);
206 input, !absl::GetFlag(FLAGS_read_from_stdin), &logger);
208 parameters.display_all_solutions = absl::GetFlag(FLAGS_all_solutions);
209 parameters.use_free_search = absl::GetFlag(FLAGS_free_search);
210 parameters.log_search_progress = absl::GetFlag(FLAGS_fz_logging);
211 if (absl::GetFlag(FLAGS_num_solutions) == 0) {
212 absl::SetFlag(&FLAGS_num_solutions,
213 absl::GetFlag(FLAGS_all_solutions)
215 : 1);
216 }
217 parameters.max_number_of_solutions = absl::GetFlag(FLAGS_num_solutions);
218 parameters.random_seed = absl::GetFlag(FLAGS_fz_seed);
219 parameters.display_statistics = absl::GetFlag(FLAGS_statistics);
220 parameters.number_of_threads = absl::GetFlag(FLAGS_threads);
221 parameters.max_time_in_seconds = absl::GetFlag(FLAGS_time_limit);
222
223 operations_research::SolverLogger solution_logger;
224 solution_logger.SetLogToStdOut(true);
225 solution_logger.EnableLogging(absl::GetFlag(FLAGS_use_flatzinc_format));
226
228 absl::GetFlag(FLAGS_params),
229 &logger, &solution_logger);
230 return EXIT_SUCCESS;
231}
int64_t max
Definition: alldiff_cst.cc:140
#define CHECK(condition)
Definition: base/logging.h:491
#define LOG(severity)
Definition: base/logging.h:416
void Start()
Definition: timer.h:31
void Reset()
Definition: timer.h:26
int64_t GetInMs() const
Definition: timer.h:46
void SetLogToStdOut(bool enable)
Definition: util/logging.h:45
void AddInfoLoggingCallback(std::function< void(const std::string &message)> callback)
Definition: util/logging.cc:23
SatParameters parameters
ModelSharedTimeLimit * time_limit
ABSL_FLAG(double, time_limit, 0, "time limit in seconds.")
int main(int argc, char **argv)
Definition: fz.cc:180
GRBmodel * model
const int ERROR
Definition: log_severity.h:32
void InitGoogleLogging(const char *argv0)
void LogInFlatzincFormat(const std::string &multi_line_input)
Definition: fz.cc:163
bool ParseFlatzincString(const std::string &input, Model *model)
Definition: parser.cc:60
bool ParseFlatzincFile(const std::string &filename, Model *model)
Definition: parser.cc:38
Model ParseFlatzincModel(const std::string &input, bool input_is_filename, SolverLogger *logger)
Definition: fz.cc:120
std::vector< char * > FixAndParseParameters(int *argc, char ***argv)
Definition: fz.cc:68
void SolveFzWithCpModelProto(const fz::Model &fz_model, const fz::FlatzincSatParameters &p, const std::string &sat_params, SolverLogger *logger, SolverLogger *solution_logger)
Collection of objects used to extend the Constraint Solver library.
static int input(yyscan_t yyscanner)
#define SOLVER_LOG(logger,...)
Definition: util/logging.h:63