%% broydensolve-doc.tex %% Copyright 2025 Matthias Floré % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Matthias Floré. % % This work consists of the files broydensolve-doc.pdf, broydensolve.sty, % broydensolve-doc.tex and README.md. \documentclass[a4paper,english,dvipsnames]{l3doc} \usepackage[english]{babel} \usepackage[a4paper]{geometry} \usepackage{parskip} \usepackage{pdflscape} \usepackage{pgfplots} \pgfplotsset{compat=1.18} \usetikzlibrary{calc} \usepackage{broydensolve} \usepackage{codehigh} \usepackage[nottoc]{tocbibind} \AtEndPreamble{\hypersetup{% linktoc=all, pdfstartview=FitH, colorlinks=true, linkcolor=Mahogany, citecolor=ForestGreen, urlcolor=MidnightBlue, bookmarksnumbered=true, pdftitle=The broydensolve package, pdfauthor=Matthias Floré, pdfsubject=Manual, pdfkeywords={Broyden,solve,system of equations}}} \setcounter{tocdepth}{2} \setcounter{secnumdepth}{2} \newcommand{\tikzname}{Ti\emph{k}Z} \IndexPrologue { \section*{Index} \markboth{Index}{Index} \addcontentsline{toc}{section}{Index} } %\let\part\section %\makeatletter %\addtocontents{toc}{\let\protect\l@part\protect\l@section} %\makeatother \title{The \texttt{broydensolve} package\\[12pt]\large Solve a system of equations with Broyden's good method} \author{Matthias Floré\\\href{mailto:matthflore@gmail.com}{\texttt{matthflore@gmail.com}}} \date{Version 2.0 (2025/07/24)}%\\[12pt] \begin{document} \maketitle \begin{abstract} \noindent This package implements Broyden's good method to solve a system of equations. It is also possible to use coordinates defined by \tikzname{} as known and unknown variables.% This is the manual for version . \end{abstract} \tableofcontents \section{Usage} The package |broydensolve| can be used by putting the following in the preamble. \begin{codehigh} \usepackage{broydensolve} \end{codehigh} \section{Motivation} To solve a system of (nonlinear) equations in a \LaTeX{} document, for example |Python| with the package |pythontex| or |Sage| with the package |sagetex| can be used. This could require multiple compilations or the option |shell-escape|. The package |broydensolve| is implemented with \LaTeX3, requires 1 compilation and does not require the option |shell-escape|. Moreover, it is possible to use coordinates defined by \tikzname{} as known and unknown variables. \section{Commands} \begin{function}[EXP]{\ang} \begin{syntax} \cs{ang}|(|\meta{coordinate}|)| \cs{ang}|(|\meta{coordinate_1},\meta{coordinate_2}|)| \cs{ang}|(|\meta{coordinate_1},\meta{coordinate_2},\meta{coordinate_3}|)| \cs{ang}|(|\meta{coordinate_1},\meta{coordinate_2},\meta{coordinate_3},\meta{coordinate_4}|)| \end{syntax} This command is only defined while the command |\BroydenSolve| is executed. Hence it does not conflict with the eponymous command of the package |siunitx|. It can be used in the function(s) given to the key |func| and gives an angle in radians. For 1 coordinate, its expansion comes down to |atan(|\meta{y_1}|,|\meta{x_1}|)|, for 2 coordinates to |atan(|\meta{y_2}-\meta{y_1}|,|\meta{x_2}-\meta{x_1}|)|, for 3 coordinates to |atan(|\meta{y_3}-\meta{y_2}|,|\meta{x_3}-\meta{x_2}|)-atan(|\meta{y_1}-\meta{y_2}|,|\meta{x_1}-\meta{x_2}|)|, for 4 coordinates to |atan(|\meta{y_4}-\meta{y_3}|,|\meta{x_4}-\meta{x_3}|)-atan(|\meta{y_2}-\meta{y_1}|,|\meta{x_2}-\meta{x_1}|)| and if this is smaller than $0$ then |2*pi| is added. \end{function} \hspace{1cm}\begin{minipage}{\textwidth-1cm} \begin{function}[EXP]{\BroydenIterations} \begin{syntax} \cs{BroydenIterations} \end{syntax} This command gives the total number of iterations after the command |\BroydenSolve| is executed. This command is expandable. \end{function} \end{minipage} \begin{function}[EXP]{\BroydenRoot} \begin{syntax} \cs{BroydenRoot}\oarg{iteration}\marg{variable} \end{syntax} This command gives the approximation for the root for \meta{variable} after the command |\BroydenSolve| is executed. The default value for \meta{iteration} is the total number of iterations. This command is expandable. \end{function} \begin{function}[EXP]{\BroydenRoots} \begin{syntax} \cs{BroydenRoots} \end{syntax} This command gives the approximation(s) for the root(s) for the variable(s) as a comma separated list after the command |\BroydenSolve| is executed. This command is expandable. \end{function} \begin{function}{\BroydenSetup} \begin{syntax} \cs{BroydenSetup}\marg{keys} \end{syntax} This command sets the \meta{keys} described in Section \ref{Keys}. \end{function} \begin{function}{\BroydenSolve} \begin{syntax} \cs{BroydenSolve}\marg{keys} \end{syntax} This command sets the \meta{keys} described in Section \ref{Keys} inside a group and tries to approximate the root(s) for the function(s) defined by the key |func| with respect to the variable(s) defined by the key |var| with initial value(s) defined by the key |init| using Broyden's good method, see \cite{Bacomfsnse}. In general, this method does \emph{not} always converge and does \emph{not} give an exact result. Angles and trigonometric functions are typically best in radians for this purpose. The key |stop-crit| influences when the iteration stops. \end{function} \begin{function}[EXP]{\col} \begin{syntax} \cs{col}|(|\meta{coordinate_1},\meta{coordinate_2},\meta{coordinate_3}|)| \end{syntax} This command is only defined while the command |\BroydenSolve| is executed. It can be used in the function(s) given to the key |func| and can be used to require that 3 points are collinear. Its expansion comes down to $\meta{x_1}(\meta{y_2}-\meta{y_3})+\meta{x_2}(\meta{y_3}-\meta{y_1})+\meta{x_3}(\meta{y_1}-\meta{y_2})$. \end{function} \begin{function}[EXP]{\dis} \begin{syntax} \cs{dis}|(|\meta{coordinate}|)| \cs{dis}|(|\meta{coordinate_1},\meta{coordinate_2}|)| \end{syntax} This command is only defined while the command |\BroydenSolve| is executed. It can be used in the function(s) given to the key |func| and gives a distance. For 1 coordinate, its expansion comes down to $\sqrt{\meta{x_{1}}^{2}+\meta{y_{1}}^{2}}$ and for 2 coordinates to $\sqrt{(\meta{x_{2}}-\meta{x_{1}})^{2}+(\meta{y_{2}}-\meta{y_{1}})^{2}}$. \end{function} \section{Keys}\label{Keys} \begin{function}{abs-approx-error} \begin{syntax} abs-approx-error=\meta{value} \end{syntax} The \meta{value} is used by the stopping criterion. Initially, it is |10^-3|. \end{function} \begin{function}{coordinates} \begin{syntax} coordinates=\meta{boolean} \end{syntax} If true then the function variables are given by \meta{variable}|x| and \meta{variable}|y| for each \meta{variable} in the \meta{list} given to the key |var| until the number of variables is the same as the number of functions. The functions can contain names of coordinates defined by \tikzname. For a coordinate \meta{name}, also \meta{name}|x| and \meta{name}|y| can be used in the functions to represent its $x$ and $y$ coordinate. This requires the package |tikz| and the \tikzname{} library |calc|. After the iteration ends, \tikzname{} coordinates are defined using the computed approximate solutions. \end{function} \begin{function}{func} \begin{syntax} func=\meta{list} \end{syntax} The comma separated \meta{list} defines the function(s). If a function contains a |,| then this function should be placed inside braces. Also a pair of braces can be required around the whole function(s). \end{function} \begin{function}{func-error} \begin{syntax} func-error=\meta{value} \end{syntax} The \meta{value} is used by the stopping criterion. Initially, it is |10^-3|. \end{function} \begin{function}{init} \begin{syntax} init=\meta{list} \end{syntax} The \meta{list} defines the initial value(s) for the iteration. \end{function} \begin{function}{iterations} \begin{syntax} iterations=\meta{number} \end{syntax} The \meta{number} is used by the stopping criterion. Initially, it is |5|. \end{function} \begin{function}{rel-approx-error} \begin{syntax} rel-approx-error=\meta{value} \end{syntax} The \meta{value} is used by the stopping criterion. Initially, it is |10^-3|. \end{function} \begin{function}{stop-crit} \begin{syntax} stop-crit=abs-approx-error stop-crit=func-error stop-crit=iterations stop-crit=rel-approx-error \end{syntax} The stopping criterion influences when the iteration stops. If the function(s) evaluate(s) to $0$ then the iteration stops immediately. Otherwise, the stopping behaviors are listed below. \begin{description} \item[|abs-approx-error|] The iteration stops if the $1$-norm of the difference between the current and the previous approximation is smaller than the value given to the key |abs-approx-error|. \item[|func-error|] The iteration stops if the $1$-norm of the function value(s) is smaller than the value given to the key |func-error|. \item[|iterations|] The iteration stops after a number of iterations determined by the key |iterations|. \item[|rel-approx-error|] The iteration stops if the $1$-norm of the difference between the current and the previous approximation is smaller than the product of the value given to the key |rel-approx-error| and the $1$-norm of the current approximation. \end{description} Initially, the stopping criterion is |rel-approx-error|. \end{function} \begin{function}{var} \begin{syntax} var=\meta{list} \end{syntax} The \meta{list} defines the function variable(s). Only the first $N$ elements of the \meta{list} are used where $N$ is the number of functions. The variable(s) must consist entirely of Latin letters in the range |[a-zA-Z]| and cannot be an existing floating point identifier. Initially, it is |x,y,z|. \end{function} \section{Examples} \begin{demohigh} \BroydenSolve{ func=x^5-x^2-1, init=1 } Found an approximate root after \BroydenIterations{} iterations:\\ $x\approx\BroydenRoot{x}$ \end{demohigh} \begin{demohigh} %\usepackage{pgfplots} %\pgfplotsset{compat=1.18} \begin{tikzpicture} \BroydenSolve{ func=x-cos(x), init=0.5, rel-approx-error=10^-1 } \begin{axis}[ axis equal image, axis lines=middle, xmin=0.45, xmax=0.95, ymin=0.45, ymax=0.95, xlabel=$x$, ylabel=$y$ ] \addplot[smooth,domain=0.45:0.95,trig format plots=rad] {cos(x)}; \addplot[smooth] {x}; \pgfplotsinvokeforeach{0,...,\BroydenIterations}{ \draw (\BroydenRoot[#1]{x},\BroydenRoot[#1]{x}) circle[radius=2pt] node[xshift=\fpeval{#1=3?0:6},yshift=\fpeval{#1=3?10:-6}] {$P_{#1}$}; } \node[align=left] at (0.76,0.52) {Found an approximate root\\ after \BroydenIterations{} iterations:\\$x\approx\BroydenRoot{x}$}; \end{axis} \end{tikzpicture} \end{demohigh} Below, we construct the points $A$ and $B$ so that $A$ lies on the circle with center $E$, $B$ lies on the circle with center $F$, $\|AB\|=5$ and $AB\perp CD$. \begin{demohigh} %\usepackage{tikz} %\usetikzlibrary{calc} \begin{tikzpicture} \coordinate (C) at (-2,5); \coordinate (D) at (6,-2); \coordinate (E) at (0,0); \coordinate (F) at (4,3); \BroydenSolve{ coordinates, func={ \dis(A)-1.5, %{\dis(A,E)-1.5}, %Ax^2+Ay^2-1.5^2, {\dis(B,F)-2}, %(Bx-Fx)^2+(By-Fy)^2-2^2, {\dis(A,B)-5}, {\ang(A,B,D,C)-pi/2} %{atan(Cy-Dy,Cx-Dx)-atan(By-Ay,Bx-Ax)-pi/2} %(Ax-Bx)*(Cx-Dx)+(Ay-By)*(Cy-Dy) }, init={-1,-1,2,3}, var={A,B} } \draw[help lines] (-2,-2) grid (6,5); \draw (C)--(D) (E) circle[radius=1.5] (F) circle[radius=2] (A)--(B); %(\BroydenRoot{Ax},\BroydenRoot{Ay})--(\BroydenRoot{Bx},\BroydenRoot{By}) \foreach\coord in {A,B,C,D,E,F}{ \fill (\coord) circle[radius=2pt] node[left] {$\coord$}; } \end{tikzpicture} \end{demohigh} \begin{demohigh} %\usepackage{tikz} %\usetikzlibrary{calc} \begin{tikzpicture} \coordinate (A) at (0,3); \coordinate (B) at (0,0); \coordinate (C) at (3,4); \BroydenSolve{ coordinates, func={ {\col(B,D,C)}, {\ang(A,D,B)-70*deg} }, init={2,2.5}, var=D } \draw[help lines] (0,0) grid (3,4); \draw (B)--(C) (A)--(D); \foreach\n in {0,...,\inteval{\BroydenIterations-1}}{ \fill (\BroydenRoot[\n]{Dx},\BroydenRoot[\n]{Dy}) circle[radius=1pt]; } \foreach\coord in {A,B,C,D}{ \fill (\coord) circle[radius=2pt] node[below] {$\coord$}; } \end{tikzpicture} \end{demohigh} \begin{demohigh} %\usepackage{tikz} %\usetikzlibrary{calc} \begin{tikzpicture} \coordinate (A) at (0.3,0.4); \coordinate (B) at (4.7,0.8); \coordinate (C) at (0.2,3.2); \coordinate (D) at (4.8,4.7); \BroydenSolve{ coordinates, func={ {\ang(A,X,B)-100*deg}, {\ang(D,X,C)-110*deg} }, init={2,2}, var=X } \draw[help lines] (0,0) grid (5,5); \draw (A)--(X)--(B)--cycle (C)--(X)--(D)--cycle; \foreach\coord in {A,B,C,D,X}{ \fill (\coord) circle[radius=2pt] node[above] {$\coord$}; } \end{tikzpicture} \end{demohigh} \section{Version history} \begin{itemize} \item[] \textbf{Version 1.0 (2025/07/20)} First version. \item[] \textbf{Version 2.0 (2025/07/24)} Updated the documentation. \end{itemize} \begin{thebibliography}{9} \bibitem{Bacomfsnse} C. G. Broyden, \emph{A class of methods for solving nonlinear simultaneous equations}, Math. Comp. \textbf{19} (1965), 577-593. \end{thebibliography} \PrintIndex \newgeometry{left=2.25cm,right=2.25cm,top=2.25cm,bottom=2.25cm} \appendix \begin{landscape} \section{The source code} \dochighinput[language=latex/latex3]{broydensolve.sty} \end{landscape} \end{document}