diff --git a/README.md b/README.md index ae4cada..09ae328 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,6 @@ It is embedded in the [Julia programming language], and is an extension to the [ - The source code is well-commented, if you'd like to understand more. - [Checkout the examples](example/). -#### JuMPeR v0.4 - -JuMPeR was recently updated to version v0.4. This changed the syntax to match the changes in JuMP v0.13. Unlike JuMP v0.13, there are no deprecation warnings. However, it should generally be a simple find-and-replace, e.g. `@defUnc` to `@uncertain`. See the documentation for examples. - [Julia programming language]: http://julialang.org/ [JuMP]: https://github.com/JuliaOpt/JuMP.jl [JuMPeR]: https://github.com/IainNZ/JuMPeR.jl diff --git a/REQUIRE b/REQUIRE index 01d59ac..09d23d7 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,2 +1,3 @@ julia 0.5 -JuMP 0.14 0.15 +JuMP 0.16.2 0.17 +MathProgBase 0.6.4 0.7 \ No newline at end of file diff --git a/src/solve.jl b/src/solve.jl index d150c34..69cd888 100644 --- a/src/solve.jl +++ b/src/solve.jl @@ -43,7 +43,7 @@ function _solve_robust(rm::Model, suppress_warnings::Bool, # 2. Setup for uncertainty sets #------------------------------------------------------------------- # Prepare to pass through preferences to a sets - prefs = Dict{Symbol,Any}([name => value for (name,value) in kwargs]) + prefs = Dict{Symbol,Any}(name => value for (name,value) in kwargs) # Build mapping from uncertainty sets to constraints uncsets_to_con_idxs = Dict{AbstractUncertaintySet,Vector{Int}}() for idx in 1:length(rmext.constraint_uncsets) diff --git a/src/uncsets_basic_cut.jl b/src/uncsets_basic_cut.jl index 21b05e8..fab7ae1 100644 --- a/src/uncsets_basic_cut.jl +++ b/src/uncsets_basic_cut.jl @@ -103,7 +103,7 @@ function get_worst_case_value(us::BasicUncertaintySet, rm::Model, idx::Int) con = rmext.unc_constraints[idx] # Update the cutting plane problem's objective, and solve cut_sense, unc_obj_coeffs, lhs_const = JuMPeR.build_cut_objective_sparse(rm, con) - @objective(us.cut_model, cut_sense, sum{u[2]*us.cut_vars[u[1]], u=unc_obj_coeffs}) + @objective(us.cut_model, cut_sense, sum(u[2]*us.cut_vars[u[1]] for u=unc_obj_coeffs)) cut_solve_status = solve(us.cut_model, suppress_warnings=true) cut_solve_status != :Optimal && error("BasicUncertaintySet: cutting plane problem is infeasible or unbounded!") diff --git a/test/REQUIRE b/test/REQUIRE index c678d11..e102414 100644 --- a/test/REQUIRE +++ b/test/REQUIRE @@ -1,3 +1,4 @@ BaseTestNext GLPKMathProgInterface +GLPK 0.4 0.4.2 ECOS diff --git a/test/adp_inventory.jl b/test/adp_inventory.jl index eb7af34..b4d501a 100644 --- a/test/adp_inventory.jl +++ b/test/adp_inventory.jl @@ -16,7 +16,7 @@ using JuMP, JuMPeR using BaseTestNext -const TOL = 1e-4 +const TOL = 5e-3 if !(:lp_solvers in names(Main)) print_with_color(:magenta, "Loading solvers...\n") @@ -51,19 +51,19 @@ print_with_color(:yellow, "Adaptive Inventory Model...\n") @constraint(rm, p[i,t] <= P) end for i in 1:I - @constraint(rm, sum{p[i,t], t=1:T} <= Q) + @constraint(rm, sum(p[i,t] for t=1:T) <= Q) end # Constraint: cannot exceed inventory limits for t in 1:T @constraint(rm, - v1 + sum{p[i,s], i=1:I, s=1:t} - sum{d[s],s=1:t} >= Vmin) + v1 + sum(p[i,s] for i=1:I, s=1:t) - sum(d[s] for s=1:t) >= Vmin) @constraint(rm, - v1 + sum{p[i,s], i=1:I, s=1:t} - sum{d[s],s=1:t} <= Vmax) + v1 + sum(p[i,s] for i=1:I, s=1:t) - sum(d[s] for s=1:t) <= Vmax) end end @testset "Affine, manual" begin - rm = RobustModel() + rm = RobustModel(solver=solver) # Uncertain parameter: demand at each time stage @uncertain(rm, d_nom[t]*(1-θ) <= d[t=1:T] <= d_nom[t]*(1+θ)) # Decision: how much to produce at each factory at each time @@ -76,21 +76,21 @@ print_with_color(:yellow, "Adaptive Inventory Model...\n") end # Objective: total cost of production @variable(rm, F); @objective(rm, Min, F) - @constraint(rm, sum{c[i,t] * p[i,t], i=1:I, t=1:T} <= F) + @constraint(rm, sum(c[i,t] * p[i,t] for i=1:I, t=1:T) <= F) add_constraints(rm, p, d) solve(rm) @test isapprox(getvalue(F), 44272.82749, atol=TOL) end @testset "Affine, auto" begin - rm = RobustModel() + rm = RobustModel(solver=solver) # Uncertain parameter: demand at each time stage @uncertain(rm, d_nom[t]*(1-θ) <= d[t=1:T] <= d_nom[t]*(1+θ)) # Decision: how much to produce at each factory at each time @adaptive(rm, p[i=1:I,t=1:T], policy=Affine, depends_on=d[1:t-1]) # Objective: total cost of production @variable(rm, F); @objective(rm, Min, F) - @constraint(rm, sum{c[i,t] * p[i,t], i=1:I, t=1:T} <= F) + @constraint(rm, sum(c[i,t] * p[i,t] for i=1:I, t=1:T) <= F) add_constraints(rm, p, d) solve(rm) @test isapprox(getvalue(F), 44272.82749, atol=TOL) diff --git a/test/adp_newsvendor.jl b/test/adp_newsvendor.jl index a3d3270..c1d9284 100644 --- a/test/adp_newsvendor.jl +++ b/test/adp_newsvendor.jl @@ -56,7 +56,7 @@ print_with_color(:yellow, "Adaptive Newsvendor Model...\n") end @testset "Static, manual" begin - m = RobustModel() + m = RobustModel(solver=solver) D = add_set(m) @variable(m, x >= 0) @variable(m, S[1:N] >= 0) @@ -70,7 +70,7 @@ print_with_color(:yellow, "Adaptive Newsvendor Model...\n") end # "Static, manual" @testset "Static, auto" begin - m = RobustModel() + m = RobustModel(solver=solver) D = add_set(m) @variable(m, x >= 0) @adaptive(m, S[1:N] >= 0, policy=Static, depends_on=D) @@ -84,7 +84,7 @@ print_with_color(:yellow, "Adaptive Newsvendor Model...\n") end # "Static, auto" @testset "Affine, manual" begin - m = RobustModel() + m = RobustModel(solver=solver) D = add_set(m) @variable(m, x >= 0) @variable(m, S_aff[1:N,0:N]) @@ -105,7 +105,7 @@ print_with_color(:yellow, "Adaptive Newsvendor Model...\n") end @testset "Affine, auto" begin - m = RobustModel() + m = RobustModel(solver=solver) D = add_set(m) @variable(m, x >= 0) @adaptive(m, S[1:N] >= 0, policy=Affine, depends_on=D) diff --git a/test/macro.jl b/test/macro.jl index 1d5f454..537c792 100644 --- a/test/macro.jl +++ b/test/macro.jl @@ -50,9 +50,9 @@ end @constraint(rm, 0 <= u - 5) @test lastus(rm) == "-u $le -5" - @constraint(rm, u == sum{i*v[i], i=1:3}) + @constraint(rm, u == sum(i*v[i] for i=1:3)) @test lastus(rm) == "u - v[1] - 2 v[2] - 3 v[3] $eq 0" - @constraint(rm, sum{i*v[i], i=1:3} + u >= 10) + @constraint(rm, sum(i*v[i] for i=1:3) + u >= 10) @test lastus(rm) == "v[1] + 2 v[2] + 3 v[3] + u $ge 10" end @@ -82,10 +82,10 @@ end @constraint(rm, (u+w)*x + 2 + w*x <= u*z + 3) @test lastuc(rm) == "u x + w x + w x + -u z $le 1" - @constraint(rm, sum{v[i]*y[i], i=1:5; i!=3} <= 9) + @constraint(rm, sum(v[i]*y[i] for i=1:5 if i!=3) <= 9) @test lastuc(rm) == "v[1] y[1] + v[2] y[2] + v[4] y[4] + v[5] y[5] $le 9" - @constraint(rm, sum{i*(u+v[i])*(y[i]+x), i=1:2:5} <= 0) + @constraint(rm, sum(i*(u+v[i])*(y[i]+x) for i=1:2:5) <= 0) @test lastuc(rm) == "(u + v[1]) y[1] + (u + v[1]) x + (3 u + 3 v[3]) y[3] + (3 u + 3 v[3]) x + (5 u + 5 v[5]) y[5] + (5 u + 5 v[5]) x $le 0" foo = u*x diff --git a/test/operators.jl b/test/operators.jl index c786b06..d32442b 100644 --- a/test/operators.jl +++ b/test/operators.jl @@ -522,60 +522,60 @@ rm = RobustModel() us = JuMPeR.get_robust(rm).default_uncset nc = us.norm_constraints @uncertain(rm, u[1:3]) -@constraint(us, norm1{u[i],i=1:3} <= 1) +@constraint(us, norm((u[i] for i=1:3),1) <= 1) @test string(nc[end]) == "‖u[1],u[2],u[3]‖₁ $leq 1" -@constraint(us, norm2{u[i],i=1:3} <= 2) +@constraint(us, norm(u[i] for i=1:3) <= 2) @test string(nc[end]) == "‖u[1],u[2],u[3]‖₂ $leq 2" -@constraint(us, norm∞{u[i],i=1:3} <= 9) +@constraint(us, norm((u[i] for i=1:3),Inf) <= 9) @test string(nc[end]) == "‖u[1],u[2],u[3]‖∞ $leq 9" -@constraint(us, 2*norm1{u[i],i=1:3} <= 1) +@constraint(us, 2*norm((u[i] for i=1:3),1) <= 1) @test string(nc[end]) == "2‖u[1],u[2],u[3]‖₁ $leq 1" -@constraint(us, -1*norm1{u[i],i=1:3} >= -1) +@constraint(us, -1*norm((u[i] for i=1:3),1) >= -1) @test string(nc[end]) == "‖u[1],u[2],u[3]‖₁ $leq 1" -@constraint(us, 1 + norm1{u[i],i=1:3} <= 1) +@constraint(us, 1 + norm((u[i] for i=1:3),1) <= 1) @test string(nc[end]) == "‖u[1],u[2],u[3]‖₁ $leq 0" @variable(rm, x) -@test_throws ErrorException @constraint(us, norm1{u[i],i=1:3} + u[1] <= 1) -@test_throws ErrorException @constraint(us, norm1{u[i],i=1:3} - u[1] <= 1) -@test_throws ErrorException @constraint(us, norm1{u[i],i=1:3} * u[1] <= 1) -@test_throws ErrorException @constraint(us, norm1{u[i],i=1:3} / u[1] <= 1) +@test_throws ErrorException @constraint(us, norm((u[i] for i=1:3),1) + u[1] <= 1) +@test_throws ErrorException @constraint(us, norm((u[i] for i=1:3),1) - u[1] <= 1) +@test_throws ErrorException @constraint(us, norm((u[i] for i=1:3),1) * u[1] <= 1) +@test_throws ErrorException @constraint(us, norm((u[i] for i=1:3),1) / u[1] <= 1) -@test_throws ErrorException @constraint(us, norm1{u[i],i=1:3} + (2*u[1]) <= 1) -@test_throws ErrorException @constraint(us, norm1{u[i],i=1:3} - (2*u[1]) <= 1) -@test_throws ErrorException @constraint(us, norm1{u[i],i=1:3} * (2*u[1]) <= 1) -@test_throws MethodError @constraint(us, norm1{u[i],i=1:3} / (2*u[1]) <= 1) +@test_throws ErrorException @constraint(us, norm((u[i] for i=1:3),1) + (2*u[1]) <= 1) +@test_throws ErrorException @constraint(us, norm((u[i] for i=1:3),1) - (2*u[1]) <= 1) +@test_throws ErrorException @constraint(us, norm((u[i] for i=1:3),1) * (2*u[1]) <= 1) +@test_throws MethodError @constraint(us, norm((u[i] for i=1:3),1) / (2*u[1]) <= 1) # MethodError: `/` has no method matching /(::Int64, ::JuMP.GenericAffExpr{Float64,JuMPeR.Uncertain}) -@test_throws ErrorException @constraint(us, norm1{u[i],i=1:3} + (2*u[1]*x+u[2]) <= 1) -@test_throws ErrorException @constraint(us, norm1{u[i],i=1:3} - (2*u[1]*x+u[2]) <= 1) -@test_throws ErrorException @constraint(us, norm1{u[i],i=1:3} * (2*u[1]*x+u[2]) <= 1) -@test_throws MethodError @constraint(us, norm1{u[i],i=1:3} / (2*u[1]*x+u[2]) <= 1) +@test_throws ErrorException @constraint(us, norm((u[i] for i=1:3),1) + (2*u[1]*x+u[2]) <= 1) +@test_throws ErrorException @constraint(us, norm((u[i] for i=1:3),1) - (2*u[1]*x+u[2]) <= 1) +@test_throws ErrorException @constraint(us, norm((u[i] for i=1:3),1) * (2*u[1]*x+u[2]) <= 1) +@test_throws MethodError @constraint(us, norm((u[i] for i=1:3),1) / (2*u[1]*x+u[2]) <= 1) -@test_throws ErrorException @constraint(us, x + norm1{u[i],i=1:3} <= 1) -@test_throws ErrorException @constraint(us, x - norm1{u[i],i=1:3} <= 1) -@test_throws ErrorException @constraint(us, (2x) + norm1{u[i],i=1:3} <= 1) -@test_throws ErrorException @constraint(us, (2x) - norm1{u[i],i=1:3} <= 1) +@test_throws ErrorException @constraint(us, x + norm((u[i] for i=1:3),1) <= 1) +@test_throws ErrorException @constraint(us, x - norm((u[i] for i=1:3),1) <= 1) +@test_throws ErrorException @constraint(us, (2x) + norm((u[i] for i=1:3),1) <= 1) +@test_throws ErrorException @constraint(us, (2x) - norm((u[i] for i=1:3),1) <= 1) -@test_throws ErrorException @constraint(us, (u[1]) + norm1{u[i],i=1:3} <= 1) -@test_throws ErrorException @constraint(us, (u[1]) - norm1{u[i],i=1:3} <= 1) -@test_throws ErrorException @constraint(us, (u[1]) * norm1{u[i],i=1:3} <= 1) -# @constraint(us, (u[1]) / norm1{u[i],i=1:3} <= 1) +@test_throws ErrorException @constraint(us, (u[1]) + norm((u[i] for i=1:3),1) <= 1) +@test_throws ErrorException @constraint(us, (u[1]) - norm((u[i] for i=1:3),1) <= 1) +@test_throws ErrorException @constraint(us, (u[1]) * norm((u[i] for i=1:3),1) <= 1) +# @constraint(us, (u[1]) / norm((u[i] for i=1:3),1) <= 1) # UndefVarError: i not defined -@test_throws ErrorException @constraint(us, (2*u[1]) + norm1{u[i],i=1:3} <= 1) -@test_throws ErrorException @constraint(us, (2*u[1]) - norm1{u[i],i=1:3} <= 1) -@test_throws ErrorException @constraint(us, (2*u[1]) * norm1{u[i],i=1:3} <= 1) -# @constraint(us, (2*u[1]) / norm1{u[i],i=1:3} <= 1) +@test_throws ErrorException @constraint(us, (2*u[1]) + norm((u[i] for i=1:3),1) <= 1) +@test_throws ErrorException @constraint(us, (2*u[1]) - norm((u[i] for i=1:3),1) <= 1) +@test_throws ErrorException @constraint(us, (2*u[1]) * norm((u[i] for i=1:3),1) <= 1) +# @constraint(us, (2*u[1]) / norm((u[i] for i=1:3),1) <= 1) # UndefVarError: i not defined -@test_throws ErrorException @constraint(us, (2*u[1]*x+u[2]) + norm1{u[i],i=1:3} <= 1) -@test_throws ErrorException @constraint(us, (2*u[1]*x+u[2]) - norm1{u[i],i=1:3} <= 1) -@test_throws ErrorException @constraint(us, (2*u[1]*x+u[2]) * norm1{u[i],i=1:3} <= 1) -# @constraint(us, (2*u[1]*x+u[2]) / norm1{u[i],i=1:3} <= 1) +@test_throws ErrorException @constraint(us, (2*u[1]*x+u[2]) + norm((u[i] for i=1:3),1) <= 1) +@test_throws ErrorException @constraint(us, (2*u[1]*x+u[2]) - norm((u[i] for i=1:3),1) <= 1) +@test_throws ErrorException @constraint(us, (2*u[1]*x+u[2]) * norm((u[i] for i=1:3),1) <= 1) +# @constraint(us, (2*u[1]*x+u[2]) / norm((u[i] for i=1:3),1) <= 1) # UndefVarError: i not defined end # "Unc. set norms" diff --git a/test/print.jl b/test/print.jl index 5b8db7d..a049ca2 100644 --- a/test/print.jl +++ b/test/print.jl @@ -13,17 +13,11 @@ using JuMP, JuMPeR using BaseTestNext -import JuMP: REPLMode, IJuliaMode -import JuMP: repl, ijulia +import JuMP: repl # Helper function to test IO methods work correctly -function io_test(mode, obj, exp_str; repl=:both) - if mode == REPLMode - repl != :show && @test sprint(print, obj) == exp_str - repl != :print && @test sprint(show, obj) == exp_str - else - @test sprint(writemime, "text/latex", obj) == "\$\$ $exp_str \$\$" - end +function io_test(obj, exp_str; repl=:both) + @test sprint(print, obj) == exp_str end @testset "Printing" begin @@ -65,27 +59,27 @@ print_with_color(:yellow, "Printing...\n") # @constraint(mod_1, norm([a,b]) <= 1) # ‖a,b‖₂ $le 1 - io_test(REPLMode, mod_1, """ + io_test(mod_1, """ Max 2 vars[1] Subject to - vars[10] $le 10 - vars[i] free $fa i $inset {1,2,$dots,9,10} + vars[10] ≤ 10 + vars[i] ∀ i ∈ {1,2,…,9,10} Uncertain constraints: -a vars[5] $le 5 +a vars[5] ≤ 5 Uncertain parameters: -bnd_free[i] free $fa i $inset {2,3,4,5} -bnd_lowb[i] $ge 2 $fa i $inset {2,3,4,5} -bnd_high[i] $le 5 $fa i $inset {2,3,4,5} -2 $le bnd_both[i] $le 5 $fa i $inset {2,3,4,5} -mat2d[i,j] free $fa i $inset {1,2,3}, j $inset {1,2,3} -mat3d[i,j,k] free $fa i $inset {1,2,3}, j $inset {1,2,3}, k $inset {1,2,3} -a $ge 1 -b $le 1 --1 $le c $le 1 -a1 $ge 1, integer -b1 $le 1, integer --1 $le c1 $le 1, integer -x $inset {0,1} +bnd_free[i] free ∀ i ∈ {2,3,4,5} +bnd_lowb[i] ≥ 2 ∀ i ∈ {2,3,4,5} +bnd_high[i] ≤ 5 ∀ i ∈ {2,3,4,5} +2 ≤ bnd_both[i] ≤ 5 ∀ i ∈ {2,3,4,5} +mat2d[i,j] free ∀ i ∈ {1,2,3}, j ∈ {1,2,3} +mat3d[i,j,k] free ∀ i ∈ {1,2,3}, j ∈ {1,2,3}, k ∈ {1,2,3} +a ≥ 1 +b ≤ 1 +-1 ≤ c ≤ 1 +a1 ≥ 1, integer +b1 ≤ 1, integer +-1 ≤ c1 ≤ 1, integer +x ∈ {0,1} y free z free, integer """, repl=:print) @@ -107,15 +101,15 @@ end # "RobustModel" @uncertain(m, i <= bnd_difflo_with_up[i=2:5] <= 5) @uncertain(m, 2 <= bnd_diffup_with_lo[i=2:5] <= i) - io_test(REPLMode, bnd_free, "bnd_free[i] free $fa i $inset {2,3,4,5}") - io_test(REPLMode, bnd_lowb, "bnd_lowb[i] $ge 2 $fa i $inset {2,3,4,5}") - io_test(REPLMode, bnd_high, "bnd_high[i] $le 5 $fa i $inset {2,3,4,5}") - io_test(REPLMode, bnd_both, "2 $le bnd_both[i] $le 5 $fa i $inset {2,3,4,5}") - io_test(REPLMode, bnd_difflo, "bnd_difflo[i] $ge $dots $fa i $inset {2,3,4,5}") - io_test(REPLMode, bnd_diffup, "bnd_diffup[i] $le $dots $fa i $inset {2,3,4,5}") - io_test(REPLMode, bnd_diffbo, "$dots $le bnd_diffbo[i] $le $dots $fa i $inset {2,3,4,5}") - io_test(REPLMode, bnd_difflo_with_up, "$dots $le bnd_difflo_with_up[i] $le 5 $fa i $inset {2,3,4,5}") - io_test(REPLMode, bnd_diffup_with_lo, "2 $le bnd_diffup_with_lo[i] $le $dots $fa i $inset {2,3,4,5}") + io_test(bnd_free, "bnd_free[i] free $fa i $inset {2,3,4,5}") + io_test(bnd_lowb, "bnd_lowb[i] $ge 2 $fa i $inset {2,3,4,5}") + io_test(bnd_high, "bnd_high[i] $le 5 $fa i $inset {2,3,4,5}") + io_test(bnd_both, "2 $le bnd_both[i] $le 5 $fa i $inset {2,3,4,5}") + io_test(bnd_difflo, "bnd_difflo[i] $ge $dots $fa i $inset {2,3,4,5}") + io_test(bnd_diffup, "bnd_diffup[i] $le $dots $fa i $inset {2,3,4,5}") + io_test(bnd_diffbo, "$dots $le bnd_diffbo[i] $le $dots $fa i $inset {2,3,4,5}") + io_test(bnd_difflo_with_up, "$dots $le bnd_difflo_with_up[i] $le 5 $fa i $inset {2,3,4,5}") + io_test(bnd_diffup_with_lo, "2 $le bnd_diffup_with_lo[i] $le $dots $fa i $inset {2,3,4,5}") end # "JuMPContainer{Uncertain}" end # "Printing" diff --git a/test/uncsets.jl b/test/uncsets.jl index 01534d4..48734f6 100644 --- a/test/uncsets.jl +++ b/test/uncsets.jl @@ -19,80 +19,84 @@ if !(:lp_solvers in names(Main)) include(joinpath(Pkg.dir("JuMP"),"test","solvers.jl")) end lp_solvers = filter(s->(!contains(string(typeof(s)),"SCSSolver")), lp_solvers) +solver_name(solver) = split(string(typeof(solver)),".")[2] @testset "UncertainySet" begin print_with_color(:yellow, "UncertainySet...\n") -@testset "Check interface throws" begin - eval(:(type IncompleteSet <: JuMPeR.AbstractUncertaintySet end)) # In global scope - @test_throws ErrorException JuMPeR.setup_set(IncompleteSet(), RobustModel(), Int[], false, nothing) - @test_throws ErrorException JuMPeR.generate_reform(IncompleteSet(), RobustModel(), Int[]) - @test_throws ErrorException JuMPeR.generate_cut(IncompleteSet(), RobustModel(), Int[]) - @test_throws ErrorException JuMPeR.generate_scenario(IncompleteSet(), RobustModel(), Int[]) -end - -# build_cut_objective -# build_cut_objective_sparse -# build_certain_constraint -# is_constraint_violated -@testset "Utilities" begin - rm = RobustModel() - @variable(rm, x[1:4] >= 0) - @uncertain(rm, u[1:5]) - @constraint(rm, (3*u[1] + 2.0) * x[1] + # u1: 3*x1 = 3*2 = 6, c: 2*x1 = 2*2 =4 - ( u[2] - 1.0) * x[2] + # u2: 1*x2 = 1*3 = 3, c: -1*x2 = -1*3 = -3 - (u[1] + u[3]) * x[3] + # u1: 3*x3 = 3*4 = 12, u3: 1*x3 = 4 - (u[3] +2*u[4]) * x[4] <= # u3: 1*x4 = 1*5 = 5, u4: 2*x4 = 10 - 5.0 + u[5]) # u5 - rm.colVal = [2.0, 3.0, 4.0, 5.0] - unc_con = JuMPeR.get_robust(rm).unc_constraints[end] +@testset "with $(solver_name(solver))," for solver in lp_solvers + @testset "Check interface throws" begin + eval(:(type IncompleteSet <: JuMPeR.AbstractUncertaintySet end)) # In global scope + @test_throws ErrorException JuMPeR.setup_set(IncompleteSet(), RobustModel(solver=solver), Int[], false, nothing) + @test_throws ErrorException JuMPeR.generate_reform(IncompleteSet(), RobustModel(solver=solver), Int[]) + @test_throws ErrorException JuMPeR.generate_cut(IncompleteSet(), RobustModel(solver=solver), Int[]) + @test_throws ErrorException JuMPeR.generate_scenario(IncompleteSet(), RobustModel(solver=solver), Int[]) + end - # Accumulate the coefficients for each uncertain parameter using - # the values of the decision variables and the coefficients, to build - # the objective function for a cut generating problem - sense, unc_coeffs, lhs_const = JuMPeR.build_cut_objective_dense(rm, unc_con) - @test sense == :Max - @test unc_coeffs[1] == 6 + 4 - @test unc_coeffs[2] == 3 - @test unc_coeffs[3] == 4 + 5 - @test unc_coeffs[4] == 10 - @test unc_coeffs[5] == -1 - @test lhs_const == 4 - 3 + # build_cut_objective + # build_cut_objective_sparse + # build_certain_constraint + # is_constraint_violated + @testset "Utilities" begin + rm = RobustModel(solver=solver) + @variable(rm, x[1:4] >= 0) + @uncertain(rm, u[1:5]) + @constraint(rm, (3*u[1] + 2.0) * x[1] + # u1: 3*x1 = 3*2 = 6, c: 2*x1 = 2*2 =4 + ( u[2] - 1.0) * x[2] + # u2: 1*x2 = 1*3 = 3, c: -1*x2 = -1*3 = -3 + (u[1] + u[3]) * x[3] + # u1: 3*x3 = 3*4 = 12, u3: 1*x3 = 4 + (u[3] +2*u[4]) * x[4] <= # u3: 1*x4 = 1*5 = 5, u4: 2*x4 = 10 + 5.0 + u[5]) # u5 + rm.colVal = [2.0, 3.0, 4.0, 5.0] + unc_con = JuMPeR.get_robust(rm).unc_constraints[end] - # Same as above, but "sparse" - sense, unc_coeffs, lhs_const = JuMPeR.build_cut_objective_sparse(rm, unc_con) - sort!(unc_coeffs) - @test sense == :Max - for i in 1:5 - @test unc_coeffs[i][1] == i - end - @test unc_coeffs[1][2] == 6 + 4 - @test unc_coeffs[2][2] == 3 - @test unc_coeffs[3][2] == 4 + 5 - @test unc_coeffs[4][2] == 10 - @test unc_coeffs[5][2] == -1 - @test lhs_const == 4 - 3 + # Accumulate the coefficients for each uncertain parameter using + # the values of the decision variables and the coefficients, to build + # the objective function for a cut generating problem + sense, unc_coeffs, lhs_const = JuMPeR.build_cut_objective_dense(rm, unc_con) + @test sense == :Max + @test unc_coeffs[1] == 6 + 4 + @test unc_coeffs[2] == 3 + @test unc_coeffs[3] == 4 + 5 + @test unc_coeffs[4] == 10 + @test unc_coeffs[5] == -1 + @test lhs_const == 4 - 3 - # ------------------- - unc_val = [1.0, 2.0, 3.0, 4.0, 5.0] - new_con = JuMPeR.build_certain_constraint(unc_con, unc_val) - @test string(new_con) == "5 x[1] + x[2] + 4 x[3] + 11 x[4] $(JuMP.repl[:leq]) 10" + # Same as above, but "sparse" + sense, unc_coeffs, lhs_const = JuMPeR.build_cut_objective_sparse(rm, unc_con) + sort!(unc_coeffs) + @test sense == :Max + for i in 1:5 + @test unc_coeffs[i][1] == i + end + @test unc_coeffs[1][2] == 6 + 4 + @test unc_coeffs[2][2] == 3 + @test unc_coeffs[3][2] == 4 + 5 + @test unc_coeffs[4][2] == 10 + @test unc_coeffs[5][2] == -1 + @test lhs_const == 4 - 3 - # Bit of a hack to test build from JuMP.JuMPDict - inner_m = Model(solver=lp_solvers[1]) - @variable(inner_m, i <= inner_u[i=1:5] <= i) - @objective(inner_m, Max, sum(inner_u)) - solve(inner_m) - new_con = JuMPeR.build_certain_constraint(unc_con, getvalue(inner_u)) - @test string(new_con) == "5 x[1] + x[2] + 4 x[3] + 11 x[4] $(JuMP.repl[:leq]) 10" + # ------------------- + unc_val = [1.0, 2.0, 3.0, 4.0, 5.0] + new_con = JuMPeR.build_certain_constraint(unc_con, unc_val) + @test all(contains(string(new_con), "x[$i]") for i in 1:4) + @test contains(string(new_con), "$(JuMP.repl[:leq])") - # ------------------- - lhs_val = 1.0*dot([5,1,4,11],[2,3,4,5]) - @test JuMPeR.check_cut_status(new_con, lhs_val, 1e-6) == :Violate - lhs_val = 1.0*dot([5,1,4,11],[2,0,0,0]) - @test JuMPeR.check_cut_status(new_con, lhs_val, 1e+6) == :Active - lhs_val = 1.0*dot([5,1,4,11],[0,0,0,0]) - @test JuMPeR.check_cut_status(new_con, lhs_val, 1e-6) == :Slack -end # "Utilities" + # Bit of a hack to test build from JuMP.JuMPDict + inner_m = Model(solver=solver) + @variable(inner_m, i <= inner_u[i=1:5] <= i) + @objective(inner_m, Max, sum(inner_u)) + solve(inner_m) + new_con = JuMPeR.build_certain_constraint(unc_con, getvalue(inner_u)) + @test all(contains(string(new_con), "x[$i]") for i in 1:4) + @test contains(string(new_con), "$(JuMP.repl[:leq])") + # ------------------- + lhs_val = 1.0*dot([5,1,4,11],[2,3,4,5]) + @test JuMPeR.check_cut_status(new_con, lhs_val, 1e-6) == :Violate + lhs_val = 1.0*dot([5,1,4,11],[2,0,0,0]) + @test JuMPeR.check_cut_status(new_con, lhs_val, 1e+6) == :Active + lhs_val = 1.0*dot([5,1,4,11],[0,0,0,0]) + @test JuMPeR.check_cut_status(new_con, lhs_val, 1e-6) == :Slack + end # "Utilities" +end # "LPSolver" end # "UncertainySet" diff --git a/test/uncsets_basic.jl b/test/uncsets_basic.jl index 4feef7d..982de68 100644 --- a/test/uncsets_basic.jl +++ b/test/uncsets_basic.jl @@ -178,7 +178,6 @@ print_with_color(:yellow, " LP tests...\n") end # "LPs with ..." - print_with_color(:yellow, " MILP tests...\n") @testset "MILPs with $(solver_name(solver)), cuts=$cuts" for solver in lazy_solvers, cuts in [true,false] diff --git a/test/uncsets_basic_L1.jl b/test/uncsets_basic_L1.jl index 02905db..5c2b155 100644 --- a/test/uncsets_basic_L1.jl +++ b/test/uncsets_basic_L1.jl @@ -45,15 +45,15 @@ print_with_color(:yellow, "BasicUncertaintySet L1 norm...\n") m = RobustModel(solver=solver) @variable(m, 0 <= x[i=1:5] <= 2*i) @uncertain(m, 0 <= u[i=1:5] <= i+4) - @objective(m, Max, sum{(6-i)*x[i], i=1:5}) - !flip && @constraint(m, sum{u[i]*x[i], i=1:5} <= 100) - flip && @constraint(m, -sum{u[i]*x[i], i=1:5} >= -100) + @objective(m, Max, sum((6-i)*x[i] for i=1:5)) + !flip && @constraint(m, sum(u[i]*x[i] for i=1:5) <= 100) + flip && @constraint(m, -sum(u[i]*x[i] for i=1:5) >= -100) a = Float64[3, 0, 0, 2, 1]; c = Float64[5, 0, 0, 5, 5] I = [1, 5, 4] z = convert(Vector{JuMPeR.UncExpr}, a.*u-c) !macr && @constraint(m, norm(z, 1) <= 1) - macr && @constraint(m, norm1{a[i]*u[i]-c[i],i=I} <= 1) + macr && @constraint(m, norm((a[i]*u[i]-c[i] for i=I),1) <= 1) @test solve(m, suppress_warnings=true, prefer_cuts=cuts) == :Optimal # u = [5, 6, 7, 5, 6] (2,3 are unrestricted) # x = [2, 4, 6, 8, ?] @@ -78,7 +78,7 @@ print_with_color(:yellow, "BasicUncertaintySet L1 norm...\n") @constraint(m, u[1] == 5.0*z[1] + 10.0) @constraint(m, u[2] == 3.0*z[1] - 2.0*z[2] + 3.0) !macr && @constraint(m, norm(z,1) <= 1) - macr && @constraint(m, norm1{z[i],i=1:2} <= 1) + macr && @constraint(m, norm((z[i] for i=1:2),1) <= 1) @test solve(m, suppress_warnings=true, prefer_cuts=cuts) == :Optimal @test isapprox(getvalue(x[1]), 1.0, atol=TOL) @test isapprox(getvalue(x[2]), 0.0, atol=TOL) diff --git a/test/uncsets_basic_L2.jl b/test/uncsets_basic_L2.jl index cd46d39..c466e05 100644 --- a/test/uncsets_basic_L2.jl +++ b/test/uncsets_basic_L2.jl @@ -45,12 +45,12 @@ print_with_color(:yellow, "BasicUncertaintySet L2 norm...\n") m = RobustModel(solver=solver) @variable(m, 0 <= x[i=1:5] <= 2*i) @uncertain(m, 0 <= u[i=1:5] <= i+4) - @objective(m, Max, sum{(6-i)*x[i], i=1:5}) - !flip && @constraint(m, sum{u[i]*x[i], i=1:5} <= 100) - flip && @constraint(m, -sum{u[i]*x[i], i=1:5} >= -100) + @objective(m, Max, sum((6-i)*x[i] for i=1:5)) + !flip && @constraint(m, sum(u[i]*x[i] for i=1:5) <= 100) + flip && @constraint(m, -sum(u[i]*x[i] for i=1:5) >= -100) a = [3, 0, 0, 2, 1]; I = [1, 5, 4] - @constraint(m, norm2{a[i]*u[i]-5,i=I} <= 1) + @constraint(m, norm(a[i]*u[i]-5 for i=I) <= 1) @test solve(m, suppress_warnings=true, prefer_cuts=cuts) == :Optimal @test isapprox(getvalue(x[1]), 2.0, atol=TOL) @test isapprox(getvalue(x[2]), 4.0, atol=TOL) diff --git a/test/uncsets_basic_Linf.jl b/test/uncsets_basic_Linf.jl index f2d7131..9a10fde 100644 --- a/test/uncsets_basic_Linf.jl +++ b/test/uncsets_basic_Linf.jl @@ -46,15 +46,15 @@ print_with_color(:yellow, "BasicUncertaintySet L∞ norm...\n") m = RobustModel(solver=solver) @variable(m, 0 <= x[i=1:5] <= 2*i) @uncertain(m, 0 <= u[i=1:5] <= i+4) - @objective(m, Max, sum{(6-i)*x[i], i=1:5}) - !flip && @constraint(m, sum{u[i]*x[i], i=1:5} <= 100) - flip && @constraint(m, -sum{u[i]*x[i], i=1:5} >= -100) + @objective(m, Max, sum((6-i)*x[i] for i=1:5)) + !flip && @constraint(m, sum(u[i]*x[i] for i=1:5) <= 100) + flip && @constraint(m, -sum(u[i]*x[i] for i=1:5) >= -100) a = Float64[2, 0, 0, 2, 2]; c = Float64[5, 0, 0, 5, 5] I = [1, 4, 5] z = convert(Vector{JuMPeR.UncExpr}, a.*u-c) !macr && @constraint(m, norm(z, Inf) <= 2) - macr && @constraint(m, norm∞{a[i]*u[i]-c[i],i=I} <= 2) + macr && @constraint(m, norm((a[i]*u[i]-c[i] for i=I),Inf) <= 2) solve(m, suppress_warnings=true, prefer_cuts=cuts, cut_tol=1e-4) # max_u = [5.0, 6, 7.0, 8.0, 9.0] # u = [3.5, 6, 7.0, 3.5, 3.5] @@ -82,7 +82,7 @@ print_with_color(:yellow, "BasicUncertaintySet L∞ norm...\n") @constraint(m, u[1] == 5.0*z[1] + 10.0) @constraint(m, u[2] == 3.0*z[1] - 2.0*z[2] + 3.0) !macr && @constraint(m, norm(z,Inf) <= 1) - macr && @constraint(m, norm∞{z[i],i=1:2} <= 1) + macr && @constraint(m, norm((z[i] for i=1:2),Inf) <= 1) @test solve(m, suppress_warnings=true, prefer_cuts=cuts) == :Optimal @test isapprox(getvalue(x[1]), 1.0, atol=TOL/10) @test isapprox(getvalue(x[2]), 0.0, atol=TOL/10)