{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# OSCAR, a Tech Preview (Part I)\n",
"\n",
"A tiny example, which makes use of the cornerstone systems polymake and GAP.\n",
"\n",
"## The Setup\n",
"\n",
"The configuration can be cloned via copying the Project.toml file and using instantiate in the REPL mode."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Julia Version 1.5.3\n",
"Commit 788b2c77c1 (2020-11-09 13:37 UTC)\n",
"Platform Info:\n",
" OS: Linux (x86_64-pc-linux-gnu)\n",
" CPU: Intel(R) Core(TM) i7-7600U CPU @ 2.80GHz\n",
" WORD_SIZE: 64\n",
" LIBM: libopenlibm\n",
" LLVM: libLLVM-9.0.1 (ORCJIT, skylake)\n",
"\u001b[32m\u001b[1mStatus\u001b[22m\u001b[39m `/data/polymake/oscar-system/oscar-notebooks/MPI-demo-200124/Project.toml`\n",
" \u001b[90m [7073ff75] \u001b[39m\u001b[37mIJulia v1.23.1\u001b[39m\n",
" \u001b[90m [f1435218] \u001b[39m\u001b[37mOscar v0.5.1 `https://github.com/oscar-system/Oscar.jl#d0908f5`\u001b[39m\n",
"\u001b[31m→\u001b[39m\u001b[90m [9b87118b] \u001b[39m\u001b[37mPackageCompiler v1.2.5\u001b[39m\n",
" \u001b[90m [8f399da3] \u001b[39m\u001b[37mLibdl\u001b[39m\n",
"\u001b[32m\u001b[1mInfo\u001b[22m\u001b[39m packages marked with \u001b[31m→\u001b[39m not downloaded, use `instantiate` to download\n"
]
}
],
"source": [
"versioninfo()\n",
"\n",
"using Pkg\n",
"Pkg.status()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## polymake's Functions Are Available"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" ----- ----- ----- - ----- \n",
"| | | | | | | | | | \n",
"| | | | | | | | \n",
"| | ----- | | | |----- \n",
"| | | | |-----| | | \n",
"| | | | | | | | | | \n",
" ----- ----- ----- - - - - \n",
"\n",
"...combining (and extending) ANTIC, GAP, Polymake and Singular\n",
"Version\u001b[32m 0.5.1 \u001b[39m... \n",
" ... which comes with absolutely no warranty whatsoever\n",
"Type: '?Oscar' for more information\n",
"(c) 2019-2021 by The Oscar Development Team\n"
]
}
],
"source": [
"using Oscar\n",
"const pm=Polymake;"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"R = pm.tropical.ragsdale_counterexample();"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Interactive visualization is possible, also within a Jupyter notebook. Yet, for static web versions svg output is nicer."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"pm.display_svg(R)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The actual example starts here. We construct a regular $4$-cube, with $\\pm1$-coordinates, but the precise coordinates will not matter here."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"C = pm.polytope.cube(4);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can get the combinatorial automorphism group directly."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"G_polymake = pm.group.automorphism_group(C.VERTICES_IN_FACETS);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"pm::Array>\n",
"0 1 2 3 6 7 4 5\n",
"0 1 4 5 2 3 6 7\n",
"2 3 0 1 4 5 6 7\n",
"1 0 2 3 4 5 6 7\n"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"gens = G_polymake.PERMUTATION_ACTION.GENERATORS"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that polymake is $0$-based, while Julia is $1$-based."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"pm::Array\n",
"0 1 4 5 2 3 6 7"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"gens[2]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Generic Julia functions can convert between $0$- and $1$-based containers. Future Polymake.jl versions will have this built-in."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"to_one_based_indexing(n::Number) = n + one(n)\n",
"to_zero_based_indexing(n::Number) = (n > zero(n) ? n - one(n) : throw(ArgumentError(\"Can't use negative index\")))\n",
"\n",
"for f in [:to_one_based_indexing, :to_zero_based_indexing]\n",
" @eval begin\n",
" $f(itr) = $f.(itr)\n",
" $f(s::S) where S<:AbstractSet = S($f.(s))\n",
" end\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Applying this to the generators of the group computed by polymake yields a standard Julia datatype."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"[[$1$, $2$, $3$, $4$, $7$, $8$, $5$, $6$], [$1$, $2$, $5$, $6$, $3$, $4$, $7$, $8$], [$3$, $4$, $1$, $2$, $5$, $6$, $7$, $8$], [$2$, $1$, $3$, $4$, $5$, $6$, $7$, $8$]]"
],
"text/plain": [
"4-element Array{Array{Int64,1},1}:\n",
" [1, 2, 3, 4, 7, 8, 5, 6]\n",
" [1, 2, 5, 6, 3, 4, 7, 8]\n",
" [3, 4, 1, 2, 5, 6, 7, 8]\n",
" [2, 1, 3, 4, 5, 6, 7, 8]"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"to_one_based_indexing(gens)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Use GAP For Groups"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"S4 = GAP: Group([ (1,2,3,4), (1,2) ])\n"
]
},
{
"data": {
"text/html": [
"$24$"
],
"text/plain": [
"24"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"S4 = GAP.Globals.Group(GAP.@gap [(1,2,3,4), (1,2)])\n",
"@show S4\n",
"GAP.Globals.Order(S4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"combinatorial_automorphism_group (generic function with 1 method)"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"function combinatorial_automorphism_group(P)\n",
" G = pm.group.automorphism_group(P.VERTICES_IN_FACETS)\n",
" gens_polymake = G.PERMUTATION_ACTION.GENERATORS # acting on the facets\n",
" gens_julia = Vector{Int64}.(pm.to_one_based_indexing(gens_polymake))\n",
" gens_gap = GAP.Globals.PermList.(GAP.julia_to_gap.(gens_julia))\n",
" return GAP.Globals.Group(gens_gap...)\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Recognizing the isomorphism type of the (combinatorial) automorphism group of a polytope is available neither in GAP nor polymake alone."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"GAP: \"((((C2 x C2 x C2) : (C2 x C2)) : C3) : C2) : C2\""
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"G = combinatorial_automorphism_group(C)\n",
"GAP.Globals.StructureDescription(G)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Some functions are implemented independently in both systems. This can be employed for cross-certification."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"G_polymake.ORDER = 384\n",
"GAP.Globals.Order(G) = 384\n"
]
},
{
"data": {
"text/html": [
"$384$"
],
"text/plain": [
"384"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"@show G_polymake.ORDER\n",
"@show GAP.Globals.Order(G)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 1.5.3",
"language": "julia",
"name": "julia-1.5"
},
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "1.5.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}