{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# polymake for the Perl Newbie\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",
    "    \n",
    "     polytope > i=5;\n",
    "    polymake:  ERROR: Unquoted string \"i\" may clash with future reserved word.\n",
    "    </code>\n",
    "\n",
    "\n",
    "    Here are some simple commands illustrating how to use the different data structures:\n",
    "    ==Scalars==\n",
    "    <code>\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$i=5;\n",
    "$j=6;\n",
    "$sum=$i+$j; print $sum;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "##### Arrays\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "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);"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "##### Hashes\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "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);"
   ]
  },
  {
   "attachments": {},
   "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 structures. `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": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$p = new Polytope(POINTS=>[[1,0,1],[1,0,-1],[1,1,0],[1,-1,0]]);"
   ]
  },
  {
   "attachments": {},
   "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": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Polymake::polytope::Polytope__Rational=ARRAY(0x2f2f1c0)\n",
       "\n"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $p;"
   ]
  },
  {
   "attachments": {},
   "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:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Polytope<Rational>\n",
       "\n"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $p->type->full_name;"
   ]
  },
  {
   "attachments": {},
   "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](/release_docs/latest/common.html) under the heading \"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": null,
   "metadata": {},
   "outputs": [],
   "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;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "You have random access:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "100 1 2 3 4\n",
       "\n"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$arr5->[0] = 100;\n",
    "print $arr5;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " It is also possible to convert the `C++`-object `Array` into a `Perl`-array by writing <code>\n",
    "> @arr4=@{$arr4}; print $arr2;\n",
    "</code> or simply<code>\n",
    "> @arr4=@$arr4;\n",
    "</code>\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: <code>\n",
    "> $set=new Set<Int>(3,2,5); print $set;\n",
    "> print $set->size;\n",
    "> @array_from_set=@$set;\n",
    "</code>\n",
    "##### Matrices\n",
    "\n",
    "Here is a simple way to initialize a matrix:<code>\n",
    "> $mat=new Matrix<Rational>([2,1,4,0,0],[3,1,5,2,1],[1,0,4,0,6](2,1,4,0,0],[3,1,5,2,1],[1,0,4,0,6));\n",
    "> print $mat;\n",
    "</code> You could also define it by passing a reference to an (`Perl`-)array of `Vectors`. The single entries are interpreted as different rows: <code>\n",
    "> $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);\n",
    "</code> 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`!):<code>\n",
    "> $mat->row(1)->[1]=7; print $mat->row(1)->[1];\n",
    "> print $mat;\n",
    "> $mat->(1,2)=8; print $mat;\n",
    "</code> A unit matrix of a certain dimension can be defined via the user-function `unit_matrix<COORDINATE_TYPE>(.)`: <code>\n",
    "> $unit_mat=4*unit_matrix<Rational>(3);\n",
    "> print $unit_mat;\n",
    "</code> The reason for the \"strange output\" is the implementation as *sparse matrix*: <code>\n",
    "> print ref($unit_mat);\n",
    "</code>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:<code>\n",
    "> $dense=new Matrix<Rational>($unit_mat);print $dense;\n",
    "</code> or just<code>\n",
    "> $dense2=dense($unit_mat);print $dense2;\n",
    "</code> You can also work with matrices that have different types of coordinates like `Rational`, `Float`, or `Int`: <code>\n",
    "> $m_rat=new Matrix<Rational>(3/5*unit_matrix<Rational>(5)); print $m_rat; \n",
    "> $m2=$mat/$m_rat; print $m2;\n",
    "> $m_int=new Matrix<Int>(unit_matrix<Rational>(5)); print $m_int;\n",
    "> $m3=$m_rat/$m_int;\n",
    "</code> The error message <code>\n",
    "polymake:  ERROR: undefined operator Matrix<Rational> / Matrix<Int> at input line 1.\n",
    "</code>indicates that you need to convert the integer matrix to a rational matrix first:<code>\n",
    "> $m3=$m_rat/convert_to<Rational>($m_int); print $m3;\n",
    "</code> By \"/\" you can add rows to a matrix, whereas \"|\" adds columns. By the way, this also works for `Vector`.<code>\n",
    "> $z_vec=zero_vector<Int>($m_int->rows);\n",
    "> $extended_matrix=($z_vec|$m_int); print $extended_matrix;\n",
    "</code>\n",
    "It is also possible to nest template parameters in any way you like, e.g.\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "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);"
   ]
  },
  {
   "attachments": {},
   "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": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$p=new Polytope<Rational>(POINTS=>cube(4)->VERTICES);\n",
    "$lp=new LinearProgram<Rational>(LINEAR_OBJECTIVE=>[0,1,1,1,1]);"
   ]
  },
  {
   "attachments": {},
   "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": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# access the property named `LP`:\n",
    "$p->LP=$lp;\n",
    "# properties can have properties themselves.\n",
    "print $p->LP->MAXIMAL_VALUE;"
   ]
  },
  {
   "attachments": {},
   "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": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$i = ($p->N_FACETS * $p->N_FACETS) * 15;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2940\n",
       "\n"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $i;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Check out the tutorial on [properties](properties) 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 {{:points.demo| here}}.\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "> \n"
      ]
     },
     "execution_count": 5,
     "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;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "> \n"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### 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;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "> \n"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### 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",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "> \n"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### 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",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "> \n"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "### 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",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "### create a minor of the vertices matrix that only contains the simple ones\n",
    "$special_points=$p->VERTICES->minor($s,All); print $special_points;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "### Writing scripts\n",
    "\n",
    "Comprehensive information on how to use scripts within `polymake` can be found [here](scripting/start).\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "polymake",
   "language": "polymake",
   "name": "polymake"
  },
  "language_info": {
   "codemirror_mode": "perl",
   "file_extension": ".pm",
   "mimetype": "text/x-polymake",
   "name": "polymake"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
