diff --git a/extern/filereaderlp/reader.cpp b/extern/filereaderlp/reader.cpp index 9f86079f10..abe56759f8 100644 --- a/extern/filereaderlp/reader.cpp +++ b/extern/filereaderlp/reader.cpp @@ -828,7 +828,7 @@ void Reader::splittokens() { // Current section is non-trivial, so mark its end, using the // value of currentsection to indicate that there is no open // section - assert(debug_open_section); + lpassert(debug_open_section); sectiontokens[currentsection].second = it; debug_open_section = false; currentsection = LpSectionKeyword::NONE; @@ -846,12 +846,12 @@ void Reader::splittokens() { // the current section if (currentsection != LpSectionKeyword::NONE && currentsection != next->keyword) { - assert(debug_open_section); + lpassert(debug_open_section); sectiontokens[currentsection].second = it; debug_open_section = false; } currentsection = LpSectionKeyword::NONE; - assert(!debug_open_section); + lpassert(!debug_open_section); continue; } // Next section is non-empty @@ -862,16 +862,16 @@ void Reader::splittokens() { lpassert(sectiontokens.count(currentsection) == 0); // Remember the beginning of the new section: its the token // following the current one - assert(!debug_open_section); + lpassert(!debug_open_section); sectiontokens[currentsection].first = next; debug_open_section = true; } // Always ends with either an open section or a section type of // LpSectionKeyword::NONE - assert(debug_open_section != (currentsection == LpSectionKeyword::NONE)); + lpassert(debug_open_section != (currentsection == LpSectionKeyword::NONE)); } // Check that the last section has been closed - assert(currentsection == LpSectionKeyword::NONE); + lpassert(currentsection == LpSectionKeyword::NONE); } void Reader::processtokens() { diff --git a/src/lp_data/Highs.cpp b/src/lp_data/Highs.cpp index f6f732c788..3acf20f5a2 100644 --- a/src/lp_data/Highs.cpp +++ b/src/lp_data/Highs.cpp @@ -3150,17 +3150,18 @@ HighsStatus Highs::callSolveQp() { return_status = interpretCallStatus(options_.log_options, call_status, return_status, "QpSolver"); if (return_status == HighsStatus::kError) return return_status; - model_status_ = runtime.status == ProblemStatus::OPTIMAL + model_status_ = runtime.status == QpModelStatus::OPTIMAL ? HighsModelStatus::kOptimal - : runtime.status == ProblemStatus::UNBOUNDED + : runtime.status == QpModelStatus::UNBOUNDED ? HighsModelStatus::kUnbounded - : runtime.status == ProblemStatus::INFEASIBLE + : runtime.status == QpModelStatus::INFEASIBLE ? HighsModelStatus::kInfeasible - : runtime.status == ProblemStatus::ITERATIONLIMIT + : runtime.status == QpModelStatus::ITERATIONLIMIT ? HighsModelStatus::kIterationLimit - : runtime.status == ProblemStatus::TIMELIMIT + : runtime.status == QpModelStatus::TIMELIMIT ? HighsModelStatus::kTimeLimit : HighsModelStatus::kNotset; + // extract variable values solution_.col_value.resize(lp.num_col_); solution_.col_dual.resize(lp.num_col_); const double objective_multiplier = lp.sense_ == ObjSense::kMinimize ? 1 : -1; @@ -3169,6 +3170,7 @@ HighsStatus Highs::callSolveQp() { solution_.col_dual[iCol] = objective_multiplier * runtime.dualvar.value[iCol]; } + // extract constraint activity solution_.row_value.resize(lp.num_row_); solution_.row_dual.resize(lp.num_row_); // Negate the vector and Hessian @@ -3179,6 +3181,35 @@ HighsStatus Highs::callSolveQp() { } solution_.value_valid = true; solution_.dual_valid = true; + + // extract basis status + basis_.col_status.resize(lp.num_col_); + basis_.row_status.resize(lp.num_row_); + + for (HighsInt i = 0; i < lp.num_col_; i++) { + if (runtime.status_var[i] == BasisStatus::ActiveAtLower) { + basis_.col_status[i] = HighsBasisStatus::kLower; + } else if (runtime.status_var[i] == BasisStatus::ActiveAtUpper) { + basis_.col_status[i] = HighsBasisStatus::kUpper; + } else if (runtime.status_var[i] == BasisStatus::InactiveInBasis) { + basis_.col_status[i] = HighsBasisStatus::kNonbasic; + } else { + basis_.col_status[i] = HighsBasisStatus::kBasic; + } + } + + for (HighsInt i = 0; i < lp.num_row_; i++) { + if (runtime.status_con[i] == BasisStatus::ActiveAtLower) { + basis_.row_status[i] = HighsBasisStatus::kLower; + } else if (runtime.status_con[i] == BasisStatus::ActiveAtUpper) { + basis_.row_status[i] = HighsBasisStatus::kUpper; + } else if (runtime.status_con[i] == BasisStatus::InactiveInBasis) { + basis_.row_status[i] = HighsBasisStatus::kNonbasic; + } else { + basis_.row_status[i] = HighsBasisStatus::kBasic; + } + } + // Get the objective and any KKT failures info_.objective_function_value = model_.objectiveValue(solution_.col_value); getKktFailures(options_, model_, solution_, basis_, info_); diff --git a/src/presolve/HighsPostsolveStack.cpp b/src/presolve/HighsPostsolveStack.cpp index 13ad08249d..0196514612 100644 --- a/src/presolve/HighsPostsolveStack.cpp +++ b/src/presolve/HighsPostsolveStack.cpp @@ -568,7 +568,7 @@ void HighsPostsolveStack::DuplicateRow::undo(const HighsOptions& options, void HighsPostsolveStack::DuplicateColumn::undo(const HighsOptions& options, HighsSolution& solution, HighsBasis& basis) const { - const bool debug_report = true; + const bool debug_report = false; const double mergeVal = solution.col_value[col]; auto okResidual = [&](const double x, const double y) { @@ -986,7 +986,7 @@ void HighsPostsolveStack::DuplicateColumn::undoFix( options.primal_feasibility_tolerance; std::vector& col_value = solution.col_value; const bool allow_assert = false; - const bool debug_report = true; + const bool debug_report = false; //============================================================================================= auto isInteger = [&](const double v) { diff --git a/src/qpsolver/basis.cpp b/src/qpsolver/basis.cpp index 384b962aac..ec1cabc920 100644 --- a/src/qpsolver/basis.cpp +++ b/src/qpsolver/basis.cpp @@ -4,17 +4,23 @@ #include Basis::Basis(Runtime& rt, std::vector active, - std::vector lower, std::vector inactive) + std::vector status, std::vector inactive) : runtime(rt), buffer_column_aq(rt.instance.num_var), buffer_row_ep(rt.instance.num_var) { buffer_vec2hvec.setup(rt.instance.num_var); + + for (HighsInt i=0; i= runtime.settings.iterationlimit) { - runtime.status = ProblemStatus::ITERATIONLIMIT; + runtime.status = QpModelStatus::ITERATIONLIMIT; break; } // check time limit if (runtime.timer.readRunHighsClock() >= runtime.settings.timelimit) { - runtime.status = ProblemStatus::TIMELIMIT; + runtime.status = QpModelStatus::TIMELIMIT; break; } @@ -272,7 +272,7 @@ void Quass::solve(const Vector& x0, const Vector& ra, Basis& b0) { if (atfsep) { HighsInt minidx = pricing->price(runtime.primal, gradient.getGradient()); if (minidx == -1) { - runtime.status = ProblemStatus::OPTIMAL; + runtime.status = QpModelStatus::OPTIMAL; break; } @@ -295,7 +295,7 @@ void Quass::solve(const Vector& x0, const Vector& ra, Basis& b0) { if (!zero_curvature_direction) { status = factor.expand(buffer_yp, buffer_gyp, buffer_l, buffer_m); if (status != QpSolverStatus::OK) { - runtime.status = ProblemStatus::INDETERMINED; + runtime.status = QpModelStatus::INDETERMINED; return; } } @@ -317,7 +317,7 @@ void Quass::solve(const Vector& x0, const Vector& ra, Basis& b0) { status = reduce(runtime, basis, stepres.limitingconstraint, buffer_d, maxabsd, constrainttodrop); if (status != QpSolverStatus::OK) { - runtime.status = ProblemStatus::INDETERMINED; + runtime.status = QpModelStatus::INDETERMINED; return; } if (!zero_curvature_direction) { @@ -334,7 +334,7 @@ void Quass::solve(const Vector& x0, const Vector& ra, Basis& b0) { : BasisStatus::ActiveAtUpper, constrainttodrop, pricing.get()); if (status != QpSolverStatus::OK) { - runtime.status = ProblemStatus::INDETERMINED; + runtime.status = QpModelStatus::INDETERMINED; return; } if (basis.getnumactive() != runtime.instance.num_var) { @@ -344,7 +344,7 @@ void Quass::solve(const Vector& x0, const Vector& ra, Basis& b0) { if (stepres.alpha == std::numeric_limits::infinity()) { // unbounded - runtime.status = ProblemStatus::UNBOUNDED; + runtime.status = QpModelStatus::UNBOUNDED; return; } atfsep = false; @@ -377,6 +377,15 @@ void Quass::solve(const Vector& x0, const Vector& ra, Basis& b0) { } } + // extract basis status + for (HighsInt i=0; i status_var; + std::vector status_con; Runtime(Instance& inst, HighsTimer& ht) : instance(inst), @@ -40,7 +34,9 @@ struct Runtime { primal(Vector(instance.num_var)), rowactivity(Vector(instance.num_con)), dualvar(instance.num_var), - dualcon(instance.num_con) {} + dualcon(instance.num_con), + status_var(instance.num_var), + status_con(instance.num_con) {} }; #endif