Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
fz.cc
Go to the documentation of this file.
1// Copyright 2010-2024 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 <cstdlib>
19#include <cstring>
20#if defined(__GNUC__) // Linux or Mac OS X.
21#include <signal.h>
22#endif // __GNUC__
23
24#include <iostream>
25#include <ostream>
26#include <string>
27#include <vector>
28
29#include "absl/flags/flag.h"
30#include "absl/log/check.h"
31#include "absl/log/initialize.h"
32#include "absl/strings/match.h"
33#include "absl/strings/str_split.h"
34#include "absl/strings/string_view.h"
37#include "ortools/base/path.h"
38#include "ortools/base/timer.h"
44
45ABSL_FLAG(double, time_limit, 0, "time limit in seconds.");
46ABSL_FLAG(bool, search_all_solutions, false, "Search for all solutions.");
47ABSL_FLAG(bool, display_all_solutions, false,
48 "Display all improving solutions.");
49ABSL_FLAG(bool, free_search, false,
50 "If false, the solver must follow the defined search."
51 "If true, other search are allowed.");
52ABSL_FLAG(int, threads, 0, "Number of threads the solver will use.");
53ABSL_FLAG(bool, presolve, true, "Presolve the model to simplify it.");
54ABSL_FLAG(bool, statistics, false, "Print solver statistics after search.");
55ABSL_FLAG(bool, read_from_stdin, false,
56 "Read the FlatZinc from stdin, not from a file.");
57ABSL_FLAG(int, fz_seed, 0, "Random seed");
58ABSL_FLAG(std::string, fz_model_name, "stdin",
59 "Define problem name when reading from stdin.");
60ABSL_FLAG(std::string, params, "", "SatParameters as a text proto.");
61ABSL_FLAG(bool, fz_logging, false,
62 "Print logging information from the flatzinc interpreter.");
63ABSL_FLAG(bool, ortools_mode, true, "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[] = "--search_all_solutions";
70 char print_solutions[] = "--display_all_solutions";
71 char free_param[] = "--free_search";
72 char threads_param[] = "--threads";
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 bool set_free_search = false;
79 for (int i = 1; i < *argc; ++i) {
80 if (strcmp((*argv)[i], "-a") == 0) {
81 (*argv)[i] = all_param;
82 }
83 if (strcmp((*argv)[i], "-i") == 0) {
84 (*argv)[i] = print_solutions;
85 }
86 if (strcmp((*argv)[i], "-f") == 0) {
87 (*argv)[i] = free_param;
88 set_free_search = true;
89 }
90 if (strcmp((*argv)[i], "-p") == 0) {
91 (*argv)[i] = threads_param;
92 }
93 if (strcmp((*argv)[i], "-l") == 0) {
94 (*argv)[i] = logging_param;
95 }
96 if (strcmp((*argv)[i], "-s") == 0) {
97 (*argv)[i] = statistics_param;
98 }
99 if (strcmp((*argv)[i], "-r") == 0) {
100 (*argv)[i] = seed_param;
101 }
102 if (strcmp((*argv)[i], "-t") == 0) {
103 (*argv)[i] = time_param;
104 use_time_param = true;
105 }
106 if (strcmp((*argv)[i], "-v") == 0) {
107 (*argv)[i] = logging_param;
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 absl::InitializeLog();
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
123 // Define the default number of workers to 1 if -f was used.
124 if (set_free_search && absl::GetFlag(FLAGS_threads) == 0) {
125 absl::SetFlag(&FLAGS_threads, 1);
126 }
127
128 return residual_flags;
129}
130
131Model ParseFlatzincModel(const std::string& input, bool input_is_filename,
132 SolverLogger* logger) {
133 WallTimer timer;
134 timer.Start();
135
136 // Check the extension.
137 if (input_is_filename && !absl::EndsWith(input, ".fzn")) {
138 LOG(FATAL) << "Unrecognized flatzinc file: `" << input << "'";
139 }
140
141 // Read model.
142 const std::string problem_name = input_is_filename
143 ? std::string(file::Stem(input))
144 : absl::GetFlag(FLAGS_fz_model_name);
145 Model model(problem_name);
146 if (input_is_filename) {
147 CHECK(ParseFlatzincFile(input, &model));
148 } else {
150 }
151
152 SOLVER_LOG(logger, "File ", (input_is_filename ? input : "stdin"),
153 " parsed in ", timer.GetInMs(), " ms");
154 SOLVER_LOG(logger, "");
155
156 // Presolve the model.
157 Presolver presolve(logger);
158 SOLVER_LOG(logger, "Presolve model");
159 timer.Reset();
160 timer.Start();
161 presolve.Run(&model);
162 SOLVER_LOG(logger, " - done in ", timer.GetInMs(), " ms");
163 SOLVER_LOG(logger);
164
165 // Print statistics.
166 ModelStatistics stats(model, logger);
167 stats.BuildStatistics();
168 stats.PrintStatistics();
169 return model;
170}
171
172void LogInFlatzincFormat(const std::string& multi_line_input) {
173 if (multi_line_input.empty()) {
174 std::cout << std::endl;
175 return;
176 }
177 const absl::string_view flatzinc_prefix =
178 absl::GetFlag(FLAGS_ortools_mode) ? "%% " : "";
179 const std::vector<absl::string_view> lines =
180 absl::StrSplit(multi_line_input, '\n');
181 for (const absl::string_view& line : lines) {
182 std::cout << flatzinc_prefix << line << std::endl;
183 }
184}
185
186} // namespace fz
187} // namespace operations_research
188
189int main(int argc, char** argv) {
190 // Flatzinc specifications require single dash parameters (-a, -f, -p).
191 // We need to fix parameters before parsing them.
192 const std::vector<char*> residual_flags =
194 // We allow piping model through stdin.
195 std::string input;
196 if (absl::GetFlag(FLAGS_read_from_stdin)) {
197 std::string currentLine;
198 while (std::getline(std::cin, currentLine)) {
199 input.append(currentLine);
200 }
201 } else {
202 if (residual_flags.empty()) {
203 LOG(ERROR) << "Usage: " << argv[0] << " <file>";
204 return EXIT_FAILURE;
205 }
206 input = residual_flags.back();
207 }
208
210 if (absl::GetFlag(FLAGS_ortools_mode)) {
211 logger.EnableLogging(absl::GetFlag(FLAGS_fz_logging));
212 // log_to_stdout is disabled later.
214 } else {
215 logger.EnableLogging(true);
216 logger.SetLogToStdOut(true);
217 }
218
221 input, !absl::GetFlag(FLAGS_read_from_stdin), &logger);
222
224 parameters.display_all_solutions = absl::GetFlag(FLAGS_display_all_solutions);
225 parameters.search_all_solutions = absl::GetFlag(FLAGS_search_all_solutions);
226 parameters.use_free_search = absl::GetFlag(FLAGS_free_search);
227 parameters.log_search_progress =
228 absl::GetFlag(FLAGS_fz_logging) || !absl::GetFlag(FLAGS_ortools_mode);
229 parameters.random_seed = absl::GetFlag(FLAGS_fz_seed);
230 parameters.display_statistics = absl::GetFlag(FLAGS_statistics);
231 parameters.number_of_threads = absl::GetFlag(FLAGS_threads);
232 parameters.max_time_in_seconds = absl::GetFlag(FLAGS_time_limit);
233 parameters.ortools_mode = absl::GetFlag(FLAGS_ortools_mode);
234
235 operations_research::SolverLogger solution_logger;
236 solution_logger.SetLogToStdOut(true);
237 solution_logger.EnableLogging(parameters.ortools_mode);
238
240 absl::GetFlag(FLAGS_params),
241 &logger, &solution_logger);
242 return EXIT_SUCCESS;
243}
int64_t GetInMs() const
Definition timer.h:47
void Reset()
Definition timer.h:27
void Start()
When Start() is called multiple times, only the most recent is used.
Definition timer.h:32
void EnableLogging(bool enable)
Definition logging.h:46
void SetLogToStdOut(bool enable)
Should all messages be displayed on stdout ?
Definition logging.h:52
void AddInfoLoggingCallback(std::function< void(const std::string &message)> callback)
Definition logging.cc:29
void PrintStatistics() const
--— Model statistics --—
Definition model.cc:1134
SatParameters parameters
ABSL_FLAG(double, time_limit, 0, "time limit in seconds.")
int main(int argc, char **argv)
Definition fz.cc:189
GRBmodel * model
time_limit
Definition solve.cc:22
absl::string_view Stem(absl::string_view path)
Definition path.cc:129
void LogInFlatzincFormat(const std::string &multi_line_input)
Definition fz.cc:172
bool ParseFlatzincString(const std::string &input, Model *model)
Definition parser.cc:67
bool ParseFlatzincFile(const std::string &filename, Model *model)
--— public parsing API --—
Definition parser.cc:42
Model ParseFlatzincModel(const std::string &input, bool input_is_filename, SolverLogger *logger)
Definition fz.cc:131
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)
In SWIG mode, we don't want anything besides these top-level includes.
int line
static int input(yyscan_t yyscanner)
static const char kUsage[]
#define SOLVER_LOG(logger,...)
Definition logging.h:109