google / google/or-tools

PDLP declared scaled a2864 instance infeasible

Open
#4,874 0 comments 0 reactions 1 assignee Claimed by @Mizux View on GitHub
Bug Solver: PDLP
Dominant language
C++
Stars
14.1k
Forks
2.5k
Avg merge
8h 39m
Merged PRs (30d)
72

Description

Version: 9.10
Language: C++
Solver: PDLP
OS: Linux

**The issue**

PDLP is declaring a scaled version of the a2864 instance from the [Mittelmann](https://plato.asu.edu/ftp/lpopt.html) library infeasible.

The instance should be feasible. This was verified by solving the instance with Gurobi that found an optimal solution.

However, after 64 iterations PDLP declared the problem infeasible.

**Relevant files**

[mps instance](https://drive.google.com/file/d/1wYPjE3spe2YzQZ0nB0wK_Y9wClYj_OGk/view)

[decoded_solve_log.json](https://github.com/user-attachments/files/22910776/decoded_solve_log.json)

[solver-output.txt](https://github.com/user-attachments/files/22910823/solver-output.txt)

**The suspected cause**

~~Inspection of the code showed that the that the objective gradient was being included in the computation of the max_dual_ray_infeasibility,~~ based on the logs it appears the algorithm stumbling across a point where the dual infeasibility (including the objective gradient) is zero and the dual objective is 1.68 * 10^{-15}. I believe there is a numerical error causing the slightly positive dual objective since it is very small (~10^{-15}). Replacing

http://github.com/google/or-tools/blob/93dafb79a0261b5211f4eb17437aeebd7f45e543/ortools/pdlp/iteration_stats.cc#L522C35-L522C66

with

result.set_dual_ray_objective(dual_ray_objective / l_inf_dual - 1e-14);

Fixed the issue and the algorithm rapidly found the optimal solution ~2624 iterations, using the command line interface, i.e.,

```bash
"$path_to_OR_tools"/build/bin/pdlp_solve --input "$path_to_instances"/"$instance_name".mps --sol_file "$path_to_solution_files"/no-polish-"$instance_name".sol --solve_log_file "$path_to_log_files"/no-polish-"$instance_name".json --params "verbosity_level: 4 num_threads: 16 termination_criteria {detailed_optimality_criteria {eps_optimal_primal_residual_absolute: 1.0e-8 eps_optimal_primal_residual_relative: 0.0 eps_optimal_dual_residual_absolute: 1.0e-8 eps_optimal_dual_residual_relative: 0.0 eps_optimal_objective_gap_absolute: 0.0 eps_optimal_objective_gap_relative: 1.0e-2} eps_primal_infeasible: 1.0e-9 eps_dual_infeasible: 1.0e-9 optimality_norm: OPTIMALITY_NORM_L_INF} use_feasibility_polishing: false handle_some_primal_gradients_on_finite_bounds_as_residuals: false"
```

**Other relevant material**

Documentation on infeasibility certificates for PDLP
https://developers.google.com/optimization/lp/pdlp_math#infeasibility_identification

**Comment on previous suspected cause**

Initially, I though that the primal infeasibility certificate was not being computed with the homogenous residuals but actually it is just being computed in a slightly confusing way (and differently from the primal certificate). In particular,

https://github.com/google/or-tools/blob/93dafb79a0261b5211f4eb17437aeebd7f45e543/ortools/pdlp/iteration_stats.cc#L505-L528

shows that the "scaled_primal_gradient" is being computed with the PrimalGradientFromObjectiveProduct function with the option use_zero_primal_objective=true. Thus this is really the scaled_homogenous_primal_gradient"

Dual infeasibility certificate computes the homogenous residuals through an option in the PrimalResidualNorms function:

https://github.com/google/or-tools/blob/93dafb79a0261b5211f4eb17437aeebd7f45e543/ortools/pdlp/iteration_stats.cc#L66-L70

https://github.com/google/or-tools/blob/93dafb79a0261b5211f4eb17437aeebd7f45e543/ortools/pdlp/iteration_stats.cc#L530-L536

I would suggest inside the ComputeInfeasibilityInformation function renaming scaled_primal_gradient to scaled_homogeneous_primal_gradient, dual_residuals to homogeneous_dual_residuals, and primal_residuals to homogeneous_primal_residuals to improve readability

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.