This page discusses an interface for implementing indexed GiNaC expressions in Sage/Pynac.

<<TableOfContents()>>

== Background ==
See the thread

http://groups.google.com/group/sage-devel/browse_thread/thread/69ab50fe11672111

for the impetus of this page.  I will repeat here that the original author of this page (Ryan Hinton) is *not* an expert at Sage or GiNaC.  Consequently, there are likely syntactic and semantic errors below.  Feel free to edit, comment, or discuss any of my mistakes.

== General idea ==
My best idea is to use Python's indexing notation and hook {{{__getitem__()}}} for Pynac expressions.  (Is this already done?)  So the following GiNaC C++ and Sage Python code should do essentially the same thing.
{{{#!cplusplus
symbol A("A"), i_sym("i"), j_sym("j");
idx i_idx(i_sym, 3), j_idx(j_sym, 4);
ex s = indexed(A, i, j).sum();
}}}
vs.
{{{#!python
var('A i j')
s = A[i,j].sum(3,4)
}}}

== Detailed ideas ==
=== Index dimensions ===
I like the {{{A[...]}}} indexing syntax, but the dimensions are missing.  There are three obvious approaches for specifying dimensions.

 * Cram them into the indexing syntax, e.g. {{{A[(i,3), (j,4)]}}}.
 * Specify the dimensions in a separate method call, e.g. {{{A[i,j].dimension(3,4)}}}.  The final result should be the same as a GiNaC indexed expression.
 * Specify them when they are used, e.g. {{{A[i,j].sum(3,4)}}}.  

RWH does *not* like cramming the dimensions into the indexing syntax.  Instead, specifying the dimensions when they are used seems most natural to RWH, but he has a shallow understanding and no experience with the GiNaC approach.  

In fact, the dimensioning method call and specify-on-use approaches can coexist.  Since GiNaC requires the dimension to be specified when the indexed expression is created, both cases require defining *implicit* dimensions.  So {{{A[i,j]}}} might translate to the following C++ code.
{{{#!cplusplus
symbol i_dim("__stmt627_A_dim_i"), j_dim("__stmt627_A_dim_j");  // unique symbol names
idx i_idx(i_sym, i_dim), j_idx(j_sym, j_dim);
return indexed(A, i_idx, j_idx);
}}}
Later, when we know the desired dimensions (e.g. in the {{{dimension()}}} or {{{sum()}}} method), we can substitute the actual dimensions.  We can use the indexed expression whether or not the indixes are explicitly dimensioned.  For example, {{{A[i,j].sum()}}} would return the 2-D sum over the implicit dimensions.  We could even give the implicit dimensions nice LaTeX names, e.g. the GiNaC equivalent of the Sage pseudocode
{{{#!python
var('__stmt627_A_dim_i', latex_name='N_{%s,%s}'%(A._latex_(), i_sym._latex_()))
}}}

=== Specifying index dimensions ===
There are several options for the syntax specifying the index dimensions.  These ideas apply equally to the calling convention for {{{sum()}}} and {{{dimension()}}}.
{{{#!python
A[i,j].dimension(3, 4})  # positional syntax is simple, but not always clear
A[i,j].dimension({i:3, j:4})  # hash syntax allows specifying the index 
        # expression to be dimensioned
A[i,j].dimension(i=3, j=4)  # keyword syntax is similar, but may have problems 
        # with general expression indexes
A[i,j].dimension(i==3, j==4)  # relation syntax is similar to substitution 
        # syntax; perhaps confusingly, this would sum ``i`` over 0,1,2 and 
        # *not* 3 -- so i==3 is the first value that is *not* included in the 
        # sum
A[i,j].dimension(0<=i<3, 0<=j<4)  # more complex relation syntax shows exactly 
        # which values are included in the sum, but not sure if GiNaC can 
        # handle general dimension ranges
}}}
We should probably include the positional syntax at a minimum.  It will do just fine for only one index, and will probably be easier when trying to specifying the dimensions of a non-trivial index expression.  RWH's next favorite option is the hash syntax.  In all of the non-positional cases there will be issues of figuring out which string/expression matches which index.  RWH assumes facilities exist so this will not be a significant obstacle.

== Operations ==
Indexed expressions should already support addition, multiplication, etc. with other expressions.  Below are ideas for operations specific to indexed expressions.

 * Of course, we should define {{{sum}}} and {{{prod}}} methods to form sums and products, respectively.  
 * (Other operations that use indices?)
 * We could use indexed expressions to create vectors and matrices.  This would probably require new vector and matrix classes to support symbolic dimensions.
 * We could use indexed expressions to create polynomials (over {{{SR}}}).
 * (Other constructions that use indices?)
 * By allowing an infinite dimension, we can take limits of sequences, (sums of) series, etc.  Sequences of functions may fit in the same framework.

Any other ides?