18 #include "absl/status/status.h"
19 #include "absl/strings/str_cat.h"
20 #include "absl/strings/string_view.h"
22 #include "ortools/pdlp/solvers.pb.h"
26 using ::absl::InvalidArgumentError;
27 using ::absl::OkStatus;
30 const absl::string_view
name) {
31 if (std::isnan(
value)) {
32 return InvalidArgumentError(absl::StrCat(
name,
" is NAN"));
35 return InvalidArgumentError(absl::StrCat(
name,
" must be non-negative"));
37 return absl::OkStatus();
41 if (criteria.optimality_norm() != OPTIMALITY_NORM_L_INF &&
42 criteria.optimality_norm() != OPTIMALITY_NORM_L2 &&
43 criteria.optimality_norm() != OPTIMALITY_NORM_L_INF_COMPONENTWISE) {
44 return InvalidArgumentError(
"invalid value for optimality_norm");
46 if (criteria.has_detailed_optimality_criteria() ||
47 criteria.has_simple_optimality_criteria()) {
48 if (criteria.has_eps_optimal_absolute()) {
49 return InvalidArgumentError(
50 "eps_optimal_absolute should not be set if "
51 "detailed_optimality_criteria or simple_optimality_criteria is used");
53 if (criteria.has_eps_optimal_relative()) {
54 return InvalidArgumentError(
55 "eps_optimal_relative should not be set if "
56 "detailed_optimality_criteria or simple_optimality_criteria is used");
59 if (criteria.has_detailed_optimality_criteria()) {
61 criteria.detailed_optimality_criteria()
62 .eps_optimal_primal_residual_absolute(),
63 "detailed_optimality_criteria.eps_optimal_primal_residual_absolute"));
65 criteria.detailed_optimality_criteria()
66 .eps_optimal_primal_residual_relative(),
67 "detailed_optimality_criteria.eps_optimal_primal_residual_relative"));
69 criteria.detailed_optimality_criteria()
70 .eps_optimal_dual_residual_absolute(),
71 "detailed_optimality_criteria.eps_optimal_dual_residual_absolute"));
73 criteria.detailed_optimality_criteria()
74 .eps_optimal_dual_residual_relative(),
75 "detailed_optimality_criteria.eps_optimal_dual_residual_relative"));
77 criteria.detailed_optimality_criteria()
78 .eps_optimal_objective_gap_absolute(),
79 "detailed_optimality_criteria.eps_optimal_objective_gap_absolute"));
81 criteria.detailed_optimality_criteria()
82 .eps_optimal_objective_gap_relative(),
83 "detailed_optimality_criteria.eps_optimal_objective_gap_relative"));
84 }
else if (criteria.has_simple_optimality_criteria()) {
86 criteria.simple_optimality_criteria().eps_optimal_absolute(),
87 "simple_optimality_criteria.eps_optimal_absolute"));
89 criteria.simple_optimality_criteria().eps_optimal_relative(),
90 "simple_optimality_criteria.eps_optimal_relative"));
93 "eps_optimal_absolute"));
95 "eps_optimal_relative"));
98 "eps_primal_infeasible"));
106 if (criteria.iteration_limit() < 0) {
107 return InvalidArgumentError(
"iteration_limit must be non-negative");
110 "kkt_matrix_pass_limit"));
116 const AdaptiveLinesearchParams& params) {
117 if (std::isnan(params.step_size_reduction_exponent())) {
118 return InvalidArgumentError(
"step_size_reduction_exponent is NAN");
120 if (params.step_size_reduction_exponent() <= 0) {
121 return InvalidArgumentError(
122 "step_size_reduction_exponent must be positive");
124 if (std::isnan(params.step_size_growth_exponent())) {
125 return InvalidArgumentError(
"step_size_growth_exponent is NAN");
127 if (params.step_size_growth_exponent() <= 0) {
128 return InvalidArgumentError(
"step_size_growth_exponent must be positive");
134 if (std::isnan(params.step_size_downscaling_factor())) {
135 return InvalidArgumentError(
"step_size_downscaling_factor is NAN");
137 if (params.step_size_downscaling_factor() <= 0 ||
138 params.step_size_downscaling_factor() >= 1) {
139 return InvalidArgumentError(
140 "step_size_downscaling_factor must be between 0 and 1 exclusive");
142 if (std::isnan(params.linesearch_contraction_factor())) {
143 return InvalidArgumentError(
"linesearch_contraction_factor is NAN");
145 if (params.linesearch_contraction_factor() <= 0 ||
146 params.linesearch_contraction_factor() >= 1) {
147 return InvalidArgumentError(
148 "linesearch_contraction_factor must be between 0 and 1 exclusive");
150 if (std::isnan(params.step_size_interpolation())) {
151 return InvalidArgumentError(
"step_size_interpolation is NAN");
153 if (params.step_size_interpolation() < 0) {
154 return InvalidArgumentError(
"step_size_interpolation must be non-negative");
160 const PrimalDualHybridGradientParams& params) {
162 <<
"termination_criteria invalid";
163 if (params.num_threads() <= 0) {
164 return InvalidArgumentError(
"num_threads must be positive");
166 if (params.verbosity_level() < 0) {
167 return InvalidArgumentError(
"verbosity_level must be non-negative");
169 if (params.major_iteration_frequency() <= 0) {
170 return InvalidArgumentError(
"major_iteration_frequency must be positive");
172 if (params.termination_check_frequency() <= 0) {
173 return InvalidArgumentError(
"termination_check_frequency must be positive");
175 if (params.restart_strategy() !=
176 PrimalDualHybridGradientParams::NO_RESTARTS &&
177 params.restart_strategy() !=
178 PrimalDualHybridGradientParams::EVERY_MAJOR_ITERATION &&
179 params.restart_strategy() !=
180 PrimalDualHybridGradientParams::ADAPTIVE_HEURISTIC &&
181 params.restart_strategy() !=
182 PrimalDualHybridGradientParams::ADAPTIVE_DISTANCE_BASED) {
183 return InvalidArgumentError(
"invalid restart_strategy");
185 if (std::isnan(params.primal_weight_update_smoothing())) {
186 return InvalidArgumentError(
"primal_weight_update_smoothing is NAN");
188 if (params.primal_weight_update_smoothing() < 0 ||
189 params.primal_weight_update_smoothing() > 1) {
190 return InvalidArgumentError(
191 "primal_weight_update_smoothing must be between 0 and 1 inclusive");
193 if (std::isnan(params.initial_primal_weight())) {
194 return InvalidArgumentError(
"initial_primal_weight is NAN");
196 if (params.has_initial_primal_weight() &&
197 params.initial_primal_weight() <= 0) {
198 return InvalidArgumentError(
199 "initial_primal_weight must be positive if specified");
201 if (params.l_inf_ruiz_iterations() < 0) {
202 return InvalidArgumentError(
"l_inf_ruiz_iterations must be non-negative");
204 if (params.l_inf_ruiz_iterations() > 100) {
205 return InvalidArgumentError(
"l_inf_ruiz_iterations must be at most 100");
207 if (std::isnan(params.sufficient_reduction_for_restart())) {
208 return InvalidArgumentError(
"sufficient_reduction_for_restart is NAN");
210 if (params.sufficient_reduction_for_restart() <= 0 ||
211 params.sufficient_reduction_for_restart() >= 1) {
212 return InvalidArgumentError(
213 "sufficient_reduction_for_restart must be between 0 and 1 exclusive");
215 if (std::isnan(params.necessary_reduction_for_restart())) {
216 return InvalidArgumentError(
"necessary_reduction_for_restart is NAN");
218 if (params.necessary_reduction_for_restart() <
219 params.sufficient_reduction_for_restart() ||
220 params.necessary_reduction_for_restart() >= 1) {
221 return InvalidArgumentError(
222 "necessary_reduction_for_restart must be in the interval "
223 "[sufficient_reduction_for_restart, 1)");
225 if (params.linesearch_rule() !=
226 PrimalDualHybridGradientParams::ADAPTIVE_LINESEARCH_RULE &&
227 params.linesearch_rule() !=
228 PrimalDualHybridGradientParams::MALITSKY_POCK_LINESEARCH_RULE &&
229 params.linesearch_rule() !=
230 PrimalDualHybridGradientParams::CONSTANT_STEP_SIZE_RULE) {
231 return InvalidArgumentError(
"invalid linesearch_rule");
235 <<
"adaptive_linesearch_parameters invalid";
237 <<
"malitsky_pock_parameters invalid";
238 if (std::isnan(params.initial_step_size_scaling())) {
239 return InvalidArgumentError(
"initial_step_size_scaling is NAN");
241 if (params.initial_step_size_scaling() <= 0.0) {
242 return InvalidArgumentError(
"initial_step_size_scaling must be positive");
245 if (std::isnan(params.infinite_constraint_bound_threshold())) {
246 return InvalidArgumentError(
"infinite_constraint_bound_threshold is NAN");
248 if (params.infinite_constraint_bound_threshold() < 0.0) {
249 return InvalidArgumentError(
250 "infinite_constraint_bound_threshold must be non-negative");
252 if (std::isnan(params.diagonal_qp_trust_region_solver_tolerance())) {
253 return InvalidArgumentError(
254 "diagonal_qp_trust_region_solver_tolerance is NAN");
256 if (params.diagonal_qp_trust_region_solver_tolerance() < 0.0) {
257 return InvalidArgumentError(
258 "diagonal_qp_trust_region_solver_tolerance must be non-negative");
#define RETURN_IF_ERROR(expr)
absl::Status ValidateTerminationCriteria(const TerminationCriteria &criteria)
absl::Status CheckNonNegative(const double value, const absl::string_view name)
absl::Status ValidateMalitskyPockParams(const MalitskyPockParams ¶ms)
absl::Status ValidateAdaptiveLinesearchParams(const AdaptiveLinesearchParams ¶ms)
absl::Status ValidatePrimalDualHybridGradientParams(const PrimalDualHybridGradientParams ¶ms)