From db9ce073e36fea7026a752347304724ad2b2ae26 Mon Sep 17 00:00:00 2001 From: carlos alquezar Date: Thu, 24 Mar 2022 13:45:02 +0100 Subject: [PATCH] initial commit - from notebook to sage --- notebook/tutorial AplK.ipynb | 5461 ++++++++++++++++++++++++++++++++++ notebooks/todo-limpio.ipynb | 719 ----- notebooks/todo.ipynb | 2218 -------------- 3 files changed, 5461 insertions(+), 2937 deletions(-) create mode 100644 notebook/tutorial AplK.ipynb delete mode 100644 notebooks/todo-limpio.ipynb delete mode 100644 notebooks/todo.ipynb diff --git a/notebook/tutorial AplK.ipynb b/notebook/tutorial AplK.ipynb new file mode 100644 index 0000000..9d42879 --- /dev/null +++ b/notebook/tutorial AplK.ipynb @@ -0,0 +1,5461 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# About the organization of the notebook\n", + "\n", + "In this document, the implementation of different mathematical objects is explained. For each one, the information is structured in the following way:\n", + "\n", + "1) First section: Definition. The object is defined using mathematical language.\n", + "2) Second section: Implementation.\n", + " 1) Ideas and decisions made\n", + " 2) Initial declaration of the main class\n", + " 3) Implementation of a new method and examples\n", + "\n", + "Each class is declared iteratively, i.e., each method is added in a different cell in order to explain it properly and to show examples. This is done in that way for a didactic purpose. For that reason, the subsection 2.c) is repeated for each new method that is added to the main class.\n", + "\n", + "***" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The cochain algebra $(A_{PL})_{n}$\n", + "In this section it is implemented the graded commutative differential cochain algebra $(A_{PL})_{n}$. For more information, see [Rational homotopy theory, Felix, Halperin, Thomas, chapter 10.c)].\n", + "\n", + "## Definition\n", + "First, consider the free graded commutative algebra $\\Lambda(t_0,\\dots,t_n,y_0,\\dots,y_n)$, where the generators $t_i$ have degree $0$, and the generators $y_j$ have degree $1$. The differential, $d$, is given by \n", + "\n", + "* $d(t_i)=y_i$\n", + "* $d(y_j)=0$\n", + "\n", + "The cochain algebra $(A_{PL})_n$ is defined as the quotient of the previous algebra by the relations:\n", + "\n", + "\n", + "\n", + "$$(A_{PL})_n=\\frac{\\Lambda(t_0,\\dots,t_n,y_0,\\dots,y_n)}{<\\sum {t_i}-1,\\sum{y_j}>}$$\n", + "\n", + "\n", + "## Implementation\n", + "\n", + "$(A_{PL})_{n}$ is a graded commutatite differential algebra, GCDA. In order to work with GCDA's that are finitely generated by elements of $degree \\geq 1$, there is defined in SAGE a class called \"DifferentialGCAlgebra\". Our first problem is that our GCDA has generators of $degree=0$ (the generators $t_i$) and this class doesn't allow us to create such object. \n", + "\n", + "As a first approximation, in order to solve this problem, we will define a new class of GCDA's that internally will work with multigraded generators, but this feature will be transparent for the user. For that reason, we will extend the class \"DifferentialGCAlgebra_multigraded\" in order to add new methods that will be useful later." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Initial declaration of the main class" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from sage.algebras.commutative_dga import *\n", + "import copy\n", + "\n", + "class AplN(DifferentialGCAlgebra_multigraded, UniqueRepresentation):\n", + " \"\"\"\n", + " A differential multi-graded commutative algebra\n", + " \n", + " This class extends the DifferentialGCAlgebra_multigraded class\n", + " to create the algebra of polynomial differential forms with coefficients in QQ\n", + "\n", + " INPUT:\n", + "\n", + " - ``A`` -- a multi-graded commutative algebra\n", + " - ``differential`` -- the differential rules\n", + "\n", + " \"\"\"\n", + "\n", + " def __init__(self, A, differential):\n", + " \"\"\"\n", + " Initialize ``self``.\n", + "\n", + " INPUT:\n", + "\n", + " - ``A`` -- a multi-graded commutative algebra\n", + " - ``differential`` -- a differential\n", + " \"\"\"\n", + "\n", + " self.n = len(A._names)/2-1\n", + " DifferentialGCAlgebra_multigraded.__init__(self, A, differential)\n", + " self.t_relation = sum(self.gens()[:self.n+1])-1\n", + " self.y_relation = sum(self.gens()[self.n+1:])\n", + "\n", + " def _base_repr(self):\n", + " \"\"\"\n", + " Return the base string representation of ``self``.\n", + " \"\"\"\n", + "\n", + " s = DifferentialGCAlgebra._base_repr(self)\n", + " old = '{}'.format(self._degrees)\n", + " new = '{}'.format([i[0] for i in self._degrees_multi])\n", + " return s.replace(old, new)\n", + "\n", + " class Element(GCAlgebra_multigraded.Element, DifferentialGCAlgebra.Element):\n", + " \"\"\"\n", + " Element class of the commutative differential multi-graded algebra (Apl)n.\n", + " \"\"\"\n", + " pass\n", + " \n", + "def AlgebraPL(n):\n", + " \"\"\"\n", + " The graded commutative differential cochain algebra Apl of dimension ``n``\n", + "\n", + " INPUT:\n", + "\n", + " - ``n`` -- A non-negative integer corresponding to the number of generators of degree 0.\n", + " \"\"\"\n", + "\n", + " if (n<0):\n", + " raise ValueError('`n` must be a non-negative integer')\n", + " ts = ['t'+str(t) for t in range(n+1)]\n", + " ys = ['y'+str(t) for t in range(n+1)]\n", + " degrees = tuple((n+1)*[(0,2)])+tuple((n+1)*[(1,2)])\n", + " gca = GradedCommutativeAlgebra(QQ, names=ts+ys, degrees=degrees)\n", + " differentials = {gca.gens_dict()[ts[i]]:gca.gens_dict()[ys[i]] for i in range(n+1)}\n", + " return AplN(gca,differentials)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Example: creating an element of $(Apl)_{n}$" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Commutative Differential Graded Algebra with generators ('t0', 't1', 'y0', 'y1') in degrees [0, 0, 1, 1] over Rational Field with differential:\n", + " t0 --> y0\n", + " t1 --> y1\n", + " y0 --> 0\n", + " y1 --> 0\n", + "Defining t0, t1, y0, y1\n" + ] + } + ], + "source": [ + "apl = AlgebraPL(1)\n", + "print(apl)\n", + "apl.inject_variables()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "y0 + y1 + t0" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p = t0 + y0 + y1\n", + "p" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding new methods: homogeneity and total degree of a polynomial\n", + "\n", + "As we mentioned before, we use a multigraded algebra internally. Specifically, we use a bigraded algebra, where the generators have either degree $(0,2)$ or degree $(1,2)$ The first component of the bigrade represents the actual degree we want to use, and the second component is ignored (it is only needed to be an even number $>0$). In particular, the generators $t_i$ have internally a degree $(0,2)$ and the generators $y_j$ have degree $(1,2)$. In order to make it transparent for the user, we implement a several methods to get, for example, the homogeneous part of a polynomial, ignoring the mentioned bigrade, and taking into account only the first compoment of the multigrade." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "class AplN(AplN,UniqueRepresentation):\n", + " class Element(AplN.Element):\n", + " \"\"\"\n", + " Element class of the commutative differential multi-graded algebra (Apl)n.\n", + " \"\"\"\n", + " \n", + " def is_homogeneous(self):\n", + " \"\"\"\n", + " Return \"True\" if \"self\" is homogeneous and \"False\" otherwise.\n", + " \"\"\"\n", + " \n", + " degrees = set([k[0] for k in self.homogeneous_parts()])\n", + " return len(degrees) == 1\n", + " \n", + " def total_degree(self):\n", + " \"\"\"\n", + " Return the total degree of this element.\n", + " \"\"\" \n", + " \n", + " degrees = set([k[0] for k in self.homogeneous_parts()])\n", + " return max(degrees)\n", + " \n", + " def homogeneous_part(self,degree):\n", + " \"\"\"\n", + " Returns the homogeneous part of the element for a given degree.\n", + " \"\"\"\n", + "\n", + " if (degree<0):\n", + " raise ValueError('`degree` must be a non-negative integer')\n", + " parts = [self.homogeneous_parts()[k] for k in self.homogeneous_parts() if list(k)[0]==degree]\n", + " return sum(parts)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Example: checking the homogeneity of a given polynomial" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defining t0, t1, y0, y1\n" + ] + } + ], + "source": [ + "apl = AlgebraPL(1)\n", + "apl.inject_variables()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p = t0 + y0 + y1\n", + "p.is_homogeneous()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Example: getting the homogeneous part of a polynomial for a given degree" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Original polynomial: y0 + y1 + t0\n", + "Homogeneous part of degree 1 of p: y0 + y1\n" + ] + } + ], + "source": [ + "p = t0 + y0 + y1\n", + "deg = 1\n", + "print(\"Original polynomial:\", p)\n", + "print(\"Homogeneous part of degree\", deg, \"of p: \", p.homogeneous_part(degree=deg))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Example: getting the total degree of a polynomial" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "q = y0*y1 + t0*y1 + 1\n", + "q.total_degree()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding new method: reduce a polynomial by relations\n", + "\n", + "As seen in the definition, the algebra $(A_{PL})_{n}$ is the quiotient algebra\n", + "\n", + "$$(A_{PL})_n=\\frac{\\Lambda(t_0,\\dots,t_n,y_0,\\dots,y_n)}{<\\sum {t_i}-1,\\sum{y_j}>}$$\n", + "\n", + "Notice that there is an isomorphism between this algebra and the free algebra:\n", + "\n", + "$$ (A_{PL})_n \\cong \\Lambda(t_1,\\dots,t_n,y_1,\\dots,y_n) $$\n", + "\n", + "\n", + "In order to obtain a representative of a particular element on the free algebra, a method called \"reduce\" is added to the elements of our class. This method reduces the variables $t_0,y_0$ applying the following rules:\n", + "\n", + "$$t_0 = 1 - \\sum_{i=1}^{n} t_i$$\n", + "$$y_0 = -\\sum_{j=1}^{n} y_j$$\n", + "\n", + "Thus, after applying this method, an element of $(A_{PL})_{n}$ will be represented as an element of the algebra $\\Lambda(t_1,\\dots,t_n,y_1,\\dots,y_n)$.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "class AplN(AplN,UniqueRepresentation):\n", + " class Element(AplN.Element):\n", + " \"\"\"\n", + " Element class of the commutative differential multi-graded algebra (Apl)n.\n", + " \"\"\"\n", + " def reduce(self, relations=[]):\n", + " \"\"\"\" \n", + " The method reduces the polynomial by the Ideal \n", + " \n", + " INPUT::\n", + " - p: polynomial in variables t_0,..t_n,y_0,...,y_n\n", + " - relations (optional): if relations are given, the polynomial is reduced following\n", + " this rules. If no relations are given, the polynomial is reduced taking into\n", + " account the relations of the parent algebra.\n", + " \n", + " OUTPUT::\n", + " - The polynomial after applying the corresponding relations \n", + " \"\"\"\n", + " apl = self.parent()\n", + " dim = len(apl.gens())//2-1\n", + " if relations:\n", + " return DifferentialGCAlgebra.Element.reduce(self, relations)\n", + " else:\n", + " return DifferentialGCAlgebra.Element.reduce(self, [apl.t_relation, apl.y_relation])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Example: getting the reduced polynomial of a given element" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defining t0, t1, y0, y1\n" + ] + } + ], + "source": [ + "apl = AlgebraPL(1)\n", + "apl.inject_variables()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "unreduced polynomial: y0 + y1 + t0\n", + "reduced polynomial: -t1 + 1\n" + ] + } + ], + "source": [ + "p=t0+y0+y1\n", + "print(\"unreduced polynomial: \", p)\n", + "print(\"reduced polynomial: \", p.reduce())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding new methods: The definite integral map\n", + "\n", + "We define a linear map:\n", + "\n", + "$$ \\int_{n}: (A_{PL})_{n}^{n} \\rightarrow \\mathbb{Q} $$\n", + "\n", + "by setting\n", + "\n", + "$$ \\int_{n}t_1^{k_1}t_2^{k_2}\\dots t_n^{k_n}dt_1\\wedge \\dots \\wedge dt_n = \\int_{0}^{1} dt_1 \\int_{0}^{1-t_1}dt_2 \\dots \\int_{0}^{1-\\sum_{1}^{n-1}t_i}t_1^{k_1}t_2^{k_2}\\dots t_n^{k_n}dt_n = \\frac{k_1!k_2! \\dots k_n!}{(k_1+ \\dots +k_n+n)!} $$" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "class AplN(AplN,UniqueRepresentation):\n", + " class Element(AplN.Element):\n", + " \"\"\"\n", + " Element class of the commutative differential multi-graded algebra (Apl)n.\n", + " \"\"\"\n", + " def _integrable_part(self):\n", + " \n", + " \"\"\"\n", + " The method returns the coefficient in Q[t_1,...,t_n] of the term\n", + " of degree `n`\n", + "\n", + " OUTPUT:\n", + " - A polynomial in the ring Q.\n", + " (After reducing the variables t_{0},y_{0} by the corresponding relations, \n", + " the algorithm removes the variables y_{1},..,y_{n}). \n", + " \"\"\"\n", + " \n", + " apl = self.parent()\n", + " pol = apl(self.reduce()) #needed in case reduce() returns an integer\n", + " relations = []\n", + " for i in range(apl.n+1): \n", + " relations.append(apl.gens()[apl.n+1+i]-1)\n", + " pol = apl(pol.homogeneous_part(degree=apl.n)) \n", + " return apl(pol.reduce(relations=relations))\n", + "\n", + " def integral(self):\n", + " \"\"\"\n", + " Returns the definite integral of the term of degree `n`\n", + " \n", + " OUTPUT:\n", + " - The rational number obtained by the definite integral \n", + " of the term of degree `n`\n", + " \n", + " \"\"\"\n", + "\n", + " apl = self.parent()\n", + " pol = self._integrable_part()\n", + " result = 0\n", + " for k in pol.dict().keys(): # k is a monomial\n", + " numerator = 1\n", + " denominator = apl.n\n", + " for e in k: # e is an exponents\n", + " numerator *= factorial(e)\n", + " denominator += e\n", + " coef = pol.dict()[k]\n", + " result += coef*numerator/factorial(denominator)\n", + " #return ((-1)**(apl.n*(apl.n-1)/2))*result\n", + " return result" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Example" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defining t0, t1, y0, y1\n" + ] + } + ], + "source": [ + "apl = AlgebraPL(1)\n", + "apl.inject_variables()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Integrable part: -t1 + 2\n", + "Definite integral: 3/2\n" + ] + } + ], + "source": [ + "p=t0+y1*(t0+1)\n", + "print(\"Integrable part: \",p._integrable_part())\n", + "print(\"Definite integral: \", p.integral())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding new method: find an integrand for a given definite integral\n", + "\n", + "The linear map we have defined above is not injective, but we can consider one way to find a polynomial whose image by the definite integral map is given. We call \"integrand\" to this particular element of the preimage set of the given element by the linear map.\n", + "\n", + "$$ \\int_{n}^{-1} c = c (n!) dt_1 \\wedge \\dots \\wedge dt_n$$\n", + "$$ c \\in \\mathbb{Q} $$\n", + "\n", + "It is easy to see that $ \\int_{n}\\int_{n}^{-1} c = c $ although the inverse is not always true. \n", + "\n", + "We define a class method, called \"integrand\", that returns a polynomial whose definite integral image is equal to a rational number given as input." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "class AplN(AplN,UniqueRepresentation):\n", + " def integrand(self, value): \n", + " \"\"\"\n", + " Returns a polynomial whose definite integral is equal to 'value'\n", + "\n", + " OUTPUT:\n", + " - A polynomial\n", + " \"\"\"\n", + " return value*factorial(self.n)*prod(self.gens()[self.n+2:])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Example: getting a polynomial for whose definite integral is given" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defining t0, t1, y0, y1\n" + ] + } + ], + "source": [ + "apl = AlgebraPL(1)\n", + "apl.inject_variables()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5*y1" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "value = 5\n", + "apl.integrand(value)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#checking that the composition of the integral and the lift is the identity map\n", + "p = apl.integrand(value)\n", + "p.integral()==value" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding new methods: find a primitive of the coboundary operator\n", + "\n", + "As we have mentioned before, there is an isomorphism between the cochain algebra $(A_{PL})_n$ and the algebra $\\Lambda (t_1, \\dots, t_n,y_1, \\dots, y_n)$, where the variables $t_i$ have degree $0$, and the variables $y_j$ have degree $1$. This algebra is the tensor product of the polynomial ring in the variables $t_i$ with the exterior algebra in the variables $y_j$:\n", + "\n", + "$$(A_{PL})_n \\cong \\mathbb{Q}[t_1, \\dots, t_n]\\otimes_{\\mathbb{Q}} \\Lambda ^{\\mathbb{Q}}(y_1, \\dots, y_n)$$\n", + "\n", + "In this algebra, we define the lexicographic monomial order in the variables $y_i$ as \n", + "\n", + "$$y_i > y_j, \\: if \\: i k_{1}^{i+1}$\n", + "- $\\exists m \\in \\mathbb{N}, 1 < m \\leq n $ so that $k_{l}^{i} = k_{l}^{i+1}$ for $1 \\leq l < m$, and $k_{l}^{i} > k_{l}^{i+1}$ for $l= m$.\n", + "\n", + "\n", + "Our algebra $(A_{PL})_n$, as a cochain algebra, has a coboundary operator, $d$, and by definition, we know that $d^2=0$. Also, we know that $H^p((A_{PL})_n)=0$ for $p \\geq 1$, meaning that, for every element $\\theta \\in (A_{PL})_n$ so that $d\\theta=0$ (i.e., $\\theta$ is closed), there exists an element $\\omega \\in (A_{PL})_n$ so that $\\theta = d\\omega$.\n", + "\n", + "Our problem here is to find a primitive $\\omega$ whose differential $\\theta$ is known, $\\theta = d\\omega$. As we know that $\\theta$ is the differential of some element, for now on we will consider polynomials where all terms have at least one exponent $k_{j}^{i} \\neq 0$ (i.e., our polynomial $\\theta$ has no terms of degree $0$)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Definition**. (pseudo-primitive of a monomial) Let $\\theta \\in (A_{PL})_n$ be a polynomial formed by only one term of degree $p$ of the form:\n", + "\n", + "$$\\theta = ct_{1}^{l_{1}^{0}} \\dots t_{n}^{l_{n}^{0}} y_{1}^{k_{1}^{0}} \\dots y_{n}^{k_{n}^{0}}$$\n", + "\n", + "satisfying:\n", + "\n", + "- $c \\in \\mathbb{Q}$\n", + "- $k_{j}^{i} \\in \\mathbb{Z}_2$\n", + "- $\\sum k_{j}^{i} = p$\n", + "- $l_{j}^{i} \\in \\mathbb{N} \\cup \\{0\\}$\n", + "\n", + "We define the *pseudo-primitive of $\\theta$* (in relation to the coboundary operator) as the homogeneous polynomial $\\omega$, of degree $p-1$, whose differential is the polynomial $\\theta$ plus some homogeneous polynomial $\\epsilon$ of degree $p$:\n", + "\n", + "$$d\\omega = \\theta+\\epsilon$$\n", + "\n", + "This polynomial is calculated in the following way:\n", + "\n", + "**Step 1:** Choose the lowest $i$ for which $k_{i}^{0}=1$\n", + "\n", + "**Step 2:** Set $k_{i}^{0}=0$ and increase $l_{i}^{0}$ by 1\n", + "\n", + "$$ \\omega = ct_{1}^{l_{1}^{0}} \\dots t_{i}^{l_{i}^{0}+1} \\dots t_{n}^{l_{n}^{0}} y_{1}^{0} \\dots y_{i}^{0} \\dots y_{n}^{k_{n}^{0}}$$\n", + "\n", + "**Step 3:** Divide the coefficient $c$ by $l_{i}^{0}+1$\n", + "\n", + "$$ \\omega = \\frac{c}{l_{i}^{0}+1}t_{1}^{l_{1}^{0}} \\dots t_{i}^{l_{i}^{0}+1} \\dots t_{n}^{l_{n}^{0}} y_{1}^{0} \\dots y_{i}^{0} \\dots y_{n}^{k_{n}^{0}}$$\n", + "\n", + "\n", + "**Lemma**: $d\\omega= \\theta + \\epsilon$\n", + "\n", + "**Proof**: TODO\n", + "***\n", + "\n", + "\n", + "#### **The algorithm**\n", + "\n", + "The input of our algorithm is a polynomial $\\theta \\in (A_{PL})_n$ that has the form:\n", + "\n", + "$$ \\theta = p^0 y_{1}^{k_{1}^{0}} \\dots y_{n}^{k_{n}^{0}} + p^1 y_{1}^{k_{1}^{1}} \\dots y_{n}^{k_{n}^{1}} + \\dots $$\n", + "\n", + "$$p^i \\in \\mathbb{Q}[t_1, \\dots, t_n]$$\n", + "\n", + "**Step 1**: Find a pseudo-primitive of the leading term of $\\theta$.\n", + "\n", + "First, we define the variables $\\omega, \\theta_0$, and we initialize them as \n", + "\n", + "$$\\omega=0$$\n", + "$$\\theta_0=\\theta$$\n", + "\n", + "The leading term of $\\theta_0$, $LT(\\theta_0)$, has the form:\n", + "\n", + "$$LT(\\theta_0) = c_0t_{1}^{l_{1}^{0}} \\dots t_{n}^{l_{n}^{0}} y_{1}^{k_{1}^{0}} \\dots y_{n}^{k_{n}^{0}}$$\n", + "$$ c_0\\in \\mathbb{Q}$$\n", + "$$ l_{i}^{0} \\geq 0$$\n", + "\n", + "What we want to do in this step is to find a polynomial $\\omega_0$ whose differential contains the leading term of the element $\\theta_0$ plus some extra terms $\\epsilon_0$:\n", + "\n", + "$$d\\omega_0 = LT(\\theta_0)+\\epsilon_0$$\n", + "\n", + "Knowing that the coboundary operator increases the degree in 1 unit, and the degree of every term comes from the variables $y_j$, one approach is the following:\n", + "\n", + "1) Assign to $\\omega_0$ the leading term of $\\theta_0$, \n", + "2) Choose the lowest $i$ for which $k_{i}^{0}=1$\n", + "3) Set $k_{i}^{0}=0$ and increase $l_{i}^{0}$ by 1\n", + "4) Divide the coefficient $c_0$ by $l_{i}^{0}+1$\n", + "\n", + "$$ \\omega_0 = \\frac{c_0}{l_{i}^{0}+1}t_{1}^{l_{1}^{0}} \\dots t_{i}^{l_{i}^{0}+1} \\dots t_{n}^{l_{n}^{0}} y_{1}^{0} \\dots y_{i}^{0} \\dots y_{n}^{k_{n}^{0}}$$\n", + "\n", + "TODO: Prueba de que esto funciona:\n", + "\n", + "$$\\omega_0 = c_0a(t)*b(y)$$\n", + "$$d\\omega_0 = d(c_0a(t))*b(y)) = c_0d(a(t))b(y)$$\n", + "\n", + "**Step 2**: Calculate the new $\\theta_i$:\n", + "\n", + "Once we have found the element $\\omega_0$, we update the variable $\\omega$ as:\n", + "\n", + "$$ \\omega = \\omega + \\omega_0$$\n", + "\n", + "and we define the new variable $\\theta_{1}$ as:\n", + "\n", + "$$ \\theta_{1} = \\theta-d\\omega $$\n", + "\n", + "If $\\theta_{1}=0$ we have finished and $\\omega$ is the element we were looking for. If $\\theta_{1} \\neq 0$, continue with the following steps.\n", + "\n", + "\n", + "**Step 3**:\n", + "\n", + "Get the leading term of $\\theta_{1}$, and obtain its pseudo-primitive $\\omega_1$.\n", + "\n", + "**Step 4:**\n", + "\n", + "Update the variable $\\omega$ as:\n", + "\n", + "$$ \\omega = \\omega + \\omega_1$$\n", + "\n", + "and define the new variable $\\theta_{2}$ as:\n", + "\n", + "$$ \\theta_{2} = \\theta-d\\omega $$\n", + "\n", + "**Step 5:**\n", + "If $\\theta_{2}=0$ we have finished and $\\omega$ is the element we were looking for. If $\\theta_{2} \\neq 0$, go back to step 3 and repeat the steps 3 and 4 several times until we get that $\\theta_{i+1}=0$.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "class AplN(AplN,UniqueRepresentation):\n", + " class Element(AplN.Element):\n", + " \"\"\"\n", + " Element class of the commutative differential multi-graded algebra (Apl)n.\n", + " \"\"\"\n", + " \n", + " def _get_term(self, coef, exp, gens):\n", + " \"\"\"\" \n", + " \n", + " Returns the term specified by its coefficient, exponents and generators\n", + " \n", + " INPUT::\n", + " - coef: The coefficient of the term\n", + " - exp: A tuple with the exponents of each variable\n", + " - gens: The generators\n", + " \n", + " OUTPUT::\n", + " - A polynomial\n", + " \"\"\"\n", + " return coef*prod(list(map(lambda exp, gen: gen^exp, exp, gens)))\n", + "\n", + " def _get_terms(self):\n", + " \"\"\"\" \n", + " \n", + " Returns self seen as a collection of terms in the variables y_j with coefficients in QQ\n", + " \n", + " OUTPUT::\n", + " - A dictionary with all terms\n", + " \n", + " \"\"\"\n", + " a = self.parent()\n", + " n = len(a.gens())/2\n", + " ts_only_gens = a.gens()[:n]+tuple(n*[1])\n", + " ys_only_gens = tuple(n*[1])+a.gens()[n:]\n", + " terms = {}\n", + " pol = self.dict()\n", + " for exp in pol.keys():\n", + " key = self._get_term(1, exp,ys_only_gens)\n", + " coef = self._get_term(pol[exp],exp,ts_only_gens)\n", + " if key not in terms.keys():\n", + " terms[key] = coef\n", + " else:\n", + " terms[key] += coef \n", + " return terms\n", + "\n", + " def _get_leading_pol(self):\n", + " \"\"\"\" \n", + " \n", + " Returns the leading polynomial\n", + " \n", + " OUTPUT::\n", + " - A polynomial\n", + " \"\"\"\n", + " terms = self._get_terms()\n", + " keys = list(terms.keys())\n", + " keys.sort(reverse=True)\n", + " return terms[keys[0]]*keys[0]\n", + "\n", + " def _get_idx(self, exp):\n", + " \"\"\"\" \n", + " \n", + " Returns the idx 'i' of the first generator 'y_i' that appears in exp\n", + " \n", + " INPUT::\n", + " - exp: A tuple with the exponents\n", + " \n", + " OUTPUT::\n", + " - A non-negative number lower or equal to 'n'\n", + " \"\"\"\n", + " n = len(exp)/2\n", + " filter_ts = n*[0]+n*[1]\n", + " diff_forms = list(map(lambda v, f: v*f, exp, filter_ts))\n", + " return next((i for i, x in enumerate(list(diff_forms)) if x), None)-n\n", + "\n", + " def _monomial_primitive(self, monomial, idx):\n", + " \"\"\"\" \n", + " \n", + " Returns the primitive of the given monomial\n", + " \n", + " INPUT::\n", + " - monomial: A monomial\n", + " - idx: the index of the variable y_j that will be used to calculate the pseudo-primitive\n", + " \n", + " OUTPUT::\n", + " - A polynomial\n", + " \"\"\"\n", + " exp = list(monomial.dict().keys())[0]\n", + " coef = monomial.dict()[exp]\n", + " n = len(exp)/2\n", + " if (exp[n+idx]==0):\n", + " raise IndexError(\"It is not possible to get a primitive using the given idx.\")\n", + " primitive = list(copy.deepcopy(exp))\n", + " primitive[n+idx] = 0\n", + " primitive[idx] += 1\n", + " new_coef = coef/primitive[idx]\n", + " a = monomial.parent()\n", + " return self._get_term(new_coef, primitive, a.gens())\n", + "\n", + " def _leading_primitive(self):\n", + " \"\"\"\" \n", + " Returns the primitive of the leading term of self\n", + " \n", + " OUTPUT::\n", + " - A polynomial\n", + " \"\"\"\n", + " polynomial = self._get_leading_pol()\n", + " # necessary condition: all monomials have apl.gens[n+idx] factor\n", + " exp = list(polynomial.dict().keys())[0]\n", + " idx = self._get_idx(exp)\n", + " aGens = polynomial.parent().gens()\n", + " primitive = 0\n", + " for exp in polynomial.dict().keys():\n", + " coef = polynomial.dict()[exp]\n", + " monomial = self._get_term(coef, exp, aGens)\n", + " primitive += self._monomial_primitive(monomial, idx)\n", + " terms = primitive._get_terms()\n", + " result = sum([terms[key]*key for key in terms.keys()])\n", + " return result\n", + "\n", + " def primitive(self):\n", + " \"\"\"\" \n", + " Retuns a polynomial whose differential is self\n", + " \n", + " OUTPUT::\n", + " - A polynomial\n", + " \"\"\"\n", + " if self.differential()!=0 :\n", + " raise ValueError(\"This polynomial is not closed.\")\n", + " w = self._leading_primitive()\n", + " theta = self - w.differential()\n", + " if (theta == 0):\n", + " return w\n", + " else:\n", + " return w+theta.primitive()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Example" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defining t0, t1, t2, t3, t4, t5, y0, y1, y2, y3, y4, y5\n" + ] + } + ], + "source": [ + "apl = AlgebraPL(5)\n", + "apl.inject_variables()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "False\n" + ] + } + ], + "source": [ + "omega_orig = t0+5*y1*y2+y3*y4*t1*y5\n", + "theta = omega_orig.differential()\n", + "print(theta.primitive().differential()==theta)\n", + "print(theta.primitive()==omega_orig)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "True\n", + "t0*t1^2*y1*y3 + 1/2*t0^2*y1*y3 + t0*y1*y3\n" + ] + } + ], + "source": [ + "theta = (t0+t1^2+1)*y0*y1*y3\n", + "print(theta.differential())\n", + "print(theta.primitive().differential()==theta)\n", + "print(theta.primitive())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The simplicial cochain algebra $A_{PL}$\n", + "This class implements the simplicial cochain algebra $A_{PL} = \\{(A_{PL})_{n}\\}_{n\\geq0}$. For more information, see [Rational homotopy theory, Felix, Halperin, Thomas, chapter 10.c)].\n", + "\n", + "## Definition\n", + "\n", + "A simplicial object $K$ with values in a category $\\mathfrak{C}$ is a sequence $\\{K_n\\}_{n \\geq 0}$ of objects in $\\mathfrak{C}$, together with $\\mathfrak{C}$-morphisms:\n", + "\n", + "$$\\delta_i: K_{n} \\rightarrow K_{n-1}, \\; 0 \\leq i \\leq n $$ \n", + "\n", + "$$s_j: K_{n} \\rightarrow K_{n+1}, \\; 0 \\leq j \\leq n$$\n", + "\n", + "that satisfy the identities:\n", + "\n", + "$$\\delta_i \\delta_j = \\delta_{j-1} \\delta_i,\\; i j+1\n", + "\\end{matrix}\\right.$$\n", + "\n", + "We define the **simplicial cochain algebra** $A_{PL} = \\{(A_{PL})_n\\}_{n \\geq 0}$ by:\n", + "\n", + "The cochain algebra $(A_{PL})_n$ is given by:\n", + "$$(A_{PL})_n = \\frac{\\wedge(t_0, \\dots, t_n,y_0,\\dots, y_n)}{<\\sum{t_i}-1, \\sum{y_j}>}$$\n", + "\n", + "The face and degeneracy morphisms are the unique cochain algebra morphisms:\n", + "\n", + "$$\\delta_i: (A_{PL})_{n} \\rightarrow (A_{PL})_{n-1}, \\; 0 \\leq i \\leq n$$\n", + "\n", + "$$s_j: (A_{PL})_{n} \\rightarrow (A_{PL})_{n+1}, \\; 0 \\leq j \\leq n$$\n", + "\n", + "satisfying\n", + "\n", + "$$\\delta_i = t_k \\rightarrow \\left\\{\\begin{matrix}\n", + "t_k,& ki\n", + "\\end{matrix}\\right. \\; \\; \\; \\;\\;\n", + "s_j = t_k \\rightarrow \\left\\{\\begin{matrix}\n", + "t_k,& kj\n", + "\\end{matrix}\\right.$$\n", + "\n", + "## Implementation\n" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "class SimplicialAplN(AplN, UniqueRepresentation):\n", + " \"\"\"\n", + " \n", + " The simplicial commutative cochain algebra Apl\n", + " \n", + " \"\"\"\n", + "\n", + " def _base_repr(self):\n", + " \"\"\"\n", + " Return the base string representation of ``self``.\n", + " \"\"\"\n", + "\n", + " s = DifferentialGCAlgebra._base_repr(self)\n", + " old = '{}'.format(self._degrees)\n", + " new = '{}'.format([i[0] for i in self._degrees_multi])\n", + " return \"Simplicial \" + s.replace(old, new)\n", + "\n", + " class Element(AplN.Element):\n", + " \"\"\"\n", + " Element class of the simplicial commutative differential algebra (Apl)n.\n", + " \"\"\"\n", + " \n", + " def face_morphism(self,i):\n", + " \"\"\"\" \n", + " \n", + " Returns the morphism face 'i' of self\n", + " \n", + " INPUT::\n", + " \n", + " - i: A non-negative integer lower or equal to 'n'. Represents the face index\n", + " \n", + " OUTPUT::\n", + " \n", + " - A morphism of cochain algebras\n", + " \"\"\"\n", + " n = self.parent().n\n", + " if(n==0):\n", + " return 0\n", + " domain = self.parent()\n", + " codomain = SimplicialAlgebraplN(n-1)\n", + " tImages = []\n", + " yImages = []\n", + " n = len(domain.gens())//2\n", + " for k in range(n):\n", + " if(ki):\n", + " tImages.append(codomain.gens()[k-1])\n", + " yImages.append(codomain.gens()[n+k-2])\n", + " images = tImages+yImages\n", + " return domain.hom(codomain=codomain,im_gens=images)\n", + " \n", + " def face(self,i):\n", + " \"\"\"\" \n", + " \n", + " Returns the face 'i' of self\n", + " \n", + " INPUT::\n", + " \n", + " - i: A non-negative integer lower or equal to 'n'. Represents the face index\n", + " \n", + " OUTPUT::\n", + " \n", + " - A polynomial that is the face 'i' of self\n", + " \"\"\"\n", + " \n", + " return self.face_morphism(i)(self)\n", + " \n", + " def degeneration_morphism(self,j):\n", + " \"\"\"\" \n", + " \n", + " Returns the morphism degeneration 'j' of self\n", + " \n", + " INPUT::\n", + " - j: A non-negative integer lower or equal to 'n'. Represents the degeneration index\n", + " \n", + " OUTPUT::\n", + " - A morphism of cochain algebras\n", + " \"\"\"\n", + " \n", + " n = self.parent().n\n", + " domain = self.parent()\n", + " codomain = SimplicialAlgebraplN(n+1)\n", + " if(j>n):\n", + " print(\"the degeneration index must be a non-negative number lower or equal to \"+str(n))\n", + " return False\n", + " elif(j<0):\n", + " print(\"the degeneration index must be non-negative\")\n", + " return False\n", + " else:\n", + " tImages = []\n", + " yImages = []\n", + " n = len(domain.gens())/2\n", + " for k in range(n):\n", + " if(kj):\n", + " tImages.append(codomain.gens()[k+1])\n", + " yImages.append(codomain.gens()[n+1+k+1])\n", + " images = tImages+yImages\n", + " return domain.hom(codomain=codomain,im_gens=images)\n", + " \n", + " def degeneration(self,j):\n", + " \"\"\"\" \n", + " \n", + " Returns the degeneration 'j' of self\n", + " \n", + " INPUT::\n", + " - j: A non-negative integer lower or equal to 'n'. Represents the degeneration index\n", + " \n", + " OUTPUT::\n", + " - A polynomial that is the degeneration 'j' of self\n", + " \"\"\"\n", + " return self.degeneration_morphism(j)(self)\n", + " \n", + "def SimplicialAlgebraplN(n):\n", + " \"\"\"\n", + " Returns the graded commutative differential cochain algebra (Apl)_n as part of\n", + " the simplicial cochain algebra A_{PL}\n", + "\n", + " INPUT:\n", + "\n", + " - ``n`` -- A non-negative integer corresponding to the number of generators of degree 0.\n", + " \"\"\"\n", + "\n", + " if (n<0):\n", + " raise ValueError('`n` must be a non-negative integer')\n", + " ts = ['t'+str(t) for t in range(n+1)]\n", + " ys = ['y'+str(t) for t in range(n+1)]\n", + " degrees = tuple((n+1)*[(0,2)])+tuple((n+1)*[(1,2)])\n", + " gca = GradedCommutativeAlgebra(QQ, names=ts+ys, degrees=degrees)\n", + " differentials = {gca.gens_dict()[ts[i]]:gca.gens_dict()[ys[i]] for i in range(n+1)}\n", + " return SimplicialAplN(gca,differentials)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defining t0, t1, t2, t3, t4, t5, y0, y1, y2, y3, y4, y5\n" + ] + } + ], + "source": [ + "s = SimplicialAlgebraplN(5)\n", + "s.inject_variables()" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p = t1+y2\n", + "p.degeneration(0).face(1)==p" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1 = p.degeneration(1).face_morphism(1)\n", + "m2 = p.degeneration_morphism(1)\n", + "(m1*m2).is_identity()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding new methods: propagate a simplex through the simplicial structure\n", + "\n", + "In this part, we want to obtain an homogeneous $(n+k)$-simplex of degree $n$, $p_{n+k} \\in (A_{PL})_{n+k}^n$, for $k>0$, where a given homogeneous $n$-simplex of degree $n$, $p_n \\in (A_{PL})_n^n$ is a face of $p_{n+k}$ of dimension $n$, and the rest of faces of dimension lower or equal to $n$ are $0$. We call this map **propagation**,denoted by $\\Gamma$ :\n", + "\n", + "$$\\Gamma_{n+k}^n: (A_{PL})_n^n \\rightarrow (A_{PL})_{n+k}^n$$\n", + "\n", + "Without lost of generality, we asume that our polynomial of degree $n$ is expressed as a polynomial in the variables $y_1,\\dots,y_n$. Let $p_n \\in (A_{PL})_n^n$ be the polynomial:\n", + "\n", + "$$p_n = q_t y_{1} \\dots y_{n}$$\n", + "\n", + "$$q_t \\in \\mathbb{Q}[t_0,\\dots,t_n]$$\n", + "\n", + "\n", + "\n", + "Let $I$ be the index set $\\{0,\\dots, n+k\\}$. For some subsets $(i_1, \\dots, i_k) \\subset I$ we know by definition that \n", + "\n", + "$$p_n = \\delta_{i_1} \\dots \\delta_{i_k} \\Gamma_{n+k}^n(p_n)$$\n", + "\n", + "and due to the relations between face morphisms, we know that we can chose a unique subset $(i_1, \\dots, i_k)$ in a way that $i_1 < \\dots < i_k$.\n", + "\n", + "Just to point the definition, notice that any other combination of faces $\\delta_{j_1} \\dots \\delta_{j_k}$ not equivalent to $\\delta_{i_1} \\dots \\delta_{i_k}$ (i.e., applying the relations between face morphisms), makes the result:\n", + "\n", + "$$\\delta_{j_1} \\dots \\delta_{j_k}\\Gamma_{n+k}^n(p_n) = 0$$\n", + "\n", + "Let $J=\\{j_0,\\dots,j_n\\} \\subset I$ be the subset $\\{i_1, \\dots, i_k\\}^C$, i.e., those elements of $I$ $\\notin \\{i_1, \\dots, i_k\\}$, and where $j_l < j_m$, for $l max_dim:\n", + " max_dim = dim\n", + " apl = SimplicialAlgebraplN(dim)\n", + " if dim>0:\n", + " values[k] = ((-1)**(dim*(dim-1)/2))*apl.integrand(cochain[k])\n", + " else:\n", + " values[k]= apl(cochain[k])\n", + " \n", + " # second, we propagate the simplicial information\n", + " simplicial_structure = {}\n", + " for n in reversed(range(max_dim+1)):\n", + " keys = [k for k in values.keys() if len(k) == n+1] # keys of the n-simplices\n", + " for k in keys:\n", + " simplicial_structure[k] = values[k] + self._propagate(cochain, k) \n", + " #print(simplicial_structure)\n", + " return AlgebraAplK.Element(self,simplicial_structure)\n", + " \n", + " def _propagate(self, cochain, simplex):\n", + " \"\"\"\n", + " Returns the part of the polynomial assigned to 'simplex' related to the\n", + " propagation of the simplicial information of its faces\n", + " \"\"\"\n", + " dim = len(simplex)-1\n", + " apl = SimplicialAlgebraplN(dim)\n", + " propagation = apl(0)\n", + " for n in reversed(range(dim)):\n", + " faces = self._faces_of_length(simplex, n+1)\n", + " apl = SimplicialAlgebraplN(n)\n", + " pol = apl(prod(apl.gens()[n+2:])) # we propagate the polynomial (y_1...y_n)\n", + " for f in faces:\n", + " if f in cochain.keys():\n", + " value = cochain[f]\n", + " face_indexes = [simplex.index(i) for i in f]\n", + " #print(\"dim: \",n,\" pol: \",pol,\" face_idx: \",face_indexes,\" dim: \", n)\n", + " propagation += value*((-1)**(n*(n-1)/2))*factorial(n)*pol.propagate(face_indexes, dim)\n", + " return propagation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{(0, 1, 2, 3): -6*y1*y2*y3 - 2*t3*y1*y2 + 2*t2*y1*y3 - 2*t1*y2*y3 - t3*y1 + t1*y3, (0, 1, 2): 0, (0, 1, 3): -t2*y1 + t1*y2, (0, 2, 3): 0, (1, 2, 3): -2*y1*y2 + t2*y1 - t1*y2 + y2, (0, 1): 0, (0, 2): 0, (0, 3): 0, (1, 2): 0, (1, 3): y1, (2, 3): 0, (0,): 0, (1,): 0, (2,): 0, (3,): 0}" + ] + }, + "execution_count": 71, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "S = SimplicialComplex([[0,1,2,3]],is_mutable=False) \n", + "A = AlgebraAplK(S)\n", + "cochain = {(0,): 0, (1,): 0, (2,):0, (3,): 0, (0,1): 0, (0,2): 0, (0,3): 0,(1,2): 0, (1,3): 1, (2,3): 0, (0,1,2):0, (0,1,3):0, (0,2,3):0, (1,2,3):1, (0,1,2,3):1}\n", + "p = A.lift_cochain(cochain)\n", + "p" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "True\n" + ] + } + ], + "source": [ + "print(p.integral()==cochain)\n", + "print(A.lift_cochain(p.integral())==p)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Adding new methods: Managing simplicial-cohomology generators" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": {}, + "outputs": [], + "source": [ + "class AlgebraAplK(AlgebraAplK, UniqueRepresentation):\n", + " \"\"\"\n", + " \n", + " The graded commutative differential cochain algebra Apl(K)\n", + " \n", + " \"\"\"\n", + " def cohomology_gens(self,degree):\n", + " \"\"\"\n", + " Returns the cohomolosy generators of a given degree\n", + " \"\"\"\n", + " gens = {}\n", + " basis = self.K.cohomology_ring(QQ).basis()\n", + " for k in basis.keys():\n", + " if k[0] == degree:\n", + " gens[k] = basis[k]\n", + " return gens\n", + " \n", + " def cohomology_group(self, n):\n", + " chainComplex = self.K.chain_complex(base_ring=QQ)\n", + " cochainComplex = chainComplex.dual()\n", + " Hn = cochainComplex.differential(n).right_kernel()/cochainComplex.differential(n-1).column_space()\n", + " return Hn\n", + "\n", + " def cochain_to_vector(self, cochain, dim):\n", + " \"\"\"\n", + " Converts a cochain, given as a dictionary, to a vector\n", + " \"\"\"\n", + " basis = self.K.n_chains(dim, base_ring=QQ, cochains=True).basis()\n", + " v = vector(QQ,len(basis)*[0])\n", + " i=0\n", + " for simplex in basis.keys():\n", + " v[i] = cochain[tuple(simplex)]\n", + " i = i+1\n", + " return v\n", + "\n", + " def vector_to_cochain(self, v, dim):\n", + " \"\"\"\n", + " Converts a cochain, given as a vector, to a dictionary\n", + " \"\"\"\n", + " cochain = {}\n", + " for d in range(self.K.dimension()+1):\n", + " basis = self.K.n_chains(d, base_ring=QQ, cochains=True).basis()\n", + " if d!=dim:\n", + " for simplex in basis.keys():\n", + " cochain[tuple(simplex)] = 0\n", + " else:\n", + " i=0\n", + " for simplex in basis.keys():\n", + " cochain[tuple(simplex)] = v[i]\n", + " i = i+1\n", + " return cochain\n", + " \n", + " def lift_cochain_complex(self, cochain, dim):\n", + " \"\"\"\n", + " (REVISAR)\n", + " Returns an element of the preimage by the differential of a given cochain\n", + " \n", + " INPUT:\n", + " - cochain: a cochain as a vector\n", + " - dim: dimension of the cochain\n", + " \"\"\"\n", + " # S = the Simplicial Complex\n", + " # cochain = the cochain you want to find a preimage by the differential\n", + " # dim = the dimension of the cochain\n", + " cochain_vector = self.cochain_to_vector(cochain, dim)\n", + " cochainComplex = self.K.chain_complex(base_ring=QQ).dual()\n", + " diff = cochainComplex.differential(dim-1)\n", + " show(diff.echelon_form())\n", + " result = diff.solve_right(cochain_vector)\n", + " return self.vector_to_cochain(result)\n", + "\n", + " def lift_cohomology_generator(self, g):\n", + " \"\"\"\n", + " Returns a representative cochain associated to a given cohomology generator.\n", + " \"\"\"\n", + " cycle = g.to_cycle()\n", + " cochain = {}\n", + " for n in range(self.K.dimension()+1):\n", + " for simplex in self.K._n_cells_sorted(n):\n", + " cochain[simplex.tuple()] = 0\n", + " for i in cycle:\n", + " #print(type(i[0].tuple()))\n", + " cochain[i[0].tuple()] = i[1]\n", + " return cochain\n", + " \n", + " def get_cohomology_aplk(self,degree):\n", + " \"\"\"\n", + " Returns a set of representative elements of Apl(K), one for each cohomology generator of a given degree\n", + " \"\"\"\n", + " representative_aplk_elements = {}\n", + " dic_gens = self.cohomology_gens(degree)\n", + " for key in dic_gens.keys():\n", + " gen = dic_gens[key]\n", + " cochain = self.lift_cohomology_generator(gen)\n", + " representative_aplk_elements[key] = self.lift_cochain(cochain)\n", + " return representative_aplk_elements\n", + " \n", + " def first_cohomology_group(self):\n", + " \"\"\"\n", + " Returns the degree >= 1 of the first non-null cohomology generator. \n", + " \"\"\"\n", + " basis = self.K.cohomology_ring(base_ring=QQ).basis()\n", + " indexes = list(basis.keys())\n", + " indexes.sort(reverse=False)\n", + "# print(indexes)\n", + " for n in range(1,len(indexes)):\n", + " if indexes[n][0] > 0:\n", + " return indexes[n][0]\n", + " return -1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Examples" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{(1, 0): h^{1,0}}" + ] + }, + "execution_count": 74, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "S = SimplicialComplex([[0,1,2],[1,3],[2,3]],is_mutable=False) \n", + "A = AlgebraAplK(S)\n", + "g = A.cohomology_gens(1)\n", + "g" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(1,\\,0,\\,-1,\\,0,\\,0\\right)\n", + "\\end{math}" + ], + "text/plain": [ + "(1, 0, -1, 0, 0)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "{(0,): 0,\n", + " (1,): 0,\n", + " (2,): 0,\n", + " (3,): 0,\n", + " (0, 1): 1,\n", + " (0, 2): 0,\n", + " (1, 2): -1,\n", + " (1, 3): 0,\n", + " (2, 3): 0,\n", + " (0, 1, 2): 0}" + ] + }, + "execution_count": 75, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "H1 = A.cohomology_group(1)\n", + "l = []\n", + "for v in H1.basis():\n", + " l.append(H1.lift_map()(v))\n", + "show(l[0])\n", + "A.vector_to_cochain(l[0],1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{(0,): 0,\n", + " (1,): 0,\n", + " (2,): 0,\n", + " (3,): 0,\n", + " (0, 1): 0,\n", + " (0, 2): 0,\n", + " (1, 2): 0,\n", + " (1, 3): 0,\n", + " (2, 3): 1,\n", + " (0, 1, 2): 0}" + ] + }, + "execution_count": 76, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gen = list(g.values())[0]\n", + "cochain = A.lift_cohomology_generator(gen)\n", + "cochain" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{(1,\n", + " 0): {(0, 1, 2): 0, (0, 1): 0, (0, 2): 0, (1, 2): 0, (1, 3): 0, (2, 3): y1, (0,): 0, (1,): 0, (2,): 0, (3,): 0}}" + ] + }, + "execution_count": 77, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "A.get_cohomology_aplk(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{(2, 0): h^{2,0}, (2, 1): h^{2,1}}" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# get the cohomology generators of a given degree\n", + "S2 = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4,5],[3,4,6],[3,5,6],[4,5,6]],is_mutable=False) \n", + "A2 = AlgebraAplK(S2)\n", + "g = A2.cohomology_gens(2)\n", + "g" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{(0,): 0,\n", + " (1,): 0,\n", + " (2,): 0,\n", + " (3,): 0,\n", + " (4,): 0,\n", + " (5,): 0,\n", + " (6,): 0,\n", + " (0, 1): 0,\n", + " (0, 2): 0,\n", + " (0, 3): 0,\n", + " (1, 2): 0,\n", + " (1, 3): 0,\n", + " (2, 3): 0,\n", + " (3, 4): 0,\n", + " (3, 5): 0,\n", + " (3, 6): 0,\n", + " (4, 5): 0,\n", + " (4, 6): 0,\n", + " (5, 6): 0,\n", + " (0, 1, 2): 0,\n", + " (0, 1, 3): 0,\n", + " (0, 2, 3): 0,\n", + " (1, 2, 3): 1,\n", + " (3, 4, 5): 0,\n", + " (3, 4, 6): 0,\n", + " (3, 5, 6): 0,\n", + " (4, 5, 6): 0}" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# get a representative cochain for a given cohomology generator\n", + "gen = list(g.values())[0]\n", + "cochain = A2.lift_cohomology_generator(gen)\n", + "cochain" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{(2,\n", + " 0): {(0, 1, 2): 0, (0, 1, 3): 0, (0, 2, 3): 0, (1, 2, 3): -2*y1*y2, (3, 4, 5): 0, (3, 4, 6): 0, (3, 5, 6): 0, (4, 5, 6): 0, (0, 1): 0, (0, 2): 0, (0, 3): 0, (1, 2): 0, (1, 3): 0, (2, 3): 0, (3, 4): 0, (3, 5): 0, (3, 6): 0, (4, 5): 0, (4, 6): 0, (5, 6): 0, (0,): 0, (1,): 0, (2,): 0, (3,): 0, (4,): 0, (5,): 0, (6,): 0},\n", + " (2,\n", + " 1): {(0, 1, 2): 0, (0, 1, 3): 0, (0, 2, 3): 0, (1, 2, 3): 0, (3, 4, 5): 0, (3, 4, 6): 0, (3, 5, 6): 0, (4, 5, 6): -2*y1*y2, (0, 1): 0, (0, 2): 0, (0, 3): 0, (1, 2): 0, (1, 3): 0, (2, 3): 0, (3, 4): 0, (3, 5): 0, (3, 6): 0, (4, 5): 0, (4, 6): 0, (5, 6): 0, (0,): 0, (1,): 0, (2,): 0, (3,): 0, (4,): 0, (5,): 0, (6,): 0}}" + ] + }, + "execution_count": 80, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "phi = A2.get_cohomology_aplk(2)\n", + "phi" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Adding new methods: find a primitive of a closed element" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### methods related to find a polynomial where the differential is given" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [], + "source": [ + "from sage.rings.polynomial.polydict import ETuple\n", + "\n", + "class SimplicialAplN(SimplicialAplN,UniqueRepresentation):\n", + " class Element(SimplicialAplN.Element):\n", + " \"\"\"\n", + " Element class of the commutative differential multi-graded algebra (Apl)n.\n", + " \"\"\"\n", + "\n", + " def _get_primitive_basis_of_a_monomial(self, monomial): \n", + " \"\"\"\n", + " Returns a basis of the primitive of a given monomial\n", + "\n", + " Example: \n", + "\n", + " \"\"\"\n", + " n_vars = len(monomial)/2\n", + " combinations = []\n", + " for i in range(n_vars):\n", + " mono = list(copy.deepcopy(monomial))\n", + " if mono[n_vars+i]:\n", + " mono[i] += 1\n", + " mono[n_vars+i] = 0\n", + " combinations.append(tuple(mono))\n", + " return list(set(combinations))\n", + "\n", + " def _add_kernel_terms_to_primitive_basis(self, basis): \n", + " new_elements = []\n", + " for e in basis:\n", + " monomial = list(copy.deepcopy(e))\n", + " n = len(e)/2\n", + " monomial[:n] = n*[0]\n", + " new_elements.append(tuple(monomial))\n", + " return new_elements\n", + " \n", + " def _get_primitive_basis(self):\n", + " \"\"\"\n", + " Returns a basis of the primitive of 'self'\n", + " \"\"\"\n", + " basis = []\n", + " p = self.reduce()\n", + " for monomial in p.dict().keys():\n", + " basis += p._get_primitive_basis_of_a_monomial(monomial)\n", + " basis = list(set(basis))\n", + " basis += p._add_kernel_terms_to_primitive_basis(basis)\n", + " basis = list(set(basis))\n", + " terms = []\n", + " apl = self.parent()\n", + " for b in basis:\n", + " dim = len(monomial)/2-1\n", + " terms.append(self._get_term(1, b, apl.gens()))\n", + " terms.sort(reverse=False)\n", + " return terms\n", + "\n", + " def _get_differential_basis(self):\n", + " \"\"\"\n", + " Returns a basis of the differential of 'self'\n", + " \"\"\"\n", + " primitive_basis = self._get_primitive_basis()\n", + " differential_basis = []\n", + " for b in primitive_basis:\n", + " diff = b.differential().reduce()\n", + " if diff: # as we want a basis, we don't consider the coeffient of the differential\n", + " for monomial in diff.dict().keys():\n", + " term = self._get_term(1, monomial, self.parent().gens())\n", + " differential_basis.append(term)\n", + " differential_basis = list(set(differential_basis))\n", + " differential_basis.sort(reverse=False)\n", + " return differential_basis\n", + "\n", + " def _get_coordinate_vector_differential(self, diff_basis):\n", + " \"\"\"\n", + " Returns the coordinates of 'self' \n", + " in terms of the differential basis\n", + " \"\"\"\n", + " p_reduced = self.reduce()\n", + " #dic = p.dict()\n", + " #terms = [p_reduced.parent()({t: dic[t]}) for t in dic.keys()]\n", + " monomials = list(p_reduced.dict().keys())\n", + " v = vector(QQ,len(diff_basis)*[0])\n", + " for i in range(len(diff_basis)):\n", + " t = diff_basis[i]\n", + " term = list(t.dict().keys())[0] # there is only one monomial\n", + " if term in monomials:\n", + " v[i] = p_reduced.dict()[term]\n", + " return v\n", + "\n", + " def _differential_matrix(self, primitive_basis, differential_basis):\n", + " \"\"\"\n", + " Returns the matrix of the differential map\n", + " \"\"\"\n", + " #primitive_basis = get_primitive_basis_of_a_polynomial(p.reduce())\n", + " #differential_basis = get_differential_basis_of_a_polynomial(p.reduce())\n", + " nrows = len(differential_basis)\n", + " ncols = len(primitive_basis)\n", + " M = matrix(QQ, nrows, ncols, nrows*ncols*[0])\n", + " for j in range(ncols):\n", + " primitive = primitive_basis[j]\n", + " #diff_dict = self._tuple_differential(primitive)\n", + " diff_primitive = primitive.differential().reduce()\n", + " monomials = list(diff_primitive.dict().keys())\n", + " for i in range(nrows):\n", + " diff_basis_element = differential_basis[i]\n", + " term = list(diff_basis_element.dict().keys())[0] # there is only one monomial\n", + " if term in monomials:\n", + " M[i,j] = diff_primitive.dict()[term] \n", + " return M\n", + "\n", + " def solve_primitive(self):\n", + " p = self.reduce()\n", + " primitive_basis = p._get_primitive_basis()\n", + " diff_basis = p._get_differential_basis()\n", + " v = p._get_coordinate_vector_differential(diff_basis)\n", + " Mdif = p._differential_matrix(primitive_basis, diff_basis)\n", + " sol = Mdif.solve_right(v)\n", + " return sum(map(lambda x,y: x*y, sol, primitive_basis))" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defining t0, t1, t2, t3, t4, t5, y0, y1, y2, y3, y4, y5\n" + ] + }, + { + "data": { + "text/plain": [ + "[1, y4, y3, y2, t1^2, t2*t3*y4, t2*t4*y3, t3*t4*y2]" + ] + }, + "execution_count": 82, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dim = 5\n", + "s = SimplicialAlgebraplN(dim)\n", + "s.inject_variables()\n", + "p = -3*t1^2 +10* y2*t3*t4\n", + "p = p.differential()\n", + "primitive_basis = p._get_primitive_basis()\n", + "primitive_basis" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[t1*y1, t2*y3*y4, t3*y2*y4, t4*y2*y3]" + ] + }, + "execution_count": 83, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "diff_basis = p._get_differential_basis()\n", + "diff_basis" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(-6, 0, -10, -10)" + ] + }, + "execution_count": 84, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v = p._get_coordinate_vector_differential(diff_basis)\n", + "v" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[ 0 0 0 0 2 0 0 0]\n", + "[ 0 0 0 0 0 1 -1 0]\n", + "[ 0 0 0 0 0 1 0 -1]\n", + "[ 0 0 0 0 0 0 1 -1]" + ] + }, + "execution_count": 85, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Mdif = p._differential_matrix(primitive_basis, diff_basis)\n", + "Mdif" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-10*t2*t4*y3 - 10*t2*t3*y4 - 3*t1^2" + ] + }, + "execution_count": 86, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p.solve_primitive()" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 87, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p.solve_primitive().differential() == p" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### find an element of the preimage by the differential of an element of Alp(K)" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": {}, + "outputs": [], + "source": [ + "class AlgebraAplK(AlgebraAplK, UniqueRepresentation):\n", + " \"\"\"\n", + " \n", + " The graded commutative differential cochain algebra Apl(K)\n", + " \n", + " \"\"\"\n", + " \n", + " class Element(AlgebraAplK.Element):\n", + " \"\"\"\n", + " Element class of the simplicial commutative differential algebra (Apl)n.\n", + " \"\"\"\n", + " \n", + " def _face_basis(self, basis, face_idx):\n", + " face_basis = []\n", + " for b in basis:\n", + " face_pol = b.face(face_idx).reduce()\n", + " if face_pol:\n", + " for monomial in face_pol.dict().keys():\n", + " #remove coefficients\n", + " term = face_pol._get_term(1, monomial, face_pol.parent().gens())\n", + " face_basis.append(term)\n", + " face_basis = list(set(face_basis))\n", + " face_basis.sort(reverse=False)\n", + " return face_basis\n", + " \n", + " def _get_primitive_basis(self):\n", + " \n", + " primitive_basis = {}\n", + " S = self.parent().simplicialComplex()\n", + " dim = S.dimension()\n", + " min_dim = self.degree()\n", + " for n in reversed(range(min_dim,dim+1)):\n", + " for simplex in S._n_cells_sorted(n):\n", + " if simplex.tuple() not in primitive_basis.keys():\n", + " primitive_basis[simplex.tuple()] = []\n", + " # add primitive elements related to the assigned polynomial\n", + " pol = self.elements[simplex.tuple()]\n", + " primitive_basis[simplex.tuple()] += pol._get_primitive_basis()\n", + " primitive_basis[simplex.tuple()] = list(set(primitive_basis[simplex.tuple()]))\n", + " primitive_basis[simplex.tuple()].sort(reverse=False)\n", + " # propagate the primitive basis through its faces\n", + " for f in range(n+1):\n", + " simplex_face = S.face(simplex,f).tuple()\n", + " if simplex_face not in primitive_basis.keys():\n", + " primitive_basis[simplex_face] = []\n", + " primitive_basis[simplex_face] += self._face_basis(primitive_basis[simplex.tuple()], f)\n", + " primitive_basis[simplex_face] = list(set(primitive_basis[simplex_face]))\n", + " primitive_basis[simplex_face].sort(reverse=False)\n", + " return primitive_basis\n", + " \n", + " def _diff_basis(self, basis):\n", + " diff_basis = []\n", + " for b in basis:\n", + " b_diff = b.differential().reduce()\n", + " if b_diff:\n", + " for monomial in b_diff.dict().keys():\n", + " #remove coefficients\n", + " term = b_diff._get_term(1, monomial, b_diff.parent().gens())\n", + " diff_basis.append(term)\n", + " diff_basis = list(set(diff_basis))\n", + " diff_basis.sort(reverse=False)\n", + " return diff_basis\n", + " \n", + " def _get_differential_basis(self, primitive_basis):\n", + " differential_basis = {}\n", + " S = self.parent().simplicialComplex()\n", + " dim = S.dimension()\n", + " min_dim = self.degree()\n", + " for n in reversed(range(min_dim,dim+1)):\n", + " for simplex in S._n_cells_sorted(n):\n", + " prim_diff_basis = primitive_basis[simplex.tuple()]\n", + " differential_basis[simplex.tuple()] = self._diff_basis(prim_diff_basis)\n", + " return differential_basis\n", + " \n", + " def _get_differential_matrix(self, p_basis, d_basis):\n", + " S = self.parent().simplicialComplex()\n", + " dim = S.dimension()\n", + " min_dim = self.degree()\n", + " ncols = sum([len(l) for l in p_basis.values()])\n", + " nrows = sum([len(l) for l in d_basis.values()])\n", + " M = zero_matrix(QQ, nrows, ncols)\n", + " row_offset = 0\n", + " col_index = 0\n", + " for n in reversed(range(min_dim-1,dim+1)):\n", + " for simplex in S._n_cells_sorted(n):\n", + "# print(simplex.tuple(), row_offset, col_index)\n", + " if simplex.tuple() in p_basis.keys():\n", + " primitives = p_basis[simplex.tuple()]\n", + " if simplex.tuple() in d_basis.keys():\n", + " differentials = d_basis[simplex.tuple()]\n", + " if primitives and differentials:\n", + " for p in primitives:\n", + " dif_p = p.differential().reduce()\n", + " dic = dif_p.dict()\n", + " for monomial in dic.keys():\n", + " term = dif_p._get_term(1, monomial, dif_p.parent().gens())\n", + " if term in differentials:\n", + " row_index = differentials.index(term)\n", + " M[row_offset + row_index, col_index] = dic[monomial]\n", + " col_index += 1\n", + " row_offset += len(differentials)\n", + " elif primitives:\n", + " col_index += len(primitives)\n", + " elif primitives:\n", + " col_index += len(primitives)\n", + " \n", + " return M\n", + " \n", + " def _get_vector_diff_coordinates(self, d_basis):\n", + " len_v = sum([len(l) for l in d_basis.values()])\n", + " v = zero_vector(QQ, len_v)\n", + " offset = 0\n", + " S = self.parent().simplicialComplex()\n", + " dim = S.dimension()\n", + " min_dim = self.degree()\n", + " for n in reversed(range(min_dim,dim+1)):\n", + " for s in S._n_cells_sorted(n):\n", + " simplex = s.tuple()\n", + " if simplex in d_basis.keys():\n", + " differentials = d_basis[simplex]\n", + " pol = self.elements[simplex].reduce()\n", + " if pol and differentials:\n", + " dic = pol.dict()\n", + " for monomial in dic.keys():\n", + " term = pol._get_term(1, monomial, pol.parent().gens())\n", + " if term in differentials:\n", + " v_index = differentials.index(term)\n", + " v[offset + v_index] = dic[monomial]\n", + " offset += len(differentials)\n", + " return v\n", + " \n", + " def _get_offsets_matrix(self, p_basis):\n", + " offsets = {}\n", + " S = self.parent().simplicialComplex()\n", + " dim = S.dimension()\n", + " min_dim = self.degree()\n", + " offset = 0\n", + " first_simplex = True\n", + " for n in reversed(range(min_dim-1,dim+1)):\n", + " for simplex in S._n_cells_sorted(n):\n", + " if simplex.tuple() in p_basis.keys():\n", + " primitives = p_basis[simplex.tuple()]\n", + " if first_simplex:\n", + " offsets[simplex.tuple()] = 0\n", + " first_simplex = False\n", + " else:\n", + " offsets[simplex.tuple()] = offset\n", + " offset += len(primitives)\n", + " return offsets\n", + " \n", + " def _get_row_face_matrix(self, primitives, face_idx, face_basis,\n", + " offset_simplex, offset_face, len_row):\n", + " M = zero_matrix(QQ,1, len_row)\n", + " for fb in face_basis: \n", + " fb_idx = face_basis.index(fb)\n", + " row = zero_matrix(QQ,1, len_row)\n", + " row[0,offset_face+fb_idx] = -1\n", + " for term in primitives:\n", + " face_term = term.face(face_idx).reduce()\n", + " dic = face_term.dict()\n", + " i = primitives.index(term)\n", + " for monomial in dic:\n", + " t = face_term._get_term(1, monomial, face_term.parent().gens())\n", + " if t == fb:\n", + " coef = dic[monomial]\n", + " row[0,offset_simplex+i] = coef\n", + " M = M.stack(row)\n", + " return M[1:]\n", + " \n", + " \n", + " def _get_face_matrix(self, p_basis):\n", + " \n", + " offsets = self._get_offsets_matrix(p_basis)\n", + " len_row = sum([len(l) for l in p_basis.values()])\n", + " M = zero_matrix(QQ,1, len_row)\n", + " min_dim = self.degree()\n", + " for n in reversed(range(min_dim,dim+1)):\n", + " for simplex in S._n_cells_sorted(n):\n", + " offset_simplex = offsets[simplex.tuple()]\n", + " primitives = p_basis[simplex.tuple()]\n", + " for f in range(n+1):\n", + " simplex_face = S.face(simplex,f).tuple()\n", + " face_primitives = p_basis[simplex_face]\n", + " offset_face = offsets[simplex_face]\n", + " rows = self._get_row_face_matrix(primitives, f, face_primitives,\n", + " offset_simplex, offset_face,\n", + " len_row)\n", + " M = M.stack(rows)\n", + " return M[1:]\n", + " \n", + " def _get_solution(self, sol, p_basis):\n", + " S = self.parent().simplicialComplex()\n", + " dim = S.dimension()\n", + " min_dim = self.degree()-1\n", + " offset = 0\n", + " values = {}\n", + " for n in reversed(range(dim+1)):\n", + " apl = SimplicialAlgebraplN(n)\n", + " for s in S._n_cells_sorted(n):\n", + " simplex = s.tuple()\n", + " pol = apl(0)\n", + " if simplex in p_basis.keys():\n", + " primitives = p_basis[simplex]\n", + " if primitives:\n", + " for p in primitives:\n", + " i = primitives.index(p)\n", + " coef = sol[offset+i]\n", + " pol += coef*p\n", + " offset += len(primitives)\n", + " values[simplex] = pol \n", + " A = self.parent()\n", + "# return values\n", + " return A._element_constructor_(values)\n", + " \n", + " def solve_primitive(self):\n", + " p_basis = self._get_primitive_basis()\n", + " d_basis = self._get_differential_basis(p_basis)\n", + " diff_matrix = self._get_differential_matrix(p_basis, d_basis)\n", + " v_dif = self._get_vector_diff_coordinates(d_basis)\n", + " face_matrix = self._get_face_matrix(p_basis)\n", + " nrows = face_matrix.nrows()\n", + " v = vector(QQ, list(v_dif)+nrows*[0])\n", + " M = diff_matrix.stack(face_matrix)\n", + " sol = M.solve_right(v)\n", + " return self._get_solution(sol, p_basis)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defining t0, t1, t2, y0, y1, y2\n" + ] + }, + { + "data": { + "text/plain": [ + "{(0,): 0, (1,): 0, (2,): 0, (3,): 0, (4,): 0, (0, 1): 0, (0, 2): 0, (0, 3): 0, (0, 4): 0, (1, 2): 0, (1, 3): 0, (1, 4): 0, (2, 3): 0, (2, 4): 0, (3, 4): 0, (0, 1, 2): 0, (0, 1, 3): 0, (0, 1, 4): 0, (0, 2, 3): 0, (0, 2, 4): 0, (0, 3, 4): 0, (1, 2, 3): 0, (1, 2, 4): 0, (1, 3, 4): 0, (2, 3, 4): 0, (0, 1, 2, 3): 3*y1*y2*y3, (0, 1, 2, 4): -3*y1*y2*y3, (0, 1, 3, 4): -3*y1*y2*y3, (0, 2, 3, 4): 0, (1, 2, 3, 4): -3*y1*y2*y3, (0, 1, 2, 3, 4): 3*y1*y2*y3 - 3*y1*y2*y4 - 3*y1*y3*y4}" + ] + }, + "execution_count": 89, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "S = SimplicialComplex([[0,1,2,3,4]],is_mutable=False)\n", + "A = AlgebraAplK(S)\n", + "s0 = SimplicialAlgebraplN(0)\n", + "s1 = SimplicialAlgebraplN(1)\n", + "s2 = SimplicialAlgebraplN(2)\n", + "s3 = SimplicialAlgebraplN(3)\n", + "s4 = SimplicialAlgebraplN(4)\n", + "s2.inject_variables()\n", + "p012 = y1*y2\n", + "p013 = y1*y2\n", + "p023 = y1*y2\n", + "p024 = y1*y2\n", + "p034 = y1*y2\n", + "p123 = y1*y2\n", + "p124 = y1*y2\n", + "p134 = y1*y2\n", + "p234 = y1*y2\n", + "\n", + "p0123 = p012.propagate([0,1,2],3) + p123.propagate([1,2,3],3)+p013.propagate([0,1,3],3)\n", + "p0134 = p013.propagate([0,1,2],3)\n", + "p0124 = p012.propagate([0,1,2],3)\n", + "p1234 = p123.propagate([0,1,2],3)\n", + "p01234 = p012.propagate([0,1,2],4) + p123.propagate([1,2,3],4) + p013.propagate([0,1,3],4)\n", + "\n", + "values = {(0,): s0(0), (1,): s0(0), (2,): s0(0), (3,): s0(0), (4,): s0(0), \n", + " (0,1): s1(0), (0,2): s1(0), (0,3): s1(0), (0,4): s1(0),\n", + " (1,2): s1(0), (1,3): s1(0), (1,4): s1(0), \n", + " (2,3): s1(0), (2,4): s1(0), \n", + " (3,4): s1(0), \n", + " (0,1,2): p012, (0,1,3): p013, (0,1,4): s2(0), \n", + " (0,2,3): s2(0), (0,2,4): s2(0), (0,3,4): s2(0),\n", + " (1,2,3): p123, (1,2,4): s2(0), (1,3,4): s2(0),\n", + " (2,3,4): s2(0), \n", + " (0,1,2,3): p0123,(0,1,2,4):p0124,(0,1,3,4): p0134,\n", + " (0,2,3,4): s3(0),(1,2,3,4): p1234,\n", + " (0,1,2,3,4): p01234}\n", + "e1 = A._element_constructor_(values)\n", + "dife1 = e1.differential()\n", + "dife1" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{(0, 1, 2, 3, 4): t3*y1*y2 - t4*y1*y2 - t2*y1*y3 - t4*y1*y3 + t1*y2*y3 + t2*y1*y4 + t3*y1*y4 - t1*y2*y4 - t1*y3*y4 + y1*y2 + y1*y3, (0, 1, 2, 3): t3*y1*y2 - t2*y1*y3 + t1*y2*y3 + y1*y2 + y1*y3, (0, 1, 2, 4): -t3*y1*y2 + t2*y1*y3 - t1*y2*y3 + y1*y2, (0, 1, 3, 4): -t3*y1*y2 + t2*y1*y3 - t1*y2*y3 + y1*y2, (0, 2, 3, 4): 0, (1, 2, 3, 4): -t3*y1*y2 + t2*y1*y3 - t1*y2*y3 + y1*y2, (0, 1, 2): y1*y2, (0, 1, 3): y1*y2, (0, 1, 4): 0, (0, 2, 3): 0, (0, 2, 4): 0, (0, 3, 4): 0, (1, 2, 3): y1*y2, (1, 2, 4): 0, (1, 3, 4): 0, (2, 3, 4): 0, (0, 1): 0, (0, 2): 0, (0, 3): 0, (0, 4): 0, (1, 2): 0, (1, 3): 0, (1, 4): 0, (2, 3): 0, (2, 4): 0, (3, 4): 0, (0,): 0, (1,): 0, (2,): 0, (3,): 0, (4,): 0}" + ] + }, + "execution_count": 90, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "primitive = dife1.solve_primitive()\n", + "primitive" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 91, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "primitive.differential() == dife1" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 92, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "primitive == e1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Example Torus" + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "metadata": {}, + "outputs": [], + "source": [ + "# S = simplicial_complexes.Torus()\n", + "# A = AlgebraAplK(S)\n", + "# s0 = SimplicialAlgebraplN(0)\n", + "# s1 = SimplicialAlgebraplN(1)\n", + "# s2 = SimplicialAlgebraplN(2)\n", + "# s2.inject_variables()\n", + "# values = {(0, 1, 2): s2(0), (0, 1, 5): s2(0), (0, 2, 6): s2(0), (0, 3, 4): s2(0), (0, 3, 5): s2(0), \n", + "# (0, 4, 6): s2(0), (1, 2, 4): s2(0), (1, 3, 4): s2(0), (1, 3, 6): -y1*y2, (1, 5, 6): s2(0), \n", + "# (2, 3, 5): s2(0), (2, 3, 6): s2(0), (2, 4, 5): y1*y2, (4, 5, 6): s2(0), \n", + "# (0, 1): s1(0), (0, 2): s1(0), (0, 3): s1(0), (0, 4): s1(0), (0, 5): s1(0), (0, 6): s1(0), \n", + "# (1, 2): s1(0), (1, 3): s1(0), (1, 4): s1(0), (1, 5): s1(0), (1, 6): s1(0), (2, 3): s1(0), (2, 4): s1(0), \n", + "# (2, 5): s1(0), (2, 6): s1(0), (3, 4): s1(0), (3, 5): s1(0), (3, 6): s1(0), (4, 5): s1(0), (4, 6): s1(0), (5, 6): s1(0), \n", + "# (0,): s0(0), (1,): s0(0), (2,): s0(0), (3,): s0(0), (4,): s0(0), (5,): s0(0), (6,): s0(0)}\n", + "# e = A._element_constructor_(values)\n", + "# preimage = e.solve_primitive()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test with random complexes and random elements of Apl(K)" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": {}, + "outputs": [], + "source": [ + "def sublist(lst1, lst2):\n", + " return set(lst1) <= set(lst2)\n", + "\n", + "def sublist_of_lists(list1,list_of_lists):\n", + " is_sublist = False\n", + " for list2 in list_of_lists:\n", + " if sublist(list1,list2):\n", + " is_sublist = True\n", + " break\n", + " return is_sublist\n", + "\n", + "def random_simplicial_complex(num_vertices,max_num_facets):\n", + " vertices = list(range(num_vertices))\n", + " simplices = []\n", + " partitions = []\n", + " for length in range(num_vertices):\n", + " partitions += [tuple(e) for e in powerset(vertices) if len(e)==length and e]\n", + " for i in range(max_num_facets):\n", + " r = randint(0,len(partitions)-1)\n", + " candidate = partitions[r]\n", + " if not sublist_of_lists(candidate,simplices):\n", + " simplices.append(candidate)\n", + " return SimplicialComplex(simplices,is_mutable=False)\n", + "\n", + "def random_cochain(S):\n", + " dim = S.dimension()\n", + " cochain = {}\n", + " for n in range(dim+1):\n", + " for s in S._n_cells_sorted(n):\n", + " cochain[s.tuple()] = randint(-100,100)\n", + " return cochain" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(0, 4, 5), (1, 2, 5), (0, 1, 2, 3)}" + ] + }, + "execution_count": 95, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "S = random_simplicial_complex(6,4)\n", + "# S = SimplicialComplex([5],is_mutable=False)\n", + "cochain = random_cochain(S)\n", + "S" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "metadata": {}, + "outputs": [], + "source": [ + "A = AlgebraAplK(S)\n", + "e = A.lift_cochain(cochain)\n", + "dife = e.differential()" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "deg: 1\n", + "deg: 2\n", + "deg: 3\n", + "dif(recover) == dif(e): True\n" + ] + } + ], + "source": [ + "hom_parts = dife.homogeneous_parts()\n", + "recover = A.null_element()\n", + "for deg in hom_parts.keys():\n", + " print(\"deg: \", deg)\n", + " recover += hom_parts[deg].solve_primitive()\n", + "print(\"dif(recover) == dif(e): \", recover.differential() == dife)\n", + "# print(\"recover == e: \", recover == e) # Although their differentials are equal, this is not always True" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defining t0, t1, t2, t3, y0, y1, y2, y3\n", + "\n", + "e1:\n", + "{(0,): 0, (1,): 0, (2,): 0, (3,): 0, (0, 1): 0, (0, 2): 0, (0, 3): 0, (1, 2): 0, (1, 3): 0, (2, 3): 0, (0, 1, 2): 0, (0, 1, 3): 0, (0, 2, 3): 0, (1, 2, 3): 0, (0, 1, 2, 3): y1*y2*y3}\n", + "\n", + "e2\n", + "{(0, 1, 2, 3): 1/3*t3*y1*y2 - 1/3*t2*y1*y3 + 1/3*t1*y2*y3 - 1/3*y1*y2, (0, 1, 2): -1/3*y1*y2, (0, 1, 3): 0, (0, 2, 3): 0, (1, 2, 3): 0, (0, 1): 0, (0, 2): 0, (0, 3): 0, (1, 2): 0, (1, 3): 0, (2, 3): 0, (0,): 0, (1,): 0, (2,): 0, (3,): 0}\n", + "\n", + "d(e2) == e1: True\n" + ] + } + ], + "source": [ + "S = SimplicialComplex([[0,1,2,3]],is_mutable=False)\n", + "A = AlgebraAplK(S)\n", + "s0 = SimplicialAlgebraplN(0)\n", + "s1 = SimplicialAlgebraplN(1)\n", + "s2 = SimplicialAlgebraplN(2)\n", + "s3 = SimplicialAlgebraplN(3)\n", + "s3.inject_variables()\n", + "p0123 = y1*y2*y3\n", + "values = {(0,): s0(0), (1,): s0(0), (2,): s0(0), (3,): s0(0), (0,1): s1(0), (0,2): s1(0),\n", + " (0,3): s1(0), (1,2): s1(0), (1,3): s1(0), (2,3): s1(0), (0,1,2): s2(0), (0,1,3): s2(0), \n", + " (0,2,3): s2(0), (1,2,3): s2(0), (0,1,2,3): p0123}\n", + "e1 = A._element_constructor_(values)\n", + "print(\"\")\n", + "print(\"e1:\")\n", + "print(e1)\n", + "print(\"\")\n", + "e2 = e1.solve_primitive()\n", + "print(\"e2\")\n", + "print(e2)\n", + "print(\"\")\n", + "print(\"d(e2) == e1: \", e2.differential() == e1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example of degree 0" + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defining t0, t1, t2, y0, y1, y2\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 99, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "S = SimplicialComplex([[0,1,2], [0,1,3]],is_mutable=False)\n", + "A = AlgebraAplK(S)\n", + "s0 = SimplicialAlgebraplN(0)\n", + "s2 = SimplicialAlgebraplN(2)\n", + "s2.inject_variables()\n", + "p012 = y0\n", + "p013 = y0\n", + "values = {(0,): s0(0), (1,): s0(0), (2,): s0(0), (3,): s0(0), (0,1): p012.face(2), (0,2): p012.face(1),\n", + " (0,3): p013.face(1), (1,2): p012.face(0), (1,3): p013.face(0), (0,1,2): p012, (0,1,3): p013}\n", + "e1 = A._element_constructor_(values)\n", + "e2 = e1.solve_primitive()\n", + "e2.differential() == e1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example" + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defining t0, t1, t2, t3, y0, y1, y2, y3\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 100, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "S = SimplicialComplex([[0,1,2,3]],is_mutable=False)\n", + "A = AlgebraAplK(S)\n", + "s0 = SimplicialAlgebraplN(0)\n", + "s1 = SimplicialAlgebraplN(1)\n", + "s2 = SimplicialAlgebraplN(2)\n", + "s3 = SimplicialAlgebraplN(3)\n", + "s3.inject_variables()\n", + "p0123 = y1*y2*y3\n", + "values = {(0,): s0(0), (1,): s0(0), (2,): s0(0), (3,): s0(0), (0,1): s1(0), (0,2): s1(0),\n", + " (0,3): s1(0), (1,2): s1(0), (1,3): s1(0), (2,3): s1(0), (0,1,2): s2(0), (0,1,3): s2(0), \n", + " (0,2,3): s2(0), (1,2,3): s2(0), (0,1,2,3): p0123}\n", + "e1 = A._element_constructor_(values)\n", + "primitive = e1.solve_primitive()\n", + "primitive.differential() == e1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Another example" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Defining t0, t1, t2, y0, y1, y2\n" + ] + }, + { + "data": { + "text/plain": [ + "{(0,): 0, (1,): 0, (2,): 0, (3,): 0, (4,): 0, (0, 1): 0, (0, 2): 0, (0, 3): 0, (0, 4): 0, (1, 2): 0, (1, 3): 0, (1, 4): 0, (2, 3): 0, (2, 4): 0, (3, 4): 0, (0, 1, 2): y1*y2, (0, 1, 3): y1*y2, (0, 1, 4): 0, (0, 2, 3): 0, (0, 2, 4): 0, (0, 3, 4): 0, (1, 2, 3): y1*y2, (1, 2, 4): 0, (1, 3, 4): 0, (2, 3, 4): 0, (0, 1, 2, 3): t3*y1*y2 - t2*y1*y3 + t1*y2*y3 + y1*y2 + y1*y3, (0, 1, 2, 4): -t3*y1*y2 + t2*y1*y3 - t1*y2*y3 + y1*y2, (0, 1, 3, 4): -t3*y1*y2 + t2*y1*y3 - t1*y2*y3 + y1*y2, (0, 2, 3, 4): 0, (1, 2, 3, 4): -t3*y1*y2 + t2*y1*y3 - t1*y2*y3 + y1*y2, (0, 1, 2, 3, 4): t3*y1*y2 - t4*y1*y2 - t2*y1*y3 - t4*y1*y3 + t1*y2*y3 + t2*y1*y4 + t3*y1*y4 - t1*y2*y4 - t1*y3*y4 + y1*y2 + y1*y3}" + ] + }, + "execution_count": 101, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "S = SimplicialComplex([[0,1,2,3,4]],is_mutable=False)\n", + "A = AlgebraAplK(S)\n", + "s0 = SimplicialAlgebraplN(0)\n", + "s1 = SimplicialAlgebraplN(1)\n", + "s2 = SimplicialAlgebraplN(2)\n", + "s3 = SimplicialAlgebraplN(3)\n", + "s4 = SimplicialAlgebraplN(4)\n", + "s2.inject_variables()\n", + "p012 = y1*y2\n", + "p013 = y1*y2\n", + "p023 = y1*y2\n", + "p024 = y1*y2\n", + "p034 = y1*y2\n", + "p123 = y1*y2\n", + "p124 = y1*y2\n", + "p134 = y1*y2\n", + "p234 = y1*y2\n", + "\n", + "p0123 = p012.propagate([0,1,2],3) + p123.propagate([1,2,3],3)+p013.propagate([0,1,3],3)\n", + "p0134 = p013.propagate([0,1,2],3)\n", + "p0124 = p012.propagate([0,1,2],3)\n", + "p1234 = p123.propagate([0,1,2],3)\n", + "p01234 = p012.propagate([0,1,2],4) + p123.propagate([1,2,3],4) + p013.propagate([0,1,3],4)\n", + "\n", + "values = {(0,): s0(0), (1,): s0(0), (2,): s0(0), (3,): s0(0), (4,): s0(0), \n", + " (0,1): s1(0), (0,2): s1(0), (0,3): s1(0), (0,4): s1(0),\n", + " (1,2): s1(0), (1,3): s1(0), (1,4): s1(0), \n", + " (2,3): s1(0), (2,4): s1(0), \n", + " (3,4): s1(0), \n", + " (0,1,2): p012, (0,1,3): p013, (0,1,4): s2(0), \n", + " (0,2,3): s2(0), (0,2,4): s2(0), (0,3,4): s2(0),\n", + " (1,2,3): p123, (1,2,4): s2(0), (1,3,4): s2(0),\n", + " (2,3,4): s2(0), \n", + " (0,1,2,3): p0123,(0,1,2,4):p0124,(0,1,3,4): p0134,\n", + " (0,2,3,4): s3(0),(1,2,3,4): p1234,\n", + " (0,1,2,3,4): p01234}\n", + "e1 = A._element_constructor_(values)\n", + "e1" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": {}, + "outputs": [], + "source": [ + "dife1 = e1.differential()\n", + "#dife1" + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dif(recovery) == diff(e1): True\n" + ] + } + ], + "source": [ + "recovery = dife1.solve_primitive()\n", + "print(\"dif(recovery) == diff(e1): \",recovery.differential() == dife1)\n", + "#recovery" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Minimal model" + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": {}, + "outputs": [], + "source": [ + "def update_cdga(gca, diff_dict={}):\n", + "\n", + " gens_dict = gca.gens_dict()\n", + " differentials = {}\n", + " if diff_dict:\n", + " for gen_name in diff_dict.keys():\n", + " gen = gens_dict[gen_name]\n", + " product_gens = diff_dict[gen_name]\n", + " gen0 = gens_dict[product_gens[0]]\n", + " if type(product_gens[1]) == int: # is a power\n", + " power = product_gens[1]\n", + " mult = gen0\n", + " for i in range(1, power):\n", + " mult *= gen0\n", + " differentials.update({gen:mult})\n", + " else:\n", + " gen1 = gens_dict[product_gens[1]]\n", + " differentials.update({gen:gen0*gen1})\n", + "# print(\"differentials\", differentials)\n", + " return gca.cdg_algebra(differentials) \n", + "\n", + " \n", + "def has_preimage(M, element):\n", + " \n", + " d = M.differential()\n", + " deg = element.degree()-1\n", + "# print(\"differential of \", element, \"degree: \", deg)\n", + " Md = d.differential_matrix(deg)\n", + " gens = M.basis(deg)\n", + " try:\n", + " solution = Md.solve_left(vector(QQ,element.basis_coefficients()))\n", + " primitive = sum(map(lambda coef, gen: coef*gen, solution, gens))\n", + " print(element, \" has preimage \", primitive)\n", + " return True\n", + " except ValueError:\n", + " return False\n", + "\n", + "def injectivity_step(M, phi, check_dim, names, \n", + " degrees, differentials, index=0, depth=0, max_depth=5):\n", + " \n", + " print(\"Injectivity at dimension \", check_dim)\n", + " if depth > max_depth:\n", + " return [M, phi, names, degrees, differentials, True]\n", + " deg = check_dim -1\n", + " gens = [g for g in M.gens() if g.degree() < check_dim]\n", + "# gens.sort(reverse=True)\n", + " gen_products = []\n", + " for i in range(len(gens)):\n", + " e0 = gens[i]\n", + " d = e0.degree()\n", + " mcd = gcd(d, check_dim)\n", + " if d%2 == 0 and mcd == d:\n", + " power = True\n", + " exp = check_dim / d\n", + " mult = e0\n", + " for j in range(1,exp-1):\n", + " mult *= e0\n", + " gen_products.append([e0, mult, power, exp])\n", + " for j in range(i+1,len(gens)):\n", + " power = False\n", + " e1 = gens[j]\n", + " if e0.degree() + e1.degree() == check_dim:\n", + " gen_products.append([e0, e1, power])\n", + "# print(\"products at dim \",check_dim,\": \", gen_products)\n", + " new_M = M\n", + " new_phi = phi\n", + " new_names = names\n", + " new_degrees = degrees\n", + " new_differentials = differentials\n", + " for pair in gen_products:\n", + " # Looking at the minimal model side\n", + " gen0 = pair[0]\n", + " deg_0 = gen0.degree()\n", + " gen1 = pair[1]\n", + " deg_1 = gen1.degree()\n", + " M_product = gen0*gen1\n", + " # Looking at the AplK side\n", + " gen0_name = list(M.gens_dict().keys())[list(M.gens_dict().values()).index(gen0)]\n", + " aplk_gen0 = phi[deg_0][gen0_name]\n", + " is_power = pair[2]\n", + " power = 0\n", + " if is_power:\n", + " power = pair[3]\n", + " aplk_gen1 = aplk_gen0\n", + " for i in range(1, power):\n", + " aplk_gen1 *= aplk_gen0\n", + " else:\n", + " gen1_name = list(M.gens_dict().keys())[list(M.gens_dict().values()).index(gen1)]\n", + " aplk_gen1 = phi[deg_1][gen1_name]\n", + " aplk_product = aplk_gen0*aplk_gen1\n", + " A = aplk_product.parent()\n", + " # Check conditions\n", + " if (M_product == M(0)) and (aplk_product == A.null_element()): # zero element\n", + " pass\n", + " elif (M_product == M(0)) and (aplk_product != A.null_element()): #check\n", + " if aplk_product.is_closed():\n", + " pass #trivial cohomology class (assuming aplk_product has preimage by differential)\n", + " else:\n", + " raise ValueError('zero associated to a non-closed element in AplK')\n", + " elif (M_product.differential() != 0): # is not closed\n", + " print(\"The element \",M_product, \" is not closed\")\n", + " pass \n", + " elif (M_product.differential() == 0) and aplk_product.is_closed() and has_preimage(M, M_product):\n", + " pass #trivial cohomology class (assuming aplk_product has preimage by differential)\n", + " elif (M_product.differential() == 0) and aplk_product.is_closed(): #key step because M_product doesn't have preimage\n", + " new_gen = 'y'+str(deg)+'_'+str(index)\n", + " if aplk_product != A.null_element():\n", + " try:\n", + " preimage = aplk_product.solve_primitive()\n", + " except ValueError:\n", + " print(\" The element \",M_product, \" has non trivial cohomology class. No generator added.\")\n", + " continue # we don't add a new generator because the element has non trivial cohomology class\n", + " phi_new_gen = {new_gen: preimage}\n", + " else: \n", + " phi_new_gen = {new_gen: A.null_element()}\n", + " print(\" Proceed to kill\", M_product, \" because has associated trivial cohomology class\")\n", + " print(\"Adding generator \"+new_gen)\n", + " new_names = names + [new_gen]\n", + " new_degrees = tuple(list(degrees)+[deg])\n", + " new_differentials = copy.deepcopy(differentials)\n", + " if not is_power:\n", + " new_differentials.update({new_gen: [gen0_name, gen1_name]})\n", + " else:\n", + " new_differentials.update({new_gen: [gen0_name, int(power)]})\n", + " gca = GradedCommutativeAlgebra(QQ, names=new_names, degrees=new_degrees)\n", + " new_M = update_cdga(gca, new_differentials)\n", + " new_phi = copy.deepcopy(phi)\n", + " d = new_phi[deg]\n", + " d.update(phi_new_gen)\n", + " return injectivity_step(new_M, new_phi, check_dim, new_names, \n", + " new_degrees, new_differentials, index=index+1, depth=depth+1, max_depth=max_depth)\n", + " else:\n", + " pass\n", + "\n", + " return [new_M, new_phi, new_names, new_degrees, new_differentials, False]\n", + "\n", + "def get_unmapped_generators(dim, coho_aplk, coho_gens, correspondence):\n", + "\n", + " dimensions = list(correspondence.keys())\n", + " unmmaped_elements = copy.deepcopy(coho_aplk)\n", + " for gen_key in coho_gens.keys():\n", + " gen = coho_gens[gen_key]\n", + " found = False\n", + " for i in range(1,dim):\n", + " if (not found) and (i in dimensions):\n", + " for j in range(i,dim):\n", + " if (j in dimensions) and (i+j == dim):\n", + " gensi = correspondence[i]\n", + " gensj = correspondence[j]\n", + " for gi in gensi.values():\n", + " if not found:\n", + " for gj in gensj.values():\n", + " product = gi.cup_product(gj) \n", + " if product == gen or -product == gen:\n", + " found = True\n", + " i_name = list(gensi.keys())[list(gensi.values()).index(gi)]\n", + " j_name = list(gensj.keys())[list(gensj.values()).index(gj)]\n", + " if gen_key in unmmaped_elements.keys():\n", + " print(\"The element \",i_name+\"*\"+j_name,\" is already mapped\")\n", + " del unmmaped_elements[gen_key]\n", + " break\n", + " return unmmaped_elements\n", + "\n", + "def surjective_step(A, M, phi, dim, names, degrees, differentials, cohomology_correspondence):\n", + " \n", + " print(\"Surjectivity at dimension \", dim)\n", + " coho_aplk = A.get_cohomology_aplk(dim)\n", + " cohomology_gens = A.cohomology_gens(dim)\n", + " g = get_unmapped_generators(dim, coho_aplk, cohomology_gens, cohomology_correspondence)\n", + " new_names = copy.deepcopy(names)\n", + " new_degrees = copy.deepcopy(degrees)\n", + " new_phi = copy.deepcopy(phi)\n", + " new_correspondence = copy.deepcopy(cohomology_correspondence)\n", + " phi_n_map = {}\n", + " correspondence_n_map = {}\n", + " for gen_key in g.keys():\n", + " deg = gen_key[0]\n", + " index = gen_key[1]\n", + " new_var = 'x'+str(deg)+'_'+str(index)\n", + " new_names += [new_var]\n", + " new_degrees += [deg]\n", + " phi_n_map[new_var] = g[gen_key]\n", + " correspondence_n_map[new_var] = cohomology_gens[gen_key]\n", + " gca = GradedCommutativeAlgebra(QQ, names=new_names, degrees=new_degrees)\n", + " new_M = update_cdga(gca, differentials)\n", + " new_phi[dim] = phi_n_map\n", + " new_correspondence[dim] = correspondence_n_map\n", + " return [new_M, new_phi, new_names, new_degrees, new_correspondence]\n", + " \n", + "def minimal_model(S, max_depth=5, max_dim=5):\n", + " \n", + " fundamental_group = S.fundamental_group()\n", + " if (fundamental_group.order() != 1):\n", + " print(\"Warning: The space is not simply-connected\")\n", + " phi = {}\n", + " cohomology_correspondence = {}\n", + " A = AlgebraAplK(S)\n", + " # First step of the algorithm\n", + " first_dim = A.first_cohomology_group()\n", + " phi_n_map = {}\n", + " correspondence_n_map = {}\n", + " if first_dim < 0:\n", + " return [0,{},{}] # due to the function returns multiple objects\n", + " elif first_dim > max_dim:\n", + " return [0,{},{}] # due to the function returns multiple objects\n", + " g = A.get_cohomology_aplk(first_dim)\n", + " cohomology_gens = A.cohomology_gens(first_dim)\n", + " names = []\n", + " degrees = []\n", + " for gen_key in g.keys():\n", + " deg = gen_key[0]\n", + " index = gen_key[1]\n", + " new_var = 'x'+str(deg)+'_'+str(index)\n", + " names += [new_var]\n", + " degrees += [deg]\n", + " phi_n_map[new_var] = g[gen_key]\n", + " correspondence_n_map[new_var] = cohomology_gens[gen_key]\n", + " differentials={}\n", + " gca = GradedCommutativeAlgebra(QQ, names=names, degrees=degrees)\n", + " M = gca.cdg_algebra(differentials)\n", + " phi[first_dim] = phi_n_map\n", + " cohomology_correspondence[first_dim] = correspondence_n_map\n", + " # Now we have an isomorphism in the first non-null cohomology group\n", + " # we check if phi is a monomorphism\n", + " [M, phi, names, degrees, differentials, limit] = injectivity_step(M, phi, first_dim+1, names, \n", + " degrees, differentials, index=0, depth=0, max_depth=5)\n", + " if limit:\n", + " print(\"The algorithm has reach the injectivity depth-limit at dimension \", first_dim)\n", + " return [M, phi]\n", + " else:\n", + " dim = first_dim + 1\n", + " for i in range(dim, max_dim):\n", + " [M, phi, names, degrees, cohomology_correspondence] = surjective_step(A, M, phi, i, names, degrees, \n", + " differentials, cohomology_correspondence)\n", + " [M, phi, names, degrees, differentials, limit] = injectivity_step(M, phi, i+1, names, \n", + " degrees, differentials, index=0, depth=0, max_depth=5)\n", + " if limit:\n", + " print(\"The algorithm has reach the injectivity depth-limit at dimension\", dim)\n", + " break \n", + " \n", + " return [M, phi, cohomology_correspondence]\n", + "\n", + "# def minimal_model():\n", + "# names = ['x1_0','x1_1']\n", + "# degrees = (1,1)\n", + "# differentials={}\n", + "# gca = GradedCommutativeAlgebra(QQ, names=names, degrees=degrees)\n", + "# cdga = gca.cdg_algebra(differentials)\n", + "# print(cdga)\n", + "# # añadimos el generador de grado uno con differencial producto de los anteriores\n", + "# new_gen = 'y1_0'\n", + "# names = names + [new_gen]\n", + "# deg = 1\n", + "# degrees = tuple(list(degrees)+[deg])\n", + "# differentials.update({'y1_0':['x1_0','x1_1']})\n", + "# gca = GradedCommutativeAlgebra(QQ, names=names, degrees=degrees)\n", + "# new_cdga = update_cdga(gca, differentials)\n", + "# print(new_cdga)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Injectivity at dimension 3\n", + "Surjectivity at dimension 3\n", + "Injectivity at dimension 4\n", + " Proceed to kill x2_0^2 because has associated trivial cohomology class\n", + "Adding generator y3_0\n", + "Injectivity at dimension 4\n", + "x2_0^2 has preimage y3_0\n", + " Proceed to kill x2_0*x2_1 because has associated trivial cohomology class\n", + "Adding generator y3_1\n", + "Injectivity at dimension 4\n", + "x2_0^2 has preimage y3_0\n", + "x2_0*x2_1 has preimage y3_1\n", + " Proceed to kill x2_1^2 because has associated trivial cohomology class\n", + "Adding generator y3_2\n", + "Injectivity at dimension 4\n", + "x2_0^2 has preimage y3_0\n", + "x2_0*x2_1 has preimage y3_1\n", + "x2_1^2 has preimage y3_2\n", + "Surjectivity at dimension 4\n", + "Injectivity at dimension 5\n", + "The element x2_0*y3_0 is not closed\n", + "The element x2_0*y3_1 is not closed\n", + "The element x2_0*y3_2 is not closed\n", + "The element x2_1*y3_0 is not closed\n", + "The element x2_1*y3_1 is not closed\n", + "The element x2_1*y3_2 is not closed\n", + "Surjectivity at dimension 5\n", + "Injectivity at dimension 6\n", + "x2_0^3 has preimage x2_0*y3_0\n", + "x2_1^3 has preimage x2_1*y3_2\n", + "The element y3_0*y3_1 is not closed\n", + "The element y3_0*y3_2 is not closed\n", + "The element y3_1*y3_2 is not closed\n", + "Surjectivity at dimension 6\n", + "Injectivity at dimension 7\n", + "Surjectivity at dimension 7\n", + "Injectivity at dimension 8\n", + "x2_0^4 has preimage x2_0^2*y3_0\n", + "x2_1^4 has preimage x2_1^2*y3_2\n", + "Surjectivity at dimension 8\n", + "Injectivity at dimension 9\n", + "Surjectivity at dimension 9\n", + "Injectivity at dimension 10\n", + "x2_0^5 has preimage x2_0^3*y3_0\n", + "x2_1^5 has preimage x2_1^3*y3_2\n" + ] + }, + { + "data": { + "text/plain": [ + "Commutative Differential Graded Algebra with generators ('x2_0', 'x2_1', 'y3_0', 'y3_1', 'y3_2') in degrees (2, 2, 3, 3, 3) over Rational Field with differential:\n", + " x2_0 --> 0\n", + " x2_1 --> 0\n", + " y3_0 --> x2_0^2\n", + " y3_1 --> x2_0*x2_1\n", + " y3_2 --> x2_1^2" + ] + }, + "execution_count": 105, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# S = SimplicialComplex([[0,1],[0,2],[1,2]],is_mutable=False) # S^1\n", + "# S = SimplicialComplex([[0,1],[0,2],[1,2],[1,3],[2,3]],is_mutable=False) # S^1 wedge S^1\n", + "# S = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3]],is_mutable=False) # S^2\n", + "# S = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4],[3,5],[4,5]],is_mutable=False) # S^1 wedge S^2\n", + "# S = SimplicialComplex([[0,1,2],[0,3,4],[1,3,5]],is_mutable=False) # S^1 surrounded by 2-cells\n", + "# S = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4,5],[3,4,6],[3,5,6],[4,5,6]],is_mutable=False) # S^2 wedge S^2\n", + "# S = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[0,2,4],[0,3,4],[2,3,4]],is_mutable=False) # S^2 wedge S^2\n", + "# S = SimplicialComplex([[0,2,3],[0,2,4,5],[0,1,2,5],[1,2,3,6],[2,3,4,6],[0,1,3,7],[0,3,4,7]],is_mutable=False) # S^2 wedge S^2\n", + "# S = simplicial_complexes.Torus()\n", + "#######################################################\n", + "# S = simplicial_complexes.Sphere(2)\n", + "#######################################################\n", + "# S = simplicial_complexes.K3Surface()\n", + "#######################################################\n", + "S1 = simplicial_complexes.Sphere(2)\n", + "S2 = simplicial_complexes.Sphere(2)\n", + "S = S1.wedge(S2, is_mutable=False)\n", + "#######################################################\n", + "#S = simplicial_complexes.ComplexProjectivePlane()\n", + "#######################################################\n", + "# S = simplicial_complexes.BrucknerGrunbaumSphere()\n", + "#######################################################\n", + "# S = simplicial_complexes.ProjectivePlane().wedge(simplicial_complexes.Sphere(2), is_mutable=False)\n", + "#######################################################\n", + "[sullivan_model, model_morphism, cohomology_correspondence] = minimal_model(S, max_depth=5, max_dim=10)\n", + "sullivan_model" + ] + }, + { + "cell_type": "code", + "execution_count": 106, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[x2_0^3, x2_0^2*x2_1, x2_0*x2_1^2, x2_1^3, y3_0*y3_1, y3_0*y3_2, y3_1*y3_2]" + ] + }, + "execution_count": 106, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sullivan_model.basis(6)" + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{2: [x2_0, x2_1], 5: [x2_1*y3_0 - x2_0*y3_1, x2_1*y3_1 - x2_0*y3_2]}" + ] + }, + "execution_count": 107, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sullivan_model.cohomology_generators(10)" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "metadata": {}, + "outputs": [], + "source": [ + "a = model_morphism[2]['x2_0']^2\n", + "b = model_morphism[3]['y3_0'] # no deberia salir 0" + ] + }, + { + "cell_type": "code", + "execution_count": 109, + "metadata": {}, + "outputs": [ + { + "ename": "KeyError", + "evalue": "()", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msolve_primitive\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36msolve_primitive\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 214\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 215\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0msolve_primitive\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 216\u001b[0;31m \u001b[0mp_basis\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_primitive_basis\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 217\u001b[0m \u001b[0md_basis\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_differential_basis\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mp_basis\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 218\u001b[0m \u001b[0mdiff_matrix\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_differential_matrix\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mp_basis\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0md_basis\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36m_get_primitive_basis\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 35\u001b[0m \u001b[0mprimitive_basis\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0msimplex\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 36\u001b[0m \u001b[0;31m# add primitive elements related to the assigned polynomial\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 37\u001b[0;31m \u001b[0mpol\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0melements\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0msimplex\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 38\u001b[0m \u001b[0mprimitive_basis\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0msimplex\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mpol\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_primitive_basis\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[0mprimitive_basis\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0msimplex\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprimitive_basis\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0msimplex\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mKeyError\u001b[0m: ()" + ] + } + ], + "source": [ + "a.solve_primitive()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "S1 = simplicial_complexes.Sphere(2)\n", + "S2 = simplicial_complexes.Sphere(2)\n", + "S = S1.wedge(S2, is_mutable=False)\n", + "A = AlgebraAplK(S)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "S.cohomology_ring().basis()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dim = 5\n", + "# Get the basis of Hm\n", + "hm_basis = sullivan_model.cohomology(dim).basis()\n", + "Hc = A.cohomology_group(dim)\n", + "apl_correspondence = {}\n", + "cochain_correspondence = {}\n", + "Hc_correspondence = {}\n", + "M = zero_matrix(QQ,len(Hc.basis()),len(hm_basis))\n", + "i = 0\n", + "for gen in list(hm_basis.keys()):\n", + " # get an element of the basis of Hm\n", + " # get a representative of a cohomology class in M\n", + " gen_repr = gen.representative()\n", + " # get the apl representative for each generator of M^p\n", + " m_gens = gen_repr.parent().gens()\n", + " aplgens = [model_morphism[g.degree()][str(g)] for g in m_gens]\n", + " apl_correspondence[gen] = A.null_element()\n", + " for exp in gen_repr.dict().keys():\n", + " coef = gen_repr.dict()[exp]\n", + " term = coef*prod([gen^e for gen,e in zip(aplgens, exp)])\n", + " apl_correspondence[gen] += term\n", + " cochain = apl_correspondence[gen].integral()\n", + " cochain_correspondence[gen] = cochain\n", + " vcochain = A.cochain_to_vector(cochain,dim)\n", + " Hc_correspondence[gen] = Hc(vcochain)\n", + " M[:,i] = Hc_correspondence[gen]\n", + " i+=1\n", + "Hc_correspondence\n", + "\n", + "# falta crear la matriz" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "show(M)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gdca_basis = gen_repr.parent().basis(gen_repr.degree())\n", + "gdca_basis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(gen_repr.dict())\n", + "gen_repr.parent().gens()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Hc_2 = A.cohomology_group(2).basis()\n", + "#A.lift_cochain(A.vector_to_cochain(Hc_2.lift((0,1)),2))\n", + "Hc_2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "\n", + "element = Hm_basis[2][0] + Hm_basis[2][1]\n", + "def integralPhiCohomology(element):\n", + " aplelement = model_morphism[2][str(element)]\n", + " cochain = aplelement.integral()\n", + " vcochain = A.cochain_to_vector(cochain,2)\n", + " Hc_2 = A.cohomology_group(2)\n", + " return Hc_2(vcochain)\n", + "integralPhiCohomology(element)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Hc_basis = A.cohomology_gens(2)\n", + "cochain0 = A.lift_cohomology_generator(list(Hc_basis.values())[0])\n", + "cochain1 = A.lift_cohomology_generator(list(Hc_basis.values())[1])\n", + "vcochain0 = A.cochain_to_vector(cochain0,2)\n", + "vcochain1 = A.cochain_to_vector(cochain1,2)\n", + "vcochain = vcochain0-3*vcochain1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Hc_2 = A.cohomology_group(2)\n", + "Hc_2(vcochain)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example step by step" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "K = simplicial_complexes.ComplexProjectivePlane()\n", + "A = AlgebraAplK(K)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# get the lowest dim for which H^{dim} is not trivial\n", + "first_dim = A.first_cohomology_group()\n", + "first_dim" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "g = A.get_cohomology_aplk(first_dim)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "g = A.get_cohomology_aplk(first_dim)\n", + "cohomology_gens = A.cohomology_gens(first_dim)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cohomology_gens" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "names = []\n", + "degrees = []\n", + "phi = {}\n", + "phi_n_map = {}\n", + "cohomology_correspondence = {}\n", + "correspondence_n_map = {}\n", + "for gen_key in g.keys():\n", + " deg = gen_key[0]\n", + " index = gen_key[1]\n", + " new_var = 'x'+str(deg)+'_'+str(index)\n", + " names += [new_var]\n", + " degrees += [deg]\n", + " phi_n_map[new_var] = g[gen_key]\n", + " correspondence_n_map[new_var] = cohomology_gens[gen_key]\n", + "differentials={}\n", + "gca = GradedCommutativeAlgebra(QQ, names=names, degrees=degrees)\n", + "M = gca.cdg_algebra(differentials)\n", + "phi[first_dim] = phi_n_map\n", + "cohomology_correspondence[first_dim] = correspondence_n_map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "r = phi[2]['x2_0']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "count = 0\n", + "for s in r.elements.keys():\n", + " if len(s)==5:\n", + " v = r.elements[s]\n", + " if v != 0:\n", + " count += 1\n", + " print(s, \" ==> \", v)\n", + "print(count)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "r = (phi[2]['x2_0']^2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "count = 0\n", + "for s in r.elements.keys():\n", + " if len(s)==5:\n", + " v = r.elements[s]\n", + " if v != 0:\n", + " count += 1\n", + " print(s, \" ==> \", v)\n", + "print(count)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "M.cohomology(4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "A.cohomology_gens(4)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "c = M.cohomology(4)\n", + "c" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "K.cohomology(4,base_ring=QQ)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "M" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dim = 2\n", + "# Get the basis of Hm\n", + "hm_basis = M.cohomology(dim).basis()\n", + "Hc = A.cohomology_group(dim)\n", + "apl_correspondence = {}\n", + "cochain_correspondence = {}\n", + "Hc_correspondence = {}\n", + "Mat = zero_matrix(QQ,len(Hc.basis()),len(hm_basis))\n", + "i = 0\n", + "for gen in list(hm_basis.keys()):\n", + " # get an element of the basis of Hm\n", + " # get a representative of a cohomology class in M\n", + " gen_repr = gen.representative()\n", + " # get the apl representative for each generator of M^p\n", + " m_gens = gen_repr.parent().gens()\n", + " aplgens = [phi[g.degree()][str(g)] for g in m_gens]\n", + " apl_correspondence[gen] = A.null_element()\n", + " for exp in gen_repr.dict().keys():\n", + " coef = gen_repr.dict()[exp]\n", + " term = coef*prod([gen^e for gen,e in zip(aplgens, exp)])\n", + " apl_correspondence[gen] += term\n", + " cochain = apl_correspondence[gen].integral()\n", + " cochain_correspondence[gen] = cochain\n", + " vcochain = A.cochain_to_vector(cochain,dim)\n", + " Hc_correspondence[gen] = Hc(vcochain)\n", + " Mat[:,i] = Hc_correspondence[gen]\n", + " i+=1\n", + "Hc_correspondence" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "M.cohomology(2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "K.cohomology(5,base_ring=QQ)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gca = GradedCommutativeAlgebra(QQ, names=['x2_0','y5_0'], degrees=(2,5))\n", + "differentials = {gca.gens()[1]:gca.gens()[0]^3}\n", + "M = gca.cdg_algebra(differentials)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "SageMath 9.2", + "language": "sage", + "name": "sagemath" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.5" + }, + "toc-autonumbering": false, + "toc-showmarkdowntxt": false + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/todo-limpio.ipynb b/notebooks/todo-limpio.ipynb deleted file mode 100644 index 3054ab8..0000000 --- a/notebooks/todo-limpio.ipynb +++ /dev/null @@ -1,719 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "from sage.structure.parent import Parent\n", - "from sage.structure.element import Element\n", - "#from sage.structure.unique_representation import UniqueRepresentation\n", - "#from sage.categories.rings import Rings\n", - "from sage.structure.richcmp import rich_to_bool, op_EQ, op_NE, op_LT, op_LE, op_GT, op_GE\n", - "#from sage.categories.morphism import Morphism\n", - "#from sage.rings.rational_field import QQ\n", - "#from sage.algebras.commutative_dga import GradedCommutativeAlgebra\n", - "#from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing\n", - "#from sage.functions.other import factorial\n", - "import itertools\n", - "import copy\n", - "import random" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Simplicial Complex" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "def cohomology_gens(S,n):\n", - " gens = {}\n", - " basis = S.cohomology_ring().basis()\n", - " for k in basis.keys():\n", - " if k[0] == n:\n", - " gens[k] = basis[k]\n", - " return gens" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "def lift_cohomology_generator(S, g):\n", - " cycle = g.to_cycle()\n", - " cochain = {}\n", - " for n in range(S.dimension()+1):\n", - " for simplex in S._n_cells_sorted(n):\n", - " cochain[simplex.tuple()] = 0\n", - " for i in cycle:\n", - " #print(type(i[0].tuple()))\n", - " cochain[i[0].tuple()] = i[1]\n", - " return cochain" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "def sublist(lst1, lst2):\n", - " return set(lst1) <= set(lst2)\n", - "\n", - "def sublist_of_lists(list1,list_of_lists):\n", - " is_sublist = False\n", - " for list2 in list_of_lists:\n", - " if sublist(list1,list2):\n", - " is_sublist = True\n", - " break\n", - " return is_sublist\n", - "\n", - "def random_simplicial_complex(num_vertices,max_num_facets):\n", - " vertices = list(range(num_vertices))\n", - " simplices = []\n", - " partitions = []\n", - " for length in range(num_vertices):\n", - " partitions += [tuple(e) for e in powerset(vertices) if len(e)==length and e]\n", - " for i in range(max_num_facets+1):\n", - " r = randint(0,len(partitions)-1)\n", - " candidate = partitions[r]\n", - " if not sublist_of_lists(candidate,simplices):\n", - " simplices.append(candidate)\n", - " return SimplicialComplex(simplices,is_mutable=False)\n", - "\n", - "def random_cochain(S):\n", - " dim = S.dimension()\n", - " cochain = {}\n", - " for n in range(dim+1):\n", - " for s in S._n_cells_sorted(n):\n", - " cochain[s.tuple()] = randint(-100,100)\n", - " return cochain" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{(2, 4), (0, 1, 3, 4)}" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "S = random_simplicial_complex(5,4)\n", - "S.facets()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Apln" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "class Apln(UniqueRepresentation):\n", - "\n", - " def __init__(self,n):\n", - " self.n = n\n", - " self.algebras = []\n", - " self.relations = []\n", - " for i in range(n+1):\n", - " [cdga, relations] = self._cdga(i)\n", - " self.algebras.append(cdga)\n", - " self.relations.append(relations)\n", - " \n", - " def _cdga(self,n):\n", - " ts = ['t'+str(t) for t in range(n+1)]\n", - " ys = ['y'+str(t) for t in range(n+1)]\n", - " degrees = tuple((n+1)*[(0,2)])+tuple((n+1)*[(1,2)])\n", - " gca = GradedCommutativeAlgebra(QQ, names=ts+ys, degrees=degrees)\n", - " t_relation = -1\n", - " y_relation = 0\n", - " #t_relation = sum(self.gca.gens()[:n])-1\n", - " #y_relation = sum(self.gca.gens()[n:])\n", - " for i in range(n+1):\n", - " t_relation += gca.gens()[i]\n", - " y_relation += gca.gens()[n+1+i]\n", - " #gca_with_relations = self.gca.quotient(self.gca.ideal(t_relation,y_relation),check=False)\n", - " dfs = {gca.gens_dict()[ts[i]]:gca.gens_dict()[ys[i]] for i in range(n+1)}\n", - " return [gca.cdg_algebra(dfs),[t_relation,y_relation]]\n", - " \n", - " def __repr__(self):\n", - " return \"Simplicial algebra of dimension %s\" % self.n\n", - " \n", - " def inject_variables(self, n):\n", - " self.algebras[n].inject_variables()\n", - " \n", - " def generators(self, n):\n", - " return self.algebras[n].gens()\n", - " \n", - " def face(self,i,n):\n", - "\n", - " if(self.n==0):\n", - " return 0\n", - " domain = self.algebras[n]\n", - " codomain = self.algebras[n-1]\n", - " tImages = []\n", - " yImages = []\n", - " n = len(domain.gens())//2\n", - " for k in range(n):\n", - " if(ki):\n", - " tImages.append(codomain.gens()[k-1])\n", - " yImages.append(codomain.gens()[n+k-2])\n", - " images = tImages+yImages\n", - " return domain.hom(codomain=codomain,im_gens=images)\n", - "\n", - " def reduce_polynomial(self,p):\n", - " ## Input:\n", - " # - p: polynomial in variables t_0,..t_n,y_0,...,y_n\n", - " ## Output:\n", - " # - The polynomial after applying the corresponding relations to reduce the variables t_0, y_0\n", - " apl = p.parent()\n", - " dim = len(apl.gens())//2-1\n", - " return p.reduce(self.relations[dim])\n", - " \n", - " def _convert_integrable_polynomial(self,p):\n", - " ## Input:\n", - " # - p: polynomial in variables t_1,..t_n,y_1,...,y_n\n", - " ## Output:\n", - " # - A polynomial in the ring Q.\n", - " # (After reducing the variables t_{0},y_{0} by the corresponding relations, \n", - " # the algorithm removes the variables y_{1},..,y_{n}). \n", - " \n", - " apl = p.parent()\n", - " n = len(apl.gens())//2\n", - " pol = self.reduce_polynomial(p)\n", - " relations = []\n", - " for i in range(n): \n", - " relations.append(apl.gens()[n+i]-1)\n", - " return pol.reduce(relations)\n", - " \n", - " def integral(self,p):\n", - " ## Input:\n", - " # - p: polynomial in variables t_0,..t_n,y_0,...,y_n\n", - " ## Output:\n", - " # - the integral of the polynomial after reducing the variables t_0, y_0 by the corresponding relations \n", - " #\n", - " apl = p.parent()\n", - " n = len(apl.gens())//2-1\n", - " pol = self._convert_integrable_polynomial(p)\n", - " result = 0\n", - " for k in pol.dict().keys(): # k is a monomial\n", - " numerator = 1\n", - " denominator = n\n", - " for e in k: # e is an exponents\n", - " numerator *= factorial(e)\n", - " denominator += e\n", - " coef = pol.dict()[k]\n", - " result += coef*numerator/factorial(denominator)\n", - " return ((-1)**(n*(n-1)/2))*result\n", - " \n", - " def lift(self, value, n): \n", - " apl = self.algebras[n]\n", - " gens = apl.gens()\n", - " return value*((-1)**(n*(n-1)/2))*factorial(n)*prod(gens[n+2:])\n", - " \n", - " def homogeneous_part(self,pol,degree):\n", - " parts = [pol.homogeneous_parts()[k] for k in pol.homogeneous_parts() if list(k)[0]==degree]\n", - " return sum(parts)\n", - " \n", - " def propagate(self, face_list, n):\n", - " \"\"\"\n", - " - face_list: indexes of the elements that form the face of the simplex we want to propagate\n", - " - EXAMPLE: p = a.propagate([0,3,4],5)\n", - " t4*y0*y3 - t3*y0*y4 + t0*y3*y4\n", - " \"\"\"\n", - " simplex_dim = len(face_list)-1\n", - " indexes = list(range(simplex_dim+1))\n", - " apl = self.algebras[n]\n", - " y_gens = [apl.gens()[n+1+i] for i in face_list]\n", - " t_gens = [apl.gens()[i] for i in face_list]\n", - " result = apl(0)\n", - " for i in reversed(indexes):\n", - " t = t_gens[i]\n", - " y_prod = copy.deepcopy(y_gens)\n", - " del y_prod[i]\n", - " y_prod = prod(y_prod)\n", - " result += ((-1)**i)*t*y_prod#((-1)**(simplex_dim+i))*t*y_prod\n", - " return result" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Apl(K)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "class AplK(UniqueRepresentation, Parent):\n", - " \n", - " def __init__(self,K, category=None):\n", - " self.K = K\n", - " self.n = K.dimension()\n", - " self.apln = Apln(K.dimension())\n", - " Parent.__init__(self,category=category )\n", - " f = MorphismFromQQToAplK(self)\n", - " self.register_coercion(f)\n", - " \n", - " def _repr_(self):\n", - " return \"Algebra AplK over %s\" % self.K\n", - " \n", - " def _element_constructor_(self,values):\n", - " return self.element_class(self,values)\n", - " \n", - " def dimension(self):\n", - " return self.K.dimension()\n", - " \n", - " def simplicialComplex(self):\n", - " return self.K\n", - " \n", - " def _n_cells_sorted(self,n):\n", - " return self.K._n_cells_sorted(n)\n", - " \n", - " def lift(self, cochain):\n", - " \n", - " # first we find polynomials compatible with the integration value\n", - " values = {}\n", - " max_n = 0\n", - " for k in cochain.keys():\n", - " n = len(k)-1\n", - " if n > max_n:\n", - " max_n = n\n", - " apl = self.apln.algebras[n]\n", - " if n>0:\n", - " values[k] = self.apln.lift(cochain[k],n)\n", - " else:\n", - " values[k]= apl(cochain[k])\n", - " \n", - " # second, we propagate the simplicial information\n", - " simplicial_structure = {}\n", - " for n in reversed(range(max_n+1)):\n", - " keys = [k for k in values.keys() if len(k) == n+1] # keys of the n-simplices\n", - " for k in keys:\n", - " simplicial_structure[k] = values[k] + self._propagate(cochain, k) \n", - " #print(simplicial_structure)\n", - " return AplKElement(self,simplicial_structure)\n", - "\n", - " def _faces_of_length(self, simplex, length):\n", - " return [tuple(e) for e in powerset(simplex) if len(e)==length]\n", - " \n", - " def _propagate(self, cochain, simplex):\n", - " \n", - " dim = len(simplex)-1\n", - " apl = self.apln.algebras[dim]\n", - " propagation = apl(0)\n", - " for n in reversed(range(dim+1)):\n", - " faces = self._faces_of_length(simplex, n)\n", - " for f in faces:\n", - " if f in cochain.keys():\n", - " dim_face = len(f)-1\n", - " value = cochain[f]\n", - " face_indexes = [simplex.index(i) for i in f]\n", - " propagation += value*((-1)**(dim_face*(dim_face-1)/2))*factorial(dim_face)*self.apln.propagate(face_indexes, dim)\n", - " return propagation\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Apl(K) Element" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "class AplKElement(Element):\n", - "\n", - " def __init__(self, parent, values):\n", - " Element.__init__(self,parent)\n", - " self.apln = Apln(parent.dimension())\n", - " self.elements = self.reduce(values) \n", - " self.check()\n", - " \n", - " def reduce(self, values):\n", - " reduced_values = {}\n", - " for k in values.keys():\n", - " n = len(k)-1\n", - " apl = self.apln.algebras[n]\n", - " reduced_values[k] = self.apln.reduce_polynomial(apl(values[k]))\n", - " return reduced_values\n", - " \n", - " def _repr_(self):\n", - " return str(self.elements)\n", - " \n", - " def dimension(self):\n", - " return self.parent().dimension()\n", - " \n", - " def nullElement(self):\n", - " C = self.__class__\n", - " values = {}\n", - " for k in self.elements.keys():\n", - " values[k]=0\n", - " return C(self.parent(),values) \n", - " \n", - " def _add_(self,other):\n", - " C = self.__class__\n", - " if(self.elements.keys()!=other.elements.keys()):\n", - " raise ValueError(\"error: keys do not match\")\n", - " newValues = {}\n", - " for k in self.elements.keys():\n", - " newValues[k] = self.elements[k]+other.elements[k]\n", - " return C(self.parent(),newValues)\n", - " \n", - " def _sub_(self,other):\n", - "\n", - " C = self.__class__\n", - " if(self.elements.keys()!=other.elements.keys()):\n", - " raise ValueError(\"error: keys do not match\")\n", - " newValues = {}\n", - " for k in self.elements.keys():\n", - " newValues[k] = self.elements[k]-other.elements[k]\n", - " return C(self.parent(),newValues)\n", - " \n", - " def _mul_(self,other):\n", - "\n", - " C = self.__class__\n", - " if(self.elements.keys()!=other.elements.keys()):\n", - " raise ValueError(\"error: keys do not match\")\n", - " newValues = {}\n", - " for k in self.elements.keys():\n", - " newValues[k] = self.elements[k]*other.elements[k]\n", - " return C(self.parent(),newValues)\n", - " \n", - " def _richcmp_(self, other, op):\n", - "\n", - " if(op==op_EQ):\n", - " if(self.elements.keys()!=other.elements.keys()):\n", - " return False\n", - " for k in self.elements.keys():\n", - " if(self.elements[k]!=other.elements[k]):\n", - " return False\n", - " return True\n", - " elif(op==op_NE):\n", - " return not self._richcmp_(other,op_EQ)\n", - " else:\n", - " raise NotImplementedError(\"operation not implemented for this element class\")\n", - " \n", - " def differential(self):\n", - " C = self.__class__\n", - " newValues = {}\n", - " for k in self.elements.keys():\n", - " newValues[k] = self.elements[k].differential()\n", - " return C(self.parent(),newValues)\n", - " \n", - " def check(self):\n", - "\n", - " S = self.parent().simplicialComplex()\n", - " dim = S.dimension()\n", - " for n in range(1,dim+1):\n", - " #print(\"Checking dimension \" + str(n))\n", - " for simplex in S._n_cells_sorted(n):\n", - " for f in range(n+1):\n", - " sFace = tuple(S.face(simplex,f))\n", - " aFace = self.apln.face(f,n)(self.elements[simplex.tuple()])\n", - " aFace = self.apln.reduce_polynomial(aFace)\n", - " #print(\"face: \" + str(f),\"simplex: \" + str(simplex),\"sFace: \" + str(self.elements[sFace]), \"aFace: \" + str(aFace))\n", - " if(self.elements[sFace] != aFace):\n", - " raise ValueError(\"the assignation is not valid\")\n", - " \n", - " def homogeneous_part(self,degree):\n", - " C = self.__class__\n", - " part = {}\n", - " for k in self.elements.keys():\n", - " part[k] = self.apln.homogeneous_part(self.elements[k],degree)\n", - " return C(self.parent(),part)\n", - " \n", - " def homogeneous_parts(self):\n", - " parts = {}\n", - " for n in range(self.dimension()+1):\n", - " parts[n] = self.homogeneous_part(n)\n", - " return parts\n", - " \n", - " def is_homogeneous(self):\n", - " isHomogeneous = True\n", - " for k in self.elements.keys():\n", - " isHomogeneous = isHomogeneous and self.elements[k].is_homogeneous()\n", - " return isHomogeneous\n", - " \n", - " def is_closed(self):\n", - " diff = self.differential()\n", - " if(diff == self.nullElement()):\n", - " return True\n", - " else:\n", - " return False\n", - " \n", - " def _integrable_component(self):\n", - " C = self.__class__\n", - " component = {}\n", - " for k in self.elements.keys():\n", - " degree = len(k)-1\n", - " component[k] = self.apln.homogeneous_part(self.elements[k],degree)\n", - " #component[k] = self.homogeneous_component(dim).elements[k]\n", - " return component\n", - " \n", - " def integral(self):\n", - " component = self._integrable_component()\n", - " cochain = {}\n", - " #integration of each polynomial\n", - " for k in component.keys():\n", - " n = len(k)-1\n", - " apl = self.apln.algebras[n]\n", - " cochain[k] = self.apln.integral(apl(component[k]))\n", - " return cochain\n", - " \n", - "#####################################################################\n", - "\n", - "class MorphismFromQQToAplK(Morphism):\n", - "\n", - " def __init__(self, codomain):\n", - " self.simplicialComplex= codomain.K\n", - " Morphism.__init__(self, QQ, codomain)\n", - "\n", - " def _call_(self, x):\n", - " S = self.simplicialComplex\n", - " params1 = {}\n", - " for d in range(S.dimension()+1):\n", - " for c in S._n_cells_sorted(d):\n", - " params1[tuple(c)]=x\n", - " A = AplK(S)\n", - " return AplKElement(A, params1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Test lift == integral" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "def test(max_vertices, verbose=False):\n", - " success = True\n", - " data = []\n", - " for i in range(10):\n", - " v = randint(2,max_vertices)\n", - " f = randint(1,v)\n", - " S = random_simplicial_complex(num_vertices=v,max_num_facets=f)\n", - " A = AplK(S)\n", - " cochain = random_cochain(S)\n", - " #print(cochain)\n", - " data = [S, cochain]\n", - " if verbose:\n", - " print(\"iteration: \" + str(i), \"num_vertices: \" + str(v), \"max_num_facets: \" + str(f), \"facets: \" + str(S.facets()))\n", - " p = A.lift(cochain)\n", - " if verbose:\n", - " print(p)\n", - " if not p.integral()==cochain:\n", - " success = False\n", - " print(\"Error\")\n", - " break\n", - " if success:\n", - " print(\"success: \" + str(success))" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "iteration: 0 num_vertices: 6 max_num_facets: 4 facets: {(1, 2, 5), (0, 3, 4, 5), (0, 1, 3), (1, 3, 4)}\n", - "{(0, 3, 4, 5): 288*y1*y2*y3 + 84*t3*y1*y2 - 84*t2*y1*y3 + 84*t1*y2*y3 - 174*y1*y2 - 112*y1*y3 + 124*y2*y3 + 43*t2*y1 + 225*t3*y1 - 43*t1*y2 + 3*t3*y2 - 225*t1*y3 - 3*t2*y3 - 63*y1 + 37*y2 + 81*y3 - 86*t1 - 69*t2 - 114*t3 + 97, (0, 1, 3): 200*y1*y2 + 13*t2*y1 - 13*t1*y2 + 18*y1 - 63*y2 - 178*t1 - 86*t2 + 97, (0, 3, 4): -174*y1*y2 + 43*t2*y1 - 43*t1*y2 - 63*y1 + 37*y2 - 86*t1 - 69*t2 + 97, (0, 3, 5): -112*y1*y2 + 225*t2*y1 - 225*t1*y2 - 63*y1 + 81*y2 - 86*t1 - 114*t2 + 97, (0, 4, 5): 124*y1*y2 + 3*t2*y1 - 3*t1*y2 + 37*y1 + 81*y2 - 69*t1 - 114*t2 + 97, (1, 2, 5): 160*y1*y2 + 83*t2*y1 - 83*t1*y2 + 20*y1 + 57*y2 + 64*t1 + 64*t2 - 81, (1, 3, 4): 14*y1*y2 + 9*t2*y1 - 9*t1*y2 - 94*y1 - 28*y2 + 92*t1 + 109*t2 - 81, (3, 4, 5): 146*y1*y2 - 179*t2*y1 + 179*t1*y2 + 57*y1 - 81*y2 + 17*t1 - 28*t2 + 11, (0, 1): 18*y1 - 178*t1 + 97, (0, 3): -63*y1 - 86*t1 + 97, (0, 4): 37*y1 - 69*t1 + 97, (0, 5): 81*y1 - 114*t1 + 97, (1, 2): 20*y1 + 64*t1 - 81, (1, 3): -94*y1 + 92*t1 - 81, (1, 4): -28*y1 + 109*t1 - 81, (1, 5): 57*y1 + 64*t1 - 81, (2, 5): -46*y1 - 17, (3, 4): 57*y1 + 17*t1 + 11, (3, 5): -81*y1 - 28*t1 + 11, (4, 5): 41*y1 - 45*t1 + 28, (0,): 97, (1,): -81, (2,): -17, (3,): 11, (4,): 28, (5,): -17}\n", - "iteration: 1 num_vertices: 5 max_num_facets: 2 facets: {(0, 2, 3, 4), (1, 3, 4)}\n", - "{(0, 2, 3, 4): 6*y1*y2*y3 + 506*t3*y1*y2 - 506*t2*y1*y3 + 506*t1*y2*y3 - 196*y1*y2 + 6*y1*y3 - 106*y2*y3 - 56*t2*y1 - 75*t3*y1 + 56*t1*y2 - 23*t3*y2 + 75*t1*y3 + 23*t2*y3 - 38*y1 - 86*y2 - 16*y3 - 50*t1 - 54*t2 - 3*t3 + 65, (0, 2, 3): -196*y1*y2 - 56*t2*y1 + 56*t1*y2 - 38*y1 - 86*y2 - 50*t1 - 54*t2 + 65, (0, 2, 4): 6*y1*y2 - 75*t2*y1 + 75*t1*y2 - 38*y1 - 16*y2 - 50*t1 - 3*t2 + 65, (0, 3, 4): -106*y1*y2 - 23*t2*y1 + 23*t1*y2 - 86*y1 - 16*y2 - 54*t1 - 3*t2 + 65, (1, 3, 4): -2*y1*y2 + 4*t2*y1 - 4*t1*y2 - 37*y1 + 60*y2 - 13*t1 + 38*t2 + 24, (2, 3, 4): 198*y1*y2 - 4*t2*y1 + 4*t1*y2 + 8*y1 + 97*y2 - 4*t1 + 47*t2 + 15, (0, 2): -38*y1 - 50*t1 + 65, (0, 3): -86*y1 - 54*t1 + 65, (0, 4): -16*y1 - 3*t1 + 65, (1, 3): -37*y1 - 13*t1 + 24, (1, 4): 60*y1 + 38*t1 + 24, (2, 3): 8*y1 - 4*t1 + 15, (2, 4): 97*y1 + 47*t1 + 15, (3, 4): 93*y1 + 51*t1 + 11, (0,): 65, (1,): 24, (2,): 15, (3,): 11, (4,): 62}\n", - "iteration: 2 num_vertices: 3 max_num_facets: 2 facets: {(0, 2), (1,)}\n", - "{(0, 2): 89*y1 + 2*t1 - 26, (0,): -26, (1,): -60, (2,): -24}\n", - "iteration: 3 num_vertices: 6 max_num_facets: 4 facets: {(1, 3), (2, 3), (0, 3, 5), (0, 1, 2, 4, 5)}\n", - "{(0, 1, 2, 4, 5): -1704*y1*y2*y3*y4 - 534*t4*y1*y2*y3 + 534*t3*y1*y2*y4 - 534*t2*y1*y3*y4 + 534*t1*y2*y3*y4 - 558*y1*y2*y3 - 444*y1*y2*y4 + 192*y1*y3*y4 - 132*y2*y3*y4 - 90*t3*y1*y2 + 238*t4*y1*y2 + 90*t2*y1*y3 + 236*t4*y1*y3 - 90*t1*y2*y3 + 198*t4*y2*y3 - 238*t2*y1*y4 - 236*t3*y1*y4 + 238*t1*y2*y4 - 198*t3*y2*y4 + 236*t1*y3*y4 + 198*t2*y3*y4 - 112*y1*y2 - 36*y1*y3 + 8*y2*y3 + 146*y1*y4 + 94*y2*y4 - 24*y3*y4 - 55*t2*y1 - 41*t3*y1 + 23*t4*y1 + 55*t1*y2 - 121*t3*y2 - 60*t4*y2 + 41*t1*y3 + 121*t2*y3 - 23*t4*y3 - 23*t1*y4 + 60*t2*y4 + 23*t3*y4 + 38*y1 + 73*y2 + 31*y3 + 85*y4 - 88*t1 - 115*t2 - 74*t3 - 63*t4 + 85, (0, 1, 2, 4): -558*y1*y2*y3 - 90*t3*y1*y2 + 90*t2*y1*y3 - 90*t1*y2*y3 - 112*y1*y2 - 36*y1*y3 + 8*y2*y3 - 55*t2*y1 - 41*t3*y1 + 55*t1*y2 - 121*t3*y2 + 41*t1*y3 + 121*t2*y3 + 38*y1 + 73*y2 + 31*y3 - 88*t1 - 115*t2 - 74*t3 + 85, (0, 1, 2, 5): -444*y1*y2*y3 + 238*t3*y1*y2 - 238*t2*y1*y3 + 238*t1*y2*y3 - 112*y1*y2 + 146*y1*y3 + 94*y2*y3 - 55*t2*y1 + 23*t3*y1 + 55*t1*y2 - 60*t3*y2 - 23*t1*y3 + 60*t2*y3 + 38*y1 + 73*y2 + 85*y3 - 88*t1 - 115*t2 - 63*t3 + 85, (0, 1, 4, 5): 192*y1*y2*y3 + 236*t3*y1*y2 - 236*t2*y1*y3 + 236*t1*y2*y3 - 36*y1*y2 + 146*y1*y3 - 24*y2*y3 - 41*t2*y1 + 23*t3*y1 + 41*t1*y2 - 23*t3*y2 - 23*t1*y3 + 23*t2*y3 + 38*y1 + 31*y2 + 85*y3 - 88*t1 - 74*t2 - 63*t3 + 85, (0, 2, 4, 5): -132*y1*y2*y3 + 198*t3*y1*y2 - 198*t2*y1*y3 + 198*t1*y2*y3 + 8*y1*y2 + 94*y1*y3 - 24*y2*y3 - 121*t2*y1 - 60*t3*y1 + 121*t1*y2 - 23*t3*y2 + 60*t1*y3 + 23*t2*y3 + 73*y1 + 31*y2 + 85*y3 - 115*t1 - 74*t2 - 63*t3 + 85, (1, 2, 4, 5): 324*y1*y2*y3 + 290*t3*y1*y2 - 290*t2*y1*y3 + 290*t1*y2*y3 - 158*y1*y2 + 74*y1*y3 + 30*y2*y3 - 135*t2*y1 - 138*t3*y1 + 135*t1*y2 - 87*t3*y2 + 138*t1*y3 + 87*t2*y3 + 90*y1 + 34*y2 + 24*y3 - 27*t1 + 14*t2 + 25*t3 - 3, (0, 1, 2): -112*y1*y2 - 55*t2*y1 + 55*t1*y2 + 38*y1 + 73*y2 - 88*t1 - 115*t2 + 85, (0, 1, 4): -36*y1*y2 - 41*t2*y1 + 41*t1*y2 + 38*y1 + 31*y2 - 88*t1 - 74*t2 + 85, (0, 1, 5): 146*y1*y2 + 23*t2*y1 - 23*t1*y2 + 38*y1 + 85*y2 - 88*t1 - 63*t2 + 85, (0, 2, 4): 8*y1*y2 - 121*t2*y1 + 121*t1*y2 + 73*y1 + 31*y2 - 115*t1 - 74*t2 + 85, (0, 2, 5): 94*y1*y2 - 60*t2*y1 + 60*t1*y2 + 73*y1 + 85*y2 - 115*t1 - 63*t2 + 85, (0, 3, 5): -146*y1*y2 + 167*t2*y1 - 167*t1*y2 - 46*y1 + 85*y2 - 13*t1 - 63*t2 + 85, (0, 4, 5): -24*y1*y2 - 23*t2*y1 + 23*t1*y2 + 31*y1 + 85*y2 - 74*t1 - 63*t2 + 85, (1, 2, 4): -158*y1*y2 - 135*t2*y1 + 135*t1*y2 + 90*y1 + 34*y2 - 27*t1 + 14*t2 - 3, (1, 2, 5): 74*y1*y2 - 138*t2*y1 + 138*t1*y2 + 90*y1 + 24*y2 - 27*t1 + 25*t2 - 3, (1, 4, 5): 30*y1*y2 - 87*t2*y1 + 87*t1*y2 + 34*y1 + 24*y2 + 14*t1 + 25*t2 - 3, (2, 4, 5): 88*y1*y2 - 84*t2*y1 + 84*t1*y2 + 79*y1 + 72*y2 + 41*t1 + 52*t2 - 30, (0, 1): 38*y1 - 88*t1 + 85, (0, 2): 73*y1 - 115*t1 + 85, (0, 3): -46*y1 - 13*t1 + 85, (0, 4): 31*y1 - 74*t1 + 85, (0, 5): 85*y1 - 63*t1 + 85, (1, 2): 90*y1 - 27*t1 - 3, (1, 3): -88*y1 + 75*t1 - 3, (1, 4): 34*y1 + 14*t1 - 3, (1, 5): 24*y1 + 25*t1 - 3, (2, 3): -68*y1 + 102*t1 - 30, (2, 4): 79*y1 + 41*t1 - 30, (2, 5): 72*y1 + 52*t1 - 30, (3, 5): -36*y1 - 50*t1 + 72, (4, 5): 77*y1 + 11*t1 + 11, (0,): 85, (1,): -3, (2,): -30, (3,): 72, (4,): 11, (5,): 22}\n", - "iteration: 4 num_vertices: 4 max_num_facets: 3 facets: {(0, 1, 2), (0, 3)}\n", - "{(0, 1, 2): -128*y1*y2 + 102*t2*y1 - 102*t1*y2 - 83*y1 - 17*y2 - 3*t1 + 23*t2 + 1, (0, 1): -83*y1 - 3*t1 + 1, (0, 2): -17*y1 + 23*t1 + 1, (0, 3): -98*y1 - 21*t1 + 1, (1, 2): -36*y1 + 26*t1 - 2, (0,): 1, (1,): -2, (2,): 24, (3,): -20}\n", - "iteration: 5 num_vertices: 3 max_num_facets: 2 facets: {(0, 2), (1,)}\n", - "{(0, 2): 91*y1 - 45*t1 - 46, (0,): -46, (1,): -75, (2,): -91}\n", - "iteration: 6 num_vertices: 4 max_num_facets: 1 facets: {(0, 1, 2)}\n", - "{(0, 1, 2): 106*y1*y2 + 100*t2*y1 - 100*t1*y2 - 83*y1 + 50*y2 - 60*t1 + 7*t2 - 20, (0, 1): -83*y1 - 60*t1 - 20, (0, 2): 50*y1 + 7*t1 - 20, (1, 2): 33*y1 + 67*t1 - 80, (0,): -20, (1,): -80, (2,): -13}\n", - "iteration: 7 num_vertices: 5 max_num_facets: 1 facets: {(0, 1, 4), (1, 3)}\n", - "{(0, 1, 4): -36*y1*y2 + 72*t2*y1 - 72*t1*y2 - 88*y1 + 25*y2 - 12*t1 + 77*t2 - 1, (0, 1): -88*y1 - 12*t1 - 1, (0, 4): 25*y1 + 77*t1 - 1, (1, 3): 52*y1 + 43*t1 - 13, (1, 4): 41*y1 + 89*t1 - 13, (0,): -1, (1,): -13, (3,): 30, (4,): 76}\n", - "iteration: 8 num_vertices: 5 max_num_facets: 2 facets: {(0, 3, 4), (0, 2, 4), (1, 2)}\n", - "{(0, 2, 4): 198*y1*y2 - 84*t2*y1 + 84*t1*y2 - 68*y1 - 75*y2 - 129*t1 - 5*t2 + 46, (0, 3, 4): 152*y1*y2 + 57*t2*y1 - 57*t1*y2 - 100*y1 - 75*y2 - 40*t1 - 5*t2 + 46, (0, 2): -68*y1 - 129*t1 + 46, (0, 3): -100*y1 - 40*t1 + 46, (0, 4): -75*y1 - 5*t1 + 46, (1, 2): -86*y1 - 66*t1 - 17, (2, 4): 77*y1 + 124*t1 - 83, (3, 4): -32*y1 + 35*t1 + 6, (0,): 46, (1,): -17, (2,): -83, (3,): 6, (4,): 41}\n", - "iteration: 9 num_vertices: 2 max_num_facets: 2 facets: {(1,), (0,)}\n", - "{(0,): -75, (1,): -70}\n", - "success: True\n" - ] - } - ], - "source": [ - "test(max_vertices=6, verbose=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Minimal model (sin terminar)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "class MinimalModel():\n", - "\n", - " def __init__(self, S):\n", - " self.K = S\n", - " self.Phi = {}\n", - " gens = self.first_non_trivial_cohomology_group()\n", - " [self.cdga, self.cohomology_dict] = self.createModel(gens)\n", - " \n", - " def first_non_trivial_cohomology_group(self, max_iter=20):\n", - " # busco el primer grupo de cohomología no trivial\n", - " i=1\n", - " gens = self.cohomology_gens(i)\n", - " while(len(gens)==0 and ii):\n", - " tImages.append(codomain.gens()[k-1])\n", - " yImages.append(codomain.gens()[n+k-2])\n", - " images = tImages+yImages\n", - " return domain.hom(codomain=codomain,im_gens=images)\n", - "\n", - " def reduce_polynomial(self,p):\n", - " ## Input:\n", - " # - p: polynomial in variables t_0,..t_n,y_0,...,y_n\n", - " ## Output:\n", - " # - The polynomial after applying the corresponding relations to reduce the variables t_0, y_0\n", - " apl = p.parent()\n", - " dim = len(apl.gens())//2-1\n", - " return p.reduce(self.relations[dim])\n", - " \n", - " def _convert_integrable_polynomial(self,p):\n", - " ## Input:\n", - " # - p: polynomial in variables t_1,..t_n,y_1,...,y_n\n", - " ## Output:\n", - " # - A polynomial in the ring Q.\n", - " # (After reducing the variables t_{0},y_{0} by the corresponding relations, \n", - " # the algorithm removes the variables y_{1},..,y_{n}). \n", - " \n", - " apl = p.parent()\n", - " n = len(apl.gens())//2\n", - " pol = self.reduce_polynomial(p)\n", - " relations = []\n", - " for i in range(n): \n", - " relations.append(apl.gens()[n+i]-1)\n", - " return pol.reduce(relations)\n", - " \n", - " def integral(self,p):\n", - " ## Input:\n", - " # - p: polynomial in variables t_0,..t_n,y_0,...,y_n\n", - " ## Output:\n", - " # - the integral of the polynomial after reducing the variables t_0, y_0 by the corresponding relations \n", - " #\n", - " apl = p.parent()\n", - " n = len(apl.gens())//2-1\n", - " pol = self._convert_integrable_polynomial(p)\n", - " result = 0\n", - " for k in pol.dict().keys(): # k is a monomial\n", - " numerator = 1\n", - " denominator = n\n", - " for e in k: # e is an exponents\n", - " numerator *= factorial(e)\n", - " denominator += e\n", - " coef = pol.dict()[k]\n", - " result += coef*numerator/factorial(denominator)\n", - " return ((-1)**(n*(n-1)/2))*result\n", - " \n", - " def lift(self, value, n): \n", - " apl = self.algebras[n]\n", - " gens = apl.gens()\n", - " return value*((-1)**(n*(n-1)/2))*factorial(n)*prod(gens[n+2:])\n", - " \n", - " def homogeneous_part(self,pol,degree):\n", - " parts = [pol.homogeneous_parts()[k] for k in pol.homogeneous_parts() if list(k)[0]==degree]\n", - " return sum(parts)\n", - " \n", - " def propagate(self, face_list, n):\n", - " \"\"\"\n", - " - face_list: indexes of the elements that form the face of the simplex we want to propagate\n", - " - EXAMPLE: p = a.propagate([0,3,4],5)\n", - " t4*y0*y3 - t3*y0*y4 + t0*y3*y4\n", - " \"\"\"\n", - " simplex_dim = len(face_list)-1\n", - " indexes = list(range(simplex_dim+1))\n", - " apl = self.algebras[n]\n", - " y_gens = [apl.gens()[n+1+i] for i in face_list]\n", - " t_gens = [apl.gens()[i] for i in face_list]\n", - " result = apl(0)\n", - " for i in reversed(indexes):\n", - " t = t_gens[i]\n", - " y_prod = copy.deepcopy(y_gens)\n", - " del y_prod[i]\n", - " y_prod = prod(y_prod)\n", - " result += ((-1)**i)*t*y_prod#((-1)**(simplex_dim+i))*t*y_prod\n", - " return result" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# Funciones añadidas" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - " def get_multidegree(self, p):\n", - " a3 = p.parent()\n", - " n = len(a3.gens())/2\n", - " multidegrees = {}\n", - " for k in p.dict().keys():\n", - " multideg = vector(QQ,n*[0])\n", - " for i in range(n):\n", - " multideg[i] = k[i]+k[i+n]\n", - " multidegrees[k] = multideg\n", - " return multidegrees\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Defining t0, t1, t2, t3, y0, y1, y2, y3\n" - ] - }, - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a = Apln(5)\n", - "a.inject_variables(3)\n", - "p = t2*y0*y1-t1*y0*y2+t0*y1*y2\n", - "q = a.face(1,3)(p)\n", - "ared = a.reduce_polynomial(q)\n", - "ared" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Empiezan celdas de pruebas" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{(0, 0, 2, 0, 1, 1, 0, 0): 5,\n", - " (0, 1, 0, 0, 1, 0, 1, 0): -1,\n", - " (1, 0, 0, 0, 0, 1, 1, 0): 1}" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "p = 5*t2^2*y0*y1-t1*y0*y2+t0*y1*y2\n", - "p.dict()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Defining t0, t1, t2, t3, y0, y1, y2, y3\n" - ] - }, - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "apl = Apln(5)\n", - "apl.inject_variables(3)\n", - "d=1\n", - "c=d\n", - "b=2*d-1/2\n", - "a=2*d-1/2\n", - "w1=a*(t0*t1^2*t2*t3*y0)+b*(t0^2*t1*t2*t3*y1)+c*(t0^2*t1^2*t3*y2)+d*(t0^2*t1^2*t2*y3)\n", - "d=5\n", - "c=d\n", - "b=2*d-1/2\n", - "a=2*d-1/2\n", - "w2=a*(t0*t1^2*t2*t3*y0)+b*(t0^2*t1*t2*t3*y1)+c*(t0^2*t1^2*t3*y2)+d*(t0^2*t1^2*t2*y3)\n", - "w1.differential()==w2.differential()" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[t2^2*y0*y1, t1*y0*y2, t0*y1*y2]" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "m0 = p.monomials()\n", - "m0" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "5*t2^2*y0*y1 + 5*y0*y1" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "p = (5*t2^2 + 5)*y0*y1\n", - "p" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{(0, 0, 2, 0, 1, 1, 0, 0): 5,\n", - " (0, 1, 0, 0, 1, 0, 1, 0): -1,\n", - " (1, 0, 0, 0, 0, 1, 1, 0): 1}" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "p = 5*t2^2*y0*y1-t1*y0*y2+t0*y1*y2\n", - "p.dict()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "def get_term(coef, exp, gens):\n", - " return coef*prod(list(map(lambda exp, gen: gen^exp, exp, gens)))\n", - "\n", - "def get_terms(p):\n", - " a = p.parent()\n", - " n = len(a.gens())/2\n", - " ts_only_gens = a.gens()[:n]+tuple(n*[1])\n", - " ys_only_gens = tuple(n*[1])+a.gens()[n:]\n", - " terms = {}\n", - " pol = p.dict()\n", - " for exp in pol.keys():\n", - " key = get_term(1, exp,ys_only_gens)\n", - " if key not in terms.keys():\n", - " coef = get_term(pol[exp],exp,ts_only_gens)\n", - " terms[key] = coef\n", - " else:\n", - " coef = get_term(pol[exp],exp,ts_only_gens)\n", - " terms[key] += coef \n", - " return terms\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5*t2^2*y0*y1 - t1*y0*y2 + t0*y1*y2 + 3*y0*y1\n" - ] - }, - { - "data": { - "text/plain": [ - "{y0*y1: 5*t2^2 + 3, y0*y2: -t1, y1*y2: t0}" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "p = 5*t2^2*y0*y1-t1*y0*y2+t0*y1*y2+3*y0*y1\n", - "print(p)\n", - "terms = get_terms(p)\n", - "terms" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# comprobamos que la suma de los términos nos da el polinomio original\n", - "p2 = sum([terms[key]*key for key in terms.keys()])\n", - "p2==p" - ] - }, - { - "cell_type": "code", - "execution_count": 81, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 81, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "\n", - "\n", - " \n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 80, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{y1: 5*t0*t2^2 + 3*t0}" - ] - }, - "execution_count": 80, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "lead_term = get_leading_term(p)\n", - "symbolic_partial_integral(lead_term, 0)" - ] - }, - { - "cell_type": "code", - "execution_count": 114, - "metadata": {}, - "outputs": [], - "source": [ - "def get_leading_pol(pol):\n", - " terms = get_terms(pol)\n", - " keys = list(terms.keys())\n", - " keys.sort(reverse=True)\n", - " return terms[keys[0]]*keys[0]\n", - "\n", - "def get_integration_idx(exp):\n", - " # gets the idx 'i' of the first generator 'y_i' that appears in exp\n", - " n = len(exp)/2\n", - " filter_ts = n*[0]+n*[1]\n", - " diff_forms = list(map(lambda v, f: v*f, exp, filter_ts))\n", - " return next((i for i, x in enumerate(list(diff_forms)) if x), None)-n\n", - "\n", - "def symbolic_partial_monomial_integral(monomial, idx):\n", - " exp = list(monomial.dict().keys())[0]\n", - " coef = monomial.dict()[exp]\n", - " n = len(exp)/2\n", - " if (exp[n+idx]==0):\n", - " raise IndexError(\"El término no se puede integrar respecto a esa variable\")\n", - " integral = list(copy.deepcopy(exp))\n", - " integral[n+idx] = 0\n", - " integral[idx] += 1\n", - " new_coef = coef/integral[idx]\n", - " a = monomial.parent()\n", - " return get_term(new_coef, integral, a.gens())\n", - " \n", - "def symbolic_partial_integral(polynomial):\n", - " # necessary condition: all monomials have apl.gens[n+integration_idx] factor\n", - " exp = list(polynomial.dict().keys())[0]\n", - " integration_idx = get_integration_idx(exp)\n", - " aGens = polynomial.parent().gens()\n", - " integral = 0\n", - " for exp in polynomial.dict().keys():\n", - " coef = polynomial.dict()[exp]\n", - " monomial = get_term(coef, exp, aGens)\n", - " integral += symbolic_partial_monomial_integral(monomial, integration_idx)\n", - " terms = get_terms(integral)\n", - " result = sum([terms[key]*key for key in terms.keys()])\n", - " return result" - ] - }, - { - "cell_type": "code", - "execution_count": 115, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "5*t0*t2^2*y1 + 3*t0*y1" - ] - }, - "execution_count": 115, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "symbolic_partial_integral(terms[y0*y1]*y0*y1)" - ] - }, - { - "cell_type": "code", - "execution_count": 143, - "metadata": {}, - "outputs": [], - "source": [ - "def find_preimage_diff(pol):\n", - " if pol.differential()!=0 :\n", - " raise ValueError(\"This polynomial is not in the kernel of the differential\")\n", - " lead_pol = get_leading_pol(pol)\n", - " w = symbolic_partial_integral(lead_pol)\n", - " theta = pol - w.differential()\n", - " if (theta == 0):\n", - " return w\n", - " else:\n", - " return w+find_preimage_diff(theta)" - ] - }, - { - "cell_type": "code", - "execution_count": 144, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "t0*t1" - ] - }, - "execution_count": 144, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Ejemplo 1\n", - "q = t0*y1+t1*y0\n", - "find_preimage_diff(q)" - ] - }, - { - "cell_type": "code", - "execution_count": 149, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 149, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#Ejemplo 2\n", - "q1 = (-1/2)*(t0*t1^2*t2*t3*y0)\n", - "q2 = (-1/2)*(t0^2*t1*t2*t3*y1)\n", - "q = q1+q2\n", - "dq = q.differential()\n", - "w = find_preimage_diff(dq)\n", - "w.differential() == dq" - ] - }, - { - "cell_type": "code", - "execution_count": 157, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "" - ], - "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\verb|-1/2*t0*t1^2*t2*t3*y0|\\phantom{\\verb!x!}\\verb|-|\\phantom{\\verb!x!}\\verb|1/2*t0^2*t1*t2*t3*y1|\n", - "\\end{math}" - ], - "text/plain": [ - "-1/2*t0*t1^2*t2*t3*y0 - 1/2*t0^2*t1*t2*t3*y1" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\verb|1/4*t0^2*t1^2*t3*y2|\\phantom{\\verb!x!}\\verb|+|\\phantom{\\verb!x!}\\verb|1/4*t0^2*t1^2*t2*y3|\n", - "\\end{math}" - ], - "text/plain": [ - "1/4*t0^2*t1^2*t3*y2 + 1/4*t0^2*t1^2*t2*y3" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "show(q)\n", - "show(w)" - ] - }, - { - "cell_type": "code", - "execution_count": 177, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Defining t0, t1, t2, t3, t4, t5, t6, y0, y1, y2, y3, y4, y5, y6\n", - "q = t2*y0*y1*y3 + t5*y1*y2*y3 + t3*y3*y4*y6\n", - "dq = y0*y1*y2*y3 - y1*y2*y3*y5\n", - "w = t0*y1*y2*y3 - t1*y2*y3*y5\n", - "dw = y0*y1*y2*y3 - y1*y2*y3*y5\n" - ] - }, - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 177, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Ejemplo 3\n", - "n=6\n", - "a = Apln(n)\n", - "a.inject_variables(n)\n", - "q = t5*y1*y2*y3+t2*y0*y1*y3+t3*y3*y4*y6\n", - "dq = q.differential()\n", - "w = find_preimage_diff(dq)\n", - "print(\"q = \", q)\n", - "print(\"dq = \",dq)\n", - "print(\"w = \",w)\n", - "print(\"dw = \", w.differential())\n", - "w.differential()==dq" - ] - }, - { - "cell_type": "code", - "execution_count": 178, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Defining t0, t1, t2, t3, t4, t5, t6, y0, y1, y2, y3, y4, y5, y6\n", - "q = t2*y0*y1 + t5*y1*y2 + t5*y3*y4 + 5*y1*y2\n", - "dq = y0*y1*y2 + y1*y2*y5 + y3*y4*y5\n", - "w = t0*y1*y2 + t1*y2*y5 + t3*y4*y5\n", - "dw = y0*y1*y2 + y1*y2*y5 + y3*y4*y5\n" - ] - }, - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 178, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Ejemplo 4\n", - "n=6\n", - "a = Apln(n)\n", - "a.inject_variables(n)\n", - "q = t5*y1*y2+t2*y0*y1+5*y1*y2+t5*y3*y4\n", - "dq = q.differential()\n", - "w = find_preimage_diff(dq)\n", - "print(\"q = \", q)\n", - "print(\"dq = \",dq)\n", - "print(\"w = \",w)\n", - "print(\"dw = \", w.differential())\n", - "w.differential()==dq" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Terminan celdas de pruebas" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "t4*y0*y1*y2*y3 - t3*y0*y1*y2*y4 + t2*y0*y1*y3*y4 - t1*y0*y2*y3*y4 + t0*y1*y2*y3*y4\n", - "y1*y2*y3*y4\n" - ] - } - ], - "source": [ - "p = a.propagate([0, 2, 3, 4, 5],5)\n", - "q = a.face(1,5)(p)\n", - "ared = a.reduce_polynomial(q)\n", - "print(q)\n", - "print(ared)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(y0, y1, y2)" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a.algebras[3].gens()[4:-1]" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Defining t0, t1, t2, t3, y0, y1, y2, y3\n" - ] - }, - { - "data": { - "text/plain": [ - "(y0, y1, y2)" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "n=3\n", - "a = Apln(n)\n", - "a.inject_variables(n)\n", - "cdga = a.algebras[n]\n", - "gens = cdga.gens()[n+1:-1]\n", - "gens\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "n = 5\n", - "n = 4\n", - "n = 3\n", - "n = 2\n", - "n = 1\n" - ] - } - ], - "source": [ - "N = 6\n", - "for n in reversed(range(1,N)):\n", - " print(\"n = \" + str(n))\n", - " for face in range(n+1):\n", - " idx = list(range(N))\n", - " del idx[face]\n", - " r = [perm for perm in itertools.permutations(idx,r=int(n)) if sorted(perm) == list(perm)]\n", - " #print(r)\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Apl(K)" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [], - "source": [ - "class AplK(UniqueRepresentation, Parent):\n", - " \n", - " def __init__(self,K, category=None):\n", - " self.K = K\n", - " self.n = K.dimension()\n", - " self.apln = Apln(K.dimension())\n", - " Parent.__init__(self,category=category )\n", - " f = MorphismFromQQToAplK(self)\n", - " self.register_coercion(f)\n", - " \n", - " def _repr_(self):\n", - " return \"Algebra AplK over %s\" % self.K\n", - " \n", - " def _element_constructor_(self,values):\n", - " return self.element_class(self,values)\n", - " \n", - " def dimension(self):\n", - " return self.K.dimension()\n", - " \n", - " def simplicialComplex(self):\n", - " return self.K\n", - " \n", - " def _n_cells_sorted(self,n):\n", - " return self.K._n_cells_sorted(n)\n", - " \n", - " def lift(self, cochain):\n", - " \n", - " # first we find polynomials compatible with the integration value\n", - " values = {}\n", - " max_n = 0\n", - " for k in cochain.keys():\n", - " n = len(k)-1\n", - " if n > max_n:\n", - " max_n = n\n", - " apl = self.apln.algebras[n]\n", - " if n>0:\n", - " values[k] = self.apln.lift(cochain[k],n)\n", - " else:\n", - " values[k]= apl(cochain[k])\n", - " \n", - " # second, we propagate the simplicial information\n", - " simplicial_structure = {}\n", - " for n in reversed(range(max_n+1)):\n", - " keys = [k for k in values.keys() if len(k) == n+1] # keys of the n-simplices\n", - " for k in keys:\n", - " simplicial_structure[k] = values[k] + self._propagate(cochain, k) \n", - " #print(simplicial_structure)\n", - " return AplKElement(self,simplicial_structure)\n", - "\n", - " def _faces_of_length(self, simplex, length):\n", - " return [tuple(e) for e in powerset(simplex) if len(e)==length]\n", - " \n", - " def _propagate(self, cochain, simplex):\n", - " \n", - " dim = len(simplex)-1\n", - " apl = self.apln.algebras[dim]\n", - " propagation = apl(0)\n", - " for n in reversed(range(dim+1)):\n", - " faces = self._faces_of_length(simplex, n)\n", - " for f in faces:\n", - " if f in cochain.keys():\n", - " dim_face = len(f)-1\n", - " value = cochain[f]\n", - " face_indexes = [simplex.index(i) for i in f]\n", - " propagation += value*((-1)**(dim_face*(dim_face-1)/2))*factorial(dim_face)*self.apln.propagate(face_indexes, dim)\n", - " return propagation\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'MorphismFromQQToAplK' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m~/Documents/0-PhD/Code/sage-9.2/local/lib/python3.8/site-packages/sage/misc/cachefunc.pyx\u001b[0m in \u001b[0;36msage.misc.cachefunc.CachedFunction.__call__ (build/cythonized/sage/misc/cachefunc.c:5975)\u001b[0;34m()\u001b[0m\n\u001b[1;32m 995\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 996\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcache\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 997\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;31m# k is not hashable\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/Documents/0-PhD/Code/sage-9.2/local/lib/python3.8/site-packages/sage/misc/weak_dict.pyx\u001b[0m in \u001b[0;36msage.misc.weak_dict.WeakValueDictionary.__getitem__ (build/cythonized/sage/misc/weak_dict.c:3737)\u001b[0;34m()\u001b[0m\n\u001b[1;32m 703\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mwr\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mNULL\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 704\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 705\u001b[0m \u001b[0mout\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mPyWeakref_GetObject\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mKeyError\u001b[0m: ((, Simplicial complex with vertex set (0, 1, 2, 3) and facets {(1, 3), (2, 3), (0, 1, 2)}), ())", - "\nDuring handling of the above exception, another exception occurred:\n", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mcochain\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mS\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mSimplicialComplex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mis_mutable\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mA\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mAplK\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mS\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0mp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mA\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_propagate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcochain\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mInteger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mp\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/Documents/0-PhD/Code/sage-9.2/local/lib/python3.8/site-packages/sage/misc/classcall_metaclass.pyx\u001b[0m in \u001b[0;36msage.misc.classcall_metaclass.ClasscallMetaclass.__call__ (build/cythonized/sage/misc/classcall_metaclass.c:1762)\u001b[0;34m()\u001b[0m\n\u001b[1;32m 320\u001b[0m \"\"\"\n\u001b[1;32m 321\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcls\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mclasscall\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 322\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mcls\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mclasscall\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcls\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 323\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 324\u001b[0m \u001b[0;31m# Fast version of type.__call__(cls, *args, **kwds)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/Documents/0-PhD/Code/sage-9.2/local/lib/python3.8/site-packages/sage/misc/cachefunc.pyx\u001b[0m in \u001b[0;36msage.misc.cachefunc.CachedFunction.__call__ (build/cythonized/sage/misc/cachefunc.c:6101)\u001b[0;34m()\u001b[0m\n\u001b[1;32m 999\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcache\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1000\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1001\u001b[0;31m \u001b[0mw\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1002\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcache\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mw\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1003\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mw\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/Documents/0-PhD/Code/sage-9.2/local/lib/python3.8/site-packages/sage/structure/unique_representation.py\u001b[0m in \u001b[0;36m__classcall__\u001b[0;34m(cls, *args, **options)\u001b[0m\n\u001b[1;32m 1006\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1007\u001b[0m \"\"\"\n\u001b[0;32m-> 1008\u001b[0;31m \u001b[0minstance\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtypecall\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcls\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0moptions\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1009\u001b[0m \u001b[0;32massert\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m \u001b[0minstance\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcls\u001b[0m \u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1010\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0minstance\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__class__\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__reduce__\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mCachedRepresentation\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__reduce__\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/Documents/0-PhD/Code/sage-9.2/local/lib/python3.8/site-packages/sage/misc/classcall_metaclass.pyx\u001b[0m in \u001b[0;36msage.misc.classcall_metaclass.typecall (build/cythonized/sage/misc/classcall_metaclass.c:2224)\u001b[0;34m()\u001b[0m\n\u001b[1;32m 484\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mArgument\u001b[0m \u001b[0;34m'cls'\u001b[0m \u001b[0mhas\u001b[0m \u001b[0mincorrect\u001b[0m \u001b[0mtype\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mexpected\u001b[0m \u001b[0mtype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mgot\u001b[0m \u001b[0mclassobj\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 485\u001b[0m \"\"\"\n\u001b[0;32m--> 486\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m<\u001b[0m\u001b[0mPyTypeObject\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;34m>\u001b[0m\u001b[0mtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtp_call\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcls\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 487\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 488\u001b[0m \u001b[0;31m# Class for timing::\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, K, category)\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mapln\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mApln\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mK\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdimension\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0mParent\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mcategory\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcategory\u001b[0m \u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 8\u001b[0;31m \u001b[0mf\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mMorphismFromQQToAplK\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 9\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mregister_coercion\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mNameError\u001b[0m: name 'MorphismFromQQToAplK' is not defined" - ] - } - ], - "source": [ - "# AplK._propagate TEST\n", - "cochain = {(0,): 0, (1,): 0, (2,):0, (3,): 0, (0,1): 0, (0,2): 0, (1,2): 1, (1,3): 0, (2,3): 0, (0,1,2):0}\n", - "S = SimplicialComplex([[0,1,2],[1,3],[2,3]],is_mutable=False) \n", - "A = AplK(S)\n", - "p = A._propagate(cochain,(0,1,2))\n", - "print(p)\n", - "a = Apln(5)\n", - "q = a.face(0,2)(p)\n", - "print(q)\n", - "ared = a.reduce_polynomial(q)\n", - "print(ared)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "S = SimplicialComplex([[0,1,2],[1,3],[2,3]],is_mutable=False) \n", - "A = AplK(S)\n", - "cochain = {(0,): 2, (1,): 3, (2,):0, (3,): 0, (0,1): 1, (0,2): 5, (1,2): 1, (1,3): 0, (2,3): 0, (0,1,2):10}\n", - "p = A.lift(cochain)\n", - "p" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "A.lift(cochain).integral()==cochain" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "A.lift(p.integral())==p" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Apl(K) Element" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [], - "source": [ - "class AplKElement(Element):\n", - "\n", - " def __init__(self, parent, values):\n", - " Element.__init__(self,parent)\n", - " self.apln = Apln(parent.dimension())\n", - " self.elements = self.reduce(values) \n", - " self.check()\n", - " \n", - " def reduce(self, values):\n", - " reduced_values = {}\n", - " for k in values.keys():\n", - " n = len(k)-1\n", - " apl = self.apln.algebras[n]\n", - " reduced_values[k] = self.apln.reduce_polynomial(apl(values[k]))\n", - " return reduced_values\n", - " \n", - " def _repr_(self):\n", - " return str(self.elements)\n", - " \n", - " def dimension(self):\n", - " return self.parent().dimension()\n", - " \n", - " def nullElement(self):\n", - " C = self.__class__\n", - " values = {}\n", - " for k in self.elements.keys():\n", - " values[k]=0\n", - " return C(self.parent(),values) \n", - " \n", - " def _add_(self,other):\n", - " C = self.__class__\n", - " if(self.elements.keys()!=other.elements.keys()):\n", - " raise ValueError(\"error: keys do not match\")\n", - " newValues = {}\n", - " for k in self.elements.keys():\n", - " newValues[k] = self.elements[k]+other.elements[k]\n", - " return C(self.parent(),newValues)\n", - " \n", - " def _sub_(self,other):\n", - "\n", - " C = self.__class__\n", - " if(self.elements.keys()!=other.elements.keys()):\n", - " raise ValueError(\"error: keys do not match\")\n", - " newValues = {}\n", - " for k in self.elements.keys():\n", - " newValues[k] = self.elements[k]-other.elements[k]\n", - " return C(self.parent(),newValues)\n", - " \n", - " def _mul_(self,other):\n", - "\n", - " C = self.__class__\n", - " if(self.elements.keys()!=other.elements.keys()):\n", - " raise ValueError(\"error: keys do not match\")\n", - " newValues = {}\n", - " for k in self.elements.keys():\n", - " newValues[k] = self.elements[k]*other.elements[k]\n", - " return C(self.parent(),newValues)\n", - " \n", - " def _richcmp_(self, other, op):\n", - "\n", - " if(op==op_EQ):\n", - " if(self.elements.keys()!=other.elements.keys()):\n", - " return False\n", - " for k in self.elements.keys():\n", - " if(self.elements[k]!=other.elements[k]):\n", - " return False\n", - " return True\n", - " elif(op==op_NE):\n", - " return not self._richcmp_(other,op_EQ)\n", - " else:\n", - " raise NotImplementedError(\"operation not implemented for this element class\")\n", - " \n", - " def differential(self):\n", - " C = self.__class__\n", - " newValues = {}\n", - " for k in self.elements.keys():\n", - " newValues[k] = self.elements[k].differential()\n", - " return C(self.parent(),newValues)\n", - " \n", - " def check(self):\n", - "\n", - " S = self.parent().simplicialComplex()\n", - " dim = S.dimension()\n", - " for n in range(1,dim+1):\n", - " #print(\"Checking dimension \" + str(n))\n", - " for simplex in S._n_cells_sorted(n):\n", - " for f in range(n+1):\n", - " sFace = tuple(S.face(simplex,f))\n", - " aFace = self.apln.face(f,n)(self.elements[simplex.tuple()])\n", - " aFace = self.apln.reduce_polynomial(aFace)\n", - " #print(\"face: \" + str(f),\"simplex: \" + str(simplex),\"sFace: \" + str(self.elements[sFace]), \"aFace: \" + str(aFace))\n", - " if(self.elements[sFace] != aFace):\n", - " raise ValueError(\"the assignation is not valid\")\n", - " \n", - " def homogeneous_part(self,degree):\n", - " C = self.__class__\n", - " part = {}\n", - " for k in self.elements.keys():\n", - " part[k] = self.apln.homogeneous_part(self.elements[k],degree)\n", - " return C(self.parent(),part)\n", - " \n", - " def homogeneous_parts(self):\n", - " parts = {}\n", - " for n in range(self.dimension()+1):\n", - " parts[n] = self.homogeneous_part(n)\n", - " return parts\n", - " \n", - " def is_homogeneous(self):\n", - " isHomogeneous = True\n", - " for k in self.elements.keys():\n", - " isHomogeneous = isHomogeneous and self.elements[k].is_homogeneous()\n", - " return isHomogeneous\n", - " \n", - " def is_closed(self):\n", - " diff = self.differential()\n", - " if(diff == self.nullElement()):\n", - " return True\n", - " else:\n", - " return False\n", - " \n", - " def _integrable_component(self):\n", - " C = self.__class__\n", - " component = {}\n", - " for k in self.elements.keys():\n", - " degree = len(k)-1\n", - " component[k] = self.apln.homogeneous_part(self.elements[k],degree)\n", - " #component[k] = self.homogeneous_component(dim).elements[k]\n", - " return component\n", - " \n", - " def integral(self):\n", - " component = self._integrable_component()\n", - " cochain = {}\n", - " #integration of each polynomial\n", - " for k in component.keys():\n", - " n = len(k)-1\n", - " apl = self.apln.algebras[n]\n", - " cochain[k] = self.apln.integral(apl(component[k]))\n", - " return cochain\n", - " \n", - "#####################################################################\n", - "\n", - "class MorphismFromQQToAplK(Morphism):\n", - "\n", - " def __init__(self, codomain):\n", - " self.simplicialComplex= codomain.K\n", - " Morphism.__init__(self, QQ, codomain)\n", - "\n", - " def _call_(self, x):\n", - " S = self.simplicialComplex\n", - " params1 = {}\n", - " for d in range(S.dimension()+1):\n", - " for c in S._n_cells_sorted(d):\n", - " params1[tuple(c)]=x\n", - " A = AplK(S)\n", - " return AplKElement(A, params1)" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [], - "source": [ - "S = SimplicialComplex([[0, 1, 2]], is_mutable=False) \n", - "apl = Apln(S.dimension())\n", - "A = AplK(S)\n", - "cochain = {(0,): 0, (1,): 0, (2,):0, (0,1): 0,(0,2): 0, (1,2): 0, (0,1,2): 1}\n", - "#A.lift(apl, cochain)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{(0, 1, 2): -2*y1*y2, (0, 1): 0, (0, 2): 0, (1, 2): 0, (0,): 0, (1,): 0, (2,): 0}" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "q = A.lift(cochain)\n", - "q" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "2*q" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# All together" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "S1 = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4],[3,5],[4,5]],is_mutable=False) \n", - "S2 = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4,5],[3,4,6],[3,5,6],[4,5,6]],is_mutable=False) \n", - "S3 = SimplicialComplex([[0,1,2],[1,3],[2,3]],is_mutable=False) \n", - "S4 = SimplicialComplex([[0,1,3],[1,2,4],[3,4,5]],is_mutable=False) \n", - "S5 = simplicial_complexes.Sphere(5)\n", - "S = S5\n", - "apl = Apln(S.dimension())\n", - "A = AplK(S)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "n = 5\n", - "gens = cohomology_gens(S,n)\n", - "cochain = lift_cohomology_generator(S,gens[(n,0)])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "gens" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "p = A.lift(cochain)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "p.integral()==cochain" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Test lift == integral" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [], - "source": [ - "def sublist(lst1, lst2):\n", - " return set(lst1) <= set(lst2)\n", - "\n", - "def sublist_of_lists(list1,list_of_lists):\n", - " is_sublist = False\n", - " for list2 in list_of_lists:\n", - " if sublist(list1,list2):\n", - " is_sublist = True\n", - " break\n", - " return is_sublist\n", - "\n", - "def random_simplicial_complex(num_vertices,max_num_facets):\n", - " vertices = list(range(num_vertices))\n", - " simplices = []\n", - " partitions = []\n", - " for length in range(num_vertices):\n", - " partitions += [tuple(e) for e in powerset(vertices) if len(e)==length and e]\n", - " for i in range(max_num_facets+1):\n", - " r = randint(0,len(partitions)-1)\n", - " candidate = partitions[r]\n", - " if not sublist_of_lists(candidate,simplices):\n", - " simplices.append(candidate)\n", - " return SimplicialComplex(simplices,is_mutable=False)\n", - "\n", - "def random_cochain(S):\n", - " dim = S.dimension()\n", - " cochain = {}\n", - " for n in range(dim+1):\n", - " for s in S._n_cells_sorted(n):\n", - " cochain[s.tuple()] = randint(-100,100)\n", - " return cochain" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{(0, 1, 4), (0, 1, 3), (0, 1, 2)}" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "S = random_simplicial_complex(5,4)\n", - "S.facets()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [], - "source": [ - "def test(max_vertices, verbose=False):\n", - " success = True\n", - " data = []\n", - " for i in range(10):\n", - " v = randint(2,max_vertices)\n", - " f = randint(1,v)\n", - " S = random_simplicial_complex(num_vertices=v,max_num_facets=f)\n", - " A = AplK(S)\n", - " cochain = random_cochain(S)\n", - " #print(cochain)\n", - " data = [S, cochain]\n", - " if verbose:\n", - " print(\"iteration: \" + str(i), \"num_vertices: \" + str(v), \"max_num_facets: \" + str(f), \"facets: \" + str(S.facets()))\n", - " p = A.lift(cochain)\n", - " if verbose:\n", - " print(p)\n", - " if not p.integral()==cochain:\n", - " success = False\n", - " print(\"Error\")\n", - " break\n", - " if success:\n", - " print(\"success: \" + str(success))" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "iteration: 0 num_vertices: 5 max_num_facets: 1 facets: {(1, 3, 4), (0, 4)}\n", - "{(1, 3, 4): -168*y1*y2 - 65*t2*y1 + 65*t1*y2 - 71*y1 - 94*y2 - 150*t1 + t2 + 87, (0, 4): -80*y1 + 60*t1 + 28, (1, 3): -71*y1 - 150*t1 + 87, (1, 4): -94*y1 + t1 + 87, (3, 4): 42*y1 + 151*t1 - 63, (0,): 28, (1,): 87, (3,): -63, (4,): 88}\n", - "iteration: 1 num_vertices: 4 max_num_facets: 1 facets: {(0, 2, 3), (0, 1, 2)}\n", - "{(0, 1, 2): -52*y1*y2 - 65*t2*y1 + 65*t1*y2 + 54*y1 + 81*y2 - 64*t1 - 58*t2 + 70, (0, 2, 3): 82*y1*y2 + 45*t2*y1 - 45*t1*y2 + 81*y1 + 71*y2 - 58*t1 - 95*t2 + 70, (0, 1): 54*y1 - 64*t1 + 70, (0, 2): 81*y1 - 58*t1 + 70, (0, 3): 71*y1 - 95*t1 + 70, (1, 2): 92*y1 + 6*t1 + 6, (2, 3): -55*y1 - 37*t1 + 12, (0,): 70, (1,): 6, (2,): 12, (3,): -25}\n", - "iteration: 2 num_vertices: 4 max_num_facets: 3 facets: {(0, 1, 3), (0, 2, 3), (1, 2)}\n", - "{(0, 1, 3): -12*y1*y2 + 47*t2*y1 - 47*t1*y2 - 59*y1 + 22*y2 - 95*t1 - 132*t2 + 67, (0, 2, 3): -178*y1*y2 - 29*t2*y1 + 29*t1*y2 - 15*y1 + 22*y2 - 7*t1 - 132*t2 + 67, (0, 1): -59*y1 - 95*t1 + 67, (0, 2): -15*y1 - 7*t1 + 67, (0, 3): 22*y1 - 132*t1 + 67, (1, 2): -5*y1 + 88*t1 - 28, (1, 3): 34*y1 - 37*t1 - 28, (2, 3): 66*y1 - 125*t1 + 60, (0,): 67, (1,): -28, (2,): 60, (3,): -65}\n", - "iteration: 3 num_vertices: 6 max_num_facets: 2 facets: {(2, 3, 4), (0, 1, 3, 4)}\n", - "{(0, 1, 3, 4): -36*y1*y2*y3 + 444*t3*y1*y2 - 444*t2*y1*y3 + 444*t1*y2*y3 - 22*y1*y2 + 120*y1*y3 - 130*y2*y3 - 51*t2*y1 - 129*t3*y1 + 51*t1*y2 - 118*t3*y2 + 129*t1*y3 + 118*t2*y3 + 22*y1 + 67*y2 - 93*y3 - 57*t1 - 8*t2 + 112*t3 - 22, (0, 1, 3): -22*y1*y2 - 51*t2*y1 + 51*t1*y2 + 22*y1 + 67*y2 - 57*t1 - 8*t2 - 22, (0, 1, 4): 120*y1*y2 - 129*t2*y1 + 129*t1*y2 + 22*y1 - 93*y2 - 57*t1 + 112*t2 - 22, (0, 3, 4): -130*y1*y2 - 118*t2*y1 + 118*t1*y2 + 67*y1 - 93*y2 - 8*t1 + 112*t2 - 22, (1, 3, 4): 172*y1*y2 - 40*t2*y1 + 40*t1*y2 + 96*y1 + 14*y2 + 49*t1 + 169*t2 - 79, (2, 3, 4): -96*y1*y2 + 92*t2*y1 - 92*t1*y2 + 35*y1 + 85*y2 - 35*t1 + 85*t2 + 5, (0, 1): 22*y1 - 57*t1 - 22, (0, 3): 67*y1 - 8*t1 - 22, (0, 4): -93*y1 + 112*t1 - 22, (1, 3): 96*y1 + 49*t1 - 79, (1, 4): 14*y1 + 169*t1 - 79, (2, 3): 35*y1 - 35*t1 + 5, (2, 4): 85*y1 + 85*t1 + 5, (3, 4): -42*y1 + 120*t1 - 30, (0,): -22, (1,): -79, (2,): 5, (3,): -30, (4,): 90}\n", - "iteration: 4 num_vertices: 2 max_num_facets: 2 facets: {(1,), (0,)}\n", - "{(0,): -2, (1,): 97}\n", - "iteration: 5 num_vertices: 5 max_num_facets: 5 facets: {(0, 2, 3, 4), (0, 1, 2, 4), (1, 2, 3)}\n", - "{(0, 1, 2, 4): -384*y1*y2*y3 + 212*t3*y1*y2 - 212*t2*y1*y3 + 212*t1*y2*y3 - 76*y1*y2 - 44*y1*y3 - 128*y2*y3 + 8*t2*y1 + 28*t3*y1 - 8*t1*y2 - 103*t3*y2 - 28*t1*y3 + 103*t2*y3 - 6*y1 + 51*y2 - 46*y3 - 37*t1 + 119*t2 + 147*t3 - 63, (0, 2, 3, 4): -150*y1*y2*y3 - 254*t3*y1*y2 + 254*t2*y1*y3 - 254*t1*y2*y3 + 142*y1*y2 - 128*y1*y3 + 74*y2*y3 + 61*t2*y1 - 103*t3*y1 - 61*t1*y2 + t3*y2 + 103*t1*y3 - t2*y3 + 51*y1 + 53*y2 - 46*y3 + 119*t1 + 125*t2 + 147*t3 - 63, (0, 1, 2): -76*y1*y2 + 8*t2*y1 - 8*t1*y2 - 6*y1 + 51*y2 - 37*t1 + 119*t2 - 63, (0, 1, 4): -44*y1*y2 + 28*t2*y1 - 28*t1*y2 - 6*y1 - 46*y2 - 37*t1 + 147*t2 - 63, (0, 2, 3): 142*y1*y2 + 61*t2*y1 - 61*t1*y2 + 51*y1 + 53*y2 + 119*t1 + 125*t2 - 63, (0, 2, 4): -128*y1*y2 - 103*t2*y1 + 103*t1*y2 + 51*y1 - 46*y2 + 119*t1 + 147*t2 - 63, (0, 3, 4): 74*y1*y2 + t2*y1 - t1*y2 + 53*y1 - 46*y2 + 125*t1 + 147*t2 - 63, (1, 2, 3): 148*y1*y2 - 55*t2*y1 + 55*t1*y2 + 49*y1 - 65*y2 + 156*t1 + 162*t2 - 100, (1, 2, 4): 52*y1*y2 - 123*t2*y1 + 123*t1*y2 + 49*y1 - 68*y2 + 156*t1 + 184*t2 - 100, (2, 3, 4): 90*y1*y2 + 165*t2*y1 - 165*t1*y2 - 59*y1 + 6*y2 + 6*t1 + 28*t2 + 56, (0, 1): -6*y1 - 37*t1 - 63, (0, 2): 51*y1 + 119*t1 - 63, (0, 3): 53*y1 + 125*t1 - 63, (0, 4): -46*y1 + 147*t1 - 63, (1, 2): 49*y1 + 156*t1 - 100, (1, 3): -65*y1 + 162*t1 - 100, (1, 4): -68*y1 + 184*t1 - 100, (2, 3): -59*y1 + 6*t1 + 56, (2, 4): 6*y1 + 28*t1 + 56, (3, 4): -100*y1 + 22*t1 + 62, (0,): -63, (1,): -100, (2,): 56, (3,): 62, (4,): 84}\n", - "iteration: 6 num_vertices: 2 max_num_facets: 1 facets: {(1,), (0,)}\n", - "{(0,): -95, (1,): 1}\n", - "iteration: 7 num_vertices: 4 max_num_facets: 3 facets: {(1, 3), (0, 2, 3)}\n", - "{(0, 2, 3): -182*y1*y2 - 93*t2*y1 + 93*t1*y2 - 53*y1 - 66*y2 - 25*t1 - 26*t2 - 52, (0, 2): -53*y1 - 25*t1 - 52, (0, 3): -66*y1 - 26*t1 - 52, (1, 3): -35*y1 + 16*t1 - 94, (2, 3): 80*y1 - t1 - 77, (0,): -52, (1,): -94, (2,): -77, (3,): -78}\n", - "iteration: 8 num_vertices: 5 max_num_facets: 4 facets: {(2, 3, 4), (1, 2), (0, 1, 3, 4)}\n", - "{(0, 1, 3, 4): 36*y1*y2*y3 - 74*t3*y1*y2 + 74*t2*y1*y3 - 74*t1*y2*y3 + 190*y1*y2 - 138*y1*y3 - 172*y2*y3 - 6*t3*y1 - 16*t3*y2 + 6*t1*y3 + 16*t2*y3 + 44*y1 - 3*y2 - 13*y3 + 90*t1 - 8*t2 + 136*t3 - 46, (0, 1, 3): 190*y1*y2 + 44*y1 - 3*y2 + 90*t1 - 8*t2 - 46, (0, 1, 4): -138*y1*y2 - 6*t2*y1 + 6*t1*y2 + 44*y1 - 13*y2 + 90*t1 + 136*t2 - 46, (0, 3, 4): -172*y1*y2 - 16*t2*y1 + 16*t1*y2 - 3*y1 - 13*y2 - 8*t1 + 136*t2 - 46, (1, 3, 4): 82*y1*y2 - 10*t2*y1 + 10*t1*y2 - 47*y1 - 51*y2 - 98*t1 + 46*t2 + 44, (2, 3, 4): 6*y1*y2 + 85*t2*y1 - 85*t1*y2 - 72*y1 + 19*y2 + 17*t1 + 161*t2 - 71, (0, 1): 44*y1 + 90*t1 - 46, (0, 3): -3*y1 - 8*t1 - 46, (0, 4): -13*y1 + 136*t1 - 46, (1, 2): -27*y1 - 115*t1 + 44, (1, 3): -47*y1 - 98*t1 + 44, (1, 4): -51*y1 + 46*t1 + 44, (2, 3): -72*y1 + 17*t1 - 71, (2, 4): 19*y1 + 161*t1 - 71, (3, 4): 6*y1 + 144*t1 - 54, (0,): -46, (1,): 44, (2,): -71, (3,): -54, (4,): 90}\n", - "iteration: 9 num_vertices: 5 max_num_facets: 3 facets: {(1, 3), (1, 2)}\n", - "{(1, 2): 91*y1 - 78*t1 + 81, (1, 3): 100*y1 + 5*t1 + 81, (1,): 81, (2,): 3, (3,): 86}\n", - "success: True\n" - ] - } - ], - "source": [ - "test(max_vertices=6, verbose=True)" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [], - "source": [ - "S = random_simplicial_complex(5,4)\n", - "A = AplK(S)" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [], - "source": [ - "c1 = random_cochain(S)\n", - "p1 = A.lift(c1)\n", - "c2 = random_cochain(S)\n", - "p2 = A.lift(c2)" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Object `differential` not found.\n" - ] - } - ], - "source": [ - "(p2*p1).differential" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "a = apl.algebras[2]" - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Commutative Differential Graded Algebra with generators ('t0', 't1', 't2', 'y0', 'y1', 'y2') in degrees ((0, 2), (0, 2), (0, 2), (1, 2), (1, 2), (1, 2)) over Rational Field with differential:\n", - " t0 --> y0\n", - " t1 --> y1\n", - " t2 --> y2\n", - " y0 --> 0\n", - " y1 --> 0\n", - " y2 --> 0" - ] - }, - "execution_count": 50, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Minimal model $S^2 \\wedge S^1$" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "S1 = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4],[3,5],[4,5]],is_mutable=False) \n", - "S2 = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4,5],[3,4,6],[3,5,6],[4,5,6]],is_mutable=False)\n", - "S = S1\n", - "apl = Apln(S.dimension())\n", - "A = AplK(S)\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# busco el primer grupo de cohomología no trivial\n", - "gens = cohomology_gens(S,1)\n", - "gens" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "c10 = lift_cohomology_generator(S,gens[(1,0)])\n", - "a10 = A.lift(c10)\n", - "a10" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# compruebo que la diferencial es cero\n", - "a10.is_closed()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# pasamos al sigiente grado\n", - "gens = cohomology_gens(S,2)\n", - "gens" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "c20 = lift_cohomology_generator(S,gens[(2,0)])\n", - "a20 = A.lift(c20)\n", - "a20" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "c20.keys()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "a20.is_closed()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "a10*a20" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Minimal model $S^2 \\wedge S^2$" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "S2 = SimplicialComplex([[0,1,2],[0,1,3],[0,2,3],[1,2,3],[3,4,5],[3,4,6],[3,5,6],[4,5,6]],is_mutable=False)\n", - "S = S2\n", - "apl = Apln(S.dimension())\n", - "A = AplK(S)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# busco el primer grupo de cohomología no trivial\n", - "gens = cohomology_gens(S,2)\n", - "gens" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "c20 = lift_cohomology_generator(S,gens[(2,0)])\n", - "a20 = A.lift(c20)\n", - "c21 = lift_cohomology_generator(S,gens[(2,1)])\n", - "a21 = A.lift(c21)\n", - "a20*a21 == a20.nullElement()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "a31 = a20.nullElement()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for k in gens.keys():\n", - " print(k[0])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Minimal model" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "class MinimalModel():\n", - "\n", - " def __init__(self, S):\n", - " self.K = S\n", - " self.Phi = {}\n", - " self.AplK = AplK(S)\n", - " self.Apln = Apln(S.dimension())\n", - " gens = self.first_non_trivial_cohomology_group()\n", - " [self.cdga, self.cohomology_dict] = self.createModel(gens)\n", - " \n", - " def first_non_trivial_cohomology_group(self, max_iter=20):\n", - " # busco el primer grupo de cohomología no trivial\n", - " i=1\n", - " gens = self.cohomology_gens(i)\n", - " while(len(gens)==0 and i