MathGroup Archive 2009

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re: Two questions about modification of


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



  • Prev by Date: Re: Green's Function for Fresnel Reflection?
  • Next by Date: Re: Re: Two questions about modification of a
  • Previous by thread: Re: Re: Two questions about modification of a matrix.
  • Next by thread: Re: Re: Two questions about modification of a