Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
linear_relaxation.h
Go to the documentation of this file.
1// Copyright 2010-2025 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 ORTOOLS_SAT_LINEAR_RELAXATION_H_
15#define ORTOOLS_SAT_LINEAR_RELAXATION_H_
16
17#include <optional>
18#include <vector>
19
20#include "absl/types/span.h"
22#include "ortools/sat/cuts.h"
26#include "ortools/sat/model.h"
29
30namespace operations_research {
31namespace sat {
32
34 std::vector<LinearConstraint> linear_constraints;
35 std::vector<std::vector<Literal>> at_most_ones;
36 std::vector<CutGenerator> cut_generators;
37};
38
39// Looks at all the encoding literal (li <=> var == value_i) that have a
40// view and add a linear relaxation of their relationship with var.
41//
42// If the encoding is full, we can just add:
43// - Sum li == 1
44// - var == min_value + Sum li * (value_i - min_value)
45//
46// When the set of such encoding literals do not cover the full domain of var,
47// we do something a bit more involved. Let min_not_encoded/max_not_encoded the
48// min and max value of the domain of var that is NOT part of the encoding.
49// We add:
50// - Sum li <= 1
51// - var >= (Sum li * value_i) + (1 - Sum li) * min_not_encoded
52// - var <= (Sum li * value_i) + (1 - Sum li) * max_not_encoded
53//
54// Note of the special case where min_not_encoded == max_not_encoded that kind
55// of reduce to the full encoding, except with a different "rhs" value.
56//
57// We also increment the corresponding counter if we added something. We
58// consider the relaxation "tight" if the encoding was full or if
59// min_not_encoded == max_not_encoded.
60void AppendRelaxationForEqualityEncoding(IntegerVariable var,
61 const Model& model,
62 LinearRelaxation* relaxation,
63 int* num_tight, int* num_loose);
64
65// This is a different relaxation that use a partial set of literal li such that
66// (li <=> var >= xi). In which case we use the following encoding:
67// - li >= l_{i+1} for all possible i. Note that the xi need to be sorted.
68// - var >= min + l0 * (x0 - min) + Sum_{i>0} li * (xi - x_{i-1})
69// - and same as above for NegationOf(var) for the upper bound.
70//
71// Like for AppendRelaxationForEqualityEncoding() we skip any li that do not
72// have an integer view.
73void AppendPartialGreaterThanEncodingRelaxation(IntegerVariable var,
74 const Model& model,
75 LinearRelaxation* relaxation);
76
77// Returns a vector of new literals in exactly one relationship.
78// In addition, this create an IntegerView for all these literals and also add
79// the exactly one to the LinearRelaxation.
80std::vector<Literal> CreateAlternativeLiteralsWithView(
81 int num_literals, Model* model, LinearRelaxation* relaxation);
82
83void AppendBoolOrRelaxation(const ConstraintProto& ct, Model* model,
84 LinearRelaxation* relaxation);
85
86void AppendBoolAndRelaxation(const ConstraintProto& ct, Model* model,
87 LinearRelaxation* relaxation,
88 ActivityBoundHelper* activity_helper = nullptr);
89
91 LinearRelaxation* relaxation);
92
94 LinearRelaxation* relaxation);
95
96// Adds linearization of int max constraints. Returns a vector of z vars such
97// that: z_vars[l] == 1 <=> target = exprs[l].
98//
99// Consider the Lin Max constraint with d expressions and n variables in the
100// form: target = max {exprs[l] = Sum (wli * xi + bl)}. l in {1,..,d}.
101// Li = lower bound of xi
102// Ui = upper bound of xi.
103// Let zl be in {0,1} for all l in {1,..,d}.
104// The target = exprs[l] when zl = 1.
105//
106// The following is a valid linearization for Lin Max.
107// target >= exprs[l], for all l in {1,..,d}
108// target <= Sum_i(wki * xi) + Sum_l((Nkl + bl) * zl), for all k in {1,..,d}
109// Where Nkl is a large number defined as:
110// Nkl = Sum_i(max((wli - wki)*Li, (wli - wki)*Ui))
111// = Sum (max corner difference for variable i, target expr k, max expr l)
112// Reference: "Strong mixed-integer programming formulations for trained neural
113// networks" by Ross Anderson et. (https://arxiv.org/pdf/1811.01988.pdf).
114// TODO(user): Support linear expression as target.
116 const ConstraintProto& ct, Model* model, LinearRelaxation* relaxation,
117 ActivityBoundHelper* activity_helper = nullptr);
118
119void AppendLinMaxRelaxationPart2(IntegerVariable target,
120 absl::Span<const Literal> alternative_literals,
121 absl::Span<const LinearExpression> exprs,
122 Model* model, LinearRelaxation* relaxation);
123
124// Note: This only works if all affine expressions share the same variable.
125void AppendMaxAffineRelaxation(const ConstraintProto& ct, Model* model,
126 LinearRelaxation* relaxation,
127 ActivityBoundHelper* activity_helper = nullptr);
128
129// Appends linear constraints to the relaxation. This also handles the
130// relaxation of linear constraints with enforcement literals.
131// A linear constraint lb <= ax <= ub with enforcement literals {ei} is relaxed
132// as following.
133// lb <= (Sum Negated(ei) * (lb - implied_lb)) + ax <= inf
134// -inf <= (Sum Negated(ei) * (ub - implied_ub)) + ax <= ub
135// Where implied_lb and implied_ub are trivial lower and upper bounds of the
136// constraint.
138 const ConstraintProto& ct, Model* model, LinearRelaxation* relaxation,
139 ActivityBoundHelper* activity_helper = nullptr);
141 absl::Span<const int> enforcement, LinearConstraint&& linear_constraint,
142 Model* model, LinearRelaxation* relaxation,
143 ActivityBoundHelper* activity_helper = nullptr);
144
146 LinearRelaxation* relaxation);
147
148// Adds linearization of no overlap constraints.
149// It adds an energetic equation linking the duration of all potential tasks to
150// the actual span of the no overlap constraint.
152 Model* model,
153 LinearRelaxation* relaxation);
154
155// Adds linearization of cumulative constraints.The second part adds an
156// energetic equation linking the duration of all potential tasks to the actual
157// span * capacity of the cumulative constraint.
159 Model* model,
160 LinearRelaxation* relaxation);
161
162// Cut generators.
163void AddIntProdCutGenerator(const ConstraintProto& ct, int linearization_level,
164 Model* m, LinearRelaxation* relaxation);
165
166void AddSquareCutGenerator(const ConstraintProto& ct, int linearization_level,
167 Model* m, LinearRelaxation* relaxation);
168
170 int linearization_level, Model* m,
171 LinearRelaxation* relaxation);
172
174 LinearRelaxation* relaxation);
175
176// Routing relaxation and cut generators.
177
178void AppendCircuitRelaxation(const ConstraintProto& ct, Model* model,
179 LinearRelaxation* relaxation);
180
181void AppendRoutesRelaxation(const ConstraintProto& ct, Model* model,
182 LinearRelaxation* relaxation);
183
185 LinearRelaxation* relaxation);
186
188 LinearRelaxation* relaxation);
189
190// Scheduling relaxations and cut generators.
191
192// Adds linearization of cumulative constraints.The second part adds an
193// energetic equation linking the duration of all potential tasks to the actual
194// span * capacity of the cumulative constraint. It uses the makespan to compute
195// the span of the constraint if defined.
196void AddCumulativeRelaxation(const AffineExpression& capacity,
198 SchedulingDemandHelper* demands,
199 const std::optional<AffineExpression>& makespan,
200 Model* model, LinearRelaxation* relaxation);
201
204 SchedulingDemandHelper* demands,
205 const std::optional<AffineExpression>& makespan,
206 Model* m, LinearRelaxation* relaxation);
207
209 const std::optional<AffineExpression>& makespan,
210 Model* m, LinearRelaxation* relaxation);
211
213 LinearRelaxation* relaxation);
214
215// Adds linearization of different types of constraints.
216void TryToLinearizeConstraint(const CpModelProto& model_proto,
217 const ConstraintProto& ct,
218 int linearization_level, Model* model,
219 LinearRelaxation* relaxation,
220 ActivityBoundHelper* helper = nullptr);
221
222// Builds the linear relaxation of a CpModelProto.
224 Model* m);
225
226} // namespace sat
227} // namespace operations_research
228
229#endif // ORTOOLS_SAT_LINEAR_RELAXATION_H_
void AppendNoOverlapRelaxationAndCutGenerator(const ConstraintProto &ct, Model *model, LinearRelaxation *relaxation)
void AppendCumulativeRelaxationAndCutGenerator(const ConstraintProto &ct, Model *model, LinearRelaxation *relaxation)
void AddSquareCutGenerator(const ConstraintProto &ct, int linearization_level, Model *m, LinearRelaxation *relaxation)
void AppendExactlyOneRelaxation(const ConstraintProto &ct, Model *model, LinearRelaxation *relaxation)
void AddCumulativeCutGenerator(const AffineExpression &capacity, SchedulingConstraintHelper *helper, SchedulingDemandHelper *demands_helper, const std::optional< AffineExpression > &makespan, Model *m, LinearRelaxation *relaxation)
void AppendLinMaxRelaxationPart2(IntegerVariable target, absl::Span< const Literal > alternative_literals, absl::Span< const LinearExpression > exprs, Model *model, LinearRelaxation *relaxation)
void AddCumulativeRelaxation(const AffineExpression &capacity, SchedulingConstraintHelper *helper, SchedulingDemandHelper *demands_helper, const std::optional< AffineExpression > &makespan, Model *model, LinearRelaxation *relaxation)
void AppendRoutesRelaxation(const ConstraintProto &ct, Model *model, LinearRelaxation *relaxation)
void AddCircuitCutGenerator(const ConstraintProto &ct, Model *m, LinearRelaxation *relaxation)
LinearRelaxation ComputeLinearRelaxation(const CpModelProto &model_proto, Model *m)
void AddIntProdCutGenerator(const ConstraintProto &ct, int linearization_level, Model *m, LinearRelaxation *relaxation)
void AddRoutesCutGenerator(const ConstraintProto &ct, Model *m, LinearRelaxation *relaxation)
void AppendMaxAffineRelaxation(const ConstraintProto &ct, Model *model, LinearRelaxation *relaxation, ActivityBoundHelper *activity_helper)
void TryToLinearizeConstraint(const CpModelProto &, const ConstraintProto &ct, int linearization_level, Model *model, LinearRelaxation *relaxation, ActivityBoundHelper *activity_helper)
void AppendPartialGreaterThanEncodingRelaxation(IntegerVariable var, const Model &model, LinearRelaxation *relaxation)
void AppendCircuitRelaxation(const ConstraintProto &ct, Model *model, LinearRelaxation *relaxation)
void AppendLinearConstraintRelaxation(const ConstraintProto &ct, Model *model, LinearRelaxation *relaxation, ActivityBoundHelper *activity_helper)
void AppendSquareRelaxation(const ConstraintProto &ct, Model *m, LinearRelaxation *relaxation)
void AddLinMaxCutGenerator(const ConstraintProto &ct, Model *m, LinearRelaxation *relaxation)
void AppendBoolAndRelaxation(const ConstraintProto &ct, Model *model, LinearRelaxation *relaxation, ActivityBoundHelper *activity_helper)
void AddAllDiffRelaxationAndCutGenerator(const ConstraintProto &ct, int linearization_level, Model *m, LinearRelaxation *relaxation)
void AppendAtMostOneRelaxation(const ConstraintProto &ct, Model *model, LinearRelaxation *relaxation)
void AddNoOverlapCutGenerator(SchedulingConstraintHelper *helper, const std::optional< AffineExpression > &makespan, Model *m, LinearRelaxation *relaxation)
void AddNoOverlap2dCutGenerator(const ConstraintProto &ct, Model *m, LinearRelaxation *relaxation)
void AppendLinMaxRelaxationPart1(const ConstraintProto &ct, Model *model, LinearRelaxation *relaxation, ActivityBoundHelper *activity_helper)
std::vector< Literal > CreateAlternativeLiteralsWithView(int num_literals, Model *model, LinearRelaxation *relaxation)
void AppendBoolOrRelaxation(const ConstraintProto &ct, Model *model, LinearRelaxation *relaxation)
void AppendRelaxationForEqualityEncoding(IntegerVariable var, const Model &model, LinearRelaxation *relaxation, int *num_tight, int *num_loose)
OR-Tools root namespace.
std::vector< std::vector< Literal > > at_most_ones
std::vector< LinearConstraint > linear_constraints