Skip to content

Commit

Permalink
Document the GAP integration in Oscar
Browse files Browse the repository at this point in the history
addresses issue #2317
  • Loading branch information
ThomasBreuer committed May 11, 2023
1 parent 56cc38a commit 3b57c98
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 3 deletions.
1 change: 1 addition & 0 deletions docs/doc.main
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@
"DeveloperDocumentation/debugging.md",
"DeveloperDocumentation/serialization.md",
"DeveloperDocumentation/design_decisions.md",
"DeveloperDocumentation/gap_integration.md",
"Polyhedral Geometry" => [
"DeveloperDocumentation/AbstractCollection.md",
"DeveloperDocumentation/SubObjectIterator.md",
Expand Down
69 changes: 69 additions & 0 deletions docs/src/DeveloperDocumentation/gap_integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# GAP Integration

This section explains how Oscar interacts with GAP.

## The Julia package [GAP.jl](https://github.com/oscar-system/GAP.jl)

This package provides a bidirectional interface between GAP and Julia.
Its [documentation](https://oscar-system.github.io/GAP.jl/stable/)
describes how to call GAP functions in Julia code and vice versa,
and how low level Julia objects can be converted to GAP objects
and vice versa.

When one works interactively in an Oscar session,
calling `GAP.prompt()` opens a GAP session which has access to the variables
in the Julia session, in particular to all Oscar functions and objects;
one can return to the Julia prompt by entering `quit;` in the GAP session.

## Interface functionalities beyond GAP.jl

For code involving Julia types that are defined in Oscar,
GAP.jl cannot provide utility functions such as conversions to and from GAP.

- The GAP package OscarInterface (at `gap/OscarInterface`)
is intended to contain the GAP code in question,
for example the declarations of new filters
and the installation of new methods.

Note that such code must be loaded at runtime into the GAP session
that is started by Julia, and the OscarInterface package gets loaded
in Oscar's `__init__` function.

- The files in the directory `src/GAP`
are intended to contain the Julia code in question,
for example conversions from GAP to `ZZRingElem`, `QQFieldElem`,
`FinFieldElem`, etc.,
and the construction of isomorphisms between algebraic structures
such as rings and fields in GAP and Oscar,
via [`Oscar.iso_oscar_gap`](@ref) and [`Oscar.iso_gap_oscar`](@ref).

- In Oscar code, global GAP variables can be accessed as members of
`GAP.Globals`, but for the case of GAP functions,
it is more efficient to use `Oscar.GAPWrap` instead.

For example, if one wants to call GAP's `IsFinite` then it is
recommended to replace the call `GAP.Globals.IsFinite(x)::Bool`,
for some GAP object `x` (a group or a ring or a list, etc.),
by `Oscar.GAPWrap.IsFinite(x)`.
This works only if the method in question gets defined in
`src/GAP/wrappers.jl`, thus methods with the required signatures
should be added to this file when they turn out to be needed.

(The reason why we collect the `GAP.@wrap` lines in an Oscar file and
not inside GAP.jl is that we can extend the list without waiting for
releases of GAP.jl.)

- In GAP code, global Julia variables can be accessed as members of
`Julia`, relative to its `Main` module.
For example, one can call `Julia.sqrt` and `Julia.typeof`
(or `Julia.Base.sqrt` and `Julia.Core.typeof`) in GAP code.

In order to access variables from the `Oscar` module,
it is not safe to use `Julia.Oscar`
because the module `Oscar` is not always defined in `Main`.
Instead, there is the global GAP variable `Oscar`.

```@docs
Oscar.iso_oscar_gap
Oscar.iso_gap_oscar
```
90 changes: 88 additions & 2 deletions docs/src/General/other.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,94 @@

## Notes for GAP users

- TODO
- TODO: also talk about how to use it from OSCAR?
This section describes differences between GAP and Oscar.

- The syntax of the languages is slightly different.

- In GAP, equality of two objects is checked with `=`,
and one assigns a value to a variable with `:=`.
In Julia, equality is checked with `==`,
and `=` denotes assignment.

- In GAP, `if` statements have the form
```
if condition1 then
statements1
elif condition2 then
statements2
else
statements3
fi;
```
whereas the Julia syntax is
```
if condition1
statements1
elseif condition2
statements2
else
statements3
end
```
Similarly, GAP's `for` loops have the form
```
for var in list do
statements
od;
```
whereas the Julia syntax is
```
for var in list
statements
end
```
(The situation with `while` loops is analogous.)
- Variable names in GAP and Julia are recommended to be written in
camel case and snake case, respectively, see [Naming conventions](@ref).
For example, the GAP function `SylowSubgroup` corresponds to
Oscar's `sylow_subgroup`.
Thus the GAP rule that the names of user variables should start with a
lowercase letter, in order to avoid clashes with system variables,
does not make sense in Julia.
Moreover, global Oscar variables are not write protected,
contrary to most global GAP variables.
Thus there is always the danger that assignments overwrite Julia functions.
For example, it is tempting to use `gens`, `hom`, and `map` as names for
variables, but Julia or Oscar define them are already.
(Also copying some lines of code from an Oscar function into a Julia session
can be dangerous in this sense,
because some names of local variables of the function may coincide with the
names of global variables.)
- GAP provides natural embeddings of many algebraic structures.
For example, two finite fields of the same characteristic are embedded
into each other whenever this makes sense, and the elements of the smaller
field are regarded also as elements of the larger field.
Analogously, subfields of cyclotomic fields are naturally embedded
into each other, and in fact their elements are internally represented
w.r.t. the smallest possible cyclotomic field.
In Oscar, this is not the case.
Each element of an algebraic structure has a parent,
and operations involving several elements (such as arithmetic operations)
are usually restricted to the situation that their parents coincide.
One has to explicitly coerce a given element into a different parent
if necessary.
The consequences can be quite subtle.
Each permutation group in Oscar has a fixed degree,
and the function `is_transitive` checks whether its argument is transitive
on the points from 1 to the degree.
In GAP, however, the function `IsTransitive`, called with a permutation
group, checks whether this group is transitive on the points which are
moved by it.
Thus the group generated by the permutation `(1, 2, 4)` is regarded as
transitive in GAP but as intransitive in Oscar.
## Notes for Singular users
Expand Down
3 changes: 2 additions & 1 deletion src/GAP/gap_to_oscar.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ function (F::FinField)(x::GAP.FFE)
return F(val)
end

# HACK: use `iso_oscar_gap` for now, until `iso_gap_oscar` becomes available
# Use `iso_oscar_gap` not `iso_gap_oscar` in order to make sure
# that the result is in `F`, and in order to cache the isomorphism in `F`.
iso = iso_oscar_gap(F)
return preimage(iso, x)
end
Expand Down

0 comments on commit 3b57c98

Please sign in to comment.