"How to make the summation to a specific period in Julia?" - julia

I am formulating mathematical programming and now I have an issue with the summation sign in a constraint. I want to sum over the specific period in a planning horizon, I have tried some but Julia report an error message.
the mathematical formula looks somewhat like this:
constraint1
and this:constraint2
here is some code I have tried:
Horizon = 12
Section = 5
TBetPM = [4 6 9 8 5]
LPM = [1 4 5 4 4]
MaxPM = [9 8 7 10 6]
PrevPM = [3 3 2 5 2]
tam=zeros(Float64,1,5)
for i=1:Section
tam[i] = TBetPM[i]-LPM[i]
end
tar = zeros(Float64,1,5)
for i=1:Section
tar[i] = Pi[i]*(MaxPM[i]-PrevPM[i])-LPM[i]
end
#constraint(mod, [i=1:Section],
sum(m[i,t] for t=1:Horizon if t<=tam[i]) >= 1
)
#constraint(mod, [i=1:Section],
sum(r[i,t] for t=1:Horizon if t<=tar[i]) >= 1
)
I also tried these but both does not work
#constraint(mod, [i=1:Section],
sum(m[i,t] for t=1:tam[i]) >= 1
)
#constraint(mod, [i=1:Section],
sum(r[i,t] for t=1:tar[i]) >= 1
)
Thank you in advance for all the answers :)

You used a model mod in your #constraint macro. It wasn't defined. You must create it if you use JuMP.
using JuMP
mod = Model()
You previsouly initialized tam and tar as two dimensionnal arrays of size 1x5 (matrices). I think you needed a one dimensional array as you accessed them as vectors :
tam = zeros(Float64,5)
tar = zeros(Float64,5)
You didn't defined the variables m and r in your model :
#variable(mod, m[i=1:Section, t=1:Horizon])
#variable(mod, r[i=1:Section, t=1:Horizon])
Finally, you might want JuMP to solve your model, this can be done with :
using GLPK # feel free here to use the solver you prefer
optimize!(mod, with_optimizer(GLPK.Optimizer))
And printing the solutions :
if termination_status(mod) == MOI.OPTIMAL
optimal_solution = value.(m), value.(r)
optimal_objective = objective_value(mod)
#show optimal_solution
#show optimal_objective
else
error("The model was not solved correctly.")
end
Whole working code (Julia v1.1.0, JuMP v0.19.0, GPLK v0.9.1):
Horizon = 12
Section = 5
TBetPM = [4 6 9 8 5]
LPM = [1 4 5 4 4]
MaxPM = [9 8 7 10 6]
PrevPM = [3 3 2 5 2]
using JuMP
using GLPK # feel free here to use the solver you prefer
mod = Model()
tam = zeros(Float64,5)
for i in 1:Section
tam[i] = TBetPM[i]-LPM[i]
end
tar = zeros(Float64,5)
for i=1:Section
tar[i] = pi*(MaxPM[i] - PrevPM[i]) - LPM[i]
end
#variable(mod, m[i=1:Section, t=1:Horizon])
#variable(mod, r[i=1:Section, t=1:Horizon])
#constraint(mod, [i=1:Section],
sum(m[i,t] for t in 1:Horizon if t <= tam[i]) >= 1)
#constraint(mod, [i=1:Section],
sum(r[i,t] for t in 1:Horizon if t <= tar[i]) >= 1)
# Solve model and printing solution
optimize!(mod, with_optimizer(GLPK.Optimizer))
if termination_status(mod) == MOI.OPTIMAL
optimal_solution = value.(m), value.(r)
optimal_objective = objective_value(mod)
#show optimal_solution
#show optimal_objective
else
error("The model was not solved correctly.")
end
I don't know if it's because of a copy/paste or something else, but you should indent your code even if it's not mandatory to compile it :p

Thank you for the reply, J.Khamphousone.
Here is the full code I have tried:
using JuMP, CPLEX, Gurobi, GLPKMathProgInterface
sex = Model(solver = GurobiSolver())
Horizon = 12
Section = 5
TBetPM = [4 6 9 8 5]
TlastPM = [0 0 0 0 0]
MaxPM = [9 8 7 10 6]
PrevPM = [3 3 2 5 2]
taf1=zeros(Float64,1,5)
for i=1:Section
taf1[i] = TBetPM[i]-TlastPM[i]
end
tafr1 = zeros(Float64,1,5)
for i=1:Section
tafr1[i] = TBetPM[i]*(MaxPM[i]-PrevPM[i])-TlastPM[i]
end
tafr = zeros(Float64,1,5)
for i=1:Section
tafr[i] = TBetPM[i]*MaxPM[i]
end
mdur = [9 6 8 10 3]
rdur = [18 16 23 16 12]
Maxdur = 24
mcost = [2 6 5.5 4 4]
rcost = [6 15 20 18 25]
scost = [0.6 1.17 0.81 0.66 1.4]
pcost = 2
ccost = 0.001
Ncus = 100
#variable(sex, m[1:Section,1:Horizon]>=0, Bin) # 1 if section s maintain in week h
#variable(sex, r[1:Section,1:Horizon]>=0, Bin) # 1 if section s renew in week h
#variable(sex, p[1:Horizon]>=0,Bin) #1 if possession in week h
#objective(sex, Min, sum(pcost*p[t] for t=1:Horizon)+
sum(mcost[i]*m[i,t] for t=1:Horizon, i=1:Section)+
sum(rcost[i]*r[i,t] for t=1:Horizon, i=1:Section)
)
#select first maintenance time (correct)
#constraint(sex, [i=1:Section],
sum(m[i,t] for t=1:Horizon if t==taf1[i]) >= 1
)
#select next maintenance time (correct)
#constraint(sex, [i=1:Section, k=1:(Horizon-TBetPM[i])],
sum(m[i,t] for t=1+k:TBetPM[i]+k) >= 1
)
#select first renewal time
#constraint(sex, [i=1:Section],
sum(r[i,t] for t in tafr1[i]) >= 1
)
#select next renewal time
#constraint(sex, [i=1:Section, k=1:(Horizon-tafr[i])],
sum(r[i,t] for t=1+k:tafr[i]+k) >= 1
)
# if there is maintenance, there is possession
#constraint(sex, [i=1:Section, h=1:Horizon],
m[i,h] <= p[h]
)
# if there is renewal, there is possession
#constraint(sex, [i=1:Section, h=1:Horizon],
r[i,h] <= p[h]
)
solve(sex)
#print(sex)
mVal = getvalue(m)
for i=1:Section, t=1:Horizon
if (mVal[i,t] ==1)
println("section[$i] repair in period [$t]", )
end
end
rVal = getvalue(r)
for i=1:Section, t=1:Horizon
if (rVal[i,t] ==1)
println("section[$i] renew in period [$t]", )
end
end

Related

Dijkstra's algorithm with adjacency matrix

I'm trying to implement the following code from here but it won't work correctly.
What I want is the shortest path distances from a source to all nodes and also the predecessors. Also, I want the input of the graph to be an adjacency matrix which contains all of the edge weights.
I'm trying to make it work in just one function so I have to rewrite it. If I'm right the original code calls other functions (from graph.jl for example).
I don't quite understand how to rewrite the for loop which calls the adj() function.
Also, I'm not sure if the input is correct in the way the code is for now.
function dijkstra(graph, source)
node_size = size(graph, 1)
dist = ones(Float64, node_size) * Inf
dist[source] = 0.0
Q = Set{Int64}() # visited nodes
T = Set{Int64}(1:node_size) # unvisited nodes
pred = ones(Int64, node_size) * -1
while condition(T)
# node selection
untraversed_nodes = [(d, k) for (k, d) in enumerate(dist) if k in T]
if minimum(untraversed_nodes)[1] == Inf
break # Break if remaining nodes are disconnected
end
node_ind = untraversed_nodes[argmin(untraversed_nodes)][2]
push!(Q, node_ind)
delete!(T, node_ind)
# distance update
curr_node = graph.nodes[node_ind]
for (neigh, edge) in adj(graph, curr_node)
t_ind = neigh.index
weight = edge.cost
if dist[t_ind] > dist[node_ind] + weight
dist[t_ind] = dist[node_ind] + weight
pred[t_ind] = node_ind
end
end
end
return dist, pred
end
So if I'm trying it with the following matrix
A = [0 2 1 4 5 1; 1 0 4 2 3 4; 2 1 0 1 2 4; 3 5 2 0 3 3; 2 4 3 4 0 1; 3 4 7 3 1 0]
and source 2 i would like to get the distances in a vector dist and the predeccessors in anothe vectore pred.
Right now I'm getting
ERROR: type Array has no field nodes
Stacktrace: [1] getproperty(::Any, ::Symbol) at .\sysimg.jl:18
I guess I have to rewrite it a bit more.
I m thankful for any help.
Assuming that graph[i,j] is a length of path from i to j (your graph is directed looking at your data), and it is a Matrix with non-negative entries, where 0 indicates no edge from i to j, a minimal rewrite of your code should be something like:
function dijkstra(graph, source)
#assert size(graph, 1) == size(graph, 2)
node_size = size(graph, 1)
dist = fill(Inf, node_size)
dist[source] = 0.0
T = Set{Int}(1:node_size) # unvisited nodes
pred = fill(-1, node_size)
while !isempty(T)
min_val, min_idx = minimum((dist[v], v) for v in T)
if isinf(min_val)
break # Break if remaining nodes are disconnected
end
delete!(T, min_idx)
# distance update
for nei in 1:node_size
if graph[min_idx, nei] > 0 && nei in T
possible_dist = dist[min_idx] + graph[min_idx, nei]
if possible_dist < dist[nei]
dist[nei] = possible_dist
pred[nei] = min_idx
end
end
end
end
return dist, pred
end
(I have not tested it extensively, so please report if you find any bugs)

Torch - Query matrix with another matrix

I have a m x n tensor (Tensor 1) and another k x 2 tensor (Tensor 2) and I wish to extract all the values of Tensor 1 using indices based on Tensor 2. For example;
Tensor1
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
[torch.DoubleTensor of size 4x5]
Tensor2
2 1
3 5
1 1
4 3
[torch.DoubleTensor of size 4x2]
And the function would yield;
6
15
1
18
The first solution that comes into mind is to simply loop through indexes and pick the correspoding values:
function get_elems_simple(tensor, indices)
local res = torch.Tensor(indices:size(1)):typeAs(tensor)
local i = 0
res:apply(
function ()
i = i + 1
return tensor[indices[i]:clone():storage()]
end)
return res
end
Here tensor[indices[i]:clone():storage()] is just a generic way to pick an element from a multi-dimensional tensor. In k-dimensional case this is exactly analogous to tensor[{indices[i][1], ... , indices[i][k]}].
This method works fine if you don't have to extract lots of values (the bottleneck is :apply method which is not able to use many optimization techniques and SIMD instructions because the function it executes is a black box). The job can be done way more efficiently: the method :index does exactly what you need... with a one-dimensional tensor. Multi-dimensional target/index tensors need to be flattened:
function flatten_indices(sp_indices, shape)
sp_indices = sp_indices - 1
local n_elem, n_dim = sp_indices:size(1), sp_indices:size(2)
local flat_ind = torch.LongTensor(n_elem):fill(1)
local mult = 1
for d = n_dim, 1, -1 do
flat_ind:add(sp_indices[{{}, d}] * mult)
mult = mult * shape[d]
end
return flat_ind
end
function get_elems_efficient(tensor, sp_indices)
local flat_indices = flatten_indices(sp_indices, tensor:size())
local flat_tensor = tensor:view(-1)
return flat_tensor:index(1, flat_indices)
end
The difference is drastic:
n = 500000
k = 100
a = torch.rand(n, k)
ind = torch.LongTensor(n, 2)
ind[{{}, 1}]:random(1, n)
ind[{{}, 2}]:random(1, k)
elems1 = get_elems_simple(a, ind) # 4.53 sec
elems2 = get_elems_efficient(a, ind) # 0.05 sec
print(torch.all(elems1:eq(elems2))) # true

How to do "for all" in sum notation in Julia/JuMP

I am trying to add constraints to a linear optimization problem in Julia using JuMP. I am using the sum{} function however, I am having trouble with some of the constraints. Does anyone know how to write "for all" in JuMP (the upside down A)? Here is the code I have so far:
using JuMP
m = Model()
c= [3 5 2 ; 4 3 5 ; 4 5 3 ; 5 4 3 ; 3 5 4]
#variable(m, x[i=1:5,j=1:3] >= 0)
#objective(m,Min,sum{c[i,j]*x[i,j],i=1:5,j=1:3})
for i=1:5
#constraint(m, sum{x[i,j],i,j=1:3} <= 480)
end
What I am trying to get is this:
I am trying to use the for loop as a substitute of "for all i from 1 to 5" however I keep getting errors. Is there another way to do this?
In mathematical notation, you sum across i, and do so for each j.
In Julia/JuMP, you can think of "∀" as being a for loop ("for all"),
and a "Σ" as being a sum{ }:
using JuMP
m = Model()
c= [3 5 2;
4 3 5;
4 5 3;
5 4 3;
3 5 4]
# x_ij >= 0 ∀ i = 1,...,5, j = 1,...,3
#variable(m, x[i=1:5,j=1:3] >= 0)
#objective(m,Min,sum{c[i,j]*x[i,j],i=1:5,j=1:3})
# ∀j = 1,...,3
for j in 1:3
#constraint(m, sum{x[i,j],i=1:5} <= 480)
end

Vector as matrix coordinates

See https://stackoverflow.com/questions/41810306/appointment-scheduling....
You example does not work. You are indexing the second element twice (by the way, a nice alternative to your floor (rand (n) * x) is to use randi()):
octave> M = randi(10, 3)
M =
9 2 5
9 3 1
2 8 7
octave> v = [2;2];
octave> M(v)
ans =
9
9
octave> M([2;2])
ans =
9
9
The right way to do what you want is to use sub2ind() which works for any number of dimensions.
octave> M(sub2ind (size (M), 2, 2))
ans = 3
octave> M = randi (10, 3, 3, 3)
M =
ans(:,:,1) =
6 3 10
1 7 9
7 6 8
ans(:,:,2) =
7 9 10
9 4 5
8 5 5
ans(:,:,3) =
3 5 10
8 3 10
4 9 4
octave> M(sub2ind (size (M), 1, 2, 3))
ans = 5
I edited the sub2ind function so it can take a vector.
works like this:
M(sub2ind2(dims, V));
I will probably send the modified sub2ind2 function on the next days.
[EDIT]
function ind = sub2ind2 (dims, varargin)
if (nargin > 1)
if (isvector (dims) && all (round (dims) == dims))
nd = length (dims);
v = varargin{1};
vlen = length (v)
dims(vlen) = prod (dims(vlen:nd));
dims(vlen+1:nd) = [];
scale = cumprod (dims(:));
for i = 1:vlen
arg = v(i);
if (isnumeric (arg) && isequal (round (arg), arg))
if (i == 1)
if (all (arg(:) > 0 & arg(:) <= dims(i)))
ind = first_arg = arg;
else
error ("sub2ind: index out of range");
endif
else
if (size_equal (first_arg, arg))
if ((i > nd && arg == 1) || all (arg(:) > 0 & arg(:) <= dims(i)))
ind += scale(i-1) * (arg - 1);
else
error ("sub2ind: index out of range");
endif
else
error ("sub2ind: all index arguments must be the same size");
endif
endif
else
error ("sub2ind: expecting integer-valued index arguments");
endif
endfor
else
error ("sub2ind: expecting dims to be an integer vector");
endif
else
print_usage ();
endif
endfunction

What math do I need to convert numbers according to this table?

Given an X, what math is needed to find its Y, using this table?
x
y
0
1
1
0
2
6
3
5
4
4
5
3
6
2
This is a language agnostic problem. I can't just store the array, and do the lookup. The input will always be the finite set of 0 to 6. It won't be scaling later.
This:
y = (8 - x) % 7
This is how I arrived at that:
x 8-x (8-x)%7
----------------
0 8 1
1 7 0
2 6 6
3 5 5
4 4 4
5 3 3
6 2 2
int f(int x)
{
return x["I#Velcro"] & 7;
}
0.048611x^6 - 0.9625x^5 + 7.340278x^4 - 26.6875x^3 + (45 + 1/9)x^2 - 25.85x + 1
Sometimes the simple ways are best. ;)
It looks like:
y = (x * 6 + 1) % 7
I don't really like the % operator since it does division so:
y = (641921 >> (x*3)) & 7;
But then you said something about not using lookup tables so maybe this doesn't work for you :-)
Update:
Since you want to actually use this in real code and cryptic numbers are not nice, I can offer this more maintainable variant:
y = (0x2345601 >> (x*4)) & 15;
Though it seems a bunch of correct answers have already appeared, I figured I'd post this just to show another way to have worked it out (they're all basically variations on the same thing):
Well, the underlying pattern is pretty simple:
x y
0 6
1 5
2 4
3 3
4 2
5 1
6 0
y = 6 - x
Your data just happens to have the y values shifted "down" by two indices (or to have the x values shifted "up").
So you need a function to shift the x value. This should do it:
x = (x + 5) % 7;
Resulting equation:
y = 6 - ((x + 5) % 7);
Combining the ideas in Dave and Paul's answer gives the rather elegant:
y = (8 - x) % 7`
(though I see I was beaten to the punch with this)
unsigned short convertNumber(unsigned short input) {
if (input <= 1) { return !input; } //convert 0 => 1, 1 => 0
return (8-input); //convert 2 => 6 ... 6 => 2
}
Homework?
How about:
y = (x <= 1 ? 1 : 8) - x
and no, i dont/cant just store the array, and do the lookup.
Why not?
yes, the input will always be the finite set of 0 to 6. it wont be scaling later.
Just use a bunch of conditionals then.
if (input == 0) return 1;
else if (input == 1) return 0;
else if (input == 2) return 6;
...
Or find a formula if it's easy to see one, and it is here:
if (input == 0) return 1;
else if (input == 1) return 0;
else return 8 - input;
Here's a way to avoid both modulo and conditionals, going from this:
y = (8 - x) % 7
We know that x % y = x - floor(x/y)*y
So we can use y = 8 - x - floor((8 - x) / 7) * 7
What about some bit-fu ?
You can get the result using only minus, logical operators and shifts.
b = (x >> 2) | ((x >> 1) & 1)
y = ((b << 3)|(b ^ 1)) - x

Resources