%% 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}