HOMOTOPY CONTINUATION METHODS:

advertisement
HOMOTOPY CONTINUATION METHODS:
An Algorithm for the Fixed Point and Newton Homotopy Methods with Some Examples
Francesco Decarolis
fdc@uchicago.edu
Ricardo Mayer
ricardom@uchicago.edu
Martin Santamaria
msantama@uchicago.edu
ABSTRACT
Homotopy Continuation Methods provide a useful
approach to find the zeros of f : Rn →Rn in a globally
convergent way. Homotopy Methods transform a hard
problem into a simpler one whit easily calculated zeros
and then gradually deform this simpler problem into
the original one computing the zeros of the intervening
problems and eventually ending with a zero of the
original problem.
This paper presents a description of a Matlab code that
can implement the Fixed Point Homotopy and the
Newton Homotopy methods to find the zeros of any
function f : Rn →Rn.
Four examples are also provided for illustrative
purposes. Two univariate examples, one of which
regarding a General Equilibrium problem, and two
multivariate ones show how the Matlab code can be
easily applied to different problems.
You will need Matlab's Symbolic Math Toolbox to run
this code.
1. INTRODUCTION: the Homotopy Continuation Methods in General
This paper accompanies a code that can implement the Fixed Point Homotopy and the
Newton Homotopy methods to find the zeros of any function f : Rn →Rn. Homotopy
methods belong to the family of continuation methods and like all these methods they
represent a way to find a solution to a problem by constructing a new problem, simpler
than the original one, and then gradually deforming this simpler problem into the original
one keeping track of the series of zeros that connect the solution of the simpler problem
to that of the original, harder one. The greatest advantage of the Homotopy Methods is
that, under some conditions, they offer a way to have a globally convergent method to
find the zeros of any function f : Rn →Rn.
Judd (1998), chapter 5, contains a detailed description of the computational issues
involved in the use of these Homotopy Continuation Methods. In this paper we follow the
discussion in Judd (1998) to construct a simple code that allows to use the Fixed Point
Homotopy (FPH) and the Newton Homotopy (NH) to find the zeros of f : Rn →Rn.
All the Homotopy methods are based on the construction of a function, H(x,t),
H: Rn+1 →Rn,
H∈C0(Rn+1). This function H , which is called the Homotopy function,
serves the objective of continuously deforming a function g into f and can be any
continuous function such that: H(x,0)=g(x) and H(x,1)=f(x). Hence we construct H(x,0)
in such a way that its zeros are easily found while we also require that, once the
parameter t is equal to 1, then H coincides with the original function f .
Among the various Homotopy functions that are generally used the Fixed Point
Homotopy and the Newton Homotopy are simple and powerful methods that can be
successfully applied to several different problems. In the next sections we describe how
these two Homotopy functions are constructed and we illustrate how the Matlab code that
we wrote applies these methods in an algorithm to find the zeros of f : Rn →Rn. Finally
we illustrate how to actually use the Matlab code we wrote through four examples, both
univariate and multivariate.
2. FIXED POINT HOMOTOPY, NEWTON HOMOTOPY AND THEIR
IMPLEMENTATION
The code described in the next section is an algorithm that finds zeros of f : Rn →Rn
through an Homotopy method. The two Homotopy methods between which our code
allows to chose are the following:
(a) Fixed Point Homotopy:
H(x,t)=(1-t) (x-x0)+tf(x)
for some x0.
(b) Newton Homotopy:
H(x,t)= f(x) - (1-t) f(x0)
for some x0.
The first Homotopy function gradually deforms the function (x-x0) into f(x), while the
second one is a function that for t=0 has its zero at x=x0 while at t=1 it is f(x). The idea of
our code will be to follow the path connecting the zeros of H(x,t) from t=0, where they
are as described above, until t=1, where we will have found the zeros of the original
problem. If H(x,0) and H(x,1) have zeros we will try to develop a way to follow a
continuous path, which we indicate as H-1(0), H-1(0)={(x,t)│H(x,t)=0}, that connects one
to the other.
The procedure we follow in order to create a code that traces the path H-1(0) is based on
the parametric approach described in Judd (1998). Hence we view x and t as both
functions of the same parameter s and we require that a parametric path satisfies
H(x(s),t(s))=0 for all s. Being on the path thus implies that we have an y(s)=(x(s),t(s))
such that H is equal to zero hence for changes in x and t it must be that y obeys the
following system differential equations (see Garcia and Zangwill (1981)):
dyi
ds
 −1i det ∂H
y−i, i  1,...,n1
∂y
where ( · )-i means that we remove the ith column.
For the system defined by the above equation to arrive to t(s)=1 it must be that we never
find any singular matrix (((∂H)/(∂y))(y)-i) before that. The condition that insures that this
is the case is that the Homotopy function H is regular, where we define H to be regular
whenever Hy=(Hx,Ht) is of full rank (i.e. rank n) at all points in H-1(0) and y≡(x,t).
The code that we present in the next section builds on this parametric approach to
describe a path in the (x,t) space that connects the zeros of H(x,0) to those of H(x,1).
3. THE CODE
The code involves using only 2 m-files, only one of them written by the user. These are:
•
A User's Script (US) : this is the only file a user will need to run. Here the user must
write the equations he wants to solve (it may be only one equation) as long with the
other inputs needed by htopy.m. This program calls the function htopy, get's the
results and further calls fsolve to refine the solution delivered by htopy. We suggest
the user first read carefully and understand well the example file called
'examplebook.m' . This example show how to solve an univariate problem and
contains extensive comments. Later, the reader should take a look at any other
example just to see the small changes needed to solve a multivariate problem. Note
that there is the freedom to choose any letter (like x, q, z, etc., or even multi-characters
expressions like x1, x2, xx1, xx2, etc.) for the independent variables with the
exception of y and t , because those will be names used internally by htopy. The order
in which the user inputs these variables will be the one in which the plots and of the
elements in the Homotopy solution vector, hopt, will appear.
•
The m-file function htopy.m. The function is relatively well-documented and we
encourage the user to have a glance of at least the first comments included in the file:
it provides a description of the inputs needed to call the function, the output it gives,
describes the organization of the whole algorithm and the choices made during the
execution of the program. Is short, htopy has two main parts:
(a) The first uses the Symbolic Math Toolbox's capabilities to construct the system of
ODEs defining the solution's path. This is, the user only have to know his initial
system of equation and not the possibly quite different system of ODEs: this is
computed on-the-fly by htopy. In particuar it will compute a symbolic Jacobian of the
system and symbolic Determinants of parts of the Jacobian. It never writes a new mfile: it will store the system of ODEs as an inline function to feed the ODE-solver
later. Some work inside the function is spent in converting symbolic object into string
objects suitable for inline functions.
(b) The second part takes such system of ODEs -now in form an inline function- and
calls the ODE-solver specified by the user. It does the path-tracking and explores
whether we have reached a solution and whether the solution is an acceptable one.
Conditional on success, returns the value of the candidate solution. If something fails
it gives an appropriate warning and information to the User so she can decide how to
proceed next.
4. FOUR APPLICATIONS OF THE HOMOTOPY CODE
Here we present four examples that will illustrate how to use the code described above.
The first two examples are univariate. In particular the first one is the same used in Judd
(1998), chapter 5, to present the Homotopy methods. Here it will be particularly useful to
exemplify the differences between the Fixed Point and the Newton Homotopy. The
second one, instead, is a simple General Equilibrium and we show how the code is used
to find the equilibrium prices. Then, finally, the third and fourth examples illustrate how
to apply the htopy.m code to multivariate problems.
4.1 Example1 (Taken from Judd (1998)).
The problem is to find the value of x for which f(x)=0, where f(x) is given by:
f(x)=2*x - 4 + sin(2*pi*x)
The unique solution of this problem is x=2. Below we show the results that we get from
the code reported in the Appendix at the end of this paper. We pick as our initial guess
for x, x0=0. We further choose to have 70 checks and UpS equal to 2.5. For the two
Homotopy methods that our htopy.m function can compute we get the following results:
(a) Fixed Point Homotopy
Computed Solutions
Homotopy Solution:
2.0008e+000
Gauss-Newton Solution:
2.0000e+000
The solution, hsol, is found in the 20th chunk in which the interval [0, uppers] has been
partitioned. The code also reports the value of H at the end of each of the previous 19
chunks and these values are always close enough to zero (according to the Htol parameter
defined in htopy.m) so that the code never uses the Gauss-Newton solver to generate the
initial guess for the ODE solver.
The figure below shows the path connecting the zero of H(x,0) to that of H(x,1). This last
zero is found at x=2.0008e+000 by our Fixed Point Homotopy method. When this value
of x is used as an initial guess for the Matlab Gauss-Newton solver (fsolve) we get that
the solution is x=2.0000e+000. This illustrates one of the key aspect of the parametric
Homotopy approach that we implement: although it does not produce by itself
particularly accurate solutions, still its outcome is accurate enough to be a good initial
guess for more refined, possibly local, methods to find the solution of the problem at
hand.
Figure 1: the Fixed Point Homotopy
1
0.9
0.8
0.7
t
0.6
0.5
0.4
0.3
0.2
0.1
0.2
0.4
0.6
0.8
1
1.2
independent variable
1.4
1.6
1.8
2
(b) Newton Homotopy
Computed Solutions
Homotopy Solution:
2.0000e+000
Gauss-Newton Solution:
2.0000e+000
This second method finds a even more refined solution that the previous one.
Interestingly we can see from the picture below how the path described by this Homotopy
method differs from the Fixed Point one used above.
Figure 2: the Newton Homotopy
0.9
0.8
0.7
t
0.6
0.5
0.4
0.3
0.2
0.1
0.2
0.4
0.6
0.8
1
1.2
independent variable
1.4
1.6
1.8
2
4.2 Example2. (General Equilibrium).
Assume a two good economy populated by only one type of individuals with CES utility
function given by:


1
Ux1,x2  x1  1 − x2  
Then it is a simple exercise of calculus to show that the excess demand of good one as a
function of the relative price p and the endowment vector e is given by:
z1p,p e 


p
pe

 1−
p
1−
−e1
The excess demand is shown below for α=0.2, ρ=0.5 and endowment vector e=(0.1 , 0.3).
As can be seen from the picture there are at least two equilibria.
Figure 3: the Excess Demand Function
0.01
0.008
0.006
0.004
0.002
0
-0.002
-0.004
-0.006
-0.008
-0.01
0
10
20
30
40
50
60
70
80
90
100
Finding the zeros of the excess demand using Homotopy continuation methods
First we start with two figures that illustrate how the Homotopy method works for this
simple case. In both cases we use the Newton Homotopy, defined by:
Hp,t  z1p,p  et  1 − tz1p,p  e − z1p0,p0  e
Intuitively, to get to the solution we start by solving the equation z1(p,p·e) – z1(p0, p0·e)
which has a solution at p0. And then we continuously deform this equation (of which we
know the solution) into the original excess demand function. The first figure illustrates
the case where p0 is smaller than the equilibrium price. As we can see from the figure as
we continuously change t from 0 to 1 the zeros of the Homotopy function converge to the
zero of the excess demand function monotonically from below.
Figure 4: Newton Homotopy for the GE with p0=1.
0.02
t=0
t=1
t=0.5
t=.7
t=.8
t=.9
0.015
0.01
0.005
0
-0.005
-0.01
-0.015
-0.02
0
1
2
3
4
5
6
The next picture, instead, depicts the opposite situation . In this case the convergence to
the solution is from above.
Figure 5: Newton Homotopy for the GE with p0=5.
0.02
t=0
t=1
t=0.5
t=.7
t=.8
t=.9
0.015
0.01
0.005
0
-0.005
-0.01
-0.015
-0.02
0
1
2
3
4
5
6
Now we show the results that we get once we use the htopy.m function to find a solution
to the problem at hand. These codes are reported at the end of this paper in the appendix.
Computed Solutions
Newton Homotopy Solution (p0=1):
2.1429e+000
Newton Homotopy Solution (p0=5):
2.3357e+000
The following figures show the set {(x,t):H(x,t)=0} found by our code respectively with
the initial guess p0=1 and p0=5.
Figura 6: Newton Homotopy for the GE with p0=1: the parametric path.
0.9
0.8
0.7
0.6
t
0.5
0.4
0.3
0.2
0.1
1.1
1.2
1.3
1.4
1.5
1.6
1.7
in d e p e n d e n t va ria b le
1.8
1.9
2
Figura 7: Newton Homotopy for the GE with p0=5: the parametric path.
0.9
0.8
0.7
0.6
t
0.5
0.4
0.3
0.2
0.1
2.5
3
3.5
4
in d e p e n d e n t va ria b le
4.5
2.1
4.3 Example3. (Bivariate Case).
The problem is to find the value of x,q,z for which f(x,q)=0, where f(x,q) is given by:
f1(x,q)= x^2 + q^2-1
f2(x,q)= sin(x)-q
The system has two symmetric solutions. Below we show the results that we get from the
code reported in the Appendix at the end of this paper. We pick as our initial guess (0,0).
We further choose to have 70 checks and UpS equal to 10. For the first one of the
Homotopy methods that our htopy.m function can compute we get the following results:
(a) Fixed Point Homotopy
Computed Solutions
x
q
Homotopy Solutions:
-7.388530437289927e-001
-6.756862152576728e-001
Gauss-Newton Solutions:
-7.390851332165159e-001
-6.736120291852369e-001
Functions Evaluation at the Computed Solutions
x^2 + q^2-1
sin(x)-q
At Homotopy Solutions
1.227087985954902e-003
1.122180544844956e-003
At Gauss-Newton Solutions
2.363775841726627e-012
5.102029909658878e-013
The code also reports the results of H evaluated at the end of each subinterval and we
have that these values are always close enough to zero so that the code does not call the
Gauss-Newton solver to be set back on track.
The pictures below show the path that our code finds.
Figure 8: variable by variable. x in the upper subplot and q in the lower one
1
0.8
t
0.6
0.4
0.2
-0.7
-0.6
-0.5
-0.4
-0.3 -0.2 -0.1
0
independent variable
0.1
0.2
0.3
1
0.8
t
0.6
0.4
0.2
-1
-0.9
-0.8
-0.7
-0.6
-0.5
-0.4
independent variable
-0.3
-0.2
-0.1
Figure 9: 3D plot of the path
3D P lot of the s olution
1
0.8
t
0.6
0.4
0.2
0
0
0.5
0
-0.5
-1
q
-0.5
-1.5
-1
x
4.4 Example4. (Trivariate Case).
The problem is to find the value of x,q,z for which f(x,q,z)=0, where f(x,q,z) is given by:
f1(x,q)= x + 0.5*q + 0.3*z-5
f2(x,q)= 0.6*x + q + z*0.1-7
f3(x,q)= 0.2*x + 0.4*q + z-4
The system above is linear, the solutions given by Mathematica is x=1.67155, q=5.8651
and z=1.31965. Below we show the results that we get from the code reported in the
Appendix at the end of this paper. We pick as our initial guess (0,0,0). We further choose
to have 50 checks and UpS equal to 30. For the for the first one of the Homotopy
methods that our htopy.m function can compute we get the following results:
(a) Fixed Point Homotopy
Computed Solutions
x
q
z
Homotopy Solutions:
1.6731e+000
5.8575e+000
1.3209e+000
Gauss-Newton Solutions
1.6716e+000
5.8651e+000
1.3196e+000
Functions Evaluation at the Computed Solutions
x + 0.5*q + 0.3*z-5
0.6*x + q + z*0.1-7
0.2*x + 0.4*q + z-4
At Homotopy Solut.
-2.5918e-004
-9.0738e-004
-2.0462e-004
At Gauss-Newton Solut.
2.6838e-012
-1.3749e-012
4.3367e-012
The three dimensional graph of the solution (just the values of x, q and z, not t) is:
3 D P lo t o f t h e s o lu t io n
1 .5
z
1
0 .5
2
0
6
5
4
1
3
2
q
1
0
x
Instead the figure below plots how each of the original independent variables changes
along the path as t increases from zero to one.
Figure 10: variable by variable. x in the upper subplot, q in the middle one and z in the
lower one.
1
0.8
t
0.6
0.4
0.2
0.2
0.4
0.6
0.8
1
independent variable
1.2
2
2.5
3
3.5
independent variable
4
1.4
1.6
1.8
1
0.8
t
0.6
0.4
0.2
0.5
1
1.5
4.5
5
5.5
1
0.8
t
0.6
0.4
0.2
0.2
0.4
0.6
0.8
independent variable
1
1.2
1.4
5. BIBLIOGRAPHY
- Judd, K. L. (1998). Numerical Methods in Economics. MIT Press, Cambridge, MA.
- Garcia, C. B. and W. I. Zangwill (1981). Pathways to Solutions, Fixed Points and
Equilibria. Prentice Hall, Englewood Cliffs, NJ.
Appendix
Example 1. One equation in one unknown, taken from Judd (1998), chapter 5.
clear;
clc;
%EXAMPLE-BOOK.
%(FROM JUDD (1998) CHAPTER 5)
%%%%%%%%%% Step 1: write down your system and variables as strings
fstring = [{'2*x - 4 + sin(2*pi*x)'}];
varlist = [{'x'}];
%%%%%%%%%% Step 2: Make some choices for your problem:
%%% choose the initial values for your variable
initialval = [0];
%%% choose the limits for your solutions
aboxa = [-100,100] ;
%%% choose an upper value for s (in the ode system)
upS =2.5;
%%% choose the number of intermediate checks for [0, upperS]
checks = 70;
%%% choose an homotopy : FP or N
homoto = 'FP';
%homoto = 'N';
%%% choose an ODE solver
% odesol = 'ode15'; %% it actually the ode15s solver
odesol = 'ode45';
%%%%%%%%%%%%%%% Step 3: call the homotopy function
[hsol, ff] = htopy(fstring,varlist,initialval, upS,checks, aboxa, homoto, odesol)
%%%%%%%%%%%%%%% Step 4: refine the solution calling fsolve
if ff == 1
nsol=fsolve(inline('[2*x(1) - 4 + sin(2*pi*x(1))]','x'),hsol)
end
Example 2. Codes for the General Equilibrium Example.
clear;
clc;
format short e;
%%%%%%%%%%%%%%%%%%
%Parameter Values%
%%%%%%%%%%%%%%%%%%
a = 0.2; %alpha
s=0.5;
%rho
%%%%%%%%%%%%%%%%%%
%Endowment Vector%
%%%%%%%%%%%%%%%%%%
e = [.1 .3];
%%%%%%%%%%%%%%%%%%
%Initial Guess
%
%%%%%%%%%%%%%%%%%%
x0=5;
%%%%%%%%%%%%%%%%%%
%Main Routine
%
%%%%%%%%%%%%%%%%%%
syms x1
syms f1
f1=-(((a/x1)^(s))*(((x1*e(1,1)+e(1,2))/((a^s)*(x1^(1-s))+(1-a)^s)))-e(1));
x=[x1];
f=[f1];
fstring = char([]);
varlist = char([]);
for i=1:1
fstring = [fstring, {char(f(i))}];
varlist = [varlist, {char(x(i))}];
end
%%%%%%%%%%%%%%%%%%%%%%
%Homotopy Parameters %
%%%%%%%%%%%%%%%%%%%%%%
upS =300;
checks=70;
aboxa=[0.1,10];
initialval = x0;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Choose an homotopy : FP or N %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%homoto = 'FP';
homoto = 'N';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Choose an ODE solver : ode15 or ode45 %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% odesol = 'ode15'; %% it actually the ode15s solver
odesol = 'ode45';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Step 3: Call the homotopy function %
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[hsol, ff] = htopy(fstring,varlist,initialval, upS,checks, aboxa, homoto, odesol)
Example 3. Two equations in two unknowns.
clear;
clc;
%Bivariate Example
format long e;
%%%%%%%%%% Step 1: write down your system and variables as strings
fstring1 = 'x^2 + q^2-1';
fstring2='sin(x)-q';
varlist = [{'x'},{'q'}];
fstring = [{fstring1},{fstring2}];
%%%%%%%%%% Step 2: Make some choices for your problem:
%%% choose the initial values for the variables
initialval = [0,0];
%%% choose the limits for your solutions
aboxa=[-100,100 ; -100, 100];
%%% choose an upper value for s (in the ode system)
upS =20;
%%% choose the number of intermediate checks for [0, upperS]
checks=70;
%%% choose an homotopy : FP or N
homoto = 'FP';
%homoto = 'N';
%%% choose an ODE solver
% odesol = 'ode15'; %% it is ctually the ode15s solver
odesol = 'ode45';
%%%%%%%%%%%%%%% Step 3: call the homotopy function
[hsol, ff] = htopy(fstring,varlist,initialval, upS,checks, aboxa, homoto, odesol)
%%%%%%%%%%%%
%%%%%%%%%%%%
%%%%%%%%%%%%
%%%%%%%%%%%%
%%%%%%%%%%%%
%%%%%%%%%%%%
if ff == 1
Step 4:in case the Homotopy finds a solution then ff=1 and
the solution found by the Homotopy, hsol, is reported.
The hsol is then used as an initial guess for fsolve and
finally both the original solution of the Homotopy, hsol,
and that of the Gauss-Newton solver, nsol, are used to
evaluate the equations of the original system.
nsol=fsolve(inline('[x(1)^2 + x(2)^2-1;sin(x(1))-x(2)]','x'),hsol)
fhom=(feval(inline('[x(1)^2 + x(2)^2-1;sin(x(1))-x(2)]','x'),hsol))./(1+norm(hsol))
fnew=(feval(inline('[x(1)^2 + x(2)^2-1;sin(x(1))-x(2)]','x'),nsol))./(1+norm(nsol))
end
Example 4. Three equations in three unknowns.
clear;
clc;
%Trivariate Example
format short e;
%%%%%%%%%% Step 1: write down your system and variables as strings
fstring1 = 'x + 0.5*q + 0.3*z-5';
fstring2='0.6*x + q + z*0.1-7';
fstring3='0.2*x + 0.4*q + z-4';
varlist = [{'x'},{'q'},{'z'}];
fstring = [{fstring1},{fstring2},{fstring3}];
%%%%%%%%%% Step 2: Make some choices for your problem:
%%% choose the initial values for the variables
initialval = [0, 0, 0];
%%% choose the limits for your solutions
aboxa=[-100,100 ;-100,100;-100, 100];
%%% choose an upper value for s (in the ode system)
upS =30;
%%% choose the number of intermediate checks for [0, upperS]
checks=50;
%%% choose an homotopy : FP or N
homoto = 'FP';
%homoto = 'N';
%%% choose an ODE solver
% odesol = 'ode15'; %% it is actually the ode15s solver
odesol = 'ode45';
%%%%%%%%%%%%%%% Step 3: call the homotopy function
[hsol, ff] = htopy(fstring,varlist,initialval, upS,checks, aboxa, homoto, odesol)
%%%%%%%%%%%%
%%%%%%%%%%%%
%%%%%%%%%%%%
%%%%%%%%%%%%
%%%%%%%%%%%%
%%%%%%%%%%%%
Step 4:in case the Homotopy finds a solution then ff=1 and
the solution found by the Homotopy, hsol, is reported.
The hsol is then used as an initial guess for fsolve and
finally both the original solution of the Homotopy, hsol,
and that of the Gauss-Newton solver, nsol, are used to
evaluate the equations of the original system.
if ff == 1
nsol=fsolve(inline('[x(1) +
;0.2*x(1) + 0.4*x(2) + x(3)
fhom=(feval(inline('[x(1) +
;0.2*x(1) + 0.4*x(2) + x(3)
fnew=(feval(inline('[x(1) +
;0.2*x(1) + 0.4*x(2) + x(3)
end
0.5*x(2) + 0.3*x(3)-5 ; 0.6*x(1) + x(2) + x(3)*0.1-7…
- 4]','x'),hsol)
0.5*x(2) + 0.3*x(3)-5 ; 0.6*x(1) + x(2) + x(3)*0.1-7…
- 4]','x'),hsol))./(1+norm(hsol))
0.5*x(2) + 0.3*x(3)-5 ; 0.6*x(1) + x(2) + x(3)*0.1-7…
- 4]','x'),nsol))./(1+norm(nsol))
THE HOMOTOPY ROUTINE: HTOPY.M
function
[opt,fall] = htopy(fu,svars, prex0, upperS, numchecks, box, Hchoice, ODEchoice)
% htopy2 computes an approximate solution to the system of equations fu(x)=0.
% It uses an homotopy represented by H(x,t)=0, with known solution for x at t=0, and
% with H(x,1)=fu(x)=0, so any x satisfying (approx) H(x,1) is an (approx) solution to
% fu(x), the system of interest.
% This implementation continously deforms H(x,0) into a sequence of H(x,t) by making
% x and t functions of another variable 's' (thus, x becomes x(s) and t becomes t(s)),
% and solves a sequence of systems of ODE in order to 'track' the path defined by H(x,t).
% For more explanations about this procedure and formulas involved, see Judd 1998, pages
% 179 to 187)
%
% OUTPUT:
%
% fall: fall = 1 only if the function succeeds. Success means: 1) a candidate solution
was found
% (i.e. a t close enough to 1 is found), AND 2) the candidate solution lies inside the
% bounds for x specified by the user (in 'box'). In any other case the function fails
% and fall = 0. This is useful to instruct other functions not to use the value in opt
% if fall is not 1.
%
% opt: if the function succeeds, opt is a vector of values x
% that makes fu(x) approx. zero. If fails because the candidate solution lies
% outside the box, then it returns and empty array []. If it fails because no
% candidate solution was found it ret)urns the values of x and t for the last
% iteration.
%
% INPUTS:
%
% fu: a cell array of strings representing a system of equations
% (it can be just a single equation) in the form f(x)=0
%
% svars : a cell array of strings containig the names of the variables included
% in fu (in particular, do not include t or s here)
%
% prex0 : a vector with the initial conditions for variables in svars
%
% upperS : this scalar is the upper bound used in the ODE part for s. You can set upperS
% relatively large and insert many check points between 0 and upperS. The function
% will exit as soon as one candidate solution has been found in any of the
% intervals defined by the checkpoints [0,s1,s2....upperS]. That can happen well
% before s is close to upperS.
%
% numchecks: A scalar. Is the number of intermediate checks s1,s2,s3... between 0
% and upperS. The fucntion will divide [0,upperS] in (numchecks+1) intervals of equal
% length
%
% box: an nx2 matrix. Each rows represent one variable in svars. The first column
% holds the lower bound for that variable and the second column contains the upper bound.
%
% Hchoice: a string. If it takes the value 'FP' then the (1-t)(x-x0) is
% done. If it takes the value 'N', it implements a Newton type homotopy (see page 179)
%
% ODEchoice: a string. If it takes the value 'ode45' then the solver ode45
% (runge-kutta, recommended choice for nonstiff problems) is used. If it takes the
% value 'ode15s', a BDF-type solver is used. This appropiate for stiff
% problem and when precision is less of a concern
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% Step 0: set tolerance parameters and default values
%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% this is our max acceptable deviation from H(x,t) = 0, we make this check
%%% at the end of each subinterval [s_{i} , s_{i+1}]
Htol = 1e-4;
%%% we accept t as close enough to 1 if t \in (1-epsilont , 1+epsilont)
epsilont=1e-1;
%% set the failure flag to 0, do not change to success unless on sol is found
fall=0;
%% set a void value for the solution as the default in case of failure
opt=[];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% Step 1: symbolize relevant variables and set the homotopy H
%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% simbolize s and t and some otehr symbols we may need
syms t s pi e a;
%%% augment the vector of initial conditions -prex0- adding the initial condition for t
%%% (zero) at the end. The augmented vector is x0
x0= [prex0, 0];
numvar = size(svars,2);
numfun = size(fu,2);
%% check your system is square
if numfun ~= numvar
'the number of variables is not equal to the number of equations'
return;
end
%% initialize these to be symbolic but empty
allvars = sym([]);
allfun = sym([]);
for i=1:numvar
allvars = [allvars, sym(svars{i})];
allfun = [allfun, sym(fu{i})];
end
%% now allvars contains all variables in symbolic form
%% and allfun has all equations in fu but with symbolic status
%%% Define your Homotopy
if Hchoice=='FP'
% this is the fixed point homotopy
H = (1-t)*(allvars-prex0) + t*allfun
elseif Hchoice=='N'
% Newton's homotopy
f0=allfun;
allfun
x0
for a=1:size(allvars,2)
f0=subs(f0,{allvars(a)},{x0(a)});
end
f0
H=allfun-(1-t)*f0
else
display('Error: no Homotopy was selected or you typed an incorrect name')
return;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% Step 2: Construct the system of ODEs (see eq. 5.9.4 , page 182)
%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%% Step 2.1: obtaing the RHS of the system
%% append symbolic t to end of list of symbolic x
allvars = [allvars, t];
%% compute the symbolic Jacobian of H w.r.t. x and t
J=jacobian(H,allvars);
%% form the Right Hand Side of the ODE system
allRHS = [];
for i = 1:numvar+1
subJ = J;
%% exclude the i-th column of the Jacobian before taking Determinant
subJ(:,i)=[];
%% concatenate each eq vertically, do the sign switch
allRHS=[allRHS; (-1)^i * (det(subJ))];
end
%% display the RHS of the ODE system
if mod(numvar,2)==0
allRHS=(-1)*allRHS;
end
%%
%%
%%
%%
now we change the notation of the symbolic expressions that appear
in allRHS. The reason is to get an expression that, once transformed
into a string (see step 2.2) will be usable as an inline function
accepted as input by fsolve (see step 2.3).
%% the first step to change the notation of allRHS is to create a row
%% vector y=[y(1), y(2), ..., y(numvar+1)], where numvar was defined in
%% step zero and corresponds to allvars-1.
yy=sym([]);
for j=1:size(allvars,2)
sj = num2str(j);
name = strcat('y(',sj,')');
yy(j)=name;
end
y=yy;
%% the second step in changing the notation is to sobstitute the original
%% variables given in allvars with the y(i) ones we constructed above.
[m1,n1]=size(allRHS);
B=jacobian(allRHS,allvars);
for j=1:m1
for i=1:m1
if B(j,i)==0
allRHSs(j)=allRHS(j);
else
allRHSs(j)=subs(allRHS(j),{allvars(i)},{y(i)});
end
allRHS(j)=allRHSs(j);
end
end
allRHS
%%%%%%% Step 2.2
%%%%%%% change the symbolic object to string object, so you can use inline functions
newstring = '[';
for i=1:size(allRHS,1)
for j=1:1
newstring = [newstring char(allRHS(i,j)) ' '];
end
newstring = [newstring ' ; '];
end
newstring = newstring(1:end-3); %remove trailing punctuation
newstring = strcat(newstring, ']');
%%%%%%% Step 2.3 :
%%%%%%% create an inline function to make RHS usable with Matlab's ODE-functions
f=inline(newstring,'s','y');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%
%%% Step 3: Do the path-tracking via ODE-solving
%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% these points define a uniform grid on [0,upperS]
checkpoints = linspace(0,1,numchecks+1)*upperS;
%% container for solutions passed by the ODE solver
pastedvalues = [];
pastedtime =[];
%% Htest will be used to asses value of H at the checkpoints. For now
%% it is a symbolic object but it will be converted to a number once we
%% have computed the values of t and the svars at which we want to compute
%% the value of H.
Htest = H;
k=0;
for j=1:numchecks
j
if (ODEchoice=='ode45')
[timepoints, varvalues] = ode45(f,[checkpoints(j),checkpoints(j+1)],x0);
elseif (ODEchoice=='ode15')
[timepoints, varvalues] = ode15s(f,[checkpoints(j),checkpoints(j+1)],x0);
else H=h;
display('Error: no ode-solver is being called or you typed an incorrect name')
return;
end
%% store the last chunk of x's t and s
pastedvalues = [pastedvalues; varvalues(2:end,:)];
pastedtime = [pastedtime; timepoints(2:end)];
%% update the initial conditions for x and t, to be used in the next iteration
x0 = varvalues(end,:);
%% find the value of t closest to 1 for this [s_i,s_{i+1}] interval
testvec =abs(varvalues(:,end) -1);
mintestvec= min(testvec);
k = k+size(testvec,1)-1;
%% test if our 'best' t is close enough to 1, if it's not, just go on
if (abs(mintestvec) < epsilont)
%% if t is accepted then report a candidate solution
z = min(testvec);
i=1;
while (testvec(i) ~= z)
i = i+1;
end
%% opt does not include tH=h;
%% set opt equal to your candidate solution
opt = varvalues(i,1:end-1);
%% test if your candidate solution lies inside the box for x or not
if (opt >= box(:,2)') | (opt <= box(:,1)')
display ('Out of bounds')
out_of_bound_guess=opt
%% your solution is out of the permisible region
%% exit the function, do not report fall=1
return;
end
%% your solution passed the test, report success
fall=1;
%%
%%
%%
if
in the case of success the program will create plots for each of
the original variables. Each plot has t on the vertical axis and
one of the independent variables on the orizontal axis.
m1 == 3
X1=pastedvalues(1:(k-size(testvec,1)+i),1);
Y1=pastedvalues(1:(k-size(testvec,1)+i),2);
Z1=pastedvalues(1:(k-size(testvec,1)+i),3);
plot3(X1,Y1,Z1)
grid on
xlabel('x')
ylabel('q')
zlabel('t')
title('3D Plot of the solution')
else
for l=1:m1-1
h(l)=subplot(m1-1,1,l); plot(pastedvalues(1:(ksize(testvec,1)+i),l)',pastedvalues(1:(k-size(testvec,1)+i),end)')
xlabel('independent variable')
ylabel('t')
axis([h(l)],'tight')
end
end
return
end
%% A cnadidate solution was not found on this subinterval. Before
%% checking the next subinterval (that is, going to the next j) we
%% assess if our new guess is such to satisfy the requirement that
%% H is equal to zero along all the path.
%% Tah is, we check taht H(x0,t)=0, where x0 is the last value of
%% varvalues.
for a=1:size(allvars,2)
Htest=subs(Htest,{allvars(a)},{x0(a)});
end
Htest
if (abs(Htest)/(1+norm(x0)) > Htol)
%% if we are off-path then use a solver to correct x, fixing t
display('Warning: off-the path. The Htol loop has been activated to correct the
initial guess for the next subinterval');
%
%
%
%
Now the program uses fsolve to produce a new vector of initial
guesses for the original independent variables, given of t which
we get at the end of the subinterval.
To produce the new guess we proceed in three parts:
%% PART I: H is evaluated at the last value of t and then the
%% notation is changed so to get an expression that, once
%% transformed into a string (see PART II) will be usable as an
%% inline function accepted as input by fsolve (see PART III).
[m2,n2]=size(H);
y(n2+1)=x0(n2+1);
B2=jacobian(H,allvars);
H2=H;
for u=1:n2
for v=1:m1
if J(u,v)==0
newHs(u)=H2(u);
else
newHs(u)=subs(H2(u),{allvars(v)},{y(v)});
end
H2(u)=newHs(u);
end
end
newH=sym([]);
r0=zeros(n2,1);
for r=1:n2
newH=[newH;H2(r)];
r0(r)=x0(r);
end
newH % shows H(y(1),...,y(numvar),t*). Where t* is the last value
% of t computed by the ODE solver for the subinterval at hand.
% PART II: then we need to make newH usable with fsolve. We make it a
% string.
newstring2 = '[';
for c=1:size(newH,1)
for w=1:1
newstring2 = [newstring2 char(newH(c,w)) ' '];
end
newstring2 = [newstring2 ' ; '];
end
newstring2 = newstring2(1:end-3); %remove trailing punctuation
newstring2 = strcat(newstring2, ']');
%% PART III: we use the above string into an inline function
%% that becomes the input of fsolve together with an initial
%% guess for the original independent variables given by the last
%% values generated for them by the ODE solver.
%% The new guess we generate through fsolve is called "newx".
f2=inline(newstring2,'y')
newx=fsolve(f2,r0)
%% Then we also implement a check to see how well we are on the path
%% with this new values of the independent variables and the value
%% of that ends the subinterval. That is we evaluate H at
%% (newx,t*). We call "newHtest" the value that we compute and that
%% we will compare to Htol.
x02=[(newx)',x0(n2+1)]
newHtest=H;
for a=1:size(allvars,2)
newHtest=subs(newHtest,{allvars(a)},{x02(a)});
end
newHtest
if abs(Htest)<abs(newHtest)
display('Matlab equation solver gave a worse x than the ODE solver')
return;
elseif (abs(newHtest)/(1+norm(x0)) > Htol)
display('Matlab equation solver gave a result such that H is far from zero. Check Htol')
return;
else
x0=x02
end % so either we start the check on the next subinterval with an
% initial guess so that H is close enough to zero or we get one
% of the two error messages above and the program stops.
end %% this complete the loop for a single subinterval
end %% all the subintervals in [0, upperS] have been examined
%% if you made it up to this point without exit the function, it means that you never
found
%% a candidate solution
display ('Warning: t did not get close enough to 1: increase upperS or refine stepsize
for t')
Download