diff --git a/src/parse_expr.jl b/src/parse_expr.jl index cdeeb8ce29f..0e3650492f1 100644 --- a/src/parse_expr.jl +++ b/src/parse_expr.jl @@ -285,8 +285,10 @@ function destructive_add!(ex::AbstractArray{<:GenericAffExpr}, c::Number, return result end - -destructive_add!(ex, c, x) = ex .+ c * x +# For some reason, the broadcast syntax `ex .+ c * x` fails if `x` is an +# `Adjoint`. But if we explicitly call `broadcast` it seems to work. +# See JuMP PR #1698 for more discussion. +destructive_add!(ex, c, x) = broadcast(+, ex, c * x) destructive_add_with_reorder!(ex, arg) = destructive_add!(ex, 1.0, arg) # Special case because "Val{false}()" is used as the default empty expression. diff --git a/test/macros.jl b/test/macros.jl index 23bf1aaa2a7..694ffcc719c 100644 --- a/test/macros.jl +++ b/test/macros.jl @@ -270,6 +270,20 @@ end "DenseAxisArray, or SparseAxisArray.") @test_throws exception @variable(model, x[1:3], container=Oops) end + + @testset "Adjoints" begin + model = Model() + @variable(model, x[1:2]) + obj = @objective(model, Min, x' * ones(2, 2) * x) + @test JuMP.isequal_canonical(obj, x[1]^2 + 2 * x[1] * x[2] + x[2]^2) + cref = @constraint(model, x' * ones(2, 2) * x <= 1) + c = JuMP.constraint_object(cref) + @test JuMP.isequal_canonical(c.func, x[1]^2 + 2 * x[1] * x[2] + x[2]^2) + @test c.set == MOI.LessThan(1.0) + @test JuMP.isequal_canonical( + JuMP.destructive_add!(0.0, x', ones(2, 2)), x' * ones(2, 2) + ) + end end @testset "Macros for JuMPExtension.MyModel" begin