OR-Tools  9.6
sol_reader.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 
15 
16 #include <limits>
17 #include <string>
18 #include <vector>
19 
20 #include "absl/container/flat_hash_map.h"
21 #include "absl/status/status.h"
22 #include "absl/status/statusor.h"
23 #include "absl/strings/str_cat.h"
24 #include "absl/strings/str_split.h"
25 #include "ortools/base/numbers.h"
27 #include "ortools/linear_solver/linear_solver.pb.h"
30 #include "ortools/util/file_util.h"
31 
32 namespace operations_research {
33 
34 absl::StatusOr<glop::DenseRow> ParseSolFile(const std::string& file_name,
35  const glop::LinearProgram& model) {
36  ASSIGN_OR_RETURN(std::string sol_file, ReadFileToString(file_name));
37  return ParseSolString(sol_file, model);
38 }
39 
40 absl::StatusOr<MPSolutionResponse> ParseSolFile(const std::string& file_name,
41  const MPModelProto& model) {
42  ASSIGN_OR_RETURN(std::string sol_file, ReadFileToString(file_name));
43  return ParseSolString(sol_file, model);
44 }
45 
46 absl::StatusOr<glop::DenseRow> ParseSolString(
47  const std::string& solution, const glop::LinearProgram& model) {
48  constexpr double kInfinity = std::numeric_limits<double>::infinity();
49 
50  absl::flat_hash_map<std::string, glop::ColIndex> var_index_by_name;
51  for (glop::ColIndex col(0); col < model.num_variables(); ++col) {
52  var_index_by_name[model.GetVariableName(col)] = col;
53  }
54 
55  glop::ColIndex num_variables = model.num_variables();
56  glop::DenseRow dense_row(num_variables.value(), 0);
57  std::vector<std::string> lines =
58  absl::StrSplit(solution, '\n', absl::SkipEmpty());
59  for (const std::string& line : lines) {
60  std::vector<std::string> fields =
61  absl::StrSplit(line, absl::ByAnyChar(" \t"), absl::SkipEmpty());
62 
63  // Remove the comments.
64  for (int i = 0; i < fields.size(); ++i) {
65  if (fields[i][0] == '#') {
66  fields.resize(i);
67  break;
68  }
69  }
70 
71  if (fields.empty()) continue;
72 
73  if (fields.size() == 1) {
74  return absl::InvalidArgumentError(
75  absl::StrCat("Found only one field on line '", line, "'."));
76  }
77  if (fields.size() > 2) {
78  return absl::InvalidArgumentError(
79  absl::StrCat("Found more than two fields on line '", line, "'."));
80  }
81 
82  const std::string var_name = fields[0];
83  const double var_value =
85  if (var_value == kInfinity) {
86  return absl::InvalidArgumentError(
87  absl::StrCat("Couldn't parse value on line '", line, "'."));
88  }
89 
90  if (var_name == "=obj=") continue;
91 
92  auto iter = var_index_by_name.find(var_name);
93  if (iter == var_index_by_name.end()) {
94  return absl::InvalidArgumentError(absl::StrCat(
95  "Couldn't find variable named '", var_name, "' in the model."));
96  }
97  dense_row[iter->second] = var_value;
98  }
99 
100  return dense_row;
101 }
102 
103 absl::StatusOr<MPSolutionResponse> ParseSolString(const std::string& solution,
104  const MPModelProto& model) {
105  constexpr double kInfinity = std::numeric_limits<double>::infinity();
106 
107  absl::flat_hash_map<std::string, int> var_index_by_name;
108  for (int var_index = 0; var_index < model.variable_size(); ++var_index) {
109  if (model.variable(var_index).name().empty()) {
110  return absl::InvalidArgumentError("Found variable without name.");
111  }
112  var_index_by_name[model.variable(var_index).name()] = var_index;
113  }
114 
115  MPSolutionResponse response;
116  std::vector<double> var_values(model.variable_size(), 0);
117  std::vector<std::string> lines =
118  absl::StrSplit(solution, '\n', absl::SkipEmpty());
119  for (const std::string& line : lines) {
120  std::vector<std::string> fields =
121  absl::StrSplit(line, absl::ByAnyChar(" \t"), absl::SkipEmpty());
122 
123  // Remove the comments.
124  for (int i = 0; i < fields.size(); ++i) {
125  if (fields[i][0] == '#') {
126  fields.resize(i);
127  break;
128  }
129  }
130 
131  if (fields.empty()) continue;
132 
133  if (fields.size() == 1) {
134  return absl::InvalidArgumentError(
135  absl::StrCat("Found only one field on line '", line, "'."));
136  }
137  if (fields.size() > 2) {
138  return absl::InvalidArgumentError(
139  absl::StrCat("Found more than two fields on line '", line, "'."));
140  }
141 
142  const std::string var_name = fields[0];
143  const double var_value =
145  if (var_value == kInfinity) {
146  return absl::InvalidArgumentError(
147  absl::StrCat("Couldn't parse value on line '", line, "'."));
148  }
149 
150  if (var_name == "=obj=") {
151  response.set_objective_value(var_value);
152  continue;
153  }
154 
155  auto iter = var_index_by_name.find(var_name);
156  if (iter == var_index_by_name.end()) {
157  return absl::InvalidArgumentError(absl::StrCat(
158  "Couldn't find variable named '", var_name, "' in the model."));
159  }
160  var_values[iter->second] = var_value;
161  }
162 
163  for (const double value : var_values) {
164  response.add_variable_value(value);
165  }
166  return response;
167 }
168 
169 } // namespace operations_research
#define ASSIGN_OR_RETURN(lhs, rexpr)
SharedResponseManager * response
int64_t value
GRBmodel * model
ColIndex col
Definition: markowitz.cc:186
Collection of objects used to extend the Constraint Solver library.
absl::StatusOr< std::string > ReadFileToString(absl::string_view filename)
Definition: file_util.cc:36
absl::StatusOr< glop::DenseRow > ParseSolFile(const std::string &file_name, const glop::LinearProgram &model)
Definition: sol_reader.cc:34
absl::StatusOr< glop::DenseRow > ParseSolString(const std::string &solution, const glop::LinearProgram &model)
Definition: sol_reader.cc:46
double ParseLeadingDoubleValue(const char *str, double deflt)
Definition: numbers.cc:200
int line
Definition: parse_proto.cc:31
constexpr double kInfinity