{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Polytopes and Linear Maps\n",
    "\n",
    "polymake works with [homogeneous coordinates](tutorial/coordinates), which is why *projective* linear transformations are natural to apply to polytopes. Affine transformations are a special case.  By the way, a *transformation* is always bijective, by definition.\n",
    "\n",
    "### Transformations\n",
    "\n",
    "We start out with a regular 3-cube ...\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$c=cube(3);"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1 -1 -1 -1\n",
       "1 1 -1 -1\n",
       "1 -1 1 -1\n",
       "1 1 1 -1\n",
       "1 -1 -1 1\n",
       "1 1 -1 1\n",
       "1 -1 1 1\n",
       "1 1 1 1\n",
       "\n"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $c->VERTICES;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "... and a homethetic image:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$T=new Matrix<Rational>([[1,0,0,0],[0,2,0,0],[0,0,3,0],[0,0,0,4]]);"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$ct=transform($c,$T);"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1 -2 -3 -4\n",
       "1 2 -3 -4\n",
       "1 -2 3 -4\n",
       "1 2 3 -4\n",
       "1 -2 -3 4\n",
       "1 2 -3 4\n",
       "1 -2 3 4\n",
       "1 2 3 4\n",
       "\n"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $ct->VERTICES;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Our points are row vectors, so (projective) linear transformations are applied by multiplying the corresponding matrix from the right.  In the above example the first column of the matrix T is the vector [1,0,0,0] which means that T acts as an affine map on *R³*.  Also the first row reads [1,0,0,0], and this says that T fixes the origin.  This is to say, T acts linearly.\n",
    "\n",
    "The purpose of the function transform used above is not only to work on the VERTICES but also on the FACETS (if available).\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1 1 0 0\n",
       "1 -1 0 0\n",
       "1 0 1 0\n",
       "1 0 -1 0\n",
       "1 0 0 1\n",
       "1 0 0 -1\n",
       "    \n"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $c->FACETS;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1 1/2 0 0\n",
       "1 -1/2 0 0\n",
       "1 0 1/3 0\n",
       "1 0 -1/3 0\n",
       "1 0 0 1/4\n",
       "1 0 0 -1/4\n",
       "\n"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $ct->FACETS;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "If we also read the FACETS as row vectors then the corresponding action is given by the transpose of the inverse of T.\n",
    "\n",
    "\n",
    "### Non-Bijective Linear Maps\n",
    "\n",
    "Sometimes we are interested in images of polytopes under a linear map which is not bijective.  An interesting case are projections, for instance, onto a coordinate subspace.\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$A=new Matrix<Rational>([[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,0]]);"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "Using transform would not work in this case:\n",
    "\n",
    "    \n",
    "    # polytope > transform($c,$A);\n",
    "    polymake:  ERROR: matrix not invertible\n",
    "\n",
    "The above error says that transform is not the proper function to deal with this situation as the linear map given by A is not invertible.  \n",
    "\n",
    "To produce the image the following command works:\n",
    "\n",
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "$ca=new Polytope<Rational>(POINTS=>$c->VERTICES*$A);"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1 -1 -1 0\n",
       "1 1 -1 0\n",
       "1 -1 1 0\n",
       "1 1 1 0\n",
       "\n"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $ca->VERTICES;"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Since we are applying a non-bijective map, the images of VERTICES do not have to be VERTICES.  Moreover, even if this is the case, multiple VERTICES may be mapped to the same (like two onto one as in the example above).  If a polytope already has a double description, that is, both VERTICES and FACETS are known, then the VERTICES and FACETS of the image under a transformation (that is, a bijective map) cane be read off right away.  However, in the non-bijective case a convex hull computation is required to compute the FACETS of the image.\n",
    "\n",
    "\n",
    "### Special Examples of Linear Maps to Apply\n",
    "\n",
    "[to be continued]\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
}