Polyhedral Geometry in OSCAR

An introduction for developers

Alexej Jordan (TU Berlin)

13th polymake conference and developer meeting - 2022-01-21

OSCAR

  • Computer algebra system
  • Combine features of several software projects:
    • GAP
    • Polymake
    • Antic
    • Singular
  • Official julia package

Challenges

  • Features need to be
    • wrapped
    • integrated into julia
  • Define and follow mathematical and programming conventions
  • Link capabilities originating from different software

Polyhedral Geometry

  • Powered by Polymake.jl
  • Specific structs, e.g. Cone, mask polymake BigObjects
    struct Cone
      pm_cone::Polymake.BigObject
    end
    
  • Methods convert in-/output and re-direct calls to Polymake.jl
    dim(C::Cone) = pm_object(C).CONE_DIM::Int
    

Challenges

  • Design: Affine (OSCAR) vs. Homogeneous (polymake/Polymake.jl)
In [2]:
Pos = Polyhedron([-1 0 0; 0 -1 0; 0 0 -1], [0, 0, 0])

println(vertices(Pos))
println(rays(Pos))
println()
println(Oscar.pm_object(Pos).VERTICES)
PointVector{Polymake.Rational}[[0, 0, 0]]
RayVector{Polymake.Rational}[[1, 0, 0], [0, 1, 0], [0, 0, 1]]

pm::Matrix<pm::Rational>
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0

  • Types: Accept and return OSCAR types
  • Implementation: Ideally use existing functionality

Current State

  • Main objects: Cone, Polyhedron, PolyhedralFan, SubdivisonOfPoints
  • Rational coordinates only, integer return where applicable
  • Additional support: Linear programs and groups
  • Serialization: Based on polymake's serialization
  • Visualization: Based on polymake's visualization

A small example

In [3]:
c = cross(3)
i = intersect(c, Pos)
println(isbounded(i))
println(vertices(i))
true
PointVector{Polymake.Rational}[[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 0, 0]]
In [4]:
es = convex_hull(vertices(i), [-1 0 0])
facets(es)
Out[4]:
4-element SubObjectIterator{AffineHalfspace}:
 The Halfspace of R^3 described by
1: x₂ + x₃ ≦ 1

 The Halfspace of R^3 described by
1: -x₂ ≦ 0

 The Halfspace of R^3 described by
1: -x₃ ≦ 0

 The Halfspace of R^3 described by
1: x₁ + x₂ + x₃ ≦ 1

Developer workflow

  • Feature flow:

OSCAR $\longleftarrow$ Polymake.jl $\longleftarrow$ libpolymake_julia $\longleftarrow$ polymake

  • Decide where/what changes are wanted/necessary
    • Use different environments for specific feature sub-flows
  • Include tests and documentation

Setting up the workspace

  • Start julia
  • activate desired environment (using Pkg)
  • dev Oscar/dev Polymake (using Pkg) to clone the repository and to use the local version in the current environment
  • The local copy is a git repository

github

  • Check the README and the documentation
    • OSCAR now has a dev corner
  • Many possibilities for communication
  • Share progress by creating a (draft) pull request
  • OSCAR CI also performs tests across repositories for equally named branches

Extend OSCAR using Polymake.jl

  • Most common case
  • The module Polymake from Polymake.jl is loaded in the context of OSCAR
  • Many polymake features are available directly from Polymake.jl:
    • BigObjects and functions are located within the respective sub-module
    • Properties can be accessed using julia's .-syntax
In [5]:
simp = Polymake.polytope.Polytope(FACETS = [0 1 0; 0 0 1; 1 -1 -1])
println(simp.VERTICES)
println(Polymake.polytope.dim(simp))
pm::Matrix<pm::Rational>
1 1 0
1 0 1
1 0 0

2
  • More complex calls, e.g. using not-wrapped templates, with the pm macro
In [6]:
simpQE = Polymake.@pm polytope.Polytope{QuadraticExtension}(VERTICES = [1 0 0; 1 1 0; 1 0 1])
Out[6]:
type
Polytope>
VERTICES
1 0 0
1 1 0
1 0 1
  • Small object types need to be wrapped first in order to be usable from within julia
    • If not wrapped: PropertyValue which can be received and passed unaltered
In [7]:
simpQE.VERTICES
Out[7]:
PropertyValue wrapping pm::Matrix<pm::QuadraticExtension<pm::Rational> >
1 0 0
1 1 0
1 0 1
In [8]:
simpQE.VERTICES[1, 1]
MethodError: no method matching getindex(::Polymake.PropertyValueAllocated, ::Int64, ::Int64)
Closest candidates are:
  getindex(::Any, ::Oscar.StraightLinePrograms.LazyRec) at /home/jordan/.julia/packages/Oscar/iRpOQ/StraightLinePrograms/src/lazy.jl:562
  getindex(::Any, ::Oscar.StraightLinePrograms.Lazy) at /home/jordan/.julia/packages/Oscar/iRpOQ/StraightLinePrograms/src/lazy.jl:111

Stacktrace:
 [1] top-level scope
   @ In[8]:1
 [2] eval
   @ ./boot.jl:373 [inlined]
 [3] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
   @ Base ./loading.jl:1196

Wrapping a new type

  • In package libpolymake_julia types and methods are linked from C++ to julia using C++ code
  • Use the polymake callable library
  • Has to be built to be usable
    • By default, a officially distributed build is used: the package libpolymake_julia_jll
    • Overwrite used julia artifacts to use local build

Extending Polymake.jl

  • In package Polymake.jl data processing on julia side is defined
  • Goal: Use polymake from within julia, not adding new features
  • Adhere to julia conventions
    • $0$-/$1$- based indexing
  • Use advantages of julia to produce generic code and reduce wrapping:
    • interfaces
    • conversion

Hints

  • Communicate
    • Weekly meet-up on Friday using Gather
  • julia packages Revise and Test can save valuable time
  • Look at the documentation, docstrings or tests