Re: Re: Two questions about modification of a

*To*: mathgroup at smc.vnet.net*Subject*: [mg101105] Re: [mg101057] Re: [mg101041] Two questions about modification of a*From*: Leonid Shifrin <lshifr at gmail.com>*Date*: Wed, 24 Jun 2009 06:32:19 -0400 (EDT)*References*: <200906220822.EAA09140@smc.vnet.net>

Carl, Andrzej, You are totally right. This one didn't occur to me. Thanks for the hint! Best, Leonid On Tue, Jun 23, 2009 at 6:04 AM, Carl Woll <carlw at wolfram.com> wrote: > Leonid Shifrin wrote: > >> Hi, >> >> Assuming that you store your matrix in a variable <matr>, here is the >> code: >> >> 1. >> >> MapIndexed[If[Times @@ #2 > Length[matr], 0, #1] &, matr, {2}] >> >> 2. >> >> matr /. _?Negative :> 0 >> >> As usual in Mathematica, in both cases above the original matrix has not >> been changed. Rather a new copy of the matrix is created as a result. >> >> If your matrix is large, you can implement the 1. much more efficiently. >> Here is the previous implementation: >> >> In[1] = >> nullify[matr_?MatrixQ] := >> MapIndexed[If[Times @@ #2 > Length[matr], 0, #1] &, matr, {2}] >> >> >> Here is an alternative one using SparseArrays: >> >> In[2] = >> nullifyFast[matr_?MatrixQ] := >> Normal[SparseArray[Thread[# -> Extract[matr, #]]]] &[ >> Flatten[Thread[{#, Range[IntegerPart[Length[matr]/#]]}] & /@ >> Range[Length[matr]], 1]]; >> >> Here is a test matrix: >> >> In[3] = >> largeTestMatr = RandomInteger[{-20, 20}, {400, 400}]; >> >> Compare performance: >> >> In[4] = >> (res1 = nullifyFast[largeTestMatr]); // Timing >> >> Out[4] = >> {0.03, Null} >> >> In[5] = >> (res2 = nullify[largeTestMatr]); // Timing >> >> Out[5] = >> {2.073, Null} >> >> In[6] = >> res1 == res2 >> >> Out[6] = >> true >> >> The solutions have such a dramatic difference in performance (for large >> matrices), since the condition i*j>N is very strong and we only need to >> keep >> a very small (comparing to a total number of matrix elements) subset of >> elements non - zero, and thus in the second solution we can utilize >> efficient built-in Mathematica facilities such as SparseArrays, while the >> first solution is very general and does not utilize the resulting matrix >> structure. >> >> For the second problem, probably the easiest way to speed up code in case >> of large matrices is to use Compile: >> >> nullifyNegativeCompiled = >> Compile[{{matr, _Real, 2}}, >> Module[{i = 1, j = 1, new = matr}, >> For[i = 1, i <= Length[matr], i++, >> For[j = 1, j <= Length[matr], j++, >> If[matr[[i, j]] < 0, new[[i, j]] = 0]]]; >> new]]; >> >> My benchmarks indicate 3-fold speed - up on <largeTestMatr>, with respect >> to >> a rule-based solution. >> >> > A much simpler (and faster) solution is to use Clip: > > Clip[matrix, {0, Infinity}] > > Carl Woll > Wolfram Research > > Regards, >> Leonid >> >> >> On Mon, Jun 22, 2009 at 1:22 AM, Mayasky <alix.zhang at gmail.com> wrote: >> >> >> >>> Suppose there is a N*N matrix. >>> >>> 1. How can I change all elements that satisfy i*j>N to 0 ? (Here i, j >>> is position of this element, as in mat[[i,j]]) >>> >>> 2. How can I change all negative elements in that matrix to 0 ? >>> >>> I know a "for loop" can be used, I just wonder if there is any more >>> concise and beautiful ways. (I doubt Mathematica doesn't have a 'find' >>> function as in another system which conveniently returns indice of >>> elements >>> that satisfy a certain condition) >>>

**References**:**Two questions about modification of a matrix.***From:*Mayasky <alix.zhang@gmail.com>