Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
sol_reader.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
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 "absl/strings/string_view.h"
28#include "ortools/linear_solver/linear_solver.pb.h"
32
33namespace operations_research {
34
35absl::StatusOr<glop::DenseRow> ParseSolFile(absl::string_view file_name,
37 ASSIGN_OR_RETURN(std::string sol_file, ReadFileToString(file_name));
38 return ParseSolString(sol_file, model);
39}
40
41absl::StatusOr<MPSolutionResponse> ParseSolFile(absl::string_view file_name,
42 const MPModelProto& model) {
43 ASSIGN_OR_RETURN(std::string sol_file, ReadFileToString(file_name));
44 return ParseSolString(sol_file, model);
45}
46
47absl::StatusOr<glop::DenseRow> ParseSolString(
48 const std::string& solution, const glop::LinearProgram& model) {
49 constexpr double kInfinity = std::numeric_limits<double>::infinity();
50
51 absl::flat_hash_map<std::string, glop::ColIndex> var_index_by_name;
52 for (glop::ColIndex col(0); col < model.num_variables(); ++col) {
53 var_index_by_name[model.GetVariableName(col)] = col;
54 }
55
56 glop::ColIndex num_variables = model.num_variables();
57 glop::DenseRow dense_row(num_variables.value(), 0);
58 std::vector<std::string> lines =
59 absl::StrSplit(solution, '\n', absl::SkipEmpty());
60 for (const std::string& line : lines) {
61 std::vector<std::string> fields =
62 absl::StrSplit(line, absl::ByAnyChar(" \t"), absl::SkipEmpty());
63
64 // Remove the comments.
65 for (int i = 0; i < fields.size(); ++i) {
66 if (fields[i][0] == '#') {
67 fields.resize(i);
68 break;
69 }
70 }
71
72 if (fields.empty()) continue;
73
74 if (fields.size() == 1) {
75 return absl::InvalidArgumentError(
76 absl::StrCat("Found only one field on line '", line, "'."));
77 }
78 if (fields.size() > 2) {
79 return absl::InvalidArgumentError(
80 absl::StrCat("Found more than two fields on line '", line, "'."));
81 }
82
83 const std::string var_name = fields[0];
84 const double var_value =
85 strings::ParseLeadingDoubleValue(fields[1], kInfinity);
86 if (var_value == kInfinity) {
87 return absl::InvalidArgumentError(
88 absl::StrCat("Couldn't parse value on line '", line, "'."));
89 }
90
91 if (var_name == "=obj=") continue;
92
93 auto iter = var_index_by_name.find(var_name);
94 if (iter == var_index_by_name.end()) {
95 return absl::InvalidArgumentError(absl::StrCat(
96 "Couldn't find variable named '", var_name, "' in the model."));
97 }
98 dense_row[iter->second] = var_value;
99 }
100
101 return dense_row;
102}
103
104absl::StatusOr<MPSolutionResponse> ParseSolString(const std::string& solution,
105 const MPModelProto& model) {
106 constexpr double kInfinity = std::numeric_limits<double>::infinity();
107
108 absl::flat_hash_map<std::string, int> var_index_by_name;
109 for (int var_index = 0; var_index < model.variable_size(); ++var_index) {
110 if (model.variable(var_index).name().empty()) {
111 return absl::InvalidArgumentError("Found variable without name.");
112 }
113 var_index_by_name[model.variable(var_index).name()] = var_index;
114 }
115
116 MPSolutionResponse response;
117 std::vector<double> var_values(model.variable_size(), 0);
118 std::vector<std::string> lines =
119 absl::StrSplit(solution, '\n', absl::SkipEmpty());
120 for (const std::string& line : lines) {
121 std::vector<std::string> fields =
122 absl::StrSplit(line, absl::ByAnyChar(" \t"), absl::SkipEmpty());
123
124 // Remove the comments.
125 for (int i = 0; i < fields.size(); ++i) {
126 if (fields[i][0] == '#') {
127 fields.resize(i);
128 break;
129 }
130 }
131
132 if (fields.empty()) continue;
133
134 if (fields.size() == 1) {
135 return absl::InvalidArgumentError(
136 absl::StrCat("Found only one field on line '", line, "'."));
137 }
138 if (fields.size() > 2) {
139 return absl::InvalidArgumentError(
140 absl::StrCat("Found more than two fields on line '", line, "'."));
141 }
142
143 const std::string var_name = fields[0];
144 const double var_value =
145 strings::ParseLeadingDoubleValue(fields[1], kInfinity);
146 if (var_value == kInfinity) {
147 return absl::InvalidArgumentError(
148 absl::StrCat("Couldn't parse value on line '", line, "'."));
149 }
150
151 if (var_name == "=obj=") {
152 response.set_objective_value(var_value);
153 continue;
154 }
155
156 auto iter = var_index_by_name.find(var_name);
157 if (iter == var_index_by_name.end()) {
158 return absl::InvalidArgumentError(absl::StrCat(
159 "Couldn't find variable named '", var_name, "' in the model."));
160 }
161 var_values[iter->second] = var_value;
162 }
163
164 for (const double value : var_values) {
165 response.add_variable_value(value);
166 }
167 return response;
168}
169
170} // namespace operations_research
#define ASSIGN_OR_RETURN(lhs, rexpr)
int64_t value
GRBmodel * model
ColIndex col
Definition markowitz.cc:187
double solution
In SWIG mode, we don't want anything besides these top-level includes.
absl::StatusOr< glop::DenseRow > ParseSolFile(absl::string_view file_name, const glop::LinearProgram &model)
Parse a solution to model from a file.
Definition sol_reader.cc:35
absl::StatusOr< std::string > ReadFileToString(absl::string_view filename)
Reads a file, optionally gzipped, to a string.
Definition file_util.cc:42
absl::StatusOr< glop::DenseRow > ParseSolString(const std::string &solution, const glop::LinearProgram &model)
Parse a solution to model from a string.
Definition sol_reader.cc:47
double ParseLeadingDoubleValue(const char *str, double deflt)
Definition numbers.cc:210
int line
int var_index
Definition search.cc:3268