Scilab 6 A
Scilab 6 A
SCILAB
By
Distributed by
i nfoClearinghouse.com
http://www.engineering.usu.edu/cee/faculty/gurro/Software_Calculators/Scil
ab_Docs/ScilabBookFunctions.zip
http://www.engineering.usu.edu/cee/faculty/gurro/Scilab.html
z = x + iy,
where x and y are real numbers, and i is the imaginary unit defined by I2 = -1.
We can think of a complex number as a point P(x,y) in the x-y plane, with the x-axis referred
to as the real axis, and the y-axis referred to as the imaginary axis. Thus, a complex number
represented in the form x+iy is said to be in its Cartesian representation.
θ = Arg(z) = arctan(y/x)
The relationship between the Cartesian and polar representation of complex numbers is given
by the Euler formula:
z = x – iy = re-Iθ .
The complex conjugate of z can be thought of as the reflection of z about the real (x-) axis.
Similarly, the negative of z,
–z = -x-iy = - reiθ,
! i - 1. - i 1. i - 1. - i 1. i - 1. !
-->z =3+5*%i
z =
3. + 5.i
The functions real and imag can be used to obtain the real and imaginary parts, respectively,
of a complex number, for example:
-->real(z), imag(z)
ans =
3.
ans =
5.
The magnitude and argument of the complex number z are obtained as:
-->abs(z), atan(imag(z)/real(z))
ans =
5.8309519
ans =
1.0303768
-->5*exp(0.25*%i)
ans =
4.8445621 + 1.2370198i
-->[r,theta] = polar(z)
theta =
1.0303768
r =
5.8309519
The complex conjugate of a complex number is obtained by using the function conj:
-->conj(z)
ans =
3. - 5.i
The negative is simply obtained by adding a minus sign to the number, i.e.,
-->-z
ans =
- 3. - 5.i
Matrices in SCILAB can have complex numbers as elements. The following commands, for
example, produce a 3x4 matrix of complex numbers. First, we generate random matrices with
integer numbers to be the real and imaginary parts of the complex numbers:
! 2. 5. 2. !
! 4. 5. 6. !
! 2. 1. 7. !
yMs =
! 0. 3. 4. !
! 6. 8. 2. !
! 2. 5. 8. !
! 2. 5. + 3.i 2. + 4.i !
! 4. + 6.i 5. + 8.i 6. + 2.i !
! 2. + 2.i 1. + 5.i 7. + 8.i !
To obtain the magnitude of the elements of the matrix just defined we simply apply the
function abs to the matrix name, i.e.,
-->abs(zMs)
ans =
! 2. 5.8309519 4.472136 !
! 7.2111026 9.4339811 6.3245553 !
! 2.8284271 5.0990195 10.630146 !
-->atanm(yMs./xMs)
ans =
be complex numbers. In these definitions the numbers x, y, x1, x2, y1, and y2 are real numbers.
Multiplication of a number by its conjugate results in the square of the number’s magnitude,
i.e.:
z⋅z = (x + i⋅y)⋅(x - i⋅y) = x2 + y2 = r2 = |z|2
Division:
z1 z1 z2 z ⋅z x ⋅ x + y1 ⋅ y2 y ⋅ x − x1 ⋅ y2 r
= ⋅ = 1 22 = 1 22 + i 1 22 = 1 ⋅ ei⋅(θ1 −θ2 ) .
z2 z2 z2 | z2 | x 2 + y2
2
x 2 + y2
2
r2
i⋅θ n i⋅nθ
Powers: zn = (r⋅e ) = rn⋅ e
Roots: because the argument θ of a complex number z has a periodicity of 2π, we can write
i⋅(θ+2kπ)
z = r ⋅e , for k = 0, 1, 2, …
(θ + 2 kπ )
i⋅
n
z = z1/ n = r 1/ n ⋅ e n
, k = 0,1, 2,L (n − 1).
- 5. + 2.i
z2 =
3. + 4.i
-->z1+z2
ans =
- 2. + 6.i
-->z1-z2
ans =
- 8. - 2.i
-->z1*z2
ans =
- 23. - 14.i
-->z1/z2
ans =
- .28 + 1.04i
column 1 to 4
column 5
! 1475. + 4282.i !
The following SCILAB command attempts to find one cubic root of z1:
-->z1^(1/3)
ans = 1.0613781 + 1.394917i
-->cubic_roots_of_z1 = [];
-->for k = 0:2
--> cubic_roots_of_z1 = [cubic_roots_of_z1
r1^(1/3)*exp(%i*((theta1+2*k*%pi)/3))];
-->end;
-->cubic_roots_of_z1
cubic_roots_of_z1 =
column 1 to 2
column 3
! - 1.0613781 - 1.394917i !
More details on the calculation of roots of real and complex numbers are presented in a
subsequent section of this chapter.
Quadratic equations
Quadratic equations are those algebraic equations with one unknown that can be reduced to
the form
ax2+bx+c = 0,
x2+(b/a)x= -(c/a)
and completing the square of a binomial in the left hand side. To complete the square of a
binomial, add the term b2/(4a2) to both sides of the equation:
(x+b/(2a))2 = (b2-4ac)/(4a2).
x = [-b± (b2-4ac)1/2]/(2a).
The quantity under the square root in this result is known as the discriminant of the equation,
i.e.,
D = b2-4ac.
According to the sign of the discriminant, the equation can have one or two real solutions, or
two complex conjugate solutions:
x1 = x2 = -b/(2a).
The basic algorithm (written in pseudo-code) for solving a quadratic equation, would look
something like this:
If D > 0,
Indicate that two distinct real solutions exist
Calculate roots as x1 = (-b+D1/2)/(2a), and x2= (-b-D1/2)/(2a)
Display roots x1 and x2
Else If D = 0,
Indicate that only one real solution exist
Calculate root as x = -b/(2a)
Display single root x
The reader is invited to write a SCILAB function to solve the quadratic equation given the
values a, b, and c.
Note: Pseudo-code is a way to present an algorithm using English-like statements that are later
coded into a particular computer language. The statements are general enough to be
understood by any programmer and easily translated into a computer language.
Cubic equations
The canonical (simplest) form of the cubic equation is
x3+ax2+bx+c = 0,
D = (p/2)2+(q/3)3.
An Italian mathematician, Gierolimo Cardano, proposed the following solutions to the cubic
equation:
x1 = -(a/3)+u+v
q q
u=3 − + D, v = 3 − − D.
2 2
Depending on the sign of the discriminant, D, the solutions to the cubic equation can be
classified as follows:
If D > 0, one real and two complex conjugate solutions (calculated using the formulas shown
above).
If D = 0, three real solutions including a double solution (x2 and x3).
If D < 0, three distinct real solutions (this case is known as the irreducible case).
In the irreducible case, the formulas shown above for the three roots of the cubic equation will
introduce complex expressions because the calculation of u and v involves the square root of
D<0. To avoid introducing such complex expressions, we can use the so-called trigonometric
form of the solution:
a | p| φ
x1 = − +2 cos( ),
3 3 3
a | p| φ −π
x2 = − +2 cos( ),
3 3 3
and
a | p| φ +π
x3 = − +2 cos( ),
3 3 3
where
q
cos(φ ) = − .
3
| p |
2
3
The algorithm for solving the cubic equation can be written in pseudo-code as follows:
If D > 0
Indicate that there one real and two complex conjugate solutions
Calculate u and v (use subroutine for cubic equation – see below)
Calculate the real root, x1 = -(a/3)+u+v
Calculate the real part of roots x2,3, xr = -(a/3)+(u+v)/2
Else D = 0
Indicate that there are three real solutions with one double root
Calculate x1 = -(a/3)+u+v, x2,3 = -(a/3) – (u+v)/2
Display roots x1, x2 = x3
The calculation of u and v for the case D>0 requires us to calculate cubic roots, namely,
q q
3 − + D, 3 − − D.
2 2
I suggest you use the following user-defined SCILAB function to obtain those cubic roots:
function RealCubicRoot(x)
//This function calculates the cubic root of a real number
One_Third = 1.0/3.0
if x < 0 then
RealCubicRoot = -(Abs(x)^One_Third)
elseif x == 0 then
RealCubicRoot = 0
else
Real CubicRoot = Abs(x)^One_Third
end
//End of the function
The function RealCubicRoot calculates the real cubic root corresponding to a real number. The
functions is designed so that if the real number is positive so is its cubic root, and if the
number is negative so is its cubic root. With this function we ensure that we always get a real
cubic root and that the calculation is not encumbered with complex number operations.
Because the functions sin and cos are periodic functions of period 2π in θ, the complex number
z can be written as
In other words, there are infinite ways to represent the complex number z. The most general
representation being
z = r⋅e i(θ+2kπ).
You can check that we need only use the values k = 0, 1, 2, ... (n-1), to produce all n
independent roots of the number z.
Example 1: Consider the number z = 16⋅eiπ = 16 ⋅cos π + i ⋅16 ⋅sin π = -16, which is actually a
real number. Calculate the roots corresponding to z1/4:
From
z = 16⋅eiπ = 16⋅ei(π+2kπ) = 16⋅ei(1+2k)π ,
it follows that
r = z1/4 = 161/4⋅ei(1+2k)(π/4) = 2⋅ei(1+2k)(π/4), k = 0, 1, 2, 3
Thus,
!For k = 0, r1 = 2⋅ei(1+2⋅0)(π/4) = 2⋅eiπ/4 = 2⋅cos(π/4) + i⋅2⋅sin(π/4) = √2⋅(1 + i)
Using values such as k = -1 or k = 4 in the general expression for the 4-th root of z = -16 will
produce values already accounted for in the four results found above. This example,
therefore, verifies that there are exactly n independent n-th roots of a complex number, with
n = 4 for this case.
Notice that the results of this example actually correspond to the 4-th roots of a real number, z
= -16. Since real numbers are special cases of complex numbers, the approach outlined above
for finding the n-th root of a complex number is also applicable to a real number. The only
requirement is that the number be written in the Polar form, z = r⋅e iθ.
-->roots_of_z = [];
-->for k = 0:3
--> roots_of_z = [roots_of_z r^(1/4)*exp(%i*((theta+2*k*%pi)/n))];
-->end;
-->roots_of_z
roots_of_z =
column 3 to 4
z = r⋅e iθ,
For the case of cubic root (n = 3), if the number z is a positive real number, θ = 0, and the
result is straightforward, z1/3 = r1/3. If the number z is a negative real number, θ = π, and
the principal value is z1/3 = r1/3⋅e iπ/3 = r1/3 ⋅(cos π/3 + i ⋅sin π/3). Thus, the principal value
of the root of a complex number is not necessarily always a real number.
The following SCILAB exercise shows the three cubic roots of a positive and a negative number.
81.
r =
81.
theta =
0.
-->for k = 0:2
--> r^(1/3)*exp(%i*(theta+2*k*%pi)/3)
-->end
ans =
4.3267487
ans =
- 2.1633744 + 3.7470743i
ans =
- 8.
r =
8.
theta =
3.1415927
-->for k = 0:2
--> r^(1/3)*exp(%i*(theta+2*k*%pi)/3)
-->end
ans =
1. + 1.7320508i
ans =
1. - 1.7320508i
P = a0+a1x+a2x2+a3x3+…+anxn,
we use a row vector containing the coefficients as [a0 a1 a2 … an], and call function poly using
this vector, the independent variable that defines the polynomial, say, ‘x’, and the qualifier
“coeff”. For example, to define a fourth-order polynomial with coefficients [1 -5 0 3 2],
use:
-->p4 = poly([1 -5 0 3 2],'x','coeff')
p4 =
3 4
1 - 5x + 3x + 2x
c =
column 1 to 10
column 11
! 3. !
-->p10 = poly(c,'y','coeff')
p10 =
2 3 4 6 7 8 9 10
23 - 122y + 34y - 20y + 4y + 525y - 2y + 11y + 3y
To find the roots of a polynomial use the function roots. For example, the roots of the fourth-
order polynomial p4 are:
-->roots(p4)
ans =
! .2059620 !
! - 1.3030302 + .9995932i !
! - 1.3030302 - .9995932i !
! .9000985 !
-->roots(p10)
ans =
! .2308180 + .7299993i !
! .2308180 - .7299993i !
! - .3995841 !
! - .5911741 + .5126340i !
! - .5911741 - .5126340i !
! .4935580 !
! .6187957 !
! - 7.1652026 !
! 1.7532393 + 4.6211667i !
! 1.7532393 - 4.6211667i !
The next example combines functions roots and poly to calculate the roots of a polynomial
given its coefficients in the vector [2 -3 5 4 2 100]:
-->roots(poly([2 -3 5 4 2 100],'s','coeff'))
ans =
The fundamental theorem of algebra indicates that a polynomial of integer order n has a total
of n roots, among real and complex roots. It also indicates that if a complex number z is a root
of a polynomial, then its complex conjugate z is also a root of the polynomial. These facts
are illustrated in the examples worked above.
with n = 2 corresponding to the quadratic equation, and n = 3 to the cubic equation. A linear
equation would be one for which n = 1, and its solution is straightforward. Equations that can
be cast in the form of a polynomial are referred to as algebraic equations. Equations
involving more complicated terms, such as trigonometric, hyperbolic, exponential, or
logarithmic functions are referred to as transcendental equations.
No general algorithms for solution exist for algebraic (or polynomial) equations of order n ≥ 4,
or for transcendental equations. The methods presented in this section are numerical methods
that can be applied to the solution of such equations, to which we will refer, in general, as
non-linear equations.
f(x) = 0.
We will present the methods of interval halving (or bisection method, the Newton-Raphson
algorithm, the secant method, and the fixed iteration method. In the interval-halving
method as well as in the secant method we need to provide two initial values of x to get the
algorithm started. In the fixed iteration and Newton-Raphson methods only one initial value is
required.
Because the solution is not exact, the algorithms for any of the methods presented herein will
not provide the exact solution to the equation f(x) = 0, instead, we will stop the algorithm
when the equation is satisfied within an allowed tolerance or error, ε. In mathematical terms
this is expressed as
|f(xR)| < ε.
The value of x for which the non-linear equation f(x)=0 is satisfied, i.e., x = xR, will be the
solution, or root, to the equation within an error of ε units.
Obviously, since the function y = f(x) changes sign as x goes from x = a to x = b, somewhere
within the interval (a,b), x must take a value xR for which f(x) = 0. The mid-point of the
interval, namely,
c = 1/2(a+b),
Two situations are possible, as illustrated in the figure below: (1) a < xR < c < b; or, (2) a < c <
xR < b. In the first case, f(a)⋅ f(c) < 0, while f(b)⋅ f(c) > 0, and xR is contained in the interval
(a,c). In the second case, f(a)⋅ f(c) > 0, while f(b)⋅ f(c) < 0, and xR is contained in the interval
(c,b). We can think of c replacing b in the first case in a general interval (a,b), while c
replaces a in the interval (a,b) in the second case. In other words, in the first case b takes the
value of c, b"c, and in the second case, a"c. We can think of the method, therefore, as
finding the center-point of an ever-decreasing interval. The mid-point value replaces the
interval extreme for which the product of its function and that of the mid-point is a positive
number.
The process is then repeated until a value of c is found so that (3) is satisfied, i.e., until
|f(c)| < ε.
The following function, half.txt, can be used to obtain a solution using interval halving. The
function looks like this:
function [x]=half(a,b,f)
//interval halving routine
N = 100; eps = 1.e-5; // define max. no. iterations and error
if (f(a)*f(b) > 0) then
error('no root possible f(a)*f(b) > 0')
abort;
end;
if(abs(f(a)) < eps) then
error('solution at a')
abort;
end;
if(abs(f(b)) < eps) then
error('solution at b')
abort;
end;
while (N > 0)
-->deff('[y]=p(x)',['y=x^3-2*x^2-2*x-1'])
We will produce a plot of the function to check possible solutions visually, for example:
The figure shows a root between 2 and 3. The next step in the solution is to load function
half, and call it with the proper arguments:
-->getf('half’);
-->x = half(2,3,p)
x =
2.8311768
To check the solution evaluate the function at the value of x:
-->p(x)
- .0000048
The function does not evaluates to zero. However, the error involved is in the order of 5x10-6,
small enough to accept the solution provided.
f(x)= f(xo)+f'(xo)(x-xo)+(f"(xo)/2!)(x-xo)2+….
Using only the first two terms of the expansion, a first approximation to the root of the
equation
f(x) = 0
x1 = xo - f(xo)/f'(xo).
The Newton-Raphson method consists in obtaining improved values of the approximate root
through the recurrent application of equation (8). For example, the second and third
approximations to that root will be given by
x2 = x1 - f(x1)/f'(x1),
and
x3= x2 - f(x2)/f'(x2),
respectively.
This iterative procedure can be generalized by writing the following equation, where i
represents the iteration number:
xi+1 = xi - f(xi)/f'(xi).
After each iteration the program should check to see if the convergence condition, namely,
|f(x i+1)|<ε,
is satisfied.
The figure below illustrates the way in which the solution is found by using the Newton-
Raphson method. Notice that the equation f(x) = 0 ≈ f(xo)+f'(xo)(x1 -xo) represents a straight
line tangent to the curve y = f(x) at x = xo. This line intersects the x-axis (i.e., y = f(x) = 0) at
the point x1 as given by x1 = xo - f(xo)/f'(xo). At that point we can construct another straight
line tangent to y = f(x) whose intersection with the x-axis is the new approximation to the root
of f(x) = 0, namely, x = x2. Proceeding with the iteration we can see that the intersection of
consecutive tangent lines with the x-axis approaches the actual root relatively fast.
The programming algorithm of any of these methods must include the option of stopping the
program if the number of iterations grows too large. How large is large? That will depend of
the particular problem solved. However, any interval-halving, fixed iteration, Newton-
Raphson, or secant method solution that takes more than 1000 iterations to converge is either
ill-posed or contains a logical error. Debugging of the program will be called for at this point
by changing the initial values provided to the program, or by checking the program's logic.
The function newton, listed below, implements the Newton-Raphson algorithm. It uses as
arguments an initial value and expressions for f(x) and f'(x).
function [x]=newton(x0,f,fp)
//newton-raphson algorithm
N = 100; eps = 1.e-5; // define max. no. iterations and error
maxval = 10000.0; // define value for divergence
xx = x0;
while (N>0)
xn = xx-f(xx)/fp(xx);
if(abs(f(xn))<eps)then
x=xn
disp(100-N);
return(x);
end;
if (abs(f(xx))>maxval)then
disp(100-N);
error('Solution diverges');
abort;
end;
N = N - 1;
xx = xn;
end;
We will use the Newton-Raphson method to solve for the equation, f(x) = x3-2x2+1 = 0. The
following SCILAB commands define the function f(x) and its derivative, fp(x), and load the
function newton.txt:
-->deff('[y]=f(x)','y=x^3-2*x^2+1');
-->deff('[y]=fp(x)','y=3*x^2-2');
-->getf('newton')
To have an idea of the location of the roots of this polynomial we'll plot the function using the
following SCILAB commands:
-->plot(x,y,'x','f(x)','my plot');
-->xgrid()
We see that the function graph crosses the x-axis somewhere between -.8 and -.4, between .8
and 1.2, and between 1.6 and 2.0. The following commands use the function newton with
different initial values. The nature of the function is such that most initial values converge to
either of the two real roots, a few diverge, but it is very difficult to make the algorithm
converge to the negative root. The number listed before the variable name ans in each
solution is the number of iterations required to obtain a solution.
-->newton(-1,f,fp)
0.
ans =
1.
-->newton(-10,f,fp)
52.
ans =
1.6180279
44.
ans =
1.6180278
-->newton(-0.1,f,fp)
49.
ans =
1.6180279
-->newton(-2,f,fp)
45.
ans =
1.6180405
-->newton(0,f,fp)
1.
ans =
1.
-->newton(0.5,f,fp)
0.
ans =
1.
-->newton(-0.8,f,fp)
47.
ans =
1.6180408
-->newton(-0.2,f,fp)
43.
ans =
1.6180405
-->newton(-0.1,f,fp)
49.
ans =
1.6180279
-->newton(-100,f,fp)
0.
!--error 9999
Solution diverges
at line 15 of function newton called by :
newton(-100,f,fp)
52.
ans =
1.6180279
-->newton(100,f,fp)
0.
!--error 9999
Solution diverges
at line 15 of function newton called by :
newton(100,f,fp)
-->newton(10,f,fp)
48.
ans =
1.6180405
f ( xi )
xi +1 = xi − ⋅ ( xi − xi −1 ).
f ( xi ) − f ( xi −1 )
To get the method started we need two values of x, say xo and x1, to get the first
approximation to the solution, namely,
f ( x1 )
x 2 = x1 − ⋅ ( x1 − x0 ).
f ( x1 ) − f ( xo )
|f(x i+1)|<ε.
Figure 4, below, illustrates the way that the secant method approximates the solution of the
equation f(x) = 0.
The function secant, listed below, uses the secant method to solve for non-linear equations. It
requires two initial values and an expression for the function, f(x).
function [x]=secant(x0,x00,f)
//newton-raphson algorithm
N = 100; eps = 1.e-5; // define max. no. iterations and error
maxval = 10000.0; // define value for divergence
xx1 = x0; xx2 = x00;
while (N>0)
gp = (f(xx2)-f(xx1))/(xx2-xx1);
xn = xx1-f(xx1)/gp;
if(abs(f(xn))<eps)then
x=xn
disp(100-N);
return(x);
end;
if (abs(f(xn))>maxval)then
disp(100-N);
error('Solution diverges');
abort;
end;
N = N - 1;
xx1 = xx2;
xx2 = xn;
end;
disp(100-N);
error('No convergence');
abort;
//end function
The following SCILAB commands define the function f(x), load the function secant.txt:
-->deff('[y]=f(x)','y=x^3-2*x^2+1')
The following commands call the function secant.txt and converge to a solution:
-->secant(-10.,-9.8,f)
11.
ans =
- .6180354
-->secant(1.0,1.2,f)
0.
ans =
1.
-->secant(5.0,5.2,f)
10.
ans =
1.6180341
x = g(x).
xn+1 =g(xn).
To get the process started we use an initial value, x = x0. Then, we calculate x1 = g(x0), x2 =
g(x1), etc. Convergence is achieved whenever |f(x)| < ε, or whenever |xn+1 - xn| < ε.
The following function will perform the iterations, it will stop if there is divergence or if
convergence is achieved. The function is stored in file fixedp:
function [x]=fixedp(x0,f)
//fixed-point iteration
N = 100; eps = 1.e-5; // define max. no. iterations and error
maxval = 10000.0; // define value for divergence
xx = x0;
while (N>0)
xn = f(xx);
if(abs(xn-xx)<eps)then
x=xn
disp(100-N);
return(x);
f(x) = 3x - exp(x) + 2 = 0,
(a) x = g1(x) = exp(x) - (2x+2); (b) x = g2(x) = (exp(x)-2)/3; and, (c) x = g3(x) = ln(3x+2).
-->deff('[y]=g1(x)','y=exp(x)-(2*x+2)');
-->deff('[y]=g2(x)','y=(exp(x)-2)/3');
-->deff('[y]=g3(x)','y=log(3*x+2)');
-->getf('fixedp')
-->fixedp(1.0,g1)
!--error 9999
No convergence
at line 21 of function fixedp called by :
fixedp(1.0,g1)
-->fixedp(-1.0,g1)
!--error 9999
No convergence
at line 21 of function fixedp called by :
fixedp(-1.0,g1)
-->fixedp(0.0,g1)
!--error 9999
No convergence
at line 21 of function fixedp called by :
fixedp(0.0,g1)
9.
ans =
- .4552324
-->fixedp(-1.0,g2)
7.
ans =
- .4552349
-->fixedp(0.0,g2)
7.
ans =
- .4552309
-->fixedp(1.0,g3)
12.
ans =
2.1253885
-->fixedp(-1.0,g3)
13.
ans =
2.1253935 + .0000049i
-->fixedp(0.0,g3)
13.
ans =
2.1253872
The number shown before the variable ans in these results indicates the number of iterations.
The fixed-point iteration method does not always converge. There is no convergence pattern
for this method. Whether the method converges or not depends on the form of the function
g(x) as well as on the initial value chosen.
f1(x1,x2,…,xn) = 0
f2(x1,x2,…,xn) = 0
.
.
f(x) = 0,
where the vector x contains the independent variables, and the vector f contains the functions
fi(x):
x1 f 1 ( x1 , x 2 ,..., x n ) f 1 (x)
x f ( x , x ,..., x ) f (x)
x= 2
, f ( x) = 2 1 2
n
= 2 .
M M M
xn f n ( x1 , x 2 ,..., x n ) f n (x)
∂f 1 / ∂x1 ∂f 1 / ∂x 2 L ∂f 1 / ∂x n
L ∂f 1 / ∂x n
∂ ( f1 , f 2 ,..., f n ) ∂f 2 / ∂x1 ∂f 1 / ∂x 2 ∂f
J= = = [ i ] n×n .
∂ ( x1 , x 2 ,..., x n ) M M O M ∂x j
∂f n / ∂x1 ∂f n / ∂x 2 L ∂f n / ∂x n
If x = x0 (a vector) represents the first guess for the solution, successive approximations to the
solution are obtained from
xn+1 = xn - J-1⋅f(xn) = xn - ∆xn,
with ∆xn = xn+1 - xn.
Convergence criteria for the solution of a system of non-linear equation could be, for example,
that the maximum of the absolute values of the functions fi(xn) is smaller than a certain
tolerance ε, i.e.,
max | f i (x n ) |< ε .
i
Another possibility for convergence is that the magnitude of the vector f(xn) be smaller than
the tolerance, i.e.,
|f(xn)| < ε.
We can also use as convergence criteria the difference between consecutive values of the
solution, i.e.,
max | ( xi ) n +1 − ( xi ) n | < ε .,
i
or,
while (N>0)
JJ = J(xx);
if(abs(det(JJ))<epsilon) then
error('newtonm - Jacobian is singular - try new x0');
abort;
end;
xn = xx - inv(JJ)*f(xx);
if(abs(f(xn))<epsilon)then
x=xn;
disp(1000-N);
return(x);
end;
if (abs(f(xx))>maxval)then
disp(100-N);
error('Solution diverges');
abort;
end;
N = N - 1;
xx = xn;
end;
error('No convergence');
abort;
//end function
The functions f and the Jacobian J need to be defined as separate functions. To illustrate the
definition of the functions consider the system of non-linear equations:
∂f 1 ∂f 1
∂x ∂x 2 2 x1 2 x2
J= 1 =
∂f 2 x 2 x1
.
∂f 2
∂x1 ∂x 2
We can define the function f as the following user-defined SCILAB function f2:
//end function
The corresponding Jacobian is calculated using the user-defined SCILAB function jacob2x2:
//end function
-->getf('f2')
-->getf('jacob2x2')
-->x0 = [2;1]
x0 =
! 2. !
! 1. !
Let’s calculate the function f(x) at x = x0 to see how far we are from a solution:
-->f2(x0)
ans =
Obviously, the function f(x0) is far away from being zero. Thus, we proceed to calculate a
better approximation by calculating the Jacobian J(x0):
-->J0 = jacob2x2(x0)
J0 =
! 4. 2. !
! 1. 2. !
-->x1 = x0 - inv(J0)*f2(x0)
x1 =
! 9.3333333 !
! 8.8333333 !
-->f2(x1)
ans =
! 115.13889 !
! 57.444444 !
Still far away from convergence. Let’s calculate a new approximation, x2:
-->x2 = x1 - inv(jacob2x2(x1))*f2(x1)
x2 =
! 6.0428135 !
! 5.7928135 !
Evaluating the functions at x2 indicates that the values of the functions are decreasing:
-->f2(x2)
ans =
! 20.072282 !
! 10.004891 !
-->x3 = x2 - inv(jacob2x2(x2))*f2(x2)
x3 =
! 5.1336734 !
! 5.0086734 !
-->f2(x3)
ans =
! 1.4414113 !
! .7128932 !
The functions are getting even smaller suggesting convergence towards a solution.
Solution using function newtonm
Next, we use function newtonm to solve the problem postulated earlier. We start by loading
function newtonm:
A call to the function using the values of x0, f2, and jacob2x2, already loaded is:
-->[x] = newtonm(x0,f2,jacob2x2)
16.
x =
! 5.0000038 !
! 4.9999962 !
The result shows the number of iterations required for convergence (16) and the solution found
as x1 = 5.0000038 and x2 = 4.9999962. Evaluating the functions for those solutions results in:
-->f2(x)
ans =
1.0E-10 *
! .2910383 !
! - .1455192 !
The values of the functions are close enough to zero (error in the order of 10-10).
Note: The functions f2 and jacob2x2 can be loaded as line functions by using deff:
-->deff('[f]=f2(x)',['f_1=x(1)^2+x(2)^2-50';'f_2=x(1)*x(2)-25';'f=[f_1;f_2]'])
--
>deff('[J]=jacob2x2(x)',['J11=2*x(1)';'J12=2*x(2)';'J21=x(2)';'J22=x(1)';'J=[J1
1,J12;J21,J22]'])
The “secant” method for a system of non-linear equations free us from having to define the n2
functions necessary to define the Jacobian for a system of n equations. Instead, we
approximate the partial derivatives in the Jacobian with
∂f i f i ( x1 , x 2 , L, x j + ∆x, L , x n ) − f i ( x1 , x 2 , L, x j , L , x n )
≈ ,
∂x j ∆x
where ∆x is a small increment in the independent variables. Notice that ∂fi/∂xj represents
element Jij in the jacobian J = ∂(f1,f2,…,fn)/∂(x1,x2,…,xn).
[m n] = size(x);
for j = 1:n
xx = x;
xx(j) = x(j) + delx;
J(:,j) = (f(xx)-f(x))/delx;
end;
//end function
Notice that for each column (i.e., each value of j) we define a variable xx which is first made
equal to x, and then the j-th element is incremented by delx, before calculating the j-th
column of the Jacobian, namely, J(:,j). This is the SCILAB implementation of the finite
difference approximation for the Jacobian elements Jij = ∂fi/∂xj as defined earlier.
-->getf('f2')
-->getf('jacobFD')
We choose an initial guess for the solution as x0 = [2;3], and an increment in the independent
variables of ∆x = 0.1:
-->x0 = [2;3]
x0 =
! 2. !
! 3. !
-->dx = 0.1
dx =
.1
Variable J0 will store the Jacobian corresponding to x0 calculated through finite differences
with the value of ∆x defined above:
-->J0 = jacobFD(f2,x0,dx)
J0 =
! 4.1 6.1 !
! 3. 2. !
-->x1 = x0 - inv(J0)*f2(x0)
x1 =
! 6.1485149 !
! 6.2772277 !
-->J1 = jacobFD(f2,x1,dx)
J1 =
! 12.39703 12.654455 !
! 6.2772277 6.1485149 !
-->x2 = x1 - inv(J1)*f2(x1)
x2 =
! 6.1417644 !
! 3.9045469 !
The next two approximations to the solution (x3 and x4) are calculated without first storing the
corresponding finite-difference Jacobians:
-->x3 = x2 - inv(jacobFD(f2,x2,dx))*f2(x2)
x3 =
! 5.5599859 !
! 4.4403496 !
-->x4 = x3 - inv(jacobFD(f2,x3,dx))*f2(x3)
x4 =
! 5.2799174 !
! 4.7200843 !
-->f2(x4)
ans =
! .1567233 !
! - .0783449 !
The functions are close to zero, but not yet at an acceptable error (i.e., something in the order
of 10-6). Therefore, we try one more approximation to the solution, i.e., x5:
-->x5 = x4 - inv(jacobFD(f2,x4,dx))*f2(x4)
x5 =
! 5.1399583 !
! 4.8600417 !
The functions are even closer to zero than before, suggesting a convergence to a solution.
-->f2(x5)
ans =
! .0391768 !
! - .0195883 !
To make the process of achieving a solution automatic, we propose the following SCILAB user -
defined function, secantm:
if abs(x0-x1)<epsilon then
error('x1=x0 - use different values');
abort;
end;
[n m] = size(x1);
while (N>0)
fxn = f(xn);
fxnm1 = f(xnm1);
for i = 1:n
for j = 1:n
JJ(i,j) = (fxn(i)-fxnm1(i))/(xn(j)-xnm1(j))
end;
end;
if abs(det(JJ))<epsilon then
error('newtonm - Jacobian is singular - try new x0,x1');
abort;
end;
xnp1 = xn - inv(JJ)*f(xn);
if abs(f(xnp1))<epsilon then
x=xnp1;
disp(1000-N);
return(x);
end;
if abs(f(xnp1))>maxval then
disp(100-N);
error('Solution diverges');
abort;
end;
N = N - 1;
xnm1 = xn;
xn = xnp1;
end;
error('No convergence');
abort;
To solve the system represented by function f2, we start by loading function secantm:
-->getf('secantm')
-->x = secantm(x0,dx,f2)
18.
x =
! 4.9999964 !
! 5.0000036 !
where x0 is a real vector representing an initial guess for the solution; fct is an external (i.e
function or list or string) representing the equation fct(x) = 0; fjac is an external (i.e function
or list or string) representing a Jacobian or derivative; and, tol is a real scalar representing
the tolerance for convergence. The default value of tol, if not provided in the function call, is
tol=1.0x10-10.
Termination of a fsolve function call occurs when the algorithm estimates that the relative
error between x and the solution is at most tol.
In the left-hand side of the function call, x is a real vector representing the final value of the
solution; v is a real vector representing the value of the function at x; and info is an integer
representing a termination indicator. Info can take any of the following values corresponding
to different termination conditions:
As indicated above, this function can be used to solve for a system of linear equations,
including a Jacobian matrix (fjac). For a single non-linear equation, fjac is the derivative.
-->deff('[y]=f(x)','y=x^3-2*x^2+1')
-->deff('[y]=fp(x)','y=x*x^2-4*x')
1.618034
1.618034
1.9999745
2.220E-16
x =
- .6180340
1.
f_x =
- 2.220E-16
x =
- .6180340
-
-->getf('jacob2x2')
Next, we define an initial value for the solution, x0, and call function fsolve using f2, jacob2x2:
-->x0 = [3;-2]
x0 =
-->fsolve(x0,f2,jacob2x2)
ans =
! 5. !
! 5. !
A second call to the function includes a left-hand side specifying the solution, x, the value of
the function at the solution, f_x, and information about the solution, info:
-->[x,f_x,info] = fsolve(x0,f2,jacob2x2)
info =
1.
f_x =
! 0. !
! 0. !
x =
! 5. !
! 5. !
You can also call function fsolve without including the Jacobian:
-->[x,f_x,info] = fsolve(x0,f2)
info =
1.
f_x =
! 0. !
! - 3.553E-15 !
x =
! 5.0000001 !
! 4.9999999 !
A second example involves the solution of the system of 3 non-linear equations without using
the Jacobian:
-->deff('[y]=f3(x)',['f_1=x(1)^2-x(2)^2+x(3)^2-4','f_2=x(1)*x(2)-x(3)+1',...
-->'f_3=sqrt(x(1)*x(2)*x(3))-1.4142','y=[f_1;f_2;f_3]'])
-->x0 = [3,3,3]
x0 =
-->[xs,fxs,m] = fsolve(x0',f3)
m =
1.
fxs =
1.0E-15 *
! - .4440892 !
! 0. !
! - .2220446 !
xs =
! 1.0000064 !
! .9999808 !
! 1.9999872 !
Arora, J.S., 1985, "Introduction to Optimum Design," Class notes, The University of Iowa, Iowa City, Iowa.
Asian Institute of Technology, 1969, "Hydraulic Laboratory Manual," AIT - Bangkok, Thailand.
Berge, P., Y. Pomeau, and C. Vidal, 1984,"Order within chaos - Towards a deterministic approach to turbulence," John
Wiley & Sons, New York.
Bras, R.L. and I. Rodriguez-Iturbe, 1985,"Random Functions and Hydrology," Addison-Wesley Publishing Company,
Reading, Massachussetts.
Brogan, W.L., 1974,"Modern Control Theory," QPI series, Quantum Publisher Incorporated, New York.
Browne, M., 1999, "Schaum's Outline of Theory and Problems of Physics for Engineering and Science," Schaum's
outlines, McGraw-Hill, New York.
Farlow, Stanley J., 1982, "Partial Differential Equations for Scientists and Engineers," Dover Publications Inc., New
York.
Friedman, B., 1956 (reissued 1990), "Principles and Techniques of Applied Mathematics," Dover Publications Inc., New
York.
Gomez, C. (editor), 1999, “Engineering and Scientific Computing with Scilab,” Birkhäuser, Boston.
Gullberg, J., 1997, "Mathematics - From the Birth of Numbers," W. W. Norton & Company, New York.
Harman, T.L., J. Dabney, and N. Richert, 2000, "Advanced Engineering Mathematics with MATLAB® - Second edition,"
Brooks/Cole - Thompson Learning, Australia.
Harris, J.W., and H. Stocker, 1998, "Handbook of Mathematics and Computational Science," Springer, New York.
Hsu, H.P., 1984, "Applied Fourier Analysis," Harcourt Brace Jovanovich College Outline Series, Harcourt Brace
Jovanovich, Publishers, San Diego.
Journel, A.G., 1989, "Fundamentals of Geostatistics in Five Lessons," Short Course Presented at the 28th International
Geological Congress, Washington, D.C., American Geophysical Union, Washington, D.C.
Julien, P.Y., 1998,”Erosion and Sedimentation,” Cambridge University Press, Cambridge CB2 2RU, U.K.
Keener, J.P., 1988, "Principles of Applied Mathematics - Transformation and Approximation," Addison-Wesley
Publishing Company, Redwood City, California.
Koch, G.S., Jr., and R. F. Link, 1971, "Statistical Analysis of Geological Data - Volumes I and II," Dover Publications,
Inc., New York.
Korn, G.A. and T.M. Korn, 1968, "Mathematical Handbook for Scientists and Engineers," Dover Publications, Inc., New
York.
Kottegoda, N. T., and R. Rosso, 1997, "Probability, Statistics, and Reliability for Civil and Environmental Engineers,"
The Mc-Graw Hill Companies, Inc., New York.
Kreysig, E., 1983, "Advanced Engineering Mathematics - Fifth Edition," John Wiley & Sons, New York.
Lindfield, G. and J. Penny, 2000, "Numerical Methods Using Matlab®," Prentice Hall, Upper Saddle River, New Jersey.
Magrab, E.B., S. Azarm, B. Balachandran, J. Duncan, K. Herold, and G. Walsh, 2000, "An Engineer's Guide to
MATLAB®", Prentice Hall, Upper Saddle River, N.J., U.S.A.
McCuen, R.H., 1989,”Hydrologic Analysis and Design - second edition,” Prentice Hall, Upper Saddle River, New Jersey.
Middleton, G.V., 2000, "Data Analysis in the Earth Sciences Using Matlab®," Prentice Hall, Upper Saddle River, New
Jersey.
Newland, D.E., 1993, "An Introduction to Random Vibrations, Spectral & Wavelet Analysis - Third Edition," Longman
Scientific and Technical, New York.
Nicols, G., 1995, “Introduction to Nonlinear Science,” Cambridge University Press, Cambridge CB2 2RU, U.K.
Parker, T.S. and L.O. Chua, , "Practical Numerical Algorithms for Chaotic Systems,” 1989, Springer-Verlag, New York.
Peitgen, H-O. and D. Saupe (editors), 1988, "The Science of Fractal Images," Springer-Verlag, New York.
Peitgen, H-O., H. Jürgens, and D. Saupe, 1992, "Chaos and Fractals - New Frontiers of Science," Springer-Verlag, New
York.
Press, W.H., B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling, 1989, “Numerical Recipes - The Art of Scientific
Computing (FORTRAN version),” Cambridge University Press, Cambridge CB2 2RU, U.K.
Raghunath, H.M., 1985, "Hydrology - Principles, Analysis and Design," Wiley Eastern Limited, New Delhi, India.
Recktenwald, G., 2000, "Numerical Methods with Matlab - Implementation and Application," Prentice Hall, Upper
Saddle River, N.J., U.S.A.
Rothenberg, R.I., 1991, "Probability and Statistics," Harcourt Brace Jovanovich College Outline Series, Harcourt Brace
Jovanovich, Publishers, San Diego, CA.
Sagan, H., 1961,"Boundary and Eigenvalue Problems in Mathematical Physics," Dover Publications, Inc., New York.
Spanos, A., 1999,"Probability Theory and Statistical Inference - Econometric Modeling with Observational Data,"
Cambridge University Press, Cambridge CB2 2RU, U.K.
Spiegel, M. R., 1971 (second printing, 1999), "Schaum's Outline of Theory and Problems of Advanced Mathematics for
Engineers and Scientists," Schaum's Outline Series, McGraw-Hill, New York.
Tanis, E.A., 1987, "Statistics II - Estimation and Tests of Hypotheses," Harcourt Brace Jovanovich College Outline
Series, Harcourt Brace Jovanovich, Publishers, Fort Worth, TX.
Tinker, M. and R. Lambourne, 2000, "Further Mathematics for the Physical Sciences," John Wiley & Sons, LTD.,
Chichester, U.K.
Tolstov, G.P., 1962, "Fourier Series," (Translated from the Russian by R. A. Silverman), Dover Publications, New York.
Tveito, A. and R. Winther, 1998, "Introduction to Partial Differential Equations - A Computational Approach," Texts in
Applied Mathematics 29, Springer, New York.
Urroz, G., 2000, "Science and Engineering Mathematics with the HP 49 G - Volumes I & II", www.greatunpublished.com,
Charleston, S.C.
Urroz, G., 2001, "Applied Engineering Mathematics with Maple", www.greatunpublished.com, Charleston, S.C.