MathGroup Archive 2009

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

Search the Archive

Re: Two questions about modification of a matrix.

  • To: mathgroup at smc.vnet.net
  • Subject: [mg101057] Re: [mg101041] Two questions about modification of a matrix.
  • From: Leonid Shifrin <lshifr at gmail.com>
  • Date: Tue, 23 Jun 2009 07:03:21 -0400 (EDT)
  • References: <200906220822.EAA09140@smc.vnet.net>

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.

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: laptop recommendation to run mathematica fast?
  • Next by Date: Re: Needs[], BeginPackage[], filename
  • Previous by thread: Re: Two questions about modification of a matrix.
  • Next by thread: Re: Re: Two questions about modification of a matrix.