Skip to content

Add sparse matrix and scaling tests#486

Open
ewu63 wants to merge 10 commits into
mdolab:mainfrom
ewu63:improve-tests
Open

Add sparse matrix and scaling tests#486
ewu63 wants to merge 10 commits into
mdolab:mainfrom
ewu63:improve-tests

Conversation

@ewu63

@ewu63 ewu63 commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Purpose

Add a few tests, partially addresses #256.

Expected time until merged

A few days

Type of change

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (non-backwards-compatible fix or feature)
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no API changes)
  • Documentation update
  • Maintenance update
  • Other (please describe)

Testing

Checklist

  • I have run ruff check and ruff format to make sure the Python code adheres to PEP-8 and is consistently formatted
  • I have formatted the Fortran code with fprettify or C/C++ code with clang-format as applicable
  • I have run unit and regression tests which pass locally with my changes
  • I have added new tests that prove my fix is effective or that my feature works
  • I have added necessary documentation

@ewu63 ewu63 requested a review from marcomangano as a code owner June 16, 2026 04:49
@codecov

codecov Bot commented Jun 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 78 lines in your changes missing coverage. Please review.
✅ Project coverage is 54.22%. Comparing base (20cfa02) to head (c294b87).

Files with missing lines Patch % Lines
tests/test_optProb.py 0.00% 78 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main     #486       +/-   ##
===========================================
- Coverage   82.99%   54.22%   -28.78%     
===========================================
  Files           1        1               
  Lines         147      225       +78     
===========================================
  Hits          122      122               
- Misses         25      103       +78     

☔ 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.

@marcomangano marcomangano 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 a lot for doing this! Just a few very minor points below

Comment thread tests/test_gradient.py
assert_sens_matches_analytic(funcsSens, atol=atol)

# test that we get real derivs for cs
if sensType == "cs":

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 is interesting, I would have thought that the assert_allclose would have caught a type mismatch. Would it make sense to move this before the call to assert_sens_matches_analytic?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

strict=True would assert dtype also but defaults to False. Typically we want it to broadcast and ignore shape but not dtype.

Comment thread tests/test_gradient.py
return funcs, False


def build_optProb(objfun=objfunc, xScale=1.0, conScale=1.0):

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.

Minor curiosity: Is the mismatch between arg and function name intentional? Naming best practice?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

A little bit? objfunc is what we use to call functions, but Optimization object's field is objfun. I can harmonize this.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Oh no I remember now, I didn't want to shadow a function with a variable with the same name.

Comment thread tests/test_gradient.py
for dvGroup in ANALYTIC[funcKey]:
self.assertFalse(np.iscomplexobj(funcsSens[funcKey][dvGroup]))

def test_failed_eval(self):

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.

For sake of future maintainability, do you mind adding a couple of lines of comment to describe these last two tests?
The first one could be "Testing that failed flags from objfunc are caught by the Gradient class", and TBH I am confused about what we are testing in the last one. Is that to ensure that the original gradient object is not scaled, similar to l.350 in test_scaling.py?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes the difference here is using CS, rather than analytic derivatives. This is more integration test while unit tests for the mapping funcs are below.

Comment thread tests/test_optProb.py
jac = convertToCSR(dense)

# _mapConJactoOpt works in place: J_opt = diag(conScale) . J . diag(invXScale)
self.optProb._mapConJactoOpt(jac)

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 is well outside the scope of the PR, but I wonder what is the rationale for _mapObjGradtoOpt returns an object (operating on a copy of the original gobj), while _mapConJactoOpt?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It's a bit of an implementation detail. _mapObjGradtoOpt operates on a numpy array directly, while _mapConJactoOpt is from older code that also operates on sparse matrices, and for efficiency it mutates in place. This is something we should probably unify, and i think some of the type hints here are wrong.

Comment thread tests/test_utils.py
def test_from_csc(self):
coo = convertToCOO(_CSC)
rows, cols, data = coo["coo"]
assert_array_equal(rows, [0, 2, 1, 0, 2])

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.

These are hardcoded and different from _COO because the "reading order" changes based on the initial format, right? Could you add a comment line similarly to what you did in the following tests?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addedd

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants