using libgap in source

87 views
Skip to first unread message

Jackson Walters

unread,
Dec 5, 2024, 10:34:45 PM12/5/24
to sage-devel
Hi all,

Probably pretty obvious, but I need to call libgap for the following function:

def unitary_change_of_basis(U,q):
   if U.nrows() == 1 and U.ncols() == 1:
       return matrix(F,[[factor_scalar(U[0,0])]])
    libgap.LoadPackage("forms")
    return matrix(F,libgap.BaseChangeToCanonical(libgap([list(row) for row in U]).HermitianFormByMatrix(F))).inverse()

It works perfectly fine in a Sage notebook, but throws errors when I try to include it in a PR.

What is the proper way to invoke libgap in, say, symmetric_group_algebra.py? Should I go back to using libgap.eval?

Thank you,
Jackson

Jackson Walters

unread,
Dec 5, 2024, 10:37:30 PM12/5/24
to sage-devel
Perhaps I can just use 

from sage.libs.gap.libgap import libgap

Jackson Walters

unread,
Dec 5, 2024, 11:14:41 PM12/5/24
to sage-devel
Seems to have made it one step further. Probably the issue is now 

libgap.LoadPackage("forms")

Error: Failed example:: Exception raised:
Traceback (most recent call last):
File "sage/libs/gap/libgap.pyx", line 684, in sage.libs.gap.libgap.Gap.__getattr__
g = self.eval(name)
File "sage/libs/gap/libgap.pyx", line 399, in sage.libs.gap.libgap.Gap.eval
elem = make_any_gap_element(self, gap_eval(gap_command))
File "sage/libs/gap/util.pyx", line 362, in sage.libs.gap.util.gap_eval
result = GAP_EvalString(cmd)
sage.libs.gap.util.GAPError: Error, Variable: 'BaseChangeToCanonical' must have a value
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/sage/src/sage/doctest/forker.py", line 716, in _run
self.compile_and_execute(example, compiler, test.globs)
File "/sage/src/sage/doctest/forker.py", line 1137, in compile_and_execute
exec(compiled, globs)
File "<doctest sage.combinat.symmetric_group_algebra.SymmetricGroupAlgebra_n._dft_unitary[6]>", line 1, in <module>
U = GF5S3._dft_unitary()
File "/sage/src/sage/combinat/symmetric_group_algebra.py", line 2212, in _dft_unitary
fourier_transform = [flatten([hat(delta(g),partition).list() for partition in Partitions(G.degree())]) for g in G]
File "/sage/src/sage/combinat/symmetric_group_algebra.py", line 2212, in <listcomp>
fourier_transform = [flatten([hat(delta(g),partition).list() for partition in Partitions(G.degree())]) for g in G]
File "/sage/src/sage/combinat/symmetric_group_algebra.py", line 2212, in <listcomp>
fourier_transform = [flatten([hat(delta(g),partition).list() for partition in Partitions(G.degree())]) for g in G]
File "/sage/src/sage/combinat/symmetric_group_algebra.py", line 2206, in hat
A = unitary_change_of_basis(U,q)
File "/sage/src/sage/combinat/symmetric_group_algebra.py", line 2200, in unitary_change_of_basis
return matrix(F,libgap.BaseChangeToCanonical(libgap([list(row) for row in U]).HermitianFormByMatrix(F))).inverse()
File "sage/libs/gap/libgap.pyx", line 686, in sage.libs.gap.libgap.Gap.__getattr__
raise AttributeError(f'No such attribute: {name}.')
AttributeError: No such attribute: BaseChangeToCanonical.

David Roe

unread,
Dec 5, 2024, 11:14:49 PM12/5/24
to sage-...@googlegroups.com
Yep, that should work.  To find the right import statements, you can do
sage: import_statements(libgap)
from sage.libs.gap.libgap import libgap
David

--
You received this message because you are subscribed to the Google Groups "sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/sage-devel/63229f29-ccaa-4f40-aeef-5a7540afd72an%40googlegroups.com.

Jackson Walters

unread,
Dec 5, 2024, 11:23:35 PM12/5/24
to sage-devel

Ah, thank you. Any idea if loading packages via libgap.LoadPackage("forms") is expected to work?

Jackson

Dima Pasechnik

unread,
Dec 6, 2024, 12:55:06 AM12/6/24
to Jackson Walters, sage-devel
On 5 December 2024 17:23:35 GMT-06:00, Jackson Walters
<jackson...@gmail.com> wrote:
>
>Ah, thank you. Any idea if loading packages via libgap.LoadPackage("forms") is
>expected to work?

absolutely. As I said elsewhere, look at how things involving libgap
are done in e.g. src/sage/graphs/.
>>> <https://groups.google.com/d/msgid/sage-devel/63229f29-ccaa-4f40-aeef-5a7540afd72an%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>>
>

Michael Orlitzky

unread,
Dec 6, 2024, 1:16:23 AM12/6/24
to sage-...@googlegroups.com
On 2024-12-05 15:23:35, Jackson Walters wrote:
>
> Ah, thank you. Any idea if loading packages via libgap.LoadPackage("forms") is
> expected to work?

Yes, but only if the GAP package you're trying to load is
installed. The only ones that are guaranteed to be installed are
gapdoc, primgrp, smallgrp, and transgrp. All others (even "standard"
packages like polycyclic) are technically optional and the test suite
should pass if they are missing. You can just grep for "polycyclic"
and copy the existing examples for that.

The other problem is that the "forms" package isn't part of the sage
distribution, and may not be available on all linux distributions, so
the CI (not to mention normal users) will be unable to test it. The
first step towards remedying that would probably be to add "forms" to
the gap_packages SPKG.

Jackson Walters

unread,
Dec 6, 2024, 1:32:01 AM12/6/24
to sage-...@googlegroups.com
Right, confirmed separately from Travis:

So the Forms package is a GAP package that has been included since GAP v4.9, but it is not included by our default installation nor in gap_packages

We are debating whether to just implement the necessary methods in Sage. I'm going to begin tomorrow.

 The first step towards remedying that would probably be to add "forms" to the gap_packages SPKG.

 It would be nice to just have these installed. This isn't something I can do, right? I should mention that locally this is all working in my installation, where I have installed `forms`.

--
You received this message because you are subscribed to the Google Groups "sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+...@googlegroups.com.

Michael Orlitzky

unread,
Dec 6, 2024, 2:14:07 AM12/6/24
to sage-...@googlegroups.com
On 2024-12-05 20:31:40, Jackson Walters wrote:
>
> It would be nice to just have these installed. This isn't something I can
> do, right? I should mention that locally this is all working in my
> installation, where I have installed `forms`.
>

You could hold a vote to make "forms" a standard package and then
require it, but your new code would have to be pretty awesome for
that to be worth it.

Instead, I would suggest leaving it optional and marking the tests
with "# optional - gap_package_forms". People using the system GAP
would then be free to install forms (if it isn't installed already)
when they want to use your code. Adding forms to gap_packages is still
useful because it provides a way for the people who installed GAP via
sage to install forms. In particular, one of the people who install
GAP via sage is our CI.

Jackson Walters

unread,
Dec 6, 2024, 8:19:55 AM12/6/24
to sage-...@googlegroups.com
You could hold a vote to make "forms" a standard package and then
require it, but your new code would have to be pretty awesome for
that to be worth it.
 
Instead, I would suggest leaving it optional and marking the tests
with "# optional - gap_package_forms". People using the system GAP
would then be free to install forms (if it isn't installed already)
when they want to use your code. Adding forms to gap_packages is still
useful because it provides a way for the people who installed GAP via
sage to install forms. In particular, one of the people who install
GAP via sage is our CI.

 While I do think "forms" has some nice features, I don't think we need to take it to a vote at this time.

This code is essentially using one function, BaseChangeToCanonical, for a Hermitian form. We were able to achieve the same decomposition with Sage code in just a few lines, as well as replicate exactly what GAP is doing.

def base_change_hermitian(U):
Up = U.LU()[2]
D = Up.diagonal()
A = ~Up * matrix.diagonal([d.sqrt() for d in D])
diag = (A.H * U * A).diagonal()
factor_diag = diagonal_matrix([conj_square_root(d) for d in diag])
return factor_diag*A.inverse()

The GAP code performs the row operations explicitly and is lengthy. For now, we simply avoid any call to libgap, and tests are beginning to pass.

Thanks,
Jackson

--
You received this message because you are subscribed to the Google Groups "sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages