3
$\begingroup$

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!!!

$\endgroup$
4
  • 2
    $\begingroup$ Have you considered using 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 are True. It's not super clear to me what you're doing, but that may be useful. $\endgroup$ Jun 16, 2016 at 17:22
  • $\begingroup$ Can you... explain what you're doing, exactly? Conceptually, I mean. Give us a smaller toy example with an input, an explanation of what you want, and an expected output. $\endgroup$ Jun 16, 2016 at 18:01
  • $\begingroup$ I added all the parameters to run it now. For a better toy model you can scale them down. What i am trying to to is say dataM is a (10x20) iA (10x10) and iB is (20x10) matrix then i wanna iterate through each row so for m=1 we would have positionAB[dataM,iA,1] which is a (9x10) and have Rij[dataM,1] which is a (1x9) matrix then wanna take the dot product of Rij.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$
    – ADDonut
    Jun 16, 2016 at 18:36
  • $\begingroup$ I have also tried to use ParalleleDo but then i have to use SetSharedVariable otherwise it doesn't update iB0[[m]] which makes it even longer $\endgroup$
    – ADDonut
    Jun 20, 2016 at 0:27

1 Answer 1

6
$\begingroup$

You may be going to too much trouble here. Consider that Position works on a matrix just as well as a vector.

You did not include values for your parameters, so I can't use your code, but take a look at the following example. I have a matrix selector that contains $0$ or $1$ entries, and I want to grab the elements of another matrix target that correspond to $1$ elements in the first matrix.

SeedRandom[2016]
selector = RandomChoice[{0, 1}, {10, 10}];
target = RandomInteger[{100, 200}, {10, 10}];

positions = Position[selector, _?Positive]
Extract[target, positions]

This is quite similar to the functionality of Pick, which you may also be interested in.

$\endgroup$
4
  • 2
    $\begingroup$ One could of course use Positive[]. $\endgroup$ Jun 20, 2016 at 6:27
  • $\begingroup$ @J.M. One certainly could, and in fact it may even be better than the explicit test, in that Positive returns False when its input is a complex number, instead of failing and returning unevaluated. My (admittedly inconsequential) gripe with it is that I wish it had been named PositiveQ, rather than just Positive, to fall in line with other predicates such as NumericQ, MatrixQ, VectorQ, etc. Oh well. In any case, I amended my answer. $\endgroup$
    – MarcoB
    Jun 20, 2016 at 16:58
  • 3
    $\begingroup$ Ah, I'll have to differ with you on that. Positive[] is set not to evaluate unless its argument is numeric (satisfies NumericQ[]); this allows it to be used in assumptions (e.g. Simplify[Abs[x], Positive[x]]) among other things. (The behavior is similar to that of the relational operators.) "Query" functions, by way of contrast, are designed never to remain unevaluated. Were there such a thing as PositiveQ[], PositiveQ[x] will return False at once, which may or may not be desired. (Similar arguments for NonNegative[], Negative[], NonPositive[] apply.) $\endgroup$ Jun 20, 2016 at 17:06
  • $\begingroup$ @J.M. Ha! That's an excellent point I had not considered. Thank you for pointing that out! $\endgroup$
    – MarcoB
    Jun 20, 2016 at 17:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.