Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
opb_reader.h
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#ifndef OR_TOOLS_SAT_OPB_READER_H_
15#define OR_TOOLS_SAT_OPB_READER_H_
16
17#include <algorithm>
18#include <cstdint>
19#include <memory>
20#include <string>
21#include <vector>
22
23#include "absl/log/check.h"
24#include "absl/strings/numbers.h"
25#include "absl/strings/str_split.h"
27#include "ortools/sat/boolean_problem.pb.h"
29
30namespace operations_research {
31namespace sat {
32
33// This class loads a file in pbo file format into a LinearBooleanProblem.
34// The format is described here:
35// http://www.cril.univ-artois.fr/PB12/format.pdf
36class OpbReader {
37 public:
38 OpbReader() = default;
39 // This type is neither copyable nor movable.
40 OpbReader(const OpbReader&) = delete;
41 OpbReader& operator=(const OpbReader&) = delete;
42
43 // Loads the given opb filename into the given problem.
44 bool Load(const std::string& filename, LinearBooleanProblem* problem) {
45 problem->Clear();
46 problem->set_name(ExtractProblemName(filename));
47
48 num_variables_ = 0;
49 int num_lines = 0;
50 for (const std::string& line : FileLines(filename)) {
51 ++num_lines;
52 ProcessNewLine(problem, line);
53 }
54 if (num_lines == 0) {
55 LOG(FATAL) << "File '" << filename << "' is empty or can't be read.";
56 }
57 problem->set_num_variables(num_variables_);
58 return true;
59 }
60
61 private:
62 // Since the problem name is not stored in the cnf format, we infer it from
63 // the file name.
64 static std::string ExtractProblemName(const std::string& filename) {
65 const int found = filename.find_last_of('/');
66 const std::string problem_name =
67 found != std::string::npos ? filename.substr(found + 1) : filename;
68 return problem_name;
69 }
70
71 void ProcessNewLine(LinearBooleanProblem* problem, const std::string& line) {
72 const std::vector<std::string> words =
73 absl::StrSplit(line, absl::ByAnyChar(" ;"), absl::SkipEmpty());
74 if (words.empty() || words[0].empty() || words[0][0] == '*') {
75 return;
76 }
77
78 if (words[0] == "min:") {
79 LinearObjective* objective = problem->mutable_objective();
80 for (int i = 1; i < words.size(); ++i) {
81 const std::string& word = words[i];
82 if (word.empty() || word[0] == ';') continue;
83 if (word[0] == 'x') {
84 int literal;
85 CHECK(absl::SimpleAtoi(word.substr(1), &literal));
86 num_variables_ = std::max(num_variables_, literal);
87 objective->add_literals(literal);
88 } else {
89 int64_t value;
90 CHECK(absl::SimpleAtoi(word, &value));
91 objective->add_coefficients(value);
92 }
93 }
94 if (objective->literals_size() != objective->coefficients_size()) {
95 LOG(INFO) << "words.size() = " << words.size();
96 LOG(FATAL) << "Failed to parse objective:\n " << line;
97 }
98 return;
99 }
100 LinearBooleanConstraint* constraint = problem->add_constraints();
101 for (int i = 0; i < words.size(); ++i) {
102 const std::string& word = words[i];
103 CHECK(!word.empty());
104 if (word == ">=") {
105 CHECK_LT(i + 1, words.size());
106 int64_t value;
107 CHECK(absl::SimpleAtoi(words[i + 1], &value));
108 constraint->set_lower_bound(value);
109 break;
110 } else if (word == "=") {
111 CHECK_LT(i + 1, words.size());
112 int64_t value;
113 CHECK(absl::SimpleAtoi(words[i + 1], &value));
114 constraint->set_upper_bound(value);
115 constraint->set_lower_bound(value);
116 break;
117 } else {
118 if (word[0] == 'x') {
119 int literal;
120 CHECK(absl::SimpleAtoi(word.substr(1), &literal));
121 num_variables_ = std::max(num_variables_, literal);
122 constraint->add_literals(literal);
123 } else {
124 int64_t value;
125 CHECK(absl::SimpleAtoi(words[i], &value));
126 constraint->add_coefficients(value);
127 }
128 }
129 }
130 if (constraint->literals_size() != constraint->coefficients_size()) {
131 LOG(FATAL) << "Failed to parse constraint:\n " << line;
132 }
133 }
134
135 int num_variables_;
136};
137
138} // namespace sat
139} // namespace operations_research
140
141#endif // OR_TOOLS_SAT_OPB_READER_H_
bool Load(const std::string &filename, LinearBooleanProblem *problem)
Loads the given opb filename into the given problem.
Definition opb_reader.h:44
OpbReader(const OpbReader &)=delete
This type is neither copyable nor movable.
OpbReader & operator=(const OpbReader &)=delete
int64_t value
int literal
In SWIG mode, we don't want anything besides these top-level includes.
int line