diff --git a/.ipynb_checkpoints/Apollonian Circle Packings-checkpoint.ipynb b/.ipynb_checkpoints/Apollonian Circle Packings-checkpoint.ipynb index d6c06f7..2c90e60 100644 --- a/.ipynb_checkpoints/Apollonian Circle Packings-checkpoint.ipynb +++ b/.ipynb_checkpoints/Apollonian Circle Packings-checkpoint.ipynb @@ -276,7 +276,8 @@ "def weyl_generators(matrix, alphas):\n", " retval = []\n", " for alpha in alphas:\n", - " retval.append(identity_matrix(len(alphas)) - 2 * alpha * alpha.transpose() * matrix)\n", + " scale_factor = (alpha.transpose() * matrix * alpha)[0][0]\n", + " retval.append(identity_matrix(len(alphas)) - 2 * alpha * alpha.transpose() * matrix / scale_factor)\n", " return retval" ] }, @@ -298,12 +299,10 @@ { "data": { "text/plain": [ - "[\n", - "[-1 0 0 1] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]\n", - "[ 0 1 0 0] [ 0 -1 0 1] [ 0 1 0 0] [ 0 1 0 0]\n", - "[ 0 0 1 0] [ 0 0 1 0] [ 0 0 -1 1] [ 0 0 1 0]\n", - "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [ 1 1 1 1/2]\n", - "]" + "[ 2 0 0 -1]\n", + "[ 0 2 0 -1]\n", + "[ 0 0 2 -1]\n", + "[ -1 -1 -1 1/2]" ] }, "execution_count": 12, @@ -312,14 +311,39 @@ } ], "source": [ - "S_i = weyl_generators(2 * M.inverse(), standard_basis(4))\n", - "S_i" + "4 * M.inverse()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[\n", + "[-1 0 0 1] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]\n", + "[ 0 1 0 0] [ 0 -1 0 1] [ 0 1 0 0] [ 0 1 0 0]\n", + "[ 0 0 1 0] [ 0 0 1 0] [ 0 0 -1 1] [ 0 0 1 0]\n", + "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [ 4 4 4 -1]\n", + "]" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "S_i = weyl_generators(4 * M.inverse(), standard_basis(4))\n", + "S_i" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, "outputs": [], "source": [ "S1 = S_i[0]\n", @@ -337,7 +361,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -346,7 +370,7 @@ "(7, 2, 4, 6)" ] }, - "execution_count": 14, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -358,7 +382,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -367,7 +391,7 @@ "(-1, 4, 4, 6)" ] }, - "execution_count": 15, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -378,7 +402,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -387,40 +411,13 @@ "(-1, 2, 2, 6)" ] }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "S3 * root" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For some reason, I have no idea why, $s_4$ doesn't seem to work. Instead this weird matrix does appear to work." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(-1, 2, 4, 8)" - ] - }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "S4 * root" + "S3 * root" ] }, { @@ -440,12 +437,7 @@ } ], "source": [ - "matrix([\n", - " [1, 0, 0, 0],\n", - " [0, 1, 0, 0],\n", - " [0, 0, 1, 0],\n", - " [4, 4, 4, -1]\n", - "]) * root" + "S4 * root" ] }, { @@ -484,7 +476,9 @@ { "cell_type": "code", "execution_count": 20, - "metadata": {}, + "metadata": { + "scrolled": true + }, "outputs": [ { "name": "stdout", @@ -594,7 +588,7 @@ " [0, 2, 0, -1],\n", "])\n", "\n", - "Wc.transpose().echelon_form()" + "Wc.transpose().rref()" ] }, { @@ -665,10 +659,10 @@ { "data": { "text/plain": [ - "[ 5 -3 -3 -3]\n", - "[-3 5 -3 -3]\n", - "[-3 -3 5 -3]\n", - "[-3 -3 -3 5]" + "[ 2 -6/5 -6/5 -6/5]\n", + "[-6/5 2 -6/5 -6/5]\n", + "[-6/5 -6/5 2 -6/5]\n", + "[-6/5 -6/5 -6/5 2]" ] }, "execution_count": 25, @@ -677,7 +671,7 @@ } ], "source": [ - "32 * m.inverse()" + "32 * m.inverse() * 2/5" ] }, { @@ -767,10 +761,15 @@ "data": { "text/plain": [ "[\n", - "[-1 6 6 6] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]\n", - "[ 0 1 0 0] [ 6 -1 6 6] [ 0 1 0 0] [ 0 1 0 0]\n", - "[ 0 0 1 0] [ 0 0 1 0] [ 6 6 -1 6] [ 0 0 1 0]\n", - "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [ 6 6 6 -1]\n", + "[ -1 6/5 6/5 6/5] [ 1 0 0 0] [ 1 0 0 0]\n", + "[ 0 1 0 0] [6/5 -1 6/5 6/5] [ 0 1 0 0]\n", + "[ 0 0 1 0] [ 0 0 1 0] [6/5 6/5 -1 6/5]\n", + "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1],\n", + "\n", + "[ 1 0 0 0]\n", + "[ 0 1 0 0]\n", + "[ 0 0 1 0]\n", + "[6/5 6/5 6/5 -1]\n", "]" ] }, @@ -780,7 +779,7 @@ } ], "source": [ - "S_i = weyl_generators(m, standard_basis(4))\n", + "S_i = weyl_generators(m.inverse(), standard_basis(4))\n", "S_i" ] }, @@ -794,14 +793,14 @@ { "data": { "text/plain": [ - "[ 1 -3 -3 -3 -1 -1 -1 -5]\n", - "[-3 1 -3 -3 -1 -1 -5 -1]\n", - "[-3 -3 1 -3 -1 -5 -1 -1]\n", - "[-3 -3 -3 1 -5 -1 -1 -1]\n", - "[-1 -1 -1 -5 1 -3 -3 -3]\n", - "[-1 -1 -5 -1 -3 1 -3 -3]\n", - "[-1 -5 -1 -1 -3 -3 1 -3]\n", - "[-5 -1 -1 -1 -3 -3 -3 1]" + "[ 1 0 0 0 1/2 1/2 1/2 -1/2]\n", + "[ 0 1 0 0 1/2 1/2 -1/2 1/2]\n", + "[ 0 0 1 0 1/2 -1/2 1/2 1/2]\n", + "[ 0 0 0 1 -1/2 1/2 1/2 1/2]\n", + "[ 0 0 0 0 0 0 0 0]\n", + "[ 0 0 0 0 0 0 0 0]\n", + "[ 0 0 0 0 0 0 0 0]\n", + "[ 0 0 0 0 0 0 0 0]" ] }, "execution_count": 30, @@ -810,7 +809,7 @@ } ], "source": [ - "Wc * P * Wc.transpose()" + "(Wc * P * Wc.transpose()).rref()" ] }, { @@ -828,6 +827,7 @@ "outputs": [], "source": [ "def quadform_from_root(root_matrix):\n", + " n = root_matrix.dimensions()[1]\n", " P = matrix([\n", " [0, -1/2, 0, 0],\n", " [-1/2, 0, 0, 0],\n", @@ -836,10 +836,13 @@ " ])\n", " \n", " # step 1: find linear relation between coords\n", - " relation = root_matrix.transpose().rref() * vector([ var('b' + str(i)) for i in range(1, root_matrix.dimensions()[0] + 1)])\n", - " \n", + " relations_temp = vector([ var('b' + str(i)) for i in range(1, n + 1)]) * root_matrix.transpose().rref()\n", + " relations = []\n", + " for i, expr in enumerate(relations_temp):\n", + " relations.append(var('b' + str(i + 1)) == expr)\n", + " \n", " # step 2: find matrix of quadratic form\n", - " W = root_matrix[0:4]\n", + " W = root_matrix[-4:]\n", " M = W * P * W.transpose()\n", " \n", " # step 3: repeat with arbitrary matrix\n", @@ -853,49 +856,156 @@ " ])\n", " D = factor(simplify(expand(W2.transpose() * M.inverse() * W2)))\n", " \n", - " return relation, M.inverse(), D[1][1]" + " return relations[4:], M.inverse(), D[1][1]" ] }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 122, "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "(2*b1 + b5 + b6 + b7 - b8, 2*b2 + b5 + b6 - b7 + b8, 2*b3 + b5 - b6 + b7 + b8, 2*b4 - b5 + b6 + b7 + b8)\n", - "[ 5 -3 -3 -3]\n", - "[-3 5 -3 -3]\n", - "[-3 -3 5 -3]\n", - "[-3 -3 -3 5]\n", - "5*b1^2 - 6*b1*b2 + 5*b2^2 - 6*b1*b3 - 6*b2*b3 + 5*b3^2 - 6*b1*b4 - 6*b2*b4 - 6*b3*b4 + 5*b4^2\n" - ] + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[2 \\, b_{5} = b_{1} + b_{2} + b_{3} - b_{4}, 2 \\, b_{6} = b_{1} + b_{2} - b_{3} + b_{4}, 2 \\, b_{7} = b_{1} - b_{2} + b_{3} + b_{4}, 2 \\, b_{8} = -b_{1} + b_{2} + b_{3} + b_{4}\\right]\n", + "\\end{math}" + ], + "text/plain": [ + "[2*b5 == b1 + b2 + b3 - b4,\n", + " 2*b6 == b1 + b2 - b3 + b4,\n", + " 2*b7 == b1 - b2 + b3 + b4,\n", + " 2*b8 == -b1 + b2 + b3 + b4]" + ] + }, + "metadata": {}, + "output_type": "display_data" }, { "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", + "5 & -3 & -3 & -3 \\\\\n", + "-3 & 5 & -3 & -3 \\\\\n", + "-3 & -3 & 5 & -3 \\\\\n", + "-3 & -3 & -3 & 5\n", + "\\end{array}\\right)\n", + "\\end{math}" + ], + "text/plain": [ + "[ 5 -3 -3 -3]\n", + "[-3 5 -3 -3]\n", + "[-3 -3 5 -3]\n", + "[-3 -3 -3 5]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}5 \\, b_{1}^{2} - 6 \\, b_{1} b_{2} + 5 \\, b_{2}^{2} - 6 \\, b_{1} b_{3} - 6 \\, b_{2} b_{3} + 5 \\, b_{3}^{2} - 6 \\, b_{1} b_{4} - 6 \\, b_{2} b_{4} - 6 \\, b_{3} b_{4} + 5 \\, b_{4}^{2}\n", + "\\end{math}" + ], + "text/plain": [ + "5*b1^2 - 6*b1*b2 + 5*b2^2 - 6*b1*b3 - 6*b2*b3 + 5*b3^2 - 6*b1*b4 - 6*b2*b4 - 6*b3*b4 + 5*b4^2" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", + "-1 & \\frac{6}{5} & \\frac{6}{5} & \\frac{6}{5} \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "\\frac{6}{5} & -1 & \\frac{6}{5} & \\frac{6}{5} \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "\\frac{6}{5} & \\frac{6}{5} & -1 & \\frac{6}{5} \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "\\frac{6}{5} & \\frac{6}{5} & \\frac{6}{5} & -1\n", + "\\end{array}\\right)\\right]\n", + "\\end{math}" + ], "text/plain": [ "[\n", - "[-9 6 6 6] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]\n", - "[ 0 1 0 0] [ 6 -9 6 6] [ 0 1 0 0] [ 0 1 0 0]\n", - "[ 0 0 1 0] [ 0 0 1 0] [ 6 6 -9 6] [ 0 0 1 0]\n", - "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [ 6 6 6 -9]\n", + "[ -1 6/5 6/5 6/5] [ 1 0 0 0] [ 1 0 0 0]\n", + "[ 0 1 0 0] [6/5 -1 6/5 6/5] [ 0 1 0 0]\n", + "[ 0 0 1 0] [ 0 0 1 0] [6/5 6/5 -1 6/5]\n", + "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1],\n", + "\n", + "[ 1 0 0 0]\n", + "[ 0 1 0 0]\n", + "[ 0 0 1 0]\n", + "[6/5 6/5 6/5 -1]\n", "]" ] }, - "execution_count": 32, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" } ], "source": [ "# cubical\n", "relation, mat, equation = quadform_from_root(Wc)\n", - "print(2 * relation)\n", - "print(32 * mat)\n", - "print(32 * equation)\n", - "weyl_generators(32 * mat, standard_basis(4))" + "show([2 * eq for eq in relation])\n", + "show(32 * mat)\n", + "show(32 * equation)\n", + "show(weyl_generators(mat, standard_basis(4)))" ] }, { @@ -904,31 +1014,130 @@ "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "(b1 + b5 + b6, b2 - b5, b3 - b6, b4 + b5 + b6)\n", - "[ 1 -2 -2 -1]\n", - "[-2 4 0 -2]\n", - "[-2 0 4 -2]\n", - "[-1 -2 -2 1]\n", - "b1^2 - 4*b1*b2 + 4*b2^2 - 4*b1*b3 + 4*b3^2 - 2*b1*b4 - 4*b2*b4 - 4*b3*b4 + b4^2\n" - ] + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[b_{5} = b_{1} - b_{2} + b_{4}, b_{6} = b_{1} - b_{3} + b_{4}\\right]\n", + "\\end{math}" + ], + "text/plain": [ + "[b5 == b1 - b2 + b4, b6 == b1 - b3 + b4]" + ] + }, + "metadata": {}, + "output_type": "display_data" }, { "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", + "1 & -2 & -2 & -1 \\\\\n", + "-2 & 4 & 0 & -2 \\\\\n", + "-2 & 0 & 4 & -2 \\\\\n", + "-1 & -2 & -2 & 1\n", + "\\end{array}\\right)\n", + "\\end{math}" + ], + "text/plain": [ + "[ 1 -2 -2 -1]\n", + "[-2 4 0 -2]\n", + "[-2 0 4 -2]\n", + "[-1 -2 -2 1]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}b_{1}^{2} - 4 \\, b_{1} b_{2} + 4 \\, b_{2}^{2} - 4 \\, b_{1} b_{3} + 4 \\, b_{3}^{2} - 2 \\, b_{1} b_{4} - 4 \\, b_{2} b_{4} - 4 \\, b_{3} b_{4} + b_{4}^{2}\n", + "\\end{math}" + ], + "text/plain": [ + "b1^2 - 4*b1*b2 + 4*b2^2 - 4*b1*b3 + 4*b3^2 - 2*b1*b4 - 4*b2*b4 - 4*b3*b4 + b4^2" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", + "-1 & 4 & 4 & 2 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "1 & -1 & 0 & 1 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "1 & 0 & -1 & 1 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "2 & 4 & 4 & -1\n", + "\\end{array}\\right)\\right]\n", + "\\end{math}" + ], "text/plain": [ "[\n", "[-1 4 4 2] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]\n", - "[ 0 1 0 0] [ 4 -7 0 4] [ 0 1 0 0] [ 0 1 0 0]\n", - "[ 0 0 1 0] [ 0 0 1 0] [ 4 0 -7 4] [ 0 0 1 0]\n", + "[ 0 1 0 0] [ 1 -1 0 1] [ 0 1 0 0] [ 0 1 0 0]\n", + "[ 0 0 1 0] [ 0 0 1 0] [ 1 0 -1 1] [ 0 0 1 0]\n", "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [ 2 4 4 -1]\n", "]" ] }, - "execution_count": 33, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" } ], "source": [ @@ -941,10 +1150,10 @@ " [4, 2, 2*sqrt(2), 1],\n", " [7, 1, 2*sqrt(2), 0],\n", "]))\n", - "print(relation)\n", - "print(8 * mat)\n", - "print(8 * equation)\n", - "weyl_generators(8 * mat, standard_basis(4))" + "show(relation)\n", + "show(8 * mat)\n", + "show(8 * equation)\n", + "show(weyl_generators(8 * mat, standard_basis(4)))" ] }, { @@ -953,19 +1162,119 @@ "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "(b1, b2, b3, b4)\n", - "[ 1 -1 -1 -1]\n", - "[-1 1 -1 -1]\n", - "[-1 -1 1 -1]\n", - "[-1 -1 -1 1]\n", - "b1^2 - 2*b1*b2 + b2^2 - 2*b1*b3 - 2*b2*b3 + b3^2 - 2*b1*b4 - 2*b2*b4 - 2*b3*b4 + b4^2\n" - ] + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\right]\n", + "\\end{math}" + ], + "text/plain": [ + "[]" + ] + }, + "metadata": {}, + "output_type": "display_data" }, { "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", + "1 & -1 & -1 & -1 \\\\\n", + "-1 & 1 & -1 & -1 \\\\\n", + "-1 & -1 & 1 & -1 \\\\\n", + "-1 & -1 & -1 & 1\n", + "\\end{array}\\right)\n", + "\\end{math}" + ], + "text/plain": [ + "[ 1 -1 -1 -1]\n", + "[-1 1 -1 -1]\n", + "[-1 -1 1 -1]\n", + "[-1 -1 -1 1]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}b_{1}^{2} - 2 \\, b_{1} b_{2} + b_{2}^{2} - 2 \\, b_{1} b_{3} - 2 \\, b_{2} b_{3} + b_{3}^{2} - 2 \\, b_{1} b_{4} - 2 \\, b_{2} b_{4} - 2 \\, b_{3} b_{4} + b_{4}^{2}\n", + "\\end{math}" + ], + "text/plain": [ + "b1^2 - 2*b1*b2 + b2^2 - 2*b1*b3 - 2*b2*b3 + b3^2 - 2*b1*b4 - 2*b2*b4 - 2*b3*b4 + b4^2" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", + "-1 & 2 & 2 & 2 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "2 & -1 & 2 & 2 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "2 & 2 & -1 & 2 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "2 & 2 & 2 & -1\n", + "\\end{array}\\right)\\right]\n", + "\\end{math}" + ], "text/plain": [ "[\n", "[-1 2 2 2] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]\n", @@ -975,9 +1284,8 @@ "]" ] }, - "execution_count": 34, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" } ], "source": [ @@ -988,17 +1296,853 @@ " [-1, 1, 0, 0],\n", " [3, 1, 2, 0]\n", "]))\n", - "print(relation)\n", - "print(4 * mat)\n", - "print(4 * equation)\n", - "weyl_generators(4 * mat, standard_basis(4))" + "show(relation)\n", + "show(4 * mat)\n", + "show(4 * equation)\n", + "show(weyl_generators(4 * mat, standard_basis(4)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "I suspect that it is highly dependent on the order of the circles in the root. Interestingly, it looks like the only relation it was able to deduce for the tetrahedral packing is $b_1, b_2, b_3, b_4 = 0$, meaning there is no null space, as we'd expect. The octahedral quadratic form we get is very different, which isn't surprising, I guess, since this is a very different coordinate system, but I'm not sure if it's right. It feels very strange, since it's only really two dimensional, rather than four, and it doesn't quite look like the equations hold up. But it does absolutely work for the tetrahedral packing, which is awesome." + "# $n$-Gon Base Pyramid\n", + "\n", + "The goal here is to find the quadratic form for an arbitrary $n$-gon base pyramid. The key to the whole process is a magic formula Dylan found for the bilinear form between two circles in an $n$-gon base pyramidal packing, namely $$\n", + " \\frac{1 - \\cos\\left(\\frac{2\\pi}{n}\\right) - 4\\sin^2\\left(\\frac{p\\pi}{n}\\right)}{1-\\cos\\left(\\frac{2\\pi}{n}\\right)}\n", + "$$\n", + "\n", + "where $p$ is how many circles are between the two circles in question. If we are finding the bilinear form between the central circle and any other circle it will always be $-1$ so we don't need to worry about that case." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "# function to compute W^T*P*W for n-gon pyramidal packing\n", + "def wmatrix(n):\n", + " vals = []\n", + " for i in range(n+1):\n", + " row = []\n", + " for j in range(n+1):\n", + " if i == j: # same vertex bilinear form'd with itself, so 1\n", + " row.append(1)\n", + " elif i ==0 or j == 0: # vertex bilinear form'd with special point, so tangent and therefore -1\n", + " row.append(-1)\n", + " else:\n", + " p = abs(i - j) # otherwise Dylan's crazy formula\n", + " row.append(\n", + " (1 - cos(2 * pi / n) - 4 * sin(pi * p / n)^2) / (1 - cos(2 * pi / n))\n", + " )\n", + " vals.append(row)\n", + " return matrix(vals)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [], + "source": [ + "# just convenience function for quadratic forms\n", + "def qform(matrix, vector):\n", + " return vector * matrix * vector" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [], + "source": [ + "def linear_relations_and_quadratic_form_from_wtpw(mat, indices=None):\n", + " if indices is None:\n", + " indices = range(mat.dimensions()[0])\n", + " n = mat.dimensions()[0]\n", + " \n", + " # work out initial relations\n", + " relations_temp = vector([ var('b' + str(i)) for i in range(1, n + 1) ]) * mat.transpose().rref()\n", + " relations = []\n", + " for i in range(n):\n", + " relations.append(var('b' + str(i + 1)) == relations_temp[i])\n", + " \n", + " # rewrite the relations in terms of the variables we care about, depends on the step\n", + " targets = [ var('b' + str(i)) for i in indices[4:] ]\n", + " relations = solve(relations, *targets)[0]\n", + " \n", + " # find the matrix corresponding to the quadratic form, picking the appropriate rows from the matrix\n", + " mat = matrix([\n", + " [ mat[i - 1][j - 1] for j in indices[:4] ] for i in indices[:4]\n", + " ])\n", + "\n", + " Q = mat.inverse()\n", + " \n", + " # find the quadratic form in variables; proper units will satisfy this being equal to zero\n", + " vec = vector([ var('b' + str(i)) for i in indices[:4] ])\n", + " nqform = vec * Q * vec\n", + " \n", + " return relations, Q, expand(nqform)" + ] + }, + { + "cell_type": "code", + "execution_count": 123, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ 9 -1 -1 -1]\n", + "[-1 1 -1 -1]\n", + "[-1 -1 1 -1]\n", + "[-1 -1 -1 1]\n" + ] + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}9 \\, b_{1}^{2} - 2 \\, b_{1} b_{3} + b_{3}^{2} - 2 \\, b_{1} b_{5} - 2 \\, b_{3} b_{5} + b_{5}^{2} - 2 \\, b_{1} b_{7} - 2 \\, b_{3} b_{7} - 2 \\, b_{5} b_{7} + b_{7}^{2}\n", + "\\end{math}" + ], + "text/plain": [ + "9*b1^2 - 2*b1*b3 + b3^2 - 2*b1*b5 - 2*b3*b5 + b5^2 - 2*b1*b7 - 2*b3*b7 - 2*b5*b7 + b7^2" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[3 \\, b_{2} = 2 \\, b_{3} - b_{5} + 2 \\, b_{7}, 3 \\, b_{4} = 2 \\, b_{3} + 2 \\, b_{5} - b_{7}, 3 \\, b_{6} = -b_{3} + 2 \\, b_{5} + 2 \\, b_{7}\\right]\n", + "\\end{math}" + ], + "text/plain": [ + "[3*b2 == 2*b3 - b5 + 2*b7, 3*b4 == 2*b3 + 2*b5 - b7, 3*b6 == -b3 + 2*b5 + 2*b7]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", + "-1 & \\frac{2}{9} & \\frac{2}{9} & \\frac{2}{9} \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "2 & -1 & 2 & 2 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "2 & 2 & -1 & 2 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "2 & 2 & 2 & -1\n", + "\\end{array}\\right)\\right]\n", + "\\end{math}" + ], + "text/plain": [ + "[\n", + "[ -1 2/9 2/9 2/9] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]\n", + "[ 0 1 0 0] [ 2 -1 2 2] [ 0 1 0 0] [ 0 1 0 0]\n", + "[ 0 0 1 0] [ 0 0 1 0] [ 2 2 -1 2] [ 0 0 1 0]\n", + "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [ 2 2 2 -1]\n", + "]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "relations, Q, nqform = linear_relations_and_quadratic_form_from_wtpw(wmatrix(6), [1, 3, 5, 7, 2, 4, 6])\n", + "print(12 * Q)\n", + "show(12 * nqform)\n", + "show([3 * rel for rel in relations])\n", + "show(weyl_generators(12 * Q, standard_basis(4)))" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [], + "source": [ + "# function to compute the linear relations and quadratic formula for an ngon base pyramid\n", + "# the circles will be numbered 1 in the center, then 2 through n winding around the circle by step, so\n", + "# for n = 4 with step = 1, we have\n", + "# b3\n", + "# b4 b1 b2\n", + "# b5\n", + "# and the quadratic form is in terms of b1, b2, b3, and b4\n", + "# and for n = 6 with step = 2, we have\n", + "# b4 b3\n", + "# b5 b1 b2\n", + "# b6 b7\n", + "# and the quadratic form is in terms of b1, b3, b5, and b7\n", + "def ngon_linear_relations_and_quadratic_form(n, step=1):\n", + " mat = wmatrix(n)\n", + " \n", + " # work out initial relations\n", + " relations_temp = vector([ var('b' + str(i)) for i in range(1, n + 2) ]) * mat.transpose().rref()\n", + " relations = []\n", + " for i in range(4, n + 1):\n", + " relations.append(var('b' + str(i + 1)) == relations_temp[i])\n", + " \n", + " # rewrite the relations in terms of the variables we care about, depends on the step\n", + " shuffled = (list(range(1, n + 2)) * step)[::step]\n", + " targets = [ var('b' + str(i)) for i in shuffled[4:] ]\n", + " relations = solve(relations, *targets)[0]\n", + " \n", + " # find the matrix corresponding to the quadratic form, picking the appropriate rows from the matrix\n", + " Q = mat[:4*step:step,:4*step:step].inverse()\n", + " \n", + " # find the quadratic form in variables; proper units will satisfy this being equal to zero\n", + " nqform = qform(Q, vector([ var('b' + str(i)) for i in range(1, 5) ]))\n", + " \n", + " return relations, Q, expand(nqform)" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[b_{5} = -b_{3} {\\left(\\sqrt{2} + 1\\right)} + b_{4} {\\left(\\sqrt{2} + 1\\right)} + b_{2}, b_{6} = b_{4} {\\left(\\sqrt{2} + 2\\right)} + b_{2} {\\left(\\sqrt{2} + 1\\right)} - 2 \\, b_{3} {\\left(\\sqrt{2} + 1\\right)}, b_{7} = -b_{3} {\\left(2 \\, \\sqrt{2} + 3\\right)} + b_{2} {\\left(\\sqrt{2} + 2\\right)} + b_{4} {\\left(\\sqrt{2} + 2\\right)}, b_{8} = b_{2} {\\left(\\sqrt{2} + 2\\right)} - 2 \\, b_{3} {\\left(\\sqrt{2} + 1\\right)} + b_{4} {\\left(\\sqrt{2} + 1\\right)}, b_{9} = b_{2} {\\left(\\sqrt{2} + 1\\right)} - b_{3} {\\left(\\sqrt{2} + 1\\right)} + b_{4}\\right]\n", + "\\end{math}" + ], + "text/plain": [ + "[b5 == -b3*(sqrt(2) + 1) + b4*(sqrt(2) + 1) + b2,\n", + " b6 == b4*(sqrt(2) + 2) + b2*(sqrt(2) + 1) - 2*b3*(sqrt(2) + 1),\n", + " b7 == -b3*(2*sqrt(2) + 3) + b2*(sqrt(2) + 2) + b4*(sqrt(2) + 2),\n", + " b8 == b2*(sqrt(2) + 2) - 2*b3*(sqrt(2) + 1) + b4*(sqrt(2) + 1),\n", + " b9 == b2*(sqrt(2) + 1) - b3*(sqrt(2) + 1) + b4]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", + "-\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 1 & -2 & -\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 3 & -2 \\\\\n", + "-2 & -\\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} & -2 & \\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} \\\\\n", + "-\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 3 & -2 & -\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 1 & -2 \\\\\n", + "-2 & \\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} & -2 & -\\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1}\n", + "\\end{array}\\right)\n", + "\\end{math}" + ], + "text/plain": [ + "[ -(sqrt(2) + 2)/(sqrt(2) - 2) + 1 -2 -(sqrt(2) + 2)/(sqrt(2) - 2) - 3 -2]\n", + "[ -2 -4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1) -2 4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1)]\n", + "[ -(sqrt(2) + 2)/(sqrt(2) - 2) - 3 -2 -(sqrt(2) + 2)/(sqrt(2) - 2) + 1 -2]\n", + "[ -2 4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1) -2 -4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1)]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}b_{1}^{2} - 4 \\, b_{1} b_{2} - 6 \\, b_{1} b_{3} - 4 \\, b_{2} b_{3} + b_{3}^{2} - 4 \\, b_{1} b_{4} - 4 \\, b_{3} b_{4} - \\frac{\\sqrt{2} b_{1}^{2}}{\\sqrt{2} - 2} - \\frac{2 \\, \\sqrt{2} b_{1} b_{3}}{\\sqrt{2} - 2} - \\frac{\\sqrt{2} b_{3}^{2}}{\\sqrt{2} - 2} - \\frac{2 \\, b_{1}^{2}}{\\sqrt{2} - 2} - \\frac{4 \\, b_{1} b_{3}}{\\sqrt{2} - 2} - \\frac{2 \\, b_{3}^{2}}{\\sqrt{2} - 2} - \\frac{4 \\, b_{2}^{2}}{\\frac{\\sqrt{2}}{\\sqrt{2} - 2} + \\frac{2}{\\sqrt{2} - 2} - 1} + \\frac{8 \\, b_{2} b_{4}}{\\frac{\\sqrt{2}}{\\sqrt{2} - 2} + \\frac{2}{\\sqrt{2} - 2} - 1} - \\frac{4 \\, b_{4}^{2}}{\\frac{\\sqrt{2}}{\\sqrt{2} - 2} + \\frac{2}{\\sqrt{2} - 2} - 1}\n", + "\\end{math}" + ], + "text/plain": [ + "b1^2 - 4*b1*b2 - 6*b1*b3 - 4*b2*b3 + b3^2 - 4*b1*b4 - 4*b3*b4 - sqrt(2)*b1^2/(sqrt(2) - 2) - 2*sqrt(2)*b1*b3/(sqrt(2) - 2) - sqrt(2)*b3^2/(sqrt(2) - 2) - 2*b1^2/(sqrt(2) - 2) - 4*b1*b3/(sqrt(2) - 2) - 2*b3^2/(sqrt(2) - 2) - 4*b2^2/(sqrt(2)/(sqrt(2) - 2) + 2/(sqrt(2) - 2) - 1) + 8*b2*b4/(sqrt(2)/(sqrt(2) - 2) + 2/(sqrt(2) - 2) - 1) - 4*b4^2/(sqrt(2)/(sqrt(2) - 2) + 2/(sqrt(2) - 2) - 1)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", + "-1 & -\\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} & -\\frac{2 \\, {\\left(\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 3\\right)}}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} & -\\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "-\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 1 & -1 & -\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 1 & 2 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "-\\frac{2 \\, {\\left(\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 3\\right)}}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} & -\\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} & -1 & -\\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "-\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 1 & 2 & -\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 1 & -1\n", + "\\end{array}\\right)\\right]\n", + "\\end{math}" + ], + "text/plain": [ + "[\n", + "[ -1 -4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1) -2*((sqrt(2) + 2)/(sqrt(2) - 2) + 3)/((sqrt(2) + 2)/(sqrt(2) - 2) - 1) -4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1)] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]\n", + "[ 0 1 0 0] [-(sqrt(2) + 2)/(sqrt(2) - 2) + 1 -1 -(sqrt(2) + 2)/(sqrt(2) - 2) + 1 2] [ 0 1 0 0] [ 0 1 0 0]\n", + "[ 0 0 1 0] [ 0 0 1 0] [-2*((sqrt(2) + 2)/(sqrt(2) - 2) + 3)/((sqrt(2) + 2)/(sqrt(2) - 2) - 1) -4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1) -1 -4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1)] [ 0 0 1 0]\n", + "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [-(sqrt(2) + 2)/(sqrt(2) - 2) + 1 2 -(sqrt(2) + 2)/(sqrt(2) - 2) + 1 -1]\n", + "]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "relations, Q, nqform = ngon_linear_relations_and_quadratic_form(8)\n", + "\n", + "show(relations)\n", + "show(8 * Q)\n", + "show(8 * nqform)\n", + "show(weyl_generators(8 * Q, standard_basis(4)))" + ] + }, + { + "cell_type": "code", + "execution_count": 163, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[3 \\, b_{2} = 2 \\, b_{3} - b_{5} + 2 \\, b_{7}, 3 \\, b_{4} = 2 \\, b_{3} + 2 \\, b_{5} - b_{7}, 3 \\, b_{6} = -b_{3} + 2 \\, b_{5} + 2 \\, b_{7}\\right]\n", + "\\end{math}" + ], + "text/plain": [ + "[3*b2 == 2*b3 - b5 + 2*b7, 3*b4 == 2*b3 + 2*b5 - b7, 3*b6 == -b3 + 2*b5 + 2*b7]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", + "9 & -1 & -1 & -1 \\\\\n", + "-1 & 1 & -1 & -1 \\\\\n", + "-1 & -1 & 1 & -1 \\\\\n", + "-1 & -1 & -1 & 1\n", + "\\end{array}\\right)\n", + "\\end{math}" + ], + "text/plain": [ + "[ 9 -1 -1 -1]\n", + "[-1 1 -1 -1]\n", + "[-1 -1 1 -1]\n", + "[-1 -1 -1 1]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}9 \\, b_{1}^{2} - 2 \\, b_{1} b_{2} + b_{2}^{2} - 2 \\, b_{1} b_{3} - 2 \\, b_{2} b_{3} + b_{3}^{2} - 2 \\, b_{1} b_{4} - 2 \\, b_{2} b_{4} - 2 \\, b_{3} b_{4} + b_{4}^{2}\n", + "\\end{math}" + ], + "text/plain": [ + "9*b1^2 - 2*b1*b2 + b2^2 - 2*b1*b3 - 2*b2*b3 + b3^2 - 2*b1*b4 - 2*b2*b4 - 2*b3*b4 + b4^2" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", + "-1 & \\frac{2}{9} & \\frac{2}{9} & \\frac{2}{9} \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "2 & -1 & 2 & 2 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "2 & 2 & -1 & 2 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "2 & 2 & 2 & -1\n", + "\\end{array}\\right)\\right]\n", + "\\end{math}" + ], + "text/plain": [ + "[\n", + "[ -1 2/9 2/9 2/9] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]\n", + "[ 0 1 0 0] [ 2 -1 2 2] [ 0 1 0 0] [ 0 1 0 0]\n", + "[ 0 0 1 0] [ 0 0 1 0] [ 2 2 -1 2] [ 0 0 1 0]\n", + "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [ 2 2 2 -1]\n", + "]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\frac{2}{9} \\, b_{2} + \\frac{2}{9} \\, b_{3} + \\frac{2}{9} \\, b_{4}\n", + "\\end{math}" + ], + "text/plain": [ + "2/9*b2 + 2/9*b3 + 2/9*b4" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "relations, Q, nqform = ngon_linear_relations_and_quadratic_form(6, 2)\n", + "\n", + "show([3 * eq for eq in relations])\n", + "show(12 * Q)\n", + "show(12 * nqform)\n", + "show(weyl_generators(12 * Q, standard_basis(4)))\n", + "\n", + "sols = solve(nqform, b1)\n", + "s1 = sols[0].rhs()\n", + "s2 = sols[1].rhs()\n", + "show(s1 + s2)" + ] + }, + { + "cell_type": "code", + "execution_count": 164, + "metadata": {}, + "outputs": [], + "source": [ + "class Circle:\n", + " def __init__(self, bt, b, h1, h2):\n", + " self.bt = bt\n", + " self.b = b\n", + " self.h1 = h1\n", + " self.h2 = h2\n", + " self.vec = vector(bt, b, h1, h2)\n", + " \n", + " def __mul__(self, other):\n", + " self.vec *= other\n", + " self.bt = self.vec[0]\n", + " self.b = self.vec[1]\n", + " self.h1 = self.vec[2]\n", + " self.h2 = self.vec[3]\n", + " \n", + " def draw(self, plt):\n", + " \n", + " \n", + "def from_xyr(x, y, r):\n", + " b = 1/r\n", + " h1 = b * x\n", + " h2 = b * y\n", + " return Circle((1 - h1^2 - h2^2) / b, b, h1, h2)" + ] + }, + { + "cell_type": "code", + "execution_count": 158, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(-2/3*sqrt(3), -1)\t1/3*sqrt(3)\n", + "(-1/6*sqrt(3), -1)\t1/6*sqrt(3)\n", + "(0, 1)\tsqrt(3)\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "Graphics object consisting of 14 graphics primitives" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "b1, b2, b3, b4, b5, b6, b7 = var('b1 b2 b3 b4 b5 b6 b7')\n", + "test = [relation.subs([b1 == 0, b2 == 1, b3 == 0, b4 == 1]) for relation in relations]\n", + "\n", + "plt = line([(-2*sqrt(3), 1), (2*sqrt(3), 1)])\n", + "plt += line([(-2*sqrt(3), -1), (2*sqrt(3), -1)])\n", + "plt += circle((-sqrt(3), 0), 1)\n", + "plt += circle((-1/3 * sqrt(3), -2/3), 1/3)\n", + "plt += circle((0, -3/4), 1/4)\n", + "plt += circle((1/3 * sqrt(3), -2/3), 1/3)\n", + "plt += circle((sqrt(3), 0), 1)\n", + "\n", + "plt += line([(-sqrt(3), 2*sqrt(3)), (-sqrt(3), -2*sqrt(3))], rgbcolor=(1,0,0))\n", + "plt += line([( sqrt(3), 2*sqrt(3)), ( sqrt(3), -2*sqrt(3))], rgbcolor=(1,0,0))\n", + "\n", + "x, y = var('x y')\n", + "c1 = (x + sqrt(3))^2 + y^2 == 1\n", + "c2 = (x + 1/3*sqrt(3))^2 + (y + 2/3)^2 == 1/9\n", + "c3 = x^2 + (y + 3/4)^2 == 1/16\n", + "i1 = solve([c1, c2], [x, y])[0]\n", + "x1 = i1[0].rhs()\n", + "y1 = i1[1].rhs()\n", + "i2 = solve([c2, c3], [x, y])[0]\n", + "x2 = i2[0].rhs()\n", + "y2 = i2[1].rhs()\n", + "\n", + "x, y, r = circle_from_points((-sqrt(3), -1), (-1/3*sqrt(3), -1), (x1, y1))\n", + "print('({}, {})\\t{}'.format(x, y, r))\n", + "\n", + "plt += circle((x, y), r, rgbcolor=(1,0,0))\n", + "plt += circle((-x, y), r, rgbcolor=(1,0,0))\n", + "\n", + "x, y, r = circle_from_points((-1/3*sqrt(3), -1), (0, -1), (x2, y2))\n", + "print('({}, {})\\t{}'.format(x, y, r))\n", + "\n", + "plt += circle((x, y), r, rgbcolor=(1,0,0))\n", + "plt += circle((-x, y), r, rgbcolor=(1,0,0))\n", + "\n", + "x, y, r = circle_from_points((-sqrt(3), 1), (x1, y1), (sqrt(3), 1))\n", + "print('({}, {})\\t{}'.format(x, y, r))\n", + "\n", + "plt += circle((x, y), r, rgbcolor=(1, 0, 0))\n", + "\n", + "show(plt)" + ] + }, + { + "cell_type": "code", + "execution_count": 152, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[b_{5} = b_{2} - 2 \\, b_{3} + 2 \\, b_{4}, b_{6} = 2 \\, b_{2} - 3 \\, b_{3} + 2 \\, b_{4}, b_{7} = 2 \\, b_{2} - 2 \\, b_{3} + b_{4}\\right]\n", + "\\end{math}" + ], + "text/plain": [ + "[b5 == b2 - 2*b3 + 2*b4, b6 == 2*b2 - 3*b3 + 2*b4, b7 == 2*b2 - 2*b3 + b4]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}6 \\, b_{1}^{2} - 4 \\, b_{1} b_{2} + \\frac{2}{3} \\, b_{2}^{2} + 4 \\, b_{1} b_{3} - 4 \\, b_{2} b_{3} + 6 \\, b_{3}^{2} - 4 \\, b_{1} b_{4} - \\frac{4}{3} \\, b_{2} b_{4} - 4 \\, b_{3} b_{4} + \\frac{2}{3} \\, b_{4}^{2}\n", + "\\end{math}" + ], + "text/plain": [ + "6*b1^2 - 4*b1*b2 + 2/3*b2^2 + 4*b1*b3 - 4*b2*b3 + 6*b3^2 - 4*b1*b4 - 4/3*b2*b4 - 4*b3*b4 + 2/3*b4^2" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "relations, Q, nqform = ngon_linear_relations_and_quadratic_form(6)\n", + "show(relations)\n", + "show(simplify(8 * nqform))" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[b5 == -1/2*b3*(sqrt(5) + 3) + 1/2*b4*(sqrt(5) + 3) + b2, b6 == -1/2*b3*(3*sqrt(5) + 5) + 1/2*b2*(sqrt(5) + 3) + b4*(sqrt(5) + 2), b7 == b4*(sqrt(5) + 3) + b2*(sqrt(5) + 2) - 2*b3*(sqrt(5) + 2), b8 == -b3*(2*sqrt(5) + 5) + b2*(sqrt(5) + 3) + b4*(sqrt(5) + 3), b9 == b2*(sqrt(5) + 3) - 2*b3*(sqrt(5) + 2) + b4*(sqrt(5) + 2), b10 == -1/2*b3*(3*sqrt(5) + 5) + 1/2*b4*(sqrt(5) + 3) + b2*(sqrt(5) + 2), b11 == 1/2*b2*(sqrt(5) + 3) - 1/2*b3*(sqrt(5) + 3) + b4]\n" + ] + } + ], + "source": [ + "relations, Q, nqform = ngon_linear_relations_and_quadratic_form(10)\n", + "print(relations)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-1/2*b2*bt1 - 1/2*b1*bt2 + h11*h12 + h21*h22" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec1 = vector([var('bt1'), var('b1'), var('h11'), var('h21')])\n", + "vec2 = vector([var('bt2'), var('b2'), var('h12'), var('h22')])\n", + "vec1 * P * vec2" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "\\begin{math}\n", + "\\newcommand{\\Bold}[1]{\\mathbf{#1}}-\\frac{2 \\, \\sin\\left(\\frac{\\pi k}{n}\\right)^{2}}{\\sin\\left(\\frac{\\pi}{n}\\right)^{2}} + 1\n", + "\\end{math}" + ], + "text/plain": [ + "-2*sin(pi*k/n)^2/sin(pi/n)^2 + 1" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "k = var('k', domain=RR)\n", + "n = var('n', domain=RR)\n", + "\n", + "c1 = 1\n", + "c2i = sin(2 * pi * k / n)\n", + "c2r = cos(2 * pi * k / n)\n", + "\n", + "dist = sin(pi * k / n)\n", + "r = dist.subs(k==1) / 2\n", + "dist /= r\n", + "\n", + "bf = 1/2 * (1 + 1 * (1 - dist^2))\n", + "show(bf)" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 \t 0\n", + "1 \t x - 1\n", + "2 \t 2*x^2 - 2\n", + "3 \t 4*x^3 - 3*x - 1\n", + "4 \t 8*x^4 - 8*x^2\n", + "5 \t 16*x^5 - 20*x^3 + 5*x - 1\n", + "6 \t 32*x^6 - 48*x^4 + 18*x^2 - 2\n", + "7 \t 64*x^7 - 112*x^5 + 56*x^3 - 7*x - 1\n", + "8 \t 128*x^8 - 256*x^6 + 160*x^4 - 32*x^2\n", + "9 \t 256*x^9 - 576*x^7 + 432*x^5 - 120*x^3 + 9*x - 1\n", + "10 \t 512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 2\n" + ] + } + ], + "source": [ + "T = []\n", + "x = var('x')\n", + "T.append(1)\n", + "T.append(x)\n", + "\n", + "def nextT():\n", + " i = len(T)\n", + " T.append(expand(2 * x * T[i - 1] - T[i - 2]))\n", + " #print(i, '\\t', T[i] - 1)\n", + " \n", + "for _ in range(9):\n", + " nextT()\n", + "\n", + "for i, poly in enumerate(T):\n", + " print(i, '\\t', poly - 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-x^6 + x^5 + x^4 - x^3 - 2*x^2 + 2*x" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "expand(x * (1 - x) * (x^4 - x^2 + 2))" ] } ], @@ -1019,7 +2163,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.2" - } + }, + "name": "Apollonian Circle Packings.ipynb" }, "nbformat": 4, "nbformat_minor": 4 diff --git a/.ipynb_checkpoints/Koebe-Andreev-Thurston-checkpoint.ipynb b/.ipynb_checkpoints/Koebe-Andreev-Thurston-checkpoint.ipynb new file mode 100644 index 0000000..7fec515 --- /dev/null +++ b/.ipynb_checkpoints/Koebe-Andreev-Thurston-checkpoint.ipynb @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Apollonian Circle Packings.ipynb b/Apollonian Circle Packings.ipynb index 7ee52b5..ce841e0 100644 --- a/Apollonian Circle Packings.ipynb +++ b/Apollonian Circle Packings.ipynb @@ -16,8 +16,37 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 24, "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}-2 \\, \\pi - \\frac{2 \\, R}{r {\\left(\\frac{R^{2}}{r^{2}} + 1\\right)}} + 2 \\, \\arctan\\left(\\frac{R}{r}\\right)$$" + ], + "text/plain": [ + "-2*pi - 2*R/(r*(R^2/r^2 + 1)) + 2*arctan(R/r)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "var('r, R')\n", + "d = diff(2 * atan(R / r) * r - 2 * pi * r, r)\n", + "show(d)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "scrolled": true + }, "outputs": [], "source": [ "P = matrix([\n", @@ -30,7 +59,114 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}2$$" + ], + "text/plain": [ + "2" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(1,\\,0,\\,0,\\,0\\right)$$" + ], + "text/plain": [ + "(1, 0, 0, 0)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(0,\\,1,\\,0,\\,0\\right)$$" + ], + "text/plain": [ + "(0, 1, 0, 0)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(0,\\,0,\\,1,\\,0\\right)$$" + ], + "text/plain": [ + "(0, 0, 1, 0)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(0,\\,0,\\,0,\\,1\\right)$$" + ], + "text/plain": [ + "(0, 0, 0, 1)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "mat = matrix([\n", + " [2, -2, -2, -2],\n", + " [-2, 2, -2, -2],\n", + " [-2, -2, 2, -2],\n", + " [-2, -2, -2, 2]\n", + "])\n", + "\n", + "a1 = vector([1, 0, 0, 0])\n", + "a2 = vector([0, 1, 0, 0])\n", + "a3 = vector([0, 0, 1, 0])\n", + "a4 = vector([0, 0, 0, 1])\n", + "\n", + "av1 = 2 / (a1 * mat * a1) * a1\n", + "av2 = 2 / (a2 * mat * a2) * a2\n", + "av3 = 2 / (a3 * mat * a3) * a3\n", + "av4 = 2 / (a4 * mat * a4) * a4\n", + "\n", + "show(a1 * mat * a1)\n", + "\n", + "show(av1)\n", + "show(av2)\n", + "show(av3)\n", + "show(av4)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, "metadata": {}, "outputs": [ { @@ -42,7 +178,7 @@ "[ 0 0 0 1]" ] }, - "execution_count": 2, + "execution_count": 27, "metadata": {}, "output_type": "execute_result" } @@ -62,7 +198,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 28, "metadata": {}, "outputs": [], "source": [ @@ -99,7 +235,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 29, "metadata": { "scrolled": true }, @@ -113,7 +249,7 @@ "[-2 -2 -2 -4]" ] }, - "execution_count": 4, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } @@ -140,7 +276,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 30, "metadata": { "scrolled": true }, @@ -154,7 +290,7 @@ "[-1/4 -1/4 -1/4 1/8]" ] }, - "execution_count": 5, + "execution_count": 30, "metadata": {}, "output_type": "execute_result" } @@ -165,7 +301,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 31, "metadata": {}, "outputs": [], "source": [ @@ -197,7 +333,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 32, "metadata": {}, "outputs": [], "source": [ @@ -206,7 +342,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 33, "metadata": {}, "outputs": [ { @@ -218,7 +354,7 @@ "[ 0 0 0 1]" ] }, - "execution_count": 8, + "execution_count": 33, "metadata": {}, "output_type": "execute_result" } @@ -229,7 +365,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 34, "metadata": {}, "outputs": [ { @@ -238,7 +374,7 @@ "b1^2 + b2^2 + b3^2 - b1*b_avg - b2*b_avg - b3*b_avg + 1/4*b_avg^2" ] }, - "execution_count": 9, + "execution_count": 34, "metadata": {}, "output_type": "execute_result" } @@ -269,7 +405,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 35, "metadata": {}, "outputs": [], "source": [ @@ -283,7 +419,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 36, "metadata": {}, "outputs": [], "source": [ @@ -293,7 +429,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 37, "metadata": {}, "outputs": [ { @@ -305,7 +441,7 @@ "[ -1 -1 -1 1/2]" ] }, - "execution_count": 12, + "execution_count": 37, "metadata": {}, "output_type": "execute_result" } @@ -316,7 +452,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 38, "metadata": {}, "outputs": [ { @@ -330,7 +466,7 @@ "]" ] }, - "execution_count": 13, + "execution_count": 38, "metadata": {}, "output_type": "execute_result" } @@ -342,7 +478,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 39, "metadata": {}, "outputs": [], "source": [ @@ -361,7 +497,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 40, "metadata": {}, "outputs": [ { @@ -370,7 +506,7 @@ "(7, 2, 4, 6)" ] }, - "execution_count": 15, + "execution_count": 40, "metadata": {}, "output_type": "execute_result" } @@ -382,7 +518,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 41, "metadata": {}, "outputs": [ { @@ -391,7 +527,7 @@ "(-1, 4, 4, 6)" ] }, - "execution_count": 16, + "execution_count": 41, "metadata": {}, "output_type": "execute_result" } @@ -402,7 +538,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 42, "metadata": {}, "outputs": [ { @@ -411,7 +547,7 @@ "(-1, 2, 2, 6)" ] }, - "execution_count": 17, + "execution_count": 42, "metadata": {}, "output_type": "execute_result" } @@ -422,7 +558,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 43, "metadata": {}, "outputs": [ { @@ -431,7 +567,7 @@ "(-1, 2, 4, 14)" ] }, - "execution_count": 18, + "execution_count": 43, "metadata": {}, "output_type": "execute_result" } @@ -451,7 +587,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 44, "metadata": {}, "outputs": [], "source": [ @@ -475,28 +611,46 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 45, "metadata": {}, + "outputs": [], + "source": [ + "def abbc_coords(b, h1, h2):\n", + " return [(h1^2 + h2^2 - 1) / b, b, h1, h2]" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "scrolled": true + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1/2*sqrt(2), 1)\n", - "sqrt(2)\n", - "(1/4*sqrt(2), 0)\n", - "2*sqrt(2)\n" + "sqrt(2)\n" ] }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ - "Graphics object consisting of 14 graphics primitives" + "Graphics object consisting of 4 graphics primitives" ] }, "metadata": {}, "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1/4*sqrt(2), 0)\n", + "2*sqrt(2)\n" + ] } ], "source": [ @@ -514,6 +668,22 @@ "print('({}, {})'.format(x, y))\n", "print(1 / r)\n", "\n", + "btest = []\n", + "coordsnew = abbc_coords(1/r, x/r, y/r)\n", + "bnew = coordsnew[0]\n", + "btest.append(circle((coordsnew[2]/bnew, coordsnew[3]/bnew), 1/bnew))\n", + "coordsnew = abbc_coords(1/r, -x/r, y/r)\n", + "bnew = coordsnew[0]\n", + "btest.append(circle((coordsnew[2]/bnew, coordsnew[3]/bnew), 1/bnew))\n", + "coordsnew = abbc_coords(1/r, x/r, -y/r)\n", + "bnew = coordsnew[0]\n", + "btest.append(circle((coordsnew[2]/bnew, coordsnew[3]/bnew), 1/bnew))\n", + "coordsnew = abbc_coords(1/r, -x/r, -y/r)\n", + "bnew = coordsnew[0]\n", + "btest.append(circle((coordsnew[2]/bnew, coordsnew[3]/bnew), 1/bnew))\n", + "\n", + "show(sum(btest))\n", + "\n", "b3 = circle(( x, y), r, rgbcolor=(1, 0, 0))\n", "b4 = circle((-x, y), r, rgbcolor=(1, 0, 0))\n", "b5 = circle(( x, -y), r, rgbcolor=(1, 0, 0))\n", @@ -526,7 +696,7 @@ "b7 = circle(( x, y), r, rgbcolor=(1, 0, 0))\n", "b8 = circle((-x, y), r, rgbcolor=(1, 0, 0))\n", "\n", - "show(c1 + c2 + c3 + c4 + c5 + c6 + b1 + b2 + b3 + b4 + b5 + b6 + b7 + b8)" + "#show(c1 + c2 + c3 + c4 + c5 + c6 + b1 + b2 + b3 + b4 + b5 + b6 + b7 + b8)" ] }, { @@ -538,16 +708,6 @@ "We first made a matrix, $W_c$, whose rows are the abbc coordinates of the circles in the root octuple. Then we found the row echelon form of that matrix, resulting in a system of linear relations the coordinates must satisfy. Then, from there, we could derive the rest of the coordinates from the first four (we chose the first four to be the \"cubicle\" from the Stange), allowing us to derive the quadratic form." ] }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [], - "source": [ - "def abbc_coords(b, h1, h2):\n", - " return [(h1^2 + h2^2 - 1) / b, b, h1, h2]" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -557,7 +717,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 47, "metadata": {}, "outputs": [ { @@ -569,7 +729,7 @@ "[ 0 0 0 1 -1/2 1/2 1/2 1/2]" ] }, - "execution_count": 22, + "execution_count": 47, "metadata": {}, "output_type": "execute_result" } @@ -613,7 +773,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 48, "metadata": {}, "outputs": [], "source": [ @@ -627,7 +787,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 49, "metadata": {}, "outputs": [ { @@ -639,7 +799,7 @@ "[-3 -3 -3 1]" ] }, - "execution_count": 24, + "execution_count": 49, "metadata": {}, "output_type": "execute_result" } @@ -651,7 +811,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 50, "metadata": {}, "outputs": [ { @@ -663,7 +823,7 @@ "[-6/5 -6/5 -6/5 2]" ] }, - "execution_count": 25, + "execution_count": 50, "metadata": {}, "output_type": "execute_result" } @@ -674,7 +834,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 51, "metadata": {}, "outputs": [ { @@ -686,7 +846,7 @@ "[bt4 b4 h14 h24]" ] }, - "execution_count": 26, + "execution_count": 51, "metadata": {}, "output_type": "execute_result" } @@ -705,7 +865,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 52, "metadata": {}, "outputs": [], "source": [ @@ -714,7 +874,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 53, "metadata": {}, "outputs": [ { @@ -723,7 +883,7 @@ "5*b1^2 - 6*b1*b2 + 5*b2^2 - 6*b1*b3 - 6*b2*b3 + 5*b3^2 - 6*b1*b4 - 6*b2*b4 - 6*b3*b4 + 5*b4^2" ] }, - "execution_count": 28, + "execution_count": 53, "metadata": {}, "output_type": "execute_result" } @@ -750,7 +910,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 54, "metadata": { "scrolled": true }, @@ -771,7 +931,7 @@ "]" ] }, - "execution_count": 29, + "execution_count": 54, "metadata": {}, "output_type": "execute_result" } @@ -783,7 +943,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 55, "metadata": { "scrolled": true }, @@ -801,7 +961,7 @@ "[ 0 0 0 0 0 0 0 0]" ] }, - "execution_count": 30, + "execution_count": 55, "metadata": {}, "output_type": "execute_result" } @@ -820,7 +980,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 56, "metadata": {}, "outputs": [], "source": [ @@ -859,7 +1019,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 57, "metadata": {}, "outputs": [ { @@ -868,9 +1028,7 @@ "" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[2 \\, b_{5} = b_{1} + b_{2} + b_{3} - b_{4}, 2 \\, b_{6} = b_{1} + b_{2} - b_{3} + b_{4}, 2 \\, b_{7} = b_{1} - b_{2} + b_{3} + b_{4}, 2 \\, b_{8} = -b_{1} + b_{2} + b_{3} + b_{4}\\right]\n", - "\\end{math}" + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[2 \\, b_{5} = b_{1} + b_{2} + b_{3} - b_{4}, 2 \\, b_{6} = b_{1} + b_{2} - b_{3} + b_{4}, 2 \\, b_{7} = b_{1} - b_{2} + b_{3} + b_{4}, 2 \\, b_{8} = -b_{1} + b_{2} + b_{3} + b_{4}\\right]$$" ], "text/plain": [ "[2*b5 == b1 + b2 + b3 - b4,\n", @@ -893,14 +1051,12 @@ "\\end{array}\\right)" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", "5 & -3 & -3 & -3 \\\\\n", "-3 & 5 & -3 & -3 \\\\\n", "-3 & -3 & 5 & -3 \\\\\n", "-3 & -3 & -3 & 5\n", - "\\end{array}\\right)\n", - "\\end{math}" + "\\end{array}\\right)$$" ], "text/plain": [ "[ 5 -3 -3 -3]\n", @@ -918,9 +1074,7 @@ "" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}5 \\, b_{1}^{2} - 6 \\, b_{1} b_{2} + 5 \\, b_{2}^{2} - 6 \\, b_{1} b_{3} - 6 \\, b_{2} b_{3} + 5 \\, b_{3}^{2} - 6 \\, b_{1} b_{4} - 6 \\, b_{2} b_{4} - 6 \\, b_{3} b_{4} + 5 \\, b_{4}^{2}\n", - "\\end{math}" + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}5 \\, b_{1}^{2} - 6 \\, b_{1} b_{2} + 5 \\, b_{2}^{2} - 6 \\, b_{1} b_{3} - 6 \\, b_{2} b_{3} + 5 \\, b_{3}^{2} - 6 \\, b_{1} b_{4} - 6 \\, b_{2} b_{4} - 6 \\, b_{3} b_{4} + 5 \\, b_{4}^{2}$$" ], "text/plain": [ "5*b1^2 - 6*b1*b2 + 5*b2^2 - 6*b1*b3 - 6*b2*b3 + 5*b3^2 - 6*b1*b4 - 6*b2*b4 - 6*b3*b4 + 5*b4^2" @@ -955,8 +1109,7 @@ "\\end{array}\\right)\\right]" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", "-1 & \\frac{6}{5} & \\frac{6}{5} & \\frac{6}{5} \\\\\n", "0 & 1 & 0 & 0 \\\\\n", "0 & 0 & 1 & 0 \\\\\n", @@ -976,8 +1129,7 @@ "0 & 1 & 0 & 0 \\\\\n", "0 & 0 & 1 & 0 \\\\\n", "\\frac{6}{5} & \\frac{6}{5} & \\frac{6}{5} & -1\n", - "\\end{array}\\right)\\right]\n", - "\\end{math}" + "\\end{array}\\right)\\right]$$" ], "text/plain": [ "[\n", @@ -1003,26 +1155,24 @@ "show([2 * eq for eq in relation])\n", "show(32 * mat)\n", "show(32 * equation)\n", - "show(weyl_generators(32 * mat, standard_basis(4)))" + "show(weyl_generators(mat, standard_basis(4)))" ] }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "" + "" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[b_{5} = b_{1} - b_{2} + b_{4}, b_{6} = b_{1} - b_{3} + b_{4}\\right]\n", - "\\end{math}" + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[b_{5} = b_{1} + b_{3} + b_{4}, b_{6} = b_{2} + b_{3} + b_{4}\\right]$$" ], "text/plain": [ - "[b5 == b1 - b2 + b4, b6 == b1 - b3 + b4]" + "[b5 == b1 + b3 + b4, b6 == b2 + b3 + b4]" ] }, "metadata": {}, @@ -1032,27 +1182,25 @@ "data": { "text/html": [ "" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", - "1 & -2 & -2 & -1 \\\\\n", - "-2 & 4 & 0 & -2 \\\\\n", - "-2 & 0 & 4 & -2 \\\\\n", - "-1 & -2 & -2 & 1\n", - "\\end{array}\\right)\n", - "\\end{math}" + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", + "17 & 15 & -6 & -6 \\\\\n", + "15 & 17 & -6 & -6 \\\\\n", + "-6 & -6 & 4 & 0 \\\\\n", + "-6 & -6 & 0 & 4\n", + "\\end{array}\\right)$$" ], "text/plain": [ - "[ 1 -2 -2 -1]\n", - "[-2 4 0 -2]\n", - "[-2 0 4 -2]\n", - "[-1 -2 -2 1]" + "[17 15 -6 -6]\n", + "[15 17 -6 -6]\n", + "[-6 -6 4 0]\n", + "[-6 -6 0 4]" ] }, "metadata": {}, @@ -1061,15 +1209,13 @@ { "data": { "text/html": [ - "" + "" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}b_{1}^{2} - 4 \\, b_{1} b_{2} + 4 \\, b_{2}^{2} - 4 \\, b_{1} b_{3} + 4 \\, b_{3}^{2} - 2 \\, b_{1} b_{4} - 4 \\, b_{2} b_{4} - 4 \\, b_{3} b_{4} + b_{4}^{2}\n", - "\\end{math}" + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}17 \\, b_{1}^{2} + 30 \\, b_{1} b_{2} + 17 \\, b_{2}^{2} - 12 \\, b_{1} b_{3} - 12 \\, b_{2} b_{3} + 4 \\, b_{3}^{2} - 12 \\, b_{1} b_{4} - 12 \\, b_{2} b_{4} + 4 \\, b_{4}^{2}$$" ], "text/plain": [ - "b1^2 - 4*b1*b2 + 4*b2^2 - 4*b1*b3 + 4*b3^2 - 2*b1*b4 - 4*b2*b4 - 4*b3*b4 + b4^2" + "17*b1^2 + 30*b1*b2 + 17*b2^2 - 12*b1*b3 - 12*b2*b3 + 4*b3^2 - 12*b1*b4 - 12*b2*b4 + 4*b4^2" ] }, "metadata": {}, @@ -1079,58 +1225,61 @@ "data": { "text/html": [ "" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", - "-1 & 4 & 4 & 2 \\\\\n", + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", + "-1 & -\\frac{30}{17} & \\frac{12}{17} & \\frac{12}{17} \\\\\n", "0 & 1 & 0 & 0 \\\\\n", "0 & 0 & 1 & 0 \\\\\n", "0 & 0 & 0 & 1\n", "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", "1 & 0 & 0 & 0 \\\\\n", - "1 & -1 & 0 & 1 \\\\\n", + "-\\frac{30}{17} & -1 & \\frac{12}{17} & \\frac{12}{17} \\\\\n", "0 & 0 & 1 & 0 \\\\\n", "0 & 0 & 0 & 1\n", "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", "1 & 0 & 0 & 0 \\\\\n", "0 & 1 & 0 & 0 \\\\\n", - "1 & 0 & -1 & 1 \\\\\n", + "3 & 3 & -1 & 0 \\\\\n", "0 & 0 & 0 & 1\n", "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", "1 & 0 & 0 & 0 \\\\\n", "0 & 1 & 0 & 0 \\\\\n", "0 & 0 & 1 & 0 \\\\\n", - "2 & 4 & 4 & -1\n", - "\\end{array}\\right)\\right]\n", - "\\end{math}" + "3 & 3 & 0 & -1\n", + "\\end{array}\\right)\\right]$$" ], "text/plain": [ "[\n", - "[-1 4 4 2] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]\n", - "[ 0 1 0 0] [ 1 -1 0 1] [ 0 1 0 0] [ 0 1 0 0]\n", - "[ 0 0 1 0] [ 0 0 1 0] [ 1 0 -1 1] [ 0 0 1 0]\n", - "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [ 2 4 4 -1]\n", + "[ -1 -30/17 12/17 12/17] [ 1 0 0 0]\n", + "[ 0 1 0 0] [-30/17 -1 12/17 12/17]\n", + "[ 0 0 1 0] [ 0 0 1 0]\n", + "[ 0 0 0 1], [ 0 0 0 1],\n", + "\n", + "[ 1 0 0 0] [ 1 0 0 0]\n", + "[ 0 1 0 0] [ 0 1 0 0]\n", + "[ 3 3 -1 0] [ 0 0 1 0]\n", + "[ 0 0 0 1], [ 3 3 0 -1]\n", "]" ] }, @@ -1143,10 +1292,10 @@ "relation, mat, equation = quadform_from_root(matrix([\n", " [2, 0, 0, 1],\n", " [2, 0, 0, -1],\n", - " [-1, 1, 0, 0],\n", - " [4, 2, 2*sqrt(2), -1],\n", - " [4, 2, 2*sqrt(2), 1],\n", - " [7, 1, 2*sqrt(2), 0],\n", + " [1, 1, sqrt(2), 0],\n", + " [1, 1, -sqrt(2), 0],\n", + " [4, 2, 0, 1],\n", + " [4, 2, 0, -1],\n", "]))\n", "show(relation)\n", "show(8 * mat)\n", @@ -1156,7 +1305,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 59, "metadata": {}, "outputs": [ { @@ -1165,9 +1314,7 @@ "" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\right]\n", - "\\end{math}" + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\right]$$" ], "text/plain": [ "[]" @@ -1187,14 +1334,12 @@ "\\end{array}\\right)" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", "1 & -1 & -1 & -1 \\\\\n", "-1 & 1 & -1 & -1 \\\\\n", "-1 & -1 & 1 & -1 \\\\\n", "-1 & -1 & -1 & 1\n", - "\\end{array}\\right)\n", - "\\end{math}" + "\\end{array}\\right)$$" ], "text/plain": [ "[ 1 -1 -1 -1]\n", @@ -1212,9 +1357,7 @@ "" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}b_{1}^{2} - 2 \\, b_{1} b_{2} + b_{2}^{2} - 2 \\, b_{1} b_{3} - 2 \\, b_{2} b_{3} + b_{3}^{2} - 2 \\, b_{1} b_{4} - 2 \\, b_{2} b_{4} - 2 \\, b_{3} b_{4} + b_{4}^{2}\n", - "\\end{math}" + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}b_{1}^{2} - 2 \\, b_{1} b_{2} + b_{2}^{2} - 2 \\, b_{1} b_{3} - 2 \\, b_{2} b_{3} + b_{3}^{2} - 2 \\, b_{1} b_{4} - 2 \\, b_{2} b_{4} - 2 \\, b_{3} b_{4} + b_{4}^{2}$$" ], "text/plain": [ "b1^2 - 2*b1*b2 + b2^2 - 2*b1*b3 - 2*b2*b3 + b3^2 - 2*b1*b4 - 2*b2*b4 - 2*b3*b4 + b4^2" @@ -1249,8 +1392,7 @@ "\\end{array}\\right)\\right]" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", "-1 & 2 & 2 & 2 \\\\\n", "0 & 1 & 0 & 0 \\\\\n", "0 & 0 & 1 & 0 \\\\\n", @@ -1270,8 +1412,7 @@ "0 & 1 & 0 & 0 \\\\\n", "0 & 0 & 1 & 0 \\\\\n", "2 & 2 & 2 & -1\n", - "\\end{array}\\right)\\right]\n", - "\\end{math}" + "\\end{array}\\right)\\right]$$" ], "text/plain": [ "[\n", @@ -1315,7 +1456,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 60, "metadata": {}, "outputs": [], "source": [ @@ -1340,7 +1481,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 61, "metadata": {}, "outputs": [], "source": [ @@ -1351,7 +1492,200 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 62, + "metadata": {}, + "outputs": [], + "source": [ + "def linear_relations_and_quadratic_form_from_wtpw(mat, indices=None):\n", + " if indices is None:\n", + " indices = range(mat.dimensions()[0] + 1)\n", + " n = mat.dimensions()[0]\n", + " \n", + " # work out initial relations\n", + " relations_temp = vector([ var('b' + str(i)) for i in range(1, n + 1) ]) * mat.transpose().rref()\n", + " relations = []\n", + " for i in range(n):\n", + " relations.append(var('b' + str(i + 1)) == relations_temp[i])\n", + " \n", + " # rewrite the relations in terms of the variables we care about, depends on the step\n", + " targets = [ var('b' + str(i)) for i in indices[4:] ]\n", + " show(relations)\n", + " show(targets)\n", + " #relations = solve(relations, *targets)[0]\n", + " \n", + " # find the matrix corresponding to the quadratic form, picking the appropriate rows from the matrix\n", + " mat = matrix([\n", + " [ mat[i - 1][j - 1] for j in indices[:4] ] for i in indices[:4]\n", + " ])\n", + "\n", + " Q = mat.inverse()\n", + " \n", + " # find the quadratic form in variables; proper units will satisfy this being equal to zero\n", + " vec = vector([ var('b' + str(i)) for i in indices[:4] ])\n", + " nqform = vec * Q * vec\n", + " \n", + " return relations, Q, expand(nqform)" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[b_{1} = b_{1}, b_{2} = b_{2}, b_{3} = b_{3}, b_{4} = b_{4}, b_{5} = b_{2} - 2 \\, b_{3} + 2 \\, b_{4}, b_{6} = 2 \\, b_{2} - 3 \\, b_{3} + 2 \\, b_{4}, b_{7} = 2 \\, b_{2} - 2 \\, b_{3} + b_{4}\\right]$$" + ], + "text/plain": [ + "[b1 == b1,\n", + " b2 == b2,\n", + " b3 == b3,\n", + " b4 == b4,\n", + " b5 == b2 - 2*b3 + 2*b4,\n", + " b6 == 2*b2 - 3*b3 + 2*b4,\n", + " b7 == 2*b2 - 2*b3 + b4]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[b_{2}, b_{4}, b_{6}\\right]$$" + ], + "text/plain": [ + "[b2, b4, b6]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ 9 -1 -1 -1]\n", + "[-1 1 -1 -1]\n", + "[-1 -1 1 -1]\n", + "[-1 -1 -1 1]\n" + ] + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}9 \\, b_{1}^{2} - 2 \\, b_{1} b_{3} + b_{3}^{2} - 2 \\, b_{1} b_{5} - 2 \\, b_{3} b_{5} + b_{5}^{2} - 2 \\, b_{1} b_{7} - 2 \\, b_{3} b_{7} - 2 \\, b_{5} b_{7} + b_{7}^{2}$$" + ], + "text/plain": [ + "9*b1^2 - 2*b1*b3 + b3^2 - 2*b1*b5 - 2*b3*b5 + b5^2 - 2*b1*b7 - 2*b3*b7 - 2*b5*b7 + b7^2" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[3 \\, b_{1} = 3 \\, b_{1}, 3 \\, b_{2} = 3 \\, b_{2}, 3 \\, b_{3} = 3 \\, b_{3}, 3 \\, b_{4} = 3 \\, b_{4}, 3 \\, b_{5} = 3 \\, b_{2} - 6 \\, b_{3} + 6 \\, b_{4}, 3 \\, b_{6} = 6 \\, b_{2} - 9 \\, b_{3} + 6 \\, b_{4}, 3 \\, b_{7} = 6 \\, b_{2} - 6 \\, b_{3} + 3 \\, b_{4}\\right]$$" + ], + "text/plain": [ + "[3*b1 == 3*b1,\n", + " 3*b2 == 3*b2,\n", + " 3*b3 == 3*b3,\n", + " 3*b4 == 3*b4,\n", + " 3*b5 == 3*b2 - 6*b3 + 6*b4,\n", + " 3*b6 == 6*b2 - 9*b3 + 6*b4,\n", + " 3*b7 == 6*b2 - 6*b3 + 3*b4]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", + "-1 & \\frac{2}{9} & \\frac{2}{9} & \\frac{2}{9} \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "2 & -1 & 2 & 2 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "2 & 2 & -1 & 2 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "2 & 2 & 2 & -1\n", + "\\end{array}\\right)\\right]$$" + ], + "text/plain": [ + "[\n", + "[ -1 2/9 2/9 2/9] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]\n", + "[ 0 1 0 0] [ 2 -1 2 2] [ 0 1 0 0] [ 0 1 0 0]\n", + "[ 0 0 1 0] [ 0 0 1 0] [ 2 2 -1 2] [ 0 0 1 0]\n", + "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [ 2 2 2 -1]\n", + "]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "relations, Q, nqform = linear_relations_and_quadratic_form_from_wtpw(wmatrix(6), [1, 3, 5, 7, 2, 4, 6])\n", + "print(12 * Q)\n", + "show(12 * nqform)\n", + "show([3 * rel for rel in relations])\n", + "show(weyl_generators(12 * Q, standard_basis(4)))" + ] + }, + { + "cell_type": "code", + "execution_count": 64, "metadata": {}, "outputs": [], "source": [ @@ -1392,21 +1726,23 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "" + "" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}b_{5} = b_{2} - b_{3} + b_{4}\n", - "\\end{math}" + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[b_{5} = -b_{3} {\\left(\\sqrt{2} + 1\\right)} + b_{4} {\\left(\\sqrt{2} + 1\\right)} + b_{2}, b_{6} = b_{4} {\\left(\\sqrt{2} + 2\\right)} + b_{2} {\\left(\\sqrt{2} + 1\\right)} - 2 \\, b_{3} {\\left(\\sqrt{2} + 1\\right)}, b_{7} = -b_{3} {\\left(2 \\, \\sqrt{2} + 3\\right)} + b_{2} {\\left(\\sqrt{2} + 2\\right)} + b_{4} {\\left(\\sqrt{2} + 2\\right)}, b_{8} = b_{2} {\\left(\\sqrt{2} + 2\\right)} - 2 \\, b_{3} {\\left(\\sqrt{2} + 1\\right)} + b_{4} {\\left(\\sqrt{2} + 1\\right)}, b_{9} = b_{2} {\\left(\\sqrt{2} + 1\\right)} - b_{3} {\\left(\\sqrt{2} + 1\\right)} + b_{4}\\right]$$" ], "text/plain": [ - "b5 == b2 - b3 + b4" + "[b5 == -b3*(sqrt(2) + 1) + b4*(sqrt(2) + 1) + b2,\n", + " b6 == b4*(sqrt(2) + 2) + b2*(sqrt(2) + 1) - 2*b3*(sqrt(2) + 1),\n", + " b7 == -b3*(2*sqrt(2) + 3) + b2*(sqrt(2) + 2) + b4*(sqrt(2) + 2),\n", + " b8 == b2*(sqrt(2) + 2) - 2*b3*(sqrt(2) + 1) + b4*(sqrt(2) + 1),\n", + " b9 == b2*(sqrt(2) + 1) - b3*(sqrt(2) + 1) + b4]" ] }, "metadata": {}, @@ -1416,27 +1752,25 @@ "data": { "text/html": [ "" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", - "4 & -2 & 0 & -2 \\\\\n", - "-2 & 1 & -2 & -1 \\\\\n", - "0 & -2 & 4 & -2 \\\\\n", - "-2 & -1 & -2 & 1\n", - "\\end{array}\\right)\n", - "\\end{math}" + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", + "-\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 1 & -2 & -\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 3 & -2 \\\\\n", + "-2 & -\\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} & -2 & \\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} \\\\\n", + "-\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 3 & -2 & -\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 1 & -2 \\\\\n", + "-2 & \\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} & -2 & -\\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1}\n", + "\\end{array}\\right)$$" ], "text/plain": [ - "[ 4 -2 0 -2]\n", - "[-2 1 -2 -1]\n", - "[ 0 -2 4 -2]\n", - "[-2 -1 -2 1]" + "[ -(sqrt(2) + 2)/(sqrt(2) - 2) + 1 -2 -(sqrt(2) + 2)/(sqrt(2) - 2) - 3 -2]\n", + "[ -2 -4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1) -2 4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1)]\n", + "[ -(sqrt(2) + 2)/(sqrt(2) - 2) - 3 -2 -(sqrt(2) + 2)/(sqrt(2) - 2) + 1 -2]\n", + "[ -2 4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1) -2 -4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1)]" ] }, "metadata": {}, @@ -1445,15 +1779,13 @@ { "data": { "text/html": [ - "" + "" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}4 \\, b_{1}^{2} - 4 \\, b_{1} b_{2} + b_{2}^{2} - 4 \\, b_{2} b_{3} + 4 \\, b_{3}^{2} - 4 \\, b_{1} b_{4} - 2 \\, b_{2} b_{4} - 4 \\, b_{3} b_{4} + b_{4}^{2}\n", - "\\end{math}" + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}b_{1}^{2} - 4 \\, b_{1} b_{2} - 6 \\, b_{1} b_{3} - 4 \\, b_{2} b_{3} + b_{3}^{2} - 4 \\, b_{1} b_{4} - 4 \\, b_{3} b_{4} - \\frac{\\sqrt{2} b_{1}^{2}}{\\sqrt{2} - 2} - \\frac{2 \\, \\sqrt{2} b_{1} b_{3}}{\\sqrt{2} - 2} - \\frac{\\sqrt{2} b_{3}^{2}}{\\sqrt{2} - 2} - \\frac{2 \\, b_{1}^{2}}{\\sqrt{2} - 2} - \\frac{4 \\, b_{1} b_{3}}{\\sqrt{2} - 2} - \\frac{2 \\, b_{3}^{2}}{\\sqrt{2} - 2} - \\frac{4 \\, b_{2}^{2}}{\\frac{\\sqrt{2}}{\\sqrt{2} - 2} + \\frac{2}{\\sqrt{2} - 2} - 1} + \\frac{8 \\, b_{2} b_{4}}{\\frac{\\sqrt{2}}{\\sqrt{2} - 2} + \\frac{2}{\\sqrt{2} - 2} - 1} - \\frac{4 \\, b_{4}^{2}}{\\frac{\\sqrt{2}}{\\sqrt{2} - 2} + \\frac{2}{\\sqrt{2} - 2} - 1}$$" ], "text/plain": [ - "4*b1^2 - 4*b1*b2 + b2^2 - 4*b2*b3 + 4*b3^2 - 4*b1*b4 - 2*b2*b4 - 4*b3*b4 + b4^2" + "b1^2 - 4*b1*b2 - 6*b1*b3 - 4*b2*b3 + b3^2 - 4*b1*b4 - 4*b3*b4 - sqrt(2)*b1^2/(sqrt(2) - 2) - 2*sqrt(2)*b1*b3/(sqrt(2) - 2) - sqrt(2)*b3^2/(sqrt(2) - 2) - 2*b1^2/(sqrt(2) - 2) - 4*b1*b3/(sqrt(2) - 2) - 2*b3^2/(sqrt(2) - 2) - 4*b2^2/(sqrt(2)/(sqrt(2) - 2) + 2/(sqrt(2) - 2) - 1) + 8*b2*b4/(sqrt(2)/(sqrt(2) - 2) + 2/(sqrt(2) - 2) - 1) - 4*b4^2/(sqrt(2)/(sqrt(2) - 2) + 2/(sqrt(2) - 2) - 1)" ] }, "metadata": {}, @@ -1463,58 +1795,56 @@ "data": { "text/html": [ "" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", - "-1 & 1 & 0 & 1 \\\\\n", + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", + "-1 & -\\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} & -\\frac{2 \\, {\\left(\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 3\\right)}}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} & -\\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} \\\\\n", "0 & 1 & 0 & 0 \\\\\n", "0 & 0 & 1 & 0 \\\\\n", "0 & 0 & 0 & 1\n", "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", "1 & 0 & 0 & 0 \\\\\n", - "4 & -1 & 4 & 2 \\\\\n", + "-\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 1 & -1 & -\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 1 & 2 \\\\\n", "0 & 0 & 1 & 0 \\\\\n", "0 & 0 & 0 & 1\n", "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", "1 & 0 & 0 & 0 \\\\\n", "0 & 1 & 0 & 0 \\\\\n", - "0 & 1 & -1 & 1 \\\\\n", + "-\\frac{2 \\, {\\left(\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 3\\right)}}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} & -\\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} & -1 & -\\frac{4}{\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} - 1} \\\\\n", "0 & 0 & 0 & 1\n", "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", "1 & 0 & 0 & 0 \\\\\n", "0 & 1 & 0 & 0 \\\\\n", "0 & 0 & 1 & 0 \\\\\n", - "4 & 2 & 4 & -1\n", - "\\end{array}\\right)\\right]\n", - "\\end{math}" + "-\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 1 & 2 & -\\frac{\\sqrt{2} + 2}{\\sqrt{2} - 2} + 1 & -1\n", + "\\end{array}\\right)\\right]$$" ], "text/plain": [ "[\n", - "[-1 1 0 1] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]\n", - "[ 0 1 0 0] [ 4 -1 4 2] [ 0 1 0 0] [ 0 1 0 0]\n", - "[ 0 0 1 0] [ 0 0 1 0] [ 0 1 -1 1] [ 0 0 1 0]\n", - "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [ 4 2 4 -1]\n", + "[ -1 -4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1) -2*((sqrt(2) + 2)/(sqrt(2) - 2) + 3)/((sqrt(2) + 2)/(sqrt(2) - 2) - 1) -4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1)] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]\n", + "[ 0 1 0 0] [-(sqrt(2) + 2)/(sqrt(2) - 2) + 1 -1 -(sqrt(2) + 2)/(sqrt(2) - 2) + 1 2] [ 0 1 0 0] [ 0 1 0 0]\n", + "[ 0 0 1 0] [ 0 0 1 0] [-2*((sqrt(2) + 2)/(sqrt(2) - 2) + 3)/((sqrt(2) + 2)/(sqrt(2) - 2) - 1) -4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1) -1 -4/((sqrt(2) + 2)/(sqrt(2) - 2) - 1)] [ 0 0 1 0]\n", + "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [-(sqrt(2) + 2)/(sqrt(2) - 2) + 1 2 -(sqrt(2) + 2)/(sqrt(2) - 2) + 1 -1]\n", "]" ] }, @@ -1523,7 +1853,7 @@ } ], "source": [ - "relations, Q, nqform = ngon_linear_relations_and_quadratic_form(4)\n", + "relations, Q, nqform = ngon_linear_relations_and_quadratic_form(8)\n", "\n", "show(relations)\n", "show(8 * Q)\n", @@ -1533,7 +1863,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 66, "metadata": {}, "outputs": [ { @@ -1542,9 +1872,7 @@ "" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[3 \\, b_{2} = 2 \\, b_{3} - b_{5} + 2 \\, b_{7}, 3 \\, b_{4} = 2 \\, b_{3} + 2 \\, b_{5} - b_{7}, 3 \\, b_{6} = -b_{3} + 2 \\, b_{5} + 2 \\, b_{7}\\right]\n", - "\\end{math}" + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[3 \\, b_{2} = 2 \\, b_{3} - b_{5} + 2 \\, b_{7}, 3 \\, b_{4} = 2 \\, b_{3} + 2 \\, b_{5} - b_{7}, 3 \\, b_{6} = -b_{3} + 2 \\, b_{5} + 2 \\, b_{7}\\right]$$" ], "text/plain": [ "[3*b2 == 2*b3 - b5 + 2*b7, 3*b4 == 2*b3 + 2*b5 - b7, 3*b6 == -b3 + 2*b5 + 2*b7]" @@ -1564,14 +1892,12 @@ "\\end{array}\\right)" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", "9 & -1 & -1 & -1 \\\\\n", "-1 & 1 & -1 & -1 \\\\\n", "-1 & -1 & 1 & -1 \\\\\n", "-1 & -1 & -1 & 1\n", - "\\end{array}\\right)\n", - "\\end{math}" + "\\end{array}\\right)$$" ], "text/plain": [ "[ 9 -1 -1 -1]\n", @@ -1589,9 +1915,7 @@ "" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}9 \\, b_{1}^{2} - 2 \\, b_{1} b_{2} + b_{2}^{2} - 2 \\, b_{1} b_{3} - 2 \\, b_{2} b_{3} + b_{3}^{2} - 2 \\, b_{1} b_{4} - 2 \\, b_{2} b_{4} - 2 \\, b_{3} b_{4} + b_{4}^{2}\n", - "\\end{math}" + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}9 \\, b_{1}^{2} - 2 \\, b_{1} b_{2} + b_{2}^{2} - 2 \\, b_{1} b_{3} - 2 \\, b_{2} b_{3} + b_{3}^{2} - 2 \\, b_{1} b_{4} - 2 \\, b_{2} b_{4} - 2 \\, b_{3} b_{4} + b_{4}^{2}$$" ], "text/plain": [ "9*b1^2 - 2*b1*b2 + b2^2 - 2*b1*b3 - 2*b2*b3 + b3^2 - 2*b1*b4 - 2*b2*b4 - 2*b3*b4 + b4^2" @@ -1626,8 +1950,7 @@ "\\end{array}\\right)\\right]" ], "text/latex": [ - "\\begin{math}\n", - "\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", "-1 & \\frac{2}{9} & \\frac{2}{9} & \\frac{2}{9} \\\\\n", "0 & 1 & 0 & 0 \\\\\n", "0 & 0 & 1 & 0 \\\\\n", @@ -1647,8 +1970,7 @@ "0 & 1 & 0 & 0 \\\\\n", "0 & 0 & 1 & 0 \\\\\n", "2 & 2 & 2 & -1\n", - "\\end{array}\\right)\\right]\n", - "\\end{math}" + "\\end{array}\\right)\\right]$$" ], "text/plain": [ "[\n", @@ -1661,6 +1983,21 @@ }, "metadata": {}, "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\frac{2}{9} \\, b_{2} + \\frac{2}{9} \\, b_{3} + \\frac{2}{9} \\, b_{4}$$" + ], + "text/plain": [ + "2/9*b2 + 2/9*b3 + 2/9*b4" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ @@ -1669,13 +2006,1302 @@ "show([3 * eq for eq in relations])\n", "show(12 * Q)\n", "show(12 * nqform)\n", - "show(weyl_generators(12 * Q, standard_basis(4)))" + "show(weyl_generators(12 * Q, standard_basis(4)))\n", + "\n", + "sols = solve(nqform, b1)\n", + "s1 = sols[0].rhs()\n", + "s2 = sols[1].rhs()\n", + "show(s1 + s2)" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [], + "source": [ + "class Circle:\n", + " def __init__(self, bt, b, h1, h2):\n", + " self.bt = bt\n", + " self.b = b\n", + " self.h1 = h1\n", + " self.h2 = h2\n", + " self.vec = vector(bt, b, h1, h2)\n", + " \n", + " def __mul__(self, other):\n", + " self.vec *= other\n", + " self.bt = self.vec[0]\n", + " self.b = self.vec[1]\n", + " self.h1 = self.vec[2]\n", + " self.h2 = self.vec[3]\n", + " \n", + " def draw(self, plt):\n", + " pass\n", + " \n", + " \n", + "def from_xyr(x, y, r):\n", + " b = 1/r\n", + " h1 = b * x\n", + " h2 = b * y\n", + " return Circle((1 - h1^2 - h2^2) / b, b, h1, h2)" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[0 = 0, 1 = 1, 0 = 0, 1 = 1, b_{5} = 1, b_{6} = 0\\right]$$" + ], + "text/plain": [ + "[0 == 0, 1 == 1, 0 == 0, 1 == 1, b5 == 1, b6 == 0]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(-2/3*sqrt(3), -1)\t1/3*sqrt(3)\n", + "(-1/6*sqrt(3), -1)\t1/6*sqrt(3)\n", + "(0, 1)\tsqrt(3)\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "Graphics object consisting of 14 graphics primitives" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "b1, b2, b3, b4, b5, b6, b7 = var('b1 b2 b3 b4 b5 b6 b7')\n", + "test = [relation.subs([b1 == 0, b2 == 1, b3 == 0, b4 == 1]) for relation in relations]\n", + "\n", + "plt = line([(-2*sqrt(3), 1), (2*sqrt(3), 1)])\n", + "plt += line([(-2*sqrt(3), -1), (2*sqrt(3), -1)])\n", + "plt += circle((-sqrt(3), 0), 1)\n", + "plt += circle((-1/3 * sqrt(3), -2/3), 1/3)\n", + "plt += circle((0, -3/4), 1/4)\n", + "plt += circle((1/3 * sqrt(3), -2/3), 1/3)\n", + "plt += circle((sqrt(3), 0), 1)\n", + "\n", + "plt += line([(-sqrt(3), 2*sqrt(3)), (-sqrt(3), -2*sqrt(3))], rgbcolor=(1,0,0))\n", + "plt += line([( sqrt(3), 2*sqrt(3)), ( sqrt(3), -2*sqrt(3))], rgbcolor=(1,0,0))\n", + "\n", + "x, y = var('x y')\n", + "c1 = (x + sqrt(3))^2 + y^2 == 1\n", + "c2 = (x + 1/3*sqrt(3))^2 + (y + 2/3)^2 == 1/9\n", + "c3 = x^2 + (y + 3/4)^2 == 1/16\n", + "i1 = solve([c1, c2], [x, y])[0]\n", + "x1 = i1[0].rhs()\n", + "y1 = i1[1].rhs()\n", + "i2 = solve([c2, c3], [x, y])[0]\n", + "x2 = i2[0].rhs()\n", + "y2 = i2[1].rhs()\n", + "\n", + "x, y, r = circle_from_points((-sqrt(3), -1), (-1/3*sqrt(3), -1), (x1, y1))\n", + "print('({}, {})\\t{}'.format(x, y, r))\n", + "\n", + "plt += circle((x, y), r, rgbcolor=(1,0,0))\n", + "plt += circle((-x, y), r, rgbcolor=(1,0,0))\n", + "\n", + "x, y, r = circle_from_points((-1/3*sqrt(3), -1), (0, -1), (x2, y2))\n", + "print('({}, {})\\t{}'.format(x, y, r))\n", + "\n", + "plt += circle((x, y), r, rgbcolor=(1,0,0))\n", + "plt += circle((-x, y), r, rgbcolor=(1,0,0))\n", + "\n", + "x, y, r = circle_from_points((-sqrt(3), 1), (x1, y1), (sqrt(3), 1))\n", + "print('({}, {})\\t{}'.format(x, y, r))\n", + "\n", + "plt += circle((x, y), r, rgbcolor=(1, 0, 0))\n", + "\n", + "show(plt)" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[b_{5} = b_{2} - 2 \\, b_{3} + 2 \\, b_{4}, b_{6} = 2 \\, b_{2} - 3 \\, b_{3} + 2 \\, b_{4}, b_{7} = 2 \\, b_{2} - 2 \\, b_{3} + b_{4}\\right]$$" + ], + "text/plain": [ + "[b5 == b2 - 2*b3 + 2*b4, b6 == 2*b2 - 3*b3 + 2*b4, b7 == 2*b2 - 2*b3 + b4]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}6 \\, b_{1}^{2} - 4 \\, b_{1} b_{2} + \\frac{2}{3} \\, b_{2}^{2} + 4 \\, b_{1} b_{3} - 4 \\, b_{2} b_{3} + 6 \\, b_{3}^{2} - 4 \\, b_{1} b_{4} - \\frac{4}{3} \\, b_{2} b_{4} - 4 \\, b_{3} b_{4} + \\frac{2}{3} \\, b_{4}^{2}$$" + ], + "text/plain": [ + "6*b1^2 - 4*b1*b2 + 2/3*b2^2 + 4*b1*b3 - 4*b2*b3 + 6*b3^2 - 4*b1*b4 - 4/3*b2*b4 - 4*b3*b4 + 2/3*b4^2" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "relations, Q, nqform = ngon_linear_relations_and_quadratic_form(6)\n", + "show(relations)\n", + "show(simplify(8 * nqform))" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[b5 == -1/2*b3*(sqrt(5) + 3) + 1/2*b4*(sqrt(5) + 3) + b2, b6 == -1/2*b3*(3*sqrt(5) + 5) + 1/2*b2*(sqrt(5) + 3) + b4*(sqrt(5) + 2), b7 == b4*(sqrt(5) + 3) + b2*(sqrt(5) + 2) - 2*b3*(sqrt(5) + 2), b8 == -b3*(2*sqrt(5) + 5) + b2*(sqrt(5) + 3) + b4*(sqrt(5) + 3), b9 == b2*(sqrt(5) + 3) - 2*b3*(sqrt(5) + 2) + b4*(sqrt(5) + 2), b10 == -1/2*b3*(3*sqrt(5) + 5) + 1/2*b4*(sqrt(5) + 3) + b2*(sqrt(5) + 2), b11 == 1/2*b2*(sqrt(5) + 3) - 1/2*b3*(sqrt(5) + 3) + b4]\n" + ] + } + ], + "source": [ + "relations, Q, nqform = ngon_linear_relations_and_quadratic_form(10)\n", + "print(relations)" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-1/2*b2*bt1 - 1/2*b1*bt2 + h11*h12 + h21*h22" + ] + }, + "execution_count": 71, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec1 = vector([var('bt1'), var('b1'), var('h11'), var('h21')])\n", + "vec2 = vector([var('bt2'), var('b2'), var('h12'), var('h22')])\n", + "vec1 * P * vec2" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}-\\frac{2 \\, \\sin\\left(\\frac{\\pi k}{n}\\right)^{2}}{\\sin\\left(\\frac{\\pi}{n}\\right)^{2}} + 1$$" + ], + "text/plain": [ + "-2*sin(pi*k/n)^2/sin(pi/n)^2 + 1" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "k = var('k', domain=RR)\n", + "n = var('n', domain=RR)\n", + "\n", + "c1 = 1\n", + "c2i = sin(2 * pi * k / n)\n", + "c2r = cos(2 * pi * k / n)\n", + "\n", + "dist = sin(pi * k / n)\n", + "r = dist.subs(k==1) / 2\n", + "dist /= r\n", + "\n", + "bf = 1/2 * (1 + 1 * (1 - dist^2))\n", + "show(bf)" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 \t 0\n", + "1 \t x - 1\n", + "2 \t 2*x^2 - 2\n", + "3 \t 4*x^3 - 3*x - 1\n", + "4 \t 8*x^4 - 8*x^2\n", + "5 \t 16*x^5 - 20*x^3 + 5*x - 1\n", + "6 \t 32*x^6 - 48*x^4 + 18*x^2 - 2\n", + "7 \t 64*x^7 - 112*x^5 + 56*x^3 - 7*x - 1\n", + "8 \t 128*x^8 - 256*x^6 + 160*x^4 - 32*x^2\n", + "9 \t 256*x^9 - 576*x^7 + 432*x^5 - 120*x^3 + 9*x - 1\n", + "10 \t 512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 2\n" + ] + } + ], + "source": [ + "T = []\n", + "x = var('x')\n", + "T.append(1)\n", + "T.append(x)\n", + "\n", + "def nextT():\n", + " i = len(T)\n", + " T.append(expand(2 * x * T[i - 1] - T[i - 2]))\n", + " #print(i, '\\t', T[i] - 1)\n", + " \n", + "for _ in range(9):\n", + " nextT()\n", + "\n", + "for i, poly in enumerate(T):\n", + " print(i, '\\t', poly - 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-x^6 + x^5 + x^4 - x^3 - 2*x^2 + 2*x" + ] + }, + "execution_count": 74, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "expand(x * (1 - x) * (x^4 - x^2 + 2))" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": {}, + "outputs": [], + "source": [ + "S1 = matrix([\n", + " [-1, 0, 0, 2],\n", + " [0, 1, 0, 0],\n", + " [0, 0, 1, 0],\n", + " [0, 0, 0, 1],\n", + "])\n", + "S2 = matrix([\n", + " [1, 0, 0, 0],\n", + " [0, -1, 0, 2],\n", + " [0, 0, 1, 0],\n", + " [0, 0, 0, 1],\n", + "])\n", + "S3 = matrix([\n", + " [1, 0, 0, 0],\n", + " [0, 1, 0, 0],\n", + " [0, 0, -1, 2],\n", + " [0, 0, 0, 1],\n", + "])\n", + "S4 = matrix([\n", + " [1, 0, 0, 0],\n", + " [0, 1, 0, 0],\n", + " [0, 0, 1, 0],\n", + " [2, 2, 2, -1],\n", + "])\n", + "Ss = [S4, S4 * S1, S4 * S1 * S2, S4 * S1 * S3, S4 * S1 * S2 * S3, S4 * S2, S4 * S2 * S3, S4 * S3]\n", + "v1 = vector(var('b' + str(i + 1)) for i in range(4))\n", + "v2 = vector(var('b' + str(i + 1)) for i in range(6))\n", + "temp = [matrix * v1 for matrix in Ss]\n", + "new = []\n", + "for blah in temp:\n", + " new.append([var('b' + str(i+1) + 'p') == blah[i] for i in range(len(blah))])\n", + "\n", + "for eqs in new:\n", + " for i in range(len(eqs)):\n", + " eqs[i] = eqs[i].subs(var('b4') == var('b1') + var('b6'))\n", + " eqs[i] = eqs[i].subs(var('b4p') == var('b1p') + var('b6p'))" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[b_{1} = b_{1}, b_{2} = b_{2}, b_{3} = b_{3}, b_{4} = b_{1} + b_{2} - b_{3}, b_{5} = b_{4}, b_{6} = b_{2} - b_{3} - b_{4}\\right]$$" + ], + "text/plain": [ + "[b1 == b1,\n", + " b2 == b2,\n", + " b3 == b3,\n", + " b4 == b1 + b2 - b3,\n", + " b5 == b4,\n", + " b6 == b2 - b3 - b4]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[b_{4}, b_{5}, b_{6}\\right]$$" + ], + "text/plain": [ + "[b4, b5, b6]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[b_{1} = b_{1}, b_{2} = b_{2}, b_{3} = b_{3}, b_{4} = b_{1} + b_{2} - b_{3}, b_{5} = b_{4}, b_{6} = b_{2} - b_{3} - b_{4}\\right]$$" + ], + "text/plain": [ + "[b1 == b1,\n", + " b2 == b2,\n", + " b3 == b3,\n", + " b4 == b1 + b2 - b3,\n", + " b5 == b4,\n", + " b6 == b2 - b3 - b4]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", + "4 & 0 & -2 & 2 \\\\\n", + "0 & 4 & -2 & 2 \\\\\n", + "-2 & -2 & 1 & -3 \\\\\n", + "2 & 2 & -3 & 9\n", + "\\end{array}\\right)$$" + ], + "text/plain": [ + "[ 4 0 -2 2]\n", + "[ 0 4 -2 2]\n", + "[-2 -2 1 -3]\n", + "[ 2 2 -3 9]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}4 \\, b_{0}^{2} + 4 \\, b_{1}^{2} - 4 \\, b_{0} b_{2} - 4 \\, b_{1} b_{2} + b_{2}^{2} + 4 \\, b_{0} b_{3} + 4 \\, b_{1} b_{3} - 6 \\, b_{2} b_{3} + 9 \\, b_{3}^{2}$$" + ], + "text/plain": [ + "4*b0^2 + 4*b1^2 - 4*b0*b2 - 4*b1*b2 + b2^2 + 4*b0*b3 + 4*b1*b3 - 6*b2*b3 + 9*b3^2" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", + "-1 & 0 & 1 & -1 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & -1 & 1 & -1 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "4 & 4 & -1 & 6 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "-\\frac{4}{9} & -\\frac{4}{9} & \\frac{2}{3} & -1\n", + "\\end{array}\\right)\\right]$$" + ], + "text/plain": [ + "[\n", + "[-1 0 1 -1] [ 1 0 0 0] [ 1 0 0 0] [ 1 0 0 0]\n", + "[ 0 1 0 0] [ 0 -1 1 -1] [ 0 1 0 0] [ 0 1 0 0]\n", + "[ 0 0 1 0] [ 0 0 1 0] [ 4 4 -1 6] [ 0 0 1 0]\n", + "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1], [-4/9 -4/9 2/3 -1]\n", + "]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "W = matrix([\n", + " [2, 0, 0, 1],\n", + " [4, 2, 0, -1],\n", + " [2, 0, 0, -1],\n", + " [4, 2, 0, 1],\n", + " [1, 1, sqrt(2), 0],\n", + " [1, 1, -sqrt(2), 0],\n", + "])\n", + "\n", + "relations, Q, nqform = linear_relations_and_quadratic_form_from_wtpw(W * P * W.transpose())#, [1, 2, 3, 4, 5, 6])\n", + "show(relations)\n", + "show(8 * Q)\n", + "show(8 * nqform)\n", + "show(weyl_generators(8 * Q, standard_basis(4)))" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": {}, + "outputs": [], + "source": [ + "def diagonalize(mat):\n", + " eigs = WPWT.eigenvectors_right()\n", + " eigvs = []\n", + " eigvals = []\n", + " for eig in eigs:\n", + " for eigv in eig[1]:\n", + " eigvs.append(eigv)\n", + " for _ in range(eig[2]):\n", + " eigvals.append(eig[0])\n", + " Q = matrix(eigvs)\n", + " D = diagonal_matrix(eigvals)\n", + " return (Q, D)" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrrrrrr}\n", + "-1 & 2 & 6 & 2 & 10 & 6 & 2 & 6 \\\\\n", + "0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrrrrrr}\n", + "1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "2 & -1 & 2 & 6 & 6 & 10 & 6 & 2 \\\\\n", + "0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrrrrrr}\n", + "1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "6 & 2 & -1 & 2 & 2 & 6 & 10 & 6 \\\\\n", + "0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrrrrrr}\n", + "1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "2 & 6 & 2 & -1 & 6 & 2 & 6 & 10 \\\\\n", + "0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrrrrrr}\n", + "1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\\\\n", + "10 & 6 & 2 & 6 & -1 & 2 & 6 & 2 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrrrrrr}\n", + "1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\\n", + "6 & 10 & 6 & 2 & 2 & -1 & 2 & 6 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrrrrrr}\n", + "1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\\\n", + "2 & 6 & 10 & 6 & 6 & 2 & -1 & 2 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrrrrrr}\n", + "1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\\\\n", + "6 & 2 & 6 & 10 & 2 & 6 & 2 & -1\n", + "\\end{array}\\right)\\right]$$" + ], + "text/plain": [ + "[\n", + "[-1 2 6 2 10 6 2 6] [ 1 0 0 0 0 0 0 0]\n", + "[ 0 1 0 0 0 0 0 0] [ 2 -1 2 6 6 10 6 2]\n", + "[ 0 0 1 0 0 0 0 0] [ 0 0 1 0 0 0 0 0]\n", + "[ 0 0 0 1 0 0 0 0] [ 0 0 0 1 0 0 0 0]\n", + "[ 0 0 0 0 1 0 0 0] [ 0 0 0 0 1 0 0 0]\n", + "[ 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 1 0 0]\n", + "[ 0 0 0 0 0 0 1 0] [ 0 0 0 0 0 0 1 0]\n", + "[ 0 0 0 0 0 0 0 1], [ 0 0 0 0 0 0 0 1],\n", + "\n", + "[ 1 0 0 0 0 0 0 0] [ 1 0 0 0 0 0 0 0]\n", + "[ 0 1 0 0 0 0 0 0] [ 0 1 0 0 0 0 0 0]\n", + "[ 6 2 -1 2 2 6 10 6] [ 0 0 1 0 0 0 0 0]\n", + "[ 0 0 0 1 0 0 0 0] [ 2 6 2 -1 6 2 6 10]\n", + "[ 0 0 0 0 1 0 0 0] [ 0 0 0 0 1 0 0 0]\n", + "[ 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 1 0 0]\n", + "[ 0 0 0 0 0 0 1 0] [ 0 0 0 0 0 0 1 0]\n", + "[ 0 0 0 0 0 0 0 1], [ 0 0 0 0 0 0 0 1],\n", + "\n", + "[ 1 0 0 0 0 0 0 0] [ 1 0 0 0 0 0 0 0]\n", + "[ 0 1 0 0 0 0 0 0] [ 0 1 0 0 0 0 0 0]\n", + "[ 0 0 1 0 0 0 0 0] [ 0 0 1 0 0 0 0 0]\n", + "[ 0 0 0 1 0 0 0 0] [ 0 0 0 1 0 0 0 0]\n", + "[10 6 2 6 -1 2 6 2] [ 0 0 0 0 1 0 0 0]\n", + "[ 0 0 0 0 0 1 0 0] [ 6 10 6 2 2 -1 2 6]\n", + "[ 0 0 0 0 0 0 1 0] [ 0 0 0 0 0 0 1 0]\n", + "[ 0 0 0 0 0 0 0 1], [ 0 0 0 0 0 0 0 1],\n", + "\n", + "[ 1 0 0 0 0 0 0 0] [ 1 0 0 0 0 0 0 0]\n", + "[ 0 1 0 0 0 0 0 0] [ 0 1 0 0 0 0 0 0]\n", + "[ 0 0 1 0 0 0 0 0] [ 0 0 1 0 0 0 0 0]\n", + "[ 0 0 0 1 0 0 0 0] [ 0 0 0 1 0 0 0 0]\n", + "[ 0 0 0 0 1 0 0 0] [ 0 0 0 0 1 0 0 0]\n", + "[ 0 0 0 0 0 1 0 0] [ 0 0 0 0 0 1 0 0]\n", + "[ 2 6 10 6 6 2 -1 2] [ 0 0 0 0 0 0 1 0]\n", + "[ 0 0 0 0 0 0 0 1], [ 6 2 6 10 2 6 2 -1]\n", + "]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ 1 -1 -3 -1 -5 -3 -1 -3]\n", + "[-1 1 -1 -3 -3 -5 -3 -1]\n", + "[-3 -1 1 -1 -1 -3 -5 -3]\n", + "[-1 -3 -1 1 -3 -1 -3 -5]\n", + "[-5 -3 -1 -3 1 -1 -3 -1]\n", + "[-3 -5 -3 -1 -1 1 -1 -3]\n", + "[-1 -3 -5 -3 -3 -1 1 -1]\n", + "[-3 -1 -3 -5 -1 -3 -1 1]\n" + ] + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrrrrrr}\n", + "-16 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 8 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 8 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 8 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\n", + "\\end{array}\\right)$$" + ], + "text/plain": [ + "[-16 0 0 0 0 0 0 0]\n", + "[ 0 8 0 0 0 0 0 0]\n", + "[ 0 0 8 0 0 0 0 0]\n", + "[ 0 0 0 8 0 0 0 0]\n", + "[ 0 0 0 0 0 0 0 0]\n", + "[ 0 0 0 0 0 0 0 0]\n", + "[ 0 0 0 0 0 0 0 0]\n", + "[ 0 0 0 0 0 0 0 0]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrrrrrr}\n", + "1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 \\\\\n", + "1 & 0 & 0 & 1 & -1 & 0 & 0 & -1 \\\\\n", + "0 & 1 & 0 & -1 & 0 & -1 & 0 & 1 \\\\\n", + "0 & 0 & 1 & 1 & 0 & 0 & -1 & -1 \\\\\n", + "1 & 0 & 0 & -1 & 0 & 1 & -1 & 0 \\\\\n", + "0 & 1 & 0 & -1 & 0 & 1 & 0 & -1 \\\\\n", + "0 & 0 & 1 & -1 & 0 & 0 & 1 & -1 \\\\\n", + "0 & 0 & 0 & 0 & 1 & -1 & 1 & -1\n", + "\\end{array}\\right)$$" + ], + "text/plain": [ + "[ 1 1 1 1 1 1 1 1]\n", + "[ 1 0 0 1 -1 0 0 -1]\n", + "[ 0 1 0 -1 0 -1 0 1]\n", + "[ 0 0 1 1 0 0 -1 -1]\n", + "[ 1 0 0 -1 0 1 -1 0]\n", + "[ 0 1 0 -1 0 1 0 -1]\n", + "[ 0 0 1 -1 0 0 1 -1]\n", + "[ 0 0 0 0 1 -1 1 -1]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0, 0\t\t[1/8]\n", + "0, 1\t\t[0]\n", + "0, 2\t\t[0]\n", + "0, 3\t\t[0]\n", + "0, 4\t\t[0]\n", + "0, 5\t\t[0]\n", + "1, 0\t\t[0]\n", + "1, 1\t\t[3/8]\n", + "1, 2\t\t[1/8]\n", + "1, 3\t\t[-1/8]\n", + "1, 4\t\t[0]\n", + "1, 5\t\t[0]\n", + "2, 0\t\t[0]\n", + "2, 1\t\t[1/8]\n", + "2, 2\t\t[3/8]\n", + "2, 3\t\t[1/8]\n", + "2, 4\t\t[0]\n", + "2, 5\t\t[0]\n", + "3, 0\t\t[0]\n", + "3, 1\t\t[-1/8]\n", + "3, 2\t\t[1/8]\n", + "3, 3\t\t[3/8]\n", + "3, 4\t\t[0]\n", + "3, 5\t\t[0]\n", + "4, 0\t\t[0]\n", + "4, 1\t\t[0]\n", + "4, 2\t\t[0]\n", + "4, 3\t\t[0]\n", + "4, 4\t\t[1/2]\n", + "4, 5\t\t[-1/4]\n", + "5, 0\t\t[0]\n", + "5, 1\t\t[0]\n", + "5, 2\t\t[0]\n", + "5, 3\t\t[0]\n", + "5, 4\t\t[-1/4]\n", + "5, 5\t\t[1/2]\n" + ] + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrrrrrr}\n", + "1 & -1 & -3 & -1 & -5 & -3 & -1 & -3 \\\\\n", + "-1 & 1 & -1 & -3 & -3 & -5 & -3 & -1 \\\\\n", + "-3 & -1 & 1 & -1 & -1 & -3 & -5 & -3 \\\\\n", + "-1 & -3 & -1 & 1 & -3 & -1 & -3 & -5 \\\\\n", + "-5 & -3 & -1 & -3 & 1 & -1 & -3 & -1 \\\\\n", + "-3 & -5 & -3 & -1 & -1 & 1 & -1 & -3 \\\\\n", + "-1 & -3 & -5 & -3 & -3 & -1 & 1 & -1 \\\\\n", + "-3 & -1 & -3 & -5 & -1 & -3 & -1 & 1\n", + "\\end{array}\\right)$$" + ], + "text/plain": [ + "[ 1 -1 -3 -1 -5 -3 -1 -3]\n", + "[-1 1 -1 -3 -3 -5 -3 -1]\n", + "[-3 -1 1 -1 -1 -3 -5 -3]\n", + "[-1 -3 -1 1 -3 -1 -3 -5]\n", + "[-5 -3 -1 -3 1 -1 -3 -1]\n", + "[-3 -5 -3 -1 -1 1 -1 -3]\n", + "[-1 -3 -5 -3 -3 -1 1 -1]\n", + "[-3 -1 -3 -5 -1 -3 -1 1]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "WPWT = matrix([\n", + " [1, -1, -3, -1, -5, -3, -1, -3],\n", + " [-1, 1, -1, -3, -3, -5, -3, -1],\n", + " [-3, -1, 1, -1, -1, -3, -5, -3],\n", + " [-1, -3, -1, 1, -3, -1, -3, -5],\n", + " [-5, -3, -1, -3, 1, -1, -3, -1],\n", + " [-3, -5, -3, -1, -1, 1, -1, -3],\n", + " [-1, -3, -5, -3, -3, -1, 1, -1],\n", + " [-3, -1, -3, -5, -1, -3, -1, 1]\n", + "])\n", + "show(weyl_generators(WPWT, standard_basis(8)))\n", + "# WPWT = W * P * W.transpose()\n", + "Q, D = diagonalize(WPWT) \n", + "print(WPWT)\n", + "show(D)\n", + "show(Q)\n", + "Qi = expand(Q.inverse())\n", + "for i in range(6):\n", + " for j in range(6):\n", + " print('{}, {}\\t\\t{}'.format(i, j, expand(Qi[:,i].transpose() * Qi[:,j])))\n", + "show(expand(Q.inverse() * D * Q))" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(1,\\,1,\\,-\\frac{1}{3},\\,-\\frac{1}{3}\\right)$$" + ], + "text/plain": [ + "(1, 1, -1/3, -1/3)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(1,\\,-\\frac{1}{3},\\,1,\\,-\\frac{1}{3}\\right)$$" + ], + "text/plain": [ + "(1, -1/3, 1, -1/3)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(1,\\,-3,\\,-3,\\,1\\right)$$" + ], + "text/plain": [ + "(1, -3, -3, 1)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(1,\\,-\\frac{1}{3},\\,-\\frac{1}{3},\\,1\\right)$$" + ], + "text/plain": [ + "(1, -1/3, -1/3, 1)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(1,\\,-3,\\,1,\\,-3\\right)$$" + ], + "text/plain": [ + "(1, -3, 1, -3)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(1,\\,1,\\,-3,\\,-3\\right)$$" + ], + "text/plain": [ + "(1, 1, -3, -3)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "S1 = matrix([\n", + " [1, 0, 3, 3],\n", + " [0, 1, 3, 3],\n", + " [0, 0, 0, -1],\n", + " [0, 0, -1, 0]\n", + "]).transpose()\n", + "S2 = matrix([\n", + " [1, 3, 0, 3],\n", + " [0, 0, 0, -1],\n", + " [0, 3, 1, 3],\n", + " [0, -1, 0, 0]\n", + "]).transpose()\n", + "S3 = matrix([\n", + " [0, 0, 0, -1],\n", + " [3, 1, 0, 3],\n", + " [3, 0, 1, 3],\n", + " [-1, 0, 0, 0]\n", + "]).transpose()\n", + "S4 = matrix([\n", + " [1, 3, 3, 0],\n", + " [0, 0, -1, 0],\n", + " [0, -1, 0, 0],\n", + " [0, 3, 3, 1]\n", + "]).transpose()\n", + "S5 = matrix([\n", + " [0, 0, -1, 0],\n", + " [3, 1, 3, 0],\n", + " [-1, 0, 0, 0],\n", + " [3, 0, 3, 1]\n", + "]).transpose()\n", + "S6 = matrix([\n", + " [0, -1, 0, 0],\n", + " [-1, 0, 0, 0],\n", + " [3, 3, 1, 0],\n", + " [3, 3, 0, 1]\n", + "]).transpose()\n", + "\n", + "for mat in [S1, S2, S3, S4, S5, S6]:\n", + " for eigvec in mat.eigenvectors_left():\n", + " if (eigvec[0] == -1):\n", + " show(eigvec[1][0])" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[b_{1} = b_{1}, b_{2} = b_{2}, b_{3} = b_{3}, b_{4} = b_{4}, b_{5} = \\frac{1}{2} \\, b_{1} + \\frac{1}{2} \\, b_{2} + \\frac{1}{2} \\, b_{3} - \\frac{1}{2} \\, b_{4}, b_{6} = \\frac{1}{2} \\, b_{1} + \\frac{1}{2} \\, b_{2} - \\frac{1}{2} \\, b_{3} + \\frac{1}{2} \\, b_{4}, b_{7} = \\frac{1}{2} \\, b_{1} - \\frac{1}{2} \\, b_{2} + \\frac{1}{2} \\, b_{3} + \\frac{1}{2} \\, b_{4}, b_{8} = -\\frac{1}{2} \\, b_{1} + \\frac{1}{2} \\, b_{2} + \\frac{1}{2} \\, b_{3} + \\frac{1}{2} \\, b_{4}\\right]$$" + ], + "text/plain": [ + "[b1 == b1,\n", + " b2 == b2,\n", + " b3 == b3,\n", + " b4 == b4,\n", + " b5 == 1/2*b1 + 1/2*b2 + 1/2*b3 - 1/2*b4,\n", + " b6 == 1/2*b1 + 1/2*b2 - 1/2*b3 + 1/2*b4,\n", + " b7 == 1/2*b1 - 1/2*b2 + 1/2*b3 + 1/2*b4,\n", + " b8 == -1/2*b1 + 1/2*b2 + 1/2*b3 + 1/2*b4]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[b_{5}, b_{6}, b_{7}, b_{8}\\right]$$" + ], + "text/plain": [ + "[b5, b6, b7, b8]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[2 \\, b_{1} = 2 \\, b_{1}, 2 \\, b_{2} = 2 \\, b_{2}, 2 \\, b_{3} = 2 \\, b_{3}, 2 \\, b_{4} = 2 \\, b_{4}, 2 \\, b_{5} = b_{1} + b_{2} + b_{3} - b_{4}, 2 \\, b_{6} = b_{1} + b_{2} - b_{3} + b_{4}, 2 \\, b_{7} = b_{1} - b_{2} + b_{3} + b_{4}, 2 \\, b_{8} = -b_{1} + b_{2} + b_{3} + b_{4}\\right]$$" + ], + "text/plain": [ + "[2*b1 == 2*b1,\n", + " 2*b2 == 2*b2,\n", + " 2*b3 == 2*b3,\n", + " 2*b4 == 2*b4,\n", + " 2*b5 == b1 + b2 + b3 - b4,\n", + " 2*b6 == b1 + b2 - b3 + b4,\n", + " 2*b7 == b1 - b2 + b3 + b4,\n", + " 2*b8 == -b1 + b2 + b3 + b4]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left(\\begin{array}{rrrr}\n", + "\\frac{5}{4} & -\\frac{3}{4} & -\\frac{3}{4} & -\\frac{3}{4} \\\\\n", + "-\\frac{3}{4} & \\frac{5}{4} & -\\frac{3}{4} & -\\frac{3}{4} \\\\\n", + "-\\frac{3}{4} & -\\frac{3}{4} & \\frac{5}{4} & -\\frac{3}{4} \\\\\n", + "-\\frac{3}{4} & -\\frac{3}{4} & -\\frac{3}{4} & \\frac{5}{4}\n", + "\\end{array}\\right)$$" + ], + "text/plain": [ + "[ 5/4 -3/4 -3/4 -3/4]\n", + "[-3/4 5/4 -3/4 -3/4]\n", + "[-3/4 -3/4 5/4 -3/4]\n", + "[-3/4 -3/4 -3/4 5/4]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\frac{5}{4} \\, b_{1}^{2} - \\frac{3}{2} \\, b_{1} b_{2} + \\frac{5}{4} \\, b_{2}^{2} - \\frac{3}{2} \\, b_{1} b_{3} - \\frac{3}{2} \\, b_{2} b_{3} + \\frac{5}{4} \\, b_{3}^{2} - \\frac{3}{2} \\, b_{1} b_{4} - \\frac{3}{2} \\, b_{2} b_{4} - \\frac{3}{2} \\, b_{3} b_{4} + \\frac{5}{4} \\, b_{4}^{2}$$" + ], + "text/plain": [ + "5/4*b1^2 - 3/2*b1*b2 + 5/4*b2^2 - 3/2*b1*b3 - 3/2*b2*b3 + 5/4*b3^2 - 3/2*b1*b4 - 3/2*b2*b4 - 3/2*b3*b4 + 5/4*b4^2" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/latex": [ + "$$\\newcommand{\\Bold}[1]{\\mathbf{#1}}\\left[\\left(\\begin{array}{rrrr}\n", + "-1 & \\frac{6}{5} & \\frac{6}{5} & \\frac{6}{5} \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "\\frac{6}{5} & -1 & \\frac{6}{5} & \\frac{6}{5} \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "\\frac{6}{5} & \\frac{6}{5} & -1 & \\frac{6}{5} \\\\\n", + "0 & 0 & 0 & 1\n", + "\\end{array}\\right), \\left(\\begin{array}{rrrr}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "\\frac{6}{5} & \\frac{6}{5} & \\frac{6}{5} & -1\n", + "\\end{array}\\right)\\right]$$" + ], + "text/plain": [ + "[\n", + "[ -1 6/5 6/5 6/5] [ 1 0 0 0] [ 1 0 0 0]\n", + "[ 0 1 0 0] [6/5 -1 6/5 6/5] [ 0 1 0 0]\n", + "[ 0 0 1 0] [ 0 0 1 0] [6/5 6/5 -1 6/5]\n", + "[ 0 0 0 1], [ 0 0 0 1], [ 0 0 0 1],\n", + "\n", + "[ 1 0 0 0]\n", + "[ 0 1 0 0]\n", + "[ 0 0 1 0]\n", + "[6/5 6/5 6/5 -1]\n", + "]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# cubical\n", + "Wc = matrix([\n", + " [4, 0, 0, 1],\n", + " [0, 2, 0, 1],\n", + " [2, 1, -sqrt(2), -1],\n", + " [2, 1, sqrt(2), -1],\n", + " [2, 1, -sqrt(2), 1],\n", + " [2, 1, sqrt(2), 1],\n", + " [4, 0, 0, -1],\n", + " [0, 2, 0, -1],\n", + "])\n", + "relation, mat, equation = linear_relations_and_quadratic_form_from_wtpw(Wc * P * Wc.transpose(), [1, 2, 3, 4, 5, 6, 7, 8])\n", + "show([2 * eq for eq in relation])\n", + "show(8 * mat)\n", + "show(8 * equation)\n", + "show(weyl_generators(mat, standard_basis(4)))" ] } ], "metadata": { "kernelspec": { - "display_name": "SageMath 9.2", + "display_name": "SageMath 9.3", "language": "sage", "name": "sagemath" }, @@ -1689,7 +3315,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.2" + "version": "3.9.5" }, "name": "Apollonian Circle Packings.ipynb" },