From 899886a6700e5a9a9cdd5cf3852440cad1deb3a1 Mon Sep 17 00:00:00 2001 From: odow Date: Wed, 7 Nov 2018 11:58:19 -0600 Subject: [PATCH 1/5] Implement value for GenericQuadExpr. --- src/quad_expr.jl | 18 +++++++++++++++++- test/expr.jl | 13 +++++++++++++ test/generate_and_solve.jl | 2 ++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/quad_expr.jl b/src/quad_expr.jl index 100c61749ea..dad3f4718b9 100644 --- a/src/quad_expr.jl +++ b/src/quad_expr.jl @@ -232,4 +232,20 @@ function Base.copy(q::GenericQuadExpr, new_model::Model) copy(q.qcoeffs), copy(q.aff, new_model)) end -# TODO: result_value for QuadExpr +# Requires that foo(::GenericAffExpr) is defined. +function value(ex::GenericQuadExpr{CoefType, VarType}, + foo::Function) where {CoefType, VarType} + # The return type of appling map to ::VarType. + MapVarType = Base.promote_op(foo, VarType) + # Later, we're going to multiply two MapVarType together + MapVarType2 = Base.promote_op(*, MapVarType, MapVarType) + # We're also going to multiply a constant with ::MapVarType2 + RetType = Base.promote_op(*, CoefType, MapVarType2) + ret = convert(RetType, foo(ex.aff)) + for (vars, coef) in ex.terms + ret += coef * foo(vars.a) * foo(vars.b) + end + return ret +end + +JuMP.result_value(ex::JuMP.GenericQuadExpr) = value(ex, JuMP.result_value) diff --git a/test/expr.jl b/test/expr.jl index dd58e303339..d454877e7e9 100644 --- a/test/expr.jl +++ b/test/expr.jl @@ -42,6 +42,19 @@ function expressions_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType @test @inferred(JuMP.value(expr2, i -> 1.0)) == 2.0 end + @testset "value for GenericQuadExpr" begin + # 1 + 2x(1) + 3x(2) + affine_term = JuMP.GenericAffExpr(1.0, 1 => 2.0, 2 => 3.0) + # 1 + 2x(1) + 3x(2) + 4x(1)^2 + 5x(1)*x(2) + 6x(2)^2 + expr = JuMP.GenericQuadExpr(affine_term, + JuMP.UnorderedPair(1, 1) => 4.0, + JuMP.UnorderedPair(1, 2) => 5.0, + JuMP.UnorderedPair(2, 2) => 6.0) + @test typeof(@inferred(JuMP.value(expr, i -> 1.0))) == Float64 + @test @inferred(JuMP.value(expr, i -> 1.0)) == 16 + @test @inferred(JuMP.value(expr, i -> 2.0)) == 62 + end + @testset "add_to_expression!(::GenericAffExpr{C,V}, ::V)" begin aff = JuMP.GenericAffExpr(1.0, :a => 2.0) @test JuMP.isequal_canonical(JuMP.add_to_expression!(aff, :b), diff --git a/test/generate_and_solve.jl b/test/generate_and_solve.jl index 89df2c5ed4d..d36e3cfd0f8 100644 --- a/test/generate_and_solve.jl +++ b/test/generate_and_solve.jl @@ -220,6 +220,8 @@ @test JuMP.result_dual(c1) == -1.0 @test JuMP.result_dual(c2) == 2.0 @test JuMP.result_dual(c3) == 3.0 + + @test JuMP.result_value(2 * x + 3 * y * x) == 2.0 end @testset "SOC" begin From 3f88a6dfe5353a0c3ec89df4655c12158b60f808 Mon Sep 17 00:00:00 2001 From: odow Date: Wed, 7 Nov 2018 13:13:01 -0600 Subject: [PATCH 2/5] Respond to @blegat's comments --- src/quad_expr.jl | 12 ++++-------- test/expr.jl | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/quad_expr.jl b/src/quad_expr.jl index dad3f4718b9..76a9e3e2015 100644 --- a/src/quad_expr.jl +++ b/src/quad_expr.jl @@ -232,16 +232,12 @@ function Base.copy(q::GenericQuadExpr, new_model::Model) copy(q.qcoeffs), copy(q.aff, new_model)) end -# Requires that foo(::GenericAffExpr) is defined. +# Requires that value(::GenericAffExpr, foo) is defined. function value(ex::GenericQuadExpr{CoefType, VarType}, foo::Function) where {CoefType, VarType} - # The return type of appling map to ::VarType. - MapVarType = Base.promote_op(foo, VarType) - # Later, we're going to multiply two MapVarType together - MapVarType2 = Base.promote_op(*, MapVarType, MapVarType) - # We're also going to multiply a constant with ::MapVarType2 - RetType = Base.promote_op(*, CoefType, MapVarType2) - ret = convert(RetType, foo(ex.aff)) + RetType = Base.promote_op( + (ctype, vtype) -> ctype * foo(vtype) * foo(vtype), CoefType, VarType) + ret = convert(RetType, value(ex.aff, foo)) for (vars, coef) in ex.terms ret += coef * foo(vars.a) * foo(vars.b) end diff --git a/test/expr.jl b/test/expr.jl index d454877e7e9..008ab27f335 100644 --- a/test/expr.jl +++ b/test/expr.jl @@ -51,8 +51,8 @@ function expressions_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType JuMP.UnorderedPair(1, 2) => 5.0, JuMP.UnorderedPair(2, 2) => 6.0) @test typeof(@inferred(JuMP.value(expr, i -> 1.0))) == Float64 - @test @inferred(JuMP.value(expr, i -> 1.0)) == 16 - @test @inferred(JuMP.value(expr, i -> 2.0)) == 62 + @test @inferred(JuMP.value(expr, i -> 1.0)) == 21 + @test @inferred(JuMP.value(expr, i -> 2.0)) == 71 end @testset "add_to_expression!(::GenericAffExpr{C,V}, ::V)" begin From 9a069fe562fadaa07a44d69b7d8273da8c5fb8e2 Mon Sep 17 00:00:00 2001 From: odow Date: Wed, 7 Nov 2018 13:24:49 -0600 Subject: [PATCH 3/5] [ci skip] clarify comment --- src/quad_expr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quad_expr.jl b/src/quad_expr.jl index 76a9e3e2015..7db862ba794 100644 --- a/src/quad_expr.jl +++ b/src/quad_expr.jl @@ -232,7 +232,7 @@ function Base.copy(q::GenericQuadExpr, new_model::Model) copy(q.qcoeffs), copy(q.aff, new_model)) end -# Requires that value(::GenericAffExpr, foo) is defined. +# Requires that value(::GenericAffExpr, foo) and foo(::VarType) is defined. function value(ex::GenericQuadExpr{CoefType, VarType}, foo::Function) where {CoefType, VarType} RetType = Base.promote_op( From c4dd6cede4d7b137b6cedd8279563d3c8eef14d9 Mon Sep 17 00:00:00 2001 From: odow Date: Wed, 7 Nov 2018 13:31:46 -0600 Subject: [PATCH 4/5] [ci skip] clarify comment redux. --- src/quad_expr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quad_expr.jl b/src/quad_expr.jl index 7db862ba794..f474f6d8c9c 100644 --- a/src/quad_expr.jl +++ b/src/quad_expr.jl @@ -232,7 +232,7 @@ function Base.copy(q::GenericQuadExpr, new_model::Model) copy(q.qcoeffs), copy(q.aff, new_model)) end -# Requires that value(::GenericAffExpr, foo) and foo(::VarType) is defined. +# Requires that foo(::VarType) is defined. function value(ex::GenericQuadExpr{CoefType, VarType}, foo::Function) where {CoefType, VarType} RetType = Base.promote_op( From 4a56ac46c1608be571e3d0e7076c7ad3b878c2eb Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Wed, 7 Nov 2018 18:57:45 -0600 Subject: [PATCH 5/5] foo -> value_func --- src/quad_expr.jl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/quad_expr.jl b/src/quad_expr.jl index f474f6d8c9c..aa2d3975b3c 100644 --- a/src/quad_expr.jl +++ b/src/quad_expr.jl @@ -232,14 +232,15 @@ function Base.copy(q::GenericQuadExpr, new_model::Model) copy(q.qcoeffs), copy(q.aff, new_model)) end -# Requires that foo(::VarType) is defined. +# Requires that value_func(::VarType) is defined. function value(ex::GenericQuadExpr{CoefType, VarType}, - foo::Function) where {CoefType, VarType} + value_func::Function) where {CoefType, VarType} RetType = Base.promote_op( - (ctype, vtype) -> ctype * foo(vtype) * foo(vtype), CoefType, VarType) - ret = convert(RetType, value(ex.aff, foo)) + (ctype, vtype) -> ctype * value_func(vtype) * value_func(vtype), + CoefType, VarType) + ret = convert(RetType, value(ex.aff, value_func)) for (vars, coef) in ex.terms - ret += coef * foo(vars.a) * foo(vars.b) + ret += coef * value_func(vars.a) * value_func(vars.b) end return ret end