{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Using polymake to Check Whether a Matroid is 1-Flowing\n",
    "\n",
    "The original PDF version was written by [Gordon Royle](https://research-repository.uwa.edu.au/en/persons/gordon-royle).\n",
    "Transformed into ipynb by [Francisco Criado](http://page.math.tu-berlin.de/~criado/index.html), Daniel Oberländer, [Manuel Radons](http://page.math.tu-berlin.de/~radons/), and [Michael Joswig](http://page.math.tu-berlin.de/~joswig/).\n",
    "\n",
    "### 1.Introduction\n",
    "\n",
    "A binary matroid $M$ is said to be $\\{e\\}$-flowing if for every element $e \\in E(M)$,\n",
    "a certain polytope defined using the circuits of $M$ that pass through $e$ has\n",
    "integral vertices. A matroid is called 1-flowing if it is $\\{e\\}$-flowing for every\n",
    "element of $E(M)$. In this tutorial-style note, we’ll work through an example,\n",
    "namely the matroid $\\operatorname{AG}(3, 2)$ and demonstrate the computational process to\n",
    "checking whether or not it is 1-flowing, using polymake, which is a computer algebra system for polytopes and associated objects."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "application \"matroid\";"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The binary matroid $\\operatorname{AG}(3, 2)$ consists of the binary vectors in $\\operatorname{PG}(3, 2)$ which lie off a hyperplane (i.e. all the affine points) and so can easily be seen to be represented by the matrix consisting of every column vector with first coordinate equal to one."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1 1 1 1 1 1 1 1\n",
       "0 0 0 0 1 1 1 1\n",
       "0 0 1 1 0 0 1 1\n",
       "0 1 0 1 0 1 0 1\n"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$M = new Matrix<Int>([[1,1,1,1,1,1,1,1],[0,0,0,0,1,1,1,1],[0,0,1,1,0,0,1,1],[0,1,0,1,0,1,0,1]]);\n",
    "print $M;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The 8 matroid elements (that is, matrix columns) are labeled 0, 1, . . ., 7 in the\n",
    "natural order. Then AG(3, 2) has 14 circuits, all of size 4, as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{0 1 2 3}\n",
       "{0 1 4 5}\n",
       "{0 1 6 7}\n",
       "{0 2 4 6}\n",
       "{0 2 5 7}\n",
       "{0 3 4 7}\n",
       "{0 3 5 6}\n",
       "{1 2 4 7}\n",
       "{1 2 5 6}\n",
       "{1 3 4 6}\n",
       "{1 3 5 7}\n",
       "{2 3 4 5}\n",
       "{2 3 6 7}\n",
       "{4 5 6 7}\n"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$AG32 = new Matroid(BINARY_VECTORS=>cols($M));\n",
    "\n",
    "print $AG32->CIRCUITS;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The automorphism group of $\\operatorname{AG}(3,2)$ is transitive on the ground set, and\n",
    "so to check whether the matrix is 1-flowing we only need to test that it\n",
    "is $\\{0\\}$-flowing. Each circuit containing 0 yields one constraint on a set of\n",
    "variables identified with $\\operatorname{E}(M)\\{0\\}$, which we will call $\\{x_1, x_2, \\ldots , x_7\\}$ with\n",
    "the natural correspondence. Each of the circuit constraints is that the sum of the corresponding variables is at least 1. Thus we get the 7 constraints\n",
    "shown in table below."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| Circuit       | &nbsp;            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Constraint &nbsp; &nbsp; &nbsp; &nbsp;            |\n",
    "| ------------- |:-------------------------------:|\n",
    "| $0123$        | $x_1+x_2+x_3\\geq 1$             |\n",
    "| $0145$        | $x_1+x_4+x_5\\geq 1$             |\n",
    "| $0167$        | $x_1+x_6+x_7\\geq 1$             |\n",
    "| $0246$        | $x_2+x_4+x_6\\geq 1$             |\n",
    "| $0257$        | $x_2+x_5+x_7\\geq 1$             |\n",
    "| $0347$        | $x_3+x_4+x_7\\geq 1$             |\n",
    "| $0356$        | $x_3+x_5+x_6\\geq 1$             |\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In addition to these constraints, each variable must be non-negative, and so we add $x_i \\geq 0$ to the list of constraints. These gives us a total of fourteen\n",
    "constraints, each determining a half-space in $\\mathbb{R}^7$, and the intersection of\n",
    "these half-spaces is an unbounded polytope; an expression for a polytope in this fashion is called an $H$-representation of the polytope ($H$ for half-space,\n",
    "I suppose).\n",
    "\n",
    "A polytope can also be described by its vertices or extreme points and, if it\n",
    "is unbounded, its rays in addition. The matroid is $\\{e\\}$-flowing if the polytope described above has integral vertices, that is, its vertices have integer\n",
    "coordinates. The description of a polytope by its vertices (and rays) is called\n",
    "its $V$-representation and so the task is to convert the H-representation into\n",
    "the $V$-representation and check integrality.\n",
    "\n",
    "Several algorithms for this task and their implementations exist.\n",
    "polymake has interfaces to many of them, e.g., cdd by Komei Fukuda.\n",
    "For a survey and extensive comparisons see Assarf et al, <i>Math. Program. Comput.</i> 9.1, pp. 1–38. [doi: 10.1007/s12532-016-0104-z](https://link.springer.com/article/10.1007/s12532-016-0104-z)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. The Computation\n",
    "\n",
    "The basic process is straightforward:\n",
    "\n",
    "1. Construct a polytope in polymake using the H-representation\n",
    "2. Ask polymake to return the $V$-representation.\n",
    "\n",
    "In practice, it is almost as straightforward, with just some possible teething\n",
    "troubles in mastering the syntax of polymake. A *constraint* in polymake of\n",
    "the form\n",
    "\n",
    "$$a^T x \\geq b$$\n",
    "\n",
    "(where a is a (column) vector of coefficients, $x$ the vector of variables and $b$\n",
    "a vector of constants) must first be re-expressed in the form\n",
    "\n",
    "$$−b + a^T x \\geq 0$$\n",
    "\n",
    "and then the constant term and coefficients in this expression gathered into\n",
    "one row vector in this order, yielding the vector\n",
    "\n",
    "$$[b, a_1, a_2, \\dots , a_n]$$.\n",
    "\n",
    "The matrix constructed below shows the circuit constraints expressed in polymake form."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1 1 1 1 0 0 0 0\n",
       "-1 1 0 0 1 1 0 0\n",
       "-1 1 0 0 0 0 1 1\n",
       "-1 0 1 0 1 0 1 0\n",
       "-1 0 1 0 0 1 0 1\n",
       "-1 0 0 1 1 0 0 1\n",
       "-1 0 0 1 0 1 1 0\n"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "$circuit_constraints = new Matrix([\n",
    "[-1,1,1,1,0,0,0,0],\n",
    "[-1,1,0,0,1,1,0,0],\n",
    "[-1,1,0,0,0,0,1,1],\n",
    "[-1,0,1,0,1,0,1,0],\n",
    "[-1,0,1,0,0,1,0,1],\n",
    "[-1,0,0,1,1,0,0,1],\n",
    "[-1,0,0,1,0,1,1,0]]);\n",
    "\n",
    "print $circuit_constraints;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We also need the constraints for non-negativity, but these can be constructed\n",
    "programatically rather than manually because the appropriate matrix is just\n",
    "a zero column vector adjacent to an identify matrix,"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "$nonneg_constraints = zero_vector(7) | unit_matrix(7);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "and the set of all constraints is obtained from the union of both matrices."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "$all_ineq = $circuit_constraints / $nonneg_constraints;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let’s just check that all is in order"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0: x1 + x2 + x3 >= 1\n",
       "1: x1 + x4 + x5 >= 1\n",
       "2: x1 + x6 + x7 >= 1\n",
       "3: x2 + x4 + x6 >= 1\n",
       "4: x2 + x5 + x7 >= 1\n",
       "5: x3 + x4 + x7 >= 1\n",
       "6: x3 + x5 + x6 >= 1\n",
       "7: x1 >= 0\n",
       "8: x2 >= 0\n",
       "9: x3 >= 0\n",
       "10: x4 >= 0\n",
       "11: x5 >= 0\n",
       "12: x6 >= 0\n",
       "13: x7 >= 0\n",
       "\n"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print_constraints($all_ineq);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally we can create the polytope and ask for its vertices!\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "application \"polytope\";"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0 0 0 0 0 0 0 1\n",
       "0 0 0 0 0 0 1 0\n",
       "0 0 1 0 0 0 0 0\n",
       "0 1 0 0 0 0 0 0\n",
       "0 0 0 1 0 0 0 0\n",
       "0 0 0 0 1 0 0 0\n",
       "0 0 0 0 0 1 0 0\n",
       "1 1 1 1 0 0 0 0\n",
       "1 0 0 1 1 0 0 1\n",
       "1 1 0 0 1 1 0 0\n",
       "1 0 1 0 1 0 1 0\n",
       "1 1/3 1/3 1/3 1/3 1/3 1/3 1/3\n",
       "1 0 0 1 0 1 1 0\n",
       "1 0 1 0 0 1 0 1\n",
       "1 1 0 0 0 0 1 1\n"
      ]
     },
     "execution_count": 9,
     "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": [
    "$p = new Polytope<Rational>(INEQUALITIES=>$all_ineq);\n",
    "\n",
    "print $p->VERTICES;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice that each row listing the vertices has eight coordinates, rather than\n",
    "seven. This is because our $7$-dimensional space has been embedded as the\n",
    "plane $x_0=1$ in an $8$-dimensional space in order to accommodate vertices\n",
    "and rays in a uniform manner. The rows with first coordinate equal to 1 are\n",
    "the vertices, while the others are the rays.\n",
    "\n",
    "We immediately see that this matroid is not $\\{0\\}$-flowing because the point\n",
    "$$(1/3, 1/3, 1/3, 1/3, 1/3, 1/3, 1/3)$$\n",
    "is a vertex of the associated polytope.\n",
    "\n",
    "A polytope whose vertices are integral is also called a <i>lattice polytope</i>.  If this is satisfied can be checked directly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print $p->LATTICE;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Seymour's Conjecture\n",
    "\n",
    "The fact that $AG(3, 2)$ is not $1$-flowing has of course long been known. And\n",
    "because the property of being $1$-flowing is closed under taking minors, this\n",
    "means that no binary matroid with an $AG(3, 2)$ minor is $1$-flowing either.\n",
    "\n",
    "There are two other known minor-minimal matroids with no $AG(3, 2)$-minor\n",
    "that are not $1$-flowing; these are the dual pair $T_{11}$ and $T_{11}^*$. Seymour conjectured that this is the complete set of excluded minors.\n",
    "\n",
    "**Conjecture. (Seymour)** A binary matroid is 1-flowing if and only if it has no $AG(3,2)$, $T_{11}$ or $T_{11}^*$ minor."
   ]
  }
 ],
 "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
}
