Speed up Expr __add__ and __iadd__#1205
Conversation
Refactor Expr.__add__ and __iadd__ to centralize term merging in a new C helper _to_dict. _to_dict iterates other.terms with PyDict_Next, skips zero coefficients, and either copies or mutates the target dict depending on the copy flag. __add__ now handles numeric additions first and uses _to_dict(copy=True) for Expr+Expr; __iadd__ uses _to_dict(copy=False) to perform in-place merges and returns self. GenExpr and numpy-array cases are preserved. Error messages were slightly adjusted and numeric values are cast to double for correctness and performance.
Add unit tests to verify Expr + Expr and Expr += Expr behavior. test_Expr_add_Expr constructs -x+1 and y-1, checks their string representations and the combined result (including a 0.0 constant term). test_Expr_iadd_Expr verifies in-place addition mutates the left expression, preserves the right expression, and checks their string representations.
There was a problem hiding this comment.
Pull request overview
This PR optimizes Expr.__add__ / Expr.__iadd__ by moving term merging into a C-level helper (_to_dict) that iterates dictionaries via PyDict_Next, aiming to reduce Python-level overhead in expression addition.
Changes:
- Reworked
Expr.__add__andExpr.__iadd__to use a new C-level merge helper forExpr + Expr/Expr += Expr. - Added unit tests covering
Expr + ExprandExpr += Exprbasic behavior. - Documented the optimization in the changelog.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/pyscipopt/expr.pxi |
Implements faster term merging for addition/in-place addition via _to_dict and updates the dunder methods to use it. |
tests/test_expr.py |
Adds tests validating string representations after Expr + Expr and Expr += Expr. |
CHANGELOG.md |
Notes the new optimization in the Unreleased section. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1205 +/- ##
==========================================
+ Coverage 57.17% 57.50% +0.33%
==========================================
Files 26 26
Lines 5674 5728 +54
==========================================
+ Hits 3244 3294 +50
- Misses 2430 2434 +4 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
Hey @Zeroto521 , I'll take a look soon. In the meantime, how would you feel about taking a look at qpsolvers/qpsolvers#347? It's about adding SCIP support to an unified QP-solver. I thought about you because you're both into numpy and the matrix API, so it might be a good fit. By the way, absolutely 0.0000000% pressure to do anything at all, of course!! |
Okay, I'll check that out later. |
This pr is 1.75x faster than the master branch.