3. Numerical Methods in MATLAB#

DING Minjie, Spring 2025


In this tutorial, we will discuss basics and numerical methods in MATLAB, including:

    1. Preparation for MATLAB

      • Set Working Directory

      • Clear Work

    1. Basic of MATLAB

      • Data Type

      • Logical Operations

      • Define Functions

    1. Graph

    1. Matrix Manipulation and Calculation

    1. Solve Nonlinear Equations/Root Finding

    1. Numerical Optimization

    1. Function Approximation with Interpolation

    1. Discretization

    1. Simulation


1.1 Set Working Directory#

We use “pwd” to get current working directory, and use “cd” to change working directory.

When we work on MATLAB, we can also select working directory by right click with the mouse.

If we use MATLAB as kernel on other platform, these two code instructions are indispensable.

cd"C:\Users\ading\A_TA_Notes"
pwd
ans = 'C:\Users\ading\A_TA_Notes'

1.2 Clear Work#

Before starting the work, we need to clean up the previous work.

clear all;  % Clears all variables from the workspace
close all;  % Closes all open figure windows
clc;        % Clears the Command Window

2.1 Data Type#

Here are three concepts used to store and manipulate data: Variable, Matrix, and Structure.

%% Variable
x = 10;          % Numeric variable
name = 'Alice';  % String variable
name
name = 'Alice'
%% Matrix(Vector)
matrix_y=[1,2,3; 4,5,6] % Create a 2x3 matrix

matrix_y(2,3)           % Access the element in the 2nd row, 3rd column
matrix_y(:,3)           % Access all elements in the 3rd column
matrix_y(2,:)           % Access all elements in the 2nd row

matrix_y(matrix_y>=3)   % Retrieve elements greater than or equal to 3
matrix_y(matrix_y>=3)=0 % Set elements greater than or equal to 3 to 0

matrix_y=zeros(3,2)     % Create a 3x2 matrix filled with zeros
matrix_y=ones(3,2)      % Create a 3x2 matrix filled with ones
matrix_y=NaN(3,2)       % Create a 3x2 matrix filled with NaN (Not a Number)
matrix_y = 2×3 double
     1     2     3
     4     5     6
ans = 6
ans = 2×1 double
     3
     6
ans = 1×3 double
     4     5     6
ans = 4×1 double
     4
     5
     3
     6
matrix_y = 2×3 double
     1     2     0
     0     0     0
matrix_y = 3×2 double
     0     0
     0     0
     0     0
matrix_y = 3×2 double
     1     1
     1     1
     1     1
matrix_y = 3×2 double
   NaN   NaN
   NaN   NaN
   NaN   NaN
%% Structure
person.name = 'Alice';  % Field 'name'
person.age = 30;        % Field 'age'
person.height = 5.5;    % Field 'height'
person
person = 包含以下字段的 struct:
      name: 'Alice'
       age: 30
    height: 5.5000

2.2 Logical Operations#

The following code demonstrates various logical and relational operations in MATLAB.

2 >= 1         % Comparison: Is 2 greater than or equal to 1?
2 < 1          % Comparison: Is 2 less than 1?

1 & 0          % Logical AND operation: 1 & 0
1 | 0          % Logical OR operation: 1 | 0
~ 1            % Logical NOT operation: ~1
~ 0            % Logical NOT operation: ~0
1 ~= 2         % Comparison: Is 1 not equal to 2?
0 | 2          % Logical OR operation with numbers: 0 | 2

[1,2;3,4]>=2 & [1,2;3,4]<4
% Element-wise comparison with logical AND
ans = logical
   1
ans = logical
   0
ans = logical
   0
ans = logical
   1
ans = logical
   0
ans = logical
   1
ans = logical
   1
ans = logical
   1
ans = 2x2 logical 数组
   0   1
   1   0

2.3 Define Your Own Functions#

We can define our own function in three ways:

  1. Use @ operator

  2. Define local function

  3. Define function file outside of current file

Use @ operator#

Define a simple function directly.

f_square_1 = @(x) (x-1)^2;
f_square_1(3)
ans = 4

Define local function#

These are functions defined within a script. They are only accessible from within the file in which they are defined.

Ideal for organizing code within a single file, especially when the local function is only relevant to that file.

function output = f_square_2(x)    
    output = (x - 1)^2;
end

f_square_2(3)
ans = 4

Another example with a parameter.

function [ output ] = f_square_2(x, c)
    output = (x-c)^2;
end

f_square_2(3,1)
ans = 4

Define function file#

This method genreate a separate .m files stored in current working directory.

The filename must match the function name.

In Jupyter, we use “%%file name.m” to generate a separate .m files.

%%file f_square_3.m

function output = f_square_3(x)    
    output = (x - 1)^2;
end
File f_square_3.m created successfully.
f_square_3(3)
ans = 4

3. Graphing#


Here is a simple example.

x_vec=(-2:0.01:2);
y_vec1=(x_vec).^2;
y_vec2=(x_vec-0.5).^2;

figure(1)
plot(x_vec, y_vec1, '-r', x_vec, y_vec2, '--b')     
% solid red line (-r) and dashed blue line (--b)
title('Graph of $y=x^{2}$','Interpreter','latex')
% use LaTeX interpreter for rendering the title text
xlabel('x')
ylabel('y')
legend('y=x^{2}','y=(x-0.5)^{2}') % adds a legend to the plot
xlim([-3, 3]);                    % Set the x-axis range

% saveas(gcf,'figure_1.pdf') 
_images/a82990229d594437e70954c652704ba54f891342fbe1f01acc7525d4d5b0aefc.png

We can also put subplots together.

x_vec=(-1:0.01:1);
y_vec=x_vec.^2;

figure(2)
subplot(2,2,1)
plot(x_vec,y_vec)
title('1st Graph of $y=x^{2}$','Interpreter','latex')
xlabel('x')
ylabel('y')
legend('y=x^{2}')

subplot(2,2,2)
plot(x_vec,y_vec)
title('2nd Graph of $y=x^{2}$','Interpreter','latex')
xlabel('x')
ylabel('y')
legend('y=x^{2}')

subplot(2,2,3)
plot(x_vec,y_vec)
title('3rd Graph of $y=x^{2}$','Interpreter','latex')
xlabel('x')
ylabel('y')
legend('y=x^{2}')

subplot(2,2,4)
plot(x_vec,y_vec)
title('4th Graph of $y=x^{2}$','Interpreter','latex')
xlabel('x')
ylabel('y')
legend('y=x^{2}')
_images/2a324de86a0c7907b1b0f46dd0b98127dd2f026d92e134b5aac57d1e120beafe.png

4. Matrix Manipulation and Calculation#


We need to manipulate matrix. And here are some commonly used instructions.

Function

Purpose

Input Type

Output Type

Use Case

ndgrid

Generates N-dimensional grids

Vectors

Coordinate matrices

Evaluating functions over multi-dimensional grids

kron

Computes Kronecker product

Matrices

Larger matrix

Constructing larger matrices

reshape

Reshapes arrays

Array, new size

Reshaped array

Reorganizing data for processing

permute

Reorders dimensions of an array

Array, new order

Permuted array

Changing orientation of multi-dimensional arrays

ndgrid#

Input: N vectors representing the grid points along each dimension.

Output: N matrices containing the coordinates of the grid points.

Use Case: Useful for evaluating functions over a grid in multiple dimensions, such as surface plots or mesh grids.

a = 1:5;
b = 1:3;
[x, y] = ndgrid(a, b);
x
y
x = 5×3 double
     1     1     1
     2     2     2
     3     3     3
     4     4     4
     5     5     5
y = 5×3 double
     1     2     3
     1     2     3
     1     2     3
     1     2     3
     1     2     3

kron#

Useful for constructing larger matrices from smaller ones, particularly in linear algebra and systems theory.

A = [1 2; 3 4];
B = [0 5; 6 7];
C = kron(A, B);
A
B
C
A = 2×2 double
     1     2
     3     4
B = 2×2 double
     0     5
     6     7
C = 4×4 double
     0     5     0    10
     6     7    12    14
     0    15     0    20
    18    21    24    28

reshape#

Output a new array with the specified dimensions

A = 1:6;                % A = [1 2 3 4 5 6]
B = reshape(A, [2, 3]); % return a matrix with 2 rows and 3 columns
C = reshape(A, 2, 3);   % return a matrix with 2 rows and 3 columns
D = reshape(A, [], 3);  % return a matrix with 3 columns
A
B
C
D
A = 1×6 double
     1     2     3     4     5     6
B = 2×3 double
     1     3     5
     2     4     6
C = 2×3 double
     1     3     5
     2     4     6
D = 2×3 double
     1     3     5
     2     4     6

permute#

rng(100)
A = rand(2, 3, 4);          % A 3D array
B = permute(A, [3, 1, 2]);  
% dimension order change from [1,2,3] to [3,1,2]
% so (2,3,4) change to (4,2,3)
% 2rows*3column*4matrice ==> 4rows*2columns*3matrices
A
B
A = 
A(:,:,1) =

    0.5434    0.4245    0.0047
    0.2784    0.8448    0.1216


A(:,:,2) =

    0.6707    0.1367    0.8913
    0.8259    0.5751    0.2092


A(:,:,3) =

    0.1853    0.2197    0.8117
    0.1084    0.9786    0.1719


A(:,:,4) =

    0.8162    0.4317    0.8176
    0.2741    0.9400    0.3361
B = 
B(:,:,1) =

    0.5434    0.2784
    0.6707    0.8259
    0.1853    0.1084
    0.8162    0.2741


B(:,:,2) =

    0.4245    0.8448
    0.1367    0.5751
    0.2197    0.9786
    0.4317    0.9400


B(:,:,3) =

    0.0047    0.1216
    0.8913    0.2092
    0.8117    0.1719
    0.8176    0.3361

spdiags#

The spdiags function in MATLAB is used to create a sparse matrix from the diagonals specified in a given matrix.

This is particularly useful when dealing with large matrices that are mostly sparse, as it allows for efficient storage and manipulation.

One of the basic syntax is:

S = spdiags(Bin, d, m, n)

where:

Bin: A matrix where each column represents a diagonal of the resulting sparse matrix.
d: A vector specifying the locations of the diagonals. For example, 0 refers to the main diagonal, 1 refers to the first upper diagonal, -1 refers to the first lower diagonal, and so forth.
m: The number of rows in the resulting sparse matrix.
n: The number of columns in the resulting sparse matrix.
% Define the diagonals
Bin = [1 2 3;   % Main diagonal
       4 5 6;   % Upper diagonal
       7 8 9];  % Lower diagonal
Bin = Bin';

% Define the diagonal positions
d = [0, 1, -1]; % Main, Upper, and Lower

% Define the size of the sparse matrix
m = 3; % Number of rows
n = 3; % Number of columns

% Create the sparse matrix
S = spdiags(Bin, d, m, n);

% Display the sparse matrix
full(S)  % Convert to full matrix for display
ans = 3×3 double
     1     5     0
     7     2     6
     0     8     3

The main diagonal (0) contains values [1, 2, 3].

The first upper diagonal (1) contains values [4, 5].

The first lower diagonal (-1) contains values [7, 8].

This results in a sparse matrix where only the specified diagonals are filled, making it memory efficient for large matrices.

%% Change diagonal position

Bin = [1 2 3;   % Main diagonal
       4 5 6;   % Upper diagonal
       7 8 9];  % Lower diagonal
Bin = Bin';

% Define the diagonal positions
d = [0, 1]; % Main, Upper, and Lower

% Define the size of the sparse matrix
m = 3; % Number of rows
n = 3; % Number of columns

% Create the sparse matrix
S = spdiags(Bin, d, m, n);

% Display the sparse matrix
full(S)  % Convert to full matrix for display
ans = 3×3 double
     1     5     0
     0     2     6
     0     0     3

speye#

The speye function in MATLAB creates a sparse identity matrix. Sparse matrices are efficient for computations involving large matrices where most of the elements are zero, helping to save memory and speed up calculations.

speye(n) creates an n×n sparse identity matrix.

And identity matrix is a square matrix with ones on the diagonal and zeros elsewhere

% Create a 4x4 sparse identity matrix
n = 4;
I = speye(n);

% Display the matrix
disp(I);
I
   (1,1)        1
   (2,2)        1
   (3,3)        1
   (4,4)        1
I = 4x4 稀疏 double 矩阵 (4 个非零值)
   (1,1)        1
   (2,2)        1
   (3,3)        1
   (4,4)        1

Backslash Operator \ (mldivide) and Division Operator /#

mldivide (Backslash Operator \)

Used to solve linear systems of equations of the form \(Ax = b\), where \(A\) is a matrix and \(b\) is a vector or matrix.

The backslash operator computes \(x = A \backslash b\), solving the equation \(Ax = b\) for \(x\).

Backslash Operator is high recommended for solving linear system. Division Operator is not preferred.

A = [1 2; 3 4];
b = [5; 6];
x = A \ b;  % Solves Ax = b
A
b
x
A = 2×2 double
     1     2
     3     4
b = 2×1 double
     5
     6
x = 2×1 double
   -4.0000
    4.5000

Division Operator /

Used for right division, which computes the solution to the equation \(xA = b\) or equivalently \(x = b / A\).

The division operator computes \(x = b / A\). This is not a direct solution to a linear system but transforms the problem to the left side.

A = [1 2; 3 4];
b = [5 6; 7 8];
x = b / A;  % Solves xA = b
A
b
x
A = 2×2 double
     1     2
     3     4
b = 2×2 double
     5     6
     7     8
x = 2×2 double
   -1.0000    2.0000
   -2.0000    3.0000

diff#

Y = diff(X,n,dim) is the nth difference calculated along the dimension specified by dim. The dim input is a positive integer scalar.

X = [1 3 5;7 11 13;17 19 23];
Y1 = diff(X,1,1);
Y2 = diff(X,1,2);
X
Y1
Y2
X = 3×3 double
     1     3     5
     7    11    13
    17    19    23
Y1 = 2×3 double
     6     8     8
    10     8    10
Y2 = 3×2 double
     2     2
     4     2
     2     4

repmat#

repmat is a function in MATLAB that stands for “repeat matrix.” It is used to replicate and tile an array (matrix) a specified number of times along each dimension

A = diag([100 200 300])
B = repmat(A,2,3)
A = 3×3 double
   100     0     0
     0   200     0
     0     0   300
B = 6×9 double
   100     0     0   100     0     0   100     0     0
     0   200     0     0   200     0     0   200     0
     0     0   300     0     0   300     0     0   300
   100     0     0   100     0     0   100     0     0
     0   200     0     0   200     0     0   200     0
     0     0   300     0     0   300     0     0   300

5. Solve Nonlinear Equations#


fsolve#

fsolve is used to solve systems of nonlinear equations. It can handle multiple variables.

The basicsyntaxr is:

x = fsolve(fun,x0,options)

[x,fval] = fsolve(___)

It means: solve nonlinear equation fun=0, start from x=x0.

x is solution. fval is value of function.

f=@(x) x^2;

x0=0.5;                                % Initial Guess;
[x_zero_1, fval_1] = fsolve(f,x0);     % Finding the Root
x_zero_1                               % Show the result
fval_1                                 % Show the result

options = optimset('Tolfun',1e-8);     % Setting Options for fsolve
% The option Tolfun specifies the tolerance to 1e-8.
x_zero_2 = fsolve(f,x0,options);       % Finding the Root
x_zero_2                               % Get a more precise result  
方程已解。

fsolve 已完成,因为按照函数容差的值衡量,
函数值向量接近于零,并且按照梯度的值衡量,
问题似乎为正则问题。
x_zero_1 = 0.0078
fval_1 = 6.1035e-05
方程已解。

fsolve 已完成,因为按照函数容差的值衡量,
函数值向量接近于零,并且按照梯度的值衡量,
问题似乎为正则问题。
x_zero_2 = 9.7657e-04

And an example of system of equations.

F = @(x) [x(1)^2 + x(2)^2 - 8; x(1) - x(2)]; % System of equations
initial_guess = [1; 1];
solution = fsolve(F, initial_guess);         % Solving the system
solution                                     % Show result
方程已解。

fsolve 已完成,因为按照函数容差的值衡量,
函数值向量接近于零,并且按照梯度的值衡量,
问题似乎为正则问题。
solution = 2×1 double
    2.0000
    2.0000

fzero#

fzero is similar to fsolve, but it is used specifically for finding roots of single-variable functions.

Another key difference is that fzero is suitable for functions that are continuous and have a sign changeie signs).

Here is an example where fzero fails, since there is no sign change.

f=@(x) x^2;
x0=0.5;   
x_zero_3 = fzero(f,x0);
x_zero_3
正在退出 fzero: 将中止搜索包含符号变化的区间
 因为在搜索期间遇到 NaN 或 Inf 函数值。
(-1.7162e+154 处的函数值为 Inf。)
请检查函数或使用其他起始值重试。
x_zero_3 = NaN

While fsolve works in this case.

f=@(x) x^2;
x0=0.5;   
x_zero_3 = fsolve(f,x0);
x_zero_3
方程已解。

fsolve 已完成,因为按照函数容差的值衡量,
函数值向量接近于零,并且按照梯度的值衡量,
问题似乎为正则问题。
x_zero_3 = 0.0078

fzero works if there is sign change.

f2=@(x) x^3;
x0 = [-0.5 0.5]              % set initial guess a interval 
% x0=0.5;                    % we can also guess a value
x_zero_4 = fzero(f2,x0);
x_zero_4

f3=@(x) x^2-1;
x0=0.5;   
x_zero_5 = fzero(f3,x0);
x_zero_5
x0 = 1×2 double
   -0.5000    0.5000
x_zero_4 = 0
x_zero_5 = 1

When to Use fzero Over fsolve?

Use fzero when:

You are dealing with a single-variable nonlinear equato n.

You want faster performance for simple root-finding a sks.

You can easily identify an interval where the function changes sign. ign.

bisection and golden section#

The bisection method and the golden section search are both used for finding roots of functions, particularly when the function is unimodal (has a single peak or trough) within a specified interval.

There is no direct built-in function for the bisection nor golden section method.

There are two possible solution.

First, we write function files. Many professors provide their version, and we can use them.

Second, some built-in functions based on idea of bisection and golden section. We can use them as a close substitute. 

For example, "fzero" algorithm, created by T. Dekker, uses a combination of bisection, secant, and inverse quadratic interpolation methods.

6. Numerical Optimization#


Some commonly used optimization methods include:

fminunc

Purpose: finds the unconstrained local mininum of a function.
Usage: suitable for unconstrained optimization problems.

fminsearch

Purpose: finds the unconstrained local mininum of a function.
Usage: suitable for unconstrained optimization problems without the need for gradient information.

fminbnd

Purpose: finds the unconstrained local minimum of a single-variable function within a specified interval. 
Usage: Ideal for simple optimization problems where the function is one-dimensional and bounded.

fmincon

Purpose: finds the minimum of a constrained nonlinear multivariable function.
Usage: suitable for optimization problems with constraints, both equality and inequality.

When we solve maximum A problem, that is to find the minimum of negative A.

max#

The max function in MATLAB is used to find the maximum value in an array or between two arrays. It can operate on vectors, matrices, or multi-dimensional arrays

The basic syntax is:

[M,I] = max(___)

It returns the index into the operating dimension that corresponds to the first occurrence of the maximum value of A.

A = [3, 5, 2, 9, 9, 1];  % Define a vector
[M, I] = max(A);         % Find the maximum value and its index
disp(M);                 % Display the maximum value
disp(I);                 % Display the index of the first occurrence
     9

     4

fminunc#

The basic syntax is:

x = fminunc(fun,x0,options)
[x,fval] = fminunc(___)

which means find minimum of fun, start from x0,

and get solution x and value fval

% fminunc
f = @(x) x^2;                       % Objective function
x0 = 2;                             % Initial guess
[x_min_1 f_min_1] = fminunc(f,x0);
x_min_1 
f_min_1
找到局部最小值。

优化已完成,因为梯度大小小于
最优性容差的值。
x_min_1 = 0
f_min_1 = 0
% fminunc
f = @(x) (x(1)-1)^2 + (x(2)-2)^2; % Objective function
x0 = [0, 0];                      % Initial guess
[x, fval] = fminunc(f, x0);
x
fval
找到局部最小值。

优化已完成,因为梯度大小小于
最优性容差的值。
x = 1×2 double
    1.0000    2.0000
fval = 4.4409e-16

fminsearch#

The basic syntax is:

x = fminsearch(fun,x0,options)
[x,fval] = fminsearch(___)
% fminsearch
f = @(x) (x(1)-1)^2 + (x(2)-2)^2; % Objective function
x0 = [0, 0];                      % Initial guess
[x, fval] = fminsearch(f, x0);
x
fval
x = 1×2 double
    1.0000    2.0000
fval = 1.8692e-09

fminbnd#

The basic syntax is:

x = fminbnd(fun,x1,x2,options)
[x,fval] = fminbnd(___)
% Find the point of the minimum value of the 
% function sin(x) in the range 0<x<2π

fun = @sin;
x1 = 0;
x2 = 2*pi;
[x,fval] = fminbnd(fun,x1,x2);
x               % x = 3/2*pi
fval            % fval = -1
x = 4.7124
fval = -1.0000

fmincon#

The basic syntax is:

x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub,nonlcon,options)
[x,fval] = fmincon(___)

where:

A, b: linear inequality constraints
Aeq, beq: linear equality constraints
lb, ub: lower bounds and upper bounds

We want to minimize the following objective function:

\[ f(\mathbf{x}) = (x_1 - 1)^2 + (x_2 - 2)^2 \]

where $\mathbf{x} = \begin{bmatrix} x_1 \ x_2 \end{bmatriraints

The optimization is subject to the following constraints:

  1. Inequality Constraint: $\( x_1 + x_2 \leq 2 \)$

  2. Equality Constraint: $\( x_1 - x_2 = 0 \)$

There are no specific bounds for the variables:

\[ -\infty < x_1, x_2 < \infty \]
f = @(x) (x(1)-1)^2 + (x(2)-2)^2;  % Objective function
x0 = [0, 0];                       % Initial guess

% Inequality constraints: x1 + x2 <= 2
A = [1, 1];                        % Coefficients for the inequality
b = 2;                             % Right-hand side of the inequality

% Equality constraints: x1 - x2 = 0
Aeq = [1, -1];                     % Coefficients for the equality
beq = 0;                           % Right-hand side of the equality

% Lower bounds
lb = [-Inf, -Inf]; % No lower bounds

% Upper bounds
ub = [Inf, Inf];   % No upper bounds

% Call fmincon
[x, fval] = fmincon(f, x0, A, b, Aeq, beq, lb, ub);

% Display results
disp('Optimal solution:');
disp(x);
disp('Objective function value at optimal solution:');
disp(fval);
找到满足约束的局部最小值。

优化已完成,因为目标函数沿
可行方向在最优性容差值范围内呈现非递减,
并且在约束容差值范围内满足约束。

Optimal solution:
    1.0000    1.0000

Objective function value at optimal solution:
    1.0000

7. Function Approximation with Interpolation#


interp1#

interp1 is a function used for one-dimensional interpolation of data points.

It allows us to estimate the values of a function at specific query points based on known data points.

This is particularly useful in scenarios when you want to estimate values between known data points.

The basic syntax is:

vq = interp1(x, v, xq, method)

Where:

x is a vector of known n x-coordinates (the __points__ at which the values are know).
v is a vector of known __values__ corresponding to the x coordinates.
xq is a vector of query __points__ where you want to evaluate the interpolated values.
vq is the output vector containing the interpolated __values__ at the query points.

interp1 supports various interpolation methods:

'linear': Linear interpolation (default).
'nearest': Nearest neighbor interpolation.
'spline': Cubic spline interpolation.
'pchip': Piecewise cubic Hermite interpolating polynomial.
'cubic': Cubic interpolation. 
% 1. Sine Function
x = -5 : 1 : 5;                         % Known data points
v = sin(x);                            % Known data values  
xq = -5 : 0.01 : 5;                     % Query points

% Different methods of interpolation
vq_lin = interp1(x,v,xq,'linear');
vq_cubic = interp1(x,v,xq,'pchip');
vq_nearest = interp1(x,v,xq,'nearest');

% True solution
vq_true = sin(xq);

% Plot results
figure(1)
plot(xq,vq_true,xq,vq_lin,xq,vq_cubic,xq,vq_nearest)
legend('sin x','linear','cubic','nearest')
_images/278cefd41d6e2bf582126145254fb22aa859033dc69c380b292f03966d3b1bdc.png

With a finer grid, we get better result.

% 2. Sine Function with a finer grid
x1 = -5 : 0.5 : 5;                            % Known data points
y1 = sin(x1);                                 % Known data values
xint = -5 : 0.01 : 5;                         % Query points

% Repeating interpolation with the finer grid
yint_lin = interp1(x1,y1,xint,'linear');
yint_cubic = interp1(x1,y1,xint,'pchip');
yint_nearest = interp1(x1,y1,xint,'nearest');

% Exact solution
yint_sol = sin(xint);

% Plot results
figure(2)
plot(xint,yint_sol,xint,yint_lin,xint,yint_cubic,xint,yint_nearest)
legend('sin x','linear','cubic','nearest')
_images/5364b43720a0e27e1de0b8493e17e636ec8c50ac456f0e3b559a00d4348df7b6.png

griddedInterpolant#

griddedInterpolant is used for n-dimensional interpolation on a grid.

Compared with interp1, griddedInterpolant has two main differences.

It can create a object, so is more flexible. 
It can handle multi-dimensional data.

Feature

interp1

griddedInterpolant

Dimensionality

One-dimensional

N-dimensional

Input Structure

Two vectors (x, y)

Grid vectors and grid data

Flexibility

Less flexible for repeated use

More flexible, allows multiple evaluations

Methods

Limited to specified methods

Multiple methods including extrapolation

Usage

Simple function call

Creates an object for interpolation

[x,y] = ndgrid(-5:0.8:5);               
% generates a grid of points in N-dimensional space
z = sin(x.^2 + y.^2) ./ (x.^2 + y.^2);
surf(x,y,z)                             
% creates a 3D surface plot
_images/de85d701eac793d1215d87e01b24c21c362777ee01f1058fe0b95d968a7c7808.png
F = griddedInterpolant(x,y,z);  
% creates an interpolant object F from the input data x, y, and z
[xq,yq] = ndgrid(-5:0.4:5);    
% creates a new grid of points for querying the interpolant
vq = F(xq,yq);    
% uses the interpolant object F to compute interpolated values 
surf(xq,yq,vq)    
% creates a 3D surface plot 
_images/83d9f22975b58e43d419477d5b113297b7b331f918bce1964fb94275e62028d3.png

From the example above, we can find that one distinction of griddedInterpolant is that, it creates an object, the “F” in example above.

So, people may prefer griddedInterpolant over interp1 even in 1-dimension case, due to its object characteristic.


8. Discretization#


8.1 Markov Chain Approximation of Continuous Stochastic Process#

The Rouwenhorst and Tauchen methods are both techniques to approximate continuous stochastic processes, particularly for Markov processes

Feature

Rouwenhorst Method

Tauchen Method

Origin

Rouwenhorst (1995)

Tauchen (1986)

Focus

highly persistent processes (\(\rho\) > 0.9)

Primarily AR(1) processes

Here is a rouwenhorst example provided by professor Benjamin Moll.

%%file rouwenhorst.m

function [grid, trans, dist] = rouwenhorst(n, mu, sigma, rho)

    % Inputs:
    % n: Number of discrete states.
    % mu: Mean of the underlying continuous process.
    % sigma: Standard deviation of the underlying continuous process.
    % rho: Autocorrelation coefficient of the process.
    
    % Outputs:
    % grid: A vector containing the discrete points.
    % trans: The transition matrix that describes the probabilities of moving between states.
    % dist: The ergodic distribution of the Markov chain.

    % grid
    width = sqrt((n-1) * sigma^2 / ( 1 - rho^2));
    grid = linspace( mu-width, mu + width, n)';
    
    %transition matrix
    p0 = (1 + rho) / 2;
    trans = [p0 1-p0; 1-p0 p0];
    
    if n > 2
        for i = 1:n-2
            cstr_temp = zeros(length(trans(:,1)), 1);
            trans = p0 .* [trans cstr_temp; cstr_temp.' 0] + (1 - p0 ) .* [cstr_temp trans; cstr_temp.' 0]  + (1 - p0 ) .*  [ cstr_temp.' 0; trans cstr_temp] + p0 .* [ cstr_temp.' 0; cstr_temp trans];
        end
        trans = bsxfun(@rdivide, trans, sum(trans,2));
    end
    
    % ergodic distribution
    dist = ones(1,n)./n;
    for i = 1: 100
        dist = dist*(trans^i);
    end
    dist = dist';
end
File rouwenhorst.m created successfully.
n = 3;
mu = 0;
sigma = 1;
rho = 0.9;
[grid, trans, dist] = rouwenhorst(n, mu, sigma, rho)
grid = 3×1 double
   -3.2444
         0
    3.2444
trans = 3×3 double
    0.9025    0.0950    0.0025
    0.0475    0.9050    0.0475
    0.0025    0.0950    0.9025
dist = 3×1 double
    0.2500
    0.5000
    0.2500

8.2 Discrete normal distribution#

Sometimes, we need to approximates a normal distribution using discrete points. Here is a function written by Professor Greg Kaplan. The function computes the probabilities for discrete points, and calculates the expected value and standard deviation.

This can be useful where a continuous distribution needs to be handled in a discrete manner

%%file discrete_normal.m

function [f,x,p] = discrete_normal(n,mu,sigma,width)
% creates equally spaced approximation to normal distribution
% n is number of points
% mu is mean
% sigma is standard deviation
% width is the multiple of stand deviation for the width of the grid
% f is the error in the approximation
% x gives the location of the points
% p is probabilities

x = linspace(mu-width*sigma,mu+width*sigma,n)';

if n==2
    p = 0.5.*ones(n,1);
elseif n>2    
    p  = zeros(n,1);
    p(1) = normcdf(x(1) + 0.5*(x(2)-x(1)),mu,sigma);
    for i = 2:n-1
        p(i) = normcdf(x(i) + 0.5*(x(i+1)-x(i)),mu,sigma) - normcdf(x(i) - 0.5*(x(i)-x(i-1)),mu,sigma);
    end
    p(n) = 1 - sum(p(1:n-1));
end

Ex = x'*p;
SDx = sqrt((x'.^2)*p - Ex.^2);

f = SDx-sigma;
File discrete_normal.m created successfully.
n = 9; 
mu = 0;
sigma = 2;
width = 5;
[f,x,p] = discrete_normal(n,mu,sigma,width)
f = 0.1262
x = 9×1 double
  -10.0000
   -7.5000
   -5.0000
   -2.5000
         0
    2.5000
    5.0000
    7.5000
   10.0000
p = 9×1 double
    0.0000
    0.0009
    0.0295
    0.2356
    0.4680
    0.2356
    0.0295
    0.0009
    0.0000

9. Simulation#


9.1 Random Number Generation#

By setting a specific seed value (in this case, 100), we ensure that the sequence of random numbers generated is the same every time we run the code..

rng(100)   % Set a random seed

“rand” generates uniformly distributed random numbers in the interval (0, 1).

The basic syntax is

rand generates a single random number
rand(n) generates an n×n matrix of random numbers.
rand(m, n) generates an m×n matrix of random numbers.
r1 = rand;           % Single random number
r2 = rand(3);       % 3x3 matrix of random numbers
r3 = rand(2, 4);    % 2x4 matrix of random numbers
r1
r2
r3
r1 = 0.5434
r2 = 3×3 double
    0.2784    0.0047    0.8259
    0.4245    0.1216    0.1367
    0.8448    0.6707    0.5751
r3 = 2×4 double
    0.8913    0.1853    0.2197    0.8117
    0.2092    0.1084    0.9786    0.1719

“random” is a more general function that generates random numbers from various probability distributions, such as normal, binomial, Poisson, etc.

The syntax depends on the distribution you want to use. For example:

random('Normal', mu, sigma, m, n) 

generates an m×n matrix of random numbers from a normal distribution with mean mu and standard deviation sigma.

Generate a 3 by 2 matrix of random number.

rng(100)                              % Set a random seed
m = 3;                                % Number of rows
n = 2;                                % Number of columns

Matrix_Normal = random('Normal',0,1,m,n); 
Matrix_Normal
% generates a 3x2 matrix named Matrix_Normal filled with random numbers 
% drawn from a normal distribution.
% 0: The mean of the normal distribution.
% 1: The standard deviation of the normal distribution.

Matrix_Uniform = random('Uniform',0,1,m,n);
Matrix_Uniform
% generates a 3x2 matrix named Matrix_Uniform filled with random numbers 
% drawn from a uniform distribution.
% 0: The lower bound of the uniform distribution.
% 1: The upper bound of the uniform distribution.
Matrix_Normal = 3×2 double
    0.1609    0.6150
   -0.6151   -0.9014
   -0.2390    0.3481
Matrix_Uniform = 3×2 double
    0.8259    0.8913
    0.1367    0.2092
    0.5751    0.1853

Generate a 2 by 1 joint normal random vector with mean mu and variance omega.a

rng(100);   
mu = [2;-1];                          % Define the mean vector
omega = [2,3;3,5];                    % Define the covariance matrix
P = chol(omega)';                     % Perform Cholesky decomposition
B1 = P*random('Normal',0,1,2,1) + mu; % Generate a joint normal random vector
B1
B1 = 2×1 double
    2.2276
   -1.0935

Or, we can use the “mvnrnd” function to achieve the same result

rng(100); 
B2 = mvnrnd(mu,omega,1)';
B2
B2 = 2×1 double
    2.2276
   -1.0935

Generate a uniform distributed random number on interval [a,b]

a=1;
b=2;
C1 = random('Uniform',0,1)*(b-a) + a;

Here is another way, which is pretty similar.

C2 = random('Uniform',a,b);

10. Reference#


  1. MATLAB Help Center, https://ww2.mathworks.cn/help/matlab/index.html.