14#ifndef PDLP_TRUST_REGION_H_
15#define PDLP_TRUST_REGION_H_
24#include "absl/algorithm/container.h"
25#include "absl/log/check.h"
60 const Eigen::VectorXd& variable_lower_bounds,
61 const Eigen::VectorXd& variable_upper_bounds,
62 const Eigen::VectorXd& center_point,
63 const Eigen::VectorXd& norm_weights,
84 const Eigen::VectorXd& objective_vector,
85 const Eigen::VectorXd& objective_matrix_diagonal,
86 const Eigen::VectorXd& variable_lower_bounds,
87 const Eigen::VectorXd& variable_upper_bounds,
88 const Eigen::VectorXd& center_point,
const Eigen::VectorXd& norm_weights,
89 double target_radius,
const Sharder& sharder,
double solve_tolerance);
97 const Eigen::VectorXd& dual_solution,
98 const Eigen::VectorXd& primal_gradient,
99 const Eigen::VectorXd& dual_gradient,
const double primal_weight,
100 double target_radius,
double solve_tolerance);
173 const Eigen::VectorXd& dual_solution,
PrimalDualNorm primal_dual_norm,
174 double primal_weight,
double radius,
const Eigen::VectorXd* primal_product,
175 const Eigen::VectorXd* dual_product,
176 bool use_diagonal_qp_trust_region_solver,
177 double diagonal_qp_trust_region_solver_tolerance);
193template <
typename TrustRegionProblem>
195 const int64_t
index) {
196 if (problem.Objective(
index) == 0.0) {
199 if (problem.Objective(
index) > 0.0) {
200 return problem.LowerBound(
index) - problem.CenterPoint(
index);
202 return problem.UpperBound(
index) - problem.CenterPoint(
index);
208template <
typename TrustRegionProblem>
210 const int64_t
index) {
211 if (problem.Objective(
index) == 0.0) {
212 return std::numeric_limits<double>::infinity();
214 return -problem.NormWeight(
index) *
220template <
typename TrustRegionProblem>
222 const double step_size) {
223 const double full_step =
224 problem.CenterPoint(
index) -
225 step_size * problem.Objective(
index) / problem.NormWeight(
index);
226 return std::min(std::max(full_step, problem.LowerBound(
index)),
227 problem.UpperBound(
index));
234template <
typename ArrayType,
typename ValueFunction>
235double EasyMedian(ArrayType array, ValueFunction value_function) {
236 CHECK_GT(array.size(), 0);
237 auto middle = array.begin() + (array.size() / 2);
238 absl::c_nth_element(array, middle,
239 [&](
typename ArrayType::value_type lhs,
240 typename ArrayType::value_type rhs) {
241 return value_function(lhs) < value_function(rhs);
243 return value_function(*middle);
250template <
typename TrustRegionProblem>
252 const TrustRegionProblem& problem, int64_t start_index, int64_t end_index,
253 std::vector<int64_t>& undecided_components) {
256 undecided_components.clear();
257 undecided_components.reserve(end_index - start_index);
258 double radius_coefficient = 0.0;
261 undecided_components.push_back(
index);
265 problem.NormWeight(
index);
268 return radius_coefficient;
271template <
typename TrustRegionProblem>
273 const TrustRegionProblem& problem,
const double step_size,
274 const std::vector<int64_t>& undecided_components) {
275 return absl::c_accumulate(
276 undecided_components, 0.0, [&](
double sum, int64_t
index) {
277 const double distance_at_projected_value =
279 problem.CenterPoint(
index);
280 return sum + problem.NormWeight(
index) *
290template <
typename TrustRegionProblem>
292 const TrustRegionProblem& problem,
const double step_size_threshold,
293 std::vector<int64_t>& undecided_components) {
294 double variable_radius_coefficient = 0.0;
295 for (
const int64_t
index : undecided_components) {
298 variable_radius_coefficient +=
300 problem.NormWeight(
index);
304 std::remove_if(undecided_components.begin(), undecided_components.end(),
305 [&](
const int64_t
index) {
306 return internal::CriticalStepSize(problem, index) >=
309 undecided_components.erase(result, undecided_components.end());
310 return variable_radius_coefficient;
317template <
typename TrustRegionProblem>
319 const TrustRegionProblem& problem,
const double step_size_threshold,
320 std::vector<int64_t>& undecided_components) {
321 double radius_sq = 0.0;
322 for (
const int64_t
index : undecided_components) {
324 radius_sq += problem.NormWeight(
index) *
330 std::remove_if(undecided_components.begin(), undecided_components.end(),
331 [&](
const int64_t
index) {
332 return internal::CriticalStepSize(problem, index) <=
335 undecided_components.erase(result, undecided_components.end());
351 const Eigen::VectorXd* primal_gradient,
352 const double norm_weight = 1.0)
355 primal_gradient_(*primal_gradient),
356 norm_weight_(norm_weight) {}
369 const Eigen::VectorXd& primal_solution_;
370 const Eigen::VectorXd& primal_gradient_;
371 const double norm_weight_;
387 const Eigen::VectorXd* dual_solution,
388 const Eigen::VectorXd* dual_gradient,
389 const double norm_weight = 1.0)
391 dual_solution_(*dual_solution),
392 dual_gradient_(*dual_gradient),
393 norm_weight_(norm_weight) {}
397 return -dual_gradient_[
index];
401 ? -std::numeric_limits<double>::infinity()
406 ? std::numeric_limits<double>::infinity()
414 const Eigen::VectorXd& dual_solution_;
415 const Eigen::VectorXd& dual_gradient_;
416 const double norm_weight_;
static T Square(const T x)
Returns the square of x.
double UpperBound(int64_t index) const
double LowerBound(int64_t index) const
DualTrustRegionProblem(const QuadraticProgram *qp, const Eigen::VectorXd *dual_solution, const Eigen::VectorXd *dual_gradient, const double norm_weight=1.0)
double NormWeight(int64_t index) const
double Objective(int64_t index) const
double CenterPoint(int64_t index) const
double NormWeight(int64_t index) const
PrimalTrustRegionProblem(const QuadraticProgram *qp, const Eigen::VectorXd *primal_solution, const Eigen::VectorXd *primal_gradient, const double norm_weight=1.0)
double LowerBound(int64_t index) const
double UpperBound(int64_t index) const
double Objective(int64_t index) const
double CenterPoint(int64_t index) const
double ComputeInitialUndecidedComponents(const TrustRegionProblem &problem, int64_t start_index, int64_t end_index, std::vector< int64_t > &undecided_components)
double ProjectedValue(const TrustRegionProblem &problem, const int64_t index, const double step_size)
double RemoveCriticalStepsAboveThreshold(const TrustRegionProblem &problem, const double step_size_threshold, std::vector< int64_t > &undecided_components)
double DistanceAtCriticalStepSize(const TrustRegionProblem &problem, const int64_t index)
double CriticalStepSize(const TrustRegionProblem &problem, const int64_t index)
double RemoveCriticalStepsBelowThreshold(const TrustRegionProblem &problem, const double step_size_threshold, std::vector< int64_t > &undecided_components)
double EasyMedian(ArrayType array, ValueFunction value_function)
double RadiusSquaredOfUndecidedComponents(const TrustRegionProblem &problem, const double step_size, const std::vector< int64_t > &undecided_components)
Validation utilities for solvers.proto.
TrustRegionResult SolveDiagonalTrustRegion(const VectorXd &objective_vector, const VectorXd &objective_matrix_diagonal, const VectorXd &variable_lower_bounds, const VectorXd &variable_upper_bounds, const VectorXd ¢er_point, const VectorXd &norm_weights, const double target_radius, const Sharder &sharder, const double solve_tolerance)
TrustRegionResult SolveDiagonalQpTrustRegion(const ShardedQuadraticProgram &sharded_qp, const VectorXd &primal_solution, const VectorXd &dual_solution, const VectorXd &primal_gradient, const VectorXd &dual_gradient, const double primal_weight, double target_radius, const double solve_tolerance)
@ kMaxNorm
The joint norm ||(x,y)||_PD = max{|x|_P, |y|_D}.
@ kEuclideanNorm
The joint norm (||(x,y)||_PD)^2 = (|x|_P)^2 + (|y|_D)^2.
TrustRegionResult SolveTrustRegion(const VectorXd &objective_vector, const VectorXd &variable_lower_bounds, const VectorXd &variable_upper_bounds, const VectorXd ¢er_point, const VectorXd &norm_weights, const double target_radius, const Sharder &sharder)
LocalizedLagrangianBounds ComputeLocalizedLagrangianBounds(const ShardedQuadraticProgram &sharded_qp, const VectorXd &primal_solution, const VectorXd &dual_solution, const PrimalDualNorm primal_dual_norm, const double primal_weight, const double radius, const VectorXd *primal_product, const VectorXd *dual_product, const bool use_diagonal_qp_trust_region_solver, const double diagonal_qp_trust_region_solver_tolerance)
double BoundGap(const LocalizedLagrangianBounds &bounds)
double lagrangian_value
The value of the Lagrangian function L(x, y) at the given solution.
double radius
The radius used when computing the bounds.
double lower_bound
A lower bound on the Lagrangian value, valid for the given radius.
double upper_bound
An upper bound on the Lagrangian value, valid for the given radius.
Eigen::VectorXd variable_lower_bounds
Eigen::VectorXd constraint_lower_bounds
Eigen::VectorXd variable_upper_bounds
Eigen::VectorXd constraint_upper_bounds
Eigen::VectorXd solution
The solution.
double solution_step_size
The step_size of the solution.