{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ILP and Hilbert bases\n",
    "\n",
    "### A first example\n",
    "\n",
    "First we will construct a new rational polytope:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$p=new Polytope<Rational>;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$p->POINTS=<<\".\";\n",
    "1 0 0 0\n",
    "1 1 0 0\n",
    "1 0 1 0\n",
    "1 1 1 0\n",
    "1 0 0 1\n",
    "1 1 0 1\n",
    "1 0 1 1\n",
    "1 1 1 1\n",
    "."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Note that points in `polymake` are always given in homogenous coordinates. I.e., the point (a,b,c) in R<sup>3</sup> is represented as `1 a b c` in `polymake`.\n",
    "\n",
    "Now we can examine some properties of `$p`. For instance we can determine the number of facets or whether `$p` is simple:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6\n",
       "    \n"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $p->N_FACETS;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1\n",
       "\n"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $p->SIMPLE;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "As you might already have noticed, our polytope is just a 3-dimensional cube. So there would have been an easier way to create it using the client `cube`:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$c = cube(3,0);"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "(You can check out the details of any function in the [`polymake` documentation](http://wwwopt.mathematik.tu-darmstadt.de/polymake_doku/2.9.8/).)\n",
    "\n",
    "And we can also verify that the two polytopes are actually equal:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1\n",
       "\n"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print equal_polyhedra($p,$c);"
   ]
  },
  {
   "attachments": {
    "rand_sphere.png": {
     "image/png": [
      "Tm90IEZvdW5k"
     ]
    }
   },
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "### Another example\n",
    "\n",
    "Now let us proceed with a somewhat more interesting example: The convex hull of 20 randomly chosen points on the 2-dimensional sphere.\n",
    "![{{ :tutorial:ilp:rand_sphere.png?200|}}](attachment:rand_sphere.png)\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$rs = rand_sphere(3,20);"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "`polymake` can of course visualise this polytope:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$rs->VISUAL;"
   ]
  },
  {
   "attachments": {
    "rand_sphere_lattice.png": {
     "image/png": [
      "Tm90IEZvdW5k"
     ]
    }
   },
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "Now we will create yet another new polytope by scaling our random sphere by a factor lambda. (Otherwise there are rather few integral points contained in it.)\n",
    "\n",
    "To this end, we have to multiply every coordinate (except for the homogenising 1 in the beginning) of every vertex by lamda. Then we can create a new polytope by specifying its vertices.\n",
    "\n",
    "![{{ :tutorial:ilp:rand_sphere_lattice.png?200|}}](attachment:rand_sphere_lattice.png)\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$lambda=2;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$s=new Matrix<Rational>([[1,0,0,0],[0,$lambda,0,0],[0,0,$lambda,0],[0,0,0,$lambda]]);"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1 0 0 0\n",
       "0 2 0 0\n",
       "0 0 2 0\n",
       "0 0 0 2\n",
       "    \n"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $s;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$scaled_rs=new Polytope<Rational>(VERTICES=>($rs->VERTICES * $s), LINEALITY_SPACE=>[]);"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "`polymake` can visualise the polytope together with its lattice points:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$scaled_rs->VISUAL->LATTICE_COLORED;"
   ]
  },
  {
   "attachments": {
    "ilp_lattice.png": {
     "image/png": [
      "Tm90IEZvdW5k"
     ]
    }
   },
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "Now will construct the integer hull of `$scaled_rs` and visualise it:\n",
    "\n",
    "![{{ :tutorial:ilp:ilp_lattice.png?200|}}](attachment:ilp_lattice.png)\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$integer_hull=new Polytope<Rational>(POINTS=>$scaled_rs->LATTICE_POINTS);"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$integer_hull->VISUAL->LATTICE_COLORED;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "In order to obtain the integer hull we simply define a new polytope `$integer_hull` as the convex hull of all `LATTICE_POINTS` contained in `$scaled_rs`.\n",
    "\n",
    "Note that if we give `POINTS` (in contrast to `VERTICES`) `polymake` constructs a polytope that is the convex hull of the given points regardless of whether they are vertices or not. I.e., redundacies are allowed here.\n",
    "\n",
    "If you specify `VERTICES` you have to make sure yourself that your points are actually vertices since `polymake` does not check this. You also need to specify the `LINEALITY_SPACE`, see [ Tutorial on polytopes](tutorial/apps_polytope ).\n",
    "\n",
    "### Linear Programming\n",
    "\n",
    "Now that we have constructed a nice integral polytope we want to apply some linear program to it.\n",
    "\n",
    "First we define a `LinearProgram` with our favourite `LINEAR_OBJECTIVE`. The linear objective is an given as a vector of length d+1, d being the dimension of the space. The vector [c<sub>0</sub>,c<sub>1</sub>, ..., c<sub>d</sub>] corresponds to the linear objective c<sub>0</sub> + c<sub>1</sub>x<sub>1</sub> + ... + c<sub>d</sub>x<sub>d</sub>.\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$objective=new LinearProgram<Rational>(LINEAR_OBJECTIVE=>[0,1,1,1]);"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Then we define a new polytope, which is a copy of our old one (`$inter_hull`) with the LP as an additional property.\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$ilp=new Polytope<Rational>(VERTICES=>$integer_hull->VERTICES, LP=>$objective);"
   ]
  },
  {
   "attachments": {
    "ilp_max_face.png": {
     "image/png": [
      "Tm90IEZvdW5k"
     ]
    },
    "ilp_min_face.png": {
     "image/png": [
      "Tm90IEZvdW5k"
     ]
    }
   },
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "![{{ :tutorial:ilp:ilp_min_face.png?200|}}](attachment:ilp_min_face.png)\n",
    "![{{ :tutorial:ilp:ilp_max_face.png?200|}}](attachment:ilp_max_face.png)\n",
    "\n",
    "And now we can perform some computations:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2\n",
       "    \n"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $ilp->LP->MAXIMAL_VALUE;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{6 9 10}\n",
       "    \n"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $ilp->LP->MAXIMAL_FACE;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$ilp->VISUAL->MIN_MAX_FACE;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Hence the LP attains its maximal value 2 on the  2-face spanned by the vertices 6, 9 and 10.\n",
    "\n",
    "`polymake` can visualise the polytope and highlight both its maximal and minimal face in a different (by default admittedly almost painful ;-) ) colour. Here you see the maximal face `{6 9 10}` in red and the minimal face `{0 3}` (on the opposite side of the polytope) in yellow.\n",
    "\n",
    "\n",
    "Note though that since we started out with a random polytope these results may vary if we perform the same computations another time on a different random polytope.\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1 -1 0 -1\n",
       "1 -1 0 1\n",
       "1 -1 1 0\n",
       "1 0 -1 -1\n",
       "1 0 -1 1\n",
       "1 0 1 -1\n",
       "1 0 1 1\n",
       "1 1 -1 0\n",
       "1 1 0 -1\n",
       "1 1 0 1\n",
       "1 1 1 0\n",
       "\n"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $ilp->VERTICES;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "### Hilbert bases\n",
    "\n",
    "Finally, we can have `polymake` compute and print a Hilbert basis for the cone spanned by `$ilp`.  Notice that this requires normaliz or 4ti2 to be installed in order to work.\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1 0 0 -1\n",
       "1 -1 1 0\n",
       "1 1 0 0\n",
       "1 0 1 0\n",
       "1 0 1 -1\n",
       "1 1 1 0\n",
       "1 0 1 1\n",
       "1 1 0 -1\n",
       "1 1 0 1\n",
       "1 0 0 0\n",
       "1 0 0 1\n",
       "1 1 -1 0\n",
       "1 -1 0 -1\n",
       "1 -1 0 0\n",
       "1 -1 0 1\n",
       "1 0 -1 -1\n",
       "1 0 -1 0\n",
       "1 0 -1 1\n",
       "\n"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $ilp->HILBERT_BASIS;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\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
}