1

I'm wondering, if there is a better and faster way to plot elliptic curves in LaTeX. So far im using the following Code:

\begin{tikzpicture}
            \begin{axis}[
            scale = \scale,
            xmin=-1,
            xmax=5,
            ymin=-3,
            ymax=3,
            xlabel={$x$},
            ylabel={$y$},
            scale only axis,
            axis lines=middle,
            domain=-3:3,
            samples=\sample,
            smooth,
            % to avoid that the "plot node" is clipped (partially)
            clip=false,
            % use same unit vectors on the axis
            axis equal image=true,
            ]
            \addplot [line width=\thick,domain=2.10381:2.5,] {sqrt((x^3-3*x-3))};
            \addplot [line width=\thick,domain=2.10381:2.5,] {-sqrt((x^3-3*x-3))};
            \end{axis}
\end{tikzpicture}

The Problem here is, that it takes a lot of time to find the solutions for y = 0 and then getting the right approximation. ( This can be seen in \addplot after domain ).

The Result should look like: enter image description here

Without finding the solution and getting a correkt approximation, there is a gap between the top and the bot curve.

  • 2
    Note it is always a good idea to provide a full minimal example others can copy and test as is. Here you only post a sniplet and we have to guess the rest. – daleif Mar 17 at 16:20
  • Here I'd probably use the standalone class, then run it though lualatex (it has more memory) and then include the resulting PDF in document where you need this image. That way it only needs to be compiled once (and is allowed to take some time). – daleif Mar 17 at 16:21
3

xmin is the solution of a simple cubic equation. Sorry about the \edef\temp hacks, has to do with the way how pgfplots does its plots. As remarked in the comments, your code fragment has too many unknowns.

\documentclass[fleqn]{article}
\usepackage{dsfont}
\usepackage[margin=2cm]{geometry}
\usepackage{pgfplots}
\usetikzlibrary{calc,intersections}
\usepgfplotslibrary{groupplots}
\pgfplotsset{compat=1.16}
\newcommand{\MyGroupPlot}{
    \edef\temp{\noexpand\nextgroupplot[title={$A=\mya,B=\myb$},xmin=\myxmin-0.5,xmax=\myxmin+\myd+0.5]
      \noexpand\addplot [thick,domain=\myxmin:\myxmin+\myd,smooth] {ysol(x,\mya,\myb)};
      \noexpand\addplot [thick,domain=\myxmin:\myxmin+\myd,smooth] {-ysol(x,\mya,\myb)};
      \noexpand\addplot [smooth,thick] coordinates {({\myxmin+min(\myd,1)/20},{-ysol(\myxmin+min(\myd,1)/20,\mya,\myb)})
        ({\myxmin+min(\myd,1)/40},{-ysol(\myxmin+min(\myd,1)/40,\mya,\myb)})
        (\myxmin,0) ({\myxmin+min(\myd,1)/40},{ysol(\myxmin+min(\myd,1)/40,\mya,\myb)})
        ({\myxmin+min(\myd,1)/20},{ysol(\myxmin+min(\myd,1)/20,\mya,\myb)})};}
    \temp
}
\begin{document}
In order to plot the points $(x,y)\in\mathds{R}^2$ that satisfy
\[ y^2=x^3+a\,x+b\;,\]
let us first find the $x$ for which $y=0$. This is a cubic equation with the
solution
\[x_0=\frac{\sqrt[3]{2} \left(\sqrt{12 a^3+81 b^2}-9
   b\right)^{2/3}-2 \sqrt[3]{3} a}{6^{2/3}
   \sqrt[3]{\sqrt{12 a^3+81 b^2}-9 b}}\;.\]
This determines the lower end, $x_\mathrm{min}$, of the plot interval in
Figure~\ref{fig:elliptic}. 

\begin{figure}[h]
\centering
 \begin{tikzpicture}[declare function={xnod(\a,\b)=0.001+%
 (-2*pow(3,1/3)*\a + pow(2,1/3)*%sign(-9*\b + sqrt(12*pow(\a,3) + 81*pow(\b,2)))*%
 pow(abs(-9*\b + sqrt(12*pow(\a,3) + 81*pow(\b,2))),2/3))/%
 (pow(6,2/3)*sign(-9*\b + sqrt(12*pow(\a,3) +  81*pow(\b,2)))*%
 pow(abs(-9*\b + sqrt(12*pow(\a,3) +  81*pow(\b,2))),1/3));
 ysol(\x,\a,\b)=sqrt((\x*\x*\x+\a*\x+\b));}]
   \begin{groupplot}[group style={group size=3 by 1},
             scale only axis,
             samples=101,            
             % use same unit vectors on the axis
             axis equal image=true,
             ]
     \edef\mya{3}       
     \edef\myb{3}       
     \edef\myd{2}       
     \pgfmathsetmacro{\myxmin}{xnod(\mya,\myb)}
     \MyGroupPlot
     \edef\mya{-3}      
     \edef\myb{3}       
     \edef\myd{4}       
     \pgfmathsetmacro{\myxmin}{xnod(\mya,\myb)}
     \MyGroupPlot
     \edef\mya{-3}      
     \edef\myb{-3}      
     \edef\myd{0.4}     
     \pgfmathsetmacro{\myxmin}{xnod(\mya,\myb)}
     \MyGroupPlot
  \end{groupplot}
 \end{tikzpicture}
\caption{A group plot of elliptic functions.}
\label{fig:elliptic}
\end{figure}
\end{document}

enter image description here

| improve this answer | |
2

I don't know how fast is pgfplots (because you didn't give a MWE so I don't want to test). But here you can plot an elliptic curve in 5 pieces. When the tangent line is not too vertical, the casual sqrt-method suffices.

When the tangent line is close to being vertical, parametrize by y and find x using newton method. Since you know exactly where are the x-intercepts, you have a good guess of the initial x0. And since that guess is already very close to the actual x, you need two iterations, three at most.

\documentclass[tikz,border=9]{standalone}

\begin{document}

% we are to plot y^2 = (x-1)x(x+1)
% the idea is that we know x-intercepts
% don't use standard form ax + b
\let\PMSM=\pgfmathsetmacro
\pgfmathdeclarefunction{f}1{\pgfmathparse{(#1-1)*#1*(#1+1)}}
\pgfmathdeclarefunction{g}1{\pgfmathparse{3*#1*#1-1}} % g = f' = df/d#1
\tikz[cap=round]{
    \draw[->](-1.1,0)--(2,0);
    \draw[->](0,0)--(0,3);
    {% -1 ≤ x ≤ -.9 % plot by newton method
        \pgfpathmoveto{\pgfpointxy{-1}{0}}
        \def\nsample{40}
        \foreach\i in{0,...,\nsample}{
            \PMSM\y{sqrt(f(-.9))*\i/\nsample} % y
            \PMSM\yy{f(-.9)*\i*\i/\nsample/\nsample} % y^2
            % initial x = -1
            \PMSM\x{-1}
            % first iteration
            \PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            % second iteration
            \PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            % third iteration not really necessary
            %\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            \pgfpathlineto{\pgfpointxy{\x}{\y}}
        }
        \pgfsetcolor{red}
        \pgfusepath{stroke}
    }
    {% -.9 ≤ x ≤ -.1 % plot by square root
        \draw[green]plot[domain=-.9:-.1](\x,{sqrt(f(\x))});
    }
    {% -.1 ≤ x ≤ 0 % plot by newton method
        \pgfpathmoveto{\pgfpointxy{0}{0}}
        \def\nsample{40}
        \foreach\i in{0,...,\nsample}{
            \PMSM\y{sqrt(f(-.1))*\i/\nsample}
            \PMSM\yy{f(-.1)*\i*\i/\nsample/\nsample}
            \PMSM\x{0} % initial x = 0
            \PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            \PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            %\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            \pgfpathlineto{\pgfpointxy{\x}{\y}}
        }
        \pgfsetcolor{blue}
        \pgfusepath{stroke}
    }
    {% 1 ≤ x ≤ 1.1 % plot by newton method
        \pgfpathmoveto{\pgfpointxy{1}{0}}
        \def\nsample{40}
        \foreach\i in{0,...,\nsample}{
            \PMSM\y{sqrt(f(1.1))*\i/\nsample}
            \PMSM\yy{f(1.1)*\i*\i/\nsample/\nsample}
            \PMSM\x{1} % initial x = 1
            \PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            \PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            %\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            \pgfpathlineto{\pgfpointxy{\x}{\y}}
        }
        \pgfsetcolor{yellow!50!black}
        \pgfusepath{stroke}
    }
    {% 1.1 ≤ x ≤ ∞ % plot by square root
        \draw[cyan]plot[domain=1.1:2](\x,{sqrt(f(\x))});
    }
}
\end{document}

edit

You can also improve your initial guess. Instead of the x-intercepts, you add a y2 term. Then the result is utterly precise, and smooth. And I iterate only once.

\documentclass[tikz,border=9]{standalone}

\begin{document}

% we are to plot y^2 = (x-1)x(x+1)
% the idea is that we know x-intercepts
% don't use standard form x^3 + ax + b
\let\PMSM=\pgfmathsetmacro
\pgfmathdeclarefunction{f}1{\pgfmathparse{(#1-1)*#1*(#1+1)}}
\pgfmathdeclarefunction{g}1{\pgfmathparse{3*#1*#1-1}} % g = f' = df/d#1
\tikz[cap=round]{
    \draw[->](-1.1,0)--(2,0);
    \draw[->](0,0)--(0,3);
    {% -1 ≤ x ≤ -.9 % plot by newton method
        \pgfpathmoveto{\pgfpointxy{-1}{0}}
        \def\nsample{40}
        \foreach\i in{0,...,\nsample}{
            \PMSM\y{sqrt(f(-.9))*\i/\nsample} % y
            \PMSM\yy{f(-.9)*\i*\i/\nsample/\nsample} % y^2
            % initial guess x = -1 + y^2/2 (first order apporx)
            \PMSM\x{-1+\yy/2}
            % first iteration
            \PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            % second iteration % but one is good enough
            %\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            \pgfpathlineto{\pgfpointxy{\x}{\y}}
        }
        \pgfsetcolor{red}
        \pgfusepath{stroke}
    }
    {% -.9 ≤ x ≤ -.1 % plot by square root
        \draw[green]plot[domain=-.9:-.1](\x,{sqrt(f(\x))});
    }
    {% -.1 ≤ x ≤ 0 % plot by newton method
        \pgfpathmoveto{\pgfpointxy{0}{0}}
        \def\nsample{40}
        \foreach\i in{0,...,\nsample}{
            \PMSM\y{sqrt(f(-.1))*\i/\nsample} % y
            \PMSM\yy{f(-.1)*\i*\i/\nsample/\nsample} % y^2
            \PMSM\x{-\yy)} % initial guess x = 0 - y^2
            \PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            %\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            \pgfpathlineto{\pgfpointxy{\x}{\y}}
        }
        \pgfsetcolor{blue}
        \pgfusepath{stroke}
    }
    {% 1 ≤ x ≤ 1.1 % plot by newton method
        \pgfpathmoveto{\pgfpointxy{1}{0}}
        \def\nsample{40}
        \foreach\i in{0,...,\nsample}{
            \PMSM\y{sqrt(f(1.1))*\i/\nsample} % y
            \PMSM\yy{f(1.1)*\i*\i/\nsample/\nsample} % y^2
            \PMSM\x{1+\yy/2} % initial guess x = 1 + y^2/2
            \PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            %\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
            \pgfpathlineto{\pgfpointxy{\x}{\y}}
        }
        \pgfsetcolor{yellow!50!black}
        \pgfusepath{stroke}
    }
    {% 1.1 ≤ x ≤ ∞ % plot by square root
        \draw[cyan]plot[domain=1.1:2](\x,{sqrt(f(\x))});
    }
}

Isn't math practical?

| improve this answer | |
  • 1
    I think in your first code all \[ and \] should be [ and ]. Also I read the question differently ("The Problem here is, that it takes a lot of time to find the solutions for y = 0 and then getting the right approximation."). Once you have the point where the curve intersects with the x axis, pgfplots is very fast, so my interpretation of the task is to find the x coordinate of that intersection, which can be found analytically. – user194703 Mar 17 at 20:39
  • @Schrödinger'scat somehow copy and pasting does not work. I'll fix. My strategy is that, we declare ECs in this form y^2 = (x-a)(x-b)(x-c); then the roots are a, b, c. Most of the time OP just needs an illustrative example of EC; it doesn't have to be any particular one. It's like the classical XY problem and I am one step ahead, guesses what's X. The second part of my answer is that we know nearly-vertical tangent line is difficult. So we switch to the parameterization by y. This is definitely faster than pgfplots in any sense. Of course you can still argue that users don't care. – Symbol 1 Mar 17 at 22:11
  • 1
    Yes, I had posted a comment with a link to this discussion where one can find similar methods, but then I reread the question, concluded that the OP only wants the locus of the point with y=0 (and then removed the comment). – user194703 Mar 17 at 22:16
  • 1
    You will be surprised about the knowledge of those who write lecture notes. ;-) Yes, I agree with all what you are saying but the bottom-line could be that you may not want to do such things with LaTeX. Mathematica has all the Weierstrass and so on stuff built in. – user194703 Mar 17 at 22:28
  • 1
    I always like the requests to add "explanations". IMHO it would make sense if all users watched this video before asking for explanations. Then they would understand that one can only explain things if one knows what the other side knows, and what they do not know. And then there are some users here who have nothing better to do than to praise some posts as having so great explanations. Well, these are explanations that worked for them, but this does not make it a "great explanation". – user194703 Mar 17 at 22:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.