460 lines
21 KiB
Protocol Buffer
460 lines
21 KiB
Protocol Buffer
// Copyright 2010-2025 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.
|
|
|
|
// These proto messages are for collecting solve statistics, e.g., during
|
|
// experiments.
|
|
|
|
syntax = "proto2";
|
|
|
|
package operations_research.pdlp;
|
|
|
|
option java_package = "com.google.ortools.pdlp";
|
|
option java_multiple_files = true;
|
|
option csharp_namespace = "Google.OrTools.PDLP";
|
|
|
|
import "ortools/pdlp/solvers.proto";
|
|
|
|
// Easy-to-compute statistics for the quadratic program.
|
|
message QuadraticProgramStats {
|
|
optional int64 num_variables = 1;
|
|
optional int64 num_constraints = 2;
|
|
|
|
// Minimum row and column infinity norms of the constraint matrix. All-zero
|
|
// rows and columns are excluded. If the constraint matrix contains no nonzero
|
|
// entries, the values returned are 0.0.
|
|
optional double constraint_matrix_col_min_l_inf_norm = 3;
|
|
optional double constraint_matrix_row_min_l_inf_norm = 4;
|
|
|
|
// The number of (finite) nonzero entries in the constraint matrix.
|
|
optional int64 constraint_matrix_num_nonzeros = 5;
|
|
|
|
// Max/min/mean/l2_norm of absolute values of (finite) elements in constraint
|
|
// matrix. Explicit zeros are included in the mean, but excluded from the min.
|
|
// Note that the maximum absolute value is also equal to the maximal row and
|
|
// column infinity norms of the constraint matrix. If the constraint matrix is
|
|
// empty, the values returned are 0.0 for the maximum, minimum, and l2_norm,
|
|
// and NaN for the average.
|
|
optional double constraint_matrix_abs_max = 6;
|
|
optional double constraint_matrix_abs_min = 7;
|
|
optional double constraint_matrix_abs_avg = 8;
|
|
optional double constraint_matrix_l2_norm = 25;
|
|
|
|
// Statistics of the combined vector of the constraint lower and upper bounds.
|
|
// Given parallel lower and upper bounds vectors, the "combined bounds" vector
|
|
// takes the maximum absolute value of each pair of bounds, ignoring all non-
|
|
// finite values. The comment in solvers.proto:TerminationCriteria provides an
|
|
// example of the combined bounds vector. The min is over the nonzero combined
|
|
// bounds. If there are no constraints, the values returned are 0 for the
|
|
// maximum, minimum, and l2 norm and NaN for the average.
|
|
optional double combined_bounds_max = 9;
|
|
optional double combined_bounds_min = 10;
|
|
optional double combined_bounds_avg = 11;
|
|
optional double combined_bounds_l2_norm = 24;
|
|
|
|
// Statistics of the combined vector of the variable lower and upper bounds.
|
|
// See the comment before `combined_bounds_max` for a description of the
|
|
// "combined bounds" vector. The min is over the nonzero combined bounds. If
|
|
// there are no variables, the values returned are 0 for the maximum, minimum,
|
|
// and l2 norm and NaN for the average.
|
|
optional double combined_variable_bounds_max = 28;
|
|
optional double combined_variable_bounds_min = 29;
|
|
optional double combined_variable_bounds_avg = 30;
|
|
optional double combined_variable_bounds_l2_norm = 31;
|
|
|
|
// Number of finite variable bound gaps, which are the elementwise difference
|
|
// between the upper and lower bounds on primal feasible solutions.
|
|
optional int64 variable_bound_gaps_num_finite = 12;
|
|
|
|
// Max/min/mean/l2_norm over all finite variable bound gaps. The min excludes
|
|
// zero bound gaps (i.e., fixed variables). When there are no finite gaps, the
|
|
// values returned are 0 for the maximum, minimum, and l2_norm, and NaN for
|
|
// the average.
|
|
optional double variable_bound_gaps_max = 13;
|
|
optional double variable_bound_gaps_min = 14;
|
|
optional double variable_bound_gaps_avg = 15;
|
|
optional double variable_bound_gaps_l2_norm = 26;
|
|
|
|
// Statistics of the objective vector. The min is over the nonzero terms.
|
|
optional double objective_vector_abs_max = 16;
|
|
optional double objective_vector_abs_min = 17;
|
|
optional double objective_vector_abs_avg = 18;
|
|
optional double objective_vector_l2_norm = 23;
|
|
|
|
optional int64 objective_matrix_num_nonzeros = 19;
|
|
|
|
// Max/min/mean/l2_norm of absolute values of elements of the objective
|
|
// matrix. The min is over nonzero terms. If the objective matrix is empty,
|
|
// the returned values are 0.0, 0.0, NaN, and 0.0 respectively.
|
|
optional double objective_matrix_abs_max = 20;
|
|
optional double objective_matrix_abs_min = 21;
|
|
optional double objective_matrix_abs_avg = 22;
|
|
optional double objective_matrix_l2_norm = 27;
|
|
}
|
|
|
|
// Specifies whether a restart was performed on a given iteration.
|
|
enum RestartChoice {
|
|
RESTART_CHOICE_UNSPECIFIED = 0;
|
|
// No restart on this iteration.
|
|
RESTART_CHOICE_NO_RESTART = 1;
|
|
// The weighted average of iterates is cleared and reset to the current point.
|
|
// Note that from a mathematical perspective this can be equivalently viewed
|
|
// as restarting the algorithm but picking the restart point to be the current
|
|
// iterate.
|
|
RESTART_CHOICE_WEIGHTED_AVERAGE_RESET = 2;
|
|
// The algorithm is restarted at the average of iterates since the last
|
|
// restart.
|
|
RESTART_CHOICE_RESTART_TO_AVERAGE = 3;
|
|
}
|
|
|
|
// Identifies the type of point used to compute the fields in a given proto; see
|
|
// ConvergenceInformation and InfeasibilityInformation.
|
|
enum PointType {
|
|
POINT_TYPE_UNSPECIFIED = 0;
|
|
// Current iterate (x_k, y_k).
|
|
POINT_TYPE_CURRENT_ITERATE = 1;
|
|
// Difference of iterates (x_{k+1} - x_k, y_{k+1} - y_k).
|
|
POINT_TYPE_ITERATE_DIFFERENCE = 2;
|
|
// Average of iterates since the last restart.
|
|
POINT_TYPE_AVERAGE_ITERATE = 3;
|
|
// There is no corresponding point.
|
|
POINT_TYPE_NONE = 4;
|
|
// Output of presolver.
|
|
POINT_TYPE_PRESOLVER_SOLUTION = 5;
|
|
// Combined solution from primal and dual feasibility polishing.
|
|
POINT_TYPE_FEASIBILITY_POLISHING_SOLUTION = 6;
|
|
}
|
|
|
|
// Information measuring how close a candidate is to establishing feasibility
|
|
// and optimality; see also TerminationCriteria.
|
|
message ConvergenceInformation {
|
|
// Type of the candidate point described by this ConvergenceInformation.
|
|
optional PointType candidate_type = 1;
|
|
|
|
// The primal objective. The primal need not be feasible.
|
|
optional double primal_objective = 2;
|
|
|
|
// The dual objective. The dual need not be feasible. The dual objective
|
|
// includes the contributions from reduced costs.
|
|
// NOTE: The definition of dual_objective changed in OR-tools version 9.8.
|
|
// See
|
|
// https://developers.google.com/optimization/lp/pdlp_math#reduced_costs_dual_residuals_and_the_corrected_dual_objective
|
|
// for details.
|
|
optional double dual_objective = 3;
|
|
|
|
// If possible (e.g., when all primal variables have lower and upper bounds),
|
|
// a correct dual bound. The value is negative infinity if no corrected dual
|
|
// bound is available.
|
|
optional double corrected_dual_objective = 4;
|
|
|
|
// The maximum violation of any primal constraint, i.e., the l_∞ norm of the
|
|
// violations.
|
|
optional double l_inf_primal_residual = 5;
|
|
|
|
// The l_2 norm of the violations of primal constraints.
|
|
optional double l2_primal_residual = 6;
|
|
|
|
// The maximum relative violation of any primal constraint, with an absolute
|
|
// offset, i.e., the l_∞ norm of [violation / (eps_ratio + |bound|)] where
|
|
// eps_ratio = eps_optimal_primal_residual_absolute
|
|
// / eps_optimal_primal_residual_relative
|
|
// and bound is the violated bound.
|
|
optional double l_inf_componentwise_primal_residual = 24;
|
|
|
|
// The maximum violation of any dual constraint, i.e., the l_∞ norm of the
|
|
// violations.
|
|
optional double l_inf_dual_residual = 7;
|
|
|
|
// The l_2 norm of the violations of dual constraints.
|
|
optional double l2_dual_residual = 8;
|
|
|
|
// The maximum relative violation of any dual constraint, with an absolute
|
|
// offset, i.e., the l_∞ norm of [violation / (eps_ratio + |objective|)] where
|
|
// eps_ratio = eps_optimal_dual_residual_absolute
|
|
// / eps_optimal_dual_residual_relative
|
|
optional double l_inf_componentwise_dual_residual = 25;
|
|
|
|
// The maximum absolute value of the primal variables, i.e., the l_∞ norm.
|
|
// This is useful to detect when the primal iterates are diverging. Divergence
|
|
// of the primal variables could be an algorithmic issue, or indicate that the
|
|
// dual is infeasible.
|
|
optional double l_inf_primal_variable = 14;
|
|
|
|
// The l_2 norm of the primal variables.
|
|
optional double l2_primal_variable = 15;
|
|
|
|
// The maximum absolute value of the dual variables, i.e., the l_∞ norm. This
|
|
// is useful to detect when the dual iterates are diverging. Divergence of the
|
|
// dual variables could be an algorithmic issue, or indicate the primal is
|
|
// infeasible.
|
|
optional double l_inf_dual_variable = 16;
|
|
|
|
// The l_2 norm of the dual variables.
|
|
optional double l2_dual_variable = 17;
|
|
|
|
reserved 9, 10, 11, 12, 13, 18, 19, 20, 21, 22, 23;
|
|
}
|
|
|
|
// Information measuring how close a point is to establishing primal or dual
|
|
// infeasibility (i.e. has no solution); see also TerminationCriteria.
|
|
message InfeasibilityInformation {
|
|
// Let x_ray be the algorithm's estimate of the primal extreme ray where x_ray
|
|
// is a vector that satisfies the sign constraints for a ray, scaled such that
|
|
// its infinity norm is one (the sign constraints are the variable bound
|
|
// constraints, with all finite bounds mapped to zero). A simple and typical
|
|
// choice of x_ray is x_ray = x / | x |_∞ where x is the current primal
|
|
// iterate projected onto the primal ray sign constraints. For this value
|
|
// compute the maximum absolute error in the primal linear program with the
|
|
// right hand side set to zero.
|
|
optional double max_primal_ray_infeasibility = 1;
|
|
|
|
// The value of the linear part of the primal objective (ignoring additive
|
|
// constants) evaluated at x_ray, i.e., c' * x_ray where c is the objective
|
|
// coefficient vector.
|
|
optional double primal_ray_linear_objective = 2;
|
|
|
|
// The l_∞ norm of the vector resulting from taking the quadratic matrix from
|
|
// primal objective and multiplying it by the primal variables. For linear
|
|
// programming problems this is zero.
|
|
optional double primal_ray_quadratic_norm = 3;
|
|
|
|
// Let (y_ray, r_ray) be the algorithm's estimate of the dual and reduced cost
|
|
// extreme ray where (y_ray, r_ray) is a vector (satisfying the dual variable
|
|
// constraints) scaled such that its infinity norm is one. A simple and
|
|
// typical choice of y_ray is (y_ray, r_ray) = (y, r) / max(| y |_∞, | r |_∞)
|
|
// where y is the current dual iterate and r is the current dual reduced
|
|
// costs. Consider the quadratic program we are solving but with the objective
|
|
// (both quadratic and linear terms) set to zero. This forms a linear program
|
|
// (label this linear program (1)) with no objective. Take the dual of (1) and
|
|
// compute the maximum absolute value of the constraint error for
|
|
// (y_ray, r_ray) to obtain the value of max_dual_ray_infeasibility.
|
|
optional double max_dual_ray_infeasibility = 4;
|
|
|
|
// The objective of the linear program labeled (1) in the previous paragraph.
|
|
optional double dual_ray_objective = 5;
|
|
|
|
// Type of the point used to compute the InfeasibilityInformation.
|
|
optional PointType candidate_type = 6;
|
|
|
|
reserved 7, 8;
|
|
}
|
|
|
|
message PointMetadata {
|
|
// Type of the point that this metadata corresponds to.
|
|
optional PointType point_type = 1;
|
|
|
|
// Projections of the primal solution onto random planes.
|
|
repeated double random_primal_projections = 2 [packed = true];
|
|
|
|
// Projections of the dual solution onto random planes.
|
|
repeated double random_dual_projections = 3 [packed = true];
|
|
|
|
// The number of primal variables that are not at their bounds.
|
|
optional int64 active_primal_variable_count = 4;
|
|
|
|
// The number of dual variables that are not at their bounds.
|
|
optional int64 active_dual_variable_count = 5;
|
|
|
|
// The number of primal variables that have a different bound status than they
|
|
// did at the last restart.
|
|
optional int64 active_primal_variable_change = 6;
|
|
|
|
// The number of dual variables that have a different bound status than they
|
|
// did at the last restart.
|
|
optional int64 active_dual_variable_change = 7;
|
|
}
|
|
|
|
// All values in IterationStats assume that the primal quadratic program is a
|
|
// minimization problem and the dual is a maximization problem. Problems should
|
|
// be transformed to this form if they are not already in this form. The dual
|
|
// vector is defined to be the vector of multipliers on the linear constraints,
|
|
// that is, excluding dual multipliers on variable bounds (reduced costs).
|
|
message IterationStats {
|
|
// The iteration number at which these stats were recorded. By convention,
|
|
// iteration counts start at 1, and the stats correspond to the solution
|
|
// *after* the iteration. Therefore stats from iteration 0 are the stats at
|
|
// the starting point.
|
|
optional int32 iteration_number = 1;
|
|
|
|
// A set of statistics measuring how close a point is to establishing primal
|
|
// and dual feasibility and optimality. This field is repeated since there
|
|
// might be several different points that are considered.
|
|
repeated ConvergenceInformation convergence_information = 2;
|
|
|
|
// A set of statistics measuring how close a point is to establishing primal
|
|
// or dual infeasibility (i.e., has no solution). This field is repeated since
|
|
// there might be several different points that could establish infeasibility.
|
|
repeated InfeasibilityInformation infeasibility_information = 3;
|
|
|
|
// Auxiliary statistics for each type of point.
|
|
repeated PointMetadata point_metadata = 11;
|
|
|
|
// The cumulative number of passes through the KKT matrix since the start of
|
|
// the solve. One pass is a multply by the constraint matrix, its transpose
|
|
// and the matrix that defines the quadratic part of the objective.
|
|
//
|
|
// For example, each iteration of mirror saddle prox contributes 2.0 to this
|
|
// sum. This is a float because it can include fractional passes through the
|
|
// data. For example, in an active set method we may only use a submatrix with
|
|
// 20% of the nonzeros of the KKT matrix at each iteration in which case 0.2
|
|
// would be added to the total.
|
|
optional double cumulative_kkt_matrix_passes = 4;
|
|
|
|
// The total number of rejected steps (e.g., within a line search procedure)
|
|
// since the start of the solve.
|
|
optional int32 cumulative_rejected_steps = 5;
|
|
|
|
// The amount of time passed since we started solving the problem (see solver
|
|
// log `solve_time_sec` which records total time).
|
|
optional double cumulative_time_sec = 6;
|
|
|
|
// The kind of restart that occurred at this iteration, or NO_RESTART if a
|
|
// restart did not occur.
|
|
optional RestartChoice restart_used = 7;
|
|
|
|
// Step size used at this iteration. Note that the step size used for the
|
|
// primal update is step_size / primal_weight, while the one used for the dual
|
|
// update is step_size * primal_weight.
|
|
optional double step_size = 8;
|
|
|
|
// Primal weight controlling the relation between primal and dual step sizes.
|
|
// See field 'step_size' for a detailed description.
|
|
optional double primal_weight = 9;
|
|
|
|
reserved 10;
|
|
}
|
|
|
|
enum TerminationReason {
|
|
TERMINATION_REASON_UNSPECIFIED = 0;
|
|
TERMINATION_REASON_OPTIMAL = 1;
|
|
// Note in this situation the dual could be either unbounded or infeasible.
|
|
TERMINATION_REASON_PRIMAL_INFEASIBLE = 2;
|
|
// Note in this situation the primal could be either unbounded or infeasible.
|
|
TERMINATION_REASON_DUAL_INFEASIBLE = 3;
|
|
TERMINATION_REASON_TIME_LIMIT = 4;
|
|
TERMINATION_REASON_ITERATION_LIMIT = 5;
|
|
TERMINATION_REASON_KKT_MATRIX_PASS_LIMIT = 8;
|
|
TERMINATION_REASON_INTERRUPTED_BY_USER = 12;
|
|
TERMINATION_REASON_NUMERICAL_ERROR = 6;
|
|
// Indicates that the solver detected invalid problem data, e.g., inconsistent
|
|
// bounds.
|
|
TERMINATION_REASON_INVALID_PROBLEM = 9;
|
|
// Indicates that the solver detected that the initial solution that was
|
|
// provided was invalid, e.g., wrong size or containing NAN or inf.
|
|
TERMINATION_REASON_INVALID_INITIAL_SOLUTION = 13;
|
|
// Indicates that an invalid value for the parameters was detected.
|
|
TERMINATION_REASON_INVALID_PARAMETER = 10;
|
|
TERMINATION_REASON_OTHER = 7;
|
|
// Primal or dual infeasibility was detected (e.g. by presolve) but no
|
|
// certificate is available.
|
|
TERMINATION_REASON_PRIMAL_OR_DUAL_INFEASIBLE = 11;
|
|
}
|
|
|
|
enum PolishingPhaseType {
|
|
POLISHING_PHASE_TYPE_UNSPECIFIED = 0;
|
|
POLISHING_PHASE_TYPE_PRIMAL_FEASIBILITY = 1;
|
|
POLISHING_PHASE_TYPE_DUAL_FEASIBILITY = 2;
|
|
}
|
|
|
|
// Details about one primal feasibility or dual feasibility polishing phase
|
|
// within a solve with `use_feasibility_polishing`. See `SolveLog` for
|
|
// descriptions of the fields with the same name.
|
|
message FeasibilityPolishingDetails {
|
|
optional PolishingPhaseType polishing_phase_type = 1;
|
|
// The iteration count for the main iteration when this feasibility polishing
|
|
// phase was triggered.
|
|
optional int32 main_iteration_count = 2;
|
|
optional PrimalDualHybridGradientParams params = 3;
|
|
optional TerminationReason termination_reason = 4;
|
|
optional int32 iteration_count = 5;
|
|
optional double solve_time_sec = 6;
|
|
optional IterationStats solution_stats = 7;
|
|
optional PointType solution_type = 8;
|
|
repeated IterationStats iteration_stats = 9;
|
|
}
|
|
|
|
message SolveLog {
|
|
// The name of the optimization problem.
|
|
optional string instance_name = 1;
|
|
|
|
// If solved with PDLP, the parameters for this solve.
|
|
optional PrimalDualHybridGradientParams params = 14;
|
|
|
|
// The reason that the solve terminated.
|
|
optional TerminationReason termination_reason = 3;
|
|
|
|
// Optional extra information about the termination reason.
|
|
optional string termination_string = 4;
|
|
|
|
// The total number of iterations during the solve. For a solve with
|
|
// `use_feasibility_polishing` this count includes the iterations from
|
|
// the feasibility polishing phases.
|
|
optional int32 iteration_count = 5;
|
|
|
|
// Time for preprocessing (everything before iteration 0). This is also
|
|
// included in `solve_time_sec`.
|
|
optional double preprocessing_time_sec = 13;
|
|
|
|
// The runtime of the solve. Note: This should not be used for comparing
|
|
// methods unless care is taken to control for noise in runtime measurement.
|
|
// For a solve with `use_feasibility_polishing` this count includes the
|
|
// iterations from the feasibility polishing phases.
|
|
optional double solve_time_sec = 6;
|
|
|
|
// The `IterationStats` for the final iteration of the solver. For a solve
|
|
// with `use_feasibility_polishing`, the work metrics (iteration_count,
|
|
// cumulative_kkt_matrix_passes, etc.) will include the work done in the
|
|
// feasibility polishing phases.
|
|
// NOTE: Regardless of preprocessing (i.e. scaling or presolve) the optimality
|
|
// or infeasibility information is evaluated with respect to the original
|
|
// problem.
|
|
optional IterationStats solution_stats = 8;
|
|
|
|
// The type of the output point that the solver returned. The quality of the
|
|
// point is reported in the corresponding entry of
|
|
// solution_stats.convergence_information and/or
|
|
// solution_stats.infeasibility_information. If termination_reason is
|
|
// TERMINATION_REASON_OPTIMAL, it's guaranteed that the corresponding entry of
|
|
// solution_stats.convergence_information satisfies the optimality conditions.
|
|
// Similarly, if termination_reason is either
|
|
// TERMINATION_REASON_PRIMAL_INFEASIBLE or TERMINATION_REASON_DUAL_INFEASIBLE
|
|
// the corresponding entry of solution_stats.infeasibility_information
|
|
// satisifes conditions for declaring primal or dual infeasibility,
|
|
// respectively.
|
|
// If termination_reason is anything else, e.g. TERMINATION_REASON_TIME_LIMIT
|
|
// or TERMINATION_REASON_PRIMAL_OR_DUAL_INFEASIBLE, the solution may not
|
|
// satisfy the optimality or infeasibility conditions.
|
|
optional PointType solution_type = 10;
|
|
|
|
// A history of iteration stats for the solve. The iteration_number fields
|
|
// should be in increasing order. The frequency at which these stats should be
|
|
// recorded is not specified. This field is "more" optional than the others
|
|
// because it often significantly increases the size of the message, and
|
|
// because the information may not be available for third-party solvers.
|
|
// For a solve with `use_feasibility_polishing`, these iteration stats will
|
|
// only reflect the work done in the main iterations (not the feasibility
|
|
// polishing phases).
|
|
repeated IterationStats iteration_stats = 7;
|
|
|
|
// Statistics of the original problem.
|
|
optional QuadraticProgramStats original_problem_stats = 11;
|
|
|
|
// Statistics of the problem after preprocessing.
|
|
optional QuadraticProgramStats preprocessed_problem_stats = 12;
|
|
|
|
// If solving with `use_feasibility_polishing`, details about the primal and
|
|
// dual feasibility polishing phases.
|
|
repeated FeasibilityPolishingDetails feasibility_polishing_details = 15;
|
|
|
|
reserved 2, 9;
|
|
}
|