On Fri, Aug 26, 2011 at 7:38 AM, Greg Sterijevski <gsterijevski@gmail.com>wrote:
> Ted,
>
> When you say
>
> "Functions are good, but giving a tiny bit
> more information to the function is also a great idea"
>
> do you mean information on indexing and shape of the data?
>
I meant the location of the element. For instance, it would be super simple
to define Hilbert's matrix if you had extra arguments to the function:
Matrix a = new DenseMatrix(10,10).assign(new ElementFunction() {
public double eval(int i, int j, double value) { return 1.0 / (1 + i
+ j); }
}
Without the indexes, you are reduced to writing loops. With the indexes,
you have a very concise functional definition.
I have missed this more than once in Mahout.
> One thought I had, I am not sure if this is 100% applicable is the
> following:
>
> 1. You have two types of data (in matrix) : structured and sparse.
> 2. Structured data is a collection of elements that fits a certain pattern.
> Some of which are
> i.) General matrix, stored rowwise
> ii.) General matrix, stored columnwise
> iii.) Diagonal matrix
>
Note that this is really just a special kind of sparse matrix.
> iii.) Upper/Lower triangular
> iv.) Symmetric stored in either upper triangular or lower triangular
> compressed format
> v.) Banded
>
And so is this a kind of sparse matrix.
> The visitor should know the pattern and be given an indexer function.
Why?
Can you adduce a use case for knowing the pattern inside the visitor? Isn't
it true that most special cases fall into two situations:
 the caller knows and can instantiate a special function fit for the
purpose? For instance, in computing an SVD, you *know* that you have a
bidiagonal form at some point. You don't need to discover this.
 standard sparse techniques work fine. For instance, if you do have a
banded matrix that just does the normal sparse thing for adding and
multiplying, don't you get what you want?
While I think that this breakdown pretty much covers it for elementwise
functions, this clearly doesn't apply to functions of an entire matrix. If
you are doing an SVD, you may find it very advantageous to handle, say
orthornormal matrices or diagonal offsets of a previous decomposition or
banded forms specially.
> The pattern designation eliminates superfluous calls to the indexer. You
> would
> not ask for element i,j when i ne j, if the matrix is diagonal.
I think that I need to see a use case to respond.
In general, you *do* need to see all the elements. For instance, suppose
that I am setting all elements of a matrix to (a_ij + 1)^2 or taking the
cosine of all elements.
It might be that you want to have a specialized assignment for just some
elements. Or you might want to have a strange kind of view that just
doesn't have some elements.
> ... The sparse structure is very important, but since you are unsure of how
> the
> sparseness occurs, whether there is a pattern or not, you could make blind
> calls to the indexer, or the indexer itself could be class (in this case)
> which returns to you a collection of acceptable tuples ( eg, element
> locations which might or might not be zero...)
>
This is abstract enough that I don't know how to relate this to use cases.
Can you provide a specific example?
If I want to do something to just the diagonal elements, I generally use the
viewDiagonal method. I can imagine a viewNonZero(double epsilon) which
gives a view that is a matrix whose purpose in life is to restrict the scope
of the assign operation, but I usually just use the iterateNonZero element
iterator for those cases.
> In cases of very small problems, Luc's 3x3 or 6x6 matrix, it makes sense to
> have subclasses of the general matrix, with rows and columns fixed to be 3
> or 6, respectively.
>
Absolutely true. It might even pay to automatically generate special cases
for known important sizes (3x3, yes, 4x4, yes, 6x6, yes, 3x5, probably not).
