2

The sparse function in MATLAB does the following:

S = sparse(i,j,v) generates a sparse matrix S from the triplets i, j, and v such that S(i(k),j(k)) = v(k). The max(i)-by-max(j) output matrix has space allotted for length(v) nonzero elements. sparse adds together elements in v that have duplicate subscripts in i and j. If the inputs i, j, and v are vectors or matrices, they must have the same number of elements. Alternatively, the argument v and/or one of the arguments i or j can be scalars.

I would like to have a fairly equivalent function in Mathematica. Has anyone tried to do this beforehand?

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
Mirko Aveta
  • 2,192
  • 11
  • 26

2 Answers2

5

Mathematica has sparse arrays not just sparse matrices:

Here are links to some tutorials:

The ability to use high-dimensional sparse array sometimes is very useful. (E.g. see "Markov chains n-gram model implementation".)

Most competitors of Mathematica support only sparse matrices.

Yifan Hu and Robert Knapp were the original designers of the functionality. I mention Yifan because before moving to Wolfram Research he worked with some of the originators and creators of the sparse matrices field (like John Reid).

Anton Antonov
  • 37,787
  • 3
  • 100
  • 178
4

While comparing the results of MATLAB and Mathematica for a little experiment the other day, I got bitten by an error, which in hindsight was because I did not pay attention to this part of the help file for MATLAB's sparse():

sparse adds together elements in v that have duplicate subscripts in i and j.

As a demonstration, here's a small MATLAB example:

il = [1 2 2 3];
jl = [1 2 2 3];
vv = [5 1 -1 4];
full(sparse(il, jl, vv))
ans =
      5     0     0
      0     0     0
      0     0     4

The ostensible Mathematica equivalent is

Normal[SparseArray[{{1, 1} -> 5, {2, 2} -> 1, {2, 2} -> -1, {3, 3} -> 4}]]
   {{5, 0, 0},
    {0, 1, 0},
    {0, 0, 4}}

Did you notice the difference? As previously noted, MATLAB adds up entries with the same indices, and you thus get 0 as the middle of the diagonal matrix. Mathematica, OTOH, retains the first one.

In fact, this behavior is controlled by the internal setting "TreatRepeatedEntries":

SystemOptions["SparseArrayOptions" -> "TreatRepeatedEntries"]
   {"SparseArrayOptions" -> {"TreatRepeatedEntries" -> First}}

(See e.g. this thread and this thread, among others.)

To get behavior similar to MATLAB, we need to modify this setting. If you are wary of modifying internal settings like these, the device of this answer can be used to localize this effect:

With[{spopt = SystemOptions["SparseArrayOptions"]}, 
     Internal`WithLocalSettings[
              SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" -> Total}],
              Normal[SparseArray[{{1, 1} -> 5, {2, 2} -> 1, {2, 2} -> -1, {3, 3} -> 4}]],
              SetSystemOptions[spopt]]]
   {{5, 0, 0},
    {0, 0, 0},
    {0, 0, 4}}

and we now get the same result as MATLAB.

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
  • 1
    For code that relies on "NonzeroPositions" and the like, note in the last example, the {2, 2} entry is listed among the "NonzeroPositions". Use SparseArray[ SparseArray[{{1, 1} -> 5, {2, 2} -> 1, {2, 2} -> -1, {3, 3} -> 4}]] to reset. – Michael E2 May 11 '20 at 17:19
  • The issue noted by Michael has also been discussed in other threads, like this one. – J. M.'s missing motivation May 11 '20 at 17:26