forked from google/or-tools
-
Notifications
You must be signed in to change notification settings - Fork 9
/
lp_parser.h
130 lines (116 loc) · 5.83 KB
/
lp_parser.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright 2010-2024 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// A simple parser of a linear program from string.
//
// We accept a format produced by LinearProgram::Dump(), which is similar to
// LP file used by lp_solve (see http://lpsolve.sourceforge.net/5.1/index.htm).
// Example:
// 1: min: 1 + x1 + 2 * x2;
// 2: 0 <= x1 <= 1;
// 3: x2 >= 2;
// 4: r1: 1 <= x1 - x2 <= 2;
// 5: 0 <= x1 + x2 <= inf;
// 6: int x1, x3;
// 7: bin x2;
//
// Line 1 is the objective, line 2 and 3 define variable bounds, line 4 is a
// named constraint, line 5 is an unnamed constraint. Line 6 is the list of
// integer variables. Line 7 is the list of binary variables. The lines can be
// in any order, the line numbers do _not_ belong to the string being parsed.
//
// Caveats:
// 1. Plus sign and multiplication sign are optional. Thus, "min: 1 x1 x2" is
// the same as "min: 1*x1 + x2". All consecutive signs will be compacted into
// one sign using mathematical rules (i.e., the parity of minus sign).
// E.g., "min: ++---+ - +x1" is the same as "min: x1".
// 2. A constraint consists of two or three parts. A two part constraint has
// a bound on the left (resp. right) side and variables on the right
// (resp. left) side, with the two parts being separated by any of the
// relation signs "<", "<=", "=", ">=", ">".
// 3. A three part constraint has the variables in the middle part, and two
// bounds on the left and right side, with all three parts being separated by
// any of "<", "<=", ">=", ">".
// 4. "<" means "<=", and ">" means ">=".
// 5. An unnamed constraint involving exactly one variable with coefficient
// equal to 1, defines the variable bound(s). Otherwise, the constraint
// defines a new constraint.
// 6. If there is no bound defined for a variable, it will be assumed to be
// unbounded (i.e., from -inf to +inf).
// 7. A bound must be a number or "inf". A coefficient must be finite and
// cannot overflow. A number can be represented in a scientific notation,
// e.g., +1.2E-2. Consequently,
// "min: 1e2" means minimization of 100,
// "min: 1 e2" means minimization of 1*e2, where e2 is a variable,
// "min: 1 + e2" means minimization of 1 + e2, where e2 is a variable,
// "min: 1 1*e2" means minimization of 1 + e2, where e2 is a variable.
// "min: 1 1e2" is invalid as it would mean minimization of 1 + 100.
// 8. In a constraint, in the part with variables, all elements must be
// variables with optional coefficients and signs (i.e., no offset is
// allowed).
// 9. Variables in the objective, and in each of the constraint cannot repeat.
// E.g., this is invalid: "min: x + x".
// 10. The offset in the objective must be specified at the beginning, i.e.,
// after min: or max: and before any variables.
// 11. The parsing will fail if due to bounding of a variable the lower bound
// becomes strictly greater than the upper bound. E.g., these fail to
// parse: "min x; 1 <= x <= 0;", "min x; 0 <= x <= 1; 2 <= x <= 3". On the
// other hand the parser does _not_ attempt to "round" the bounds for integer
// variables. E.g., "min x; 0.5 <= x <= 0.8; int x" results in bounding the x
// variable between 0.5 and 0.8, despite there is no integer value it can
// take. Similarly, "min x; bin x; x <= 0.5" results in bounding the x
// variable between 0.0 and 0.5, despite the only value it can take is 0.
#ifndef OR_TOOLS_LP_DATA_LP_PARSER_H_
#define OR_TOOLS_LP_DATA_LP_PARSER_H_
#if defined(USE_LP_PARSER)
#include <string>
#include <vector>
#include "absl/base/attributes.h"
#include "absl/base/port.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "ortools/linear_solver/linear_solver.pb.h"
#include "ortools/lp_data/lp_data.h"
#include "ortools/lp_data/lp_types.h"
namespace operations_research {
// This calls ParseLp() under the hood. See below.
absl::StatusOr<MPModelProto> ModelProtoFromLpFormat(absl::string_view model);
namespace glop {
// Like ModelProtoFromLpFormat(), but outputs a glop::LinearProgram.
ABSL_MUST_USE_RESULT bool ParseLp(absl::string_view model, LinearProgram* lp);
// Represents a constraint parsed from the LP file format (used by
// LinearProgram::Dump()).
struct ParsedConstraint {
// The name of the constraint. Empty if the constraint has no name.
std::string name;
// Contains the names of the variables used in the constraint, in the order in
// which they appear in the string representation.
std::vector<std::string> variable_names;
// Contains the coefficients of the variables used in the constraint. Note
// that variable_names and coefficients are parallel arrays, i.e.
// coefficients[i] is the coefficient for variable_names[i].
std::vector<Fractional> coefficients;
// The lower bound of the constraint. Set to -infinity when the constraint has
// no lower bound.
Fractional lower_bound;
// The upper bound of the constraint. Set to +infinity when the constraint has
// no upper bound.
Fractional upper_bound;
};
// Parses a constraint in the format used by LinearProgram::Dump(). Returns an
// InvalidArgumentError with an appropriate error message when the parsing
// fails.
absl::StatusOr<ParsedConstraint> ParseConstraint(absl::string_view constraint);
} // namespace glop
} // namespace operations_research
#endif // defined(USE_LP_PARSER)
#endif // OR_TOOLS_LP_DATA_LP_PARSER_H_