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

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.

   1 symbol A("A"), i_sym("i"), j_sym("j");
   2 idx i_idx(i_sym, 3), j_idx(j_sym, 4);
   3 ex s = indexed(A, i, j).sum();

vs.

   1 var('A i j')
   2 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.

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.

   1 symbol i_dim("__stmt627_A_dim_i"), j_dim("__stmt627_A_dim_j");  // unique symbol names
   2 idx i_idx(i_sym, i_dim), j_idx(j_sym, j_dim);
   3 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

   1 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().

   1 A[i,j].dimension(3, 4})  # positional syntax is simple, but not always clear
   2 A[i,j].dimension({i:3, j:4})  # hash syntax allows specifying the index 
   3         # expression to be dimensioned
   4 A[i,j].dimension(i=3, j=4)  # keyword syntax is similar, but may have problems 
   5         # with general expression indexes
   6 A[i,j].dimension(i==3, j==4)  # relation syntax is similar to substitution 
   7         # syntax; perhaps confusingly, this would sum ``i`` over 0,1,2 and 
   8         # *not* 3 -- so i==3 is the first value that is *not* included in the 
   9         # sum
  10 A[i,j].dimension(0<=i<3, 0<=j<4)  # more complex relation syntax shows exactly 
  11         # which values are included in the sum, but not sure if GiNaC can 
  12         # 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.

Any other ides?