I am trying to optimize my code that searches for elements in the rows of matrix that are greater than 0. Then use that position to grab the element from other matrix. I use the do loop to iterate through each row. Then have another function that creates a new vector to replace that row of the vector. I have read these two questions on stackexchange (Question 1,Question 2) that say to use Map, Scan or NestList instead of for loops, but I am having difficulty applying it to my program. Any suggestions on how to speed this up would be greatly appreciated.
These are my function to search the matrix
positionAB = Function[{dataM, AB, row}, AB[[Flatten[Position[
dataM[[All, row]], x : _ /; x > 0]]]]];
Rij = Function[{dataM, row}, dataM[[Flatten[Position[dataM[[All, row]],
x : _ /; x > 0]], row]]];
randomnFunction=Function[{x,y},(x.y)^2]
My loop is
indexM[data0_, initA0_, initB0_] := Block[
{initA = initA0,
initB = initB0,
data = data0,
iA0, iB0, iAB, id, ir},
iA0 = initA;
iB0 = initB;
id = data;
Do[
iAB = positionAB[id, iA0, m];
ir = Rij[id, m];
ii=randomFunction[ir,iAB];
iB0[[m]]=ii;,
{m, 0, Length[iB0]}
];
]
Everyone says not to use for loops, which is what I originally had so switch to a Do but it has the exact same time to evaluate. Not sure how to use the suggestion in (Question 1,Question 2) for my iteration. Any advice would be greatly appreciated. I have many other numerical iterations using Euler's Algorithm that I have the same issue with.
It pretty large matrices. I have
dataM = RandomInteger[{0, 10}, {2000, 3000}];
iA = RandomReal[{-1, 1}, {2000, 10}];
iB = RandomReal[{-1, 1}, {3000, 10}];
So i have
indexM[dataM,iA,iB]//AbsoluteTiming
Which for each iteration of m creates a 1x10 array. So after the loop the row of iB0 i.e. iB0[[m]]
will be update with the new vector.
Update: I have tried to do the same thing as this numerical method on stack exchange but doesn't help with my row replacement. I have tried MarcoB's suggestion but has gotten very convoluted to to the dot product and of the ir and iAB which is a giant array of arrays of different sizes. Ill update my code i have tried with that soon.
I also tried to use ParallelDo
but doesn't update my iB0 unless I use SetSharedVariable
which makes the computation time longer than my original. Any suggestions to get ParallelDo
to work if i can't use Functional methods?
Update: MarcoB method
dataMatrix = RandomInteger[{0, 2}, {3, 4}];
iA = RandomReal[{-1, 1}, {3, 2}];
iB = RandomReal[{-1, 1}, {4, 2}];
positions = Position[dataMatrix, _?(# > 0 &)]
c = SortBy[GatherBy[positions, Last], Last@*Last][[;; , ;; , 1]]
rij = Select[DeleteCases[0] /@ Transpose[dataMatrix], UnsameQ[#, {}] &]
f = Function[{n, m}, n.m];
AB = Map[(iB[[#, All]]) &, c]
MapThread[f, {rij, AB}]
So I have gotten this but still have trouble dealing with a column that has all zeros.
Update: In some good news if I can over come the zero elements it takes the time down from 69.1293 to 36.64. Not great but something!!! Open for any suggestions!!!
Pick
? You give it two arrays of the same size, and it picks elements out of the first one corresponding to elements in the second which areTrue
. It's not super clear to me what you're doing, but that may be useful. $\endgroup$positionAB[dataM,iA,1]
which is a (9x10) and haveRij[dataM,1]
which is a (1x9) matrix then wanna take the dot product ofRij.postionAB
to get (1x10) matrix and i wanna store this (1x10) matrix in an array where it will be the m entry. And repeat for m iterations. $\endgroup$ParalleleDo
but then i have to useSetSharedVariable
otherwise it doesn't updateiB0[[m]]
which makes it even longer $\endgroup$