In [1]:

```
versioninfo()
using Pkg
Pkg.status()
```

In [2]:

```
using Oscar
const pm=Polymake;
```

In the context of Hilbert's 16th Problem Itenberg and Viro constructed a counter-example to a conjecture of Ragsdale, via *patchworking*. This is just to show that (almost) all of polymake's functionality is available through Julia.

In [3]:

```
R = pm.tropical.ragsdale_counterexample();
```

Interactive visualization is possible, also within a Jupyter notebook. Yet, for static web versions svg output is nicer.

In [4]:

```
pm.display_svg(R)
```

The actual example starts here. We construct a regular $4$-cube, with $\pm1$-coordinates, but the precise coordinates will not matter here.

In [5]:

```
C = pm.polytope.cube(4);
```

We can get the combinatorial automorphism group directly.

In [6]:

```
G_polymake = pm.group.automorphism_group(C.VERTICES_IN_FACETS);
```

From the type information output (which is suppressed by ";" following the command) we see that the group is given as a permutation group. What is not obvious, but true: this is the natural action on the eight facets.

In [7]:

```
gens = G_polymake.PERMUTATION_ACTION.GENERATORS
```

Out[7]:

Note that polymake is $0$-based, while Julia is $1$-based.

In [8]:

```
gens[2]
```

Out[8]:

Generic Julia functions can convert between $0$- and $1$-based containers. Future Polymake.jl versions will have this built-in.

In [9]:

```
to_one_based_indexing(n::Number) = n + one(n)
to_zero_based_indexing(n::Number) = (n > zero(n) ? n - one(n) : throw(ArgumentError("Can't use negative index")))
for f in [:to_one_based_indexing, :to_zero_based_indexing]
@eval begin
$f(itr) = $f.(itr)
$f(s::S) where S<:AbstractSet = S($f.(s))
end
end
```

Applying this to the generators of the group computed by polymake yields a standard Julia datatype.

In [10]:

```
to_one_based_indexing(gens)
```

Out[10]:

The software of choice to deal with groups is GAP. Here is a micro-demo, which constructs a symmetric group of degree four from a 4-cycle and a transposition.

In [11]:

```
S4 = GAP.Globals.Group(GAP.@gap [(1,2,3,4), (1,2)])
@show S4
GAP.Globals.Order(S4)
```

Out[11]:

A typical OSCAR-function will provide natural ways of communication between the cornerstone systems. The function is fairly short, the bulk of the code are some straightforward conversions.

In [12]:

```
function combinatorial_automorphism_group(P)
G = pm.group.automorphism_group(P.VERTICES_IN_FACETS)
gens_polymake = G.PERMUTATION_ACTION.GENERATORS # acting on the facets
gens_julia = Vector{Int64}.(pm.to_one_based_indexing(gens_polymake))
gens_gap = GAP.Globals.PermList.(GAP.julia_to_gap.(gens_julia))
return GAP.Globals.Group(gens_gap...)
end
```

Out[12]:

Recognizing the isomorphism type of the (combinatorial) automorphism group of a polytope is available neither in GAP nor polymake alone.

In [13]:

```
G = combinatorial_automorphism_group(C)
GAP.Globals.StructureDescription(G)
```

Out[13]:

Some functions are implemented independently in both systems. This can be employed for cross-certification.

In [14]:

```
@show G_polymake.ORDER
@show GAP.Globals.Order(G)
```

Out[14]: