14#ifndef PDLP_TRUST_REGION_H_
15#define PDLP_TRUST_REGION_H_
24#include "absl/algorithm/container.h"
89 double target_radius,
const Sharder& sharder,
double solve_tolerance);
96 const Eigen::VectorXd& primal_solution,
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);
167 const Eigen::VectorXd& primal_solution,
168 const Eigen::VectorXd& dual_solution,
PrimalDualNorm primal_dual_norm,
169 double primal_weight,
double radius,
const Eigen::VectorXd* primal_product,
170 const Eigen::VectorXd* dual_product,
171 bool use_diagonal_qp_trust_region_solver,
172 double diagonal_qp_trust_region_solver_tolerance);
188template <
typename TrustRegionProblem>
190 const int64_t
index) {
191 if (problem.Objective(
index) == 0.0) {
194 if (problem.Objective(
index) > 0.0) {
195 return problem.LowerBound(
index) - problem.CenterPoint(
index);
197 return problem.UpperBound(
index) - problem.CenterPoint(
index);
203template <
typename TrustRegionProblem>
205 const int64_t
index) {
206 if (problem.Objective(
index) == 0.0) {
207 return std::numeric_limits<double>::infinity();
209 return -problem.NormWeight(
index) *
215template <
typename TrustRegionProblem>
217 const double step_size) {
218 const double full_step =
219 problem.CenterPoint(
index) -
220 step_size * problem.Objective(
index) / problem.NormWeight(
index);
222 problem.UpperBound(
index));
229template <
typename ArrayType,
typename ValueFunction>
230double EasyMedian(ArrayType array, ValueFunction value_function) {
232 auto middle = array.begin() + (array.size() / 2);
233 absl::c_nth_element(array, middle,
234 [&](
typename ArrayType::value_type lhs,
235 typename ArrayType::value_type rhs) {
236 return value_function(lhs) < value_function(rhs);
238 return value_function(*middle);
245template <
typename TrustRegionProblem>
247 const TrustRegionProblem& problem, int64_t start_index, int64_t end_index,
248 std::vector<int64_t>& undecided_components) {
251 undecided_components.clear();
252 undecided_components.reserve(end_index - start_index);
253 double radius_coefficient = 0.0;
256 undecided_components.push_back(
index);
260 problem.NormWeight(
index);
263 return radius_coefficient;
266template <
typename TrustRegionProblem>
268 const TrustRegionProblem& problem,
const double step_size,
269 const std::vector<int64_t>& undecided_components) {
270 return absl::c_accumulate(
271 undecided_components, 0.0, [&](
double sum, int64_t
index) {
272 const double distance_at_projected_value =
274 problem.CenterPoint(
index);
275 return sum + problem.NormWeight(
index) *
285template <
typename TrustRegionProblem>
287 const TrustRegionProblem& problem,
const double step_size_threshold,
288 std::vector<int64_t>& undecided_components) {
289 double variable_radius_coefficient = 0.0;
290 for (
const int64_t
index : undecided_components) {
293 variable_radius_coefficient +=
295 problem.NormWeight(
index);
299 std::remove_if(undecided_components.begin(), undecided_components.end(),
300 [&](
const int64_t
index) {
301 return internal::CriticalStepSize(problem, index) >=
304 undecided_components.erase(result, undecided_components.end());
305 return variable_radius_coefficient;
312template <
typename TrustRegionProblem>
314 const TrustRegionProblem& problem,
const double step_size_threshold,
315 std::vector<int64_t>& undecided_components) {
316 double radius_sq = 0.0;
317 for (
const int64_t
index : undecided_components) {
319 radius_sq += problem.NormWeight(
index) *
325 std::remove_if(undecided_components.begin(), undecided_components.end(),
326 [&](
const int64_t
index) {
327 return internal::CriticalStepSize(problem, index) <=
330 undecided_components.erase(result, undecided_components.end());
345 const Eigen::VectorXd* primal_solution,
346 const Eigen::VectorXd* primal_gradient,
347 const double norm_weight = 1.0)
349 primal_solution_(*primal_solution),
350 primal_gradient_(*primal_gradient),
351 norm_weight_(norm_weight) {}
364 const Eigen::VectorXd& primal_solution_;
365 const Eigen::VectorXd& primal_gradient_;
366 const double norm_weight_;
382 const Eigen::VectorXd* dual_solution,
383 const Eigen::VectorXd* dual_gradient,
384 const double norm_weight = 1.0)
386 dual_solution_(*dual_solution),
387 dual_gradient_(*dual_gradient),
388 norm_weight_(norm_weight) {}
392 return -dual_gradient_[
index];
396 ? -std::numeric_limits<double>::infinity()
401 ? std::numeric_limits<double>::infinity()
409 const Eigen::VectorXd& dual_solution_;
410 const Eigen::VectorXd& dual_gradient_;
411 const double norm_weight_;
#define CHECK_GT(val1, val2)
static T Square(const T x)
double Objective(int64_t index) const
double UpperBound(int64_t index) const
double LowerBound(int64_t index) const
double CenterPoint(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 UpperBound(int64_t index) const
double LowerBound(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 CenterPoint(int64_t index) const
double NormWeight(int64_t index) const
SharedBoundsManager * bounds
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)
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)
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)
Eigen::VectorXd variable_upper_bounds
Eigen::VectorXd variable_lower_bounds
Eigen::VectorXd constraint_lower_bounds
Eigen::VectorXd constraint_upper_bounds
double solution_step_size
VectorXd variable_lower_bounds
VectorXd variable_upper_bounds
VectorXd objective_vector
VectorXd objective_matrix_diagonal