Sunday, October 19, 2008

Inf, Nan; Relational & Logical Operators and Find


These are some last set of expressions/operators that we need to familiarize ourselves with before we get to the discussion of programming and the use of M-files in MATLAB

Inf, Nan and eps

Infinity (+ or -) in MATLAB is represented by inf. This may happen more often you can think (for example, when there is stagnant data for a variable or there are data repetitions, some samples may show a zero variance, which in turn can result in 1/0 situations when you are finding correlations. 

Contrary to inf, NaN are 'quantities' which MATLAB throws up when a result is neither a number or infinity (e.g. an inf / inf situation). From my experience, NaN is most useful in pre-allocation, when you do not know the exact size of a matrix, but have some idea of the maximum. More on this later when we discuss pre-allocation and vectorization. 

Like all numeic software, MATLAB too has limits to how big/small numbers it can deal with.In MATLAB numbers larger than 1.7977e+308 (realmax) are taken to be Inf, and numbers smaller than 2.2251e-308 (realmin) are taken to be -Inf. 

A related expressiion is eps - which, to quote MATLAB help, represents floating point relative accuracy. It is roughly equal to 2 ^ (-52), but may depend on the CPU and the OS used (my desktop gives 2.2204e-016). Any quantity less than eps is taken to be same as zero. The reason it's called relative accuracy can be best explained by an example (taken from Kevin's notes):

>> x = 1; 

>> x = x + eps/2;

% gives x = 1 (because eps/2 is less than eps)

>> x = x - 1

% so it gives 0

Now let's change x = 1 to x = 2.1, and do the same steps again. and you get

>> x

  4.4409e-016

The reason (or may be it would be better to use the word 'explanation'), is that while:

eps/1 > eps/2

eps/2.1 <  eps/2

To expland on this, let's write x + eps/2 

as 

x * (1 + eps/2*x)

Now only if eps/2*x  >  eps, the expression is evaluated as the finite (non-zero) number it is, otherwise it's taken to be zero.

A mere technical detail it may seem right now, but when one is dealing with big (or very small) numbers and doing extensive calculations, failure to understand the role of precision can result in errors and blow-ups.

Relational Operators

The order / comparison operators in MATLAB work the way do in maths. The obvious ones are:

= (equal; eq), 
~= (not equal; ne), 
> (greater than; gt)
< (less than; lt)
>= (greater than or equa to; ge),
<= (less than or equal to; le)

When the comparison is made between two scalars their use is obvious. When it's between a scalar and a matrix, each element of the matrix is compared against the scalar. Two matrices can be compared only when they have the same dimesion, and in that case the comparison is always between apples and apples and never between apples and oranges. Or, in a less flowery (fruity?) language, x(i, j) is compared against y(i, j), where i and j refers to the same row and column indices respectively. 

The use of relational operators is almost always in control loops (if-else, for-end etc.) to check whether a condition is satisfied (or not) and what to do if the condition is satisfied (and what if it's not). 

Logical Operators

& (and), | (or) and ~ (not) are the well known Boolean operators and they work as they do in basic Boolean algebra. Their use is exactly like the relational operators discussed above. Very often they are used in conjunction with the relational operators, if (a <> d) etc etc.

Now we discuss some 'commands in logic' - i.e. the MATLAB commands that work in the sense of logical operations. The most important ones are:

1. logical: is used to convert non-logical (numbers) to logical elements. Logical numbers can be thought of as switches which are either on (1) or off (0).  Also, they can be used to work like indicator functions. Let:

>> x = [1 2 3 4];
>> y = [1 1];

then, x(y) = [x(1) x(1)]

but x(logical(y)) = [x(1) x(2)]

because, although logical(y) returns [1 1], but these represents indicators (on or off) for the 'location' (first and second element). 

2. all: takes input as logicals (1 or 0) and returns 1 if all the elements of a row are on, otherwise 0. Result on a matrix is a row vector.

3. any: similar to all, but differs in that it returns 1 if any of the element of a row are on, otherwise 0. 

4. is*: represents a collection of questions that you can ask of an input, whether it is infinite, finite, NaN etc. etc. Output is a logical. The list, inter alia,  includes:

isnan(x): returns 1 for all the elements which are NaN, and 0 at others

isinf(x): returns 1 for all the elements which are Inf, and 0 at others

isfinite(x): returns 1 for all the elements which are not Inf (finite), and 0 at others: 

ischar(x): returns 1 if x is a character array, and 0 otherwise

isempty(x): returns 1 if x is an empty matrix, and 0 otherwise

isequal(x, y): returns 1 if all the elements of x and y are equal, and 0 otherwise (x and y must be of same size)

islogical(x): returns 1 if x is logical and 0 otherwise

isscalar(x): returns 1 if x is a scalar, and 0 otherwise

isvector(x): returns 1 if x is a vector and 0 otherwise

[NB: isnan(x) + isinf(x) + isfinite(x) always equals 1. Why?] 

There are other variants of is* too. Look for help on is* for more. 

Find

The find command is so useful it deserves special mention. Although it is not one of the logical commands itself, it takes logical inputs and returns matrix indices where the logical statement is true [ack: Kevin Sheppard]. For example:

[i, j] = find( x <  y ) returns indices (row and column index) of x wherever x is less than y. It works for both scalars and matrices in the same way as relational operators do. 

Note that just the command x  <  y returns output which are logical (1 or 0), which then are used by find to get the row and column index. Some more examples:

>> find(a > 5);

>> a(find(a>5)) = 0;

>> ind = (a == 1);

>> b = a(ind);

>> b = a(a == 1);

>> ind = find(a == 1);

>> a(find(a == 1)) = 2;

More on this as we go along. 

Some Useful Functions


Some often used Functions in Computational Finance

Here are some oft-needed functions for Computational Finance. Most are obvious, but still it's good to know what all is available. For a given matrix x of size, say, N X k:

>> length(x)

% gives max(N, k)

>> [n, p] = size(x)

% gives n = N, and p = k

>> n = size(x, 1)

% gives n = N

>> p = size(x, 2)

% gives p = k

i.e. size(x, dimension) returns the length of a particular dimension of the matrix - number of rows (dimension = 1) or number of columns (dimension = 2).

>> sum(x)

% gives the output as a row vector containing sum of each column 

Functions min(x), max(x), mean(x), median(x), std(x), var(x), skewness(x), kurtosis(x) all work similarly and return a row vector containing respectively, the minimum, maximum, mean, median, standard deviation, variance, skewness and kurtosis of each column of the matrix x. Help yourself and see help on each. It'll be time well spent, as you ARE going to need them often.

>> log(x)

% returns the natural logarithm of EACH element in x

Functions sqrt(x), log10(x) (base 10 logarithm), log2(x) (base 2 logarithm) and exp(x) work similarly.

>> cov(x)

% returns the covariance matrix with size k X k. If x is a vector the output is same % as var(x)

Function corrcoef(x) works similary (returning correlation coefficients instead of covariances), only that it has several extensions. See help corrcoef for details. 

>> sort(x)

% sorts each row of the matrix separately in increasing order

>> sortrows(x, col)

% sorts the matrix as a group w.r.t to the column given by col. equivalent to 'sort
% by-column ...' in Excel

>> unique(x)

% sorts all the elements of a matrix in ascending order, and returns the unique 
% entries as a column 

There are other "set-theoretic" functions (e.g. union) which work like unique does, but they aren't probably as useful as unique for the purpose at hand. See help unique for examples.

>> diag(x)

% returns vector of diagonal elements if x is a matrix, 
% else if x is a vector, it returns a square matrix with elements of the vector as 
% diagonal entries and zero elsewhere

Some other often used Functions

1. linspace(x1, x2, N): returns a row vector starting with x1, ending with x2 and having N elements in between, with the common difference between any two elements given by (x2 - x1) / (N - 1)

2. Another use of the colon (:) operator: similar to linspace. used as [x1 : d : x2], where d is the common difference.

3. repmat(x, m, n): stacks copies of a matrix together. m represents the number of copies 'below' (rows), and n represents the number of copies 'side-by-side' (columns). So repmat(x, 3, 2) is equivalent to [x x; x x; x x]

4. reshape(x, m, n): returns a matrix taking elements (column-wise) from x but with changed number of rows (m) and columns (n). product of number of rows and columns of x must be same as the product m*n. The most obvious use of this is to convert a matrix into a row or a column vector, with columns (row) one below (after) the other

These are the main ones I can think of right now. Will add more as I remember them. If any of you stumble across anything useful not included here, please do share.