Vector as matrix coordinates - vector

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

Related

Simulating a probability problem: 3 independent dice

I decided to simulate a probability question from a textbook:
Three fair dice are rolled independently, what is the probability that one dice shows 6 and the other two show two non-equal numbers (and neither is equal 6)
The dice is assumed fair, so "theoretical" answer will be $\frac{\binom{5}{2}}{\binom{6}{3}}=0.5$; I decided to simulate this in Julia, here is the function I wrote for this:
function simulation(n_experiments::Int = 100)
dice = [DiscreteUniform(1, 6) for i in 1:3] # 3 independent fair dice
successes = 0
for trial in 1:n_experiments
experiment = rand.(dice) # roll
one_six = sum(r == 6 for r in experiment) == 1 # check if there is only one "6"
others = filter(num -> num != 6, experiment)
no_duplicates = length(Set(others)) == 2 # check if other two are distinct
if no_duplicates
if one_six
successes += 1 # count "success"
end
end
end
return successes / n_experiments
end
I expected this to return something around 0.5, but in fact it returns ~0.27 after about 10^5 iterations (n_experiments). Can anyone please help me find the flaw in the code?
I think your code is right, but your math wrong:
julia> function simulation(n_experiments=100)
chains = rand.(fill(DiscreteUniform(1, 6), 3), n_experiments)
return (1/n_experiments) * mapreduce(+, chains...) do d1, d2, d3
(d1 == 6 && d2 != 6 && d3 != 6 && d2 != d3) || (d1 != 6 && d2 == 6 && d3 != 6 && d1 != d3) || (d1 != 6 && d2 != 6 && d3 == 6 && d1 != d2)
end
end
simulation (generic function with 1 method)
julia> simulation(10_000)
0.279
julia> count(Iterators.product(1:6, 1:6, 1:6)) do (d1, d2, d3)
(d1 == 6 && d2 != 6 && d3 != 6 && d2 != d3) || (d1 != 6 && d2 == 6 && d3 != 6 && d1 != d3) || (d1 != 6 && d2 != 6 && d3 == 6 && d1 != d2)
end
60
julia> 60 / 6^3
0.2777777777777778
I'd love to see a concise way to encode the condition. I avoided your variant due to allocations, and mine is only verbose make sure it's correct -- but way too long...
Addendum
Here's the optimized variant with a generated condition. Not relevant for the question, but because I find it cool. Credit for the condition formula goes to Bogumił.
julia> #generated function condition(xs::NTuple{N,<:Any}) where {N}
offdiagonals = ((i, j) for i = 1:N for j = (i+1):N)
names = Symbol.(:xs, 1:N)
assignments = [:($(names[i]) = xs[$i]) for i = 1:N]
comparisons = [:($(names[i]) != $(names[j])) for (i, j) in offdiagonals]
condition = Expr(:&&, :(maximum(xs) == 6), comparisons...)
return quote
$(assignments...)
$condition
end
end
condition (generic function with 1 method)
julia> #code_warntype condition((1,2,3))
MethodInstance for condition(::Tuple{Int64, Int64, Int64})
from condition(xs::Tuple{Vararg{var"#s17", N}} where var"#s17") where N in Main at REPL[71]:1
Static Parameters
N = 3
Arguments
#self#::Core.Const(condition)
xs::Tuple{Int64, Int64, Int64}
Locals
xs3::Int64
xs2::Int64
xs1::Int64
Body::Bool
1 ─ (xs1 = Base.getindex(xs, 1))
│ (xs2 = Base.getindex(xs, 2))
│ (xs3 = Base.getindex(xs, 3))
│ %4 = Main.maximum(xs)::Int64
│ %5 = (%4 == 6)::Bool
└── goto #7 if not %5
2 ─ %7 = (xs1 != xs2)::Bool
└── goto #6 if not %7
3 ─ %9 = (xs1 != xs3)::Bool
└── goto #5 if not %9
4 ─ %11 = (xs2 != xs3)::Bool
└── return %11
5 ─ return false
6 ─ return false
7 ─ return false
julia> function simulation(n_experiments=100)
(1/n_experiments) * sum(1:n_experiments) do _
dice = (rand(1:6), rand(1:6), rand(1:6))
condition(dice)
end
end
simulation (generic function with 2 methods)
julia> #time simulation(10_000_000)
0.157303 seconds
0.2777498
This has no allocations at all. sum is exactly as fast as a manual loop!

"How to make the summation to a specific period in 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

I need to find the 9th positive integer that is a multiple of 4, 13, 14, 26, and 50 using python:

Why doesn't this code work? I am getting a continuous loop...
solution = 0
multiple = 0
max_bound = 100000
i = 1
while i < max_bound:
if (i % 4 == 0) and (i % 13 == 0) and (i % 14) and (i % 26 == 0) and (i % 50 == 0):
multiple += 1
if multiple == 9:
solution = i
break
i += 1
if multiple == 9:
print("#1 : 9th Multiple ::", "Correct." if solution == 81900 else ("Wrong: " + str(solution)))
You just missed the 14 verification you used (1 % 14) instead of (i % 14 == 0) which returns 0(False) when the number is divisible by 14 instead of True and with the and operator it doesn't enter the if statement.
solution = 0
multiple = 0
max_bound = 100000
i = 1
while i < max_bound:
if (i % 4 == 0) and (i % 13 == 0) and (i % 14 == 0) and (i % 26 == 0) and (i % 50 == 0):
multiple += 1
if multiple == 9:
solution = i
break
i += 1
if multiple == 9:
print("#1 : 9th Multiple ::", "Correct." if solution == 81900 else ("Wrong: " + str(solution)))

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

Non Decreasing Number Combinations (Interval)

So my problem is the following:
Given a number X of size and an A (1st number), B(Last number) interval, I have to find the number of all different kind of non decreasing combinations (increasing or null combinations) that I can build.
Example:
Input: "2 9 11"
X = 2 | A = 9 | B = 11
Output: 8
Possible Combinations ->
[9],[9,9],[9,10],[9,11],[10,10],[10,11],[11,11],[10],[11].
Now, If it was the same input, but with a different X, line X = 4, this would change a lot...
[9],[9,9],[9,9,9],[9,9,9,9],[9,9,9,10],[9,9,9,11],[9,9,10,10]...
Your problem can be reformulated to simplify to just two parameters
X and N = B - A + 1 to give you sequences starting with 0 instead of A.
If you wanted exactly X numbers in each item, it is simple combination with repetition and the equation for that would be
x_of_n = (N + X - 1)! / ((N - 1)! * X!)
so for your first example it would be
X = 2
N = 11 - 9 + 1 = 3
x_of_n = 4! / (2! * 2!) = 4*3*2 / 2*2 = 6
to this you need to add the same with X = 1 to get x_of_n = 3, so you get the required total 9.
I am not aware of simple equation for the required output, but when you expand all the equations to one sum, there is a nice recursive sequence, where you compute next (N,X) from (N,X-1) and sum all the elements:
S[0] = N
S[1] = S[0] * (N + 1) / 2
S[2] = S[1] * (N + 2) / 3
...
S[X-1] = S[X-2] * (N + X - 1) / X
so for the second example you give we have
X = 4, N = 3
S[0] = 3
S[1] = 3 * 4 / 2 = 6
S[2] = 6 * 5 / 3 = 10
S[3] = 10 * 6 / 4 = 15
output = sum(S) = 3 + 6 + 10 + 15 = 34
so you can try the code here:
function count(x, a, b) {
var i,
n = b - a + 1,
s = 1,
total = 0;
for (i = 0; i < x; i += 1) {
s *= (n + i) / (i + 1); // beware rounding!
total += s;
}
return total;
}
console.log(count(2, 9, 11)); // 9
console.log(count(4, 9, 11)); // 34
Update: If you use a language with int types (JS has only double),
you need to use s = s * (n + i) / (i + 1) instead of *= operator to avoid temporary fractional number and subsequent rounding problems.
Update 2: For a more functional version, you can use a recursive definition
function count(x, n) {
return n < 1 || x < 1 ? 0 : 1 + count(n - 1, x) + count(n, x - 1);
}
where n = b - a + 1

Resources