diff --git a/src/core/objective.jl b/src/core/objective.jl index 046437c5..aca4167d 100644 --- a/src/core/objective.jl +++ b/src/core/objective.jl @@ -123,6 +123,38 @@ function objective_min_fuel_and_flow_cost_polynomial(pm::AbstractPowerModel; kwa end end +""" + _pow(x, i) + +A type-unstable version of `x^i` becaues using the base `x^i` for JuMP variables +has some unusual behavior: + +```julia +julia> model = Model(); + +julia> @variable(model, x) +x + +julia> typeof(x^1) +QuadExpr (alias for GenericQuadExpr{Float64, VariableRef}) + +julia> typeof(x^1.0) +NonlinearExpr +``` +""" +function _pow(x, i) + if i == 0 + return 1 + elseif i == 1 + return x + elseif i == 2 + return x^2 + else + return x^Float64(i) + end +end + + "" function _objective_min_fuel_and_flow_cost_polynomial_linquad(pm::AbstractPowerModel; report::Bool=true) gen_cost = Dict() @@ -131,31 +163,19 @@ function _objective_min_fuel_and_flow_cost_polynomial_linquad(pm::AbstractPowerM for (n, nw_ref) in nws(pm) for (i,gen) in nw_ref[:gen] pg = sum( var(pm, n, :pg, i)[c] for c in conductor_ids(pm, n) ) - - if length(gen["cost"]) == 1 - gen_cost[(n,i)] = gen["cost"][1] - elseif length(gen["cost"]) == 2 - gen_cost[(n,i)] = gen["cost"][1]*pg + gen["cost"][2] - elseif length(gen["cost"]) == 3 - gen_cost[(n,i)] = gen["cost"][1]*pg^2 + gen["cost"][2]*pg + gen["cost"][3] - else - gen_cost[(n,i)] = 0.0 - end + gen_cost[(n, i)] = JuMP.@expression( + pm.model, + sum(v * _pow(pg, d - 1) for (d, v) in enumerate(reverse(gen["cost"]))), + ) end from_idx = Dict(arc[1] => arc for arc in nw_ref[:arcs_from_dc]) for (i,dcline) in nw_ref[:dcline] p_dc = sum( var(pm, n, :p_dc, from_idx[i])[c] for c in conductor_ids(pm, n) ) - - if length(dcline["cost"]) == 1 - dcline_cost[(n,i)] = dcline["cost"][1] - elseif length(dcline["cost"]) == 2 - dcline_cost[(n,i)] = dcline["cost"][1]*p_dc + dcline["cost"][2] - elseif length(dcline["cost"]) == 3 - dcline_cost[(n,i)] = dcline["cost"][1]*p_dc^2 + dcline["cost"][2]*p_dc + dcline["cost"][3] - else - dcline_cost[(n,i)] = 0.0 - end + dcline_cost[(n, i)] = JuMP.@expression( + pm.model, + sum(v * _pow(p_dc, d - 1) for (d, v) in enumerate(reverse(dcline["cost"]))), + ) end end @@ -275,7 +295,7 @@ function _objective_min_fuel_and_flow_cost_polynomial_nl(pm::AbstractPowerModel; pg = sum( var(pm, n, :pg, i)[c] for c in conductor_ids(pm, n)) gen_cost[(n,i)] = JuMP.@expression( pm.model, - sum(v * pg^(d-1) for (d, v) in enumerate(reverse(gen["cost"]))), + sum(v * _pow(pg, d-1) for (d, v) in enumerate(reverse(gen["cost"]))), ) end @@ -285,7 +305,7 @@ function _objective_min_fuel_and_flow_cost_polynomial_nl(pm::AbstractPowerModel; p_dc = sum( var(pm, n, :p_dc, from_idx[i])[c] for c in conductor_ids(pm, n)) dcline_cost[(n,i)] = JuMP.@expression( pm.model, - sum(v * p_dc^(d-1) for (d, v) in enumerate(reverse(dcline["cost"]))), + sum(v * _pow(p_dc, d - 1) for (d, v) in enumerate(reverse(dcline["cost"]))), ) end end @@ -316,16 +336,10 @@ function _objective_min_fuel_cost_polynomial_linquad(pm::AbstractPowerModel; rep for (n, nw_ref) in nws(pm) for (i,gen) in nw_ref[:gen] pg = sum( var(pm, n, :pg, i)[c] for c in conductor_ids(pm, n) ) - - if length(gen["cost"]) == 1 - gen_cost[(n,i)] = gen["cost"][1] - elseif length(gen["cost"]) == 2 - gen_cost[(n,i)] = gen["cost"][1]*pg + gen["cost"][2] - elseif length(gen["cost"]) == 3 - gen_cost[(n,i)] = gen["cost"][1]*pg^2 + gen["cost"][2]*pg + gen["cost"][3] - else - gen_cost[(n,i)] = 0.0 - end + gen_cost[(n, i)] = JuMP.@expression( + pm.model, + sum(v * _pow(pg, d - 1) for (d, v) in enumerate(reverse(gen["cost"]))), + ) end end @@ -345,7 +359,7 @@ function _objective_min_fuel_cost_polynomial_nl(pm::AbstractPowerModel; report:: pg = sum( var(pm, n, :pg, i)[c] for c in conductor_ids(pm, n)) gen_cost[(n,i)] = JuMP.@expression( pm.model, - sum(v * pg^(d-1) for (d, v) in enumerate(reverse(gen["cost"]))), + sum(v * _pow(pg, d - 1) for (d, v) in enumerate(reverse(gen["cost"]))), ) end end diff --git a/test/docs.jl b/test/docs.jl index e7b6eb89..7338be12 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -31,6 +31,7 @@ #print(pm.model) @test JuMP.num_nonlinear_constraints(pm.model) == 0 + @test JuMP.num_constraints(pm.model, JuMP.NonlinearExpr, JuMP.MOI.EqualTo{Float64}) == 12 @test JuMP.num_variables(pm.model) == 28 result = optimize_model!(pm, optimizer=JuMP.optimizer_with_attributes(Ipopt.Optimizer, "print_level"=>0)) diff --git a/test/model.jl b/test/model.jl index c301e41c..68d719c1 100644 --- a/test/model.jl +++ b/test/model.jl @@ -16,6 +16,7 @@ pm = instantiate_model("../test/data/matpower/case5.m", ACPPowerModel, PowerModels.build_opf, jump_model=m) @test JuMP.num_nonlinear_constraints(pm.model) == 0 + @test JuMP.num_constraints(pm.model, JuMP.NonlinearExpr, JuMP.MOI.EqualTo{Float64}) == 28 @test JuMP.num_variables(pm.model) == 49 @test pm.model[:my_var] == x