Skip to content

[Bridges] fix SquareBridge with differing constants in off-diagonal - #3068

Merged
odow merged 3 commits into
od/fix-claude-004from
od/fix-claude-001
Sep 6, 2026
Merged

[Bridges] fix SquareBridge with differing constants in off-diagonal#3068
odow merged 3 commits into
od/fix-claude-004from
od/fix-claude-001

Conversation

@odow

@odow odow commented Sep 6, 2026

Copy link
Copy Markdown
Member

SquareBridge ConstraintFunction getter has a sign error when a symmetrization constraint has a nonzero constant

src/Bridges/Constraint/bridges/SquareBridge.jl, MOI.get(::MOI.ModelLike, ::MOI.ConstraintFunction, ::SquareBridge), line 270.

When entries (i, j) and (j, i) of the square matrix differ by a nonzero
constant c (e.g. f_ij = 3 + x, f_ji = 2 + x), bridge_constraint adds a
constraint (f_ij - f_ji) - c == -c (the constant is moved into the set by
normalize_and_add_constraint). When reconstructing f_ji in the
ConstraintFunction getter, the code subtracts rhs a second time instead of
adding it back, so the recovered f_ji is off by 2c.

Repro (c = 1):

inner = MOI.Utilities.Model{Float64}()
model = MOI.Bridges.Constraint.Square{Float64}(inner)
x = MOI.add_variable(model)
y = MOI.add_variable(model)
f = MOI.Utilities.operate(vcat, Float64, 1.0x .+ 1.0, 1.0x .+ 2.0, 1.0x .+ 3.0, 2.0y)
ci = MOI.add_constraint(model, f, MOI.PositiveSemidefiniteConeSquare(2))
MOI.get(model, MOI.ConstraintFunction(), ci)
# entry (2,1) comes back as `4 + x` instead of the original `2 + x`

This only shows up when the off-diagonal expressions differ by a nonzero
constant (e.g. 1 + x vs 2 + x); the common case of numerically-identical
or purely-linear-difference-with-zero-constant entries doesn't trigger it,
which is presumably why the existing test suite (test/Bridges/Constraint/test_SquareBridge.jl)
didn't catch it.

Fix

Add rhs instead of subtracting it:

f_ji = MOI.Utilities.operate!(+, T, f_ji, rhs)

See issue-001.patch. Verified: the repro above returns the original
function exactly after the fix, and test/Bridges/Constraint/test_SquareBridge.jl
still passes in full (all testsets, 367 @tests total).

Note: issue-003.patch touches a different hunk of the same file
(SquareBridge.jl, the ConstraintPrimal/ConstraintPrimalStart getter and
setter rather than the ConstraintFunction getter); they're independent
fixes and both apply cleanly together.

Comment thread test/Bridges/Constraint/test_SquareBridge.jl Outdated
@odow
odow changed the base branch from master to od/fix-claude-004 September 6, 2026 23:23
@odow
odow merged commit 039f8d3 into od/fix-claude-004 Sep 6, 2026
27 checks passed
@odow
odow deleted the od/fix-claude-001 branch September 6, 2026 23:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant