{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Elliptic curves\n", "\n", "An elliptic curve $E$ is a set of points satisfying an equation of form\n", "$$\n", "y^2 = x^3 + ax + b,\n", "$$\n", "where $4a^3 + 27b^2 \\ne 0$,\n", "together with a \"point at infinity\", denoted by $\\mathcal{O}$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us first draw a graph of a cubic polynomial, followed by the corresponding elliptic curve." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@interact\n", "def _(a=slider(-5, 5, default=-2),\n", " b=slider(-5, 5, default=-2),\n", " xr=range_slider(-10, 10, default=(-3, 3), label=\"x range\"),\n", " yr=range_slider(-10, 10, default=(-5, 5), label=\"y range\")):\n", " x, y = var('x y')\n", " E = x^3 + a*x + b\n", " xlim = (x, *xr)\n", " ylim = (y, *yr)\n", " show(plot(E, xlim))\n", " show(implicit_plot(y^2 == E, xlim, ylim, frame=False, axes=True))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us now demonstrate the group addition operation on the elliptic curve." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@interact\n", "def _(a=slider(-5, 5, default=-2),\n", " b=slider(-5, 5, default=-2),\n", " Px=slider(-10, 10, default=2),\n", " Ps=slider([\"-\", \"+\"], default=\"+\", label=\"Py sign\"),\n", " Qx=slider(-10, 10, default=3),\n", " Qs=slider([\"-\", \"+\"], default=\"-\", label=\"Qy sign\"),\n", " xr=range_slider(-10, 10, default=(-3, 3), label=\"x range\"),\n", " yr=range_slider(-10, 10, default=(-5, 5), label=\"y range\")):\n", " x, y = var('x y')\n", " s = {\"+\": 1, \"-\": -1}\n", " E = x^3 + a*x + b\n", " pts = []\n", " Py = s[Ps] * sqrt(E.subs(x == Px))\n", " if Py.is_real():\n", " pts.append((Px, Py))\n", " Qy = s[Qs] * sqrt(E.subs(x == Qx))\n", " if Qy.is_real():\n", " pts.append((Qx, Qy))\n", " xlim = (x, *xr)\n", " ylim = (y, *yr)\n", " p = implicit_plot(y^2 == E, xlim, ylim, frame=False, axes=True)\n", " if pts:\n", " p += point(pts, color=\"red\", size=50)\n", " if len(pts) > 1:\n", " if pts[0] == pts[1] and Py != 0:\n", " lm = (3*Px^2 + a)/(2*Py)\n", " elif Px != Qx:\n", " lm = (Py - Qy)/(Px - Qx)\n", " else:\n", " pts += [(Px, yr[0]), (Px, yr[1])]\n", " if len(pts) == 2:\n", " Rx = lm^2 - Px - Qx\n", " Ry = lm * (Px - Rx) - Py\n", " R = [(Rx, Ry), (Rx, -Ry)]\n", " pts.append(R[1])\n", " p += point(R[0], color=\"magenta\", size=50)\n", " p += point(R[1], color=\"brown\", size=50)\n", " if Ry != 0:\n", " p += line2d(R, color=\"cyan\")\n", " p += line2d(pts, color=\"green\")\n", " show(p, xmin=xr[0], xmax=xr[1], ymin=yr[0], ymax=yr[1])" ] } ], "metadata": { "kernelspec": { "display_name": "SageMath 9.2.rc2", "language": "sage", "name": "sagemath" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }