Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the logarithm and the exponential of a Drinfeld module #35260

Merged
merged 31 commits into from
May 22, 2023

Conversation

DavidAyotte
Copy link
Member

📚 Description

The goal of this PR is to implement the logarithm and the exponential of a Drinfeld module.

Background material

Let $\phi:T \mapsto \gamma(T) + g_1 \tau + \cdots + g_r \tau^r$ with $g_r\neq 0$ be a rank $r$ Drinfeld module and let $\Lambda\subset \mathbb{C}_{\infty}$ be the associated rank $r$ lattice. Then recall that the exponential $e_{\phi}:\mathbb{C}_{\infty} \rightarrow \mathbb{C}_{\infty}$ of the Drinfeld module $\phi$ is defined by:

$$ e_{\phi}(z) := z\prod_{\lambda\in \Lambda\setminus {0}} \left( 1 - z/\lambda \right). $$

It can be viewed as a power series in $z$:

$$ e_{\phi}(z) = z + \alpha_1 z^{q} + \alpha_2 z^{q^2} + \alpha_3 z^{q^3} + \cdots $$

Moreover, it satisfies the following functional equation:

$$ e_{\phi}(az) = \phi_a(e_{\phi}(z)). $$

The logarithm of $\phi$ is defined to be the compositional inverse of $e_{\phi}$, denoted $\mathrm{log}_{\phi}$. By applying $\mathrm{log}_{\phi}$ on both side of the functional equation, we obtain the following recurrence relation:

$$ \beta_k = \frac{1}{\gamma(T) - \gamma(T)^{q^i - 1}} \sum_{i = 0}^{k-1} \beta_i g_{k-i}^{q^i} $$

where $\beta_k$ is the $q^k$-th coefficient of $\mathrm{log}_{\phi}$ and $\beta_0 = 1$.

Examples

sage: A = GF(2)['T']
sage: K.<T> = Frac(A)
sage: phi = DrinfeldModule(A, [T, 1])
sage: q = A.base_ring().cardinality()
sage: log = phi.logarithm(); log
z + ((1/(T^2+T))*z^2) + ((1/(T^6+T^5+T^3+T^2))*z^4) + O(z^7)
sage: log[q] == -1/((T**q - T))
True
sage: log[q**2] == 1/((T**q - T)*(T**(q**2) - T))
True
sage: log[q**3] == -1/((T**q - T)*(T**(q**2) - T)*(T**(q**3) - T))
True

Ideas

The idea here is to first compute the logarithm of a Drinfeld module using lazy power series and then compute its compositional inverse to find its exponential.

📝 Checklist

  • I have made sure that the title is self-explanatory and the description concisely explains the PR.
  • I have linked an issue or discussion.
  • I have created tests covering the changes.
  • I have updated the documentation accordingly.

⌛ Dependencies

Depends on #35026 because this PR implements Drinfeld modules.

CC: @xcaruso @ymusleh @kryzar

@DavidAyotte
Copy link
Member Author

DavidAyotte commented Mar 10, 2023

It should be possible to implement the exponential of a Drinfeld module once issue #35261 is fixed.

EDIT (2023-03-13): I found a workaround to the issue mentioned above. Essentially, it consists in computing explicitely the coefficients of the exponential using the the fact that it is the compositional inverse of the logarithm.

@DavidAyotte DavidAyotte marked this pull request as draft March 10, 2023 18:55
@codecov-commenter
Copy link

codecov-commenter commented Mar 11, 2023

Codecov Report

Patch coverage: 100.00% and project coverage change: -0.03 ⚠️

Comparison is base (f449b14) 88.62% compared to head (01d620d) 88.60%.

❗ Current head 01d620d differs from pull request most recent head 643cfde. Consider uploading reports for the commit 643cfde to get more accurate results

Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #35260      +/-   ##
===========================================
- Coverage    88.62%   88.60%   -0.03%     
===========================================
  Files         2148     2146       -2     
  Lines       398653   397860     -793     
===========================================
- Hits        353308   352512     -796     
- Misses       45345    45348       +3     
Impacted Files Coverage Δ
...function_field/drinfeld_modules/drinfeld_module.py 97.05% <100.00%> (+1.02%) ⬆️

... and 67 files with indirect coverage changes

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@kryzar
Copy link
Contributor

kryzar commented Mar 13, 2023

Great! I'm not an expert but I'd be happy to review the code!

@DavidAyotte
Copy link
Member Author

Great! I'm not an expert but I'd be happy to review the code!

If you want a good grasp of these objects, I suggest that you read the chapter on the Carlitz module of Goss's book (chapter 3) and then section 4.6 for the general case.

@xcaruso xcaruso requested review from kryzar and xcaruso March 13, 2023 13:56
@mantepse
Copy link
Collaborator

Since #35261 is fixed, could you please recheck? The method from #35261 should be faster, or at least not slower.

@DavidAyotte
Copy link
Member Author

Since #35261 is fixed, could you please recheck? The method from #35261 should be faster, or at least not slower.

Yes it works now, thanks! Beforehand I used your workaround by using the option valuation=1 in the element constructor. I was wondering if it's best to keep it or not? Looking at the documention of Lazy series, I'm not sure what this parameter does exactly.

@mantepse
Copy link
Collaborator

Ok, thanks for the feedback, I have to explain the parameter better then in the Dichtring.

For now: it is any lower bound on the minimal degree (aka valuation) of the series. It is mostly optional, in many cases the code will figure it out by itself. But if it is known it does not hurt to supply it.

@mantepse
Copy link
Collaborator

Do I understand correctly that the exponential of a Drinfeld module is not a Drinfeld module (but a sequence of Drinfeld modules)?

@mantepse
Copy link
Collaborator

Can you see a relation to sage.rings.lazy_series_ring.LazyCompletionGradedAlgebra?

@DavidAyotte
Copy link
Member Author

DavidAyotte commented Apr 14, 2023

Do I understand correctly that the exponential of a Drinfeld module is not a Drinfeld module (but a sequence of Drinfeld modules)?

Yes and no. The exponential of a Drinfeld module is not a Drinfeld module, but it is not a sequence of Drinfeld module either. Let $F$ be a $\mathbb{F}_q[T]$-algebra which is a field. A Drinfeld $\mathbb{F}_q[T]$-module over $F$ is really just a morphism of $\mathbb{F}_q$-algebra determined by $\phi : T \mapsto \phi_T:=\iota(T) + g_1 \tau + \cdots + g_r \tau^r$ where $\tau:x \mapsto x^q$ is the $q$-Frobenius, $g_i\in F$, $g_r\neq 0$ and $\iota : \mathbb{F}_q[T]\rightarrow F$ is the algebra structure morphism.

In particular a Drinfeld $\mathbb{F}_q[T]$-module is determined by the list $[\iota(T), g_1, \ldots, g_r]$ and that's how they are represented in sagemath.

Suppose that $F = C$ is an algebraically closed and complete extension of the rational function field $\mathbb{F}_q(T)$, then there exists a map $e_{\phi} : C \rightarrow C$ which is $\mathbb{F}_q$-linear, entire and surjective. Moreover, it satisfy the functional equation: $e_{\phi}(ax) = \phi_a(e_{\phi}(x))$. This map is the exponential of the Drinfeld module $\phi$ and, by its properties, it is a power series: $\sum_{i\geq 0} a_i z^{q^i}$. The logarithm is the compositional inverse of the exponential.

However, I did explained the things a bit backward here, because given a Drinfeld module described by $[\iota(T), g_1, \ldots, g_r]$, it is actually easier to first compute the logarithm using a recurrence relation on the list elements and then compute the compositional inverse of the logarithm to obtain the exponential.

I hope this gives you a better understanding of what's going on here!

@DavidAyotte
Copy link
Member Author

What do you mean with "Ore power series"?

It's a bit unknown, but I mean the power series version of an Ore polynomial. However, I think this would require a bit of work to implement in SageMath.

Yes, it is exactly what I had in mind when I wrote: "I think that there are still some place for optimization but it's not obvious and will be for another ticket." :-)

What I don't really like about using this form $1 + \sum_{i} \alpha_i \tau^i$ ("Ore power series") over this one $z + \sum_i \alpha_i z^{q^i}$ ("standard") is that manipulating the power series will give wrong result as SageMath won't treat the variable $\tau$ as the Frobenius. So, just to be sure that I understand correctly: do you suggest to keep the standard form in this ticket?

@xcaruso
Copy link
Contributor

xcaruso commented May 4, 2023

Yes!
And for another ticket (maybe): implement Ore powers series and add an option to logarithm and exponential to let them return Ore powers series instead of actual series.

@mantepse
Copy link
Collaborator

mantepse commented May 4, 2023

What do you mean with "Ore power series"?

It's a bit unknown, but I mean the power series version of an Ore polynomial. However, I think this would require a bit of work to implement in SageMath.

Am I mistaken that the only thing you'd need to do is to put OrePolynomialRing into GradedAlgebrasWithBasis?

@DavidAyotte
Copy link
Member Author

What do you mean with "Ore power series"?

It's a bit unknown, but I mean the power series version of an Ore polynomial. However, I think this would require a bit of work to implement in SageMath.

Am I mistaken that the only thing you'd need to do is to put OrePolynomialRing into GradedAlgebrasWithBasis?

Can you expand a bit on this idea? Do you mean to do something like this:

sage: A = GF(3)['T']
sage: K.<T> = Frac(A)
sage: L = OrePolynomialRing(K, K.frobenius_endomorphism())
sage: GradedAlgebrasWithBasis(L)
...

@mantepse
Copy link
Collaborator

mantepse commented May 4, 2023

Can you expand a bit on this idea? Do you mean to do something like this:

sage: A = GF(3)['T']
sage: K.<T> = Frac(A)
sage: L = OrePolynomialRing(K, K.frobenius_endomorphism())
sage: GradedAlgebrasWithBasis(L)
...

What I meant is to use the generic completion of a graded algebra with basis. However, this does not work out of the box, because OrePolynomialRing is not in the category GradedAlgebrasWithBasis.

Then you can just say

sage: R.formal_series_ring()
Lazy completion of Ore Polynomial Ring in x over Finite Field in a of size 5^3 twisted by a |--> a^5

However, I am not sure whether this would be against some unwritten policy in sage, because the polynomial rings aren't in this category either.

On the other hand, it would be very easy to provide a specialised implementation, for example by adapting LazyCompletionGradedAlgebra.

@xcaruso
Copy link
Contributor

xcaruso commented May 5, 2023

They were my last two comments.
After this, I'm happy with the ticket and ready to give a positive review.

@xcaruso
Copy link
Contributor

xcaruso commented May 15, 2023

All tests pass.

@kryzar Do you agree for giving a positive review to this ticket?

Copy link
Contributor

@kryzar kryzar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies for delaying my review.

I approve the changes. I commented on two things which I think could be better next time. Those are important, but it is also important not to delay this PR any longer.

@DavidAyotte
Copy link
Member Author

I refactored logarithm and exponential following Antoine's suggestion and put back the need review status of the ticket. I hope the code is a bit clearer now.

@github-actions
Copy link

Documentation preview for this PR is ready! 🎉
Built with commit: 2b242fb

@xcaruso
Copy link
Contributor

xcaruso commented May 16, 2023

OK!

@vbraun vbraun merged commit fdf9668 into sagemath:develop May 22, 2023
@mkoeppe mkoeppe added this to the sage-10.1 milestone May 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants