forked from google/or-tools
-
Notifications
You must be signed in to change notification settings - Fork 9
/
termination.h
134 lines (115 loc) · 6.17 KB
/
termination.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
131
132
133
134
// 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.
#ifndef PDLP_TERMINATION_H_
#define PDLP_TERMINATION_H_
#include <atomic>
#include <optional>
#include "ortools/pdlp/solve_log.pb.h"
#include "ortools/pdlp/solvers.pb.h"
namespace operations_research::pdlp {
struct TerminationReasonAndPointType {
TerminationReason reason;
PointType type;
};
// Information about the quadratic program's primal and dual bounds that are
// needed to evaluate relative convergence criteria.
struct QuadraticProgramBoundNorms {
double l2_norm_primal_linear_objective;
double l2_norm_constraint_bounds;
double l_inf_norm_primal_linear_objective;
double l_inf_norm_constraint_bounds;
};
// Computes the effective optimality criteria for a `TerminationCriteria`.
TerminationCriteria::DetailedOptimalityCriteria EffectiveOptimalityCriteria(
const TerminationCriteria& termination_criteria);
// Like the previous overload but takes a `SimpleOptimalityCriteria`. Useful in
// unit tests where no `TerminationCriteria` is naturally available.
TerminationCriteria::DetailedOptimalityCriteria EffectiveOptimalityCriteria(
const TerminationCriteria::SimpleOptimalityCriteria& simple_criteria);
// Checks if any of the simple termination criteria are satisfied by `stats`,
// and returns a termination reason if so, and nullopt otherwise. The "simple"
// termination criteria are `time_sec_limit`, `iteration_limit`,
// `kkt_matrix_pass_limit`, and `interrupt_solve`. The corresponding fields of
// `stats` (`cumulative_time_sec`, `iteration_number`,
// `cumulative_kkt_matrix_passes`) are the only ones accessed. If returning a
// termination reason, the `PointType` will be set to `POINT_TYPE_NONE`.
std::optional<TerminationReasonAndPointType> CheckSimpleTerminationCriteria(
const TerminationCriteria& criteria, const IterationStats& stats,
const std::atomic<bool>* interrupt_solve = nullptr);
// Checks if any iterate-based termination criteria (i.e., the criteria not
// checked by `CheckSimpleTerimationCriteria()`) are satisfied by the solution
// state described by `stats` (see definitions of termination criteria in
// solvers.proto). `bound_norms` provides the instance-dependent data required
// for the relative convergence criteria. Returns a termination reason and a
// point type if so (if multiple criteria are satisfied, the optimality and
// infeasibility conditions are checked first). If `force_numerical_termination`
// is true, returns `TERMINATION_REASON_NUMERICAL_ERROR` if no other criteria
// are satisfied. The return value is empty in any other case. If the output is
// not empty, the `PointType` indicates which entry prompted termination. If no
// entry prompted termination, e.g. `TERMINATION_REASON_NUMERICAL_ERROR` is
// returned, then the `PointType` is set to `POINT_TYPE_NONE`. NOTE: This
// function assumes that the solution used to compute the stats satisfies the
// primal and dual variable bounds; see
// https://developers.google.com/optimization/lp/pdlp_math#dual_variable_bounds.
std::optional<TerminationReasonAndPointType> CheckIterateTerminationCriteria(
const TerminationCriteria& criteria, const IterationStats& stats,
const QuadraticProgramBoundNorms& bound_norms,
bool force_numerical_termination = false);
// Extracts the norms needed for the termination criteria from the full problem
// `stats`.
QuadraticProgramBoundNorms BoundNormsFromProblemStats(
const QuadraticProgramStats& stats);
// Returns `epsilon_absolute / epsilon_relative`, returning 1.0 if
// `epsilon_absolute` and `epsilon_relative` are equal (even if they are both
// 0.0 or infinity, which would normally yield NAN).
double EpsilonRatio(double epsilon_absolute, double epsilon_relative);
// Metrics for tracking progress when relative convergence criteria are used.
// These depend on the `ConvergenceInformation`, the problem data, and the
// convergence tolerances.
struct RelativeConvergenceInformation {
// Relative versions of the residuals, defined as
// relative_residual = residual / (eps_ratio + norm),
// where
// eps_ratio = `eps_optimal_absolute / eps_optimal_relative`
// residual = one of the residuals (l{2,_inf}_{primal,dual}_residual)
// norm = the relative norm (l{2,_inf} norm of
// {constraint_bounds,primal_linear_objective} respectively).
// If `eps_optimal_relative == eps_optimal_absolute`, eps_ratio will be 1.0
// (even if `eps_optimal_relative` == 0.0 or inf). Otherwise, if
// `eps_optimal_relative == 0.0`, these will all be 0.0.
//
// If `eps_optimal_relative > 0.0`, the absolute and relative termination
// criteria translate to relative_residual <= `eps_optimal_relative`.
double relative_l_inf_primal_residual = 0;
double relative_l2_primal_residual = 0;
double relative_l_inf_dual_residual = 0;
double relative_l2_dual_residual = 0;
// Relative optimality gap:
// (primal_objective - dual_objective) /
// (eps_ratio + |primal_objective| + |dual_objective|)
double relative_optimality_gap = 0;
};
RelativeConvergenceInformation ComputeRelativeResiduals(
const TerminationCriteria::DetailedOptimalityCriteria& optimality_criteria,
const ConvergenceInformation& stats,
const QuadraticProgramBoundNorms& bound_norms);
bool ObjectiveGapMet(
const TerminationCriteria::DetailedOptimalityCriteria& optimality_criteria,
const ConvergenceInformation& stats);
// Determines if the optimality criteria are met.
bool OptimalityCriteriaMet(
const TerminationCriteria::DetailedOptimalityCriteria& optimality_criteria,
const ConvergenceInformation& stats, OptimalityNorm optimality_norm,
const QuadraticProgramBoundNorms& bound_norms);
} // namespace operations_research::pdlp
#endif // PDLP_TERMINATION_H_