> restart:
> # BROYDEN ALGORITHM 10.2
> #
> # To approximate the solution of the nonlinear system F(X) = 0
> # given an initial approximation X.
> #
> # INPUT:   Number n of equations and unknowns: initial
> #          approximation X = (X(1),...,X(n)): tolerance TOL:
> #          maximum number of iterations N.
> #
> # OUTPUT:  Approximate solution X = (X(1),...,X(n)) or a message
> #          that the number of iterations was exceeded.
> print(`This is the Broyden Method for Nonlinear Systems.`):
> OK := FALSE:
> while OK = FALSE do
>    print(`Input the number n of equations.`):
>    N := scanf(`%d`)[1]:print(`n = `):print(N):
>    if N >= 2 then
>       OK := TRUE:
>    else
>       print(`n must be an integer greater than 1.`):
>    fi:
> od:
> for I1 from 1 to N do
>    print(`Input the function f[i](x1,x2, ... xn) in terms of x1, x2, ... for i = `):print(I1):
>    print(`For example: x1-x2^2+1`):
>    F[I1] := scanf(`%a`)[1]:print(`function is `):print(F[I1]):
> od:
> for I1 from 1 to N do
>    for J from 1 to N do
>       PD[I1,J] := diff(F[I1],evaln(x || J)):print(`partial derivative i,j `):print(I1,J):print(PD[I1,J]):
>       PD[I1,J] := unapply(PD[I1,J],evaln(x || (1..N))):
>    od:
> od:
> for I1 from 1 to N do
>    F[I1] := unapply(F[I1],evaln(x || (1..N))):
> od:
> OK := FALSE:
> while OK = FALSE do
>    print(`Input tolerance`):
>    TOL := scanf(`%f`)[1]:print(`Tolerance = `):print(TOL):
>    if TOL > 0 then
>       OK := TRUE:
>    else
>       print(`Tolerance must be positive.`):
>    fi:
> od:
> OK := FALSE:
> while OK = FALSE do
>    print(`Input the maximum number of iterations.`):
>    NN := scanf(`%d`)[1]:print(`Maximum number of iterations = `):print(NN):
>    if NN > 0 then
>       OK := TRUE:
>    else
>       print(`Must be a positive integer.`):
>    fi:
> od:
> for I1 from 1 to N do
> print(`Input initial approximation X(I), I = `, I1):
> X[I1-1] := scanf(`%f`)[1]: print(`Input is `): print(X[I1-1]):
> od:
> if OK = TRUE then
>    print(`Select output destination`):
>    print(`1. Screen`):
>    print(`2. Text file`):
>    print(`Enter 1 or 2`):
>    FLAG := scanf(`%d`)[1]:print(`Your response is `):print(FLAG):
>    if FLAG = 2 then
>       print(`Input the file name in the form - drive:\\name.ext`):
>       print(`for example  A:\\OUTPUT.DTA`):
>       NAME := scanf(`%s`)[1]:print(`Output file is `):print(NAME):
>       OUP := fopen(NAME,WRITE,TEXT):
>    else
>       OUP := default:
>    fi:
>    print(`Select amount of output`):
>    print(`1. Answer only`):
>    print(`2. All intermeditate approximations`):
>    print(`Enter 1 or 2`):
>    FLAG := scanf(`%d`)[1]: print(`Your response is `):print(FLAG):
>    fprintf(OUP, `BROYDENS METHOD FOR NONLINEAR SYSTEMS\n\n`):
>    if FLAG = 2 then
>       fprintf(OUP, `Iteration, Approximation, Error\n`):
>    fi:
> # Step 1
> # A will hold the Jacobian for the initial approximation
>    for I1 from 1 to N do
>       for J from 1 to N do
>          A[I1-1,J-1] := evalf(PD[I1,J](seq(X[i],i=0..N-1))):
>       od:
> # Compute V = F(X(0))
>       V[I1-1] := evalf(F[I1](seq(X[i],i=0..N-1))):
>    od:
> # Step 2
>    for I1 from 1 to N do
>       for J from 1 to N do
>          B[I1-1,J-1] := 0:
>       od:
>       B[I1-1,I1-1] := 1:
>    od:
>    I1 := 1:
>    while I1 <= N and OK = TRUE do
>       I2 := I1+1:
>       I3 := I1:
>       if I1 <> N then
>          C := abs(A[I1-1,I1-1]):
>          for J from I2 to N do
>             if abs(A[J-1,I1-1]) > C then
>                I3 := J:
>                C := abs(A[J-1,I1-1]):
>             fi:
>          od:
>          if C <= 1.0e-20 then
>             OK := FALSE:
>          else
>             if I3 <> I1 then
>               for J from 1 to N do
>                   C := A[I1-1,J-1]:
>                   A[I1-1,J-1] := A[I3-1,J-1]:
>                   A[I3-1,J-1] := C:
>                   C := B[I1-1,J-1]:
>                   B[I1-1,J-1] := B[I3-1,J-1]:
>                   B[I3-1,J-1] := C:
>                od:
>             fi:
>          fi:
>       else
>          if abs(A[N-1,N-1]) <= 1.0e-20 then
>             OK := FALSE:
>          fi:
>       fi:
>       if OK = TRUE then
>          for J from 1 to N do
>             if J <> I1 then
>                C := A[J-1,I1-1]/A[I1-1,I1-1]:
>                for K from 1 to N do
>                   A[J-1,K-1] := A[J-1,K-1]-C*A[I1-1,K-1]:
>                   B[J-1,K-1] := B[J-1,K-1]-C*B[I1-1,K-1]:
>                od:
>             fi:
>          od:
>       fi:
>       I1 := I1+1:
>    od:
>    if OK = TRUE then
>       for I1 from 1 to N do
>          C := A[I1-1,I1-1]:
>          for J from 1 to N do
>             A[I1-1,J-1] := B[I1-1,J-1]/C:
>          od:
>       od:
>    else
>       print(`Jacobian has no inverse`):
>    fi:
>    if OK = TRUE then
> # Step 3
>       K := 2:
> # Note: S = S(1)
>       SN := 0:
>       for I1 from 1 to N do
>          S[I1-1] := 0:
>          for J from 1 to N do
>             S[I1-1] := S[I1-1]-A[I1-1,J-1]*V[J-1]:
>          od:
>          SN := SN+S[I1-1]^2:
>       od:
>       SN := sqrt(SN):
>       for I1 from 1 to N do
>          X[I1-1] := X[I1-1]+S[I1-1]:
>       od:
>       if FLAG = 2 then
>          fprintf(OUP,` %d`,K-1):
>          for I1 from 1 to N do
>             fprintf(OUP,` %11.8f`,X[I1-1]):
>          od:
>          fprintf(OUP,`\n %12.6e\n`,SN):
>       fi:
> # Step 4
>       while K < NN and OK = TRUE do
> # Step 5
>          for I1 from 1 to N do
>             VV := evalf(F[I1](seq(X[i],i=0..N-1))):
>             Y[I1-1] := VV-V[I1-1]:
>             V[I1-1] := VV:
>          od:
> # Note:  V = F(X(K)) and Y = Y(K)
> # Step 6
>          ZN := 0:
>          for I1 from 1 to N do
>             Z[I1-1] := 0:
>             for J from 1 to N do
>                Z[I1-1] := Z[I1-1]-A[I1-1,J-1]*Y[J-1]:
>             od:
>             ZN := ZN+Z[I1-1]*Z[I1-1]:
>          od:
>          ZN := sqrt(ZN):
> # Note:  Z = -A(K-1)^(-1)*Y(K)
> # Step 7
>          P := 0:
> # P will be S(K)^T*A(K-1)^(-1)*Y(K)
>          for I1 from 1 to N do
>             P := P-S[I1-1]*Z[I1-1]:
>          od:
> # Step 8
>          for I1 from 1 to N do
>             U[I1-1] := 0:
>             for J from 1 to N do
>                U[I1-1] := U[I1-1]+S[J-1]*A[J-1,I1-1]:
>             od:
> # Step 9
>          od:
>          for I1 from 1 to N do
>             for J from 1 to N do
>                A[I1-1,J-1] := A[I1-1,J-1]+(S[I1-1]+Z[I1-1])*U[J-1]/P:
>             od:
>          od:
> # Step 10
>          SN := 0:
>          for I1 from 1 to N do
>             S[I1-1] := 0:
>             for J from 1 to N do
>                S[I1-1] := S[I1-1]-A[I1-1,J-1]*V[J-1]:
>             od:
>             SN := SN+S[I1-1]^2:
>          od:
>          SN := sqrt(SN):
> # Note: A = A(K)^(-1) and S = -A(K)^(-1)*F(X(K))
> # Step 11
>          for I1 from 1 to N do
>             X[I1-1] := X[I1-1]+S[I1-1]:
>          od:
> # Note:  X = X(K+1)
>          KK := K+1:
>          if FLAG = 2 then
>             fprintf(OUP, ` %2d`, K):
>             for I1 from 1 to N do
>                fprintf(OUP, ` %11.8f`, X[I1-1]):
>             od:
>             fprintf(OUP, `\n%12.6e\n`, SN):
>          fi:
>          if SN <= TOL then
> # Procedure completed successfully
>             OK := FALSE:
>             fprintf(OUP, `Iteration number %d`, K):
>             fprintf(OUP, ` gives solution:\n\n`):
>             for I1 from 1 to N do
>                fprintf(OUP, ` %11.8f`, X[I1-1]):
>             od:
>             fprintf(OUP, `\n\nto within tolerance %.10e\n\n`, TOL):
>             fprintf(OUP, `Process is complete\n`):
>          else
> # Step 13
>             K := KK:
>          fi:
>       od:
>       if K >= NN then
> # Step 14
>          fprintf(OUP, `Procedure does not converge in %d iterations\n`, NN):
>       fi:
>    fi:
> fi:
> if OUP <> default then
> fclose(OUP):
> print(`Output file `,NAME,` created sucessfully`):
> fi:
