20#include "absl/log/check.h"
21#include "absl/status/status.h"
22#include "absl/status/statusor.h"
23#include "absl/strings/str_cat.h"
32absl::StatusOr<GlpkRay> ComputePrimalRay(glp_prob*
const problem,
33 const int non_basic_variable) {
34 const int num_cstrs = glp_get_num_rows(problem);
37 const int non_basic_variable_status =
41 CHECK_NE(non_basic_variable_status, GLP_BS);
99 problem, num_cstrs, non_basic_variable);
100 const double t = (glp_get_obj_dir(problem) == GLP_MAX ? 1.0 : -1.0) *
101 (reduced_cost >= 0 ? 1.0 : -1.0);
105 switch (non_basic_variable_status) {
108 return absl::InternalError(
109 "a non-basic variable at its lower-bound is reported as cause of "
110 "unboundness but the reduced cost's sign indicates that the solver "
111 "considered making it smaller");
116 return absl::InternalError(
117 "a non-basic variable at its upper-bound is reported as cause of "
118 "unboundness but the reduced cost's sign indicates that the solver "
119 "considered making it bigger");
125 return absl::InternalError(absl::StrCat(
127 " reported as cause of unboundness"));
136 ray_non_zeros.emplace_back(non_basic_variable, t);
144 std::vector<int> inds(num_cstrs + 1);
145 std::vector<double> vals(num_cstrs + 1);
146 const int non_zeros =
147 glp_eval_tab_col(problem, non_basic_variable, inds.data(), vals.data());
148 for (
int i = 1;
i <= non_zeros; ++
i) {
149 ray_non_zeros.emplace_back(inds[i], t * vals[i]);
155absl::StatusOr<GlpkRay> ComputeDualRay(glp_prob*
const problem,
156 const int basic_variable) {
157 const int num_cstrs = glp_get_num_rows(problem);
300 problem, num_cstrs, basic_variable);
303 problem, num_cstrs, basic_variable);
305 problem, num_cstrs, basic_variable);
306 if (!(primal_value > upper_bound || primal_value < lower_bound)) {
307 return absl::InternalError(
308 "dual ray computation failed: GLPK identified a basic variable as the "
309 "source of unboundness but its primal value is within its bounds");
316 const double t = (glp_get_obj_dir(problem) == GLP_MAX ? 1.0 : -1.0) *
317 (primal_value > upper_bound ? 1.0 : -1.0);
325 ray_non_zeros.emplace_back(basic_variable, t);
334 const int num_structural_vars = glp_get_num_cols(problem);
335 std::vector<int> inds(num_structural_vars + 1);
336 std::vector<double> vals(num_structural_vars + 1);
337 const int non_zeros =
338 glp_eval_tab_row(problem, basic_variable, inds.data(), vals.data());
339 for (
int i = 1;
i <= non_zeros; ++
i) {
340 ray_non_zeros.emplace_back(inds[i], -t * vals[i]);
352 glp_prob*
const problem) {
353 const int unbound_ray = glp_get_unbnd_ray(problem);
354 if (unbound_ray <= 0) {
356 DCHECK_EQ(unbound_ray, 0);
363 if (!glp_bf_exists(problem)) {
364 const int factorization_rc = glp_factorize(problem);
365 if (factorization_rc != 0) {
374 const bool is_dual_ray =
376 glp_get_num_rows(problem),
377 unbound_ray) == GLP_BS;
379 (is_dual_ray ? ComputeDualRay(problem, unbound_ray)
380 : ComputePrimalRay(problem, unbound_ray)));
#define ASSIGN_OR_RETURN(lhs, rexpr)
absl::StatusOr< std::optional< GlpkRay > > GlpkComputeUnboundRay(glp_prob *const problem)
double ComputeFormVarPrimalValue(glp_prob *const problem, const int num_cstrs, const int k)
int ComputeFormVarStatus(glp_prob *const problem, const int num_cstrs, const int k)
std::string BasisStatusString(const int stat)
double ComputeFormVarReducedCost(glp_prob *const problem, const int num_cstrs, const int k)
double ComputeFormVarLowerBound(glp_prob *const problem, const int num_cstrs, const int k)
double ComputeFormVarUpperBound(glp_prob *const problem, const int num_cstrs, const int k)
std::string ReturnCodeString(const int rc)
StatusBuilder InternalErrorBuilder()
GlpkRay(GlpkRayType type, SparseVector non_zero_components)
std::vector< std::pair< int, double > > SparseVector
SparseVector non_zero_components