{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Using Perl within polymake\n",
    "\n",
    "The language that the interactive version of `polymake` speaks is a dialect of Perl that we refer to as `polymake`/Perl. See [www.perl.org](http://www.perl.org) for comprehensive Perl information.  Note also that the ordinary Perl manual pages are particularly useful, especially the perlintro man page which is also available on [perldoc](http://perldoc.perl.org/perlintro.html).  This short section here cannot be a replacement for a thorough introduction to this language, but we want to focus on a few key points that are relevant to `polymake`.\n",
    "\n",
    "### Standard data structures\n",
    "\n",
    "The Perl programming language originally provides three different data structures, scalars(`$`), arrays(`@`), and hashes(`%`). The user always has to specify the type of a variable using the appropriate symbol `$`, `@`, or `%`. If you forget to do so, you will receive the following error message:\n",
    "\n",
    "    > i=5;\n",
    "    polymake:  ERROR: Unquoted string \"i\" may clash with future reserved word.\n",
    "\n",
    "    \n",
    "\n",
    "\n",
    "\n",
    "Here are some simple commands illustrating how to use the different data structures:\n",
    "##### Scalars\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "11"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$i=5;\n",
    "$j=6;\n",
    "$sum=$i+$j; print $sum;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "##### Arrays\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3a b c daa\n",
       "b\n",
       "c\n",
       "d1234"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "@array=(\"a\",\"b\",\"c\"); print scalar(@array);\n",
    "push(@array,\"d\"); print \"@array\"; \n",
    "$first_entry=$array[0]; print $first_entry;\n",
    "print join(\"\\n\",@array);\n",
    "@array2=(3,1,4,2);\n",
    "print sort(@array2);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "##### Hashes\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "fourzerofour, zero4, 0"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%hash=();\n",
    "$hash{\"zero\"}=0;\n",
    "$hash{\"four\"}=4;\n",
    "print keys %hash;\n",
    "print join(\", \",keys %hash);\n",
    "print join(\", \",values %hash);\n",
    "%hash=(\"one\",1,\"two\",2);\n",
    "%hash=(\"one\"=>1,\"two\"=>2);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "### `polymake`-Perl\n",
    "\n",
    "In addition to the three standard data structures, the enriched version of `Perl` used in `polymake` also provides special data structures for dealing with more complicated concepts. For an introduction to the polymake object model see [here](properties.ipynb#Objects).\n",
    "\n",
    "`polymake`'s object hierarchy is completely reflected on the Perl side. Let us create a small polytope as an example object.\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "$p = new Polytope(POINTS=>[[1,0,1],[1,0,-1],[1,1,0],[1,-1,0]]);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Note that the `Perl`-type of the variable `$p` is `Scalar`, as the variable is internally treated as a reference to a `C++`-object. The true nature of the object becomes visible if it is printed:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Polymake::polytope::Polytope__Rational=ARRAY(0x55c8aa54c778)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $p;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this case it is a `polymake` object from the application `polytope`, and it happens to be of type `Polytope<Rational>`. Technically, `$p` is a reference to an array (but it should be never treated as an array unless you are deliberately trying to crash `polymake`). If you want less technical information on the type of your object, use this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Polytope<Rational>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $p->type->full_name;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "#### \"Small objects\": Data structures inherited from C++\n",
    "\n",
    "You can use objects that are inherited from the `C++`-side of `polymake` in the interactive shell. A complete list of so-called \"small objects\" can be found in the [online documentation](https://polymake.org/doku.php/documentation/latest/common#property_types).\n",
    "Here is a selection of three different structures that facilitate everyday work with `polymake`:\n",
    "##### Arrays\n",
    "\n",
    "The small object `Array` can be initialized in different ways and with different template parameters:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "a b c3 2 50 1 2 30 1 2 3 40 1 2 3 4"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "@array=(\"a\",\"b\",\"c\");\n",
    "$arr1=new Array<String>(\\@array); print $arr1;\n",
    "$arr2=new Array<Int>([3,2,5]); print $arr2;\n",
    "$arr3=new Array<Int>(0,1,2,3); print $arr3;\n",
    "$arr4=new Array<Int>(0..4); print $arr4;\n",
    "$arr5=new Array<Int>($arr4); print $arr5;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "You have random access:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "100 1 2 3 4"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$arr5->[0] = 100;\n",
    "print $arr5;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " It is also possible to convert the `C++`-object `Array` into a `Perl`-array by writing \n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3 2 5"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "@arr4=@{$arr4}; print $arr2;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    " or simply\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "@arr4=@$arr4;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "##### Sets\n",
    "\n",
    "On `C++`-side sets are stored in a balanced binary search (AVL) tree. For more information see the [PTL-documentation](https://polymake.org/release_docs/master/PTL/classpm_1_1Set.html). In many cases, the small objects can be converted into `Perl`-types in the expected way: \n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{2 3 5}3"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$set=new Set<Int>(3,2,5); print $set;\n",
    "print $set->size;\n",
    "@array_from_set=@$set;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "##### Matrices\n",
    "\n",
    "Here is a simple way to initialize a matrix:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2 1 4 0 0\n",
       "3 1 5 2 1\n",
       "1 0 4 0 6\n"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$mat=new Matrix<Rational>([[2,1,4,0,0],[3,1,5,2,1],[1,0,4,0,6]]);\n",
    "print $mat;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    " You could also define it by passing a reference to an (`Perl`-)array of `Vectors`. The single entries are interpreted as different rows: \n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "$row1=new Vector<Rational>([2,1,4,0,0]);\n",
    "$row2=new Vector<Rational>([3,1,5,2,1]);\n",
    "$row3=new Vector<Rational>([1,0,4,0,6]);\n",
    "@matrix_rows=($row1,$row2,$row3);\n",
    "$matrix_from_array=new Matrix<Rational>(\\@matrix_rows);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    " You can change a single entry of a matrix in the following way (if it is not already assigned to an immutable property like `VERTICES`!):\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7\n",
       "2 1 4 0 0\n",
       "3 7 5 2 1\n",
       "1 0 4 0 6\n",
       "\n",
       "2 1 4 0 0\n",
       "3 7 8 2 1\n",
       "1 0 4 0 6\n"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$mat->row(1)->[1]=7;\n",
    "print $mat->row(1)->[1], \"\\n\";\n",
    "print $mat, \"\\n\";\n",
    "$mat->elem(1,2)=8;\n",
    "print $mat;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    " A unit matrix of a certain dimension can be defined via the user-function `unit_matrix<COORDINATE_TYPE>(.)`: \n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3) (0 4)\n",
       "(3) (1 4)\n",
       "(3) (2 4)\n"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$unit_mat=4*unit_matrix<Rational>(3);\n",
    "print $unit_mat;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    " The reason for the \"strange output\" is the implementation as *sparse matrix*: \n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Polymake::common::SparseMatrix_A_Rational_I_NonSymmetric_Z"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print ref($unit_mat);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "However, some functions cannot deal with this special type of matrix. In this case it is necessary to transform the sparse matrix into a dense matrix first via:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4 0 0\n",
       "0 4 0\n",
       "0 0 4\n"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$dense=new Matrix<Rational>($unit_mat);print $dense;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    " or just\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4 0 0\n",
       "0 4 0\n",
       "0 0 4\n"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$dense2=dense($unit_mat);print $dense2;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    " You can also work with matrices that have different types of coordinates like `Rational`, `Float`, or `Int`: \n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3/5 0 0 0 0\n",
       "0 3/5 0 0 0\n",
       "0 0 3/5 0 0\n",
       "0 0 0 3/5 0\n",
       "0 0 0 0 3/5\n",
       "\n",
       "2 1 4 0 0\n",
       "3 7 8 2 1\n",
       "1 0 4 0 6\n",
       "3/5 0 0 0 0\n",
       "0 3/5 0 0 0\n",
       "0 0 3/5 0 0\n",
       "0 0 0 3/5 0\n",
       "0 0 0 0 3/5\n",
       "\n",
       "1 0 0 0 0\n",
       "0 1 0 0 0\n",
       "0 0 1 0 0\n",
       "0 0 0 1 0\n",
       "0 0 0 0 1\n",
       "\n"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$m_rat=new Matrix<Rational>(3/5*unit_matrix<Rational>(5)); print $m_rat, \"\\n\"; \n",
    "$m2=$mat/$m_rat; print $m2, \"\\n\";\n",
    "$m_int=new Matrix<Int>(unit_matrix<Rational>(5)); print $m_int, \"\\n\";"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sometimes there is incompatible types:\n",
    "```perl\n",
    "> $m3=$m_rat/$m_int;\n",
    "```\n",
    "```\n",
    "C++/perl Interface module compilation failed; most likely due to a type mismatch.\n",
    "Set the variable $Polymake::User::Verbose::cpp to a positive value and repeat for more details.\n",
    "```\n",
    "\n",
    "The error message indicates that you need to convert the integer matrix to a rational matrix first:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3/5 0 0 0 0\n",
       "0 3/5 0 0 0\n",
       "0 0 3/5 0 0\n",
       "0 0 0 3/5 0\n",
       "0 0 0 0 3/5\n",
       "1 0 0 0 0\n",
       "0 1 0 0 0\n",
       "0 0 1 0 0\n",
       "0 0 0 1 0\n",
       "0 0 0 0 1\n"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$m3=$m_rat/(convert_to<Rational>($m_int)); print $m3;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    " By \"/\" you can add rows to a matrix, whereas \"|\" adds columns. By the way, this also works for `Vector`.\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0 1 0 0 0 0\n",
       "0 0 1 0 0 0\n",
       "0 0 0 1 0 0\n",
       "0 0 0 0 1 0\n",
       "0 0 0 0 0 1\n"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$z_vec=zero_vector<Int>($m_int->rows);\n",
    "$extended_matrix=($z_vec|$m_int); print $extended_matrix;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "It is also possible to nest template parameters in any way you like, e.g.\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{2 5 6}\n",
       "{2 3 5}\n",
       "Polymake::common::Array__Set__Int"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$set=new Set<Int>(3,2,5);\n",
    "$template_Ex=new Array<Set<Int>>((new Set<Int>(5,2,6)),$set); print $template_Ex; print ref($template_Ex);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "However, if you use a template combination, you have never used before, it may take some time until you see the result. This is due to the fact that `polymake` compiles your new combination *on the fly*. But this is only a one-time effect, and next time you use this combination it will work without delay.\n",
    "\n",
    "#### \"Big Objects\": Objects with properties\n",
    "\n",
    "A big object is an instance of a data type which represents a mathematical concept with clear semantics. They may have template parameters.\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "$p=new Polytope<Rational>(POINTS=>cube(4)->VERTICES);\n",
    "$lp=new LinearProgram<Rational>(LINEAR_OBJECTIVE=>[0,1,1,1,1]);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Big objects have properties which come with a type, which is either built-in or a small object type or a big object type, and which can be accessed using the `-``>` operator.\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/html": [
       "<details><summary><pre style=\"display:inline\"><small>Click here for additional output</small></pre></summary>\n",
       "<pre>\n",
       "polymake: used package lrs\n",
       "  Implementation of the reverse search algorithm of Avis and Fukuda.\n",
       "  Copyright by David Avis.\n",
       "  http://cgm.cs.mcgill.ca/~avis/C/lrs.html\n",
       "\n",
       "</pre>\n",
       "</details>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# access the property named `LP`:\n",
    "$p->LP=$lp;\n",
    "# properties can have properties themselves.\n",
    "print $p->LP->MAXIMAL_VALUE;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "Scalar properties can be used in arithmetic expressions right away.\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "$i = ($p->N_FACETS * $p->N_FACETS) * 15;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "960"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $i;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Check out the tutorial on [properties](properties.ipynb) to learn more about the way properties are used and computed.\n",
    "\n",
    "### A small example script...\n",
    "\n",
    "...to demonstrate the usage of `polymake`/Perl. You can download the matrix file [here](https://polymake.org/lib/exe/fetch.php/points.demo).\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### load matrix from file\n",
    "open(INPUT, \"< demo/Workshop2011/points.demo\");\n",
    "$matrix=new Matrix<Rational>(<INPUT>);\n",
    "close(INPUT);\n",
    "print $matrix;\n",
    "\n",
    "\n",
    "### create a polytope from the matrix\n",
    "$p=new Polytope<Rational>(POINTS=>$matrix);\n",
    "print $p->FACETS;\n",
    "print $p->DIM;\n",
    "print $p->VERTEX_SIZES;\n",
    "\n",
    "\n",
    "### print \"simple\" vertices\n",
    "for(my $i=0;$i<scalar(@{$p->VERTEX_SIZES});$i++){\n",
    "    if($p->VERTEX_SIZES->[$i]==$p->DIM){\n",
    "    print $i.\": \".$p->VERTICES->row($i).\"\\n\";\n",
    "    }\n",
    "}\n",
    "\n",
    "\n",
    "### put their indices in a set\n",
    "$s=new Set<Int>();\n",
    "for(my $i=0;$i<scalar(@{$p->VERTEX_SIZES});$i++){\n",
    "    if($p->VERTEX_SIZES->[$i]==$p->DIM){\n",
    "    $s+=$i;\n",
    "    }\n",
    "}\n",
    "\n",
    "\n",
    "### iterate the set in two different ways\n",
    "foreach(@{$s}){\n",
    "    print $p->VERTICES->row($_).\"\\n\";\n",
    "}\n",
    "foreach my $index(@{$s}){\n",
    "    print $p->VERTICES->row($index).\"\\n\";\n",
    "}\n",
    "\n",
    "\n",
    "### create a minor of the vertices matrix that only contains the simple ones\n",
    "$special_points=$p->VERTICES->minor($s,All); print $special_points;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Writing scripts\n",
    "\n",
    "Comprehensive information on how to use scripts within `polymake` can be found [here](https://polymake.org/doku.php/user_guide/howto/scripting)."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "polymake",
   "language": "polymake",
   "name": "polymake"
  },
  "language_info": {
   "codemirror_mode": "perl",
   "file_extension": ".pl",
   "mimetype": "text/x-polymake",
   "name": "polymake"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
