2

I want to construct a big matrix where the input of the matrix element is based on the relation between the row indices and column indices.

Here's an example of what I tried but did not work:

f[n_] := n
g[m_] := m    
W[n_, m_] /; f[n] == g[m] := 1
W[n_, m_] /; f[n] != g[m]: = 2
Table[W[n, m], {n, 1, 4}, {m, 1, 4}]

I also tried the following (using the variable n on the LHS instead of f[n]), and it worked.

f[n_] := n
g[m_] := m       
W[n_, m_] /; n == g[m]: = 1
W[n_, m_] /; n != g[m] := 2
Table[W[n, m], {n, 1, 4}, {m, 1, 4}]

But that's not what I want since the relation between the indices is a bit complicated.

Is there any way to put a condition with a function on the LHS?

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
YYing
  • 125
  • 6

1 Answers1

3

For larger matrix sizes, the following should be more efficient as f and g have to be evaluated less often.

n = 4; 
ConstantArray[1, {n, n}] + Unitize[Outer[Subtract, f /@ Range[n], g /@ Range[n], 1]]

Another possibility is this:

n = 4;
SparseArray[{n_, m_} /; f[n] == g[m] :> 1, {n, n}, 2];

This produces a SparseArray which can be converted to a conventional (dense) matrix by applying Normal.

For really huge matrix (n in the millions), some additional work pays off:

With[{nf = Nearest[f /@ Range[n] -> Automatic]},
 SparseArray[
  Join @@ MapThread[ Thread@*List, {nf[g /@ Range[n], {∞, 0}], Range[n]}] -> 1,
  {n, n},
  2
  ]
 ]
Henrik Schumacher
  • 106,770
  • 7
  • 179
  • 309