In Mahout, all of this works pretty well without needing the information
that you are suggesting.

Inversion is not supported, of course, but a solve method on Diagonal can
definitely know what to do.  See CholeskyDecomposition for an example.
 Addition of a diagonal matrix to a normal matrix works because the abstract
addition method iterates only through non-zeros which gives only the
diagonal elements.

On Fri, Aug 26, 2011 at 4:31 PM, Greg Sterijevski <gsterijev...@gmail.com>wrote:

> Okay, here we go!
>
> Yes, every matrix can be written or considered sparse. My point is that
> knowing the sparsity obeys a pattern (say diagonal) makes your life easier.
>
> Maybe my muddled discussion has added more confusion, an example is in
> order
> (to maximize the entropy, of course). If I was going to build a
> "DiagonalRealMatrix" object,
> I would store the minimum information:
> 1. Data - a vector of n reals
> 2. Indexer -
>    public final int index( i, j ){
>      if( i == j ) return j;
>      return -1;
>    }
>
> Presented the information that D is diagonal (through the Java Type System
> or through a type variable that I explicitly set in the constructor), I
> know
> that some operations can be made very simple. Say I want to take the
> inverse
> of D, in place. The matrix function that takes the inverse doesn't need to
> know much. Something like:
>
> new DiagonalInvertFunction() {
>      public void eval(double[] data) {
>            for( int i = 0 ; i < data.length; i++){
>              data[i] = 1.0/data[i];
>             }
>      }
> }
>
> Would be very quick and scale very well. Contrast this the case where we
> are
> handed a sparse structure and attempt to invert it. Since we are not told
> that it is diagonal, either we need to explicitly test for "diagonality" or
> we proceed with some inversion method that can handle arbitrary forms of
> sparseness. Both approaches (testing or using a sparse invertor) must be
> more expensive? No?
>
> Say that we are adding the diagonal above to a generic matrix (this is a
> bit
> outside of the scope of the discussion). I know, because of the pattern of
> the matrix, I need only make n additions, instead of looping naively
> through
> based on some striding scheme.
>
> Where my idea falls apart is precisely in operations like the one you cite
> below. Say that the user wants to calculate, elementwise, the cosine of
> each
> element in this diagonal matrix. Here the situation is messy because the
> pattern of the data changes. The tidy vector which stores just the diagonal
> elements, is not appropriate since the diagonal matrix now becomes a
> general
> matrix.
>
> In the end, I think I see your point, but, its an empirical question as to
> whether my examples (as archetypes) are more likely to occur in practice
> versus your example.
>
> -Greg
>
>
> On Fri, Aug 26, 2011 at 1:41 PM, Ted Dunning <ted.dunn...@gmail.com>
> wrote:
>
> > On Fri, Aug 26, 2011 at 7:38 AM, Greg Sterijevski <
> gsterijev...@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
> > bi-diagonal 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 element-wise
> > 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).
> >
>

Reply via email to