{ "cells": [ { "cell_type": "markdown", "id": "c372a9b5-ac0d-4b16-8f5e-3aa3c242771b", "metadata": {}, "source": [ "This notebook illustrates the functionality of Singular, using a SageMath kernel." ] }, { "cell_type": "markdown", "id": "20552d14-aed7-4e46-8ef9-2c979936c2dd", "metadata": {}, "source": [ "# 1. Resultants for Elimination of Variables" ] }, { "cell_type": "markdown", "id": "aa81c0c4-8125-45d7-a6ec-e1a5b033c7c7", "metadata": {}, "source": [ "We can type in singular commands directly in a code cell via the `%%singular` magic." ] }, { "cell_type": "code", "execution_count": 1, "id": "595cdc02-2ee9-4519-9144-6812bbccdb7a", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "// coefficients: QQ\n", "// number of vars : 2\n", "// block 1 : ordering Dp\n", "// : names x y\n", "// block 2 : ordering C\n" ] } ], "source": [ "%%singular\n", "ring r = 0, (x,y), Dp; r" ] }, { "cell_type": "markdown", "id": "88c8ba6c-cc8b-405e-ad8f-3aec04309d80", "metadata": {}, "source": [ "We declared a ring `r` over the rational numbers (characteristic 0),\n", "for polynomials in x and y,\n", "in the degree lexicographic ordering (as in a dictionary)." ] }, { "cell_type": "code", "execution_count": 2, "id": "e6eedf43-2de8-427d-b4e6-9a80fe697c6c", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "x2+4xy+4y2-4\n" ] } ], "source": [ "%%singular\n", "poly p = 4*y^2 - 4 + 4*x*y + x^2;\n", "p" ] }, { "cell_type": "markdown", "id": "02cec9aa-7212-4c0a-b6bc-a25627ccaa48", "metadata": {}, "source": [ "We see `p` shown in the degree lexicographic order:\n", "\n", "* first the highest degree monomials (`x2` $ = x^2$),\n", "\n", "* with those with highest powers of `x` appearing first." ] }, { "cell_type": "markdown", "id": "58eb5647-6278-4ef9-b652-0e530aa5ddc6", "metadata": {}, "source": [ "Then we define a second polynomial `q`:" ] }, { "cell_type": "code", "execution_count": 3, "id": "25959439-0082-4693-9fa6-a0692d8f2c5d", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4x2-4xy+y2-4\n" ] } ], "source": [ "%%singular\n", "poly q = 4*x^2 - 4*x*y + y^2 - 4; q" ] }, { "cell_type": "markdown", "id": "ee0d7d10-3cff-4ae0-b96a-fae02f4a177b", "metadata": {}, "source": [ "The polynomials `p` and `q` define a system." ] }, { "cell_type": "markdown", "id": "1226303b-da62-4a6e-8a61-09ddfff9f93c", "metadata": {}, "source": [ "To eliminate `x` from the system `p(x,y) = 0 = q(x,y)`\n", "we compute *the resultant* of `p` and `q` with respect to `x`." ] }, { "cell_type": "code", "execution_count": 4, "id": "11eaa650-39c0-4b45-b750-bdd787a75628", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "625y4-1000y2+144\n" ] } ], "source": [ "%%singular\n", "poly rx = resultant(p,q,x);\n", "rx" ] }, { "cell_type": "markdown", "id": "184c3a3c-399d-4ea2-9d64-a437f93dbcb6", "metadata": {}, "source": [ "All values for `y` for which `p(x,y) = 0 = q(x,y)`\n", "also make `resultant(p,q,x)` zero." ] }, { "cell_type": "markdown", "id": "f06f5316-e767-4f12-83b8-e2bc12a99208", "metadata": {}, "source": [ "To compute numerical values for `y`, we load the `solve` library." ] }, { "cell_type": "code", "execution_count": 5, "id": "90759913-8cd6-4506-a0b3-e14e15f8a4b9", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "// ** loaded /usr/bin/../share/singular/LIB/solve.lib (4.1.2.0,Feb_2019)\n" ] } ], "source": [ "%%singular\n", "LIB \"solve.lib\";" ] }, { "cell_type": "markdown", "id": "dbac62d2-cfda-427b-aab8-91d32b4bc932", "metadata": {}, "source": [ "We ask to compute all roots\n", "with 10 decimal places of precision:" ] }, { "cell_type": "code", "execution_count": 6, "id": "2003f1de-0294-421f-852c-45d7938263fe", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "[1]:\n", " -1.2\n", "[2]:\n", " -0.4\n", "[3]:\n", " 0.4\n", "[4]:\n", " 1.2\n" ] } ], "source": [ "%%singular\n", "list L = laguerre_solve(rx,10);\n", "L" ] }, { "cell_type": "markdown", "id": "336946aa-c16d-42bf-983b-444164cd3387", "metadata": {}, "source": [ "Root finding is related to factorization:" ] }, { "cell_type": "code", "execution_count": 7, "id": "066411db-c02d-4827-a9fc-dce2640c6d81", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1]:\n", " _[1]=1\n", " _[2]=5y-6\n", " _[3]=5y-2\n", " _[4]=5y+2\n", " _[5]=5y+6\n", "[2]:\n", " 1,1,1,1,1\n" ] } ], "source": [ "%%singular\n", "factorize(rx);" ] }, { "cell_type": "markdown", "id": "ae533986-955d-4d55-b548-55e91bb2a43e", "metadata": {}, "source": [ "For this simple problem, observe that this allows to compute the exact rational values for `y`." ] }, { "cell_type": "markdown", "id": "e619b906-0562-4f08-915f-16838fedffb3", "metadata": {}, "source": [ "Of course, there is the `solve` command, which gives the roots directly. But we must to declare the polynomials `p` and `q` as the generators of an *ideal*. An ideal generated by a finite list of polynomials consists of all polynomial combinations of the generators." ] }, { "cell_type": "code", "execution_count": 8, "id": "ccabc336-dab5-468c-ba3b-3dc16b2564ba", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "I[1]=x2+4xy+4y2-4\n", "I[2]=4x2-4xy+y2-4\n" ] } ], "source": [ "%%singular\n", "ideal I = p, q;\n", "I" ] }, { "cell_type": "code", "execution_count": 9, "id": "3e30d56d-a7a0-407f-ba92-ff2851981ff8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1]:\n", " [1]:\n", "0.4\n", " [2]:\n", "-1.2\n", "[2]:\n", " [1]:\n", "-1.2\n", " [2]:\n", "-0.4\n", "[3]:\n", " [1]:\n", "1.2\n", " [2]:\n", "0.4\n", "[4]:\n", " [1]:\n", "-0.4\n", " [2]:\n", "1.2\n", "\n", "// 'solve' created a ring, in which a list SOL of numbers (the complex solutions)\n", "// is stored.\n", "// To access the list of complex solutions, type (if the name R was assigned\n", "// to the return value):\n", " setring R; SOL; \n", "// coefficients: real[i](complex:8 digits, additional 8 digits)/(i^2+1)\n", "// number of vars : 2\n", "// block 1 : ordering lp\n", "// : names x y\n", "// block 2 : ordering C\n" ] } ], "source": [ "%%singular\n", "solve(I);" ] }, { "cell_type": "markdown", "id": "c047e159-c303-4c6c-9fc9-150969ba8bf7", "metadata": {}, "source": [ "# 2. Groebner Bases and Multiplication Matrices" ] }, { "cell_type": "markdown", "id": "71471508-da84-432e-9dc5-f86a04e47f3d", "metadata": {}, "source": [ "A Groebner basis of an ideal is a set of generators so the division algorithm has a unique outcome." ] }, { "cell_type": "code", "execution_count": 10, "id": "af4f90d9-201c-45e8-ad72-54d9b028211f", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "g[1]=20xy+15y2-12\n", "g[2]=4x2-4xy+y2-4\n", "g[3]=125y3+48x-164y\n" ] } ], "source": [ "%%singular\n", "ideal g = groebner(I);\n", "g" ] }, { "cell_type": "markdown", "id": "70eab003-5440-41e0-9485-61b0b4735803", "metadata": {}, "source": [ "A lexicographic monomial order eliminates variables\n", "and the resulting Groebner basis has a triangular form.\n", "\n", "A lexicographic monomial order in Singular is `lp`:" ] }, { "cell_type": "code", "execution_count": 11, "id": "6319b0ae-2ae8-4b0d-bbea-92580e0fa27f", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "// coefficients: QQ\n", "// number of vars : 2\n", "// block 1 : ordering lp\n", "// : names x y\n", "// block 2 : ordering C\n" ] } ], "source": [ "%%singular\n", "ring s = 0, (x,y), lp;\n", "s" ] }, { "cell_type": "markdown", "id": "05029c81-ad67-4fe9-a133-6e3fe11eb60b", "metadata": {}, "source": [ "After this ring definition, the current ring becomes `s`\n", "and the ideal `I` does not exist in this ring.\n", "\n", "To return to the original ring `r`, we type" ] }, { "cell_type": "code", "execution_count": 12, "id": "4a6a4632-2ac1-4ead-b615-ad84ad47c367", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "%%singular\n", "setring r;" ] }, { "cell_type": "markdown", "id": "7edf3c65-3eed-43e5-afaa-f8f62a6db319", "metadata": {}, "source": [ "After returning to the ring `r`, we have" ] }, { "cell_type": "code", "execution_count": 13, "id": "f1561f95-4aa4-416e-a85e-3156b6178c56", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I[1]=x2+4xy+4y2-4\n", "I[2]=4x2-4xy+y2-4\n" ] } ], "source": [ "%%singular\n", "I" ] }, { "cell_type": "markdown", "id": "12dc3df7-bbe2-4e24-8bf9-3f7e5f75c575", "metadata": {}, "source": [ "Before converting to a lexicographic order,\n", "we must force the computation of a reduced standard basis:" ] }, { "cell_type": "code", "execution_count": 14, "id": "ba4ee54c-b0c4-41a9-be74-dc5a042c571f", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "I[1]=20xy+15y2-12\n", "I[2]=5x2+5y2-8\n", "I[3]=125y3+48x-164y\n" ] } ], "source": [ "%%singular\n", "option(redSB);\n", "I = std(I);\n", "I;" ] }, { "cell_type": "markdown", "id": "a3840db5-0264-4f8b-b7f0-40658f19fed6", "metadata": {}, "source": [ "Instead of computing a Groebner basis in the ring `s`\n", "from scratch, we convert with the FGLM Algorithm:" ] }, { "cell_type": "code", "execution_count": 15, "id": "bef684ae-3fd4-43d1-9dc0-8f6cc995445b", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "J[1]=625y4-1000y2+144\n", "J[2]=48x+125y3-164y\n" ] } ], "source": [ "%%singular\n", "setring s;\n", "ideal J = fglm(r,I);\n", "J;" ] }, { "cell_type": "markdown", "id": "ada39047-b3c5-4bc9-be88-4e8bb4486dcc", "metadata": {}, "source": [ "We see that after conversion we get a triangular form. In symbolic computation, solving often means to rewrite the problem into a simpler form. One very typical symbolic computation is the computation of normal forms." ] }, { "cell_type": "code", "execution_count": 16, "id": "0fa67db9-5a9c-4e5f-8594-b3b386474dff", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "g[1]=20xy+15y2-12\n", "g[2]=4x2-4xy+y2-4\n", "g[3]=125y3+48x-164y\n" ] } ], "source": [ "%%singular\n", "setring r;\n", "g;" ] }, { "cell_type": "markdown", "id": "f3c87f47-1411-4d9b-928b-c35b0082ce91", "metadata": {}, "source": [ "With a Groebner basis `g` we can rewrite any polynomial\n", "modulo the ideal into a unique normal form:" ] }, { "cell_type": "code", "execution_count": 17, "id": "29aefaf0-190d-443d-aa34-2f78337364e6", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-y2+8/5\n" ] } ], "source": [ "%%singular\n", "reduce(x^2,g);" ] }, { "cell_type": "code", "execution_count": 18, "id": "26365f5e-119a-4d63-a00d-3f4c48c2ada1", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-3/4y2+3/5\n" ] } ], "source": [ "%%singular\n", "reduce(x*y,g);" ] }, { "cell_type": "code", "execution_count": 19, "id": "5a0f2599-f106-45a2-906e-678deac3af92", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "36/125x-48/125y\n" ] } ], "source": [ "%%singular\n", "reduce(x*y^2,g);" ] }, { "cell_type": "markdown", "id": "4fcfb451-cf00-44d9-a7d9-1d3e4c417d51", "metadata": {}, "source": [ "Monomials returned by `reduce` are 1, $x$, $y$, and $y^2$." ] }, { "cell_type": "markdown", "id": "ece32093-c6f4-420b-b698-fbe111cd7c69", "metadata": {}, "source": [ "For a polynomial system with finitely many solutions, say $N$,\n", "the number of different monomials that can appear in the\n", "outcome of `reduce` equals $N$." ] }, { "cell_type": "code", "execution_count": 20, "id": "ab614f6c-53b6-4c53-bfe6-a109587fc0f3", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "// ** loaded /usr/bin/../share/singular/LIB/rootsmr.lib (4.1.2.0,Feb_2019)\n", "// ** loaded /usr/bin/../share/singular/LIB/rootsur.lib (4.1.2.0,Feb_2019)\n", "// ** loaded /usr/bin/../share/singular/LIB/linalg.lib (4.1.2.0,Feb_2019)\n" ] } ], "source": [ "%%singular\n", "LIB \"rootsmr.lib\";" ] }, { "cell_type": "markdown", "id": "cbc967e3-ccfd-4eed-800d-ea82cf73c2c8", "metadata": {}, "source": [ "With the `rootsmr.lib` written by Enrique A. Tobis,\n", "we can compute the generalization of a companion matrix\n", "for several variables." ] }, { "cell_type": "markdown", "id": "51891931-cdc2-4687-b709-f6d831b7f140", "metadata": {}, "source": [ "A basis for the quotient ring is computed as" ] }, { "cell_type": "code", "execution_count": 21, "id": "7d5f75c2-6ae4-441e-882f-5f098c135f4b", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "B[1]=y2\n", "B[2]=x\n", "B[3]=y\n", "B[4]=1\n" ] } ], "source": [ "%%singular\n", "ideal B = qbase(I);\n", "B;" ] }, { "cell_type": "markdown", "id": "452bc7b9-e1fd-4417-93b5-d0d11c27098e", "metadata": {}, "source": [ "Because the system defined by `p` and `q`\n", "has four solutions, the computation modulo `p` and `q`\n", "defines a four dimensional quotient ring." ] }, { "cell_type": "code", "execution_count": 22, "id": "5a9d1f84-f9bd-4401-be55-02972d3fc629", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "0, -1, -3/4,0,\n", "36/125, 0, 0, 1,\n", "-48/125,0, 0, 0,\n", "0, 8/5,3/5, 0 \n" ] } ], "source": [ "%%singular\n", "matrix m = matmult(x,B,I);\n", "print(m);" ] }, { "cell_type": "markdown", "id": "a9e5c6f3-9e3c-46fd-9b32-1194efdfadac", "metadata": {}, "source": [ "The columns of the matrix `m` contain the normal forms\n", "of the multiples of the basis elements in `B` with `x`.\n", "Recall" ] }, { "cell_type": "code", "execution_count": 23, "id": "32137640-910e-498c-8806-809a4decf5ef", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "36/125x-48/125y\n" ] } ], "source": [ "%%singular\n", "reduce(x*y^2,g);" ] }, { "cell_type": "markdown", "id": "d783f724-2590-4b1a-be60-18d826e3ded6", "metadata": {}, "source": [ "We constructed the eigenvalue problem `x B = m B`.\n", "\n", "The eigenvalues of the multiplication matrix give\n", "the values for the `x` coordinate of the solutions." ] }, { "cell_type": "code", "execution_count": 24, "id": "f70a33e4-034b-4539-9f93-4718052feb05", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1]:\n", " _[1]=-6/5\n", " _[2]=-2/5\n", " _[3]=2/5\n", " _[4]=6/5\n", "[2]:\n", " 1,1,1,1\n" ] } ], "source": [ "%%singular\n", "eigenvals(m)" ] }, { "cell_type": "markdown", "id": "8e195e8b-2114-456d-b17a-34c8fb27bbd8", "metadata": {}, "source": [ "To avoid introducing multiplicities, one should take a random\n", "linear form instead of multiplying with `x`." ] }, { "cell_type": "markdown", "id": "9534048c-a4e7-4ca8-a93a-56ae282e13b7", "metadata": {}, "source": [ "# 3. Intersection Multiplicity" ] }, { "cell_type": "markdown", "id": "70eb85d9-7f9a-4056-b8ba-8abba80f7f14", "metadata": {}, "source": [ "Let ${\\mathbf z} \\in {\\mathbb C}^n$ be an isolated solution of $f({\\mathbf x}) = {\\mathbf 0}$.\n", "\n", "The intersection multiplicity $\\mu({\\mathbf z})$ is\n", "defined algebraically as the dimension of the local quotient ring:\n", "\n", "$$\n", " \\mu({\\mathbf z}) = {\\rm dim}_{\\mathbb C} \n", " \\left( {\\mathbb C}[{\\mathbf x}]_{\\langle x_1 - z_1, x_2 - z_2, \\ldots, \n", " x_n - z_n \\rangle} / \\langle f \\rangle \\right).\n", "$$" ] }, { "cell_type": "markdown", "id": "cb63af4c-bd1e-4461-ae9d-1bd77ef0f596", "metadata": {}, "source": [ "Consider $I = \\langle x^3 - y z , y^3 - x z , z^3 - x y \\rangle$." ] }, { "cell_type": "code", "execution_count": 25, "id": "8ee4b688-79e4-4653-8ea8-7c85c8348749", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "\n", "\n", "\n", "\n", "j[1]=xy-z3\n", "j[2]=xz-y3\n", "j[3]=yz-x3\n", "j[4]=x4-z4\n", "j[5]=y4-z4\n", "j[6]=z5\n" ] } ], "source": [ "%%singular\n", "ring R = 32003,(x,y,z),ds;\n", "poly f1 = x**3-y*z;\n", "poly f2 = y**3-x*z;\n", "poly f3 = z**3-x*y;\n", "ideal i = f1,f2,f3;\n", "ideal j = std(i);\n", "j;" ] }, { "cell_type": "code", "execution_count": 26, "id": "14eb4fa4-ce76-44f6-b880-2f99d78df49d", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "11\n" ] } ], "source": [ "%%singular\n", "mult(j)" ] } ], "metadata": { "kernelspec": { "display_name": "SageMath 9.5", "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.10.12" } }, "nbformat": 4, "nbformat_minor": 5 }