JuMPDict change of dimension - dictionary

I am using Julia 0.6.2 and JuMP 0.18.5 (I can't use a more recent version since I need to use an old package).
Creating JuMP variables with conditions on the index lead to a JuMPDict instead of an Array.
For example:
m = Model(solver = CplexSolver())
# type of x: JuMP.JuMPDict{JuMP.Variable,2}
#variable(m, x[i in 1:3, j in 1:3; i < j] >= 0)
# type of y: JuMP.JuMPDict{JuMP.Variable,3}
#variable(m, y[i in 1:3, j in 1:3, k in 1:3; i < j] >= 0)
I would like to apply a function f to x and to y[:, :, k] for all k in 1:3. However, I don't know how to define such a generic function.
I tried to set the argument type of f to JuMP.JuMPDict{JuMP.Variable,2}:
function f(input::JuMP.JuMPDict{JuMP.Variable,2})
...
end
I can use the function on x but not on y:
f(x) # Works
for k in 1:3
f(y[:, :, k]) # does not work as y is not an array
end
My last idea was to convert y into several JuMP.JuMPDict{JuMP.Variable,2}:
function convertTo2D(dict3D::JuMP.JuMPDict{JuMP.Variable,3}, k::Int)
dict2D = JuMP.JuMPDict{JuMP.Variable,2}() # This line returns "ERROR: KeyError: key :model not found"
for (key, value) in keys(dict3D)
if key[3] == k
dict2D[(key[1], key[2])] = value # Not sure if it will work
end
end
return dict2D
end
If this was working I could use:
for k in 1:3
f(convertTd2D(y, k))
end
Do you know how I could fix convertTo2D or do what I want another way?

Anonymous variables solved my problem. Thanks to them I can successively create the variables of y in a for loop. Variable y is now an array of "2D dictionaries" rather than a "3D dictionaries":
y = Array{JuMP.JuMPDict{JuMP.Variable,2}, 1}([])
for k in 1:3
yk = #variable(m, [i in 1:3, j in 1:3; i < j] >= 0)
f(yk)
push!(y, yk)
end

Related

What do multiple objective functions mean in Julia jump?

I have multiple objective functions for the same model in Julia JuMP created using an #optimize in a for loop. What does it mean to have multiple objective functions in Julia? What objective is minimized, or is it that all the objectives are minimized jointly? How are the objectives minimized jointly?
using JuMP
using MosekTools
K = 3
N = 2
penalties = [1.0, 3.9, 8.7]
function fac1(r::Number, i::Number, l::Number)
fac1 = 1.0
for m in 0:r-1
fac1 *= (i-m)*(l-m)
end
return fac1
end
function fac2(r::Number, i::Number, l::Number, tau::Float64)
return tau ^ (i + l - 2r + 1)/(i + l - 2r + 1)
end
function Q_r(i::Number, l::Number, r::Number, tau::Float64)
if i >= r && l >= r
return 2 * fac1(r, i, l) * fac2(r, i, l, tau)
else
return 0.0
end
end
function Q(i::Number, l::Number, tau::Number)
elem = 0
for r in 0:N
elem += penalties[r + 1] * Q_r(i, l, r, tau)
end
return elem
end
# discrete segment starting times
mat = Array{Float64, 3}(undef, K, N+1, N+1)
function Q_mat()
for k in 0:K-1
for i in 1:N+1
for j in 1:N+1
mat[k+1, i, j] = Q(i, j, convert(Float64, k))
end
end
return mat
end
end
function A_tau(r::Number, n::Number, tau::Float64)
fac = 1
for m in 1:r
fac *= (n - (m - 1))
end
if n >= r
return fac * tau ^ (n - r)
else
return 0.0
end
end
function A_tau_mat(tau::Float64)
mat = Array{Float64, 2}(undef, N+1, N+1)
for i in 1:N+1
for j in 1:N+1
mat[i, j] = A_tau(i, j, tau)
end
end
return mat
end
function A_0(r::Number, n::Number)
if r == n
fac = 1
for m in 1:r
fac *= r - (m - 1)
end
return fac
else
return 0.0
end
end
m = Model(optimizer_with_attributes(Mosek.Optimizer, "QUIET" => false, "INTPNT_CO_TOL_DFEAS" => 1e-7))
#variable(m, A[i=1:K+1,j=1:K,k=1:N+1,l=1:N+1])
#variable(m, p[i=1:K+1,j=1:N+1])
# constraint difference might be a small fractional difference.
# assuming that time difference is 1 second starting from 0.
for i in 1:K
#constraint(m, -A_tau_mat(convert(Float64, i-1)) * p[i] .+ A_tau_mat(convert(Float64, i-1)) * p[i+1] .== [0.0, 0.0, 0.0])
end
for i in 1:K+1
#constraint(m, A_tau_mat(convert(Float64, i-1)) * p[i] .== [1.0 12.0 13.0])
end
#constraint(m, A_tau_mat(convert(Float64, K+1)) * p[K+1] .== [0.0 0.0 0.0])
for i in 1:K+1
#objective(m, Min, p[i]' * Q_mat()[i] * p[i])
end
optimize!(m)
println("p value is ", value.(p))
println(A_tau_mat(0.0), A_tau_mat(1.0), A_tau_mat(2.0))
With the standard JuMP you can have only one goal function at a time. Running another #objective macro just overwrites the previous goal function.
Consider the following code:
julia> m = Model(GLPK.Optimizer);
julia> #variable(m,x >= 0)
x
julia> #objective(m, Max, 2x)
2 x
julia> #objective(m, Min, 2x)
2 x
julia> println(m)
Min 2 x
Subject to
x >= 0.0
It can be obviously seen that there is only one goal function left.
However, indeed there is an area in optimization called multi-criteria optimization. The goal here is to find a Pareto-barrier.
There is a Julia package for handling MC and it is named MultiJuMP. Here is a sample code:
using MultiJuMP, JuMP
using Clp
const mmodel = multi_model(Clp.Optimizer, linear = true)
const y = #variable(mmodel, 0 <= y <= 10.0)
const z = #variable(mmodel, 0 <= z <= 10.0)
#constraint(mmodel, y + z <= 15.0)
const exp_obj1 = #expression(mmodel, -y +0.05 * z)
const exp_obj2 = #expression(mmodel, 0.05 * y - z)
const obj1 = SingleObjective(exp_obj1)
const obj2 = SingleObjective(exp_obj2)
const multim = get_multidata(mmodel)
multim.objectives = [obj1, obj2]
optimize!(mmodel, method = WeightedSum())
This library also supports plotting of the Pareto frontier.
The disadvantage is that as of today it does not seem to be actively maintained (however it works with the current Julia and JuMP versions).

How to define a JuMP expression conditional on index value

I am trying to define a #NLexpression in JuMP that has different specifications at different indices. In the below example, I want the expression y[j,k] to be defined as 1/(x[j] - x[k]) when j != k and take some other value when j == k. I can simulate this behavior by defining an auxiliary variable z and adding constraints conditional on index values. Is there a similar way to define expression conditional on index values?
using JuMP, Ipopt
model = JuMP.Model(with_optimizer(Ipopt.Optimizer))
#variable(model, 0 <= x[1:2])
#NLexpression(model, y[j=1:2,k=1:2], 1/(x[j] - x[k])) # <- problematic line
#variable(model, z[1:2,1:2])
for j=1:2, k=1:2
if j == k
#constraint(model, z[j,k] == 1)
else
#NLconstraint(model, z[j,k] == 1/(p[j] - p[k]))
end
end
display(model)
You're not obligated to use JuMP's macros to create containers for expressions. You should be able to conditionally create the expressions as follows:
model = JuMP.Model()
#variable(model, 0 <= x[1:2])
y = Dict() # Or Array, if you prefer.
for j=1:2, k=1:2
if j == k
y[j,k] = 1
else
y[j,k] = #NLexpression(model, 1/(p[j] - p[k]))
end
end

How to sum for all in Julia/JuMP v 1.10

I saw an outdated answer in the following thread (How to do "for all" in sum notation in Julia/JuMP)
which is 3 years old unfortunately, but it's exactly what I want. However the code fails due to a number of syntax errors as the sum() function has changed these past few years.
For my code, I found that the sum() function only works for one indexing variable i, but if I include another variable j, the function stops working. I'm also using jupyter notebook if that makes any difference. Any ideas?
Using JuMP
ZS = Model(with_optimizer(Gurobi.Optimizer))
P = [[10 -20];
[30 -40]]
#variable(ZS, x[1,1:2])
#variable(ZS, y[1:2,1])
#objective(ZS, Max, sum(x[i]*P[i,j]*y[j] for i=1:2 for j=1:2))
#constraint(ZS, con1, x[1] + x[2] <= 1)
#constraint(ZS, con2, y[1] + y[2] <= 1)
optimize!(ZS)
For this example of code, I received a "key not found" error
Seems like you need an update of the for loop syntax and to set your solver to be non-convex.
I also recommend using anonymous labeling for vars, exp etc so that you can change them as required.
using JuMP
using Gurobi
ZS = Model(Gurobi.Optimizer)
set_optimizer_attribute(ZS, "NonConvex", 2)
P = [[10 -20];
[30 -40]]
xs = #variable(ZS, x[1:2])
ys = #variable(ZS, y[1:2])
my_obj = #objective(ZS, Max, sum(x[i]*P[i,j]*y[j] for i in 1:2, j in 1:2))
con1 = #constraint(ZS, x[1] + x[2] <= 1)
con2 = #constraint(ZS, , y[1] + y[2] <= 1)
optimize!(ZS)
Runtime is pretty dang long though...
Change definitions of variables to be one-dimensional like this:
#variable(ZS, x[1:2])
#variable(ZS, y[1:2])
and all should work as expected.
Alternatively leave x and y two dimensional and redefine your objective and constraints like this:
#objective(ZS, Max, sum(x[1,i]*P[i,j]*y[j,1] for i=1:2 for j=1:2))
#constraint(ZS, con1, x[1,1] + x[1,2] <= 1)
#constraint(ZS, con2, y[1,1] + y[2,1] <= 1)
As a side note you can define P more simply like this:
julia> P = [10 -20
30 -40]
2×2 Array{Int64,2}:
10 -20
30 -40

How can I use universal and existential quantification in julia?

I want to code domination definition in Julia. x dom y. x , y are 2 vectors.
b=all(x<=y) && any(x<y)
would you please help me. How can I code this concept in Julia?
Thank you
The simplest approach can be almost like you have specified it:
dom(x, y) = all(x .<= y) && any(x .< y)
You could also use a loop e.g. like this:
function dom(x::AbstractVector, y::AbstractVector)
#assert length(x) == length(y)
wasless = false
for (xi, yi) in zip(x, y)
if xi < yi
wasless = true
elseif xi > yi
return false
end
end
return wasless
end

Julia - Continue outer loop

I am currently porting an algorithm from Java to Julia and now I have come across a part where I have to continue an outer loop from an inner loop when some condition is met:
loopC: for(int x : Y){
for(int i: I){
if(some_condition(i)){
continue loopC;
}
}
}
I have found some issues on GitHub on this topic but there seems to be only a discussion about it and no solution yet. Does anybody know a way how to accomplish this in Julia?
As in some other languages julia uses break for this:
for i in 1:4
for j in 1:4
if j == 2
break
end
end
end
breaks out of the inner loop whenever j is 2
However, if you ever need to exit the outer loop you can use #goto and #label like so
for i in 1:4
for j in 1:4
if (j-i) == 2
#goto label1
end
if j == 2
#goto label2
end
do stuff
end
#label label2
end
#label label1
Straight from the julia docs http://docs.julialang.org/en/release-0.5/manual/control-flow/
It is sometimes convenient to terminate the repetition of a while
before the test condition is falsified or stop iterating in a for loop
before the end of the iterable object is reached. This can be
accomplished with the break keyword
As mentioned by #isebarn, break can be used to exit the inner loop:
for i in 1:3
for j in 1:3
if j == 2
break # continues with next i
end
#show (i,j)
end # next j
end # next i
(i, j) = (1, 1)
(i, j) = (2, 1)
(i, j) = (3, 1)
However, some caution is required because the behaviour of break depends on how the nested loops are specified:
for i in 1:3, j in 1:3
if j == 2
break # exits both loops
end
#show (i,j)
end # next i,j
(i, j) = (1, 1)
See https://en.wikibooks.org/wiki/Introducing_Julia/Controlling_the_flow#Nested_loops
It is also possible, albeit cumbersome, to return from a nested function that contains the inner loop:
for i in 1:3
(i -> for j in 1:3
if j == 2
return
end
#show (i,j)
end)(i)
end
(i, j) = (1, 1)
(i, j) = (2, 1)
(i, j) = (3, 1)

Resources