Skip to content

Highs::passModel() and Highs::passHessian() now return HighsStatus::kWarning if any of the HighsLp vectors or HighsHessian::start_ have greater size than required by HighsLp::num_col_ and HighsLp::num_row_ - #3372

Open
jajhall wants to merge 44 commits into
latestfrom
fix-3366

Conversation

@jajhall

@jajhall jajhall commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Description

Observing an assert when experimenting with #3364, I decided that trimming HighsLp vectors that are too large (and logging) would be good for users and developers.

lpDimensionsOk and its parameter list have been modified to be consistent with assessHessianDimensions and "legal" used to distinguish them from "trim", as in trimHessianDimension

NB @fwesselm I spotted that if num_col = iCol then lp_.col_names_[num_col] = std::move(lp_.col_names_[iCol]); leads to lp_.col_names_[num_col] being an empty string.

Checklist

  • I have read the contributing guidelines
  • This PR targets the latest branch
  • Tests are passing
  • Documentation was updated where relevant
  • This PR is not primarily AI-generated (per the AI contributions policy in CONTRIBUTING.md)

Related issue

Closes #3366

Julian Hall added 5 commits October 7, 2026 12:04
…Warning if any of the HighsLp vectors or HighsHessian::start_ have greater size than required by HighsLp::num_col_ and HighsLp::num_row_. They are resized, with logging when this occurs
@codecov

codecov Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.58738% with 33 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.19%. Comparing base (6af93b8) to head (b98344c).
⚠️ Report is 21 commits behind head on latest.

Files with missing lines Patch % Lines
highs/lp_data/HighsLp.cpp 90.39% 17 Missing ⚠️
highs/lp_data/Highs.cpp 96.40% 6 Missing ⚠️
highs/util/HighsMatrixUtils.cpp 93.75% 6 Missing ⚠️
check/TestLpValidation.cpp 99.06% 2 Missing ⚠️
highs/model/HighsHessian.h 50.00% 1 Missing ⚠️
highs/model/HighsModel.cpp 93.75% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           latest    #3372      +/-   ##
==========================================
+ Coverage   75.02%   75.19%   +0.17%     
==========================================
  Files         460      460              
  Lines      111862   112441     +579     
  Branches    17746    17772      +26     
==========================================
+ Hits        83921    84548     +627     
+ Misses      27659    27611      -48     
  Partials      282      282              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@fwesselm fwesselm left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @jajhall. Just a couple of comments from me.

Comment thread highs/lp_data/HighsLpUtils.cpp Outdated
Comment thread highs/lp_data/HighsLpUtils.cpp Outdated
Comment thread highs/model/HighsHessianUtils.cpp Outdated
Comment thread highs/model/HighsHessianUtils.cpp Outdated
Comment thread highs/lp_data/HighsLpUtils.cpp
Comment thread check/TestLpValidation.cpp Outdated
Comment thread check/TestLpValidation.cpp Outdated
Comment thread highs/lp_data/HighsLp.h Outdated
Comment thread highs/lp_data/HighsLpUtils.cpp Outdated
Comment thread highs/model/HighsHessianUtils.cpp Outdated
Comment thread highs/util/HighsMatrixUtils.cpp Outdated
Comment thread highs/util/HighsMatrixUtils.cpp Outdated
Comment thread highs/util/HighsMatrixUtils.cpp Outdated
Comment thread highs/util/HighsMatrixUtils.cpp Outdated
Comment thread highs/util/HighsMatrixUtils.cpp Outdated
Comment thread highs/util/HighsMatrixUtils.cpp Outdated
Comment thread check/TestLpValidation.cpp Outdated
Comment thread highs/lp_data/HighsLp.h
Comment thread highs/util/HighsMatrixUtils.cpp
Comment thread highs/util/HighsMatrixUtils.cpp Outdated
Julian Hall added 2 commits October 12, 2026 17:06
…ned matrix, and added some asserts to check the partitioned matrix in primal/dual simplex
@jajhall

jajhall commented Oct 12, 2026

Copy link
Copy Markdown
Member Author

Spotted quite a few methods in the Highs class that, if called first after creating the Highs instance would yield logging before highsLogHeader is called. These methods are not logical to call before the typical "first method", but the changes keep the code consistent. This means that many more methods in the Highs class are not const - since calling highsLogHeader changes the data member used to record whether it's been called.

highsLogHeader is now called from the more generic Highs::onFirstCall that can be used to do other stuff in due course

@fwesselm

Copy link
Copy Markdown
Collaborator

Just a thought, could mutable be used to keep these methods const?

mutable bool made_first_call_ = false;
mutable bool written_log_header_ = false;

The only question would be if any of the const methods could be called concurrently by different threads.

@jajhall

jajhall commented Oct 13, 2026

Copy link
Copy Markdown
Member Author

Just a thought, could mutable be used to keep these methods const?

mutable bool made_first_call_ = false;
mutable bool written_log_header_ = false;

The only question would be if any of the const methods could be called concurrently by different threads.

If it's just a question of writing the log header - as it is currently - then I think I'm correct in saying that the worst that could happen is that it gets written twice. This is not a problem, as anyone with multiple threads using the same HiGHS instance will either get unreadable logging, or will be sending logging to different files for each thread. In the latter case, having the header at the top of the file (or not) isn't a bad thing, even if they are parsing the log file.

Am I right in thinking that the advantage of marking a method as const is that it can be called concurrently by different threads (because data members shared between threads can't be changed)? If so, then I can see the value in just using onFirstCall to write the logging header and making written_log_header_ mutable. This will mean that many methods can become const again. The performance gain won't be much as, obviously, the major computation occurs in methods that can't be const.

@fwesselm fwesselm left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jajhall, just one more question. Would it be possible to have a

mutable std::once_flag log_header_flag_;

member in Highs.h:

void Highs::logHeader() const {
    // Defer logging the header until output is switched on
    if (!*options_.log_options.output_flag) return;
    std::call_once(log_header_flag_, [this]() {
      highsLogHeader(options_.log_options, options_.log_githash);
    });
  }

This would allow for making the methods const again and every Highs instance would have its own flag.

Comment thread highs/lp_data/Highs.cpp
void Highs::logHeader(const bool log_header) {
if (!options_.output_flag) return;
// if (!*options_.log_options.output_flag) return;
static std::once_flag flag;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I am not an expert in this, but the static std::once_flag is shared by all Highs instances, so the header is now only logged once per process: if a process creates two Highs instances, only the first one logs the header.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'm happy with this. It means that a lot of methods are const again, and we don't have to argue that the mutable value doesn't really compromise thread safety.

@@ -3181,6 +3181,8 @@ HighsStatus Highs::computeIllConditioning(
Highs conditioning;
const bool dev_conditioning = false;
conditioning.setOptionValue("output_flag", false); // dev_conditioning);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If output_flag is false, logHeader(false) does immediately return, correct? Is the parameter log_header used only here?

if (!options_.output_flag) return;

Comment thread highs/lp_data/HighsLp.cpp
return status;
}

HighsStatus HighsLp::assess(const HighsOptions& options) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since matrix dimensions may not have been set, it may be good to call this->setMatrixDimensions() here?

}

HighsStatus HighsSparseMatrix::assess(const HighsOptions& options) {
const bool sum_duplicates = false;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe return a warning/error if there are no vectors but starting points are set? Maybe there is another case that could be handled with a warning...

if (this->numVec() == 0 && this->start_.size() > 1) ...

lp.a_matrix_.value_.resize(lp_num_nz);

// Matrix should have been trimmed in lp.a_matrix_.assess
assert(lp.a_matrix_.trimDimensions(log_options) == HighsStatus::kOk);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would only trim if assertions are enabled (debug mode)?

@fwesselm

Copy link
Copy Markdown
Collaborator

@jajhall, I merged with latest (there were conflicts)

@jajhall

jajhall commented Oct 14, 2026

Copy link
Copy Markdown
Member Author

Sorry @fwesselm, this is getting horrible to review. Don't look at this yet, as I'll write some commentary about the reasoning for the changes

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants