Using Polymake.jl

In this section, the main functionality of Polymake.jl is covered: how to access polymake's powerful abilities. For this cause one needs to know how to call polymake methods and how to handle the supported types.

Executing Polymake Methods

Directly calling a polymake method

One of the simplest yet most useful possibilities Polymake.jl offers is to directly use a polymake method via the following macro:

Polymake.@pmMacro
@pm polymakeapp.function_name{Template, parameters}(args)

This macro can be used to

  • create polymake Big Objects (such as polytopes)
  • call polymake functions with specific template parameters.

The expression passed to the macro has to be:

  • a fully qualified name of a polymake object (i.e. starting with the

lowercase name of a polymake application), or

  • a function with template parameters enclosed in { ... }.

Examples

julia> P = @pm polytope.Polytope{QuadraticExtension}(POINTS=[1 0 0; 0 1 0])
type: Polytope<QuadraticExtension<Rational>>

POINTS
1 0 0
0 1 0



julia> @pm common.convert_to{Float}(P)
type: Polytope<Float>

POINTS
1 0 0
0 1 0


CONE_AMBIENT_DIM
3



julia> @pm tropical.Polytope{Max}(POINTS=[1 0 0; 0 1 0])
type: Polytope<Max, Rational>

POINTS
0 -1 -1
0 1 0


!!! Note the expression in @pm macro is parsed syntactically, so it has to be a valid julia expression. However template parameters need not to be defined in julia, but must be valid names of polymake property types. Nested types (such as {QuadraticExtension{Rational}}) are allowed.

source

The @pm macro can be used to issue more complicated calls to polymake from julia. If You need to pass templates to BigObjects, some limited support is provided in costructors. For example one can construct polytope.Polytope{Float64}(...). However for this to work templates need to be valid julia types/object, hence it is not possible to construct a Polytope<QuadraticExtension> through such call. For this (and in general: for passing more complicated templates) one needs the @pm macro:

$obj = new BigObject<Template,Parameters>(args)

becomes

obj = @pm appname.BigObject{Template, Parameters}(args)

Examples:

tropical.Polytope{max, Polymake.Rational}(POINTS=[1 0 0; 1 1 0; 1 1 1])
# call to constructor, note that max is a julia function, hence a valid object
@pm tropical.Polytope{Max, QuadraticExtension}(POINTS=[1 0 0; 1 1 0; 1 1 1])
# macro call: none of the types in templates need to exist in julia

As a rule of thumb any template passed to @pm macro needs to be translatable on syntax level to a C++ one. E.g. Matrix{Integer} works, as it translates to pm::Matrix<pm::Integer>.

Such templates can be passed to functions as well. A very useful example is the common.convert_to:

julia> c = polytope.cube(3);

julia> f = c.FACETS;

julia> f[1,1] # f is an opaque pm::perl::PropertyValue to julia
ERROR: MethodError: no method matching getindex(::Polymake.PropertyValueAllocated, ::Int64, ::Int64)
Stacktrace:
  [...]

julia> m = @pm common.convert_to{Matrix{Integer}}(f) # the template must consist of C++ names
pm::Matrix<pm::Integer>
1 1 0 0
1 -1 0 0
1 0 1 0
1 0 -1 0
1 0 0 1
1 0 0 -1

julia> m[1,1]
1

Since the combination of the @pm macro and common.convert_to is quite common there is a specialized @convert_to macro for this:


julia> m = @convert_to Matrix{Integer} f # the template must consist of C++ names
pm::Matrix<pm::Integer>
1 1 0 0
1 -1 0 0
1 0 1 0
1 0 -1 0
1 0 0 1
1 0 0 -1

Wrapped methods

As the @pm macro allows to access polymake's library, there is no need for every method to be wrapped. In general, the wrapped methods restrict to simpler ones in the context of small types, guaranteeing compatibility with julia or allowing easy modification/operations of/with instances of these types. This results in a handling of these types which is equivalent to julia's syntax, e.g. arrays can be accessed with the brackets operator [] or addition can be applied by using +:

julia> m = Polymake.Matrix{Polymake.Rational}(4,6)
pm::Matrix<pm::Rational>
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0


julia> m[2,1] = 9
9

julia> m
pm::Matrix<pm::Rational>
0 0 0 0 0 0
9 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0

julia> a = Polymake.TropicalNumber{Polymake.Min}(7)
pm::TropicalNumber<pm::Min, pm::Rational>
7

julia> b = Polymake.TropicalNumber{Polymake.Min}(10)
pm::TropicalNumber<pm::Min, pm::Rational>
10

julia> a + b
pm::TropicalNumber<pm::Min, pm::Rational>
7

Function Arguments

Functions in Polymake.jl accept the following types for their arguments:

  • simple data types (bools, machine integers, floats)
  • wrapped native types (Polymake.Integer, Polymake.Rational, Polymake.Vector, Polymake.Matrix, Polymake.Set etc.)
  • other objects returned by polymake:
    • Polymake.BigObject,
    • Polymake.PropertyValue (containers opaque to Julia)

If an object passed to Polymake.jl function is of a different type the software will try its best to convert it to a known one. However, if the conversion doesn't work an ArgumentError will be thrown:

ERROR: ArgumentError: Unrecognized argument type: SomeType.
You need to convert to polymake compatible type first.

You can tell Polymake.jl how to convert it by definig

Base.convert(::Type{Polymake.PolymakeType}, x::SomeType)

The returned value must be of one of the types as above. For example to use AbstractAlgebra.jl matrices as input to Polymake.jl one may define

Base.convert(::Type{Polymake.PolymakeType}, M::Generic.MatSpaceElem) = Polymake.Matrix(M.entries)

and the following should run smoothly.

julia> using AbstractAlgebra, Polymake
polymake version 4.0
Copyright (c) 1997-2020
Ewgenij Gawrilow, Michael Joswig (TU Berlin)
https://polymake.org

This is free software licensed under GPL; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


julia> mm = AbstractAlgebra.matrix(ZZ, [1 2 3; 4 5 6])
[1 2 3]
[4 5 6]

julia> polytope.Polytope(POINTS=mm)
ERROR: ArgumentError: Unrecognized argument type: AbstractAlgebra.Generic.MatSpaceElem{Int64}.
You need to convert to polymake compatible type first.
  [...]

julia> Base.convert(::Type{Polymake.PolymakeType}, M::Generic.MatSpaceElem) = Polymake.Matrix(M.entries)

julia> polytope.Polytope(POINTS=mm)
type: Polytope<Rational>

POINTS
1 2 3
1 5/4 3/2

Accessing the polyDB

Polymake.jl allows the user to access the objects stored within the polyDB via the Mongoc.jl package; this functionality can be found in another sub-module, Polymake.Polydb, which requires no additional interaction to be loaded. It offers two different ways for querying, as well as some methods for information. For demonstration purposes, there also is a Jupyter notebook in the examples/ folder.

General tools

There are three types one needs to know when working with Polymake.Polydb:

Polymake.Polydb.CollectionType
  Collection{T}

Type for referencing a specific collection. T<:Union{Polymake.BigObject, Mongoc.BSON} defines the template and/or element types returned by operations applied on objects of this type.

source
Polymake.Polydb.CursorType
  Cursor{T}

Type containing the results of a query. Can be iterated, but the iterator can not be reset. For this cause, one has to query again. T<:Union{Polymake.BigObject, Mongoc.BSON} defines the element types.

source

To receive the Database object referencing to the polyDB, there is the get_db() method:

Polymake.Polydb.get_dbMethod
  get_db()

Connect to the polyDB and return Database instance.

The uri of the server can be set in advance by writing its String representation into ENV["POLYDBTESTURI"]. (used to connect to the github services container for testing)

Examples

julia> db = Polymake.Polydb.get_db();

julia> typeof(db)
Polymake.Polydb.Database
source

A specific Collection object can then be obtained with the brackets operator:

Base.getindexMethod
  getindex(db::Database, name::AbstractString)

Return a Polymake.Polydb.Collection{Polymake.BigObject} instance from db with the given name. Sections and collections in the name are connected with the '.' sign.

Examples

julia> db = Polymake.Polydb.get_db();

julia> collection = getindex(db, "Polytopes.Lattice.SmoothReflexive")
Polymake.Polydb.Collection{Polymake.BigObject}: Polytopes.Lattice.SmoothReflexive

julia> collection = db["Matroids.Small"]
Polymake.Polydb.Collection{Polymake.BigObject}: Matroids.Small
source

By default, the results are parsed to Polymake.BigObjects when accessed, but one may choose to change this behaviour by adjusting the typing template of Collection or Cursor using the following method:

Polymake.Polydb.CollectionMethod
  Collection{T}(c::Collection)

Create another Collection object with a specific template parameter referencing the same collection as c. T can be chosen from Polymake.BigObject and Mongoc.BSON.

Examples

julia> db = Polymake.Polydb.get_db();

julia> collection = db["Polytopes.Lattice.SmoothReflexive"]
Polymake.Polydb.Collection{Polymake.BigObject}: Polytopes.Lattice.SmoothReflexive

julia> collection_bson = Polymake.Polydb.Collection{Mongoc.BSON}(collection)
Polymake.Polydb.Collection{Mongoc.BSON}: Polytopes.Lattice.SmoothReflexive

julia> collection_bo = Polymake.Polydb.Collection{Polymake.BigObject}(collection_bson)
Polymake.Polydb.Collection{Polymake.BigObject}: Polytopes.Lattice.SmoothReflexive
source

Information

Polymake.Polydb.infoFunction
  info(db::Database, level::Base.Integer=1)

Print a structured list of the sections and collections of the Polydb together with information about each of these (if existent).

Detail of the output determined by value of level:

  • 1: short description,
  • 2: description,
  • 3: description, authors, maintainers,
  • 4: full info,
  • 5: full info and list of recommended search fields.
source
  info(c::Collection, level::Base.Integer=1)

Print information about collection c (if existent).

Detail of the output determined by value of level:

  • 1: short description,
  • 2: description,
  • 3: description, authors, maintainers,
  • 4: full info,
  • 5: full info and list of recommended search fields.
source
Polymake.Polydb.get_collection_namesFunction
  get_collection_names(db::Database)

Return a Vector{String} containing the names of all collections in the Polydb, excluding meta collections.

Examples

julia> db = Polymake.Polydb.get_db();

julia> Polymake.Polydb.get_collection_names(db)
16-element Vector{String}:
 "Polytopes.Combinatorial.FacesBirkhoffPolytope"
 "Polytopes.Combinatorial.SmallSpheresDim4"
 "Polytopes.Geometric.01Polytopes"
 "Polytopes.Lattice.SmoothReflexive"
 "Polytopes.Lattice.ExceptionalMaximalHollow"
 "Tropical.TOM"
 ⋮
 "Polytopes.Lattice.Panoptigons"
 "Tropical.Cubics"
 "Tropical.SchlaefliFan"
 "Polytopes.Lattice.Reflexive"
 "Polytopes.Combinatorial.CombinatorialTypes"
source
Polymake.Polydb.get_fieldsFunction
  get_fields(c::Collection)

Return a Vector{String} containing the names of the fields of c.

Examples

julia> db = Polymake.Polydb.get_db();

julia> collection = db["Matroids.Small"]
Polymake.Polydb.Collection{Polymake.BigObject}: Matroids.Small

julia> Polymake.Polydb.get_fields(collection)
27-element Vector{String}:
 "DUAL"
 "N_BASES"
 "TUTTE_POLYNOMIAL"
 "SERIES_PARALLEL"
 "N_FLATS"
 "SPLIT_FLACETS"
 ⋮
 "TERNARY"
 "REGULAR"
 "TRANSVERSAL"
 "IDENTICALLY_SELF_DUAL"
 "BETA_INVARIANT"
source

Querying

There are two ways for querying within Polymake.jl.

Methods

Mongoc.findFunction
find(collection::Collection, bson_filter::BSON=BSON();
    options::Union{Nothing, BSON}=nothing) :: Cursor

Executes a query on collection and returns an iterable Cursor.

Example

function find_contract_codes(collection, criteria::Dict=Dict()) :: Vector{String}
    result = Vector{String}()

    let
        bson_filter = Mongoc.BSON(criteria)
        bson_options = Mongoc.BSON("""{ "projection" : { "_id" : true }, "sort" : { "_id" : 1 } }""")
        for bson_document in Mongoc.find(collection, bson_filter, options=bson_options)
            push!(result, bson_document["_id"])
        end
    end

    return result
end

Check the libmongoc documentation for more information.

find(bucket::Bucket, bson_filter::BSON=BSON();
    options::BSON=BSON()) :: Cursor

Looks for files in GridFS bucket.

  find(c::Collection{T}, d::Dict=Dict(); opts::Union{Nothing, Dict})

Search a collection c for documents matching the criteria given by d. Apply search options opts.

Examples

julia> db = Polymake.Polydb.get_db();

julia> collection = db["Polytopes.Lattice.SmoothReflexive"];

julia> query = Dict("DIM"=>3, "N_FACETS"=>5);

julia> results = Polymake.Polydb.find(collection, query);

julia> typeof(results)
Polymake.Polydb.Cursor{Polymake.BigObject}
source
  find(c::Collection{T}, d::Pair...)

Search a collection c for documents matching the criteria given by d.

Examples

julia> db = Polymake.Polydb.get_db();

julia> collection = db["Polytopes.Lattice.SmoothReflexive"];

julia> results = Polymake.Polydb.find(collection, "DIM"=>3, "N_FACETS"=>5);

julia> typeof(results)
Polymake.Polydb.Cursor{Polymake.BigObject}
source

Macros

Polymake.Polydb.@selectMacro

Polymake.Polydb.@select collectionName

This macro can be used as part of a chain for easy (i.e. human readable) querying. Generate a method asking a container for the entry with key collectionName.

See also: @filter, @map

Examples

julia> db = Polymake.Polydb.get_db();

julia> collection = db |>
       Polymake.Polydb.@select("Polytopes.Lattice.SmoothReflexive")
Polymake.Polydb.Collection{Polymake.BigObject}: Polytopes.Lattice.SmoothReflexive
source
Polymake.Polydb.@filterMacro

Polymake.Polydb.@filter conditions...

This macro can be used as part of a chain for easy (i.e. human readable) querying. Convert conditions into the corresponding Dict and generate a method expanding its input by this Dict. Multiple conditions can be passed in the same line and/or in different lines.

See also: @select, @map

Examples

julia> db = Polymake.Polydb.get_db();

julia> query_tuple = db |>
       Polymake.Polydb.@select("Polytopes.Lattice.SmoothReflexive") |>
       Polymake.Polydb.@filter("DIM" <= 3) |>
       Polymake.Polydb.@filter("N_VERTICES" == 8)
(Polymake.Polydb.Collection{Polymake.BigObject}
    COLLECTION: Polytopes.Lattice.SmoothReflexive
    Smooth reflexive lattice polytopes in dimensions up to 9, up to lattice equivalence. The lists were computed with the algorithm of Mikkel Oebro (see [[http://arxiv.org/abs/0704.0049|arxiv: 0704.0049]]) and are taken from the [[http://polymake.org/polytopes/paffenholz/www/fano.html|website of Andreas Paffenholz]]. They also contain splitting data according to [[https://arxiv.org/abs/1711.02936| arxiv: 1711.02936]].
    Authored by
        Andreas Paffenholz, paffenholz@opt.tu-darmstadt.de, TU Darmstadt
        Benjamin Lorenz, paffenholz@opt.tu-darmstadt.de, TU Berlin
        Mikkel Oebro
    Fields: AFFINE_HULL, CONE_DIM, DIM, EHRHART_POLYNOMIAL, F_VECTOR, FACET_SIZES, FACET_WIDTHS, FACETS, H_STAR_VECTOR, LATTICE_DEGREE, LATTICE_VOLUME, LINEALITY_SPACE, N_BOUNDARY_LATTICE_POINTS, N_EDGES, N_FACETS, N_INTERIOR_LATTICE_POINTS, N_LATTICE_POINTS, N_RIDGES, N_VERTICES, REFLEXIVE, SMOOTH, SELF_DUAL, SIMPLE, TERMINAL, VERTEX_SIZES, VERTICES, VERTICES_IN_FACETS, VERY_AMPLE, ALTSHULER_DET, BALANCED, CENTROID, DIAMETER, NORMAL, N_HILBERT_BASIS, IS_PRISM, IS_PRODUCT, IS_SKEW_PRISM, IS_SIMPLEX_SUM, PRISM_BASE, PRODUCT_FACTORS, SIMPLEX_SUM_BASES, SKEW_PRISM_BASES, Dict{String,Any}("DIM" => Dict{String,Any}("$lte" => 3),"N_VERTICES" => Dict{String,Any}("$eq" => 8)))

julia> query_tuple = db |>
       Polymake.Polydb.@select("Polytopes.Lattice.SmoothReflexive") |>
       Polymake.Polydb.@filter("DIM" <= 3, "N_VERTICES" == 8)
(Polymake.Polydb.Collection{Polymake.BigObject}
    COLLECTION: Polytopes.Lattice.SmoothReflexive
    Smooth reflexive lattice polytopes in dimensions up to 9, up to lattice equivalence. The lists were computed with the algorithm of Mikkel Oebro (see [[http://arxiv.org/abs/0704.0049|arxiv: 0704.0049]]) and are taken from the [[http://polymake.org/polytopes/paffenholz/www/fano.html|website of Andreas Paffenholz]]. They also contain splitting data according to [[https://arxiv.org/abs/1711.02936| arxiv: 1711.02936]].
    Authored by
        Andreas Paffenholz, paffenholz@opt.tu-darmstadt.de, TU Darmstadt
        Benjamin Lorenz, paffenholz@opt.tu-darmstadt.de, TU Berlin
        Mikkel Oebro
    Fields: AFFINE_HULL, CONE_DIM, DIM, EHRHART_POLYNOMIAL, F_VECTOR, FACET_SIZES, FACET_WIDTHS, FACETS, H_STAR_VECTOR, LATTICE_DEGREE, LATTICE_VOLUME, LINEALITY_SPACE, N_BOUNDARY_LATTICE_POINTS, N_EDGES, N_FACETS, N_INTERIOR_LATTICE_POINTS, N_LATTICE_POINTS, N_RIDGES, N_VERTICES, REFLEXIVE, SMOOTH, SELF_DUAL, SIMPLE, TERMINAL, VERTEX_SIZES, VERTICES, VERTICES_IN_FACETS, VERY_AMPLE, ALTSHULER_DET, BALANCED, CENTROID, DIAMETER, NORMAL, N_HILBERT_BASIS, IS_PRISM, IS_PRODUCT, IS_SKEW_PRISM, IS_SIMPLEX_SUM, PRISM_BASE, PRODUCT_FACTORS, SIMPLEX_SUM_BASES, SKEW_PRISM_BASES, Dict{String,Any}("DIM" => Dict{String,Any}("$lte" => 3),"N_VERTICES" => Dict{String,Any}("$eq" => 8)))
source
Polymake.Polydb.@mapMacro

Polymake.Polydb.@map [optFields...]

This macro can be used as part of a chain for easy (i.e. human readable) querying. Generate a method running a query given a Tuple{Collection, Dict}. If optFields are given (as Strings), the results only contain the stated fields and the objects metadata.

See also: @select, @filter

Examples

julia> db = Polymake.Polydb.get_db();

julia> results = db |>
       Polymake.Polydb.@select("Polytopes.Lattice.SmoothReflexive") |>
       Polymake.Polydb.@filter("DIM" == 3, "N_VERTICES" == 8) |>
       Polymake.Polydb.@map() |>
       collect
7-element Vector{Polymake.BigObject}:
 Polymake.BigObjectAllocated(Ptr{Nothing} @0x00000000028c5320)
 Polymake.BigObjectAllocated(Ptr{Nothing} @0x000000000abd7b40)
 Polymake.BigObjectAllocated(Ptr{Nothing} @0x000000000a6d7bf0)
 Polymake.BigObjectAllocated(Ptr{Nothing} @0x000000000a431470)
 Polymake.BigObjectAllocated(Ptr{Nothing} @0x000000000bcaf290)
 Polymake.BigObjectAllocated(Ptr{Nothing} @0x00000000098fb670)
 Polymake.BigObjectAllocated(Ptr{Nothing} @0x000000000a1ba460)
source