Skip to content

Commit 4a7def6

Browse files
committed
test and changelog
1 parent 2a8dc58 commit 4a7def6

3 files changed

Lines changed: 53 additions & 16 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
## Unreleased
44
### Added
55
### Fixed
6-
- all fundamental callbacks now raise an error if not implemented
6+
- getTermsQuadratic() now correctly returns all linear terms
77
### Changed
88
### Removed
99

src/pyscipopt/scip.pxi

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8090,18 +8090,6 @@ cdef class Model:
80908090
"""
80918091
Retrieve bilinear, quadratic, and linear terms of a quadratic constraint.
80928092
8093-
According to SCIP's quadratic expression interface, a quadratic
8094-
expression is represented as
8095-
8096-
$x^T Q x + b^T x + c^T y + d$,
8097-
8098-
where variables in $x$ appear in the quadratic part (matrix $Q$) and
8099-
variables in $y$ appear only linearly. The coefficients for $c^T y$
8100-
(purely linear part) are returned as ``linterms``. For variables that
8101-
appear in the quadratic part (the $x$ variables), their associated
8102-
linear coefficients $b$ are stored together with the quadratic term
8103-
and are returned as part of ``quadterms``.
8104-
81058093
Parameters
81068094
----------
81078095
cons : Constraint
@@ -8117,9 +8105,8 @@ cdef class Model:
81178105
coefficient ``lincoef`` associated with the same variable when it
81188106
also appears linearly in the quadratic part.
81198107
linterms : list of tuple
8120-
Pairs ``(var, coef)`` for variables that appear only in the pure
8121-
linear part (the ``c^T y`` term above), i.e., variables that do
8122-
not participate in any quadratic or bilinear term.
8108+
Pairs ``(var, coef)`` for variables that appear only in the pure, i.e.,
8109+
variables that do not participate in any quadratic or bilinear term.
81238110
81248111
"""
81258112
cdef SCIP_EXPR* expr

tests/test_nonlinear.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,56 @@ def test_quad_coeffs():
288288
assert linterms[0][0].name == z.name
289289
assert linterms[0][1] == 4
290290

291+
292+
def test_quad_coeffs_mixed_linear_and_quadratic():
293+
"""ensure getTermsQuadratic exposes all linear coefficients
294+
295+
``linterms`` contains purely linear variables (those that do not appear
296+
in the quadratic part). For variables that also appear quadratically,
297+
their linear coefficients are stored in the ``lincoef`` component of
298+
``quadterms``.
299+
"""
300+
scip = Model()
301+
302+
var1 = scip.addVar(name="var1", vtype='C', lb=None)
303+
var2 = scip.addVar(name="var2", vtype='C')
304+
var3 = scip.addVar(name="var3", vtype='B')
305+
var4 = scip.addVar(name="var4", vtype='B')
306+
307+
cons = scip.addCons(
308+
8 * var4
309+
+ 4 * var3
310+
- 5 * var2
311+
+ 6 * var3 ** 2
312+
- 3 * var1 ** 2
313+
+ 2 * var2 * var1
314+
+ 7 * var1 * var3
315+
== -2
316+
)
317+
318+
bilinterms, quadterms, linterms = scip.getTermsQuadratic(cons)
319+
320+
# Linear part: getTermsQuadratic must report all linear coefficients,
321+
# including those of variables that also appear quadratically or
322+
# bilinearly.
323+
lin_only = {v.name: c for (v, c) in linterms}
324+
assert lin_only["var4"] == 8
325+
assert lin_only["var3"] == 4
326+
assert lin_only["var2"] == -5
327+
328+
# For completeness, checking if the coefficients from reconstructing the full linear
329+
# coefficients from both linterms and quadterms match
330+
full_lin = {}
331+
for v, c in linterms:
332+
full_lin[v.name] = full_lin.get(v.name, 0.0) + c
333+
for v, _, lincoef in quadterms:
334+
if lincoef != 0.0:
335+
full_lin[v.name] = full_lin.get(v.name, 0.0) + lincoef
336+
337+
assert full_lin["var4"] == 8
338+
assert full_lin["var3"] == 4
339+
assert full_lin["var2"] == -5
340+
291341
def test_addExprNonLinear():
292342
m = Model()
293343
x = m.addVar("x", lb=0, ub=1, obj=10)

0 commit comments

Comments
 (0)