Skip to content

flatten "fails" on SparseMatrix #3530

@gwhitney

Description

@gwhitney

Describe the bug
The documentation states that flatten returns a 1-dimensional collection. However, since it returns a SparseMatrix when the input is a SparseMatrix, and SparseMatrix cannot represent a 1-dimensional collection, this property is impossible to fulfill.

To Reproduce

const SM = math.sparse([[1],[0]])
const M2 = math.flatten(SM) // this is a no-op, even though the input is two-dimensional!

Discussion

I think the documented property of flatten, that it always return a 1-dimensional result, is the most important property to preserve for computational convenience of mathjs. It is a pain to deal with possibly 2-dimensional outputs of flatten if you happen to get a SparseMatrix to work on. Therefore, one proposal to deal with this issue would be:

  1. Make flatten() an exception to the general principle that mathjs functions that take a collection argument return the same type of collection as the input, and return an array when the input is an array, and a 1-dimensional DenseMatrix otherwise.

However, the principle that the type of argument is preserved is also generally speaking (issue #3529 notwithstanding) also very useful for computation with mathjs, so this issue also possibly suggests an alternate proposal:

  1. Perhaps it's not really semantically consistent for mathjs to have an implementation of Matrix that cannot represent 1-dimensional collections. So instead, enhance SparseMatrix to allow at least for 1-dimensional as well as 2-dimensional collections (if not arbitrary dimensions). Then have flatten() return a 1-dimensional SparseMatrix when its input is a SparseMatrix. Also adjust other instances of return values of SparseMatrix for other functions that would naturally be 1-dimensional. After all, sparse vectors are definitely a thing that one sometimes wants to compute with.

Note that proposal (2) would lead to another possible to solution to issue #3529: if SparseMatrix could represent 1-dimensional collections, then size() could preserve the type of its input while still satisfying the property that inputs of the same size produce results that are deepEqual(). (However, I personally would still recommend having size() return the same type regardless of the type of its argument, on the principle that the size is a property of any collection, and the same property should have the same type for any collection. Just raising the point that allowing 1-dim SparseMatrix would afford a third solution to #3529.)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions