OR-Tools  9.3
piecewise_linear_function.h
Go to the documentation of this file.
1// Copyright 2010-2021 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// This file implements piecewise linear functions over int64_t. It is built
15// by inserting segments.
16//
17// This class maintains a minimal internal representation and checks for
18// overflow.
19
20#ifndef OR_TOOLS_UTIL_PIECEWISE_LINEAR_FUNCTION_H_
21#define OR_TOOLS_UTIL_PIECEWISE_LINEAR_FUNCTION_H_
22
23#include <algorithm>
24#include <functional>
25#include <memory>
26#include <string>
27#include <vector>
28
31#include "ortools/base/macros.h"
33
34namespace operations_research {
35// This structure stores one straight line. It contains the start point, the
36// end point and the slope.
37// It is defined for x values between start_x and end_x.
39 public:
40 PiecewiseSegment(int64_t point_x, int64_t point_y, int64_t slope,
41 int64_t other_point_x);
42
43 // Returns the value of the segment at point x.
44 int64_t Value(int64_t x) const;
45 // Returns the start of the segment's domain.
46 int64_t start_x() const { return start_x_; }
47 // Returns the end of the segment's domain.
48 int64_t end_x() const { return end_x_; }
49 // Returns the value at the start of the segment's domain.
50 int64_t start_y() const { return Value(start_x_); }
51 // Returns the value at the end of the segment's domain.
52 int64_t end_y() const { return Value(end_x_); }
53 // Returns the segment's slope.
54 int64_t slope() const { return slope_; }
55 // Returns the intersection of the segment's extension with the y axis.
56 int64_t intersection_y() const { return intersection_y_; }
57
58 // Comparison method useful for sorting a sequence of segments.
59 static bool SortComparator(const PiecewiseSegment& segment1,
60 const PiecewiseSegment& segment2);
61 // Comparison method useful for finding in which segment a point belongs.
62 static bool FindComparator(int64_t point, const PiecewiseSegment& segment);
63
64 // Expands segment to the specified endpoint, if it is further
65 // than the current endpoint. The reference point of the segment
66 // doesn't change for overflow reasons.
67 void ExpandEnd(int64_t end_x);
68 // Adds 'constant' to the 'x' the segments.
69 void AddConstantToX(int64_t constant);
70 // Adds 'constant' to the 'y' the segments.
71 void AddConstantToY(int64_t constant);
72
73 std::string DebugString() const;
74
75 private:
76 // Computes the value of the segment at point x, taking care of possible
77 // overflows when the value x follow the x coordinate of the segment's
78 // reference point.
79 int64_t SafeValuePostReference(int64_t x) const;
80 // Computes the value of the segment at point x, taking care of possible
81 // overflows when the value x follow the x coordinate of the segment's
82 // reference point.
83 int64_t SafeValuePreReference(int64_t x) const;
84
85 // The x coordinate of the segment's left endpoint.
86 int64_t start_x_;
87 // The x coordinate of the segment's right endpoint.
88 int64_t end_x_;
89 // The segment's slope.
90 int64_t slope_;
91 // The x coordinate of the segment's finite reference point.
92 int64_t reference_x_;
93 // The y coordinate of the segment's finite reference point.
94 int64_t reference_y_;
95 // The intersection of the segment's extension with the y axis.
96 int64_t intersection_y_;
97};
98
99// In mathematics, a piecewise linear function is a function composed
100// of straight-line, non overlapping sections.
102 public:
103 static const int kNotFound;
104
105 // This API provides a factory for creating different families of Piecewise
106 // Linear Functions based on specific properties of each family. The
107 // PiecewiseLinearFunction is composed by a set of PiecwiseSegments and upon
108 // creation is not modifiable but with the provided function operations.
109 // The object returned by any of these builders in the factory is owned by
110 // the client code.
111
112 // Builds the most generic form of multiple-segment piecewise linear function
113 // supporting domain holes. For a fixed index i the elements in points_x[i]
114 // points_y[i], slopes[i], other_points_x[i] represent a segment.
115 // The point (points_x[i], points_y[i]) represents one of the endpoints of
116 // the segment and the other_points_x[i] represents the x coordinate of the
117 // other endpoint which may precede, follow or coincide with points_x[i].
118 // The segments represented by these vectors should not be overlapping.
119 // Common endpoints are allowed.
121 std::vector<int64_t> points_x, std::vector<int64_t> points_y,
122 std::vector<int64_t> slopes, std::vector<int64_t> other_points_x);
123
124 // Builds a multiple-segment step function with continuous or non continuous
125 // domain. The arguments have the same semantics with the generic builder of
126 // the piecewise linear function. In the step function all the slopes are 0.
128 std::vector<int64_t> points_x, std::vector<int64_t> points_y,
129 std::vector<int64_t> other_points_x);
130
131 // Builds a multiple-segment piecewise linear function with domain from
132 // from kint64min to kint64max with n points and n+1 slopes. Each slope
133 // stops at the point with the corresponding index apart from the last one
134 // which stops at kint64max. The first slope stops at the first point at
135 // the level specified.
137 int64_t initial_level, std::vector<int64_t> points_x,
138 std::vector<int64_t> slopes);
139
140 // Builds a function consisting of one segment.
142 int64_t point_x, int64_t point_y, int64_t slope, int64_t other_point_x);
143
144 // Builds a function consisting of one ray starting at the specified
145 // x and y coordinates with the specified slope.
146 static PiecewiseLinearFunction* CreateRightRayFunction(int64_t point_x,
147 int64_t point_y,
148 int64_t slope);
149
150 // Builds a function consisting of one ray starting at the specified
151 // x and y coordinates with the specified slope.
152 static PiecewiseLinearFunction* CreateLeftRayFunction(int64_t point_x,
153 int64_t point_y,
154 int64_t slope);
155
156 // Builds a two-segment fixed charge piecewise linear cost function. For
157 // values less than zero, the cost is zero. For values greater than zero,
158 // cost follows the line specified by the slope and the value given as
159 // arguments. The slope and value are positive.
161 int64_t value);
162
163 // Builds an earliness-tardiness two-segment piecewise linear cost function.
164 // The reference specifies the point where the cost is zero. Before the
165 // reference, the cost increases with the earliness slope and after the
166 // reference, it increases with the tardiness slope. The absolute values of
167 // the slopes are given.
169 int64_t reference, int64_t earliness_slope, int64_t tardiness_slope);
170
171 // Builds an earliness-tardiness three-segment piecewise linear cost function
172 // with a slack period around the due date. The early slack is the point
173 // before which the cost increases with the ealiness slope specified. The
174 // late slack is the point after which the cost increases with the late slope
175 // specified. Between the early and the late slack point, the cost is zero.
176 // The absolute values of the slopes are given.
178 int64_t early_slack, int64_t late_slack, int64_t earliness_slope,
179 int64_t tardiness_slope);
180
181 // Returns if x is in the domain of the function.
182 bool InDomain(int64_t x) const;
183 // Determines whether the piecewise linear function is convex or non-convex
184 // and returns true when the function is convex.
185 bool IsConvex() const;
186 // Returns true if the piecewise linear function is non-decreasing.
187 bool IsNonDecreasing() const;
188 // Returns true if the piecewise linear function is non-increasing.
189 bool IsNonIncreasing() const;
190 // Returns the value of the piecewise linear function for x.
191 int64_t Value(int64_t x) const;
192 // Returns the maximum value of all the segments in the function.
193 int64_t GetMaximum() const;
194 // Returns the minimum value of all the segments in the function.
195 int64_t GetMinimum() const;
196 // Returns the maximum endpoint value of the segments in the specified
197 // range. If the range is disjoint from the segments in the function, it
198 // returns kint64max.
199 int64_t GetMaximum(int64_t range_start, int64_t range_end) const;
200 // Returns the minimum endpoint value of the segments in the specified
201 // range. If the range is disjoint from the segments in the function, it
202 // returns kint64max.
203 int64_t GetMinimum(int64_t range_start, int64_t range_end) const;
204 // Returns the smallest range within a given range containing all values
205 // greater than a given value.
206 std::pair<int64_t, int64_t> GetSmallestRangeGreaterThanValue(
207 int64_t range_start, int64_t range_end, int64_t value) const;
208 // Returns the smallest range within a given range containing all values
209 // less than a given value.
210 std::pair<int64_t, int64_t> GetSmallestRangeLessThanValue(
211 int64_t range_start, int64_t range_end, int64_t value) const;
212 // Returns the smallest range within a given range containing all values
213 // greater than value_min and less than value_max.
214 std::pair<int64_t, int64_t> GetSmallestRangeInValueRange(
215 int64_t range_start, int64_t range_end, int64_t value_min,
216 int64_t value_max) const;
217
218 // Adds 'constant' to the 'x' of all segments. If the argument is positive,
219 // the translation is to the right and when it's negative, to the left. The
220 // overflows and the underflows are sticky.
221 void AddConstantToX(int64_t constant);
222 // Adds 'constant' to the 'y' of all segments. If the argument is positive,
223 // the translation is up and when it's negative, down. The overflows and the
224 // underflows are sticky.
225 void AddConstantToY(int64_t constant);
226 // Adds the function to the existing one. The domain of the resulting
227 // function is the intersection of the two domains. The overflows and
228 // the underflows are sticky.
229 void Add(const PiecewiseLinearFunction& other);
230 // Subtracts the function to the existing one. The domain of the
231 // resulting function is the intersection of the two domains. The
232 // overflows and the underflows are sticky.
233 void Subtract(const PiecewiseLinearFunction& other);
234 // Decomposes the piecewise linear function in a set of convex piecewise
235 // linear functions. The objects in the vector are owned by the client code.
236 std::vector<PiecewiseLinearFunction*> DecomposeToConvexFunctions() const;
237
238 const std::vector<PiecewiseSegment>& segments() const { return segments_; }
239
240 std::string DebugString() const;
241
242 private:
243 // Takes the sequence of segments, sorts them on increasing start and inserts
244 // them in the piecewise linear function.
245 explicit PiecewiseLinearFunction(std::vector<PiecewiseSegment> segments);
246 // Inserts a segment in the function.
247 void InsertSegment(const PiecewiseSegment& segment);
248 // Operation between two functions. In any operation between two functions the
249 // final domain is the intersection between the two domains.
250 void Operation(const PiecewiseLinearFunction& other,
251 const std::function<int64_t(int64_t, int64_t)>& operation);
252 // Finds start and end segment indices from a range; returns false if the
253 // range is outside the domain of the function.
254 bool FindSegmentIndicesFromRange(int64_t range_start, int64_t range_end,
255 int* start_segment, int* end_segment) const;
256 void UpdateStatus() {
257 if (is_modified_) {
258 is_convex_ = IsConvexInternal();
259 is_non_decreasing_ = IsNonDecreasingInternal();
260 is_non_increasing_ = IsNonIncreasingInternal();
261 is_modified_ = false;
262 }
263 }
264 bool IsConvexInternal() const;
265 bool IsNonDecreasingInternal() const;
266 bool IsNonIncreasingInternal() const;
267
268 // The vector of segments in the function, sorted in ascending order of start
269 // points.
270 std::vector<PiecewiseSegment> segments_;
271 bool is_modified_;
272 bool is_convex_;
273 bool is_non_decreasing_;
274 bool is_non_increasing_;
275};
276} // namespace operations_research
277#endif // OR_TOOLS_UTIL_PIECEWISE_LINEAR_FUNCTION_H_
static PiecewiseLinearFunction * CreateRightRayFunction(int64_t point_x, int64_t point_y, int64_t slope)
static PiecewiseLinearFunction * CreateLeftRayFunction(int64_t point_x, int64_t point_y, int64_t slope)
static PiecewiseLinearFunction * CreateStepFunction(std::vector< int64_t > points_x, std::vector< int64_t > points_y, std::vector< int64_t > other_points_x)
std::pair< int64_t, int64_t > GetSmallestRangeInValueRange(int64_t range_start, int64_t range_end, int64_t value_min, int64_t value_max) const
std::vector< PiecewiseLinearFunction * > DecomposeToConvexFunctions() const
void Add(const PiecewiseLinearFunction &other)
static PiecewiseLinearFunction * CreateOneSegmentFunction(int64_t point_x, int64_t point_y, int64_t slope, int64_t other_point_x)
std::pair< int64_t, int64_t > GetSmallestRangeGreaterThanValue(int64_t range_start, int64_t range_end, int64_t value) const
void Subtract(const PiecewiseLinearFunction &other)
std::pair< int64_t, int64_t > GetSmallestRangeLessThanValue(int64_t range_start, int64_t range_end, int64_t value) const
const std::vector< PiecewiseSegment > & segments() const
static PiecewiseLinearFunction * CreatePiecewiseLinearFunction(std::vector< int64_t > points_x, std::vector< int64_t > points_y, std::vector< int64_t > slopes, std::vector< int64_t > other_points_x)
static PiecewiseLinearFunction * CreateEarlyTardyFunctionWithSlack(int64_t early_slack, int64_t late_slack, int64_t earliness_slope, int64_t tardiness_slope)
static PiecewiseLinearFunction * CreateFullDomainFunction(int64_t initial_level, std::vector< int64_t > points_x, std::vector< int64_t > slopes)
static PiecewiseLinearFunction * CreateEarlyTardyFunction(int64_t reference, int64_t earliness_slope, int64_t tardiness_slope)
static PiecewiseLinearFunction * CreateFixedChargeFunction(int64_t slope, int64_t value)
PiecewiseSegment(int64_t point_x, int64_t point_y, int64_t slope, int64_t other_point_x)
static bool FindComparator(int64_t point, const PiecewiseSegment &segment)
static bool SortComparator(const PiecewiseSegment &segment1, const PiecewiseSegment &segment2)
int64_t value
Collection of objects used to extend the Constraint Solver library.
const double constant