1
$\begingroup$

I have a matrix Mat1 whos columns are ordered as :

Col = Flatten[Outer[{#2, #1} &, {0, 1}, Delete[Range[-2, 2, 1], 3]], 1]

and the rows are ordered as:

Rows = Flatten[Outer[{#1, #2} &, Delete[Range[-1, 1, 1], 2], Delete[Range[-1, 1, 1], 2]], 1]

The matrix is given as:

Mat1 = Outer[f[Flatten[{#1, #2}]] &, Col, Rows, 1]

$$ \left( \begin{array}{cccc} f(\{-2,0,-1,-1\}) & f(\{-2,0,-1,1\}) & f(\{-2,0,1,-1\}) & f(\{-2,0,1,1\}) \\f(\{-1,0,-1,-1\}) & f(\{-1,0,-1,1\}) & f(\{-1,0,1,-1\}) & f(\{-1,0,1,1\}) \\f(\{1,0,-1,-1\}) & f(\{1,0,-1,1\}) & f(\{1,0,1,-1\}) & f(\{1,0,1,1\}) \\f(\{2,0,-1,-1\}) & f(\{2,0,-1,1\}) & f(\{2,0,1,-1\}) & f(\{2,0,1,1\}) \\ f(\{-2,1,-1,-1\}) & f(\{-2,1,-1,1\}) & f(\{-2,1,1,-1\}) & f(\{-2,1,1,1\}) \\ f(\{-1,1,-1,-1\}) & f(\{-1,1,-1,1\}) & f(\{-1,1,1,-1\}) & f(\{-1,1,1,1\}) \\ f(\{1,1,-1,-1\}) & f(\{1,1,-1,1\}) & f(\{1,1,1,-1\}) & f(\{1,1,1,1\}) \\ f(\{2,1,-1,-1\}) & f(\{2,1,-1,1\}) & f(\{2,1,1,-1\}) & f(\{2,1,1,1\}) \end{array} \right)$$

Another matrix Mat2 with a fewer elements is given as:

Mat2 = Outer[f[Flatten[{#1 , #2}]] &, {{-2, 0}, {1, 0}, {2, 1}}, {{-1, 1}, {1, -1}, {1, 1}}, 1]

$$\left( \begin{array}{ccc} f(\{-2,0,-1,1\}) & f(\{-2,0,1,-1\}) & f(\{-2,0,1,1\}) \\ f(\{1,0,-1,1\}) & f(\{1,0,1,-1\}) & f(\{1,0,1,1\}) \\ f(\{2,1,-1,1\}) & f(\{2,1,1,-1\}) & f(\{2,1,1,1\}) \end{array} \right)$$

I want to make all the elements of the first matrix (Mat1) equal to zero that are not same as elements of Mat2. This will create a kind of a sparse matrix like:

$$\left( \begin{array}{cccc} 0 & f(\{-2,0,-1,1\}) & f(\{-2,0,1,-1\}) & f(\{-2,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & f(\{1,0,-1,1\}) & f(\{1,0,1,-1\}) & f(\{1,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & f(\{2,1,-1,1\}) & f(\{2,1,1,-1\}) & f(\{2,1,1,1\}) \end{array} \right)$$

How can I do this? (and for any general Range of col and Rows)

Edit: Building Mat1 with Outer for a large list of Rows and Col causes my system to hang and removes all variables from Mathematica. Outer carries out the arrangement of the elements at the positions I need in the matrix but it doesn't work for very big dimensions. I am only interested in the final sparse matrix with the elements at the positions dictated by the list of Rows and Col. Is there any way to get the final matrix by somehow using Rows and Col without the need to build Mat1?.

$\endgroup$

3 Answers 3

1
$\begingroup$

Update: An approach to use Col, Rows and the indices used to create Mat2 to get the desired sparse array without creating Mat1:

c2 = {{-2, 0}, {1, 0}, {2, 1}};
r2 = {{-1, 1}, {1, -1}, {1, 1}};
positions = Tuples[{Flatten@Position[Col, #]& /@ c2, Flatten@Position[Rows, #]& /@ r2}];

SparseArray[positions -> Flatten @ Mat2, Length /@ {Col, Rows}] // MatrixForm // TeXForm

$\left( \begin{array}{cccc} 0 & f(\{-2,0,-1,1\}) & f(\{-2,0,1,-1\}) & f(\{-2,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & f(\{1,0,-1,1\}) & f(\{1,0,1,-1\}) & f(\{1,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & f(\{2,1,-1,1\}) & f(\{2,1,1,-1\}) & f(\{2,1,1,1\}) \\ \end{array} \right)$

If you like, you can use f directly without having to use Mat2:

SparseArray[positions -> (f[Flatten[{Col[[#[[1]]]], Rows[[#[[2]]]]}]] & /@ 
     positions), Length /@ {Col, Rows}] // MatrixForm // TeXForm

same result

Original answer:

SparseArray

You can define a function f0 that takes two matrices as input and returns a SparseArray with the desired entries:

ClearAll[f0]
f0[m1_, m2_] := Module[{pos = Position[m1, Alternatives @@ Flatten[m2]]},
   SparseArray[pos -> Extract[m1, pos], Dimensions[m1]]];

f0[Mat1, Mat2] // MatrixForm // TeXForm

$\left( \begin{array}{cccc} 0 & f(\{-2,0,-1,1\}) & f(\{-2,0,1,-1\}) & f(\{-2,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & f(\{1,0,-1,1\}) & f(\{1,0,1,-1\}) & f(\{1,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & f(\{2,1,-1,1\}) & f(\{2,1,1,-1\}) & f(\{2,1,1,1\}) \\ \end{array} \right)$

ReplaceAll

Alternatively, define a function f1 that gives 0 for any input except one that matches elements of Mat2 and use it with ReplaceAll:

ClearAll[f1]
f1[x : Alternatives @@ Flatten[Mat2]] := x
f1[_] := 0;

Mat1 /. a_f :> f1[a] // MatrixForm // TeXForm

same result

You can also Map f1 on Mat1 at level 2:

Map[f1, Mat1, {2}] // MatrixForm // TeXForm

same result

or use it to construct the result directly without creating Mat:

Outer[f1@f[Flatten[{#1, #2}]] &, Col, Rows, 1] // MatrixForm // TeXForm

same result

$\endgroup$
9
  • $\begingroup$ That is a very nice answer but my problem is in using Mat1 when I have a large list of Rows and Col. When I run the code Mat1 = Outer[f[Flatten[{#1, #2}]] &, Col, Rows, 1] my Mathematica hangs and maybe runs out of memory. Is there any way to get the final matrix by somehow using Rows and Col without the need to build Mat1?. Outer carries out the arrangement of the elements at the positions I need but it doesn't work for big dimensions. $\endgroup$
    – jsid
    Sep 20, 2018 at 18:53
  • $\begingroup$ @jsid, please see the update. $\endgroup$
    – kglr
    Sep 20, 2018 at 19:13
  • $\begingroup$ Great. Seems to work really good for now. Let me test it further. $\endgroup$
    – jsid
    Sep 20, 2018 at 19:35
  • $\begingroup$ How time efficient will your method be for a matrix size of 16777216 by 1024, Is there a way to know this?. I had been running your code for an hour now but its still going on. $\endgroup$
    – jsid
    Sep 20, 2018 at 21:27
  • $\begingroup$ @jsid, how big is Mat2? $\endgroup$
    – kglr
    Sep 20, 2018 at 21:35
1
$\begingroup$

Given:

Col = Flatten[Outer[{#2, #1} &, {0, 1}, Delete[Range[-2, 2, 1], 3]], 1];
Rows = Flatten[Outer[{#1, #2} &, Delete[Range[-1, 1, 1], 2], Delete[Range[-1, 1, 1], 2]], 1];

and:

c = {{-2, 0}, {1, 0}, {2, 1}};
r = {{-1, 1}, {1, -1}, {1, 1}};

Mat2 = Outer[f[Flatten[{#1 , #2}]] &, c, r, 1];

You can construct your desired sparse array with:

sparse = Module[{m = SparseArray[{}, {Length[Col], Length[Rows]}]},
    m[[
        Flatten @ Position[Col, Alternatives @@ c, 1],
        Flatten @ Position[Rows, Alternatives @@ r, 1]
    ]] = Mat2;
    m
];

Check:

sparse //MatrixForm //TeXForm

$\left( \begin{array}{cccc} 0 & f(\{-2,0,-1,1\}) & f(\{-2,0,1,-1\}) & f(\{-2,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & f(\{1,0,-1,1\}) & f(\{1,0,1,-1\}) & f(\{1,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & f(\{2,1,-1,1\}) & f(\{2,1,1,-1\}) & f(\{2,1,1,1\}) \\ \end{array} \right)$

$\endgroup$
8
  • $\begingroup$ I would like to ask you the same question as how time efficient will your method be for a matrix size of 16777216 by 1024?. I haven't yet run your code but would soon do. $\endgroup$
    – jsid
    Sep 20, 2018 at 21:31
  • $\begingroup$ @jsid Depends on the dimensions of Mat2. What are they? Or equivalently, what are the lengths of c and r? $\endgroup$
    – Carl Woll
    Sep 20, 2018 at 21:36
  • $\begingroup$ Length of c is 62250 and r is 1024 $\endgroup$
    – jsid
    Sep 20, 2018 at 21:48
  • $\begingroup$ @jsid Those dimensions should not be a problem. What is f? $\endgroup$
    – Carl Woll
    Sep 20, 2018 at 22:02
  • $\begingroup$ f is a function that is needed to be evaluated after the matrix has been formed. Each evaluation of f takes on an average about 0.02 seconds with Absolute Timing. $\endgroup$
    – jsid
    Sep 20, 2018 at 22:05
0
$\begingroup$

The second matrix is more like a list of elements you want to set to zero. Therefore I'd suggest

Mat2List = Flatten[Mat2]
Do[
If[MemberQ[Mat2List,Mat1[[j,i]]],
(*then we are good to go*),
Mat1[[j,i]] = 0
]
, {i, 1, Length[Rows]}, 
{j, 1, Length[Col]}
] 

Which checks for all members of Mat1 whether they are in Mat2

$\endgroup$
1
  • $\begingroup$ Your code is working but when I increase the dimensions of the Rows and Col my Mathematica hangs and all the variables are removed. How can I use this for big matrices?. I only need the final matrix with the zeros and the elements of Mat2 at correct positions in the matrix. I do not need Mat1, is there a way to create such sparse matrix?. $\endgroup$
    – jsid
    Sep 20, 2018 at 17:25

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.