Skip to content

Commit 81a0dc0

Browse files
authored
Merge branch 'master' into Term/ptr
2 parents ff82bde + 8b1d1f5 commit 81a0dc0

3 files changed

Lines changed: 15 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
- Removed `Py_INCREF`/`Py_DECREF` on `Model` in `catchEvent`/`dropEvent` that caused memory leak for imbalanced usage
99
- Used `getIndex()` instead of `ptr()` for sorting nonlinear expression terms to avoid nondeterministic behavior
1010
### Changed
11+
- Speed up `constant * Expr` via C-level API
1112
- Speed up `Term.__eq__` via the C-level API
1213
### Removed
13-
- Removed `Term.ptrtuple` to optimize `Term` memory usage
1414
- Removed outdated warning about Make build system incompatibility
15+
- Removed `Term.ptrtuple` to optimize `Term` memory usage
1516

1617
## 6.1.0 - 2026.01.31
1718
### Added

src/pyscipopt/expr.pxi

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -303,22 +303,24 @@ cdef class Expr:
303303
cdef PyObject *v2_ptr = NULL
304304
cdef PyObject *old_v_ptr = NULL
305305
cdef Term child
306-
cdef double prod_v
306+
cdef double coef
307307

308308
if _is_number(other):
309-
f = float(other)
310-
return Expr({v:f*c for v,c in self.terms.items()})
309+
coef = float(other)
310+
while PyDict_Next(self.terms, &pos1, &k1_ptr, &v1_ptr):
311+
res[<Term>k1_ptr] = <double>(<object>v1_ptr) * coef
312+
return Expr(res)
311313

312314
elif isinstance(other, Expr):
313315
while PyDict_Next(self.terms, &pos1, &k1_ptr, &v1_ptr):
314316
pos2 = <Py_ssize_t>0
315317
while PyDict_Next(other.terms, &pos2, &k2_ptr, &v2_ptr):
316318
child = (<Term>k1_ptr) * (<Term>k2_ptr)
317-
prod_v = (<double>(<object>v1_ptr)) * (<double>(<object>v2_ptr))
319+
coef = (<double>(<object>v1_ptr)) * (<double>(<object>v2_ptr))
318320
if (old_v_ptr := PyDict_GetItem(res, child)) != NULL:
319-
res[child] = <double>(<object>old_v_ptr) + prod_v
321+
res[child] = <double>(<object>old_v_ptr) + coef
320322
else:
321-
res[child] = prod_v
323+
res[child] = coef
322324
return Expr(res)
323325

324326
elif isinstance(other, GenExpr):

tests/test_expr.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,11 @@ def test_mul():
224224
x = m.addVar(name="x")
225225
y = m.addVar(name="y")
226226

227+
# test Expr * number
228+
assert str((x + y) * 2.0) == "Expr({Term(x): 2.0, Term(y): 2.0})"
229+
assert str(2.0 * (x + y)) == "Expr({Term(x): 2.0, Term(y): 2.0})"
230+
231+
# test Expr * Expr
227232
assert str(Expr({CONST: 1.0}) * x) == "Expr({Term(x): 1.0})"
228233
assert str(y * Expr({CONST: -1.0})) == "Expr({Term(y): -1.0})"
229234
assert str((x - x) * y) == "Expr({Term(x, y): 0.0})"

0 commit comments

Comments
 (0)