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.