On 11/09/2017 23:15, Kiran Kedlaya wrote:
When you use the ModularForms constructor to create a space of modular
forms, the backend computation of things like Hecke operators is carried
out using the ModularSymbols class. Would it make sense to be able to
provide the constructor with an optional argument specifying a different
backend, such as one of the following? (ModularSymbols would remain as the
default.)

+1
It is not clear (at least for me) what are the performances of each of them.

-- CremonaModularSymbols is a separate implementation of modular symbols
derived from Cremona's code for tabulating modular elliptic curves.
-- BrandtModules implements the "method of graphs" operating on ideal
classes in a quaternionic order.
-- Pari recently added a "method of trace formulas".
-- Possibly coming soon: Birch's variant of the method of graphs based on
reduction of quadratic forms (see https://trac.sagemath.org/ticket/23342).
-- Did I miss something obvious?

There are plenty of caveats here. For one, these methods don't all apply at
the same level of generality, or offer the same feature set even in cases
of overlapping applicability. For another, some of these methods are
working with different constructions that produce isomorphic Hecke modules,
but not "the same" (i.e., not canonically isomorphic) underlying spaces.

How simple is it to compute a non canonical isomorphism for the Hecke modules?

You might want to try several approaches concerning the organization of the code

A) Inheritance


B) A class with an attribute _backend. Each backend should provide a fixed API (with possibly some method raising `NotImplementedError`). This ensures the compatibility between the different backends even if some of them are not fully functionals. This is how it is for Graph/DiGraph in Sage.


C) A master class with distinct possible backends (each one being initalized at the time they are needed)

class ModularForms:

  @lazy_attribute
  def _backend_cremona(self)

  @lazy_attribute
  def _backend_modular_symbols(self)

  def compute_something(self, backend='default')
    # compute something with the given backend
    # if backend=='default' try to find the optimal one based on
    # what is already computed and the time it would take to
    # get it
    # if the computation is not doable with the given
    # backend, raises an error

In order to be able to force the usage of a given backend by default, you might add an extra _default_backend='cremona' to let the Cremona's version to have precedence when backend='default'.


Vincent

--
You received this message because you are subscribed to the Google Groups 
"sage-nt" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send an email to [email protected].
Visit this group at https://groups.google.com/group/sage-nt.
For more options, visit https://groups.google.com/d/optout.

Reply via email to