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