More efficient way of calculating this recurrence relation in Mathematica - recursion

Verbeia opened up a rather interesting discussion on the performance of the functional programming style in Mathematica. It can be found here: What is the most efficient way to construct large block matrices in Mathematica?)
I'm working on a problem, and after doing some timing of my code one particularly time consuming portion is where I calculate entries of a matrix through a recurrence relation:
c = Table[0, {2L+1}, {2L+1}];
c[[1, 1]] = 1;
Do[c[[i, i]] = e[[i - 1]] c[[i - 1, i - 1]], {i, 2, 2 L + 1}];
Do[c[[i, 1]] = (1 - e[[i - 1]]) c[[i - 1, 1]], {i, 2, 2 L + 1}];
Do[c[[i, j]] = (1 - e[[i - 1]]) c[[i - 1, j]] +
e[[i - 1]] c[[i - 1, j - 1]], {i, 2, 2 L + 1}, {j, 2, i - 1}];
Where e is some externally defined list. Is there any way I could write this in a more efficient manner? I can't seem to find any obvious way of using the built in functions to accomplish this in a more idiomatic and efficient way.
I realize I can only do so much, since this code is O(n^2), but I have a series of matrix multiplications (About 6 in all) that, combined, take less time to run than this statement. Anything I can do to speed this up even slightly would make an appreciable difference in run times for me.
Update:
In line with what acl recommended, I tried using Compile to speed up my expressions. For a relatively small L = 600, I get 3.81 seconds on the naive Do[...], 1.54 seconds for plain old Compile, and 0.033 seconds for Compile[..., CompilationTarget->"C"].
For a more realistic size of L = 1200, the timings become 16.68, 0.605, and 0.132 for Do, Compile and Compile[.., CompilationTarget->"C"] respectively. I'm able to achieve the same 2 orders of magnitude speedup that acl mentioned in his post.

Try Compile. Here I define 3 functions: f as you defined it, fc compiled (to some sort of bytecode) and fcc compiled to C (look up the documentation as to how to examine the generated code).
First, make mma tell us if something can't be compiled:
SetSystemOptions["CompileOptions"->"CompileReportExternal"->True]
then the functions:
ClearAll[f];
f=Function[{ell,e},
Module[{c=Table[0,{2ell+1},{2ell+1}]},
c[[1,1]]=1;
Do[c[[i,i]]=e[[i-1]] c[[i-1,i-1]],{i,2,2 ell+1}];
Do[c[[i,1]]=(1-e[[i-1]]) c[[i-1,1]],{i,2,2 ell+1}];
Do[c[[i,j]]=(1-e[[i-1]]) c[[i-1,j]]+e[[i-1]] c[[i-1,j-1]],
{i,2,2 ell+1},{j,2,i-1}];
c
]
];
ClearAll[fc];
fc=Compile[{{ell,_Integer},{e,_Integer,1}},
Module[{c},
c=Table[0,{2ell+1},{2ell+1}];
c[[1,1]]=1;
Do[c[[i,i]]=e[[i-1]] c[[i-1,i-1]],{i,2,2 ell+1}];
Do[c[[i,1]]=(1-e[[i-1]]) c[[i-1,1]],{i,2,2 ell+1}];
Do[c[[i,j]]=(1-e[[i-1]]) c[[i-1,j]]+e[[i-1]] c[[i-1,j-1]],
{i,2,2 ell+1},{j,2,i-1}];
c
]
];
ClearAll[fcc];
fcc=Compile[{{ell,_Integer},{e,_Integer,1}},
Module[{c},
c=Table[0,{2ell+1},{2ell+1}];
c[[1,1]]=1;
Do[c[[i,i]]=e[[i-1]] c[[i-1,i-1]],{i,2,2 ell+1}];
Do[c[[i,1]]=(1-e[[i-1]]) c[[i-1,1]],{i,2,2 ell+1}];
Do[c[[i,j]]=(1-e[[i-1]]) c[[i-1,j]]+e[[i-1]] c[[i-1,j-1]],
{i,2,2 ell+1},{j,2,i-1}];
c
],
CompilationTarget->"C",
RuntimeOptions->"Speed"
];
no errors, so it's OK. And now test (these on a macbook with a 2.4GHz core 2 duo running on battery):
ell=400;
e=RandomInteger[{0,1},2*ell];
f[ell,e];//Timing
fc[ell,e];//Timing
fcc[ell,e];//Timing
giving
{2.60925, Null}
{0.092022, Null}
{0.022709, Null}
so the version compiled to C is two orders of magnitude faster here.
If you change the types and get compilation errors, ask.
EDIT: If e contains reals, try
ClearAll[fc];
fc=Compile[{{ell,_Integer},{e,_Real,1}},
Module[{c},
c=Table[0.,{2ell+1},{2ell+1}];
c[[1,1]]=1;
Do[c[[i,i]]=e[[i-1]] c[[i-1,i-1]],{i,2,2 ell+1}];
Do[c[[i,1]]=(1-e[[i-1]]) c[[i-1,1]],{i,2,2 ell+1}];
Do[c[[i,j]]=(1-e[[i-1]]) c[[i-1,j]]+e[[i-1]] c[[i-1,j-1]],
{i,2,2 ell+1},{j,2,i-1}];
c
]
];
ClearAll[fcc];
fcc=Compile[{{ell,_Integer},{e,_Real,1}},
Module[{c},
c=Table[0.,{2ell+1},{2ell+1}];
c[[1,1]]=1;
Do[c[[i,i]]=e[[i-1]] c[[i-1,i-1]],{i,2,2 ell+1}];
Do[c[[i,1]]=(1-e[[i-1]]) c[[i-1,1]],{i,2,2 ell+1}];
Do[c[[i,j]]=(1-e[[i-1]]) c[[i-1,j]]+e[[i-1]] c[[i-1,j-1]],
{i,2,2 ell+1},{j,2,i-1}];
c
],
CompilationTarget\[Rule]"C",
RuntimeOptions\[Rule]"Speed"
];
instead.
One can get a feel for how this works by saying
Needs["CompiledFunctionTools`"]
CompilePrint[fc]
and obtaining
2 arguments
18 Integer registers
6 Real registers
3 Tensor registers
Underflow checking off
Overflow checking off
Integer overflow checking on
RuntimeAttributes -> {}
I0 = A1
T(R1)0 = A2
I12 = 0
I1 = 2
I3 = 1
I14 = -1
R0 = 0.
Result = T(R2)2
1 I11 = I1 * I0
2 I11 = I11 + I3
3 I7 = I1 * I0
4 I7 = I7 + I3
5 I17 = I12
6 T(R2)2 = Table[ I11, I7]
7 I15 = I12
8 goto 13
9 I16 = I12
10 goto 12
11 Element[ T(R2)2, I17] = R0
12 if[ ++ I16 < I7] goto 11
13 if[ ++ I15 < I11] goto 9
14 R1 = I3
15 Part[ T(R2)2, I3, I3] = R1
16 I4 = I1 * I0
17 I4 = I4 + I3
18 I5 = I3
19 goto 26
20 I10 = I5 + I14
21 I8 = I10
22 R4 = Part[ T(R1)0, I8]
23 R5 = Part[ T(R2)2, I8, I8]
24 R4 = R4 * R5
25 Part[ T(R2)2, I5, I5] = R4
26 if[ ++ I5 < I4] goto 20
27 I4 = I1 * I0
28 I4 = I4 + I3
29 I5 = I3
30 goto 40
31 I10 = I5 + I14
32 I13 = I10
33 R4 = Part[ T(R1)0, I13]
34 R5 = - R4
35 R4 = I3
36 R4 = R4 + R5
37 R5 = Part[ T(R2)2, I13, I3]
38 R4 = R4 * R5
39 Part[ T(R2)2, I5, I3] = R4
40 if[ ++ I5 < I4] goto 31
41 I4 = I1 * I0
42 I4 = I4 + I3
43 I5 = I3
44 goto 63
45 I6 = I5 + I14
46 I17 = I3
47 goto 62
48 I16 = I5 + I14
49 I9 = I16
50 R4 = Part[ T(R1)0, I9]
51 R2 = R4
52 R4 = - R2
53 R5 = I3
54 R5 = R5 + R4
55 R4 = Part[ T(R2)2, I9, I17]
56 R5 = R5 * R4
57 I16 = I17 + I14
58 R4 = Part[ T(R2)2, I9, I16]
59 R3 = R2 * R4
60 R5 = R5 + R3
61 Part[ T(R2)2, I5, I17] = R5
62 if[ ++ I17 < I6] goto 48
63 if[ ++ I5 < I4] goto 45
64 Return
with the names of the registers indicating their type etc. You can also look at the generated C code if you use the "C" option (but that is a bit harder to read).

Given that e is already defined (as mentioned in your comment), you can get the first two steps like this:
firsttwosteps = DiagonalMatrix[FoldList[#1 * #2&, 1, e]] +
ArrayFlatten[{{ {{0}} , {Table[0,{2L}]} },
{Transpose[{Rest# FoldList[(1-#2)#1 &,1,e]}], Table[0,{2L},{2L}]}}]
That is, you set up the diagonal and the first column as required in two matrices and add them. This works because the only dependency of the second step on the first step is the element at position {1,1}.
The third step is a little trickier. If you want a purely functional solution, then it's a case of two FoldLists. And you might find it easier to build firsttwosteps in transposed form, and then transpose the upper-triangular result into a lower-triangular final result.
firsttwostepsT = DiagonalMatrix[FoldList[#1 * #2&, 1, e]] +
ArrayFlatten[{{ {{0}} ,{Rest# FoldList[(1-#2)#1 &,1,e]} },
{ Table[0,{2L}, {1}], Table[0,{2L},{2L}]}}]
And then:
Transpose # FoldList[With[{cim1 = #1},
Most#FoldList[(1 - #2[[1]]) #1 + #2[[1]] #2[[2]] &, 0.,
Transpose[{Join[e, {0}], cim1}]]] &, First#firsttwostepsT, Join[e, {0}]]
In the check I did, this preserved the diagonal of firsttwostepsT and produces an upper triangular matrix before it's transposed.
The reason your code is slow is that you are repeated redefining the same entire matrix by defining individual parts. As a general principle, you almost never need Do loops and ReplacePart type constructs in Mathematica. There is almost always a better way.

Related

Hmmm Assembly Fibonacci Sequence

I need to write and print out the Fibonacci sequence up to a given integer (can choose yourself)
I have to do this in Hmmm... Assembly
It gets stuck in infinite recursion, but I have no idea why
00 read r4 # User input
01 setn r4 -1 # adds -1 to r4
02 setn r1 1 # r1 == 1
03 setn r2 0 # r2 == 0
04 setn r5 1 # used as the first number of the fibonacci sequence
05 write r5 # 1
06 jeqzn r4 13 # if r4 == 0, the fibonacci sequence stops
07 add r3 r1 r2 # r3 = r1 + r2
08 addn r4 -1 # r4 = r4 -1
09 copy r2 r1 # r2 now equals r1
10 copy r1 r3 # r1 nog equals r3
11 write r3 # prints fibonacci number
12 jumpn 06 # checks if r4 == 0
13 halt # stops
current output:
1
1
2
3
5
8
13
21
34
55
89
144
233
377
..
..
Wanted output (example): if input (r4) = 10
1
1
2
3
5
8
13
21
34
55
08 addn r4 -1 (r4 should eventually end up being 0)
06 jeqzn r4 13 (should check when it's true, and it should halt)
What prevents it from halting?
Looks like line 1 sets r4 (the input) to -1 instead of the desired subtracting 1, so it should be addn r4 -1.
It's also worth noting the current implementation is iterative and not recursive, and the loop doesn't appear to be infinite but just really long as it would have to count down from -1 to wrap around to 0 (assuming addn does not saturate).

Julia Key Error when accessing a value in dictionary

When trying to run this code Julia keeps giving me the error message "KeyError: key 18=>63 not found" anytime I try to access demand[i]. It seems that this error happens every time the element in dem is larger than 50.
using JuMP, Clp
hours = 1:24
dem = [43 40 36 36 35 38 41 46 49 48 47 47 48 46 45 47 50 63 75 75 72 66 57 50]
demand = Dict(zip(hours, dem))
m = Model(solver=ClpSolver())
#variable(m, x[demand] >= 0)
#variable(m, y[demand] >= 0)
for i in demand
if demand[i] > 50
#constraint(m, y[i] == demand[i])
else
#constraint(m, x[i] == demand[i])
end
end
Not sure how to solve this issue.
You are using a Python-style for x in dict. In Julia, this iterates over the key-value pairs of the dictionary, not the keys. Try
for i in keys(demand)
if demand[i] > 50
#constraint(m, y[i] == demand[i])
else
#constraint(m, x[i] == demand[i])
end
end
or
for (h, d) in demand
if d > 50
#constraint(m, y[h] == d)
else
#constraint(m, x[h] == d)
end
end
This worked for me, using Julia 1.0
using JuMP, Clp
hours = 1:24
dem = [43 40 36 36 35 38 41 46 49 48 47 47 48 46 45 47 50 63 75 75 72 66 57 50]
demand = Dict(zip(hours, dem))
m = Model()
setsolver(m, ClpSolver())
#variable(m, x[keys(demand)] >= 0)
#variable(m, y[keys(demand)] >= 0)
for (h, d) in demand
if d > 50
#constraint(m, y[h] == d)
else
#constraint(m, x[h] == d)
end
end
status = solve(m)
println("Objective value: ", getobjectivevalue(m))
println("x = ", getvalue(x))
println("y = ", getvalue(y))
REF:
Reply of #Fengyang Wang
Comment of #Wikunia at https://stackoverflow.com/a/51910619/1096140
https://jump.readthedocs.io/en/latest/quickstart.html

Rolling queue size

I want to calculate number of items waiting or queued over. Let's say, I have fixed capacity of 102 item/hour and different incoming items for 9 hours.
as data table:
dt<-data.table(hour = c(1,2,3,4,5,6,7,8,9),
incoming = c(78,102,115,117,105,99,91,80,71),
capacity = rep(102,9))
I want to calculate queued items in each period.
In 1 and 2 capacity is enough and queue is 0.
In 3, 13 items are queued
In 4, 15+13 backlogged items are queued.
In 6, there were 31 backlogged items and 3 items are deducted so 28 were queued.
I have tried several options but could not figure out how to calculate.
Result should be:
Explicit looping in R won't get you far, and I don't see a vectorized solution for this, but this is trivial to solve using Rcpp:
library(Rcpp)
cppFunction("NumericVector queue(NumericVector x) {
NumericVector res(x.size());
res[0] = std::max<double>(0, x[0]);
for (int i = 1, size = x.size(); i < size; ++i) {
res[i] = std::max<double>(0, res[i-1] + x[i]);
}
return res;
}")
dt[, queued := queue(incoming - capacity)][]
# hour incoming capacity queued
#1: 1 78 102 0
#2: 2 102 102 0
#3: 3 115 102 13
#4: 4 117 102 28
#5: 5 105 102 31
#6: 6 99 102 28
#7: 7 91 102 17
#8: 8 80 102 0
#9: 9 71 102 0
I'd create a separate function to get queued number like #sebastian-c did, but with #R.S. 's logic. Like this
get_queue <- function(x){
n <- length(x)
y <- c(max(0, x[[1]]), rep(0, n - 1))
for(i in 2:n){
y[i] <- max(0, y[i - 1] + x[i])
}
y
}
And then
dt[,incoming_capacity := incoming - capacity]
dt[,queued := get_queue(incoming_capacity)]
Another alternative:
require(data.table)
dt<-data.table(hour = c(1,2,3,4,5,6,7,8,9),
incoming = c(78,102,115,117,105,99,91,80,71),
capacity = rep(102,9))
dt$incoming_capactity<- dt$incoming-dt$capacity
dt$carriedover<- 0
dt$carriedover[1]<- max(0,dt$incoming_capactity[1]) #added
for( i in 2:length(dt$carriedover)) {
dt$carriedover[i]<- max(0,dt$incoming_capactity[i] + dt$carriedover[i-1])
}
dt

Deleting multiple columns in R

I have a dataframe df with column names from m1 to m100
I want to delete columns in the range m50 to m100. Is there a faster way to do it than hardcoding it
df <- subset(df_cohort, select = -c("M50","M51","M52","M53"......,"M100") )
With dplyr you could do it like this:
library(dplyr)
df <- select(df, -(M50:M100))
This removes all columns between column "M50" and column "M100".
A different option, that does not depend on the order of columns is to use
df <- select(df, -num_range("M", 50:100))
Assuming you have something like:
mydf <- data.frame(matrix(1:100, ncol = 100,
dimnames = list(NULL, paste0("m", 1:100))))
Simply do:
mydf[paste0("m", 50:100)] <- list(NULL) ## This is pretty destructive ;-)
By the way, you can also do:
subset(mydf, select = m1:m49)
or
subset(mydf, select = -(m50:m100))
More eloquently put, without using any external packages or extra function calls, just use R's logical subsets:
mydf <- data.frame(matrix(1:100, ncol = 100,
dimnames = list(NULL, paste0("M", 1:100))))
mydf[,1:49]
yielding:
> mydf[,1:49]
m1 m2 m3 m4 m5 m6 m7 m8 m9 m10 m11 m12 m13 m14 m15 m16 m17 m18 m19 m20 m21 m22
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
m23 m24 m25 m26 m27 m28 m29 m30 m31 m32 m33 m34 m35 m36 m37 m38 m39 m40 m41 m42
1 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
m43 m44 m45 m46 m47 m48 m49
1 43 44 45 46 47 48 49
We can assign the columns to NULL in data.table
library(data.table)
setDT(df_cohort)[, paste0('M', 50:100) := NULL]
If we need to subset,
setDT(df_cohort)[, setdiff(names(df_cohort),
paste0('m', 50:100)), with=FALSE]

if 13* D = 1 mod 60 then D = 37 how?

I am solving an example problem, RSA algorithm
I have been given two prime numbers 7 and 11. Let's say p=7 and q=11
I have to calculate the decryption key, d, for some encryption key, e.
Firstly I calculated n=p*q which implies that n=77.
Suppose that e=13,
to calculate d I used the formula d*e = 1 mod fi,
where fi=(p-1)(q-1), and so fi=60
The final equation becomes 13*d = 1 mod fi
According to some solved example
d is calculated to be 37, how is this result obtained?
Any help would be appreciated.
i think this is what you are looking for
Verifying the answer is easy, finding it in the first place, a little more work.
Verification:
13 * 37 = 481
481 = 8 * 60 + 1
Hence if you divide 13 * 37 by 60 you have remainder 1.
Alternate answers:
Any integer of the form (37 + 60 k) where k is any integer is also a solution. (97, -23, etc.)
To find the solution you can proceed as follows:
Solve:
13 d = 1 + 60 k
mod 13:
0 = 1 + 8k (mod 13)
8k = -1 (mod 13)
Add 13's until a multiple of 8 is found:
8k = 12 or 25 or 38 or 51 or 64 .... aha a multiple of 8!
k = 64 / 8 = 8
Substitute k = 8 back into 13 d = 1 + 60 k
13 d = 1 + 8 * 60 = 481
481 /13 = 37
and that is the answer.
Use the extended Euclidean algorithm to compute integers x and y such that
13*x+60*y=1
Then x is the answer you're looking for, mod 60.

Resources