Sunday, November 16, 2008

M - Files: III


Debugging

There are three ways of debugging a user-defined function:

1. Brute Force 1: Break the whole function into its (logical) parts and examine what happens as you change inputs and go through a set of commands one by one. May be just copy and paste the sequence of instructions on the command window and what happens to the values of the variables created / modified within the function. It's equivalent to writing the function as a script or breaking it down to smaller scripts.

2. Brute Force 2: Just remove the semicolon at the end of all commands in the function. This will print on the command screen anything or everything that your function does to the variables defined / created within its body. It can potentially, however, result in a very cluttered command window making it difficult to figure out where the program is going wrong (especially when the number of commands is large and you are working with empirical data).

3. Use keyboard & return: Use of the command keyboard within an M-file interrupts the execution of the function and transfers control to the user. In that case, the command prompt symbol is changed to 'K>>'. One can examine or change variables (all MATLAB commands remain valid). To terminate the keyboard mode use the command return.

A related command is pause. You have to enable it first though (use pause on). When an M-file encounters pause it halts execution temporarily until the user presses any key. This can also be a useful debugging tool - or may be just to see after a set of steps if your function is doing what it is supposed to do.

Requesting User Input

It's often needed (or efficient or just plain simple useful) to be able to ask user for inputs (as to whether to continue beyond a point or what values to give to any of the variables or where to read the data from or what name to use to save a variable or the workspace etc etc). The syntax is:

>> user_entry = input('prompt')

A couple of useful extensions include:

>> user_entry = input('prompt', 's')

% In this case the user_entry is taken as a string (even if the user input is numeric)

>> user_entry = input('prompt\n')

% In this case the user_entry input is taken on the 'next line'. Try yourself to see the difference.

An Example

1. Solving the equation f (x) = exp (- x) - sin (x)

function [x, n] = newton1(x0, tol, maxit)

% Using the Newton’s method for solving the equation:
% f (x) = exp (-x) - sin (x)

x = x0; n = 0; done = 0;

while ~done
n = n + 1;
x_new = x -(exp(-x) - sin(x)) / (-exp(-x) - cos(x));
done = (n >= maxit) ( lt (abs(x_new - x), tol);
x = x_new;
end

2. The command feval

The command feval executes the function at pre-specified (argument) values.

For example say you have a function called myfun which takes a single argument 'x'. Then

>> feval('myfun', x0)

evaluates myfun(x) at value x0.

See help feval for more details.

3. Let our myfun be a function that evaluates the function and also calculates the first derivative as in newton1 above:

function [fx, fx_prime] = myfun(x)

% Evaluate f (x) = exp (x) - sin(x) and its first derivative

fx = exp (-x) - sin (x);
fx_prime = - exp (- x) - cos (x);

4. Now let's use myfun(x) and feval together to modify the newton1 function above.

(This also illustrates that you can use a custom function created as an M-file (in this case myfun(x)) inside another custom function (in this case newton2). It's not only more efficient and neater that way, it also makes for easier debugging. And of course, it also illustrates the use of feval)

function [x, n] = newton2 (fname, x0, tol, maxit)

% Using the Newton’s method for solving the equation/function given by fname
% function fname to be entered as a string
% For example if the function name fname, is myfun, it should be entered as 'myfun'

x = x0; n = 0; done = 0;

while ~done
n = n + 1;
[fx, fx_prime] = feval ('myfun', x);
x_new = x – fx / fx_prime;
done = (n > maxit) ( lt (abs(x_new - x), tol);
x = x_new;
end

Note that this now becomes a general function for solving any equation by Newton's method - of course, as long as the function fname is appropriately created. To the extent possible, this is how you should try to create your own functions. Divide the whole into logically sensible parts, and make them as general as possible.

Saturday, November 15, 2008

M - Files: II


More on Functions

In general, all functions have the form:

function [output1, output2, ...] = myFunctionName(input1, input2, ...)

where output1 refers to the first output, input1 refers to the first input etc.

Any comment lines immediately below the function definition till the first command in the body of the function appear when the help myFunctionName command is used. Try it with the function we created (help maxVal).

nargin & nargout

MATLAB is quite flexible when it comes to specifying inputs and outputs. The function nargin returns the number of input arguments (nargin = number of arguments in) supplied and nargout returns the number of outputs requested (nargout = number of arguments out). 

Inside the body of functions nargin and nargout return the number of input arguments that were used to call the function. As an illustration, say you write a function that iterates until a convergence criteria is met or a maximum number of iterations has been reached. One way to write such a function is to make the convergence criteria and the maximum number of iterations be optional arguments:

function x = SolveIt(a,tol,MaxIters)

if ( lt(nargin, 3) )
MaxIters = 100; 
end

if ( lt(nargin, 2) )
tol = sqrt(eps); 
end

...

NB: the reason I have had to use 'lt' (syntax for 'less than') instead of the symbol '<', is because of blogger. '<' when used within parentheses, seems to ignore any number after '<'. In practice there is no difference. You may use either.

The command 'nargout' works similarly. An example would be:

function [x_sort,x_mean,x_med,x_std] = myMarks(x) 

x_sort = sort(x); 
if nargout > 1, x_mean = mean(x); end 
if nargout > 2, x_med = median(x); end 
if nargout > 3, x_std = std(x); end 

Outside the body of the function (or in command window), the functions nargin and nargout work differently. nargin('fun') and nargout('fun') respectively return the number of declared inputs and outputs for the function 'fun'. For example, in the example discussed previously nargin('maxVal') returns 1 and nargout('maxVal') returns 3. 

varargin & varargout

To specify a variable (not fixed in advance) number of inputs to and outputs from a function argument one can use varargin (variable arguments in) and varargout (variable arguments out). To illustrate, here is an example taken from the Mathworks site:

function vartest(argA, argB, varargin)

optargin = size(varargin,2);
stdargin = nargin - optargin;
fprintf('Number of inputs = %d\n', nargin)
fprintf('Inputs from individual arguments(%d):\n', stdargin)

if stdargin >= 1
fprintf('%d\n', argA)
end

if stdargin == 2
fprintf('%d\n', argB)
end

fprintf('Inputs packaged in varargin(%d):\n', optargin)

for k = 1 : size(varargin, 2) 
fprintf('%d\n', varargin{k})
end

A few points about varargin (& varargout): 

The varargin (varargout) statement is used only inside a function M-file to contain optional input (output) arguments passed to the function. The varargin (varargout) argument must be declared as the last input (output) argument to a function, collecting all the inputs (outputs) from that point onwards. In the declaration, varargin (varargout) must be lowercase.

Here is an example on varargout, again taken from the Mathworks site:

function [s, varargout] = mysize(x)

nout = max(nargout, 1) - 1;
s = size(x);
for k = 1 : nout, varargout(k) = {s(k)}; end

returns the size vector and, optionally, individual sizes.  So

>> [s, rows, cols] = mysize(rand(4,5));

returns s = [4 5], rows = 4, cols = 5

And finally, though I may have mentioned it earlier, name of the M-file takes precedence over the name used in the function definition. That is, a user-defined function is called by the name of the M-file, and not the name given in the function definition. In general, it is always advisable to keep them the same. 

M - Files: I


Scripts and Functions

Although a lot can be done by writing instructions / steps on the command window in MATLAB, often one needs to experiment with a sequence of commands (for example, to see what change in one of the inputs does to a output - say, call option value on change of volatility or interest rate). Also, it would be very inefficient if every time one has to re-enter a particular sequence of commands in course of a project (an example could be comparing short term movements to a long term average by, say, estimating a rolling moving average). 

All of this, and more, can be achieved by what are called M-files. An M-file is just a text-editor (like a notepad) where one can record/type a set of commands and call from the command line. All M-files have a .m extension (just like a notepad has a .txt extension) and they are of two types:

Script M-files (or scripts): They have no input / output arguments and operate on variables on the existing workspace

Function M-files (or functions): They can accept input arguments and return output arguments. They are differentiated from the scripts in that a function contains an explicit function definition at the top of the M-file ( of the kind function [output] = myFunctionName(input) ). Also, internal variable declared within a function are local to the function (unless declared global). 

Both a script and a function enable one to store a sequence of commands / instructions that one may need frequently. Also, in general M-files are a more efficient and neat way of passing instructions as they help keep the command window uncluttered while one fiddles around with inputs and the sequence of commands. 

As an example, let's say we want a function that can find out the location of the maximum value in a matrix:

function [row, col, val] = maxVal(A)

% maxVal(x)
% Finds the location(s) and value of the maximum entry in a matrix
%
% [row, col, val] = maxVal(A)
%
% 'A' is the input matrix
% 'row' gives the row indices of the maxima (in case not unique)
% 'col' gives the column indices of the minima (in case not unique)
%  'val' gives the maximum value

val = max(max(A));
[row, col] = find(A == val);

In this function there are three output arguments and a single input argument. We'll discuss more on multiple inputs and output later. 

It's always advisable to include comment lines after the function definition. This not only makes sure you remember what you were trying to do when you wrote the function in the first place, it also allows for more effective sharing of codes across users.

To see if a function name or a variable already exists as an existing M-file or a MATLAB built-in function, use the command:

>> exist('functionName')

If the function or file doesn't exist, the above command would give an output 0, else a value between 1 - 8. See help exist for details.

One should also avoid using MATLAB keywords for a function name. To see the list of keywords, use the following command:

>> iskeyword

Scripts vs Functions

Scripts, simply stated are just a set of commands written in an M-file instead of the command window. Commands written in a script works on the variables existing in the workspace. Functions in that sense are different. For one, the same variable names as in the workspace can be used within a function without risking any modification of the existing variables in the workspace. Also, any variables created when the function is running are lost when the function completes. [HT: Kevin Sheppard]

Monday, November 3, 2008

Flow Control - Iteration and Selection


Loops and Conditional Statements

Description of Flow Control ('for - end', 'if - else' loops etc) in MATLAB is something that is best outsourced. There is a fair bit of material on that available already on the web and doubt I can add much that would be too different. Besides, basic idea of looping (iteration or repetition) and 'if-else' (selection) is quite intuitive and would be familiar to most of you. For the uninitiated, here is a good doc with lots of examples.

And, of course, you can also look at Kevin Sheppard's doc. It also has a lot of examples.

Thursday, October 23, 2008