null  null
MATLAB®
Mathematics
R2015b
How to Contact MathWorks
Latest news:
www.mathworks.com
Sales and services:
www.mathworks.com/sales_and_services
User community:
www.mathworks.com/matlabcentral
Technical support:
www.mathworks.com/support/contact_us
Phone:
508-647-7000
The MathWorks, Inc.
3 Apple Hill Drive
Natick, MA 01760-2098
MATLAB® Mathematics
© COPYRIGHT 1984–2015 by The MathWorks, Inc.
The software described in this document is furnished under a license agreement. The software may be used
or copied only under the terms of the license agreement. No part of this manual may be photocopied or
reproduced in any form without prior written consent from The MathWorks, Inc.
FEDERAL ACQUISITION: This provision applies to all acquisitions of the Program and Documentation
by, for, or through the federal government of the United States. By accepting delivery of the Program
or Documentation, the government hereby agrees that this software or documentation qualifies as
commercial computer software or commercial computer software documentation as such terms are used
or defined in FAR 12.212, DFARS Part 227.72, and DFARS 252.227-7014. Accordingly, the terms and
conditions of this Agreement and only those rights specified in this Agreement, shall pertain to and
govern the use, modification, reproduction, release, performance, display, and disclosure of the Program
and Documentation by the federal government (or other entity acquiring for or through the federal
government) and shall supersede any conflicting contractual terms or conditions. If this License fails
to meet the government's needs or is inconsistent in any respect with federal procurement law, the
government agrees to return the Program and Documentation, unused, to The MathWorks, Inc.
Trademarks
MATLAB and Simulink are registered trademarks of The MathWorks, Inc. See
www.mathworks.com/trademarks for a list of additional trademarks. Other product or brand
names may be trademarks or registered trademarks of their respective holders.
Patents
MathWorks products are protected by one or more U.S. patents. Please see
www.mathworks.com/patents for more information.
Revision History
June 2004
First printing
October 2004
March 2005
June 2005
September 2005
March 2006
September 2006
September 2007
March 2008
October 2008
March 2009
September 2009
March 2010
September 2010
April 2011
September 2011
March 2012
September 2012
March 2013
September 2013
March 2014
October 2014
March 2015
September 2015
Online only
Online only
Second printing
Second printing
Second printing
Second printing
Online only
Online only
Online only
Online only
Online only
Online only
Online only
Online only
Online only
Online only
Online only
Online only
Online only
Online only
Online only
Online only
Online only
New for MATLAB 7.0 (Release 14), formerly
part of Using MATLAB
Revised for MATLAB 7.0.1 (Release 14SP1)
Revised for MATLAB 7.0.4 (Release 14SP2)
Minor revision for MATLAB 7.0.4
Revised for MATLAB 7.1 (Release 14SP3)
Revised for MATLAB 7.2 (Release 2006a)
Revised for MATLAB 7.3 (Release 2006b)
Revised for MATLAB 7.5 (Release 2007b)
Revised for MATLAB 7.6 (Release 2008a)
Revised for MATLAB 7.7 (Release 2008b)
Revised for MATLAB 7.8 (Release 2009a)
Revised for MATLAB 7.9 (Release 2009b)
Revised for MATLAB 7.10 (Release 2010a)
Revised for MATLAB 7.11 (Release 2010b)
Revised for MATLAB 7.12 (Release 2011a)
Revised for MATLAB 7.13 (Release 2011b)
Revised for MATLAB 7.14 (Release 2012a)
Revised for MATLAB 8.0 (Release 2012b)
Revised for MATLAB 8.1 (Release 2013a)
Revised for MATLAB 8.2 (Release 2013b)
Revised for MATLAB 8.3 (Release 2014a)
Revised for MATLAB 8.4 (Release 2014b)
Revised for MATLAB 8.5 (Release 2015a)
Revised for MATLAB 8.6 (Release 2015b)
Contents
1
Matrices and Arrays
Creating and Concatenating Matrices . . . . . . . . . . . . . . . . . .
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Constructing a Simple Matrix . . . . . . . . . . . . . . . . . . . . . . . .
Specialized Matrix Functions . . . . . . . . . . . . . . . . . . . . . . . .
Concatenating Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Matrix Concatenation Functions . . . . . . . . . . . . . . . . . . . . . .
Generating a Numeric Sequence . . . . . . . . . . . . . . . . . . . . . .
1-2
1-2
1-3
1-4
1-6
1-7
1-8
Matrix Indexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Accessing Single Elements . . . . . . . . . . . . . . . . . . . . . . . . .
Linear Indexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Functions That Control Indexing Style . . . . . . . . . . . . . . . .
Assigning to Elements Outside Array Bounds . . . . . . . . . . .
Accessing Multiple Elements . . . . . . . . . . . . . . . . . . . . . . . .
Using Logicals in Array Indexing . . . . . . . . . . . . . . . . . . . .
Single-Colon Indexing with Different Array Types . . . . . . .
Indexing on Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . .
1-11
1-11
1-12
1-12
1-13
1-13
1-16
1-19
1-20
Getting Information About a Matrix . . . . . . . . . . . . . . . . . . .
Dimensions of the Matrix . . . . . . . . . . . . . . . . . . . . . . . . . .
Classes Used in the Matrix . . . . . . . . . . . . . . . . . . . . . . . . .
Data Structures Used in the Matrix . . . . . . . . . . . . . . . . . .
1-21
1-21
1-22
1-23
Resizing and Reshaping Matrices . . . . . . . . . . . . . . . . . . . . .
Expanding the Size of a Matrix . . . . . . . . . . . . . . . . . . . . . .
Diminishing the Size of a Matrix . . . . . . . . . . . . . . . . . . . .
Reshaping a Matrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Preallocating Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1-24
1-24
1-28
1-28
1-30
Shifting and Sorting Matrices . . . . . . . . . . . . . . . . . . . . . . . .
Shift and Sort Functions . . . . . . . . . . . . . . . . . . . . . . . . . . .
Shifting the Location of Matrix Elements . . . . . . . . . . . . . .
1-33
1-33
1-33
v
2
Sorting the Data in Each Column . . . . . . . . . . . . . . . . . . . .
Sorting the Data in Each Row . . . . . . . . . . . . . . . . . . . . . . .
Sorting Row Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1-34
1-35
1-36
Operating on Diagonal Matrices . . . . . . . . . . . . . . . . . . . . . .
Diagonal Matrix Functions . . . . . . . . . . . . . . . . . . . . . . . . .
Constructing a Matrix from a Diagonal Vector . . . . . . . . . .
Returning a Triangular Portion of a Matrix . . . . . . . . . . . .
Concatenating Matrices Diagonally . . . . . . . . . . . . . . . . . . .
1-38
1-38
1-38
1-39
1-39
Empty Matrices, Scalars, and Vectors . . . . . . . . . . . . . . . . . .
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The Empty Matrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Scalars . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1-40
1-40
1-41
1-43
1-44
Full and Sparse Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sparse Matrix Functions . . . . . . . . . . . . . . . . . . . . . . . . . . .
1-45
1-45
1-45
Multidimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Creating Multidimensional Arrays . . . . . . . . . . . . . . . . . . .
Accessing Multidimensional Array Properties . . . . . . . . . . .
Indexing Multidimensional Arrays . . . . . . . . . . . . . . . . . . .
Reshaping Multidimensional Arrays . . . . . . . . . . . . . . . . . .
Permuting Array Dimensions . . . . . . . . . . . . . . . . . . . . . . .
Computing with Multidimensional Arrays . . . . . . . . . . . . . .
Organizing Data in Multidimensional Arrays . . . . . . . . . . .
Multidimensional Cell Arrays . . . . . . . . . . . . . . . . . . . . . . .
Multidimensional Structure Arrays . . . . . . . . . . . . . . . . . . .
1-47
1-47
1-49
1-52
1-52
1-56
1-58
1-60
1-62
1-63
1-64
Summary of Matrix and Array Functions . . . . . . . . . . . . . .
1-66
Linear Algebra
Matrices in the MATLAB Environment . . . . . . . . . . . . . . . . .
Creating Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Adding and Subtracting Matrices . . . . . . . . . . . . . . . . . . . . .
vi
Contents
2-2
2-2
2-3
Vector Products and Transpose . . . . . . . . . . . . . . . . . . . . . . .
Multiplying Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Identity Matrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Kronecker Tensor Product . . . . . . . . . . . . . . . . . . . . . . . . . . .
Vector and Matrix Norms . . . . . . . . . . . . . . . . . . . . . . . . . . .
Using Multithreaded Computation with Linear Algebra
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2-4
2-6
2-8
2-8
2-9
2-10
Systems of Linear Equations . . . . . . . . . . . . . . . . . . . . . . . . .
Computational Considerations . . . . . . . . . . . . . . . . . . . . . .
General Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Square Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Overdetermined Systems . . . . . . . . . . . . . . . . . . . . . . . . . . .
Underdetermined Systems . . . . . . . . . . . . . . . . . . . . . . . . .
Using Multithreaded Computation with Systems of Linear
Equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Iterative Methods for Solving Systems of Linear Equations .
2-11
2-11
2-12
2-13
2-15
2-18
Inverses and Determinants . . . . . . . . . . . . . . . . . . . . . . . . . .
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Pseudoinverses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2-23
2-23
2-24
Factorizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Cholesky Factorization . . . . . . . . . . . . . . . . . . . . . . . . . . . .
LU Factorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
QR Factorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Using Multithreaded Computation for Factorization . . . . . .
2-27
2-27
2-27
2-28
2-30
2-33
Powers and Exponentials . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Positive Integer Powers . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Inverse and Fractional Powers . . . . . . . . . . . . . . . . . . . . . .
Element-by-Element Powers . . . . . . . . . . . . . . . . . . . . . . . .
Exponentials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2-35
2-35
2-35
2-36
2-36
Eigenvalues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Eigenvalue Decomposition . . . . . . . . . . . . . . . . . . . . . . . . . .
Multiple Eigenvalues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Schur Decomposition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2-39
2-39
2-40
2-41
Singular Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2-42
2-20
2-21
vii
3
viii
Contents
Random Numbers
Random Numbers in MATLAB . . . . . . . . . . . . . . . . . . . . . . . . .
3-2
Why Do Random Numbers Repeat After Startup? . . . . . . . . .
3-3
Create Arrays of Random Numbers . . . . . . . . . . . . . . . . . . . .
3-4
Random Numbers Within a Specific Range . . . . . . . . . . . . . .
3-6
Random Integers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3-7
Random Numbers from Normal Distribution with Specific
Mean and Variance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3-8
Random Numbers Within a Sphere . . . . . . . . . . . . . . . . . . . . .
3-9
Generate Random Numbers That Are Repeatable . . . . . . . .
Specify the Seed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Save and Restore the Generator Settings . . . . . . . . . . . . . .
3-11
3-11
3-12
Generate Random Numbers That Are Different . . . . . . . . .
3-15
Managing the Global Stream . . . . . . . . . . . . . . . . . . . . . . . . .
Random Number Data Types . . . . . . . . . . . . . . . . . . . . . . .
3-17
3-21
Creating and Controlling a Random Number Stream . . . . .
Substreams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Choosing a Random Number Generator . . . . . . . . . . . . . . .
3-23
3-24
3-25
Multiple streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3-31
Replace Discouraged Syntaxes of rand and randn . . . . . . .
Description of the Former Syntaxes . . . . . . . . . . . . . . . . . .
Description of Replacement Syntaxes . . . . . . . . . . . . . . . . .
Replacement Syntaxes for Initializing the Generator with an
Integer Seed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Replacement Syntaxes for Initializing the Generator with a
State Vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
If You Are Unable to Upgrade from Former Syntax . . . . . . .
3-34
3-34
3-35
3-35
3-36
3-37
4
5
Sparse Matrices
Computational Advantages of Sparse Matrices . . . . . . . . . . .
Memory Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Computational Efficiency . . . . . . . . . . . . . . . . . . . . . . . . . . .
4-2
4-2
4-3
Constructing Sparse Matrices . . . . . . . . . . . . . . . . . . . . . . . . .
Creating Sparse Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . .
Importing Sparse Matrices . . . . . . . . . . . . . . . . . . . . . . . . . .
4-4
4-4
4-8
Accessing Sparse Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Nonzero Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Indices and Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Indexing in Sparse Matrix Operations . . . . . . . . . . . . . . . .
Visualizing Sparse Matrices . . . . . . . . . . . . . . . . . . . . . . . .
4-9
4-9
4-11
4-11
4-14
Sparse Matrix Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Efficiency of Operations . . . . . . . . . . . . . . . . . . . . . . . . . . .
Permutations and Reordering . . . . . . . . . . . . . . . . . . . . . . .
Factoring Sparse Matrices . . . . . . . . . . . . . . . . . . . . . . . . . .
Systems of Linear Equations . . . . . . . . . . . . . . . . . . . . . . . .
Eigenvalues and Singular Values . . . . . . . . . . . . . . . . . . . .
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4-16
4-16
4-17
4-21
4-29
4-32
4-35
Graph and Network Algorithms
Directed and Undirected Graphs . . . . . . . . . . . . . . . . . . . . . .
What Is a Graph? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Creating Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Graph Node IDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Modify an Existing Graph . . . . . . . . . . . . . . . . . . . . . . . . . . .
5-2
5-2
5-4
5-9
5-9
Modify Nodes and Edges of Existing Graph . . . . . . . . . . . . .
5-11
Add Graph Node Names, Edge Weights, and Other
Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5-15
ix
6
7
x
Contents
Graph Plotting and Customization . . . . . . . . . . . . . . . . . . . .
5-20
Build Watts-Strogatz Small World Graph Model . . . . . . . . .
5-33
Visualize Breadth-First and Depth-First Search . . . . . . . . .
5-42
Use Page Rank Algorithm to Rank Websites . . . . . . . . . . . .
5-46
Functions of One Variable
Create and Evaluate Polynomials . . . . . . . . . . . . . . . . . . . . . .
6-2
Roots of Polynomials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Numeric Roots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Roots Using Substitution . . . . . . . . . . . . . . . . . . . . . . . . . . .
Roots in a Specific Interval . . . . . . . . . . . . . . . . . . . . . . . . . .
Symbolic Roots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6-4
6-4
6-5
6-6
6-8
Integrate and Differentiate Polynomials . . . . . . . . . . . . . . .
6-10
Polynomial Curve Fitting . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6-12
Roots of Scalar Functions . . . . . . . . . . . . . . . . . . . . . . . . . . .
Solving a Nonlinear Equation in One Variable . . . . . . . . . .
Using a Starting Interval . . . . . . . . . . . . . . . . . . . . . . . . . .
Using a Starting Point . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6-14
6-14
6-16
6-17
Computational Geometry
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7-2
Triangulation Representations . . . . . . . . . . . . . . . . . . . . . . . .
2-D and 3-D Domains . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Triangulation Matrix Format . . . . . . . . . . . . . . . . . . . . . . . .
Querying Triangulations Using the triangulation Class . . . .
7-3
7-3
7-4
7-6
8
Delaunay Triangulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Definition of Delaunay Triangulation . . . . . . . . . . . . . . . . .
Creating Delaunay Triangulations . . . . . . . . . . . . . . . . . . .
Triangulation of Point Sets Containing Duplicate Locations
7-17
7-17
7-19
7-47
Spatial Searching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Nearest-Neighbor Search . . . . . . . . . . . . . . . . . . . . . . . . . .
Point-Location Search . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7-50
7-50
7-50
7-54
Voronoi Diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Plot 2-D Voronoi Diagram and Delaunay Triangulation . . . .
Computing the Voronoi Diagram . . . . . . . . . . . . . . . . . . . . .
7-59
7-59
7-63
Types of Region Boundaries . . . . . . . . . . . . . . . . . . . . . . . . .
Convex Hulls vs. Nonconvex Polygons . . . . . . . . . . . . . . . . .
Alpha Shapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7-68
7-68
7-72
Computing the Convex Hull . . . . . . . . . . . . . . . . . . . . . . . . . .
Computing the Convex Hull Using convhull and convhulln .
Convex Hull Computation Using the delaunayTriangulation
Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Convex Hull Computation Using alphaShape . . . . . . . . . . .
7-76
7-76
7-81
7-84
Interpolation
Gridded and Scattered Sample Data . . . . . . . . . . . . . . . . . . . .
8-2
Interpolating Gridded Data . . . . . . . . . . . . . . . . . . . . . . . . . . .
Gridded Data Representation . . . . . . . . . . . . . . . . . . . . . . . .
Grid-Based Interpolation . . . . . . . . . . . . . . . . . . . . . . . . . . .
Interpolation with the interp Family of Functions . . . . . . . .
Interpolation with the griddedInterpolant Class . . . . . . . . .
8-4
8-4
8-18
8-25
8-37
Interpolation of Multiple 1-D Value Sets . . . . . . . . . . . . . . .
8-50
Interpolation of 2-D Selections in 3-D Grids . . . . . . . . . . . .
8-52
xi
Interpolating Scattered Data . . . . . . . . . . . . . . . . . . . . . . . . .
Scattered Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Interpolating Scattered Data Using griddata and griddatan
scatteredInterpolant Class . . . . . . . . . . . . . . . . . . . . . . . . .
Interpolating Scattered Data Using the scatteredInterpolant
Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Interpolation of Complex Scattered Data . . . . . . . . . . . . . . .
Addressing Problems in Scattered Data Interpolation . . . . .
8-54
8-54
8-57
8-61
8-61
8-71
8-73
Interpolation Using a Specific Delaunay Triangulation . . .
8-83
Nearest-Neighbor Interpolation Using a delaunayTriangulation
Query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8-83
Linear Interpolation Using a delaunayTriangulation Query
8-84
Extrapolating Scattered Data . . . . . . . . . . . . . . . . . . . . . . . .
Factors That Affect the Accuracy of Extrapolation . . . . . . . .
Compare Extrapolation of Coarsely and Finely Sampled
Scattered Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Extrapolation of 3-D Data . . . . . . . . . . . . . . . . . . . . . . . . . .
9
xii
Contents
8-86
8-86
8-86
8-90
Optimization
Function Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9-2
Optimizing Nonlinear Functions . . . . . . . . . . . . . . . . . . . . . . .
Minimizing Functions of One Variable . . . . . . . . . . . . . . . . .
Minimizing Functions of Several Variables . . . . . . . . . . . . . .
Maximizing Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
fminsearch Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9-3
9-3
9-5
9-6
9-6
Curve Fitting via Optimization . . . . . . . . . . . . . . . . . . . . . . . .
Curve Fitting by Optimization . . . . . . . . . . . . . . . . . . . . . . .
Creating an Example File . . . . . . . . . . . . . . . . . . . . . . . . . . .
Running the Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Plotting the Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9-9
9-9
9-9
9-10
9-10
Set Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
How to Set Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Options Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9-12
9-12
9-12
Tolerances and Stopping Criteria . . . . . . . . . . . . . . . . . . . .
Output Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
Iterative Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9-16
Output Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
What Is an Output Function? . . . . . . . . . . . . . . . . . . . . . . .
Creating and Using an Output Function . . . . . . . . . . . . . . .
Structure of the Output Function . . . . . . . . . . . . . . . . . . . .
Example of a Nested Output Function . . . . . . . . . . . . . . . .
Fields in optimValues . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
States of the Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Stop Flag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9-18
9-18
9-18
9-20
9-20
9-23
9-23
9-24
Plot Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
What Is A Plot Function? . . . . . . . . . . . . . . . . . . . . . . . . . .
Example: Plot Function . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9-26
9-26
9-26
Troubleshooting and Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9-29
Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9-30
Function Handles
Parameterizing Functions . . . . . . . . . . . . . . . . . . . . . . . . . . .
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Parameterizing Using Nested Functions . . . . . . . . . . . . . . .
Parameterizing Using Anonymous Functions . . . . . . . . . . .
11
9-13
9-14
10-2
10-2
10-2
10-3
Calculus
Ordinary Differential Equations . . . . . . . . . . . . . . . . . . . . . .
Function Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Initial Value Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Types of Solvers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11-2
11-2
11-4
11-5
xiii
Solver Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Integrator Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
xiv
Contents
11-8
11-9
11-9
11-36
Types of DDEs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Constant Delay DDEs . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Time-Dependent and State-Dependent DDEs . . . . . . . . . .
DDEs of Neutral Type . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Evaluating the Solution at Specific Points . . . . . . . . . . . . .
History and Initial Values . . . . . . . . . . . . . . . . . . . . . . . . .
Propagation of Discontinuities . . . . . . . . . . . . . . . . . . . . . .
11-43
11-43
11-43
11-44
11-44
11-44
11-44
Discontinuities in DDEs . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11-46
DDE with Constant Delays . . . . . . . . . . . . . . . . . . . . . . . . . .
11-47
State-Dependent Delay Problem . . . . . . . . . . . . . . . . . . . . .
11-50
Cardiovascular Model with Discontinuities . . . . . . . . . . . .
11-54
DDE of Neutral Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11-58
Initial Value DDE of Neutral Type . . . . . . . . . . . . . . . . . . .
11-62
Boundary-Value Problems . . . . . . . . . . . . . . . . . . . . . . . . . .
Function Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Boundary Value Problems . . . . . . . . . . . . . . . . . . . . . . . . .
BVP Solver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Integrator Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11-66
11-66
11-67
11-67
11-70
11-71
Partial Differential Equations . . . . . . . . . . . . . . . . . . . . . . .
Function Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Initial Value Problems . . . . . . . . . . . . . . . . . . . . . . . . . . .
PDE Solver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Integrator Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11-91
11-91
11-91
11-92
11-95
11-96
Selected Bibliography for Differential Equations . . . . . .
11-107
Integration to Find Arc Length . . . . . . . . . . . . . . . . . . . . .
11-108
12
Complex Line Integrals . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11-109
Singularity on Interior of Integration Domain . . . . . . . .
11-112
Analytic Solution to Integral of Polynomial . . . . . . . . . . .
11-114
Integration of Numeric Data . . . . . . . . . . . . . . . . . . . . . . .
11-115
Fourier Transforms
Discrete Fourier Transform (DFT) . . . . . . . . . . . . . . . . . . . .
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Visualizing the DFT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12-2
12-2
12-3
Fast Fourier Transform (FFT) . . . . . . . . . . . . . . . . . . . . . . . .
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The FFT in One Dimension . . . . . . . . . . . . . . . . . . . . . . . . .
The FFT in Multiple Dimensions . . . . . . . . . . . . . . . . . . .
12-8
12-8
12-9
12-22
Function Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12-28
xv
1
Matrices and Arrays
• “Creating and Concatenating Matrices” on page 1-2
• “Matrix Indexing” on page 1-11
• “Getting Information About a Matrix” on page 1-21
• “Resizing and Reshaping Matrices” on page 1-24
• “Shifting and Sorting Matrices” on page 1-33
• “Operating on Diagonal Matrices” on page 1-38
• “Empty Matrices, Scalars, and Vectors” on page 1-40
• “Full and Sparse Matrices” on page 1-45
• “Multidimensional Arrays” on page 1-47
• “Summary of Matrix and Array Functions” on page 1-66
1
Matrices and Arrays
Creating and Concatenating Matrices
In this section...
“Overview” on page 1-2
“Constructing a Simple Matrix” on page 1-3
“Specialized Matrix Functions” on page 1-4
“Concatenating Matrices” on page 1-6
“Matrix Concatenation Functions” on page 1-7
“Generating a Numeric Sequence” on page 1-8
Overview
The most basic MATLAB® data structure is the matrix: a two-dimensional, rectangularly
shaped data structure capable of storing multiple elements of data in an easily accessible
format. These data elements can be numbers, characters, logical states of true or
false, or even other MATLAB structure types. MATLAB uses these two-dimensional
matrices to store single numbers and linear series of numbers as well. In these cases,
the dimensions are 1-by-1 and 1-by-n respectively, where n is the length of the numeric
series. MATLAB also supports data structures that have more than two dimensions.
These data structures are referred to as arrays in the MATLAB documentation.
MATLAB is a matrix-based computing environment. All of the data that you enter into
MATLAB is stored in the form of a matrix or a multidimensional array. Even a single
numeric value like 100 is stored as a matrix (in this case, a matrix having dimensions 1by-1):
A = 100;
whos A
Name
A
Size
1x1
Bytes
8
Class
double array
Regardless of the class being used, whether it is numeric, character, or logical true or
false data, MATLAB stores this data in matrix (or array) form. For example, the string
'Hello World' is a 1-by-11 matrix of individual character elements in MATLAB. You
can also build matrices composed of more complex classes, such as MATLAB structures
and cell arrays.
1-2
Creating and Concatenating Matrices
To create a matrix of basic data elements such as numbers or characters, see
• “Constructing a Simple Matrix” on page 1-3
• “Specialized Matrix Functions” on page 1-4
To build a matrix composed of other matrices, see
• “Concatenating Matrices” on page 1-6
• “Matrix Concatenation Functions” on page 1-7
Constructing a Simple Matrix
The simplest way to create a matrix in MATLAB is to use the matrix constructor
operator, []. Create a row in the matrix by entering elements (shown as E below) within
the brackets. Separate each element with a comma or space:
row = [E1, E2, ..., Em]
row = [E1 E2 ... Em]
For example, to create a one row matrix of five elements, type
A = [12 62 93 -8 22];
To start a new row, terminate the current row with a semicolon:
A = [row1; row2; ...; rown]
This example constructs a 3 row, 5 column (or 3-by-5) matrix of numbers. Note that all
rows must have the same number of elements:
A = [12 62 93 -8 22; 16 2 87 43 91; -4 17 -72 95 6]
A =
12
62
93
-8
22
16
2
87
43
91
-4
17
-72
95
6
The square brackets operator constructs two-dimensional matrices only, (including 0by-0, 1-by-1, and 1-by-n matrices). To construct arrays of more than two dimensions, see
“Creating Multidimensional Arrays” on page 1-49.
For instructions on how to read or overwrite any matrix element, see “Matrix Indexing”
on page 1-11.
1-3
1
Matrices and Arrays
Entering Signed Numbers
When entering signed numbers into a matrix, make sure that the sign immediately
precedes the numeric value. Note that while the following two expressions are
equivalent,
7 -2 +5
ans =
10
7 - 2 + 5
ans =
10
the next two are not:
[7 -2 +5]
ans =
7
-2
5
[7 - 2 + 5]
ans =
10
Specialized Matrix Functions
MATLAB has a number of functions that create different kinds of matrices. Some create
specialized matrices like the Hankel or Vandermonde matrix. The functions shown in the
table below create matrices for more general use.
1-4
Function
Description
ones
Create a matrix or array of all ones.
zeros
Create a matrix or array of all zeros.
eye
Create a matrix with ones on the diagonal and zeros elsewhere.
accumarray
Distribute elements of an input matrix to specified locations in an
output matrix, also allowing for accumulation.
diag
Create a diagonal matrix from a vector.
magic
Create a square matrix with rows, columns, and diagonals that add
up to the same number.
rand
Create a matrix or array of uniformly distributed random numbers.
randn
Create a matrix or array of normally distributed random numbers
and arrays.
randperm
Create a vector (1-by-n matrix) containing a random permutation of
the specified integers.
Creating and Concatenating Matrices
Most of these functions return matrices of type double (double-precision floating point).
However, you can easily build basic arrays of any numeric type using the ones, zeros,
and eye functions.
To do this, specify the MATLAB class name as the last argument:
A = zeros(4, 6, 'uint32')
A =
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
Examples
Here are some examples of how you can use these functions.
Creating a Magic Square Matrix
A magic square is a matrix in which the sum of the elements in each column, or each
row, or each main diagonal is the same. To create a 5-by-5 magic square matrix, use the
magic function as shown.
A = magic(5)
A =
17
24
23
5
4
6
10
12
11
18
1
7
13
19
25
8
14
20
21
2
15
16
22
3
9
Note that the elements of each row, each column, and each main diagonal add up to the
same value: 65.
Creating a Diagonal Matrix
Use diag to create a diagonal matrix from a vector. You can place the vector along the
main diagonal of the matrix, or on a diagonal that is above or below the main one, as
shown here. The -1 input places the vector one row below the main diagonal:
A = [12 62 93 -8 22];
B = diag(A, -1)
B =
0
0
0
0
0
0
1-5
1
Matrices and Arrays
12
0
0
0
0
0
62
0
0
0
0
0
93
0
0
0
0
0
-8
0
0
0
0
0
22
0
0
0
0
0
Concatenating Matrices
Matrix concatenation is the process of joining one or more matrices to make a new
matrix. The brackets [] operator discussed earlier in this section serves not only as a
matrix constructor, but also as the MATLAB concatenation operator. The expression
C = [A B] horizontally concatenates matrices A and B. The expression C = [A; B]
vertically concatenates them.
This example constructs a new matrix C by concatenating matrices A and B in a vertical
direction:
A = ones(2, 5) * 6;
B = rand(3, 5);
% 2-by-5 matrix of 6's
% 3-by-5 matrix of random values
C = [A; B]
C =
6.0000
6.0000
0.9501
0.2311
0.6068
% Vertically concatenate A and B
6.0000
6.0000
0.4860
0.8913
0.7621
6.0000
6.0000
0.4565
0.0185
0.8214
6.0000
6.0000
0.4447
0.6154
0.7919
6.0000
6.0000
0.9218
0.7382
0.1763
Keeping Matrices Rectangular
You can construct matrices, or even multidimensional arrays, using concatenation
as long as the resulting matrix does not have an irregular shape (as in the second
illustration shown below). If you are building a matrix horizontally, then each component
matrix must have the same number of rows. When building vertically, each component
must have the same number of columns.
This diagram shows two matrices of the same height (i.e., same number of rows) being
combined horizontally to form a new matrix.
1-6
Creating and Concatenating Matrices
The next diagram illustrates an attempt to horizontally combine two matrices of unequal
height. MATLAB does not allow this.
Matrix Concatenation Functions
The following functions combine existing matrices to form a new matrix.
Function
Description
cat
Concatenate matrices along the specified dimension
horzcat
Horizontally concatenate matrices
vertcat
Vertically concatenate matrices
repmat
Create a new matrix by replicating and tiling existing matrices
blkdiag
Create a block diagonal matrix from existing matrices
Examples
Here are some examples of how you can use these functions.
Concatenating Matrices and Arrays
An alternative to using the [] operator for concatenation are the three functions
cat, horzcat, and vertcat. With these functions, you can construct matrices
(or multidimensional arrays) along a specified dimension. Either of the following
commands accomplish the same task as the command C = [A; B] used in the section
on “Concatenating Matrices” on page 1-6:
C = cat(1, A, B);
C = vertcat(A, B);
% Concatenate along the first dimension
% Concatenate vertically
Replicating a Matrix
Use the repmat function to create a matrix composed of copies of an existing matrix.
When you enter
repmat(M, v, h)
1-7
1
Matrices and Arrays
MATLAB replicates input matrix M v times vertically and h times horizontally. For
example, to replicate existing matrix A into a new matrix B, use
A = [8
A =
8
3
4
1 6; 3 5 7; 4 9 2]
1
5
9
6
7
2
B = repmat(A, 2, 4)
B =
8
1
6
8
1
3
5
7
3
5
4
9
2
4
9
8
1
6
8
1
3
5
7
3
5
4
9
2
4
9
6
7
2
6
7
2
8
3
4
8
3
4
1
5
9
1
5
9
6
7
2
6
7
2
8
3
4
8
3
4
1
5
9
1
5
9
6
7
2
6
7
2
Creating a Block Diagonal Matrix
The blkdiag function combines matrices in a diagonal direction, creating what is called
a block diagonal matrix. All other elements of the newly created matrix are set to zero:
A = magic(3);
B = [-5 -6 -9; -4 -4 -2];
C = eye(2) * 8;
D = blkdiag(A, B, C)
D =
8
1
6
0
0
3
5
7
0
0
4
9
2
0
0
0
0
0 -5 -6
0
0
0 -4 -4
0
0
0
0
0
0
0
0
0
0
0
0
0
-9
-2
0
0
0
0
0
0
0
8
0
0
0
0
0
0
0
8
Generating a Numeric Sequence
Because numeric sequences can often be useful in constructing and indexing into
matrices and arrays, MATLAB provides a special operator to assist in creating them.
This section covers
1-8
Creating and Concatenating Matrices
• “The Colon Operator” on page 1-9
• “Using the Colon Operator with a Step Value” on page 1-9
The Colon Operator
The colon operator (first:last) generates a 1-by-n matrix (or vector) of sequential
numbers from the first value to the last. The default sequence is made up of
incremental values, each 1 greater than the previous one:
A = 10:15
A =
10
11
12
13
14
15
The numeric sequence does not have to be made up of positive integers. It can include
negative numbers and fractional numbers as well:
A = -2.5:2.5
A =
-2.5000
-1.5000
-0.5000
0.5000
1.5000
2.5000
By default, MATLAB always increments by exactly 1 when creating the sequence, even if
the ending value is not an integral distance from the start:
A = 1:6.3
A =
1
2
3
4
5
6
Also, the default series generated by the colon operator always contains increments
rather than decrements. The operation shown in this example attempts to increment
from 9 to 1 and thus MATLAB returns an empty matrix:
A = 9:1
A =
Empty matrix: 1-by-0
The next section explains how to generate a nondefault numeric series.
Using the Colon Operator with a Step Value
To generate a series that does not use the default of incrementing by 1, specify an
additional value with the colon operator (first:step:last). In between the starting
and ending value is a step value that tells MATLAB how much to increment (or
decrement, if step is negative) between each number it generates.
1-9
1
Matrices and Arrays
To generate a series of numbers from 10 to 50, incrementing by 5, use
A = 10:5:50
A =
10
15
20
25
30
35
40
45
50
You can increment by noninteger values. This example increments by 0.2:
A = 3:0.2:3.8
A =
3.0000
3.2000
3.4000
3.6000
3.8000
To create a sequence with a decrementing interval, specify a negative step value:
A = 9:-1:1
A =
9
8
1-10
7
6
5
4
3
2
1
Matrix Indexing
Matrix Indexing
In this section...
“Accessing Single Elements” on page 1-11
“Linear Indexing” on page 1-12
“Functions That Control Indexing Style” on page 1-12
“Assigning to Elements Outside Array Bounds” on page 1-13
“Accessing Multiple Elements” on page 1-13
“Using Logicals in Array Indexing” on page 1-16
“Single-Colon Indexing with Different Array Types” on page 1-19
“Indexing on Assignment” on page 1-20
Accessing Single Elements
To reference a particular element in a matrix, specify its row and column number using
the following syntax, where A is the matrix variable. Always specify the row first and
column second:
A(row, column)
For example, for a 4-by-4 magic square A,
A = magic(4)
A =
16
2
5
11
9
7
4
14
3
10
6
15
13
8
12
1
you would access the element at row 4, column 2 with
A(4, 2)
ans =
14
For arrays with more than two dimensions, specify additional indices following the row
and column indices. See the section on “Multidimensional Arrays” on page 1-47.
1-11
1
Matrices and Arrays
Linear Indexing
You can refer to the elements of a MATLAB matrix with a single subscript, A(k).
MATLAB stores matrices and arrays not in the shape that they appear when displayed
in the MATLAB Command Window, but as a single column of elements. This single
column is composed of all of the columns from the matrix, each appended to the last.
So, matrix A
A = [2 6 9; 4 2 8; 3 5 1]
A =
2
6
9
4
2
8
3
5
1
is actually stored in memory as the sequence
2, 4, 3, 6, 2, 5, 9, 8, 1
The element at row 3, column 2 of matrix A (value = 5) can also be identified as element
6 in the actual storage sequence. To access this element, you have a choice of using the
standard A(3,2) syntax, or you can use A(6), which is referred to as linear indexing.
If you supply more subscripts, MATLAB calculates an index into the storage column
based on the dimensions you assigned to the array. For example, assume a twodimensional array like A has size [d1 d2], where d1 is the number of rows in the array
and d2 is the number of columns. If you supply two subscripts (i, j) representing rowcolumn indices, the offset is
(j-1) * d1 + i
Given the expression A(3,2), MATLAB calculates the offset into A's storage column as
(2-1) * 3 + 3, or 6. Counting down six elements in the column accesses the value 5.
Functions That Control Indexing Style
If you have row-column subscripts but want to use linear indexing instead, you can
convert to the latter using the sub2ind function. In the 3-by-3 matrix A used in the
previous section, sub2ind changes a standard row-column index of (3,2) to a linear index
of 6:
A = [2 6 9; 4 2 8; 3 5 1];
1-12
Matrix Indexing
linearindex = sub2ind(size(A), 3, 2)
linearindex =
6
To get the row-column equivalent of a linear index, use the ind2sub function:
[row col] = ind2sub(size(A), 6)
row =
3
col =
2
Assigning to Elements Outside Array Bounds
When you assign to elements outside the bounds of a numeric array, MATLAB expands
the array to include those elements and fills the missing values with 0.
Assign a value to an element outside the bounds of A.
A = magic(4);
A(3,5) = 7
A =
16
2
5
11
9
7
4
14
3
10
6
15
13
8
12
1
0
0
7
0
When you extend structure and cell arrays, MATLAB fills unaddressed elements
with an empty value. MATLAB fills unaddressed elements in categorical arrays with
<undefined>. For datetime arrays, MATLAB fills unaddressed elements with NaT (Nota-Time).
If you try to refer to elements outside an array on the right side of an assignment
statement, MATLAB throws an error.
test = A(7,7)
Undefined function or variable 'A'.
Accessing Multiple Elements
For the 4-by-4 matrix A shown below, it is possible to compute the sum of the elements in
the fourth column of A by typing
1-13
1
Matrices and Arrays
A = magic(4);
A(1,4) + A(2,4) + A(3,4) + A(4,4)
You can reduce the size of this expression using the colon operator. Subscript expressions
involving colons refer to portions of a matrix. The expression
A(1:m, n)
refers to the elements in rows 1 through m of column n of matrix A. Using this notation,
you can compute the sum of the fourth column of A more succinctly:
sum(A(1:4, 4))
Nonconsecutive Elements
To refer to nonconsecutive elements in a matrix, use the colon operator with a step value.
The m:3:n in this expression means to make the assignment to every third element in
the matrix. Note that this example uses linear indexing:
B = A;
B(1:3:16) = -10
B =
-10
2
3
5
11
-10
9
-10
6
-10
14
15
-10
8
12
-10
MATLAB supports a type of array indexing that uses one array as the index into another
array. You can base this type of indexing on either the values or the positions of elements
in the indexing array.
Here is an example of value-based indexing where array B indexes into elements 1, 3, 6,
7, and 10 of array A. In this case, the numeric values of array B designate the intended
elements of A:
A = 5:5:50
A =
5
10
15
B = [1 3 6 7 10];
20
25
35
50
A(B)
ans =
5
1-14
15
30
30
35
40
45
50
Matrix Indexing
If you index into a vector with another vector, the orientation of the indexed vector is
honored for the output:
A(B')
ans =
5
15
A1 = A'; A1(B)
ans =
30
35
50
5
15
30
35
50
If you index into a vector with a nonvector, the shape of the indices is honored:
C = [1 3 6; 7 9 10];
A(C)
ans =
5
35
15
45
30
50
The end Keyword
MATLAB provides the keyword end to designate the last element in a particular
dimension of an array. This keyword can be useful in instances where your program
does not know how many rows or columns there are in a matrix. You can replace the
expression in the previous example with
B(1:3:end) = -10
Note The keyword end has several meanings in MATLAB. It can be used as explained
above, or to terminate a conditional block of code such as if and for blocks, or to
terminate a nested function.
Specifying All Elements of a Row or Column
The colon by itself refers to all the elements in a row or column of a matrix. Using the
following syntax, you can compute the sum of all elements in the second column of a 4by-4 magic square A:
1-15
1
Matrices and Arrays
sum(A(:, 2))
ans =
34
By using the colon with linear indexing, you can refer to all elements in the entire
matrix. This example displays all the elements of matrix A, returning them in a columnwise order:
A(:)
ans =
16
5
9
4
.
.
.
12
1
Using Logicals in Array Indexing
A logical array index designates the elements of an array A based on their position in the
indexing array, B, not their value. In this masking type of operation, every true element
in the indexing array is treated as a positional index into the array being accessed.
In the following example, B is a matrix of logical ones and zeros. The position of these
elements in B determines which elements of A are designated by the expression A(B):
A = [1 2 3; 4 5 6; 7 8 9]
A =
1
2
3
4
5
6
7
8
9
B = logical([0 1 0; 1 0 1; 0 0 1]);
B =
0
1
0
1
0
1
0
0
1
A(B)
ans =
1-16
Matrix Indexing
4
2
6
9
The find function can be useful with logical arrays as it returns the linear indices of
nonzero elements in B, and thus helps to interpret A(B):
find(B)
ans =
2
4
8
9
Logical Indexing – Example 1
This example creates logical array B that satisfies the condition A > 0.5, and uses the
positions of ones in B to index into A:
rng(0,'twister');
A = rand(5);
B = A > 0.5;
A(B) = 0
A =
0
0
0.1270
0
0
% Reset the random number generator
0.0975
0.2785
0
0
0
0.1576
0
0
0.4854
0
0.1419
0.4218
0
0
0
0
0.0357
0
0
0
A simpler way to express this is
A(A > 0.5) = 0
Logical Indexing – Example 2
The next example highlights the location of the prime numbers in a magic square using
logical indexing to set the nonprimes to 0:
A = magic(4)
A =
16
2
5
11
3
10
13
8
1-17
1
Matrices and Arrays
9
4
7
14
B = isprime(A)
B =
0
1
1
1
0
1
0
0
6
15
12
1
1
0
0
0
1
0
0
0
A(~B) = 0;
% Logical indexing
A
A =
0
5
0
0
2
11
7
0
3
0
0
0
13
0
0
0
find(B)
ans =
2
5
6
7
9
13
Logical Indexing with a Smaller Array
In most cases, the logical indexing array should have the same number of elements as
the array being indexed into, but this is not a requirement. The indexing array may have
smaller (but not larger) dimensions:
A = [1 2 3;4 5 6;7 8 9]
A =
1
2
3
4
5
6
7
8
9
B = logical([0 1 0; 1 0 1])
B =
0
1
0
1
0
1
1-18
Matrix Indexing
isequal(numel(A), numel(B))
ans =
0
A(B)
ans =
4
7
8
MATLAB treats the missing elements of the indexing array as if they were present and
set to zero, as in array C below:
% Add zeros to indexing array C to give it the same number of
% elements as A.
C = logical([B(:);0;0;0]);
isequal(numel(A), numel(C))
ans =
1
A(C)
ans =
4
7
8
Single-Colon Indexing with Different Array Types
When you index into a standard MATLAB array using a single colon, MATLAB returns a
column vector (see variable n, below). When you index into a structure or cell array using
a single colon, you get a comma-separated list (see “Access Data in a Structure Array”
and “Access Data in a Cell Array” for more information.)
Create three types of arrays:
n = [1 2 3; 4 5 6];
c = {1 2; 3 4};
s = cell2struct(c, {'a', 'b'}, 1);
s(:,2)=s(:,1);
Use single-colon indexing on each:
n(:)
ans =
c{:}
ans =
s(:).a
ans =
1-19
1
Matrices and Arrays
1
4
2
5
3
6
1
ans =
1
ans =
3
ans =
2
ans =
2
ans =
1
ans =
4
2
Indexing on Assignment
When assigning values from one matrix to another matrix, you can use any of the styles
of indexing covered in this section. Matrix assignment statements also have the following
requirement.
In the assignment A(J,K,...) = B(M,N,...), subscripts J, K, M, N, etc. may be scalar,
vector, or array, provided that all of the following are true:
• The number of subscripts specified for B, not including trailing subscripts equal to 1,
does not exceed ndims(B).
• The number of nonscalar subscripts specified for A equals the number of nonscalar
subscripts specified for B. For example, A(5, 1:4, 1, 2) = B(5:8) is valid
because both sides of the equation use one nonscalar subscript.
• The order and length of all nonscalar subscripts specified for A matches the order
and length of nonscalar subscripts specified for B. For example, A(1:4, 3, 3:9)
= B(5:8, 1:7) is valid because both sides of the equation (ignoring the one scalar
subscript 3) use a 4-element subscript followed by a 7-element subscript.
1-20
Getting Information About a Matrix
Getting Information About a Matrix
In this section...
“Dimensions of the Matrix” on page 1-21
“Classes Used in the Matrix” on page 1-22
“Data Structures Used in the Matrix” on page 1-23
Dimensions of the Matrix
These functions return information about the shape and size of a matrix.
Function
Description
length
Return the length of the longest dimension. (The length of a matrix or
array with any zero dimension is zero.)
ndims
Return the number of dimensions.
numel
Return the number of elements.
size
Return the length of each dimension.
The following examples show some simple ways to use these functions. Both use the 3by-5 matrix A shown here:
A = 10*gallery('uniformdata',[5],0);
A(4:5, :) = []
A =
9.5013
7.6210
6.1543
4.0571
2.3114
4.5647
7.9194
9.3547
6.0684
0.1850
9.2181
9.1690
0.5789
3.5287
8.1317
Example Using numel
Using the numel function, find the average of all values in matrix A:
sum(A(:))/numel(A)
ans =
5.8909
Example Using ndims, numel, and size
Using ndims and size, go through the matrix and find those values that are between 5
and 7, inclusive:
1-21
1
Matrices and Arrays
if ndims(A) ~= 2
return
end
[rows cols] = size(A);
for m = 1:rows
for n = 1:cols
x = A(m, n);
if x >= 5 && x <= 7
disp(sprintf('A(%d, %d) = %5.2f', m, n, A(m,n)))
end
end
end
The code returns the following:
A(1, 3) =
A(3, 1) =
6.15
6.07
Classes Used in the Matrix
These functions test elements of a matrix for a specific data type.
Function
Description
isa
Detect if input is of a given data type.
iscell
Determine if input is a cell array.
iscellstr
Determine if input is a cell array of strings.
ischar
Determine if input is a character array.
isfloat
Determine if input is a floating-point array.
isinteger
Determine if input is an integer array.
islogical
Determine if input is a logical array.
isnumeric
Determine if input is a numeric array.
isreal
Determine if input is an array of real numbers.
isstruct
Determine if input is a MATLAB structure array.
Example Using isnumeric and isreal
Pick out the real numeric elements from this vector:
1-22
Getting Information About a Matrix
A = [5+7i 8/7 4.23 39j pi 9-2i];
for m = 1:numel(A)
if isnumeric(A(m)) && isreal(A(m))
disp(A(m))
end
end
The values returned are
1.1429
4.2300
3.1416
Data Structures Used in the Matrix
These functions test elements of a matrix for a specific data structure.
Function
Description
isempty
Determine if input has any dimension with size zero.
isscalar
Determine if input is a 1-by-1 matrix.
issparse
Determine if input is a sparse matrix.
isvector
Determine if input is a 1-by-n or n-by-1 matrix.
1-23
1
Matrices and Arrays
Resizing and Reshaping Matrices
In this section...
“Expanding the Size of a Matrix” on page 1-24
“Diminishing the Size of a Matrix” on page 1-28
“Reshaping a Matrix” on page 1-28
“Preallocating Memory” on page 1-30
Expanding the Size of a Matrix
You can expand the size of any existing matrix as long as doing so does not give the
resulting matrix an irregular shape. (See “Keeping Matrices Rectangular” on page 1-6).
For example, you can vertically combine a 4-by-3 matrix and 7-by-3 matrix because all
rows of the resulting matrix have the same number of columns (3).
Two ways of expanding the size of an existing matrix are
• Concatenating new elements onto the matrix
• Storing to a location outside the bounds of the matrix
Note If you intend to expand the size of a matrix repeatedly over time as it requires more
room (usually done in a programming loop), it is advisable to preallocate space for the
matrix when you initially create it. See “Preallocating Memory” on page 1-30.
Concatenating Onto the Matrix
Concatenation is most useful when you want to expand a matrix by adding new elements
or blocks that are compatible in size with the original matrix. This means that the size of
all matrices being joined along a specific dimension must be equal along that dimension.
See “Concatenating Matrices” on page 1-6.
This example runs a user-defined function compareResults on the data in matrices
stats04 and stats03. Each time through the loop, it concatenates the results of this
function onto the end of the data stored in comp04:
col = 10;
comp04 = [];
1-24
Resizing and Reshaping Matrices
for k = 1:50
t = compareResults(stats04(k,1:col), stats03(k,1:col));
comp04 = [comp04; t];
end
Concatenating to a Structure or Cell Array
You can add on to arrays of structures or cells in the same way as you do with ordinary
matrices. This example creates a 3-by-8 matrix of structures S, each having 3 fields: x, y,
and z, and then concatenates a second structure matrix S2 onto the original:
Create a 3-by-8 structure array S:
for k = 1:24
S(k) = struct('x', 10*k, 'y', 10*k+1, 'z', 10*k+2);
end
S = reshape(S, 3, 8);
Create a second array that is 3-by-2 and uses the same field names:
for k = 25:30
S2(k-24) = struct('x', 10*k, 'y', 10*k+1, 'z', 10*k+2);
end
S2= reshape(S2, 3, 2);
Concatenate S2 onto S along the horizontal dimension:
S = [S S2]
S =
3x10 struct array with fields:
x
y
z
Adding Smaller Blocks to a Matrix
To add one or more elements to a matrix where the sizes are not compatible, you can
often just store the new elements outside the boundaries of the original matrix. The
MATLAB software automatically pads the matrix with zeros to keep it rectangular.
Construct a 3-by-5 matrix, and attempt to add a new element to it using concatenation.
The operation fails because you are attempting to join a one-column matrix with one that
has five columns:
A = [ 10
20
30
40
50; ...
1-25
1
Matrices and Arrays
60 70 80 90 100; ...
110 120 130 140 150];
A = [A; 160]
Error using vertcat
CAT arguments dimensions are not consistent.
Try this again, but this time do it in such a way that enables MATLAB to make
adjustments to the size of the matrix. Store the new element in row 4, a row that does
not yet exist in this matrix. MATLAB expands matrix A by an entire new row by padding
columns 2 through 5 with zeros:
A(4,1) = 160
A =
10
20
60
70
110
120
160
0
30
80
130
0
40
90
140
0
50
100
150
0
Note Attempting to read from nonexistent matrix locations generates an error. You can
only write to these locations.
You can also expand the matrix by adding a matrix instead of just a single element:
A(4:6,1:3) = magic(3)+100
A =
10
20
30
40
60
70
80
90
110
120
130
140
108
101
106
0
103
105
107
0
104
109
102
0
50
100
150
0
0
0
You do not have to add new elements sequentially. Wherever you store the new elements,
MATLAB pads with zeros to make the resulting matrix rectangular in shape:
A(4,8) = 300
A =
10
20
60
70
110
120
0
0
1-26
30
80
130
0
40
90
140
0
50
100
150
0
0
0
0
0
0
0
0
0
0
0
0
300
Resizing and Reshaping Matrices
Expanding a Structure or Cell Array
You can expand a structure or cell array in the same way that you can a matrix. This
example adds an additional cell to a cell array by storing it beyond the bounds of
the original array. MATLAB pads the data structure with empty cells ([]) to keep it
rectangular.
The original array is 2-by-3:
C = {'Madison', 'G', [5 28 1967]; ...
46, '325 Maple Dr', 3015.28}
Add a cell to C{3,1} and MATLAB appends an entire row:
C{3, 1} = ...
struct('Fund_A', .45, 'Fund_E', .35, 'Fund_G', 20);
C =
'Madison'
'G'
[1x3 double]
[
46]
'325 Maple Dr'
[3.0153e+003]
[1x1 struct]
[]
[]
Expanding a Character Array
You can expand character arrays in the same manner as other MATLAB arrays, but it
is generally not recommended. MATLAB expands any array by padding uninitialized
elements with zeros. Because zero is interpreted by MATLAB and some other
programming languages as a string terminator, you may find that some functions treat
the expanded string as if it were less than its full length.
Expand a 1-by-5 character array to twelve characters. The result appears at first to be a
typical string:
greeting = 'Hello';
greeting =
Hello World
greeting(1,8:12) = 'World'
Closer inspection however reveals string terminators at the point of expansion:
uint8(greeting)
ans =
72 101 108
108
111
0
0
87
111
114
108
100
This causes some functions, like strcmp, to return what might be considered an
unexpected result:
strcmp(greeting, 'Hello
World')
1-27
1
Matrices and Arrays
ans =
0
Diminishing the Size of a Matrix
You can delete rows and columns from a matrix by assigning the empty array [] to those
rows or columns. Start with
A = magic(4)
A =
16
2
5
11
9
7
4
14
3
10
6
15
13
8
12
1
Then, delete the second column of A using
A(:, 2) = []
This changes matrix A to
A =
16
5
9
4
3
10
6
15
13
8
12
1
If you delete a single element from a matrix, the result is not a matrix anymore. So
expressions like
A(1,2) = []
result in an error. However, you can use linear indexing to delete a single element, or a
sequence of elements. This reshapes the remaining elements into a row vector:
A(2:2:10) = []
results in
A =
16
9
3
6
13
12
1
Reshaping a Matrix
The following functions change the shape of a matrix.
1-28
Resizing and Reshaping Matrices
Function
Description
reshape
Modify the shape of a matrix.
rot90
Rotate the matrix by 90 degrees.
fliplr
Flip the matrix about a vertical axis.
flipud
Flip the matrix about a horizontal axis.
flip
Flip the matrix along the specified direction.
transpose
Flip a matrix about its main diagonal, turning row vectors into
column vectors and vice versa.
ctranspose
Transpose a matrix and replace each element with its complex
conjugate.
Examples
Here are a few examples to illustrate some of the ways you can reshape matrices.
Reshaping a Matrix
Reshape 3-by-4 matrix A to have dimensions 2-by-6:
A = [1 4 7 10; 2 5 8 11; 3 6 9 12]
A =
1
4
7
10
2
5
8
11
3
6
9
12
B = reshape(A, 2, 6)
B =
1
3
5
7
2
4
6
8
9
10
11
12
Transposing a Matrix
Transpose A so that the row elements become columns. You can use either the
transpose function or the transpose operator (.') to do this:
B = A.'
B =
1
4
7
2
5
8
3
6
9
1-29
1
Matrices and Arrays
10
11
12
There is a separate function called ctranspose that performs a complex conjugate
transpose of a matrix. The equivalent operator for ctranpose on a matrix A is A':
A = [1+9i 2-8i 3+7i; 4-6i 5+5i 6-4i]
A =
1.0000 + 9.0000i
2.0000 -8.0000i
4.0000 -6.0000i
5.0000 + 5.0000i
B = A'
B =
1.0000 -9.0000i
2.0000 + 8.0000i
3.0000 -7.0000i
3.0000 + 7.0000i
6.0000 -4.0000i
4.0000 + 6.0000i
5.0000 -5.0000i
6.0000 + 4.0000i
Rotating a Matrix
Rotate the matrix by 90 degrees:
B = rot90(A)
B =
10
11
7
8
4
5
1
2
12
9
6
3
Flipping a Matrix
Flip A in a left-to-right direction:
B = fliplr(A)
B =
10
7
11
8
12
9
4
5
6
1
2
3
Preallocating Memory
Repeatedly expanding the size of an array over time, (for example, adding more elements
to it each time through a programming loop), can adversely affect the performance of
your program. This is because
• MATLAB has to spend time allocating more memory each time you increase the size
of the array.
1-30
Resizing and Reshaping Matrices
• This newly allocated memory is likely to be noncontiguous, thus slowing down any
operations that MATLAB needs to perform on the array.
The preferred method for sizing an array that is expected to grow over time is to estimate
the maximum possible size for the array, and preallocate this amount of memory for it at
the time the array is created. In this way, your program performs one memory allocation
that reserves one contiguous block.
The following command preallocates enough space for a 25,000 by 10,000 matrix, and
initializes each element to zero:
A = zeros(25000, 10000);
Building a Preallocated Array
Once memory has been preallocated for the maximum estimated size of the array, you
can store your data in the array as you need it, each time appending to the existing data.
This example preallocates a large array, and then reads blocks of data from a file into the
array until it gets to the end of the file:
blocksize = 5000;
maxrows = 2500000; cols = 20;
rp = 1;
% row pointer
% Preallocate A to its maximum possible size
A = zeros(maxrows, cols);
% Open the data file, saving the file pointer.
fid = fopen('statfile.dat', 'r');
while true
% Read from file into a cell array. Stop at EOF.
block = textscan(fid, '%n', blocksize*cols);
if isempty(block{1})
break,
end;
% Convert cell array to matrix, reshape, place into A.
A(rp:rp+blocksize-1, 1:cols) = ...
reshape(cell2mat(block), blocksize, cols);
% Process the data in A.
evaluate_stats(A);
% User-defined function
% Update row pointer
rp = rp + blocksize;
1-31
1
Matrices and Arrays
end
Note If you eventually need more room in a matrix than you had preallocated, you can
preallocate additional storage in the same manner, and concatenate this additional
storage onto the original array.
1-32
Shifting and Sorting Matrices
Shifting and Sorting Matrices
In this section...
“Shift and Sort Functions” on page 1-33
“Shifting the Location of Matrix Elements” on page 1-33
“Sorting the Data in Each Column” on page 1-34
“Sorting the Data in Each Row” on page 1-35
“Sorting Row Vectors” on page 1-36
Shift and Sort Functions
Use these functions to shift or sort the elements of a matrix.
Function
Description
circshift
Circularly shift matrix contents.
sort
Sort array elements in ascending or descending order.
sortrows
Sort rows in ascending order.
issorted
Determine if matrix elements are in sorted order.
You can sort matrices, multidimensional arrays, and cell arrays of strings along any
dimension and in ascending or descending order of the elements. The sort functions also
return an optional array of indices showing the order in which elements were rearranged
during the sorting operation.
Shifting the Location of Matrix Elements
The circshift function shifts the elements of a matrix in a circular manner along one
or more dimensions. Rows or columns that are shifted out of the matrix circulate back
into the opposite end. For example, shifting a 4-by-7 matrix one place to the left moves
the elements in columns 2 through 7 to columns 1 through 6, and moves column 1 to
column 7.
Create a 5-by-8 matrix named A and shift it to the right along the second (horizontal)
dimension by three places (you would use [0,-3] to shift to the left by three places):
A = [1:8; 11:18; 21:28; 31:38; 41:48]
1-33
1
Matrices and Arrays
A =
1
11
21
31
41
2
12
22
32
42
3
13
23
33
43
4
14
24
34
44
5
15
25
35
45
6
16
26
36
46
7
17
27
37
47
8
18
28
38
48
B = circshift(A, [0, 3])
B =
6
7
8
1
16
17
18
11
26
27
28
21
36
37
38
31
46
47
48
41
2
12
22
32
42
3
13
23
33
43
4
14
24
34
44
5
15
25
35
45
Now take A and shift it along both dimensions: three columns to the right and two rows
up:
A = [1:8; 11:18; 21:28; 31:38; 41:48];
B = circshift(A, [-2,
B =
26
27
28
36
37
38
46
47
48
6
7
8
16
17
18
3])
21
31
41
1
11
22
32
42
2
12
23
33
43
3
13
24
34
44
4
14
25
35
45
5
15
Since circshift circulates shifted rows and columns around to the other end of a
matrix, shifting by the exact size of A returns all rows and columns to their original
location:
B = circshift(A, size(A));
all(B(:) == A(:))
ans =
1
% Do all elements of B equal A?
% Yes
Sorting the Data in Each Column
The sort function sorts matrix elements along a specified dimension. The syntax for the
function is
sort(matrix, dimension)
1-34
Shifting and Sorting Matrices
To sort the columns of a matrix, specify 1 as the dimension argument. To sort along
rows, specify dimension as 2.
This example makes a 6-by-7 arbitrary test matrix:
A=floor(gallery('uniformdata',[6 7],0)*100)
A =
95
45
92
41
13
1
84
23
1
73
89
20
74
52
60
82
17
5
19
44
20
48
44
40
35
60
93
67
89
61
93
81
27
46
83
76
79
91
0
19
41
1
Sort each column of A in ascending order:
c = sort(A, 1)
c =
23
1
48
44
60
45
76
61
89
79
95
82
17
40
73
91
92
93
0
5
35
41
81
89
13
19
19
20
27
60
1
41
44
46
74
93
1
20
52
67
83
84
issorted(c(:, 1))
ans =
1
Sorting the Data in Each Row
Use issorted to sort data in each row. Using the example above, if you sort each row of
A in descending order, issorted tests for an ascending sequence. You can flip the vector
to test for a sorted descending sequence:
A=floor(gallery('uniformdata',[6 7],0)*100);
r = sort(A, 2, 'descend')
r =
95
92
84
45
89
74
73
52
82
60
44
20
93
67
60
48
93
89
83
81
41
23
19
44
61
13
20
17
40
46
1
1
5
35
27
1-35
1
Matrices and Arrays
91
79
76
41
19
1
0
issorted(fliplr(r(1, :)))
ans =
1
When you specify a second output, sort returns the indices of the original matrix A
positioned in the order they appear in the output matrix.
[r,index] = sort(A, 2, 'descend');
index
index =
1
3
7
2
4
4
6
3
7
1
2
1
6
7
5
6
7
5
1
2
3
1
7
4
2
3
2
1
6
5
5
5
3
3
6
7
6
2
4
4
5
4
The second row of index contains the sequence, 4 6 3 7 1 5 2, which means that
the second row of matrix r is comprised of A(2,4), A(2,6), A(2,3), A(2,7), A(2,1),
A(2,5), and A(2,2).
Sorting Row Vectors
The sortrows function sorts the entire row of a matrix according to the elements in a
specified column, maintaining the order of elements in each row.
For example, create a random matrix A:
A = floor(gallery('uniformdata',[6 7],0)*100);
A =
95
45
92
41
13
1
84
23
1
73
89
20
74
52
60
82
17
5
19
44
20
48
44
40
35
60
93
67
89
61
93
81
27
46
83
76
79
91
0
19
41
1
Use the sortrows function to sort the rows of A in ascending order according to the
values in the first column:
r = sortrows(A,1)
1-36
Shifting and Sorting Matrices
r =
23
48
60
76
89
95
1
44
82
79
61
45
73
40
17
91
93
92
89
35
5
0
81
41
20
60
19
19
27
13
74
93
44
41
46
1
52
67
20
1
83
84
Now sort the rows of A in ascending order according to the values in the fourth column:
r = sortrows(A,4)
r =
76
79
91
60
82
17
48
44
40
95
45
92
89
61
93
23
1
73
0
5
35
41
81
89
19
19
60
13
27
20
41
44
93
1
46
74
1
20
67
84
83
52
1-37
1
Matrices and Arrays
Operating on Diagonal Matrices
In this section...
“Diagonal Matrix Functions” on page 1-38
“Constructing a Matrix from a Diagonal Vector” on page 1-38
“Returning a Triangular Portion of a Matrix” on page 1-39
“Concatenating Matrices Diagonally” on page 1-39
Diagonal Matrix Functions
There are several MATLAB functions that work specifically on diagonal matrices.
Function
Description
blkdiag
Construct a block diagonal matrix from input arguments.
diag
Return a diagonal matrix or the diagonals of a matrix.
trace
Compute the sum of the elements on the main diagonal.
tril
Return the lower triangular part of a matrix.
triu
Return the upper triangular part of a matrix.
Constructing a Matrix from a Diagonal Vector
The diag function has two operations that it can perform. You can use it to generate a
diagonal matrix:
A = diag([12:4:32])
A =
12
0
0
0
16
0
0
0
20
0
0
0
0
0
0
0
0
0
0
0
0
24
0
0
0
0
0
0
28
0
0
0
0
0
0
32
You can also use the diag function to scan an existing matrix and return the values
found along one of the diagonals:
A = magic(5)
1-38
Operating on Diagonal Matrices
A =
17
23
4
10
11
24
5
6
12
18
diag(A, 2)
ans =
1
14
22
1
7
13
19
25
8
14
20
21
2
15
16
22
3
9
% Return contents of second diagonal of A
Returning a Triangular Portion of a Matrix
The tril and triu functions return a triangular portion of a matrix, the former
returning the piece from the lower left and the latter from the upper right. By default,
the main diagonal of the matrix divides these two segments. You can use an alternate
diagonal by specifying an offset from the main diagonal as a second input argument:
A = magic(6);
B = tril(A, -1)
B =
0
0
0
3
0
0
31
9
0
8
28
33
30
5
34
4
36
29
0
0
0
0
12
13
0
0
0
0
0
18
0
0
0
0
0
0
Concatenating Matrices Diagonally
You can diagonally concatenate matrices to form a composite matrix using the blkdiag
function. See “Creating a Block Diagonal Matrix” on page 1-8 for more information on
how this works.
1-39
1
Matrices and Arrays
Empty Matrices, Scalars, and Vectors
In this section...
“Overview” on page 1-40
“The Empty Matrix” on page 1-41
“Scalars” on page 1-43
“Vectors” on page 1-44
Overview
Although matrices are two dimensional, they do not always appear to have a rectangular
shape. A 1-by-8 matrix, for example, has two dimensions yet is linear. These matrices are
described in the following sections:
• “The Empty Matrix” on page 1-41
An empty matrix has one or more dimensions that are equal to zero. A twodimensional matrix with both dimensions equal to zero appears in the MATLAB
application as []. The expression A = [] assigns a 0-by-0 empty matrix to A.
• “Scalars” on page 1-43
A scalar is 1-by-1 and appears in MATLAB as a single real or complex number (e.g., 7,
583.62, -3.51, 5.46097e-14, 83+4i).
• “Vectors” on page 1-44
A vector is 1-by-n or n-by-1, and appears in MATLAB as a row or column of real or
complex numbers:
Column Vector
53.2
87.39
4-12i
43.9
1-40
Row Vector
53.2 87.39 4-12i 43.9
Empty Matrices, Scalars, and Vectors
The Empty Matrix
A matrix having at least one dimension equal to zero is called an empty matrix. The
simplest empty matrix is 0-by-0 in size. Examples of more complex matrices are those of
dimension 0-by-5 or 10-by-0.
To create a 0-by-0 matrix, use the square bracket operators with no value specified:
A = [];
whos A
Name
A
Size
Bytes
0x0
0
Class
double array
You can create empty matrices (and arrays) of other sizes using the zeros, ones, rand,
or eye functions. To create a 0-by-5 matrix, for example, use
A = zeros(0,5)
Operating on an Empty Matrix
The basic model for empty matrices is that any operation that is defined for m-by-n
matrices, and that produces a result whose dimension is some function of m and n, should
still be allowed when m or n is zero. The size of the result of this operation is consistent
with the size of the result generated when working with nonempty values, but instead is
evaluated at zero.
For example, horizontal concatenation
C = [A B]
requires that A and B have the same number of rows. So if A is m-by-n and B is m-by-p,
then C is m-by-(n+p). This is still true if m, n, or p is zero.
As with all matrices in MATLAB, you must follow the rules concerning compatible
dimensions. In the following example, an attempt to add a 1-by-3 matrix to a 0-by-3
empty matrix results in an error:
[1 2 3] + ones(0,3)
Error using +
Matrix dimensions must agree.
1-41
1
Matrices and Arrays
Common Operations
The following operations return zero on an empty array:
A = [];
size(A), length(A), numel(A), any(A), sum(A)
These operations return a nonzero value on an empty array :
A = [];
ndims(A), isnumeric(A), isreal(A), isfloat(A), isempty(A), ...
all(A), prod(A)
Using Empty Matrices in Relational Operations
You can use empty matrices in relational operations such as “equal to” (==) or “greater
than” (>) as long as both operands have the same dimensions, or the nonempty operand
is scalar. The result of any relational operation involving an empty matrix is the empty
matrix. Even comparing an empty matrix for equality to itself does not return true, but
instead yields an empty matrix:
x = ones(0,3);
y = x;
y == x
ans =
Empty matrix: 0-by-3
Using Empty Matrices in Logical Operations
MATLAB has two distinct types of logical operators:
• Short-circuit (&&, ||) — Used in testing multiple logical conditions (e.g., x >= 50 &&
x < 100) where each condition evaluates to a scalar true or false.
• Element-wise (&, |) — Performs a logical AND, OR, or NOT on each element of a
matrix or array.
Short-circuit Operations
The rule for operands used in short-circuit operations is that each operand must be
convertible to a logical scalar value. Because of this rule, empty matrices cannot be used
in short-circuit logical operations. Such operations return an error.
The only exception is in the case where MATLAB can determine the result of a logical
statement without having to evaluate the entire expression. This is true for the following
1-42
Empty Matrices, Scalars, and Vectors
two statements because the result of the entire statements are known by considering just
the first term:
true || []
ans =
1
false && []
ans =
0
Element-wise Operations
Unlike the short-circuit operators, all element-wise operations on empty matrices are
considered valid as long as the dimensions of the operands agree, or the nonempty
operand is scalar. Element-wise operations on empty matrices always return an empty
matrix:
true | []
ans =
[]
Note This behavior is consistent with the way MATLAB does scalar expansion with
binary operators, wherein the nonscalar operand determines the size of the result.
Scalars
Any individual real or complex number is represented in MATLAB as a 1-by-1 matrix
called a scalar value:
A = 5;
ndims(A)
ans =
2
% Check number of dimensions in A
size(A)
ans =
1
% Check value of row and column dimensions
1
Use the isscalar function to tell if a variable holds a scalar value:
isscalar(A)
1-43
1
Matrices and Arrays
ans =
1
Vectors
Matrices with one dimension equal to one and the other greater than one are called
vectors. Here is an example of a numeric vector:
A = [5.73 2-4i 9/7 25e3 .046 sqrt(32) 8j];
size(A)
ans =
1
% Check value of row and column dimensions
7
You can construct a vector out of other vectors, as long as the critical dimensions agree.
All components of a row vector must be scalars or other row vectors. Similarly, all
components of a column vector must be scalars or other column vectors:
A = [29 43 77 9 21];
B = [0 46 11];
C = [A 5 ones(1,3) B]
C =
29
43
77
9
21
5
1
1
1
0
46
11
Concatenating an empty matrix to a vector has no effect on the resulting vector. The
empty matrix is ignored in this case:
A = [5.36; 7.01; []; 9.44]
A =
5.3600
7.0100
9.4400
Use the isvector function to tell if a variable holds a vector:
isvector(A)
ans =
1
1-44
Full and Sparse Matrices
Full and Sparse Matrices
In this section...
“Overview” on page 1-45
“Sparse Matrix Functions” on page 1-45
Overview
It is not uncommon to have matrices with a large number of zero-valued elements and,
because the MATLAB software stores zeros in the same way it stores any other numeric
value, these elements can use memory space unnecessarily and can sometimes require
extra computing time.
Sparse matrices provide a way to store data that has a large percentage of zero elements
more efficiently. While full matrices internally store every element in memory regardless
of value, sparse matrices store only the nonzero elements and their row indices. Using
sparse matrices can significantly reduce the amount of memory required for data storage.
You can create sparse matrices for the double and logical classes. All MATLAB builtin arithmetic, logical, and indexing operations can be applied to sparse matrices, or
to mixtures of sparse and full matrices. Operations on sparse matrices return sparse
matrices and operations on full matrices return full matrices.
For more information about the computational advantages and construction of sparse
matrices, see “Memory Management” on page 4-2 and “Creating Sparse Matrices” on
page 4-4.
Sparse Matrix Functions
This table shows some of the functions most commonly used when working with sparse
matrices.
Function
Description
full
Convert a sparse matrix to a full matrix.
issparse
Determine if a matrix is sparse.
nnz
Return the number of nonzero matrix elements.
nonzeros
Return the nonzero elements of a matrix.
1-45
1
Matrices and Arrays
1-46
Function
Description
nzmax
Return the amount of storage allocated for nonzero elements.
spalloc
Allocate space for a sparse matrix.
sparse
Create a sparse matrix or convert full to sparse.
speye
Create a sparse identity matrix.
sprand
Create a sparse uniformly distributed random matrix.
Multidimensional Arrays
Multidimensional Arrays
In this section...
“Overview” on page 1-47
“Creating Multidimensional Arrays” on page 1-49
“Accessing Multidimensional Array Properties” on page 1-52
“Indexing Multidimensional Arrays” on page 1-52
“Reshaping Multidimensional Arrays” on page 1-56
“Permuting Array Dimensions” on page 1-58
“Computing with Multidimensional Arrays” on page 1-60
“Organizing Data in Multidimensional Arrays” on page 1-62
“Multidimensional Cell Arrays” on page 1-63
“Multidimensional Structure Arrays” on page 1-64
Overview
An array having more than two dimensions is called a multidimensional array in the
MATLAB application. Multidimensional arrays in MATLAB are an extension of the
normal two-dimensional matrix. Matrices have two dimensions: the row dimension and
the column dimension.
You can access a two-dimensional matrix element with two subscripts: the first
representing the row index, and the second representing the column index.
Multidimensional arrays use additional subscripts for indexing. A three-dimensional
array, for example, uses three subscripts:
• The first references array dimension 1, the row.
1-47
1
Matrices and Arrays
• The second references dimension 2, the column.
• The third references dimension 3. This illustration uses the concept of a page to
represent dimensions 3 and higher.
To access the element in the second row, third column of page 2, for example, you use the
subscripts (2,3,2).
As you add dimensions to an array, you also add subscripts. A four-dimensional array, for
example, has four subscripts. The first two reference a row-column pair; the second two
access the third and fourth dimensions of data.
Most of the operations that you can perform on matrices (i.e., two-dimensional arrays)
can also be done on multidimensional arrays.
Note The general multidimensional array functions reside in the datatypes directory.
1-48
Multidimensional Arrays
Creating Multidimensional Arrays
You can use the same techniques to create multidimensional arrays that you use for twodimensional matrices. In addition, MATLAB provides a special concatenation function
that is useful for building multidimensional arrays.
This section discusses
• “Creating and Extending Multidimensional Arrays Using Indexed Assignment” on
page 1-49
• “Generating Arrays Using MATLAB Functions” on page 1-50
• “Building Multidimensional Arrays with the cat Function” on page 1-51
Creating and Extending Multidimensional Arrays Using Indexed Assignment
You can create a multidimensional array by creating a 2-D array and extending it.
Create a 2-D array A and extend A to a 3-D array using indexed assignment:
A = [5 7 8; 0 1 9; 4 3 6];
A(:,:,2) = [1 0 4; 3 5 6; 9 8 7]
A(:,:,1) =
5
7
0
1
4
3
8
9
6
A(:,:,2) =
1
0
3
5
9
8
4
6
7
You can extend an array by assigning a single value to the new elements. MATLAB
expands the scalar value to match the dimensions of the addressed elements. This
expansion is called scalar expansion.
Extend A by a third page using scalar expansion.
A(:,:,3) = 5
A(:,:,1) =
5
7
0
1
4
3
8
9
6
1-49
1
Matrices and Arrays
A(:,:,2) =
1
0
3
5
9
8
A(:,:,3) =
5
5
5
5
5
5
4
6
7
5
5
5
To extend the rows, columns, or pages of an array, use similar assignment statements.
The dimensions of arrays on the right side and the left side of the assignment must be
the same.
Extend A into a 3-by-3-by-3-by-2, four-dimensional array. In the first assignment,
MATLAB pads A to fill the unassigned elements in the extended dimension with zeros.
The next two assignments replace the zeros with the specified values.
A(:,:,1,2) = [1 2 3; 4 5 6; 7 8 9];
A(:,:,2,2) = [9 8 7; 6 5 4; 3 2 1];
A(:,:,3,2) = [1 0 1; 1 1 0; 0 1 1];
Generating Arrays Using MATLAB Functions
You can use MATLAB functions such as randn, ones, and zeros to generate
multidimensional arrays in the same way you use them for two-dimensional arrays.
Each argument you supply represents the size of the corresponding dimension in the
resulting array. For example, to create a 4-by-3-by-2 array of normally distributed
random numbers:
B = randn(4,3,2)
To generate an array filled with a single constant value, use the repmat function.
repmat replicates an array (in this case, a 1-by-1 array) through a vector of array
dimensions.
B = repmat(5, [3 4 2])
1-50
B(:,:,1) =
5
5
5
5
5
5
5
5
5
5
5
5
B(:,:,2) =
5
5
5
5
Multidimensional Arrays
5
5
5
5
5
5
5
5
Note Any dimension of an array can have size zero, making it a form of empty array. For
example, 10-by-0-by-20 is a valid size for a multidimensional array.
Building Multidimensional Arrays with the cat Function
The cat function is a simple way to build multidimensional arrays; it concatenates a list
of arrays along a specified dimension:
B = cat(dim, A1, A2...)
where A1, A2, and so on are the arrays to concatenate, and dim is the dimension along
which to concatenate the arrays.
For example, to create a new array with cat:
B = cat(3, [2 8; 0 5], [1 3; 7 9])
B(:,:,1) =
2
8
0
5
B(:,:,2) =
1
3
7
9
The cat function accepts any combination of existing and new data. In addition, you can
nest calls to cat. The lines below, for example, create a four-dimensional array.
A = cat(3, [9 2; 6 5], [7 1; 8 4])
B = cat(3, [3 5; 0 1], [5 6; 2 1])
D = cat(4, A, B, cat(3, [1 2; 3 4], [4 3;2 1]))
cat automatically adds subscripts of 1 between dimensions, if necessary. For example, to
create a 2-by-2-by-1-by-2 array, enter
C = cat(4, [1 2; 4 5], [7 8; 3 2])
In the previous case, cat inserts as many singleton dimensions as needed to create a
four-dimensional array whose last dimension is not a singleton dimension. If the dim
1-51
1
Matrices and Arrays
argument had been 5, the previous statement would have produced a 2-by-2-by-1-by-1by-2 array. This adds additional 1s to indexing expressions for the array. To access the
value 8 in the four-dimensional case, use
Accessing Multidimensional Array Properties
You can use the following MATLAB functions to get information about multidimensional
arrays you have created.
• size — Returns the size of each array dimension.
size(C)
ans =
2
2
rows columns
1
dim3
2
dim4
• ndims — Returns the number of dimensions in the array.
ndims(C)
ans =
4
• whos — Provides information on the format and storage of the array.
whos
Name
Size
A
B
C
D
2x2x2
2x2x2
4-D
4-D
Bytes
64
64
64
192
Class
double
double
double
double
array
array
array
array
Grand total is 48 elements using 384 bytes
Indexing Multidimensional Arrays
Many of the concepts that apply to two-dimensional matrices extend to multidimensional
arrays as well.
1-52
Multidimensional Arrays
To access a single element of a multidimensional array, use integer subscripts. Each
subscript indexes a dimension—the first indexes the row dimension, the second indexes
the column dimension, the third indexes the first page dimension, and so on.
Consider a 10-by-5-by-3 array nddata of random integers:
nddata = fix(8 * randn(10,5,3));
To access element (3,2) on page 2 of nddata, for example, use nddata(3,2,2).
You can use vectors as array subscripts. In this case, each vector element must be a valid
subscript, that is, within the bounds defined by the dimensions of the array. To access
elements (2,1), (2,3), and (2,4) on page 3 of nddata, use
nddata(2,[1 3 4],3);
The Colon and Multidimensional Array Indexing
The MATLAB colon indexing extends to multidimensional arrays. For example, to access
the entire third column on page 2 of nddata, use nddata(:,3,2).
The colon operator is also useful for accessing other subsets of data. For example,
nddata(2:3,2:3,1) results in a 2-by-2 array, a subset of the data on page 1 of nddata.
This matrix consists of the data in rows 2 and 3, columns 2 and 3, on the first page of the
array.
The colon operator can appear as an array subscript on both sides of an assignment
statement. For example, to create a 4-by-4 array of zeros:
C = zeros(4, 4)
Now assign a 2-by-2 subset of array nddata to the four elements in the center of C.
C(2:3,2:3) = nddata(2:3,1:2,2)
Linear Indexing with Multidimensional Arrays
MATLAB linear indexing also extends to multidimensional arrays. In this case,
MATLAB operates on a page-by-page basis to create the storage column, again
appending elements columnwise. See “Linear Indexing” on page 1-12 for an introduction
to this topic.
For example, consider a 5-by-4-by-3-by-2 array C.
1-53
1
Matrices and Arrays
Again, a single subscript indexes directly into this column. For example, C(4) produces
the result
1-54
Multidimensional Arrays
ans =
0
If you specify two subscripts (i,j) indicating row-column indices, MATLAB calculates
the offset as described above. Two subscripts always access the first page of a
multidimensional array, provided they are within the range of the original array
dimensions.
If more than one subscript is present, all subscripts must conform to the original array
dimensions. For example, C(6,2) is invalid because all pages of C have only five rows.
If you specify more than two subscripts, MATLAB extends its indexing scheme
accordingly. For example, consider four subscripts (i,j,k,l) into a four-dimensional
array with size [d1 d2 d3 d4]. MATLAB calculates the offset into the storage column
by
(l-1)(d3)(d2)(d1)+(k-1)(d2)(d1)+(j-1)(d1)+i
For example, if you index the array C using subscripts (3, 4, 2, 1), MATLAB returns the
value 5 (index 38 in the storage column).
In general, the offset formula for an array with dimensions [d1 d2 d3 ... dn] using
any subscripts (s1 s2 s3 ... sn) is
(sn-1)(dn-1)(dn-2)...(d1)+(sn-1-1)(dn-2)...(d1)+...+(s2-1)(d1)+s1
Because of this scheme, you can index an array using any number of subscripts. You
can append any number of 1s to the subscript list because these terms become zero. For
example,
C(3,2,1,1,1,1,1,1)
is equivalent to
C(3,2)
Avoiding Ambiguity in Multidimensional Indexing
Some assignment statements, such as
A(:,:,2) = 1:10
are ambiguous because they do not provide enough information about the shape of the
dimension to receive the data. In the case above, the statement tries to assign a onedimensional vector to a two-dimensional destination. MATLAB produces an error for
1-55
1
Matrices and Arrays
such cases. To resolve the ambiguity, be sure you provide enough information about the
destination for the assigned data, and that both data and destination have the same
shape. For example:
A(1,:,2) = 1:10;
Reshaping Multidimensional Arrays
Unless you change its shape or size, a MATLAB array retains the dimensions specified
at its creation. You change array size by adding or deleting elements. You change
array shape by re-specifying the array's row, column, or page dimensions while
retaining the same elements. The reshape function performs the latter operation. For
multidimensional arrays, its form is
B = reshape(A,[s1 s2 s3 ...])
s1, s2, and so on represent the desired size for each dimension of the reshaped matrix.
Note that a reshaped array must have the same number of elements as the original array
(that is, the product of the dimension sizes is constant).
M
reshape(M, [6 5])
The reshape function operates in a columnwise manner. It creates the reshaped matrix
by taking consecutive elements down each column of the original data construct.
C
1-56
reshape(C, [6 2])
Multidimensional Arrays
Here are several new arrays from reshaping nddata:
B = reshape(nddata, [6 25])
C = reshape(nddata, [5 3 10])
D = reshape(nddata, [5 3 2 5])
Removing Singleton Dimensions
MATLAB automatically removes trailing singleton dimensions (dimensions whose sizes
are equal to 1) from all multidimensional arrays. For example, if you attempt to create
an array of size 3-by-2-by-1-by-1, perhaps with the command rand(3,2,1,1), then
MATLAB strips away the singleton dimensions at the end of the array and creates a 3by-2 matrix. This is because every array technically has an infinite number of trailing
singleton dimensions. A 3-by-2 array is the same as an array with size 3-by-2-by-1-by-1by-1-by-...
For example, consider the following 2-by-2 matrix, A.
A = eye(2)
A =
1
0
0
1
A is a 2-by-2 identity matrix.
Find the size of the fourth dimension of A.
size(A,4)
ans =
1
Although A is a 2-by-2 matrix, the size of the fourth dimension in A is 1. In fact, the size
of each dimension beyond the second is 1.
The first two dimensions of an array are never stripped away, since they are always
relevant.
size(3)
1-57
1
Matrices and Arrays
ans =
1
1
Even a scalar in MATLAB is a 1-by-1 matrix.
MATLAB creates singleton dimensions if you explicitly specify them when you create or
reshape an array, or if you perform a calculation that results in an array dimension of
one:
B = repmat(5, [2 3 1 4]);
size(B)
ans =
2
3
1
4
The squeeze function removes singleton dimensions from an array:
C = squeeze(B);
size(C)
ans =
2
3
4
The squeeze function does not affect two-dimensional arrays; row vectors remain rows.
Permuting Array Dimensions
The permute function reorders the dimensions of an array:
B = permute(A, dims);
dims is a vector specifying the new order for the dimensions of A, where 1 corresponds
to the first dimension (rows), 2 corresponds to the second dimension (columns), 3
corresponds to pages, and so on.
1-58
Multidimensional Arrays
For a more detailed look at the permute function, consider a four-dimensional array A
of size 5-by-4-by-3-by-2. Rearrange the dimensions, placing the column dimension first,
followed by the second page dimension, the first page dimension, then the row dimension.
The result is a 4-by-2-by-3-by-5 array.
You can think of permute's operation as an extension of the transpose function, which
switches the row and column dimensions of a matrix. For permute, the order of the
1-59
1
Matrices and Arrays
input dimension list determines the reordering of the subscripts. In the example above,
element (4,2,1,2) of A becomes element (2,2,1,4) of B, element (5,4,3,2) of A
becomes element (4,2,3,5) of B, and so on.
Inverse Permutation
The ipermute function is the inverse of permute. Given an input array A and a vector of
dimensions v, ipermute produces an array B such that permute(B,v) returns A.
For example, these statements create an array E that is equal to the input array C:
D = ipermute(C, [1 4 2 3]);
E = permute(D, [1 4 2 3])
You can obtain the original array after permuting it by calling ipermute with the same
vector of dimensions.
Computing with Multidimensional Arrays
Many of the MATLAB computational and mathematical functions accept
multidimensional arrays as arguments. These functions operate on specific dimensions of
multidimensional arrays; that is, they operate on individual elements, on vectors, or on
matrices.
Operating on Vectors
Functions that operate on vectors, like sum, mean, and so on, by default typically
work on the first nonsingleton dimension of a multidimensional array. Most of these
functions optionally let you specify a particular dimension on which to operate. There are
exceptions, however. For example, the cross function, which finds the cross product of
two vectors, works on the first nonsingleton dimension having length 3.
Note In many cases, these functions have other restrictions on the input arguments —
for example, some functions that accept multiple arrays require that the arrays be the
same size. Refer to the online help for details on function arguments.
Operating Element-by-Element
MATLAB functions that operate element-by-element on two-dimensional arrays, like
the trigonometric and exponential functions in the elfun directory, work in exactly the
1-60
Multidimensional Arrays
same way for multidimensional cases. For example, the sin function returns an array
the same size as the function's input argument. Each element of the output array is the
sine of the corresponding element of the input array.
Similarly, the arithmetic, logical, and relational operators all work with corresponding
elements of multidimensional arrays that are the same size in every dimension. If one
operand is a scalar and one an array, the operator applies the scalar to each element of
the array.
Operating on Planes and Matrices
Functions that operate on planes or matrices, such as the linear algebra and matrix
functions in the matfun directory, do not accept multidimensional arrays as arguments.
That is, you cannot use the functions in the matfun directory, or the array operators *,
^, \, or /, with multidimensional arguments. Supplying multidimensional arguments or
operands in these cases results in an error.
You can use indexing to apply a matrix function or operator to matrices within a
multidimensional array. For example, create a three-dimensional array A:
A = cat(3, [1 2 3; 9 8 7; 4 6 5], [0 3 2; 8 8 4; 5 3 5], ...
[6 4 7; 6 8 5; 5 4 3]);
Applying the eig function to the entire multidimensional array results in an error:
eig(A)
??? Undefined function or method 'eig' for input
arguments of type 'double' and attributes 'full 3d real'.
You can, however, apply eig to planes within the array. For example, use colon notation
to index just one page (in this case, the second) of the array:
eig(A(:,:,2))
ans =
12.9129
-2.6260
2.7131
Note In the first case, subscripts are not colons; you must use squeeze to avoid an
error. For example, eig(A(2,:,:)) results in an error because the size of the input
is [1 3 3]. The expression eig(squeeze(A(2,:,:))), however, passes a valid twodimensional matrix to eig.
1-61
1
Matrices and Arrays
Organizing Data in Multidimensional Arrays
You can use multidimensional arrays to represent data in two ways:
• As planes or pages of two-dimensional data. You can then treat these pages as
matrices.
• As multivariate or multidimensional data. For example, you might have a fourdimensional array where each element corresponds to either a temperature or air
pressure measurement taken at one of a set of equally spaced points in a room.
For example, consider an RGB image. For a single image, a multidimensional array is
probably the easiest way to store and access data.
To access an entire plane of the image, use
redPlane = RGB(:,:,1);
1-62
Multidimensional Arrays
To access a subimage, use
subimage = RGB(20:40,50:85,:);
The RGB image is a good example of data that needs to be accessed in planes for
operations like display or filtering. In other instances, however, the data itself might be
multidimensional. For example, consider a set of temperature measurements taken at
equally spaced points in a room. Here the location of each value is an integral part of
the data set—the physical placement in three-space of each element is an aspect of the
information. Such data also lends itself to representation as a multidimensional array.
Now to find the average of all the measurements, use
mean(mean(mean(TEMP)));
To obtain a vector of the “middle” values (element (2,2)) in the room on each page, use
B = TEMP(2,2,:);
Multidimensional Cell Arrays
Like numeric arrays, the framework for multidimensional cell arrays in MATLAB is an
extension of the two-dimensional cell array model. You can use the cat function to build
multidimensional cell arrays, just as you use it for numeric arrays.
For example, create a simple three-dimensional cell array C:
A{1,1} = [1 2;4 5];
A{1,2} = 'Name';
A{2,1} = 2-4i;
1-63
1
Matrices and Arrays
A{2,2} = 7;
B{1,1} = 'Name2';
B{1,2} = 3;
B{2,1} = 0:1:3;
B{2,2} = [4 5]';
C = cat(3, A, B);
The subscripts for the cells of C look like
Multidimensional Structure Arrays
Multidimensional structure arrays are extensions of rectangular structure arrays. Like
other types of multidimensional arrays, you can build them using direct assignment or
the cat function:
patient(1,1,1).name = 'John Doe';
patient(1,1,1).billing = 127.00;
patient(1,1,1).test = [79 75 73; 180
patient(1,2,1).name = 'Ann Lane';
patient(1,2,1).billing = 28.50;
patient(1,2,1).test = [68 70 68; 118
patient(1,1,2).name = 'Al Smith';
patient(1,1,2).billing = 504.70;
patient(1,1,2).test = [80 80 80; 153
patient(1,2,2).name = 'Dora Jones';
patient(1,2,2).billing = 1173.90;
patient(1,2,2).test = [73 73 75; 103
1-64
178 177.5; 220 210 205];
118 119; 172 170 169];
153 154; 181 190 182];
103 102; 201 198 200];
Multidimensional Arrays
Applying Functions to Multidimensional Structure Arrays
To apply functions to multidimensional structure arrays, operate on fields and field
elements using indexing. For example, find the sum of the columns of the test array in
patient(1,1,2):
sum((patient(1,1,2).test));
Similarly, add all the billing fields in the patient array:
total = sum([patient.billing]);
1-65
1
Matrices and Arrays
Summary of Matrix and Array Functions
This section summarizes the principal functions used in creating and handling matrices.
Most of these functions work on multidimensional arrays as well.
Functions to Create a Matrix
Function
Description
[a,b] or [a;b]
Create a matrix from specified elements, or concatenate matrices
together.
accumarray
Construct a matrix using accumulation.
blkdiag
Construct a block diagonal matrix.
cat
Concatenate matrices along the specified dimension.
diag
Create a diagonal matrix from a vector.
horzcat
Concatenate matrices horizontally.
magic
Create a square matrix with rows, columns, and diagonals that
add up to the same number.
ones
Create a matrix of all ones.
rand
Create a matrix of uniformly distributed random numbers.
repmat
Create a new matrix by replicating or tiling another.
vertcat
Concatenate two or more matrices vertically.
zeros
Create a matrix of all zeros.
Functions to Modify the Shape of a Matrix
1-66
Function
Description
ctranspose
Flip a matrix about the main diagonal and replace each element
with its complex conjugate.
flip
Flip a matrix along the specified dimension.
fliplr
Flip a matrix about a vertical axis.
flipud
Flip a matrix about a horizontal axis.
reshape
Change the dimensions of a matrix.
rot90
Rotate a matrix by 90 degrees.
Summary of Matrix and Array Functions
Function
Description
transpose
Flip a matrix about the main diagonal.
Functions to Find the Structure or Shape of a Matrix
Function
Description
isempty
Return true for 0-by-0 or 0-by-n matrices.
isscalar
Return true for 1-by-1 matrices.
issparse
Return true for sparse matrices.
isvector
Return true for 1-by-n matrices.
length
Return the length of a vector.
ndims
Return the number of dimensions in a matrix.
numel
Return the number of elements in a matrix.
size
Return the size of each dimension.
Functions to Determine Class
Function
Description
iscell
Return true if the matrix is a cell array.
ischar
Return true if matrix elements are characters or strings.
isfloat
Determine if input is a floating point array.
isinteger
Determine if input is an integer array.
islogical
Return true if matrix elements are logicals.
isnumeric
Return true if matrix elements are numeric.
isreal
Return true if matrix elements are real numbers.
isstruct
Return true if matrix elements are MATLAB structures.
Functions to Sort and Shift Matrix Elements
Function
Description
circshift
Circularly shift matrix contents.
issorted
Return true if the matrix elements are sorted.
sort
Sort elements in ascending or descending order.
1-67
1
Matrices and Arrays
Function
Description
sortrows
Sort rows in ascending order.
Functions That Work on Diagonals of a Matrix
Function
Description
blkdiag
Construct a block diagonal matrix.
diag
Return the diagonals of a matrix.
trace
Compute the sum of the elements on the main diagonal.
tril
Return the lower triangular part of a matrix.
triu
Return the upper triangular part of a matrix.
Functions to Change the Indexing Style
Function
Description
ind2sub
Convert a linear index to a row-column index.
sub2ind
Convert a row-column index to a linear index.
Functions for Working with Multidimensional Arrays
1-68
Function
Description
cat
Concatenate arrays.
circshift
Shift array circularly.
ipermute
Inverse permute array dimensions.
ndgrid
Generate arrays for n-dimensional functions and interpolation.
ndims
Return the number of array dimensions.
permute
Permute array dimensions.
shiftdim
Shift array dimensions.
squeeze
Remove singleton dimensions.
2
Linear Algebra
• “Matrices in the MATLAB Environment” on page 2-2
• “Systems of Linear Equations” on page 2-11
• “Inverses and Determinants” on page 2-23
• “Factorizations” on page 2-27
• “Powers and Exponentials” on page 2-35
• “Eigenvalues” on page 2-39
• “Singular Values” on page 2-42
2
Linear Algebra
Matrices in the MATLAB Environment
In this section...
“Creating Matrices” on page 2-2
“Adding and Subtracting Matrices” on page 2-3
“Vector Products and Transpose” on page 2-4
“Multiplying Matrices” on page 2-6
“Identity Matrix” on page 2-8
“Kronecker Tensor Product” on page 2-8
“Vector and Matrix Norms” on page 2-9
“Using Multithreaded Computation with Linear Algebra Functions” on page 2-10
Creating Matrices
The MATLAB environment uses the term matrix to indicate a variable containing real
or complex numbers arranged in a two-dimensional grid. An array is, more generally,
a vector, matrix, or higher dimensional grid of numbers. All arrays in MATLAB are
rectangular, in the sense that the component vectors along any dimension are all the
same length.
Symbolic Math Toolbox™ software extends the capabilities of MATLAB software to
matrices of mathematical expressions.
MATLAB has dozens of functions that create different kinds of matrices. There are two
functions you can use to create a pair of 3-by-3 example matrices for use throughout this
chapter. The first example is symmetric:
A = pascal(3)
A =
1
1
1
1
2
3
1
3
6
The second example is not symmetric:
B = magic(3)
B =
2-2
Matrices in the MATLAB Environment
8
3
4
1
5
9
6
7
2
Another example is a 3-by-2 rectangular matrix of random integers:
C = fix(10*rand(3,2))
C =
9
2
6
4
8
7
A column vector is an m-by-1 matrix, a row vector is a 1-by-n matrix, and a scalar is a 1by-1 matrix. The statements
u = [3; 1; 4]
v = [2 0 -1]
s = 7
produce a column vector, a row vector, and a scalar:
u =
3
1
4
v =
2
0
-1
s =
7
For more information about creating and working with matrices, see “Creating and
Concatenating Matrices” on page 1-2.
Adding and Subtracting Matrices
Addition and subtraction of matrices is defined just as it is for arrays, element by
element. Adding A to B, and then subtracting A from the result recovers B:
A = pascal(3);
2-3
2
Linear Algebra
B = magic(3);
X = A + B
X =
9
4
5
2
7
12
7
10
8
1
5
9
6
7
2
Y = X - A
Y =
8
3
4
Addition and subtraction require both matrices to have the same dimension, or one of
them be a scalar. If the dimensions are incompatible, an error results:
C = fix(10*rand(3,2))
X = A + C
Error using plus
Matrix dimensions must agree.
w = v + s
w =
9
7
6
Vector Products and Transpose
A row vector and a column vector of the same length can be multiplied in either order.
The result is either a scalar, the inner product, or a matrix, the outer product :
u = [3; 1; 4];
v = [2 0 -1];
x = v*u
x =
2
X = u*v
X =
6
2
2-4
0
0
-3
-1
Matrices in the MATLAB Environment
8
0
-4
For real matrices, the transpose operation interchanges aij and aji. MATLAB uses the
apostrophe operator (') to perform a complex conjugate transpose, and uses the dotapostrophe operator (.') to transpose without conjugation. For matrices containing all
real elements, the two operators return the same result.
The example matrix A is symmetric, so A' is equal to A. But, B is not symmetric:
B = magic(3);
X = B'
X =
8
1
6
3
5
7
4
9
2
Transposition turns a row vector into a column vector:
x = v'
x =
2
0
-1
If x and y are both real column vectors, the product x*y is not defined, but the two
products
x'*y
and
y'*x
are the same scalar. This quantity is used so frequently, it has three different names:
inner product, scalar product, or dot product.
For a complex vector or matrix, z, the quantity z' not only transposes the vector or
matrix, but also converts each complex element to its complex conjugate. That is, the sign
of the imaginary part of each complex element changes. So if
z = [1+2i 7-3i 3+4i; 6-2i 9i 4+7i]
z =
1.0000 + 2.0000i
7.0000 - 3.0000i
3.0000 + 4.0000i
2-5
2
Linear Algebra
6.0000 - 2.0000i
0 + 9.0000i
4.0000 + 7.0000i
then
z'
ans =
1.0000 - 2.0000i
7.0000 + 3.0000i
3.0000 - 4.0000i
6.0000 + 2.0000i
0 - 9.0000i
4.0000 - 7.0000i
The unconjugated complex transpose, where the complex part of each element retains its
sign, is denoted by z.':
z.'
ans =
1.0000 + 2.0000i
7.0000 - 3.0000i
3.0000 + 4.0000i
6.0000 - 2.0000i
0 + 9.0000i
4.0000 + 7.0000i
For complex vectors, the two scalar products x'*y and y'*x are complex conjugates of
each other, and the scalar product x'*x of a complex vector with itself is real.
Multiplying Matrices
Multiplication of matrices is defined in a way that reflects composition of the underlying
linear transformations and allows compact representation of systems of simultaneous
linear equations. The matrix product C = AB is defined when the column dimension of A
is equal to the row dimension of B, or when one of them is a scalar. If A is m-by-p and B
is p-by-n, their product C is m-by-n. The product can actually be defined using MATLAB
for loops, colon notation, and vector dot products:
A =
B =
m =
for
pascal(3);
magic(3);
3; n = 3;
i = 1:m
for j = 1:n
C(i,j) = A(i,:)*B(:,j);
end
end
MATLAB uses a single asterisk to denote matrix multiplication. The next two examples
illustrate the fact that matrix multiplication is not commutative; AB is usually not equal
to BA:
2-6
Matrices in the MATLAB Environment
X = A*B
X =
15
26
41
15
38
70
15
26
39
28
34
28
47
60
43
Y = B*A
Y =
15
15
15
A matrix can be multiplied on the right by a column vector and on the left by a row
vector:
u = [3; 1; 4];
x = A*u
x =
8
17
30
v = [2 0 -1];
y = v*B
y =
12
-7
10
Rectangular matrix multiplications must satisfy the dimension compatibility conditions:
C = fix(10*rand(3,2));
X = A*C
X =
17
31
51
19
41
70
Y = C*A
Error using mtimes
Inner matrix dimensions must agree.
2-7
2
Linear Algebra
Anything can be multiplied by a scalar:
s = 7;
w = s*v
w =
14
0
-7
Identity Matrix
Generally accepted mathematical notation uses the capital letter I to denote identity
matrices, matrices of various sizes with ones on the main diagonal and zeros elsewhere.
These matrices have the property that AI = A and IA = A whenever the dimensions are
compatible. The original version of MATLAB could not use I for this purpose because
it did not distinguish between uppercase and lowercase letters and i already served as
a subscript and as the complex unit. So an English language pun was introduced. The
function
eye(m,n)
returns an m-by-n rectangular identity matrix and eye(n) returns an n-by-n square
identity matrix.
Kronecker Tensor Product
The Kronecker product, kron(X,Y), of two matrices is the larger matrix formed from all
possible products of the elements of X with those of Y. If X is m-by-n and Y is p-by-q, then
kron(X,Y) is mp-by-nq. The elements are arranged in the following order:
[X(1,1)*Y
X(1,2)*Y
X(m,1)*Y
X(m,2)*Y
. . .
. . .
. . .
X(1,n)*Y
X(m,n)*Y]
The Kronecker product is often used with matrices of zeros and ones to build up repeated
copies of small matrices. For example, if X is the 2-by-2 matrix
X =
1
3
2
4
and I = eye(2,2) is the 2-by-2 identity matrix, then the two matrices
kron(X,I)
2-8
Matrices in the MATLAB Environment
and
kron(I,X)
are
1
0
3
0
0
1
0
3
2
0
4
0
0
2
0
4
1
3
0
0
2
4
0
0
0
0
1
3
0
0
2
4
and
Vector and Matrix Norms
The p-norm of a vector x,
1/ p
x p=
( Â xi p )
,
is computed by norm(x,p). This is defined by any value of p > 1, but the most common
values of p are 1, 2, and ∞. The default value is p = 2, which corresponds to Euclidean
length:
v = [2 0 -1];
[norm(v,1) norm(v) norm(v,inf)]
ans =
3.0000
2.2361
2.0000
The p-norm of a matrix A,
A
Ax
p
= max
x
x
p
,
p
can be computed for p = 1, 2, and ∞ by norm(A,p). Again, the default value is p = 2:
2-9
2
Linear Algebra
C = fix(10*rand(3,2));
[norm(C,1) norm(C) norm(C,inf)]
ans =
19.0000
14.8015
13.0000
Using Multithreaded Computation with Linear Algebra Functions
MATLAB software supports multithreaded computation for a number of linear algebra
and element-wise numerical functions. These functions automatically execute on
multiple threads. For a function or expression to execute faster on multiple CPUs, a
number of conditions must be true:
1
The function performs operations that easily partition into sections that execute
concurrently. These sections must be able to execute with little communication
between processes. They should require few sequential operations.
2
The data size is large enough so that any advantages of concurrent execution
outweigh the time required to partition the data and manage separate execution
threads. For example, most functions speed up only when the array contains several
thousand elements or more.
3
The operation is not memory-bound; processing time is not dominated by memory
access time. As a general rule, complicated functions speed up more than simple
functions.
The matrix multiply (X*Y) and matrix power (X^p) operators show significant increase
in speed on large double-precision arrays (on order of 10,000 elements). The matrix
analysis functions det, rcond, hess, and expm also show significant increase in speed
on large double-precision arrays.
2-10
Systems of Linear Equations
Systems of Linear Equations
In this section...
“Computational Considerations” on page 2-11
“General Solution” on page 2-12
“Square Systems” on page 2-13
“Overdetermined Systems” on page 2-15
“Underdetermined Systems” on page 2-18
“Using Multithreaded Computation with Systems of Linear Equations” on page 2-20
“Iterative Methods for Solving Systems of Linear Equations” on page 2-21
Computational Considerations
One of the most important problems in technical computing is the solution of systems of
simultaneous linear equations.
In matrix notation, the general problem takes the following form: Given two matrices A
and b, does there exist a unique matrix x, so that Ax = b or xA = b?
It is instructive to consider a 1-by-1 example. For example, does the equation
7x = 21
have a unique solution?
The answer, of course, is yes. The equation has the unique solution x = 3. The solution is
easily obtained by division:
x = 21/7 = 3.
The solution is not ordinarily obtained by computing the inverse of 7, that is 7–
1
= 0.142857..., and then multiplying 7–1 by 21. This would be more work and, if 7–1 is
represented to a finite number of digits, less accurate. Similar considerations apply to
sets of linear equations with more than one unknown; the MATLAB software solves such
equations without computing the inverse of the matrix.
Although it is not standard mathematical notation, MATLAB uses the division
terminology familiar in the scalar case to describe the solution of a general system of
simultaneous equations. The two division symbols, slash, /, and backslash, \, correspond
2-11
2
Linear Algebra
to the two MATLAB functions mrdivide and mldivide. mrdivide and mldivide are
used for the two situations where the unknown matrix appears on the left or right of the
coefficient matrix:
x = b/A
Denotes the solution to the matrix equation xA = b.
x = A\b
Denotes the solution to the matrix equation Ax = b.
Think of “dividing” both sides of the equation Ax = b or xA = b by A. The coefficient
matrix A is always in the “denominator.”
The dimension compatibility conditions for x = A\b require the two matrices A and b to
have the same number of rows. The solution x then has the same number of columns as
b and its row dimension is equal to the column dimension of A. For x = b/A, the roles of
rows and columns are interchanged.
In practice, linear equations of the form Ax = b occur more frequently than those of the
form xA = b. Consequently, the backslash is used far more frequently than the slash.
The remainder of this section concentrates on the backslash operator; the corresponding
properties of the slash operator can be inferred from the identity:
(b/A)' = (A'\b').
The coefficient matrix A need not be square. If A is m-by-n, there are three cases:
m=n
Square system. Seek an exact solution.
m>n
Overdetermined system. Find a least-squares solution.
m<n
Underdetermined system. Find a basic solution with at most
m nonzero components.
The mldivide Algorithm
The mldivide operator employs different solvers to handle different kinds of coefficient
matrices. The various cases are diagnosed automatically by examining the coefficient
matrix. For more information, see the “Algorithms” section of the mldivide reference
page.
General Solution
The general solution to a system of linear equations Ax = b describes all possible
solutions. You can find the general solution by:
2-12
Systems of Linear Equations
1
Solving the corresponding homogeneous system Ax = 0. Do this using the null
command, by typing null(A). This returns a basis for the solution space to Ax = 0.
Any solution is a linear combination of basis vectors.
2
Finding a particular solution to the nonhomogeneous system Ax = b.
You can then write any solution to Ax = b as the sum of the particular solution to Ax = b,
from step 2, plus a linear combination of the basis vectors from step 1.
The rest of this section describes how to use MATLAB to find a particular solution to
Ax = b, as in step 2.
Square Systems
The most common situation involves a square coefficient matrix A and a single right side
column vector b.
Nonsingular Coefficient Matrix
If the matrix A is nonsingular, the solution, x = A\b, is then the same size as b. For
example:
A = pascal(3);
u = [3; 1; 4];
x = A\u
x =
10
-12
5
It can be confirmed that A*x is exactly equal to u.
If A and b are square and the same size, x= A\b is also that size:
b = magic(3);
X = A\b
X =
19
-17
6
-3
4
0
-1
13
-6
It can be confirmed that A*x is exactly equal to b.
2-13
2
Linear Algebra
Both of these examples have exact, integer solutions. This is because the coefficient
matrix was chosen to be pascal(3), which is a full rank matrix (nonsingular).
Singular Coefficient Matrix
A square matrix A is singular if it does not have linearly independent columns. If A is
singular, the solution to Ax = b either does not exist, or is not unique. The backslash
operator, A\b, issues a warning if A is nearly singular and raises an error condition if it
detects exact singularity.
If A is singular and Ax = b has a solution, you can find a particular solution that is not
unique, by typing
P = pinv(A)*b
P is a pseudoinverse of A. If Ax = b does not have an exact solution, pinv(A) returns a
least-squares solution.
For example:
A = [ 1
-1
1
3
4
10
7
4
18 ]
is singular, as you can verify by typing
rank(A)
ans =
2
Since A is not full rank, it has some singular values equal to zero.
Note: For information about using pinv to solve systems with rectangular coefficient
matrices, see “Pseudoinverses” on page 2-24.
Exact Solutions
For b =[5;2;12], the equation Ax = b has an exact solution, given by
pinv(A)*b
2-14
Systems of Linear Equations
ans =
0.3850
-0.1103
0.7066
Verify that pinv(A)*b is an exact solution by typing
A*pinv(A)*b
ans =
5.0000
2.0000
12.0000
Least-Squares Solutions
However, if b = [3;6;0], Ax = b does not have an exact solution. In this case,
pinv(A)*b returns a least-squares solution. If you type
A*pinv(A)*b
ans =
-1.0000
4.0000
2.0000
you do not get back the original vector b.
You can determine whether Ax = b has an exact solution by finding the row reduced
echelon form of the augmented matrix [A b]. To do so for this example, enter
rref([A b])
ans =
1.0000
0
0
0
1.0000
0
2.2857
1.5714
0
0
0
1.0000
Since the bottom row contains all zeros except for the last entry, the equation does not
have a solution. In this case, pinv(A) returns a least-squares solution.
Overdetermined Systems
This example shows how overdetermined systems are often encountered in various kinds
of curve fitting to experimental data.
2-15
2
Linear Algebra
A quantity, y, is measured at several different values of time, t, to produce the following
observations. You can enter the data and view it in a table with the following statements.
t = [0 .3 .8 1.1 1.6 2.3]';
y = [.82 .72 .63 .60 .55 .50]';
B = table(t,y)
B =
t
___
y
____
0
0.3
0.8
1.1
1.6
2.3
0.82
0.72
0.63
0.6
0.55
0.5
Try modeling the data with a decaying exponential function
.
The preceding equation says that the vector y should be approximated by a linear
combination of two other vectors. One is a constant vector containing all ones and the
other is the vector with components exp(-t). The unknown coefficients, and , can
be computed by doing a least-squares fit, which minimizes the sum of the squares of
the deviations of the data from the model. There are six equations in two unknowns,
represented by a 6-by-2 matrix.
E = [ones(size(t)) exp(-t)]
E =
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
2-16
1.0000
0.7408
0.4493
0.3329
0.2019
0.1003
Systems of Linear Equations
Use the backslash operator to get the least-squares solution.
c = E\y
c =
0.4760
0.3413
In other words, the least-squares fit to the data is
The following statements evaluate the model at regularly spaced increments in t, and
then plot the result together with the original data:
T = (0:0.1:2.5)';
Y = [ones(size(T)) exp(-T)]*c;
plot(T,Y,'-',t,y,'o')
2-17
2
Linear Algebra
E*c is not exactly equal to y, but the difference might well be less than measurement
errors in the original data.
A rectangular matrix A is rank deficient if it does not have linearly independent columns.
If A is rank deficient, the least-squares solution to AX = B is not unique. The backslash
operator, A\B, issues a warning if A is rank deficient and produces a least-squares
solution if the system has no solution and a basic solution if the system has infinitely
many solutions.
Underdetermined Systems
This example shows how the solution to underdetermined systems is not unique.
Underdetermined linear systems involve more unknowns than equations. The matrix
2-18
Systems of Linear Equations
left division operation in MATLAB finds a basic solution, which has at most m nonzero
components for an m-by-n coefficient matrix.
Here is a small, random example:
R = [6 8 7 3; 3 5 4 1]
rng(0);
b = randi(8,2,1)
R =
6
3
8
5
7
4
3
1
b =
7
8
The linear system Rp = b involves two equations in four unknowns. Since the coefficient
matrix contains small integers, it is appropriate to use the format command to display
the solution in rational format. The particular solution is obtained with
format rat
p = R\b
p =
0
17/7
0
-29/7
One of the nonzero components is p(2) because R(:,2) is the column of R with largest
norm. The other nonzero component is p(4) because R(:,4) dominates after R(:,2) is
eliminated.
The complete general solution to the underdetermined system can be characterized by
adding p to an arbitrary linear combination of the null space vectors, which can be found
using the null function with an option requesting a rational basis.
Z = null(R,'r')
Z =
2-19
2
Linear Algebra
-1/2
-1/2
1
0
-7/6
1/2
0
1
It can be confirmed that R*Z is zero and that the residual R*x - b is small for any
vector x, where
x = p + Z*q.
Since the columns of Z are the null space vectors, the product Z*q is a linear combination
of those vectors:
v
Z * q = ( x1
v Ê uˆ
v
v
x2 ) Á ˜ = ux1 + wx2 .
w
Ë ¯
To illustrate, choose an arbitrary q and construct x.
q = [-2; 1];
x = p + Z*q;
Calculate the norm of the residual.
format short
norm(R*x - b)
ans =
2.6645e-15
Using Multithreaded Computation with Systems of Linear Equations
MATLAB software supports multithreaded computation for a number of linear algebra
and element-wise numerical functions. These functions automatically execute on
multiple threads. For a function or expression to execute faster on multiple CPUs, a
number of conditions must be true:
2-20
1
The function performs operations that easily partition into sections that execute
concurrently. These sections must be able to execute with little communication
between processes. They should require few sequential operations.
2
The data size is large enough so that any advantages of concurrent execution
outweigh the time required to partition the data and manage separate execution
Systems of Linear Equations
threads. For example, most functions speed up only when the array contains several
thousand elements or more.
The operation is not memory-bound; processing time is not dominated by memory
access time. As a general rule, complicated functions speed up more than simple
functions.
3
inv, lscov, linsolve, and mldivide show significant increase in speed on large
double-precision arrays (on order of 10,000 elements or more) when multithreading is
enabled.
Iterative Methods for Solving Systems of Linear Equations
If the coefficient matrix A is large and sparse, factorization methods are generally not
efficient. Iterative methods generate a series of approximate solutions. MATLAB provides
several iterative methods to handle large, sparse input matrices.
pcg
Preconditioned conjugate gradients method. This method is appropriate for
Hermitian positive definite coefficient matrix A.
bicg
BiConjugate Gradients Method
bicgstab
BiConjugate Gradients Stabilized Method
bicgstabl
BiCGStab(l) Method
cgs
Conjugate Gradients Squared Method
gmres
Generalized Minimum Residual Method
lsqr
LSQR Method
minres
Minimum Residual Method. This method is appropriate for Hermitian coefficient
matrix A.
qmr
2-21
2
Linear Algebra
Quasi-Minimal Residual Method
symmlq
Symmetric LQ Method
tfqmr
Transpose-Free QMR Method
2-22
Inverses and Determinants
Inverses and Determinants
In this section...
“Introduction” on page 2-23
“Pseudoinverses” on page 2-24
Introduction
If A is square and nonsingular, the equations AX = I and XA = I have the same solution,
X. This solution is called the inverse of A, is denoted by A-1, and is computed by the
function inv.
The determinant of a matrix is useful in theoretical considerations and some types of
symbolic computation, but its scaling and round-off error properties make it far less
satisfactory for numeric computation. Nevertheless, the function det computes the
determinant of a square matrix:
A = pascal(3)
A =
1
1
1
d = det(A)
X = inv(A)
1
2
3
1
3
6
-3
5
-2
1
-2
1
d =
1
X =
3
-3
1
Again, because A is symmetric, has integer elements, and has determinant equal to one,
so does its inverse. However,
B = magic(3)
B =
2-23
2
Linear Algebra
8
3
4
d = det(B)
X = inv(B)
1
5
9
6
7
2
d =
-360
X =
0.1472
-0.0611
-0.0194
-0.1444
0.0222
0.1889
0.0639
0.1056
-0.1028
Closer examination of the elements of X, or use of format rat, would reveal that they
are integers divided by 360.
If A is square and nonsingular, then, without round-off error, X = inv(A)*B is
theoretically the same as X = A\B and Y = B*inv(A) is theoretically the same as Y =
B/A. But the computations involving the backslash and slash operators are preferable
because they require less computer time, less memory, and have better error-detection
properties.
Pseudoinverses
Rectangular matrices do not have inverses or determinants. At least one of the equations
AX = I and XA = I does not have a solution. A partial replacement for the inverse is
provided by the Moore-Penrose pseudoinverse, which is computed by the pinv function:
format short
C = fix(10*gallery('uniformdata',[3 2],0));
X = pinv(C)
X =
0.1159
-0.0534
-0.0729
0.1152
The matrix
Q = X*C
Q =
1.0000
2-24
0.0000
0.0171
0.0418
Inverses and Determinants
0.0000
1.0000
is the 2-by-2 identity, but the matrix
P = C*X
P =
0.8293
-0.1958
0.3213
-0.1958
0.7754
0.3685
0.3213
0.3685
0.3952
is not the 3-by-3 identity. However, P acts like an identity on a portion of the space in the
sense that P is symmetric, P*C is equal to C, and X*P is equal to X.
Solving a Rank-Deficient System
If A is m-by-n with m > n and full rank n, each of the three statements
x = A\b
x = pinv(A)*b
x = inv(A'*A)*A'*b
theoretically computes the same least-squares solution x, although the backslash
operator does it faster.
However, if A does not have full rank, the solution to the least-squares problem is not
unique. There are many vectors x that minimize
norm(A*x -b)
The solution computed by x = A\b is a basic solution; it has at most r nonzero
components, where r is the rank of A. The solution computed by x = pinv(A)*b is the
minimal norm solution because it minimizes norm(x). An attempt to compute a solution
with x = inv(A'*A)*A'*b fails because A'*A is singular.
Here is an example that illustrates the various solutions:
A = [ 1 2 3
4 5 6
7 8 9
10 11 12 ];
does not have full rank. Its second column is the average of the first and third columns. If
b = A(:,2)
2-25
2
Linear Algebra
is the second column, then an obvious solution to A*x = b is x = [0 1 0]'. But none
of the approaches computes that x. The backslash operator gives
x = A\b
Warning: Rank deficient, rank = 2, tol = 1.4594e-014.
x =
0.5000
0
0.5000
This solution has two nonzero components. The pseudoinverse approach gives
y = pinv(A)*b
y =
0.3333
0.3333
0.3333
There is no warning about rank deficiency. But norm(y) = 0.5774 is less than
norm(x) = 0.7071. Finally,
z = inv(A'*A)*A'*b
fails completely:
Warning: Matrix is close to singular or badly scaled.
Results may be inaccurate. RCOND = 9.868649e-018.
z =
-0.8594
1.3438
-0.6875
2-26
Factorizations
Factorizations
In this section...
“Introduction” on page 2-27
“Cholesky Factorization” on page 2-27
“LU Factorization” on page 2-28
“QR Factorization” on page 2-30
“Using Multithreaded Computation for Factorization” on page 2-33
Introduction
All three of the matrix factorizations discussed in this section make use of triangular
matrices, where all the elements either above or below the diagonal are zero. Systems of
linear equations involving triangular matrices are easily and quickly solved using either
forward or back substitution.
Cholesky Factorization
The Cholesky factorization expresses a symmetric matrix as the product of a triangular
matrix and its transpose
A = R′R,
where R is an upper triangular matrix.
Not all symmetric matrices can be factored in this way; the matrices that have such a
factorization are said to be positive definite. This implies that all the diagonal elements
of A are positive and that the off-diagonal elements are “not too big.” The Pascal matrices
provide an interesting example. Throughout this chapter, the example matrix A has been
the 3-by-3 Pascal matrix. Temporarily switch to the 6-by-6:
A = pascal(6)
A =
1
1
1
1
1
1
1
2
3
4
5
6
1
3
6
10
15
21
1
4
10
20
35
56
1
5
15
35
70
126
1
6
21
56
126
252
2-27
2
Linear Algebra
The elements of A are binomial coefficients. Each element is the sum of its north and
west neighbors. The Cholesky factorization is
R = chol(A)
R =
1
0
0
0
0
0
1
1
0
0
0
0
1
2
1
0
0
0
1
3
3
1
0
0
1
4
6
4
1
0
1
5
10
10
5
1
The elements are again binomial coefficients. The fact that R'*R is equal to A
demonstrates an identity involving sums of products of binomial coefficients.
Note: The Cholesky factorization also applies to complex matrices. Any complex matrix
that has a Cholesky factorization satisfies
A′ = A
and is said to be Hermitian positive definite.
The Cholesky factorization allows the linear system
Ax = b
to be replaced by
R′Rx = b.
Because the backslash operator recognizes triangular systems, this can be solved in the
MATLAB environment quickly with
x = R\(R'\b)
If A is n-by-n, the computational complexity of chol(A) is O(n3), but the complexity of
the subsequent backslash solutions is only O(n2).
LU Factorization
LU factorization, or Gaussian elimination, expresses any square matrix A as the product
of a permutation of a lower triangular matrix and an upper triangular matrix
A = LU,
2-28
Factorizations
where L is a permutation of a lower triangular matrix with ones on its diagonal and U is
an upper triangular matrix.
The permutations are necessary for both theoretical and computational reasons. The
matrix
È0 1 ˘
Í
˙
Î1 0 ˚
cannot be expressed as the product of triangular matrices without interchanging its two
rows. Although the matrix
Èe 1 ˘
Í
˙
Î1 0 ˚
can be expressed as the product of triangular matrices, when ε is small, the elements
in the factors are large and magnify errors, so even though the permutations are not
strictly necessary, they are desirable. Partial pivoting ensures that the elements of L are
bounded by one in magnitude and that the elements of U are not much larger than those
of A.
For example:
[L,U] = lu(B)
L =
1.0000
0.3750
0.5000
0
0.5441
1.0000
0
1.0000
0
8.0000
0
0
1.0000
8.5000
0
6.0000
-1.0000
5.2941
U =
The LU factorization of A allows the linear system
A*x = b
to be solved quickly with
2-29
2
Linear Algebra
x = U\(L\b)
Determinants and inverses are computed from the LU factorization using
det(A) = det(L)*det(U)
and
inv(A) = inv(U)*inv(L)
You can also compute the determinants using det(A) = prod(diag(U)), though the
signs of the determinants might be reversed.
QR Factorization
An orthogonal matrix, or a matrix with orthonormal columns, is a real matrix whose
columns all have unit length and are perpendicular to each other. If Q is orthogonal, then
Q′Q = 1.
The simplest orthogonal matrices are two-dimensional coordinate rotations:
È cos(q ) sin(q ) ˘
Í
˙.
Î- sin(q ) cos(q ) ˚
For complex matrices, the corresponding term is unitary. Orthogonal and unitary
matrices are desirable for numerical computation because they preserve length, preserve
angles, and do not magnify errors.
The orthogonal, or QR, factorization expresses any rectangular matrix as the product of
an orthogonal or unitary matrix and an upper triangular matrix. A column permutation
might also be involved:
A = QR
or
AP = QR,
where Q is orthogonal or unitary, R is upper triangular, and P is a permutation.
There are four variants of the QR factorization—full or economy size, and with or without
column permutation.
2-30
Factorizations
Overdetermined linear systems involve a rectangular matrix with more rows than
columns, that is m-by-n with m > n. The full-size QR factorization produces a square, mby-m orthogonal Q and a rectangular m-by-n upper triangular R:
C=gallery('uniformdata',[5 4], 0);
[Q,R] = qr(C)
Q =
0.6191
0.1506
0.3954
0.3167
0.5808
0.1406
0.4084
-0.5564
0.6676
-0.2410
-0.1899
0.5034
0.6869
0.1351
-0.4695
-0.5058
0.5974
-0.1478
-0.1729
0.5792
1.5346
0
0
0
0
1.0663
0.7245
0
0
0
1.2010
0.3474
0.9320
0
0
1.4036
-0.0126
0.6596
0.6648
0
0.5522
0.4475
-0.2008
-0.6370
-0.2207
R =
In many cases, the last m – n columns of Q are not needed because they are multiplied
by the zeros in the bottom portion of R. So the economy-size QR factorization produces a
rectangular, m-by-n Q with orthonormal columns and a square n-by-n upper triangular
R. For the 5-by-4 example, this is not much of a saving, but for larger, highly rectangular
matrices, the savings in both time and memory can be quite important:
[Q,R] = qr(C,0)
Q =
0.6191
0.1506
0.3954
0.3167
0.5808
0.1406
0.4084
-0.5564
0.6676
-0.2410
-0.1899
0.5034
0.6869
0.1351
-0.4695
-0.5058
0.5974
-0.1478
-0.1729
0.5792
1.5346
0
1.0663
0.7245
1.2010
0.3474
1.4036
-0.0126
R =
2-31
2
Linear Algebra
0
0
0
0
0.9320
0
0.6596
0.6648
In contrast to the LU factorization, the QR factorization does not require any pivoting
or permutations. But an optional column permutation, triggered by the presence of a
third output argument, is useful for detecting singularity or rank deficiency. At each step
of the factorization, the column of the remaining unfactored matrix with largest norm
is used as the basis for that step. This ensures that the diagonal elements of R occur in
decreasing order and that any linear dependence among the columns is almost certainly
be revealed by examining these elements. For the small example given here, the second
column of C has a larger norm than the first, so the two columns are exchanged:
[Q,R,P] = qr(C)
Q =
-0.3522
-0.7044
-0.6163
0.8398
-0.5285
0.1241
R =
-11.3578
0
0
-8.2762
7.2460
0
-0.4131
-0.4739
0.7777
P =
0
1
1
0
When the economy-size and column permutations are combined, the third output
argument is a permutation vector, rather than a permutation matrix:
[Q,R,p] = qr(C,0)
Q =
-0.3522
-0.7044
-0.6163
0.8398
-0.5285
0.1241
R =
-11.3578
0
-8.2762
7.2460
p =
2-32
Factorizations
2
1
The QR factorization transforms an overdetermined linear system into an equivalent
triangular system. The expression
norm(A*x - b)
equals
norm(Q*R*x - b)
Multiplication by orthogonal matrices preserves the Euclidean norm, so this expression is
also equal to
norm(R*x - y)
where y = Q'*b. Since the last m-n rows of R are zero, this expression breaks into two
pieces:
norm(R(1:n,1:n)*x - y(1:n))
and
norm(y(n+1:m))
When A has full rank, it is possible to solve for x so that the first of these expressions is
zero. Then the second expression gives the norm of the residual. When A does not have
full rank, the triangular structure of R makes it possible to find a basic solution to the
least-squares problem.
Using Multithreaded Computation for Factorization
MATLAB software supports multithreaded computation for a number of linear algebra
and element-wise numerical functions. These functions automatically execute on
multiple threads. For a function or expression to execute faster on multiple CPUs, a
number of conditions must be true:
1
The function performs operations that easily partition into sections that execute
concurrently. These sections must be able to execute with little communication
between processes. They should require few sequential operations.
2
The data size is large enough so that any advantages of concurrent execution
outweigh the time required to partition the data and manage separate execution
2-33
2
Linear Algebra
threads. For example, most functions speed up only when the array contains several
thousand elements or more.
3
The operation is not memory-bound; processing time is not dominated by memory
access time. As a general rule, complicated functions speed up more than simple
functions.
lu and qr show significant increase in speed on large double-precision arrays (on order of
10,000 elements).
2-34
Powers and Exponentials
Powers and Exponentials
In this section...
“Positive Integer Powers” on page 2-35
“Inverse and Fractional Powers” on page 2-35
“Element-by-Element Powers” on page 2-36
“Exponentials” on page 2-36
Positive Integer Powers
If A is a square matrix and p is a positive integer, A^p effectively multiplies A by itself
p-1 times. For example:
A = [1 1 1;1 2 3;1 3 6]
A =
1
1
1
1
2
3
1
3
6
6
14
25
10
25
46
X = A^2
X =
3
6
10
Inverse and Fractional Powers
If A is square and nonsingular, A^(-p) effectively multiplies inv(A) by itself p-1 times:
Y = A^(-3)
Y =
145.0000 -207.0000
81.0000
-207.0000 298.0000 -117.0000
2-35
2
Linear Algebra
81.0000 -117.0000
46.0000
Fractional powers, like A^(2/3), are also permitted; the results depend upon the
distribution of the eigenvalues of the matrix.
Element-by-Element Powers
The .^ operator produces element-by-element powers. For example:
X = A.^2
A =
1
1
1
1
4
9
1
9
36
Exponentials
The function
sqrtm(A)
computes A^(1/2) by a more accurate algorithm. The m in sqrtm distinguishes this
function from sqrt(A), which, like A.^(1/2), does its job element-by-element.
A system of linear, constant coefficient, ordinary differential equations can be written
where x = x(t) is a vector of functions of t and A is a matrix independent of t. The
solution can be expressed in terms of the matrix exponential
.
The function
expm(A)
computes the matrix exponential. An example is provided by the 3-by-3 coefficient
matrix,
2-36
Powers and Exponentials
A = [0 -6 -1; 6 2 -16; -5 20 -10]
A =
0
6
-5
-6
2
20
-1
-16
-10
and the initial condition, x(0).
x0 = [1 1 1]'
x0 =
1
1
1
The matrix exponential is used to compute the solution, x(t), to the differential equation
at 101 points on the interval
.
X = [];
for t = 0:.01:1
X = [X expm(t*A)*x0];
end
A three-dimensional phase plane plot shows the solution spiraling in towards the origin.
This behavior is related to the eigenvalues of the coefficient matrix.
plot3(X(1,:),X(2,:),X(3,:),'-o')
2-37
2
Linear Algebra
2-38
Eigenvalues
Eigenvalues
In this section...
“Eigenvalue Decomposition” on page 2-39
“Multiple Eigenvalues” on page 2-40
“Schur Decomposition” on page 2-41
Eigenvalue Decomposition
An eigenvalue and eigenvector of a square matrix A are, respectively, a scalar λ and a
nonzero vector υ that satisfy
Aυ = λυ.
With the eigenvalues on the diagonal of a diagonal matrix Λ and the corresponding
eigenvectors forming the columns of a matrix V, you have
AV = VΛ.
If V is nonsingular, this becomes the eigenvalue decomposition
A = VΛV–1.
A good example is provided by the coefficient matrix of the ordinary differential equation
in the previous section:
A =
0
6
-5
-6
2
20
-1
-16
-10
The statement
lambda = eig(A)
produces a column vector containing the eigenvalues. For this matrix, the eigenvalues
are complex:
lambda =
-3.0710
-2.4645+17.6008i
-2.4645-17.6008i
2-39
2
Linear Algebra
The real part of each of the eigenvalues is negative, so eλt approaches zero as t increases.
The nonzero imaginary part of two of the eigenvalues, ±ω, contributes the oscillatory
component, sin(ωt), to the solution of the differential equation.
With two output arguments, eig computes the eigenvectors and stores the eigenvalues in
a diagonal matrix:
[V,D] = eig(A)
V =
-0.8326
-0.3553
-0.4248
0.2003 - 0.1394i
-0.2110 - 0.6447i
-0.6930
D =
-3.0710
0
0
0
-2.4645+17.6008i
0
0.2003 + 0.1394i
-0.2110 + 0.6447i
-0.6930
0
0
-2.4645-17.6008i
The first eigenvector is real and the other two vectors are complex conjugates of each
other. All three vectors are normalized to have Euclidean length, norm(v,2), equal to
one.
The matrix V*D*inv(V), which can be written more succinctly as V*D/V, is within
round-off error of A. And, inv(V)*A*V, or V\A*V, is within round-off error of D.
Multiple Eigenvalues
Some matrices do not have an eigenvector decomposition. These matrices are not
diagonalizable. For example:
A = [ 6
-9
4
12
-20
9
For this matrix
[V,D] = eig(A)
produces
V =
2-40
19
-33
15 ]
Eigenvalues
-0.4741
0.8127
-0.3386
-0.4082
0.8165
-0.4082
-0.4082
0.8165
-0.4082
0
1.0000
0
0
0
1.0000
D =
-1.0000
0
0
There is a double eigenvalue at λ = 1. The second and third columns of V are the same.
For this matrix, a full set of linearly independent eigenvectors does not exist.
Schur Decomposition
The MATLAB advanced matrix computations do not require eigenvalue decompositions.
They are based, instead, on the Schur decomposition
A = USU′.
where U is an orthogonal matrix and S is a block upper triangular matrix with 1-by-1
and 2-by-2 blocks on the diagonal. The eigenvalues are revealed by the diagonal elements
and blocks of S, while the columns of U provide a basis with much better numerical
properties than a set of eigenvectors. The Schur decomposition of this defective example
is
[U,S] = schur(A)
U =
-0.4741
0.8127
-0.3386
0.6648
0.0782
-0.7430
0.5774
0.5774
0.5774
20.7846
1.0000
0
-44.6948
-0.6096
1.0000
S =
-1.0000
0
0
The double eigenvalue is contained in the lower 2-by-2 block of S.
Note: If A is complex, schur returns the complex Schur form, which is upper triangular
with the eigenvalues of A on the diagonal.
2-41
2
Linear Algebra
Singular Values
A singular value and corresponding singular vectors of a rectangular matrix A are,
respectively, a scalar σ and a pair of vectors u and v that satisfy
Av = σu
A′u = σv.
With the singular values on the diagonal of a diagonal matrix Σ and the corresponding
singular vectors forming the columns of two orthogonal matrices U and V, you have
AV = UΣ
A′U = VΣ.
Since U and V are orthogonal, this becomes the singular value decomposition
A = UΣV′.
The full singular value decomposition of an m-by-n matrix involves an m-by-m U, an
m-by-n Σ, and an n-by-n V. In other words, U and V are both square and Σ is the same
size as A. If A has many more rows than columns, the resulting U can be quite large,
but most of its columns are multiplied by zeros in Σ. In this situation, the economy sized
decomposition saves both time and storage by producing an m-by-n U, an n-by-n Σ and
the same V.
The eigenvalue decomposition is the appropriate tool for analyzing a matrix when
it represents a mapping from a vector space into itself, as it does for an ordinary
differential equation. However, the singular value decomposition is the appropriate tool
for analyzing a mapping from one vector space into another vector space, possibly with a
different dimension. Most systems of simultaneous linear equations fall into this second
category.
If A is square, symmetric, and positive definite, then its eigenvalue and singular value
decompositions are the same. But, as A departs from symmetry and positive definiteness,
the difference between the two decompositions increases. In particular, the singular
value decomposition of a real matrix is always real, but the eigenvalue decomposition of a
real, nonsymmetric matrix might be complex.
For the example matrix
A =
9
6
2
2-42
4
8
7
Singular Values
the full singular value decomposition is
[U,S,V] = svd(A)
U =
0.6105
0.6646
0.4308
-0.7174
0.2336
0.6563
14.9359
0
0
0
5.1883
0
0.3355
-0.7098
0.6194
S =
V =
0.6925
0.7214
-0.7214
0.6925
You can verify that U*S*V' is equal to A to within round-off error. For this small
problem, the economy size decomposition is only slightly smaller:
[U,S,V] = svd(A,0)
U =
0.6105
0.6646
0.4308
-0.7174
0.2336
0.6563
14.9359
0
0
5.1883
S =
V =
0.6925
0.7214
-0.7214
0.6925
2-43
2
Linear Algebra
Again, U*S*V' is equal to A to within round-off error.
2-44
3
Random Numbers
• “Random Numbers in MATLAB” on page 3-2
• “Why Do Random Numbers Repeat After Startup?” on page 3-3
• “Create Arrays of Random Numbers” on page 3-4
• “Random Numbers Within a Specific Range” on page 3-6
• “Random Integers” on page 3-7
• “Random Numbers from Normal Distribution with Specific Mean and Variance” on
page 3-8
• “Random Numbers Within a Sphere” on page 3-9
• “Generate Random Numbers That Are Repeatable” on page 3-11
• “Generate Random Numbers That Are Different” on page 3-15
• “Managing the Global Stream” on page 3-17
• “Creating and Controlling a Random Number Stream” on page 3-23
• “Multiple streams” on page 3-31
• “Replace Discouraged Syntaxes of rand and randn” on page 3-34
3
Random Numbers
Random Numbers in MATLAB
When you create random numbers using software, the results are not random in a strict,
mathematical sense. However, software applications, such as MATLAB, use algorithms
that make your results appear to be random and independent. The results also pass
various statistical tests of randomness and independence. These apparently random and
independent numbers are often described as pseudorandom and pseudoindependent. You
can use these numbers as if they are truly random and independent. One benefit of using
pseudorandom, pseudoindependent numbers is that you can repeat a random number
calculation at any time. This approach can be useful in testing or diagnostic situations.
Although repeatability can be useful, it is possible to repeat your results accidentally
when you really want different results. There are several ways to avoid this problem. The
documentation contains several examples that show how to ensure that your results are
different when that is your intention.
Note: You can assume any reference to random numbers in the MATLAB documentation
is actually referring to pseudorandom numbers, unless otherwise stated.
Related Examples
3-2
•
“Generate Random Numbers That Are Repeatable” on page 3-11
•
“Generate Random Numbers That Are Different” on page 3-15
Why Do Random Numbers Repeat After Startup?
Why Do Random Numbers Repeat After Startup?
All the random number functions, rand, randn, randi, and randperm, draw values
from a shared random number generator. Every time you start MATLAB, the generator
resets itself to the same state. Therefore, a command such as rand(2,2) returns the
same result any time you execute it immediately following startup. Also, any script or
function that calls the random number functions returns the same result whenever you
restart.
If you want to avoid repeating the same random number arrays when MATLAB restarts,
then execute the command,
rng('shuffle');
before calling rand, randn, randi, or randperm. This command ensures that you do not
repeat a result from a previous MATLAB session.
If you want to repeat a result that you got at the start of a MATLAB session without
restarting, you can reset the generator to the startup state at any time using
rng('default');
When you execute rng('default'), the ensuing random number commands return
results that match the output of a new MATLAB session. For example,
rng('default');
A = rand(2,2)
A =
0.8147
0.9058
0.1270
0.9134
The values in A match the output of rand(2,2) whenever you restart MATLAB.
See Also
rng
3-3
3
Random Numbers
Create Arrays of Random Numbers
There are four fundamental random number functions: rand, randi, randn, and
randperm. The rand function returns real numbers between 0 and 1 that are drawn
from a uniform distribution. For example,
r1 = rand(1000,1);
r1 is a 1000-by-1 column vector containing real floating-point numbers drawn from a
uniform distribution. All the values in r1 are in the open interval (0, 1). A histogram of
these values is roughly flat, which indicates a fairly uniform sampling of numbers.
The randi function returns double integer values drawn from a discrete uniform
distribution. For example,
r2 = randi(10,1000,1);
r2 is a 1000-by-1 column vector containing integer values drawn from a discrete uniform
distribution whose range is 1,2,...,10. A histogram of these values is roughly flat, which
indicates a fairly uniform sampling of integers between 1 and 10.
The randn function returns arrays of real floating-point numbers that are drawn from a
standard normal distribution. For example,
r3 = randn(1000,1);
r3 is a 1000-by-1 column vector containing numbers drawn from a standard normal
distribution. A histogram of r3 looks like a roughly normal distribution whose mean is 0
and standard deviation is 1.
You can use the randperm function to create arrays of random integer values that have
no repeated values. For example,
r4 = randperm(15,5);
r4 is a 1-by-5 array containing randomly selected integer values on the closed interval,
[1, 15]. Unlike randi, which can return an array containing repeated values, the array
returned by randperm has no repeated values.
Successive calls to any of these functions return different results. This behavior is useful
for creating several different arrays of random values.
See Also
rand | randi | randn | randperm
3-4
Create Arrays of Random Numbers
Related Examples
•
“Random Numbers Within a Specific Range” on page 3-6
•
“Random Integers” on page 3-7
•
“Random Numbers from Normal Distribution with Specific Mean and Variance” on
page 3-8
More About
•
“Random Numbers in MATLAB” on page 3-2
3-5
3
Random Numbers
Random Numbers Within a Specific Range
This example shows how to create an array of random floating-point numbers that are
drawn from a uniform distribution in the open interval (50, 100).
By default, rand returns normalized values (between 0 and 1) that are drawn from
a uniform distribution. To change the range of the distribution to a new range, (a, b),
multiply each value by the width of the new range, (b – a) and then shift every value by
a.
First, initialize the random number generator to make the results in this example
repeatable.
rng(0,'twister');
Create a vector of 1000 random values. Use the rand function to draw the values from a
uniform distribution in the open interval, (50,100).
a = 50;
b = 100;
r = (b-a).*rand(1000,1) + a;
Verify the values in r are within the specified range.
r_range = [min(r) max(r)]
r_range =
50.0261
99.9746
The result is in the open interval, (50,100).
Note: Some combinations of a and b make it theoretically possible for your results to
include a or b. In practice, this is extremely unlikely to happen.
3-6
Random Integers
Random Integers
This example shows how to create an array of random integer values that are drawn
from a discrete uniform distribution on the set of numbers, –10, –9,...,9, 10.
The simplest randi syntax returns double-precision integer values between 1 and a
specified value, imax. To specify a different range, use the imin and imax arguments
together.
First, initialize the random number generator to make the results in this example
repeatable.
rng(0,'twister');
Create a 1-by-1000 array of random integer values drawn from a discrete uniform
distribution on the set of numbers, –10, –9,...,9, 10. Use the syntax, randi([imin
imax],m,n]).
r = randi([-10 10],1,1000);
Verify that the values in r are within the specified range.
r_range = [min(r) max(r)]
r_range =
-10
10
3-7
3
Random Numbers
Random Numbers from Normal Distribution with Specific Mean
and Variance
This example shows how to create an array of random floating-point numbers that are
drawn from a normal distribution having a mean of 500 and variance of 25.
The randn function returns a sample of random numbers from a normal distribution
with mean 0 and variance 1. The general theory of random variables states that if x is
a random variable whose mean is mx and variance is s x2 , then the random variable,
y, defined by y = ax + b, where a and b are constants, has mean m y
= am x + b and
variance s 2y = a2s x2. You can apply this concept to get a sample of normally distributed
random numbers with mean 500 and variance 25.
First, initialize the random number generator to make the results in this example
repeatable.
rng(0,'twister');
Create a vector of 1000 random values drawn from a normal distribution with a mean of
500 and a standard deviation of 5.
a = 5;
b = 500;
y = a.*randn(1000,1) + b;
Calculate the sample mean, standard deviation, and variance.
stats = [mean(y) std(y) var(y)]
stats =
499.8368
4.9948
24.9483
The mean and variance are not 500 and 25 exactly because they are calculated from a
sampling of the distribution.
3-8
Random Numbers Within a Sphere
Random Numbers Within a Sphere
This example shows how to create random points within the volume of a sphere, as
described by Knuth [1]. The sphere in this example is centered at the origin and has a
radius of 3.
One way to create points inside a sphere is to specify them in spherical coordinates. Then
you can convert them to Cartesian coordinates to plot them.
First, initialize the random number generator to make the results in this example
repeatable.
rng(0,'twister')
Calculate an elevation angle for each point in the sphere. These values are in the open
interval,
, but are not uniformly distributed.
rvals = 2*rand(1000,1)-1;
elevation = asin(rvals);
Create an azimuth angle for each point in the sphere. These values are uniformly
distributed in the open interval,
.
azimuth = 2*pi*rand(1000,1);
Create a radius value for each point in the sphere. These values are in the open interval,
, but are not uniformly distributed.
radii = 3*(rand(1000,1).^(1/3));
Convert to Cartesian coordinates and plot the result.
[x,y,z] = sph2cart(azimuth,elevation,radii);
figure
plot3(x,y,z,'.')
axis equal
3-9
3
Random Numbers
If you want to place random numbers on the surface of the sphere, then specify a constant
radius value to be the last input argument to sph2cart. In this case, the value is 3.
[x,y,z] = sph2cart(azimuth,elevation,3);
References
[1] Knuth, D. The Art of Computer Programming. Vol. 2, 3rd ed. Reading, MA: AddisonWesley Longman, 1998, pp. 134–136.
3-10
Generate Random Numbers That Are Repeatable
Generate Random Numbers That Are Repeatable
Specify the Seed
This example shows how to repeat arrays of random numbers by specifying the seed first.
Every time you initialize the generator using the same seed, you always get the same
result.
First, initialize the random number generator to make the results in this example
repeatable.
rng('default');
Now, initialize the generator using a seed of 1.
rng(1);
Then, create an array of random numbers.
A = rand(3,3)
A =
0.4170
0.7203
0.0001
0.3023
0.1468
0.0923
0.1863
0.3456
0.3968
Repeat the same command.
A = rand(3,3)
A =
0.5388
0.4192
0.6852
0.2045
0.8781
0.0274
0.6705
0.4173
0.5587
The first call to rand changed the state of the generator, so the second result is different.
Now, reinitialize the generator using the same seed as before. Then reproduce the first
matrix, A.
rng(1);
3-11
3
Random Numbers
A = rand(3,3)
A =
0.4170
0.7203
0.0001
0.3023
0.1468
0.0923
0.1863
0.3456
0.3968
In some situations, setting the seed alone will not guarantee the same results. This is
because the generator that the random number functions draw from might be different
than you expect when your code executes. For long-term repeatability, specify the seed
and the generator type together.
For example, the following code sets the seed to 1 and the generator to Mersenne
Twister.
rng(1,'twister');
Set the seed and generator type together when you want to:
• Ensure that the behavior of code you write today returns the same results when you
run that code in a future MATLAB release.
• Ensure that the behavior of code you wrote in a previous MATLAB release returns the
same results using the current release.
• Repeat random numbers in your code after running someone else’s random number
code.
See the rng reference page for a list of available generators.
Save and Restore the Generator Settings
This example shows how to create repeatable arrays of random numbers by saving
and restoring the generator settings. The most common reason to save and restore
generator settings is to reproduce the random numbers generated at a specific point in
an algorithm or iteration. For example, you can use the generator settings as an aid in
debugging.
First, initialize the random number generator to make the results in this example
repeatable.
rng(1,'twister');
3-12
Generate Random Numbers That Are Repeatable
Save the generator settings in a structure, s.
s = rng;
Create an array, A, of random integer values between 1 and 10.
A = randi(10,3,3)
A =
5
8
1
4
2
1
2
4
4
Repeat the same command.
A = randi(10,3,3)
A =
6
5
7
3
9
1
7
5
6
The first call to randi changed the state of the generator, so the second result is
different.
Now, return the generator to the original state stored in s, and reproduce the first array,
A.
rng(s);
A = randi(10,3,3)
A =
5
8
1
4
2
1
2
4
4
Unlike reseeding, which reinitializes the generator, this approach allows you to save and
restore the generator settings at any point.
See Also
rng
3-13
3
Random Numbers
Related Examples
•
“Generate Random Numbers That Are Different” on page 3-15
More About
•
3-14
“Random Numbers in MATLAB” on page 3-2
Generate Random Numbers That Are Different
Generate Random Numbers That Are Different
This example shows how to avoid repeating the same random number arrays when
MATLAB restarts. This technique is useful when you want to combine results from the
same random number commands executed different MATLAB sessions.
All the random number functions, rand, randn, randi, and randperm, draw values
from a shared random number generator. Every time you start MATLAB, the generator
resets itself to the same state. Therefore, a command such as rand(2,2) returns the
same result any time you execute it immediately following startup. Also, any script or
function that calls the random number functions returns the same result whenever you
restart.
One way to get different random numbers is to initialize the generator using a different
seed every time. Doing so ensures that you don’t repeat results from a previous session.
Execute the rng('shuffle') command once in your MATLAB session before calling
any of the random number functions.
rng('shuffle')
You can execute this command in a MATLAB Command Window, or you can add it to
your startup file, which is a special script that MATLAB executes every time you restart.
Now, execute a random number command.
A = rand(2,2);
Each time you call rng('shuffle'), it reseeds the generator using a different seed
based on the current time.
Alternatively, specify different seeds explicitly. For example,
rng(1);
A = rand(2,2);
rng(2);
B = rand(2,2);
Arrays A and B are different because the generator is initialized with a different seed
before each call to the rand function.
Note: Frequent reseeding of the generator does not improve the statistical properties
of the output and does not make the output more random in any real sense. Reseeding
3-15
3
Random Numbers
can be useful when you restart MATLAB or before you run a large calculation involving
random numbers. However, reseeding the generator too frequently within a session is not
a good idea because the statistical properties of your random numbers can be adversely
affected.
See Also
rng
Related Examples
•
“Generate Random Numbers That Are Repeatable” on page 3-11
More About
3-16
•
“Random Numbers in MATLAB” on page 3-2
•
“Startup Options in MATLAB Startup File”
Managing the Global Stream
Managing the Global Stream
rand, randn, and randi draw random numbers from an underlying random number
stream, called the global stream. The rng function provides a simple way to control the
global stream. For more comprehensive control, the RandStream class allows you to get a
handle to the global stream and control random number generation.
Get a handle to the global stream as follows:
globalStream = RandStream.getGlobalStream
globalStream =
mt19937ar random stream (current global stream)
Seed: 0
NormalTransform: Ziggurat
Return the properties of the stream with the get method:
get(globalStream)
Type:
NumStreams:
StreamIndex:
Substream:
Seed:
State:
NormalTransform:
Antithetic:
FullPrecision:
'mt19937ar'
1
1
1
0
[625x1 uint32]
'Ziggurat'
0
1
Now, use the rand function to generate uniform random values from the global stream.
rand(1,5);
Use the randn and randi functions to generate normal random values and integer
random values from the global stream.
A = randi(100,1,5);
A = randn(1,5);
The State property is the internal state of the generator. You can save the State of
globalStream.
myState = globalStream.State;
3-17
3
Random Numbers
Using myState, you can restore the state of globalStream and reproduce previous
results.
myState = globalStream.State;
A = rand(1,100);
globalStream.State = myState;
B=rand(1,100);
isequal(A,B)
ans =
1
rand, randi, and randn access the global stream. Since all of these functions access
the same underlying stream, a call to one affects the values produced by the others at
subsequent calls.
globalStream.State = myState;
A = rand(1,100);
globalStream.State = myState;
randi(100);
B = rand(1,100);
isequal(A,B)
ans =
0
The global stream is a handle object of the RandStream class.
RandStream.getGlobalStream returns a handle. The properties of the global stream
can be viewed or modified from any handle to the stream.
stream1=RandStream.getGlobalStream;
stream2=RandStream.getGlobalStream;
stream1.NormalTransform='Polar';
stream2.NormalTransform
ans =
Polar
The following table shows the methods available for the RandStream class. Static
methods are indicated with the syntax RandStream.methodName.
3-18
Managing the Global Stream
Method
Description
RandStream
Create a random number stream
RandStream.create
Create multiple independent random
number streams
get
Get the properties of a random stream
RandStream.list
List available random number generator
algorithms
RandStream.getGlobalStream
Get the global random number stream
RandStream.setGlobalStream
Set the global random number stream
set
Set a property of a random stream
reset
Reset a stream to its initial internal state
rand
Generate pseudorandom numbers from a
uniform distribution
randn
Generate pseudorandom numbers from a
standard normal distribution
randi
Generate pseudorandom integers from a
uniform discrete distribution
randperm
Random permutation of a set of values
The properties of a random stream are given the following table.
Property
Description
Type
(Read-only) Generator algorithm used by
the stream. RandStream.list specifies
the possible generators.
Seed
(Read-only) Seed value used to create the
stream.
NumStreams
(Read-only) Number of streams in the
group in which the current stream was
created.
StreamIndex
(Read-only) Index of the current stream
from among the group of streams with
which the current stream was created.
3-19
3
Random Numbers
Property
Description
State
Internal state of the generator. Do not
depend on the format of this property. The
value you assign to S.State must be a
value previously read from S.State.
Substream
Index of the substream to which the
stream is currently set. The default is 1.
Multiple substreams are not supported
by all generator types; the multiplicative
lagged Fibonacci generator (mlfg6331_64)
and combined multiple recursive generator
(mrg32k3a) support substreams.
NormalTransform
Transformation algorithm used by
randn(s, ...) to generate normal
pseudorandom values. Possible values are
'Ziggurat', 'Polar', or 'Inversion'.
Antithetic
Logical value indicating whether S
generates antithetic pseudorandom values.
For uniform values, these are the usual
values subtracted from 1. The default is
false.
FullPrecision
Logical value indicating whether s
generates values using its full precision.
Some generators can create pseudorandom
values faster, but with fewer random bits,
if FullPrecision is false. The default is
true.
Suppose you want to repeat a simulation. The RandStream class gives you several ways
to replicate output. As shown in the previous example, you can save the state of the
global stream.
myState=GlobalStream.State;
A=rand(1,100);
GlobalStream.State=myState;
B=rand(1,100);
isequal(A,B)
ans =
3-20
Managing the Global Stream
1
You can also reset a stream to its initial settings with the method reset.
reset(GlobalStream)
A=rand(1,100);
reset(GlobalStream)
B=rand(1,100);
isequal(A,B)
ans =
1
Random Number Data Types
rand and randn generate values in double precision by default.
GlobalStream=RandStream.getGlobalStream;
myState=GlobalStream.State;
A=rand(1,5);
class(A)
ans =
double
To specify the class as double explicitly:
GlobalStream.State=myState;
B=rand(1,5,'double');
class(B)
ans =
double
isequal(A,B)
ans =
1
rand and randn will also generate values in single precision.
3-21
3
Random Numbers
GlobalStream.State=myState;
A=rand(1,5,'single');
class(A)
ans =
single
The values are the same as if you had cast the double precision values from the previous
example. The random stream that the functions draw from advances the same way
regardless of what class of values is returned.
A,B
A =
0.8235
0.6948
0.3171
0.9502
0.0344
0.8235
0.6948
0.3171
0.9502
0.0344
B =
randi supports both integer types and single or double precision.
A=randi([1 10],1,5,'double');
class(A)
ans =
double
B=randi([1 10],1,5,'uint8');
class(B)
ans =
uint8
3-22
Creating and Controlling a Random Number Stream
Creating and Controlling a Random Number Stream
In this section...
“Substreams” on page 3-24
“Choosing a Random Number Generator” on page 3-25
The RandStream class allows you to create a random number stream. This is useful
for several reasons. For example, you might want to generate random values without
affecting the state of the global stream. You might want separate sources of randomness
in a simulation. Or you may need to use a different generator algorithm than the one
MATLAB software uses at startup. With the RandStream constructor, you can create
your own stream, set the writable properties, and use it to generate random numbers.
You can control the stream you create the same way you control the global stream. You
can even replace the global stream with the stream you create.
To create a stream, use the RandStream constructor.
myStream=RandStream('mlfg6331_64');
rand(myStream,1,5)
ans =
0.6530
0.8147
0.7167
0.8615
0.0764
The random stream myStream acts separately from the global stream. The functions
rand, randn, and randi will continue to draw from the global stream, and will not affect
the results of the RandStream methods rand, randn and randi applied to myStream.
You can make myStream the global stream using the RandStream.setGlobalStream
method.
RandStream.setGlobalStream(myStream)
RandStream.getGlobalStream
ans =
mlfg6331_64 random stream (current global stream)
Seed: 0
NormalTransform: Ziggurat
RandStream.getGlobalStream==myStream
3-23
3
Random Numbers
ans =
1
Substreams
You may want to return to a previous part of a simulation. A random stream can be
controlled by having it jump to fixed checkpoints, called substreams. The Substream
property allows you to jump back and forth among multiple substreams. To use the
Substream property, create a stream using a generator that supports substreams.
(See “Choosing a Random Number Generator” on page 3-25 for a list of generator
algorithms and their properties.)
stream=RandStream('mlfg6331_64');
RandStream.setGlobalStream(stream)
The initial value of Substream is 1.
stream.Substream
ans =
1
Substreams are useful in serial computation. Substreams can recreate all or part of a
simulation by returning to a particular checkpoint in stream. For example, they can be
used in loops.
for i=1:5
stream.Substream=i;
rand(1,i)
end
ans =
0.6530
ans =
0.3364
0.8265
ans =
0.9539
0.6446
ans =
3-24
0.4913
Creating and Controlling a Random Number Stream
0.0244
0.5134
0.6305
0.6534
ans =
0.3323
0.9296
0.5767
0.1233
0.6934
Each of these substreams can reproduce its loop iteration. For example, you can return to
the 5th substream. The result will return the same values as the 5th output above.
stream.Substream=5;
rand(1,5)
ans =
0.3323
0.9296
0.5767
0.1233
0.6934
Choosing a Random Number Generator
MATLAB software offers six generator algorithms. The following table summarizes
the key properties of the available generator algorithms and the keywords used
to create them. To return a list of all the available generator algorithms, use the
RandStream.list method.
Generator algorithms
Keyword
Generator
Multiple Stream and
Substream Support
Approximate Period In
Full Precision
mt19937ar
Mersenne twister
(default)
No
dsfmt19937
SIMD-oriented fast
Mersenne twister
No
mcg16807
Multiplicative
congruential
generator
No
mlfg6331_64
Multiplicative lagged
Fibonacci generator
Yes
2124
mrg32k3a
Combined multiple
recursive generator
Yes
2191
shr3cong
Shift-register
generator summed
No
264
219937 - 1
219937 - 1
2 31 - 2
3-25
3
Random Numbers
Keyword
Generator
with linear
congruential
generator
swb2712
Modified subtract
with borrow
generator
Multiple Stream and
Substream Support
No
Approximate Period In
Full Precision
21492
Some of the generators (mcg16807, shr3cong, swb2712) provide for backwards
compatibility with earlier versions of MATLAB. Two generators (mrg32k3a,
mlfg6331_64) provide explicit support for parallel random number generation. The
remaining generators (mt19937ar, dsfmt19937) are designed primarily for sequential
applications. Depending on the application, some generators may be faster or return
values with more precision.
Another reason for the choice of generators has to do with applications. All
pseudorandom number generators are based on deterministic algorithms, and all will fail
a sufficiently specific statistical test for randomness. One way to check the results of a
Monte Carlo simulation is to rerun the simulation with two or more different generator
algorithms, and MATLAB software's choice of generators provide you with the means to
do that. Although it is unlikely that your results will differ by more than Monte Carlo
sampling error when using different generators, there are examples in the literature
where this kind of validation has turned up flaws in a particular generator algorithm (see
[13] for an example).
Generator Algorithms
mcg16807
A 32-bit multiplicative congruential generator, as described in [14], with multiplier
a = 75 , modulo m = 231 - 1 . This generator has a period of 2 31 - 2 and does not
support multiple streams or substreams. Each U(0,1) value is created using a
single 32-bit integer from the generator; the possible values are all multiples of
(2 31 - 1)-1 strictly within the interval (0,1). The randn algorithm used by default
for mcg16807 streams is the polar algorithm (described in [1]). Note: This generator
is identical to the one used beginning in MATLAB Version 4 by both the rand and
randn functions, activated using rand('seed',s) or randn('seed',s).
mlfg6331_64
3-26
Creating and Controlling a Random Number Stream
A 64-bit multiplicative lagged Fibonacci generator, as described in [10], with lags
l = 63 , k = 31 . This generator is similar to the MLFG implemented in the SPRNG
package. It has a period of approximately 2124 . It supports up to 261 parallel
streams, via parameterization, and 251 substreams each of length 272 . Each U(0,1)
value is created using one 64-bit integer from the generator; the possible values are
all multiples of 2 -53 strictly within the interval (0,1). The randn algorithm used
by default for mlfg6331_64 streams is the ziggurat algorithm [7], but with the
mlfg6331_64 generator underneath.
mrg32k3a
A 32-bit combined multiple recursive generator, as described in [2]. This generator
is similar to the CMRG implemented in the RngStreams package. It has a period
of 2191 and supports up to 263 parallel streams via sequence splitting, each of
length 2127 . It also supports 251 substreams, each of length 276 . Each U(0,1)
value is created using two 32-bit integers from the generator; the possible values
are multiples of 2 -53 strictly within the interval (0,1). The randn algorithm used by
default for mrg32k3a streams is the ziggurat algorithm [7], but with the mrg32k3a
generator underneath.
mt19937ar
The Mersenne Twister, as described in [11], has period 219937 - 1 and each U(0,1)
value is created using two 32-bit integers. The possible values are multiples of
2 -53 in the interval (0,1). This generator does not support multiple streams or
substreams. The randn algorithm used by default for mt19937ar streams is the
ziggurat algorithm [7], but with the mt19937ar generator underneath. Note: This
generator is identical to the one used by the rand function beginning in MATLAB
Version 7, activated by rand('twister',s).
dsfmt19937
The Double precision SIMD-oriented Fast Mersenne Twister, as described in [12], is
a faster implementation of the Mersenne Twister algorithm. The period is 219937 - 1
and the possible values are multiples of 2 -52 in the interval (0,1). The generator
produces double precision values in [1,2) natively, which are transformed to create
U(0,1) values. This generator does not support multiple streams or substreams.
shr3cong
3-27
3
Random Numbers
Marsaglia's SHR3 shift-register generator summed with a linear congruential
generator with multiplier a = 69069 , addend b = 1234567 , and modulus 2 -32 . SHR3
is a 3-shift-register generator defined as u = u(I + L13 )(I + R17 )(I + L5 ) , where I is the
identity operator, L is the left shift operator, and R is the right shift operator. The
combined generator (the SHR3 part is described in [7]) has a period of approximately
264 . This generator does not support multiple streams or substreams. Each U(0,1)
value is created using one 32-bit integer from the generator; the possible values are
all multiples of 2 -32 strictly within the interval (0,1). The randn algorithm used
by default for shr3cong streams is the earlier form of the ziggurat algorithm [9],
but with the shr3cong generator underneath. This generator is identical to the
one used by the randn function beginning in MATLAB Version 5, activated using
randn('state',s).
Note: The SHR3 generator used in [6] (1999) differs from the one used in [7] (2000).
MATLAB uses the most recent version of the generator, presented in [7].
swb2712
A modified Subtract-with-Borrow generator, as described in [8]. This generator is
similar to an additive lagged Fibonacci generator with lags 27 and 12, but is modified
to have a much longer period of approximately 21492 . The generator works natively
in double precision to create U(0,1) values, and all values in the open interval (0,1)
are possible. The randn algorithm used by default for swb2712 streams is the
ziggurat algorithm [7], but with the swb2712 generator underneath. Note: This
generator is identical to the one used by the rand function beginning in MATLAB
Version 5, activated using rand('state',s).
Transformation Algorithms
Inversion
Computes a normal random variate by applying the standard normal inverse
cumulative distribution function to a uniform random variate. Exactly one uniform
value is consumed per normal value.
Polar
The polar rejection algorithm, as described in [1]. Approximately 1.27 uniform values
are consumed per normal value, on average.
3-28
Creating and Controlling a Random Number Stream
Ziggurat
The ziggurat algorithm, as described in [7]. Approximately 2.02 uniform values are
consumed per normal value, on average.
References
[1] Devroye, L. Non-Uniform Random Variate Generation, Springer-Verlag, 1986.
[2] L’Ecuyer, P. “Good Parameter Sets for Combined Multiple Recursive Random Number
Generators”, Operations Research, 47(1): 159–164. 1999.
[3] L'Ecuyer, P. and S. Côté. “Implementing A Random Number Package with Splitting
Facilities”, ACM Transactions on Mathematical Software, 17: 98–111. 1991.
[4] L'Ecuyer, P. and R. Simard. “TestU01: A C Library for Empirical Testing of Random
Number Generators,” ACM Transactions on Mathematical Software, 33(4):
Article 22. 2007.
[5] L'Ecuyer, P., R. Simard, E. J. Chen, and W. D. Kelton. “An Objected-Oriented
Random-Number Package with Many Long Streams and Substreams.”
Operations Research, 50(6):1073–1075. 2002.
[6] Marsaglia, G. “Random numbers for C: The END?” Usenet posting to sci.stat.math.
1999. Available online at http://groups.google.com/group/sci.crypt/browse_thread/
thread/ca8682a4658a124d/.
[7] Marsaglia G., and W. W. Tsang. “The ziggurat method for generating random
variables.” Journal of Statistical Software, 5:1–7. 2000. Available online at http://
www.jstatsoft.org/v05/i08.
[8] Marsaglia, G., and A. Zaman. “A new class of random number generators.” Annals of
Applied Probability 1(3):462–480. 1991.
[9] Marsaglia, G., and W. W. Tsang. “A fast, easily implemented method for
sampling from decreasing or symmetric unimodal density functions.” SIAM
J.Sci.Stat.Comput. 5(2):349–359. 1984.
[10] Mascagni, M., and A. Srinivasan. “Parameterizing Parallel Multiplicative LaggedFibonacci Generators.” Parallel Computing, 30: 899–916. 2004.
[11] Matsumoto, M., and T. Nishimura.“Mersenne Twister: A 623-Dimensionally
Equidistributed Uniform Pseudorandom Number Generator.” ACM Transactions
on Modeling and Computer Simulation, 8(1):3–30. 1998. Available online at
3-29
3
Random Numbers
[12] Matsumoto, M., and M. Saito.“A PRNG Specialized in Double Precision Floating
Point Numbers Using an Affine Transition.” Monte Carlo and Quasi-Monte Carlo
Methods 2008, 10.1007/978-3-642-04107-5_38. 2009. Available online at http://
www.math.sci.hiroshima-u.ac.jp/~%20m-mat/MT/ARTICLES/dSFMT.pdf.
[13] Moler, C.B. Numerical Computing with MATLAB. SIAM, 2004. Available online at
http://www.mathworks.com/moler
[14] Park, S.K., and K.W. Miller. “Random Number Generators: Good Ones Are Hard to
Find.” Communications of the ACM, 31(10):1192–1201. 1998.
3-30
Multiple streams
Multiple streams
MATLAB software includes generator algorithms that allow you to create multiple
independent random number streams. The RandStream.create factory method allows
you to create three streams that have the same generator algorithm and seed value but
are statistically independent.
[s1,s2,s3]=RandStream.create('mlfg6331_64','NumStreams',3)
s1 =
mlfg6331_64 random
StreamIndex:
NumStreams:
Seed:
NormalTransform:
stream
1
3
0
Ziggurat
s2 =
mlfg6331_64 random
StreamIndex:
NumStreams:
Seed:
NormalTransform:
stream
2
3
0
Ziggurat
s3 =
mlfg6331_64 random
StreamIndex:
NumStreams:
Seed:
NormalTransform:
stream
3
3
0
Ziggurat
As evidence of independence, you can see that these streams are largely uncorrelated.
r1=rand(s1,100000,1);
r2=rand(s2,100000,1);
r3=rand(s3,100000,1);
corrcoef([r1,r2,r3])
ans =
1.0000
-0.0017
-0.0017
1.0000
-0.0010
-0.0050
3-31
3
Random Numbers
-0.0010
-0.0050
1.0000
By using different seeds, you can create streams that return different values and act
separately from one another.
s1=RandStream('mt19937ar','seed',1);
s2=RandStream('mt19937ar','seed',2);
s3=RandStream('mt19937ar','seed',3);
Seed values must be integers between 0 and 2 32 - 1 . With different seeds, streams
typically return values that are uncorrelated.
r1=rand(s1,100000,1);
r2=rand(s2,100000,1);
r3=rand(s3,100000,1);
corrcoef([r1,r2,r3])
ans =
1.0000
0.0030
0.0045
0.0030
1.0000
-0.0015
0.0045
-0.0015
1.0000
For generator types that do not explicitly support independent streams, different seeds
provide a method to create multiple streams. However, using a generator specifically
designed for multiple independent streams is a better option, as the statistical properties
across streams are better understood.
Depending on the application, it might be useful to create only some of the streams in a
set of independent streams. The StreamIndex property returns the index of a specified
stream from a set of factory-generated streams.
numLabs=256;
labIndex=4;
s1=RandStream.create('mlfg6331_64',
'NumStreams',numLabs,'StreamIndices',labIndex)
s1=
mlfg6331_64 random stream
StreamIndex: 4
NumStreams: 256
Seed: 0
NormalTransform: Ziggurat
3-32
Multiple streams
Multiple streams, since they are statistically independent, can be used to verify the
precision of a simulation. For example, a set of independent streams can be used to
repeat a Monte Carlo simulation several times in different MATLAB sessions or on
different processors and determine the variance in the results. This makes multiple
streams useful in large-scale parallel simulations.
Note: Not all generators algorithms support multiple streams. See the table of generator
algorithms in “Choosing a Random Number Generator” on page 3-25 for a summary of
generator properties.
3-33
3
Random Numbers
Replace Discouraged Syntaxes of rand and randn
In this section...
“Description of the Former Syntaxes” on page 3-34
“Description of Replacement Syntaxes” on page 3-35
“Replacement Syntaxes for Initializing the Generator with an Integer Seed” on page
3-35
“Replacement Syntaxes for Initializing the Generator with a State Vector” on page
3-36
“If You Are Unable to Upgrade from Former Syntax” on page 3-37
Description of the Former Syntaxes
In earlier versions of MATLAB, you controlled the random number generator used by
the rand and randn functions with the 'seed', 'state' or 'twister' inputs. For
example:
rand('seed',sd)
randn('seed',sd)
rand('state',s)
randn('state',s)
rand('twister',5489)
These syntaxes referred to different types of generators, and they will be removed in a
future release for the following reasons:
• The terms 'seed' and 'state' are misleading names for the generators.
• All of the former generators except 'twister' are flawed.
• They unnecessarily use different generators for rand and randn.
To assess the impact this change will have on your existing code, execute the following
commands at the start of your MATLAB session:
warning('on','MATLAB:RandStream:ActivatingLegacyGenerators')
warning('on','MATLAB:RandStream:ReadingInactiveLegacyGeneratorState')
3-34
Replace Discouraged Syntaxes of rand and randn
Description of Replacement Syntaxes
Use the rng function to control the shared generator used by rand, randn, randi and
all other random number generation functions like randperm, sprand, and so on. To
learn how to use the rng function to replace the former syntaxes, take a few moments
to understand what the former syntaxes did. This should help you to see which new rng
syntax best suits your needs.
The first input to the former syntaxes of rand(Generator,s) or randn(Generator,s)
specified the type of the generator, as described here.
Generator = 'seed' referred to the MATLAB v4 generator, not to the seed
initialization value.
Generator = 'state' referred to the MATLAB v5 generators, not to the internal
state of the generator.
Generator = 'twister' referred to the Mersenne Twister generator, now the
MATLAB startup generator.
The v4 and v5 generators are no longer recommended unless you are trying to exactly
reproduce the random numbers generated in earlier versions of MATLAB. The simplest
way to update your code is to use rng. The rng function replaces the names for the rand
and randn generators as follows.
rand/randn Generator Name
rng Generator Name
'seed'
'v4'
'state'
'v5uniform' (for rand)
or
'v5normal' (for randn)
'twister'
'twister' (recommended)
Replacement Syntaxes for Initializing the Generator with an Integer Seed
The most common uses of the integer seed sd in the former rand(Generator,sd)
syntax were to:
• Reproduce exactly the same random numbers each time (e.g., by using a seed such as
0, 1, or 3141879)
3-35
3
Random Numbers
• Try to ensure that MATLAB always gives different random numbers in separate runs
(for example, by using a seed such as sum(100*clock))
The following table shows replacements for syntaxes with an integer seed sd.
• The first column shows the former syntax with rand and randn.
• The second column shows how to exactly reproduce the former behavior with the new
rng function. In most cases, this is done by specifying a legacy generator type such as
the v4 or v5 generators, which is no longer recommended.
• The third column shows the recommended alternative, which does not specify the
optional generator type input to rng. Therefore, if you always omit the Generator
input, rand, randn, and randi just use the default Mersenne Twister generator that
is used at MATLAB startup. In future releases when new generators supersede the
Mersenne Twister, this code will use the new default.
Former rand/randn Syntax
Not Recommended: Reproduce
Recommended
Former Behavior Exactly By Specifying Alternative: Does Not
Generator Type
Override Generator
Type
rand('twister',5489)
rng(5489,'twister')
rand('seed',sd)
randn('seed',sd)
rng('default')
rng(sd,'v4')
rand('state',sd)
rng(sd,'v5uniform')
randn('state',sd)
rng(sd,'v5normal')
rand('seed',sum(100*clock))
rng(sum(100*clock),'v4')
rng(sd)
rng('shuffle')
Replacement Syntaxes for Initializing the Generator with a State Vector
The most common use of the state vector (shown here as st) in the previous
rand(Generator,st) syntax was to reproduce exactly the random numbers generated
at a specific point in an algorithm or iteration. For example, you could use this vector as
an aid in debugging.
The rng function changes the former pattern of saving and restoring the state of the
random number generator as shown in the next table. The example in the left column
assumes that you are using the v5 uniform generator. The example in the right column
uses the new syntax, and works for any generator you use.
3-36
Replace Discouraged Syntaxes of rand and randn
Former Syntax Using rand/randn
New Syntax Using rng
% Save v5 generator state.
st = rand('state');
% Get generator settings.
s = rng;
% Call rand.
x = rand;
% Call rand.
x = rand;
% Restore v5 generator state.
rand('state',st);
% Restore previous generator
% settings.
rng(s);
% Call rand again and hope
% for the same results.
y = rand
% Call rand again and
% get the same results.
y = rand
For a demonstration, see this instructional video.
If You Are Unable to Upgrade from Former Syntax
If there is code that you are not able or not permitted to modify and you know that it uses
the former random number generator control syntaxes, it is important to remember that
when you use that code MATLAB will switch into legacy mode. In legacy mode, rand and
randn are controlled by separate generators, each with their own settings.
Calls to rand in legacy mode use one of the following:
• The 'v4' generator, controlled by rand('seed', ...)
• The 'v5uniform' generator, controlled by rand('state', ...)
• The 'twister' generator, controlled by rand('twister', ...)
Calls to randn in legacy mode use one of the following:
• The 'v4' generator, controlled by randn('seed', ...)
• The 'v5normal' generator, controlled by randn('state', ...)
If code that you rely on puts MATLAB into legacy mode, use the following command to
escape legacy mode and get back to the default startup generator:
rng default
Alternatively, to guard around code that puts MATLAB into legacy mode, use:
3-37
3
Random Numbers
s = rng
...
rng(s)
3-38
% Save current settings of the generator.
% Call code using legacy random number generator syntaxes.
% Restore previous settings of the generator.
4
Sparse Matrices
• “Computational Advantages of Sparse Matrices” on page 4-2
• “Constructing Sparse Matrices” on page 4-4
• “Accessing Sparse Matrices” on page 4-9
• “Sparse Matrix Operations” on page 4-16
4
Sparse Matrices
Computational Advantages of Sparse Matrices
In this section...
“Memory Management” on page 4-2
“Computational Efficiency” on page 4-3
Memory Management
Using sparse matrices to store data that contains a large number of zero-valued elements
can both save a significant amount of memory and speed up the processing of that data.
sparse is an attribute that you can assign to any two-dimensional MATLAB matrix that
is composed of double or logical elements.
The sparse attribute allows MATLAB to:
• Store only the nonzero elements of the matrix, together with their indices.
• Reduce computation time by eliminating operations on zero elements.
For full matrices, MATLAB stores every matrix element internally. Zero-valued elements
require the same amount of storage space as any other matrix element. For sparse
matrices, however, MATLAB stores only the nonzero elements and their indices. For
large matrices with a high percentage of zero-valued elements, this scheme significantly
reduces the amount of memory required for data storage.
The whos command provides high-level information about matrix storage, including size
and storage class. For example, this whos listing shows information about sparse and full
versions of the same matrix.
M_full = magic(1100);
M_full(M_full > 50) = 0;
M_sparse = sparse(M_full);
whos
Name
M_full
M_sparse
Size
1100x1100
1100x1100
% Create 1100-by-1100 matrix.
% Set elements >50 to zero.
% Create sparse matrix of same.
Bytes
9680000
5004
Class
Attributes
double
double
sparse
Notice that the number of bytes used is fewer in the sparse case, because zero-valued
elements are not stored.
4-2
Computational Advantages of Sparse Matrices
Computational Efficiency
Sparse matrices also have significant advantages in terms of computational efficiency.
Unlike operations with full matrices, operations with sparse matrices do not perform
unnecessary low-level arithmetic, such as zero-adds (x+0 is always x). The resulting
efficiencies can lead to dramatic improvements in execution time for programs working
with large amounts of sparse data.
For more information, see “Sparse Matrix Operations” on page 4-16.
4-3
4
Sparse Matrices
Constructing Sparse Matrices
In this section...
“Creating Sparse Matrices” on page 4-4
“Importing Sparse Matrices” on page 4-8
Creating Sparse Matrices
• “Converting Full to Sparse” on page 4-4
• “Creating Sparse Matrices Directly” on page 4-5
• “Creating Sparse Matrices from Their Diagonal Elements” on page 4-7
MATLAB never creates sparse matrices automatically. Instead, you must determine if a
matrix contains a large enough percentage of zeros to benefit from sparse techniques.
The density of a matrix is the number of nonzero elements divided by the total number of
matrix elements. For matrix M, this would be
nnz(M) / prod(size(M));
or
nnz(M) / numel(M);
Matrices with very low density are often good candidates for use of the sparse format.
Converting Full to Sparse
You can convert a full matrix to sparse storage using the sparse function with a single
argument.
S = sparse(A)
For example:
A = [ 0
0
0
2
1
3
0
0
S = sparse(A)
4-4
0
0
0
4
5
0
0
0];
Constructing Sparse Matrices
produces
S =
(3,1)
(2,2)
(3,2)
(4,3)
(1,4)
1
2
3
4
5
The printed output lists the nonzero elements of S, together with their row and column
indices. The elements are sorted by columns, reflecting the internal data structure.
You can convert a sparse matrix to full storage using the full function, provided
the matrix order is not too large. For example A = full(S) reverses the example
conversion.
Converting a full matrix to sparse storage is not the most frequent way of generating
sparse matrices. If the order of a matrix is small enough that full storage is possible, then
conversion to sparse storage rarely offers significant savings.
Creating Sparse Matrices Directly
You can create a sparse matrix from a list of nonzero elements using the sparse function
with five arguments.
S = sparse(i,j,s,m,n)
i and j are vectors of row and column indices, respectively, for the nonzero elements
of the matrix. s is a vector of nonzero values whose indices are specified by the
corresponding (i,j) pairs. m is the row dimension for the resulting matrix, and n is the
column dimension.
The matrix S of the previous example can be generated directly with
S = sparse([3 2 3 4 1],[1 2 2 3 4],[1 2 3 4 5],4,4)
S =
(3,1)
(2,2)
(3,2)
(4,3)
1
2
3
4
4-5
4
Sparse Matrices
(1,4)
5
The sparse command has a number of alternate forms. The example above uses a form
that sets the maximum number of nonzero elements in the matrix to length(s). If
desired, you can append a sixth argument that specifies a larger maximum, allowing you
to add nonzero elements later without reallocating the sparse matrix.
The matrix representation of the second difference operator is a good example of a sparse
matrix. It is a tridiagonal matrix with -2s on the diagonal and 1s on the super- and
subdiagonal. There are many ways to generate it—here's one possibility.
D = sparse(1:n,1:n,-2*ones(1,n),n,n);
E = sparse(2:n,1:n-1,ones(1,n-1),n,n);
S = E+D+E'
For n = 5, MATLAB responds with
S =
(1,1)
(2,1)
(1,2)
(2,2)
(3,2)
(2,3)
(3,3)
(4,3)
(3,4)
(4,4)
(5,4)
(4,5)
(5,5)
-2
1
1
-2
1
1
-2
1
1
-2
1
1
-2
Now F = full(S) displays the corresponding full matrix.
F = full(S)
F =
-2
1
0
0
0
4-6
1
-2
1
0
0
0
1
-2
1
0
0
0
1
-2
1
0
0
0
1
-2
Constructing Sparse Matrices
Creating Sparse Matrices from Their Diagonal Elements
Creating sparse matrices based on their diagonal elements is a common operation, so the
function spdiags handles this task. Its syntax is
S = spdiags(B,d,m,n)
To create an output matrix S of size m-by-n with elements on p diagonals:
• B is a matrix of size min(m,n)-by-p. The columns of B are the values to populate the
diagonals of S.
• d is a vector of length p whose integer elements specify which diagonals of S to
populate.
That is, the elements in column j of B fill the diagonal specified by element j of d.
Note: If a column of B is longer than the diagonal it's replacing, super-diagonals are
taken from the lower part of the column of B, and sub-diagonals are taken from the upper
part of the column of B.
As an example, consider the matrix B and the vector d.
B = [ 41
52
63
74
11
22
33
44
0
0
13
24 ];
d = [-3
0
2];
Use these matrices to create a 7-by-4 sparse matrix A:
A = spdiags(B,d,7,4)
A =
(1,1)
(4,1)
(2,2)
(5,2)
(1,3)
11
41
22
52
13
4-7
4
Sparse Matrices
(3,3)
(6,3)
(2,4)
(4,4)
(7,4)
33
63
24
44
74
In its full form, A looks like this:
full(A)
ans =
11
0
0
41
0
0
0
0
22
0
0
52
0
0
13
0
33
0
0
63
0
0
24
0
44
0
0
74
spdiags can also extract diagonal elements from a sparse matrix, or replace matrix
diagonal elements with new values. Type help spdiags for details.
Importing Sparse Matrices
You can import sparse matrices from computations outside the MATLAB environment.
Use the spconvert function in conjunction with the load command to import text
files containing lists of indices and nonzero elements. For example, consider a threecolumn text file T.dat whose first column is a list of row indices, second column is a list
of column indices, and third column is a list of nonzero values. These statements load
T.dat into MATLAB and convert it into a sparse matrix S:
load T.dat
S = spconvert(T)
The save and load commands can also process sparse matrices stored as binary data in
MAT-files.
4-8
Accessing Sparse Matrices
Accessing Sparse Matrices
In this section...
“Nonzero Elements” on page 4-9
“Indices and Values” on page 4-11
“Indexing in Sparse Matrix Operations” on page 4-11
“Visualizing Sparse Matrices” on page 4-14
Nonzero Elements
There are several commands that provide high-level information about the nonzero
elements of a sparse matrix:
• nnz returns the number of nonzero elements in a sparse matrix.
• nonzeros returns a column vector containing all the nonzero elements of a sparse
matrix.
• nzmax returns the amount of storage space allocated for the nonzero entries of a
sparse matrix.
To try some of these, load the supplied sparse matrix west0479, one of the HarwellBoeing collection.
load west0479
whos
Name
M_full
M_sparse
west0479
Size
1100x1100
1100x1100
479x479
Bytes
9680000
5004
24564
Class
Attributes
double
double
double
sparse
sparse
This matrix models an eight-stage chemical distillation column.
Try these commands.
nnz(west0479)
ans =
1887
format short e
4-9
4
Sparse Matrices
west0479
west0479 =
(25,1)
(31,1)
(87,1)
(26,2)
(31,2)
(88,2)
(27,3)
(31,3)
(89,3)
(28,4)
.
.
.
1.0000e+00
-3.7648e-02
-3.4424e-01
1.0000e+00
-2.4523e-02
-3.7371e-01
1.0000e+00
-3.6613e-02
-8.3694e-01
1.3000e+02
nonzeros(west0479);
ans =
1.0000e+00
-3.7648e-02
-3.4424e-01
1.0000e+00
-2.4523e-02
-3.7371e-01
1.0000e+00
-3.6613e-02
-8.3694e-01
1.3000e+02
.
.
.
Note: Use Ctrl+C to stop the nonzeros listing at any time.
Note that initially nnz has the same value as nzmax by default. That is, the number of
nonzero elements is equivalent to the number of storage locations allocated for nonzeros.
However, MATLAB does not dynamically release memory if you zero out additional array
4-10
Accessing Sparse Matrices
elements. Changing the value of some matrix elements to zero changes the value of nnz,
but not that of nzmax.
However, you can add as many nonzero elements to the matrix as desired. You are not
constrained by the original value of nzmax.
Indices and Values
For any matrix, full or sparse, the find function returns the indices and values of
nonzero elements. Its syntax is
[i,j,s] = find(S)
find returns the row indices of nonzero values in vector i, the column indices in vector
j, and the nonzero values themselves in the vector s. The example below uses find to
locate the indices and values of the nonzeros in a sparse matrix. The sparse function
uses the find output, together with the size of the matrix, to recreate the matrix.
[i,j,s] = find(S)
[m,n] = size(S)
S = sparse(i,j,s,m,n)
Indexing in Sparse Matrix Operations
Because sparse matrices are stored in compressed sparse column format, there are
different costs associated with indexing into a sparse matrix than there are with indexing
into a full matrix. Such costs are negligible when you need to change only a few elements
in a sparse matrix, so in those cases it’s normal to use regular array indexing to reassign
values:
B = speye(4);
[i,j,s] = find(B);
[i,j,s]
ans =
1
2
3
4
1
2
3
4
1
1
1
1
4-11
4
Sparse Matrices
B(3,1) = 42;
[i,j,s] = find(B);
[i,j,s]
ans =
1
3
2
3
4
1
1
2
3
4
1
42
1
1
1
In order to store the new matrix with 42 at (3,1), MATLAB inserts an additional row
into the nonzero values vector and subscript vectors, then shifts all matrix values after
(3,1).
Using linear indexing to access or assign an element in a large sparse matrix will fail if
the linear index exceeds intmax.
S = spalloc(2^30,2^30,2)
S(end) = 1
Maximum variable size allowed by the program is exceeded.
To access an element whose linear index is greater than intmax, use array indexing:
S(2^30,2^30) = 1
S =
(1073741824,1073741824)
1
While the cost of indexing into a sparse matrix to change a single element is negligible, it
is compounded in the context of a loop and can become quite slow for large matrices. For
that reason, in cases where many sparse matrix elements need to be changed, it is best
to vectorize the operation instead of using a loop. For example, consider a sparse identity
matrix:
n = 10000;
A = 4*speye(n);
Changing the elements of A within a loop takes considerably more time than a similar
vectorized operation:
tic; A(1:n-1,n) = -1; A(n,1:n-1) = -1; toc
4-12
Accessing Sparse Matrices
Elapsed time is 0.001899 seconds.
tic; for k = 1:n-1, C(k,n) = -1; C(n,k) = -1; end, toc
Elapsed time is 0.286563 seconds.
The difference in execution time in this example is over two orders of magnitude. Since
MATLAB stores sparse matrices in compressed sparse column format, it needs to shift
multiple entries in A during each pass through the loop.
Preallocating the memory for a sparse matrix and then filling it in an element-wise
manner similarly causes a significant amount of overhead in indexing into the sparse
array:
S1 = spalloc(1000,1000,100000);
tic;
for n = 1:100000
i = ceil(1000*rand(1,1));
j = ceil(1000*rand(1,1));
S1(i,j) = rand(1,1);
end
toc
Elapsed time is 26.281000 seconds.
Constructing the vectors of indices and values eliminates the need to index into the
sparse array, and thus is significantly faster:
i =
j =
v =
for
ceil(1000*rand(100000,1));
ceil(1000*rand(100000,1));
zeros(size(i));
n = 1:100000
v(n) = rand(1,1);
end
tic;
S2 = sparse(i,j,v,1000,1000);
toc
Elapsed time is 0.078000 seconds.
For that reason, it’s best to construct sparse matrices all at once using a construction
function, like the sparse or spdiags functions.
For example, suppose you wanted the sparse form of the coordinate matrix C:
4-13
4
Sparse Matrices
Ê4
Á
Á0
C = Á0
Á
Á0
Á1
Ë
0
4
0
0
1
0
0
4
0
1
0
0
0
4
1
-1ˆ
˜
-1˜
-1˜
˜
-1˜
4 ˜¯
Construct the five-column matrix directly with the sparse function using the triplet
pairs for the row subscripts, column subscripts, and values:
i
j
s
C
C
=
=
=
=
=
[1 5 2 5 3 5 4 5 1 2 3 4 5]';
[1 1 2 2 3 3 4 4 5 5 5 5 5]';
[4 1 4 1 4 1 4 1 -1 -1 -1 -1 4]';
sparse(i,j,s)
(1,1)
(5,1)
(2,2)
(5,2)
(3,3)
(5,3)
(4,4)
(5,4)
(1,5)
(2,5)
(3,5)
(4,5)
(5,5)
4
1
4
1
4
1
4
1
-1
-1
-1
-1
4
The ordering of the values in the output reflects the underlying storage by columns. For
more information on how MATLAB stores sparse matrices, see John R. Gilbert, Cleve
Moler, and Robert Schreiber's Sparse Matrices In Matlab: Design and Implementation,
(SIAM Journal on Matrix Analysis and Applications, 13:1, 333–356 (1992)).
Visualizing Sparse Matrices
It is often useful to use a graphical format to view the distribution of the nonzero
elements within a sparse matrix. The MATLAB spy function produces a template view of
the sparsity structure, where each point on the graph represents the location of a nonzero
array element.
For example:
4-14
Accessing Sparse Matrices
Load the supplied sparse matrix west0479, one of the Harwell-Boeing collection.
load west0479
View the sparsity structure.
spy(west0479)
4-15
4
Sparse Matrices
Sparse Matrix Operations
In this section...
“Efficiency of Operations” on page 4-16
“Permutations and Reordering” on page 4-17
“Factoring Sparse Matrices” on page 4-21
“Systems of Linear Equations” on page 4-29
“Eigenvalues and Singular Values” on page 4-32
“References” on page 4-35
Efficiency of Operations
• “Computational Complexity” on page 4-16
• “Algorithmic Details” on page 4-16
Computational Complexity
The computational complexity of sparse operations is proportional to nnz, the number
of nonzero elements in the matrix. Computational complexity also depends linearly on
the row size m and column size n of the matrix, but is independent of the product m*n, the
total number of zero and nonzero elements.
The complexity of fairly complicated operations, such as the solution of sparse linear
equations, involves factors like ordering and fill-in, which are discussed in the previous
section. In general, however, the computer time required for a sparse matrix operation is
proportional to the number of arithmetic operations on nonzero quantities.
Algorithmic Details
Sparse matrices propagate through computations according to these rules:
• Functions that accept a matrix and return a scalar or constant-size vector always
produce output in full storage format. For example, the size function always returns
a full vector, whether its input is full or sparse.
• Functions that accept scalars or vectors and return matrices, such as zeros, ones,
rand, and eye, always return full results. This is necessary to avoid introducing
4-16
Sparse Matrix Operations
sparsity unexpectedly. The sparse analog of zeros(m,n) is simply sparse(m,n).
The sparse analogs of rand and eye are sprand and speye, respectively. There is no
sparse analog for the function ones.
• Unary functions that accept a matrix and return a matrix or vector preserve the
storage class of the operand. If S is a sparse matrix, then chol(S) is also a sparse
matrix, and diag(S) is a sparse vector. Columnwise functions such as max and
sum also return sparse vectors, even though these vectors can be entirely nonzero.
Important exceptions to this rule are the sparse and full functions.
• Binary operators yield sparse results if both operands are sparse, and full results if
both are full. For mixed operands, the result is full unless the operation preserves
sparsity. If S is sparse and F is full, then S+F, S*F, and F\S are full, while S.*F and
S&F are sparse. In some cases, the result might be sparse even though the matrix has
few zero elements.
• Matrix concatenation using either the cat function or square brackets produces
sparse results for mixed operands.
• Submatrix indexing on the right side of an assignment preserves the storage format
of the operand unless the result is a scalar. T = S(i,j) produces a sparse result
if S is sparse and either i or j is a vector. It produces a full scalar if both i and j
are scalars. Submatrix indexing on the left, as in T(i,j) = S, does not change the
storage format of the matrix on the left.
Permutations and Reordering
• “Reordering for Sparsity” on page 4-19
• “Reordering to Reduce Bandwidth” on page 4-20
• “Approximate Minimum Degree Ordering” on page 4-20
A permutation of the rows and columns of a sparse matrix S can be represented in two
ways:
• A permutation matrix P acts on the rows of S as P*S or on the columns as S*P'.
• A permutation vector p, which is a full vector containing a permutation of 1:n, acts on
the rows of S as S(p,:), or on the columns as S(:,p).
For example, the statements
p = [1 3 4 2 5]
I = eye(5,5);
4-17
4
Sparse Matrices
P = I(p,:);
e = ones(4,1);
S = diag(11:11:55) + diag(e,1) + diag(e,-1)
produce:
p =
1
3
4
2
5
1
0
0
0
0
0
0
0
1
0
0
1
0
0
0
0
0
1
0
0
0
0
0
0
1
11
1
0
0
0
1
22
1
0
0
0
1
33
1
0
0
0
1
44
1
0
0
0
1
55
P =
S =
You can now try some permutations using the permutation vector p and the permutation
matrix P. For example, the statements S(p,:) and P*S produce
ans =
11
0
0
1
0
1
1
0
22
0
0
33
1
1
0
0
1
44
0
1
0
0
1
0
55
Similarly, S(:,p) and S*P' produce
ans =
11
1
0
0
4-18
0
1
33
1
0
0
1
44
1
22
1
0
0
0
0
1
Sparse Matrix Operations
0
0
1
0
55
If P is a sparse matrix, then both representations use storage proportional to n and
you can apply either to S in time proportional to nnz(S). The vector representation
is slightly more compact and efficient, so the various sparse matrix permutation
routines all return full row vectors with the exception of the pivoting permutation
in LU (triangular) factorization, which returns a matrix compatible with the full LU
factorization.
To convert between the two representations, let I = speye(n) be an identity matrix of
the appropriate size. Then,
P = I(p,:)
P' = I(:,p)
p = (1:n)*P'
p = (P*(1:n)')'
The inverse of P is simply R = P'. You can compute the inverse of p with r(p) = 1:n.
r(p) = 1:5
r =
1
4
2
3
5
Reordering for Sparsity
Reordering the columns of a matrix can often make its LU or QR factors sparser.
Reordering the rows and columns can often make its Cholesky factors sparser. The
simplest such reordering is to sort the columns by nonzero count. This is sometimes a
good reordering for matrices with very irregular structures, especially if there is great
variation in the nonzero counts of rows or columns.
The function p = colperm(S) computes this column-count permutation. The colperm
code has only a single line.
[ignore,p] = sort(sum(spones(S)));
This line performs these steps:
1
The inner call to spones creates a sparse matrix with ones at the location of every
nonzero element in S.
4-19
4
Sparse Matrices
2
The sum function sums down the columns of the matrix, producing a vector that
contains the count of nonzeros in each column.
3
full converts this vector to full storage format.
4
sort sorts the values in ascending order. The second output argument from sort is
the permutation that sorts this vector.
Reordering to Reduce Bandwidth
The reverse Cuthill-McKee ordering is intended to reduce the profile or bandwidth of the
matrix. It is not guaranteed to find the smallest possible bandwidth, but it usually does.
The function symrcm(A) actually operates on the nonzero structure of the symmetric
matrix A + A', but the result is also useful for asymmetric matrices. This ordering is
useful for matrices that come from one-dimensional problems or problems that are in
some sense “long and thin.”
Approximate Minimum Degree Ordering
The degree of a node in a graph is the number of connections to that node. This is the
same as the number of off-diagonal nonzero elements in the corresponding row of the
adjacency matrix. The approximate minimum degree algorithm generates an ordering
based on how these degrees are altered during Gaussian elimination or Cholesky
factorization. It is a complicated and powerful algorithm that usually leads to sparser
factors than most other orderings, including column count and reverse Cuthill-McKee.
Because the keeping track of the degree of each node is very time-consuming, the
approximate minimum degree algorithm uses an approximation to the degree, rather
than the exact degree.
The following MATLAB functions implement the approximate minimum degree
algorithm:
• symamd — Use with symmetric matrices.
• colamd — Use with nonsymmetric matrices and symmetric matrices of the form A*A'
or A'*A.
See “Reordering and Factorization” on page 4-22 for an example using symamd.
You can change various parameters associated with details of the algorithms using the
spparms function.
For details on the algorithms used by colamd and symamd, see [5]. The approximate
degree the algorithms use is based on [1].
4-20
Sparse Matrix Operations
Factoring Sparse Matrices
• “LU Factorization” on page 4-21
• “Cholesky Factorization” on page 4-25
• “QR Factorization” on page 4-26
• “Incomplete Factorizations” on page 4-27
LU Factorization
If S is a sparse matrix, the following command returns three sparse matrices L, U, and P
such that P*S = L*U.
[L,U,P] = lu(S)
lu obtains the factors by Gaussian elimination with partial pivoting. The permutation
matrix P has only n nonzero elements. As with dense matrices, the statement [L,U] =
lu(S) returns a permuted unit lower triangular matrix and an upper triangular matrix
whose product is S. By itself, lu(S) returns L and U in a single matrix without the pivot
information.
The three-output syntax
[L,U,P] = lu(S)
selects P via numerical partial pivoting, but does not pivot to improve sparsity in the LU
factors. On the other hand, the four-output syntax
[L,U,P,Q]=lu(S)
selects P via threshold partial pivoting, and selects P and Q to improve sparsity in the LU
factors.
You can control pivoting in sparse matrices using
lu(S,thresh)
where thresh is a pivot threshold in [0,1]. Pivoting occurs when the diagonal entry in a
column has magnitude less than thresh times the magnitude of any sub-diagonal entry
in that column. thresh = 0 forces diagonal pivoting. thresh = 1 is the default. (The
default for thresh is 0.1 for the four-output syntax).
4-21
4
Sparse Matrices
When you call lu with three or less outputs, MATLAB automatically allocates the
memory necessary to hold the sparse L and U factors during the factorization. Except
for the four-output syntax, MATLAB does not use any symbolic LU prefactorization to
determine the memory requirements and set up the data structures in advance.
Reordering and Factorization
This example shows the effects of reordering and factorization on sparse matrices.
If you obtain a good column permutation p that reduces fill-in, perhaps from symrcm
or colamd, then computing lu(S(:,p)) takes less time and storage than computing
lu(S).
Create a sparse matrix using the Bucky ball example.
B = bucky;
B has exactly three nonzero elements in each row and column.
Create two permutations, r and m using symrcm and symamd respectively.
r = symrcm(B);
m = symamd(B);
The two permutations are the symmetric reverse Cuthill-McKee ordering and the
symmetric approximate minimum degree ordering.
Create spy plots to show the three adjacency matrices of the Bucky Ball graph with
these three different numberings. The local, pentagon-based structure of the original
numbering is not evident in the others.
figure
subplot(1,3,1)
spy(B)
title('Original')
subplot(1,3,2)
spy(B(r,r))
title('Reverse Cuthill-McKee')
subplot(1,3,3)
spy(B(m,m))
title('Approx Min Degree')
4-22
Sparse Matrix Operations
The reverse Cuthill-McKee ordering, r, reduces the bandwidth and concentrates all the
nonzero elements near the diagonal. The approximate minimum degree ordering, m,
produces a fractal-like structure with large blocks of zeros.
To see the fill-in generated in the LU factorization of the Bucky ball, use speye, the
sparse identity matrix, to insert -3s on the diagonal of B.
B = B - 3*speye(size(B));
Since each row sum is now zero, this new B is actually singular, but it is still instructive
to compute its LU factorization. When called with only one output argument, lu returns
the two triangular factors, L and U, in a single sparse matrix. The number of nonzeros
4-23
4
Sparse Matrices
in that matrix is a measure of the time and storage required to solve linear systems
involving B.
Here are the nonzero counts for the three permutations being considered.
• lu(B) (Original): 1022
• lu(B(r,r)) (Reverse Cuthill-McKee): 968
• lu(B(m,m)) (Approximate minimum degree): 636
Even though this is a small example, the results are typical. The original numbering
scheme leads to the most fill-in. The fill-in for the reverse Cuthill-McKee ordering is
concentrated within the band, but it is almost as extensive as the first two orderings.
For the approximate minimum degree ordering, the relatively large blocks of zeros are
preserved during the elimination and the amount of fill-in is significantly less than that
generated by the other orderings.
The spy plots below reflect the characteristics of each reordering.
figure
subplot(1,3,1)
spy(lu(B))
title('Original')
subplot(1,3,2)
spy(lu(B(r,r)))
title('Reverse Cuthill-McKee')
subplot(1,3,3)
spy(lu(B(m,m)))
title('Approx Min Degree')
4-24
Sparse Matrix Operations
Cholesky Factorization
If S is a symmetric (or Hermitian), positive definite, sparse matrix, the statement below
returns a sparse, upper triangular matrix R so that R'*R = S.
R = chol(S)
chol does not automatically pivot for sparsity, but you can compute approximate
minimum degree and profile limiting permutations for use with chol(S(p,p)).
Since the Cholesky algorithm does not use pivoting for sparsity and does not require
pivoting for numerical stability, chol does a quick calculation of the amount of memory
required and allocates all the memory at the start of the factorization. You can use
4-25
4
Sparse Matrices
symbfact, which uses the same algorithm as chol, to calculate how much memory is
allocated.
QR Factorization
MATLAB computes the complete QR factorization of a sparse matrix S with
[Q,R] = qr(S)
or
[Q,R,E] = qr(S)
but this is often impractical. The unitary matrix Q often fails to have a high proportion
of zero elements. A more practical alternative, sometimes known as “the Q-less QR
factorization,” is available.
With one sparse input argument and one output argument
R = qr(S)
returns just the upper triangular portion of the QR factorization. The matrix R provides a
Cholesky factorization for the matrix associated with the normal equations:
R'*R = S'*S
However, the loss of numerical information inherent in the computation of S'*S is
avoided.
With two input arguments having the same number of rows, and two output arguments,
the statement
[C,R] = qr(S,B)
applies the orthogonal transformations to B, producing C = Q'*B without computing Q.
The Q-less QR factorization allows the solution of sparse least squares problems
minimize Ax - b
2
with two steps
[c,R] = qr(A,b)
x = R\c
If A is sparse, but not square, MATLAB uses these steps for the linear equation solving
backslash operator:
4-26
Sparse Matrix Operations
x = A\b
Or, you can do the factorization yourself and examine R for rank deficiency.
It is also possible to solve a sequence of least squares linear systems with different
right-hand sides, b, that are not necessarily known when R = qr(A) is computed. The
approach solves the “semi-normal equations”
R'*R*x = A'*b
with
x = R\(R'\(A'*b))
and then employs one step of iterative refinement to reduce round off error:
r = b - A*x
e = R\(R'\(A'*r))
x = x + e
Incomplete Factorizations
The ilu and ichol functions provide approximate, incomplete factorizations, which are
useful as preconditioners for sparse iterative methods.
The ilu function produces three incomplete lower-upper (ILU) factorizations: the zerofill ILU (ILU(0)), a Crout version of ILU (ILUC(tau)), and ILU with threshold dropping
and pivoting (ILUTP(tau)). The ILU(0) never pivots and the resulting factors only
have nonzeros in positions where the input matrix had nonzeros. Both ILUC(tau) and
ILUTP(tau), however, do threshold-based dropping with the user-defined drop tolerance
tau.
For example:
A = gallery('neumann', 1600) + speye(1600);
nnz(A)
ans =
7840
nnz(lu(A))
ans =
126478
shows that A has 7840 nonzeros, and its complete LU factorization has 126478 nonzeros.
On the other hand, the following code shows the different ILU outputs:
4-27
4
Sparse Matrices
[L,U] = ilu(A);
nnz(L)+nnz(U)-size(A,1);
ans =
7840
norm(A-(L*U).*spones(A),’fro’)./norm(A,’fro’)
ans =
4.8874e-017
opts.type = 'ilutp';
opts.droptol = 1e-4;
[L,U,P] = ilu(A, opts);
nnz(L)+nnz(U)-size(A,1)
ans =
31147
norm(P*A - L*U,’fro’)./norm(A,’fro’)
ans =
9.9224e-005
opts.type = ‘crout’;
nnz(L)+nnz(U)-size(A,1)
ans =
31083
norm(P*A-L*U,'fro')./norm(A,'fro')
ans =
9.7344e-005
These calculations show that the zero-fill factors have 7840 nonzeros, the ILUTP(1e-4)
factors have 31147 nonzeros, and the ILUC(1e-4) factors have 31083 nonzeros. Also,
the relative error of the product of the zero-fill factors is essentially zero on the pattern
of A. Finally, the relative error in the factorizations produced with threshold dropping is
on the same order of the drop tolerance, although this is not guaranteed to occur. See the
ilu reference page for more options and details.
The ichol function provides zero-fill incomplete Cholesky factorizations (IC(0)) as
well as threshold-based dropping incomplete Cholesky factorizations (ICT(tau)) of
symmetric, positive definite sparse matrices. These factorizations are the analogs of
the incomplete LU factorizations above and have many of the same characteristics. For
example:
A = delsq(numgrid('S',200));
nnz(A)
ans =
4-28
Sparse Matrix Operations
195228
nnz(chol(A,'lower'))
ans =
7762589
shows that A has 195228 nonzeros, and its complete Cholesky factorization without
reordering has 7762589 nonzeros. By contrast:
L = ichol(A);
nnz(L)
ans =
117216
norm(A-(L*L').*spones(A),'fro')./norm(A,'fro')
ans =
3.5805e-017
opts.type = 'ict';
opts.droptol = 1e-4;
L = ichol(A,opts);
nnz(L)
ans =
1166754
norm(A-L*L','fro')./norm(A,'fro')
ans =
2.3997e-004
IC(0) has nonzeros only in the pattern of the lower triangle of A, and on the pattern
of A, the product of the factors matches. Also, the ICT(1e-4) factors are considerably
sparser than the complete Cholesky factor, and the relative error between A and L*L'
is on the same order of the drop tolerance. It is important to note that unlike the factors
provided by chol, the default factors provided by ichol are lower triangular. See the
ichol reference page for more information.
Systems of Linear Equations
There are two different classes of methods for solving systems of simultaneous linear
equations:
• Direct methods are usually variants of Gaussian elimination. These methods involve
the individual matrix elements directly, through matrix operations such as LU or
Cholesky factorization. MATLAB implements direct methods through the matrix
division operators / and \, which you can use to solve linear systems.
4-29
4
Sparse Matrices
• Iterative methods produce only an approximate solution after a finite number of steps.
These methods involve the coefficient matrix only indirectly, through a matrix-vector
product or an abstract linear operator. Iterative methods are usually applied only to
sparse matrices.
Direct Methods
Direct methods are usually faster and more generally applicable than indirect methods,
if there is enough storage available to carry them out. Iterative methods are usually
applicable to restricted cases of equations and depend on properties like diagonal
dominance or the existence of an underlying differential operator. Direct methods are
implemented in the core of the MATLAB software and are made as efficient as possible
for general classes of matrices. Iterative methods are usually implemented in MATLABlanguage files and can use the direct solution of subproblems or preconditioners.
Using a Different Preordering
If A is not diagonal, banded, triangular, or a permutation of a triangular matrix,
backslash (\) reorders the indices of A to reduce the amount of fill-in—that is, the
number of nonzero entries that are added to the sparse factorization matrices. The new
ordering, called a preordering, is performed before the factorization of A. In some cases,
you might be able to provide a better preordering than the one used by the backslash
algorithm.
To use a different preordering, first turn off both of the automatic preorderings that
backslash might perform by default, using the function spparms as follows:
currentParms = spparms;
spparms('autoamd',0);
spparms('autommd',0);
Now, assuming you have created a permutation vector p that specifies a preordering of
the indices of A, apply backslash to the matrix A(:,p), whose columns are the columns
of A, permuted according to the vector p.
x = A (:,p) \ b;
x(p) = x;
spparms(currentParms);
The command spparms(defaultParms) restores the controls to their prior state, in
case you use A\b later without specifying an appropriate preordering.
4-30
Sparse Matrix Operations
Iterative Methods
Eleven functions are available that implement iterative methods for sparse systems of
simultaneous linear systems.
Functions for Iterative Methods for Sparse Systems
Function
Method
bicg
Biconjugate gradient
bicgstab
Biconjugate gradient stabilized
bicgstabl
Biconjugate gradient stabilized (l)
cgs
Conjugate gradient squared
gmres
Generalized minimum residual
lsqr
Least squares
minres
Minimum residual
pcg
Preconditioned conjugate gradient
qmr
Quasiminimal residual
symmlq
Symmetric LQ
tfqmr
Transpose-free quasiminimal residual
These methods are designed to solve Ax = b or minimize the norm of b – Ax. For the
Preconditioned Conjugate Gradient method, pcg, A must be a symmetric, positive
definite matrix. minres and symmlq can be used on symmetric indefinite matrices. For
lsqr, the matrix need not be square. The other seven can handle nonsymmetric, square
matrices and each method has a distinct benefit.
All eleven methods can make use of preconditioners. The linear system
Ax = b
is replaced by the equivalent system
M -1 Ax = M -1b
The preconditioner M is chosen to accelerate convergence of the iterative method. In
many cases, the preconditioners occur naturally in the mathematical model. A partial
4-31
4
Sparse Matrices
differential equation with variable coefficients can be approximated by one with constant
coefficients, for example. Incomplete matrix factorizations can be used in the absence of
natural preconditioners.
The five-point finite difference approximation to Laplace's equation on a square,
two-dimensional domain provides an example. The following statements use the
preconditioned conjugate gradient method preconditioner M = L*L', where L is the zerofill incomplete Cholesky factor of A.
A = delsq(numgrid('S',50));
b = ones(size(A,1),1);
tol = 1e-3;
maxit = 100;
L = ichol(A);
[x,flag,err,iter,res] = pcg(A,b,tol,maxit,L,L');
Twenty-one iterations are required to achieve the prescribed accuracy. On the other
hand, using a different preconditioner may yield better results. For example, using
ichol to construct a modified incomplete Cholesky, the prescribed accuracy is met after
only 15 iterations:
L = ichol(A,struct('type','nofill','michol','on'));
[x,flag,err,iter,res] = pcg(A,b,tol,maxit,L,L');
Background information on these iterative methods and incomplete factorizations is
available in [2] and [6].
Eigenvalues and Singular Values
Two functions are available that compute a few specified eigenvalues or singular values.
svds is based on eigs.
Functions to Compute a Few Eigenvalues or Singular Values
Function
Description
eigs
Few eigenvalues
svds
Few singular values
These functions are most frequently used with sparse matrices, but they can be used
with full matrices or even with linear operators defined in MATLAB code.
The statement
4-32
Sparse Matrix Operations
[V,lambda] = eigs(A,k,sigma)
finds the k eigenvalues and corresponding eigenvectors of the matrix A that are nearest
the “shift” sigma. If sigma is omitted, the eigenvalues largest in magnitude are found. If
sigma is zero, the eigenvalues smallest in magnitude are found. A second matrix, B, can
be included for the generalized eigenvalue problem: Aυ = λBυ.
The statement
[U,S,V] = svds(A,k)
finds the k largest singular values of A and
[U,S,V] = svds(A,k,0)
finds the k smallest singular values.
This example shows how to find the smallest eigenvalue and eigenvector of a sparse
matrix.
Set up the five-point Laplacian difference operator on a 65-by-65 grid in an L-shaped,
two-dimensional domain.
L = numgrid('L',65);
A = delsq(L);
Determine the order and number of nonzero elements.
size(A)
nnz(A)
ans =
2945
2945
ans =
14473
A is a matrix of order 2945 with 14,473 nonzero elements.
4-33
4
Sparse Matrices
Compute the smallest eigenvalue and eigenvector.
[v,d] = eigs(A,1,0);
Distribute the components of the eigenvector over the appropriate grid points and
produce a contour plot of the result.
L(L>0) = full(v(L(L>0)));
x = -1:1/32:1;
contour(x,x,L,15)
axis square
The numerical techniques used in eigs and svds are described in [6].
4-34
Sparse Matrix Operations
References
[1] Amestoy, P. R., T. A. Davis, and I. S. Duff, “An Approximate Minimum Degree
Ordering Algorithm,” SIAM Journal on Matrix Analysis and Applications, Vol.17,
No. 4, Oct. 1996, pp. 886-905.
[2] Barrett, R., M. Berry, T. F. Chan, et al., Templates for the Solution of Linear Systems:
Building Blocks for Iterative Methods, SIAM, Philadelphia, 1994.
[3] Davis, T.A., Gilbert, J. R., Larimore, S.I., Ng, E., Peyton, B., “A Column Approximate
Minimum Degree Ordering Algorithm,” Proc.SIAM Conference on Applied Linear
Algebra, Oct. 1997, p. 29.
[4] Gilbert, John R., Cleve Moler, and Robert Schreiber, “Sparse Matrices in MATLAB:
Design and Implementation,” SIAM J. Matrix Anal. Appl., Vol. 13, No. 1,
January 1992, pp. 333-356.
[5] Larimore, S. I., An Approximate Minimum Degree Column Ordering Algorithm, MS
Thesis, Dept. of Computer and Information Science and Engineering, University
of Florida, Gainesville, FL, 1998.
[6] Saad, Yousef, Iterative Methods for Sparse Linear Equations. PWS Publishing
Company, 1996.
4-35
5
Graph and Network Algorithms
• “Directed and Undirected Graphs” on page 5-2
• “Modify Nodes and Edges of Existing Graph” on page 5-11
• “Add Graph Node Names, Edge Weights, and Other Attributes” on page 5-15
• “Graph Plotting and Customization” on page 5-20
• “Build Watts-Strogatz Small World Graph Model” on page 5-33
• “Visualize Breadth-First and Depth-First Search” on page 5-42
• “Use Page Rank Algorithm to Rank Websites” on page 5-46
5
Graph and Network Algorithms
Directed and Undirected Graphs
In this section...
“What Is a Graph?” on page 5-2
“Creating Graphs” on page 5-4
“Graph Node IDs” on page 5-9
“Modify an Existing Graph” on page 5-9
What Is a Graph?
A graph is a collection of nodes and edges that represents relationships:
• Nodes are vertices that correspond to objects.
• Edges are the connections between objects.
• The graph edges sometimes have Weights, which indicate the strength (or some other
attribute) of each connection between the nodes.
These definitions are general, as the exact meaning of the nodes and edges in a graph
depends on the specific application. For instance, you can model the friendships in a
social network using a graph. The graph nodes are people, and the edges represent
friendships. The natural correspondence of graphs to physical objects and situations
means that you can use graphs to model a wide variety of systems. For example:
• The Internet — The graph nodes are computers, and the edges are network
connections between computers.
• A brain — The graph nodes are neurons, and the edges represent neuron connections.
• Web page linking — The graph nodes are web pages, and the edges represent links
between pages.
• Airports — The graph nodes are airports, and the edges represent flights between
airports.
In MATLAB, the graph and digraph functions construct objects that represent
undirected and directed graphs.
• Undirected graphs have edges that do not have a direction. The edges indicate a
two-way relationship, in that each edge can be traversed in both directions. The figure
below shows a simple undirected graph with three nodes and three edges.
5-2
Directed and Undirected Graphs
• Directed graphs have edges with direction. The edges indicate a one-way
relationship, in that each edge can only be traversed in a single direction. The figure
below shows a simple directed graph with three nodes and two edges.
5-3
5
Graph and Network Algorithms
The exact position, length, or orientation of the edges in a graph illustration typically do
not have meaning. In other words, the same graph can be visualized in several different
ways by rearranging the nodes and/or distorting the edges, as long as the underlying
structure does not change.
Graphs created using graph and digraph can have self-loops (an edge connecting a node
to itself). However, graphs cannot have multiple edges with the same source and target
nodes.
Creating Graphs
The primary ways to create a graph are to use an adjacency matrix or an edge list.
5-4
Directed and Undirected Graphs
Adjacency Matrix
One way to represent the information in a graph is with a square adjacency matrix.
The nonzero entries in an adjacency matrix indicate an edge between two nodes, and
the value of the entry indicates the weight of the edge. The diagonal elements of an
adjacency matrix are typically zero, but a nonzero diagonal element indicates a self-loop,
or a node that is connected to itself by an edge.
• The adjacency matrix for undirected graphs created by graph must be symmetric.
Although, in practice the matrices are frequently triangular to avoid repetition. Use
graph(A,'upper') or graph(A,'lower') to construct an undirected graph using
only the upper or lower triangle of the adjacency matrix.
• The adjacency matrix for a directed graph created by digraph does not need to be
symmetric.
• For large graphs, the adjacency matrix contains many zeros and is typically a sparse
matrix.
For example, consider this undirected graph.
5-5
5
Graph and Network Algorithms
You can represent the graph with this adjacency matrix.
Ê0 1 2ˆ
Á
˜
Á1 0 3 ˜ .
Á2 3 0˜
Ë
¯
To construct the graph in MATLAB, input:
A = [0 1 2; 1 0 3; 2 3 0];
node_names = {'A','B','C'};
G = graph(A,node_names)
5-6
Directed and Undirected Graphs
You can use adjacency matrices to create a graph using the graph or digraph functions,
or you can use the adjacency function to find the unweighted sparse adjacency matrix
of a pre-existing graph.
Edge List
Another way to represent the information in a graph is by listing all of the edges. For
connected graphs, the graph nodes are implied by the list of the graph edges. However,
some graphs have disconnected nodes that need to be listed separately.
For example, consider the same undirected graph.
Now represent the graph by the edge list
5-7
5
Graph and Network Algorithms
Edge
( A, B)
( A, C)
( B, C)
Weight
1
2
3
From the edge list it is easy to conclude that the graph has three unique nodes, A, B, and
C, which are connected by the three listed edges.
In MATLAB, the list of edges is separated by column into source nodes and target nodes.
For directed graphs the edge direction (from source to target) is important, but for
undirected graphs the source and target node are interchangeable. One way to construct
this graph using the edge list is to use separate inputs for the source nodes, target nodes,
and edge weights:
source_nodes = {'A','A','B'};
target_nodes = {'B','C','C'};
edge_weights = [1 2 3];
G = graph(source_nodes, target_nodes, edge_weights)
Another way to construct a graph from the edge list is by creating a table with the
appropriate variables. When using this method, the first variable in the table must be
a two column matrix or cell array of strings named EndNodes. To construct this graph
using a table, input:
EdgeTable = table({'A' 'B'; 'A' 'C'; 'B' 'C'},[1 2 3]', ...
'VariableNames',{'EndNodes','Weight'});
G = graph(EdgeTable)
Both graph and digraph permit construction of a graph from the edge list. After
constructing a graph, G, you can look at the edges (and any properties they might have)
with G.Edges. The order of the edges in G.Edges is sorted by source node (first column)
and secondarily by target node (second column).
Since the underlying implementation of graph and digraph depends on sparse
matrices, many of the same indexing costs apply. Ultimately, it is quickest to construct
a graph all at once from the triplet pairs (source,target,weight) using one of the
aforementioned methods, instead of creating an empty graph and iteratively adding more
nodes and edges. Performance is best when you minimize the number of calls to graph,
digraph, addedge, addnode, rmedge, and rmnode.
5-8
Directed and Undirected Graphs
Graph Node IDs
By default, all of the nodes in a graph created using graph or digraph are numbered.
Thus, it’s always an option to refer to the nodes in a graph by their numeric node index.
If the graph has node names (that is, G.Nodes contains a variable Name), then you also
can refer to the nodes in a graph using their names. Thus, named nodes in a graph can be
referred to by either their node indices or node names. For example, node 1 can be called,
'A'.
The term node ID encompasses both aspects of node identification. The node ID of a node
refers to both the node index and the node name.
For convenience, MATLAB remembers which type of node ID you use in calling most
graph functions. So if you refer to the nodes in a graph by their node indices, most graph
functions return a numeric answer that also refers to the nodes by their indices.
A = [0 1 1 0; 1 0 1 0; 1 1 0 1; 0 0 1 0];
G = graph(A,{'a','b','c','d'});
p = shortestpath(G,1,4)
p =
1
3
4
However, if you refer to the nodes by their names, then most graph functions return an
answer that also refers to the nodes by their names (contained in a cell array of strings).
p1 = shortestpath(G,'a','d')
p1 =
'a'
'c'
'd'
Use findnode to find the numeric node ID for a given node name. Conversely, for a
given numeric node ID, index into G.Nodes.Name to determine the corresponding node
name.
Modify an Existing Graph
After you construct a graph or digraph object, you can use a variety of functions to
modify the graph structure. The table lists the available graph manipulation functions,
which modify the nodes and edges of either graph or digraph objects.
5-9
5
Graph and Network Algorithms
addedge
Add one or more edges to a graph
rmedge
Remove one or more edges from a graph
addnode
Add one or more nodes to a graph
rmnode
Remove one or more edges from a graph
findnode
Locate a specific edge in a graph
findedge
Locate a specific edge in a graph
numedges
Find the number of edges in a graph
numnodes
Find the number of nodes in a graph
reordernodes
Permute the order of the nodes in a graph
subgraph
Extract subgraph
See “Modify Nodes and Edges of Existing Graph” on page 5-11 for some common
graph modification examples.
See Also
digraph | graph
More About
5-10
•
Using graph Objects
•
Using digraph Objects
•
“Modify Nodes and Edges of Existing Graph” on page 5-11
•
“Add Graph Node Names, Edge Weights, and Other Attributes” on page 5-15
•
“Graph Plotting and Customization” on page 5-20
Modify Nodes and Edges of Existing Graph
Modify Nodes and Edges of Existing Graph
This example shows how to access and modify the nodes and/or edges in a graph or
digraph object using the addedge, rmedge, addnode, rmnode, findedge, findnode,
and subgraph functions.
Add Nodes
Create a graph with four nodes and four edges. The corresponding elements in s and t
specify the end nodes of each graph edge.
s = [1 1 1 2];
t = [2 3 4 3];
G = graph(s,t)
G =
graph with properties:
Edges: [4x1 table]
Nodes: [4x0 table]
View the edge list of the graph.
G.Edges
ans =
EndNodes
________
1
1
1
2
2
3
4
3
Use addnode to add five nodes to the graph. This command adds five disconnected nodes
with node IDs 5, 6, 7, 8, and 9.
G = addnode(G,5)
5-11
5
Graph and Network Algorithms
G =
graph with properties:
Edges: [4x1 table]
Nodes: [9x0 table]
Remove Nodes
Use rmnode to remove nodes 3, 5, and 6 from the graph. All edges connected to one of the
removed nodes also are removed. The remaining six nodes in the graph are renumbered
to reflect the new number of nodes.
G = rmnode(G,[3 5 6])
G =
graph with properties:
Edges: [2x1 table]
Nodes: [6x0 table]
Add Edges
Use addedge to add two edges to G. The first edge is between node 1 and node 5, and
the second edge is between node 2 and node 5. This command adds two new rows to
G.Edges.
G = addedge(G,[1 2],[5 5])
G =
graph with properties:
Edges: [4x1 table]
Nodes: [6x0 table]
Remove Edges
Use rmedge to remove the edge between node 1 and node 3. This command removes a
row from G.Edges.
5-12
Modify Nodes and Edges of Existing Graph
G = rmedge(G,1,3)
G =
graph with properties:
Edges: [3x1 table]
Nodes: [6x0 table]
Determine Edge Index
Determine the edge index for the edge between nodes 1 and 5. The edge index, ei, is a
row number in G.Edges.
ei = findedge(G,1,5)
ei =
2
Determine Node Index
Add node names to the graph, and then determine the node index for node 'd'. The
numeric node index, ni, is a row number in G.Nodes. You can use both ni and the node
name, 'd', to refer to the node when using other graph functions, like shortestpath.
G.Nodes.Name = {'a' 'b' 'c' 'd' 'e' 'f'}';
ni = findnode(G,'d')
ni =
4
Extract Subgraph
Use subgraph to extract a piece of the graph containing only two nodes.
H = subgraph(G,[1 2])
5-13
5
Graph and Network Algorithms
H =
graph with properties:
Edges: [1x1 table]
Nodes: [2x1 table]
View the edge list of the subgraph.
H.Edges
ans =
EndNodes
__________
'a'
'b'
Modify Node and Edge Tables with Variables Editor
The node and edge information for a graph object is contained in two properties: Nodes
and Edges. Both of these properties are tables containing variables to describe the
attributes of the nodes and edges in the graph. Since Nodes and Edges are both tables,
you can use the Variables editor to interactively view or edit the tables. For more
information, see “View, Edit, and Copy Variables”.
See Also
addedge | addnode | digraph | findedge | findnode | graph | rmedge | rmnode
| subgraph
More About
5-14
•
“Directed and Undirected Graphs” on page 5-2
•
Using graph Objects
•
Using digraph Objects
Add Graph Node Names, Edge Weights, and Other Attributes
Add Graph Node Names, Edge Weights, and Other Attributes
This example shows how to add attributes to the nodes and edges in graphs created using
graph and digraph. You can specify node names or edge weights when you originally
call graph or digraph to create a graph. However, this example shows how to add
attributes to a graph after it has been created.
Create Graph
Create a directed graph. The corresponding elements in s and t define the source and
target nodes of each edge in the graph.
s = [1 1 2 2 3];
t = [2 4 3 4 4];
G = digraph(s,t)
G =
digraph with properties:
Edges: [5x1 table]
Nodes: [4x0 table]
Add Node Names
Add node names to the graph by adding the variable, Name, to the G.Nodes table. The
Name variable must be an N-by-1 cell array of strings, where N = numnodes(G). It is
important to use the Name variable when adding node names, as this variable name is
treated specially by some graph functions.
G.Nodes.Name = {'First' 'Second' 'Third' 'Fourth'}';
View the new Nodes table.
G.Nodes
ans =
Name
________
5-15
5
Graph and Network Algorithms
'First'
'Second'
'Third'
'Fourth'
Use table indexing to view the names of nodes 1 and 4.
G.Nodes.Name([1 4])
ans =
'First'
'Fourth'
Add Edge Weights
Add edge weights to the graph by adding the variable, Weight, to the G.Edges table.
The Weight variable must be an M-by-1 numeric vector, where M = numedges(G). It is
important to use the Weight variable when adding edge weights, as this variable name
is treated specially by some graph functions.
G.Edges.Weight = [10 20 30 40 50]';
View the new Edges table.
G.Edges
ans =
EndNodes
____________________
Weight
______
'First'
'First'
'Second'
'Second'
'Third'
10
20
30
40
50
'Second'
'Fourth'
'Third'
'Fourth'
'Fourth'
Use table indexing to view the first and third rows of G.Edges.
5-16
Add Graph Node Names, Edge Weights, and Other Attributes
G.Edges([1 3],:)
ans =
EndNodes
____________________
Weight
______
'First'
'Second'
10
30
'Second'
'Third'
Add Custom Attributes
In principle you can add any variable to G.Nodes and G.Edges that defines an attribute
of the graph nodes or edges. Adding custom attributes can be useful, since functions like
subgraph and reordernodes preserve the graph attributes.
For example, add a variable named Power to G.Edges to indicate whether each edge is
'on' or 'off'.
G.Edges.Power = {'on' 'on' 'on' 'off' 'off'}';
G.Edges
ans =
EndNodes
____________________
Weight
______
Power
_____
'First'
'First'
'Second'
'Second'
'Third'
10
20
30
40
50
'on'
'on'
'on'
'off'
'off'
'Second'
'Fourth'
'Third'
'Fourth'
'Fourth'
Add a variable named Size to G.Nodes to indicate the physical size of each node.
G.Nodes.Size = [10 20 10 30]';
G.Nodes
ans =
5-17
5
Graph and Network Algorithms
Name
________
Size
____
'First'
'Second'
'Third'
'Fourth'
10
20
10
30
Modify Tables with Variables Editor
Since Nodes and Edges are both tables, you can use the Variables editor to interactively
view or edit the tables. For more information, see “View, Edit, and Copy Variables”.
Label Nodes and Edges of Graph Plot
When you plot a graph, you can use the variables in G.Nodes and G.Edges to label the
graph nodes and edges. This practice is convenient, since these variables are already
guaranteed to have the correct number of elements.
Plot the graph and label the edges using the Power variable in G.Edges. Label the nodes
using the Size variable in G.Nodes.
p = plot(G,'EdgeLabel',G.Edges.Power,'NodeLabel',G.Nodes.Size)
p =
GraphPlot with properties:
NodeColor:
MarkerSize:
Marker:
EdgeColor:
LineWidth:
LineStyle:
NodeLabel:
EdgeLabel:
XData:
YData:
[0 0.4470 0.7410]
4
'o'
[0 0.4470 0.7410]
0.5000
'-'
{'10' '20' '10'
{'on' 'on' 'on'
[2 1.5000 1 2]
[4 3 2 1]
Use GET to show all properties
5-18
'30'}
'off'
'off'}
Add Graph Node Names, Edge Weights, and Other Attributes
See Also
digraph | graph
More About
•
“Directed and Undirected Graphs” on page 5-2
•
“Modify Nodes and Edges of Existing Graph” on page 5-11
•
Using graph Objects
•
Using digraph Objects
5-19
5
Graph and Network Algorithms
Graph Plotting and Customization
This example shows how to plot graphs, and then customize the display to add labels or
highlighting to the graph nodes and edges.
Graph Plotting Objects
Use the plot function to plot graph and digraph objects. By default, plot examines
the size and type of graph to determine which layout to use and adds node labels to
graphs that have 100 or fewer nodes. The node labels use the node names if available;
otherwise, the labels are numeric node indices.
For example, create a graph using the buckyball adjacency matrix, and then plot the
graph using all of the default options. If you call plot and specify an output argument,
then the function returns a handle to a GraphPlot object. Subsequently, you can use
this object to adjust properties of the plot. For example, you can change the color or style
of the edges, the size and color of the nodes, and so on.
G = graph(bucky);
p = plot(G)
p =
GraphPlot with properties:
NodeColor:
MarkerSize:
Marker:
EdgeColor:
LineWidth:
LineStyle:
NodeLabel:
EdgeLabel:
XData:
YData:
[0 0.4470 0.7410]
4
'o'
[0 0.4470 0.7410]
0.5000
'-'
{1x60 cell}
{}
[1x60 double]
[1x60 double]
Use GET to show all properties
5-20
Graph Plotting and Customization
After you have a handle to the GraphPlot object, use dot indexing to access or change
the property values. For a complete list of the properties that you can adjust, see
GraphPlot.
Change the value of NodeColor to 'red'.
p.NodeColor = 'red';
5-21
5
Graph and Network Algorithms
Determine the line width of the edges.
p.LineWidth
ans =
0.5000
5-22
Graph Plotting and Customization
Create and Plot Graph
Create and plot a graph representing an L-shaped membrane constructed from a square
grid with a side of 12 nodes. Specify an output argument with plot to return a handle to
the GraphPlot object.
n = 12;
A = delsq(numgrid('L',n));
G = graph(A,'OmitSelfLoops')
G =
graph with properties:
Edges: [130x2 table]
Nodes: [75x0 table]
p = plot(G)
p =
GraphPlot with properties:
NodeColor:
MarkerSize:
Marker:
EdgeColor:
LineWidth:
LineStyle:
NodeLabel:
EdgeLabel:
XData:
YData:
[0 0.4470 0.7410]
4
'o'
[0 0.4470 0.7410]
0.5000
'-'
{1x75 cell}
{}
[1x75 double]
[1x75 double]
Use GET to show all properties
5-23
5
Graph and Network Algorithms
Proportional Node Coloring
Color the graph nodes based on their degree. In this graph, all of the interior nodes have
the same maxiumum degree of 4, nodes along the boundary of the graph have a degree of
3, and the corner nodes have the smallest degree of 2. Store this node coloring data as the
variable NodeColors in G.Nodes.
G.Nodes.NodeColors = degree(G);
p.NodeCData = G.Nodes.NodeColors;
colorbar
5-24
Graph Plotting and Customization
Edge Line Width by Weight
Add some random integer weights to the graph edges, and then plot the edges such that
their line width is proportional to their weight. Since an edge line width approximately
greater than 7 starts to become cumbersome, scale the line widths such that the edge
with the greatest weight has a line width of 7. Store this edge width data as the variable
LWidths in G.Edges.
G.Edges.Weight = randi([10 250],130,1);
G.Edges.LWidths = 7*G.Edges.Weight/max(G.Edges.Weight);
p.LineWidth = G.Edges.LWidths;
5-25
5
Graph and Network Algorithms
Extract Subgraph
Extract and plot the top right corner of G as a subgraph, to make it easier to read the
details on the graph. The new graph, H, inherits the NodeColors and LWidths variables
from G, so that recreating the previous plot customizations is straightforward. However,
the nodes in H are renumbered to account for the new number of nodes in the graph.
H = subgraph(G,[1:31 36:41]);
p1 = plot(H,'NodeCData',H.Nodes.NodeColors,'LineWidth',H.Edges.LWidths);
colorbar
5-26
Graph Plotting and Customization
Label Nodes and Edges
Use labeledge to label the edges whose width is larger than 6 with the label, 'Large'.
The labelnode function works in a similar manner for labeling nodes.
labeledge(p1,find(H.Edges.LWidths > 6),'Large')
5-27
5
Graph and Network Algorithms
Highlight Shortest Path
Find the shortest path between node 11 and node 37 in the subgraph, H. Highlight the
edges along this path in red, and increase the size of the end nodes on the path.
path = shortestpath(H,11,37)
path =
11
12
17
highlight(p1,[11 37])
5-28
18
19
24
25
30
36
37
Graph Plotting and Customization
highlight(p1,path,'EdgeColor','r')
Remove the node labels and colorbar, and make all of the nodes black.
p1.NodeLabel = {};
colorbar off
p1.NodeColor = 'black';
5-29
5
Graph and Network Algorithms
Find a different shortest path that ignores the edge weights. Highlight this path in
green.
path2 = shortestpath(H,11,37,'Method','unweighted')
path2 =
11
12
13
14
15
20
highlight(p1,path2,'EdgeColor','g')
5-30
25
30
31
37
Graph Plotting and Customization
Plotting Large Graphs
It is common to create graphs that have hundreds of thousands, or even millions, of
nodes and/or edges. For this reason, plot treats large graphs slightly differently to
maintain readability and performance. The plot function makes these adjustments
when working with graphs that have more than 100 nodes:
1
The default graph layout method is always 'subspace'.
2
The nodes are no longer labeled automatically.
3
The MarkerSize property is set to 2. (Smaller graphs have a marker size of 4).
5-31
5
Graph and Network Algorithms
4
The ArrowSize property of directed graphs is set to 4. (Smaller directed graphs use
an arrow size of 7).
See Also
digraph | graph | plot
More About
5-32
•
“Directed and Undirected Graphs” on page 5-2
•
Using graph Objects
•
Using digraph Objects
•
Using GraphPlot Objects
•
GraphPlot Properties
Build Watts-Strogatz Small World Graph Model
Build Watts-Strogatz Small World Graph Model
This example shows how to construct and analyze a Watts-Strogatz small-world graph.
The Watts-Strogatz model is a random graph that has small-world network properties,
such as clustering and short average path length.
Algorithm Description
Creating a Watts-Strogatz graph has two basic steps:
1
Create a ring lattice with
nodes of mean degree
nearest neighbors on either side.
. Each node is connected to its
2
For each edge in the graph, rewire the target node with probability . The rewired
edge cannot be a duplicate or self-loop.
After the first step the graph is a perfect ring lattice. So when
rewired and the model returns a ring lattice. In contrast, when
rewired and the ring lattice is transformed into a random graph.
, no edges are
, all of the edges are
The file WattsStrogatz.m implements this graph algorithm for undirected graphs. The
input parameters are N, K, and beta according to the algorithm description above.
View the file WattsStrogatz.m.
% Copyright 2015 The MathWorks, Inc.
function h = WattsStrogatz(N,K,beta)
% H = WattsStrogatz(N,K,beta) returns a Watts-Strogatz model graph with N
% nodes, N*K edges, mean node degree 2*K, and rewiring probability beta.
%
% beta = 0 is a ring lattice, and beta = 1 is a random graph.
%
%
s
t
t
Connect each node to its K next and previous neighbors. This constructs
indices for a ring lattice.
= repelem((1:N)',1,K);
= s + repmat(1:K,N,1);
= mod(t-1,N)+1;
% Rewire the target node of each edge with probability beta
5-33
5
Graph and Network Algorithms
for source=1:N
switchEdge = rand(K, 1) < beta;
newTargets = rand(N, 1);
newTargets(source) = 0;
newTargets(s(t==source)) = 0;
newTargets(t(source, ~switchEdge)) = 0;
[~, ind] = sort(newTargets, 'descend');
t(source, switchEdge) = ind(1:nnz(switchEdge));
end
h = graph(s,t);
end
Ring Lattice
Construct a ring lattice with 500 nodes using the WattsStrogatz function. When beta
is 0, the function returns a ring lattice whose nodes all have degree 2K.
h = WattsStrogatz(500,25,0);
plot(h,'NodeColor','k','Layout','circle');
title('Watts-Strogatz Graph with $N = 500$ nodes, $K = 25$, and $\beta = 0$', ...
'Interpreter','latex')
5-34
Build Watts-Strogatz Small World Graph Model
Some Random Edges
Increase the amount of randomness in the graph by raising beta to 0.15 and 0.50.
h2 = WattsStrogatz(500,25,0.15);
plot(h2,'NodeColor','k','EdgeAlpha',0.1);
title('Watts-Strogatz Graph with $N = 500$ nodes, $K = 25$, and $\beta = 0.15$', ...
'Interpreter','latex')
5-35
5
Graph and Network Algorithms
h3 = WattsStrogatz(500,25,0.50);
plot(h3,'NodeColor','k','EdgeAlpha',0.1);
title('Watts-Strogatz Graph with $N = 500$ nodes, $K = 25$, and $\beta = 0.50$', ...
'Interpreter','latex')
5-36
Build Watts-Strogatz Small World Graph Model
Random Graph
Generate a completely random graph by increasing beta to its maximum value of 1.0.
This rewires all of the edges.
h4 = WattsStrogatz(500,25,1);
plot(h4,'NodeColor','k','EdgeAlpha',0.1);
title('Watts-Strogatz Graph with $N = 500$ nodes, $K = 25$, and $\beta = 1$', ...
'Interpreter','latex')
5-37
5
Graph and Network Algorithms
Degree Distribution
The degree distribution of the nodes in the different Watts-Strogatz graphs varies. When
beta is 0, the nodes all have the same degree, 2K, so the degree distribution is just a
Dirac-delta function centered on 2K,
distribution changes.
. However, as beta increases, the degree
This plot shows the degree distributions for the nonzero values of beta.
histogram(degree(h2),'BinMethod','integers','FaceAlpha',0.9);
hold on
histogram(degree(h3),'BinMethod','integers','FaceAlpha',0.9);
histogram(degree(h4),'BinMethod','integers','FaceAlpha',0.8);
5-38
Build Watts-Strogatz Small World Graph Model
hold off
title('Node degree distributions for Watts-Strogatz Model Graphs')
xlabel('Degree of node')
ylabel('Number of nodes')
legend('\beta = 1.0','\beta = 0.50','\beta = 0.15','Location','NorthWest')
Hub Formation
The Watts-Strogatz graph has a high clustering coefficient, so the nodes tend to form
cliques, or small groups of closely interconnected nodes. As beta increases towards its
maximum value of 1.0, you see an increasingly large number of hub nodes, or nodes
of high relative degree. The hubs are a common connection between other nodes and
5-39
5
Graph and Network Algorithms
between cliques in the graph. The existence of hubs is what permits the formation of
cliques while preserving a short average path length.
Calculate the average path length and number of hub nodes for each value of beta. For
the purposes of this example, the hub nodes are nodes with degree greater than or equal
to 55. These are all of the nodes whose degree increased 10% or more compared to the
original ring lattice.
n = 55;
d = [mean(mean(distances(h))), nnz(degree(h)>=n); ...
mean(mean(distances(h2))), nnz(degree(h2)>=n); ...
mean(mean(distances(h3))), nnz(degree(h3)>=n);
mean(mean(distances(h4))), nnz(degree(h4)>=n)];
T = table([0 0.15 0.50 1]', d(:,1), d(:,2),...
'VariableNames',{'Beta','AvgPathLength','NumberOfHubs'})
T =
Beta
____
AvgPathLength
_____________
NumberOfHubs
____________
0
0.15
0.5
1
5.48
2.0715
1.9101
1.9008
0
20
85
92
As beta increases, the average path length in the graph quickly falls to its limiting
value. This is due to the formation of the highly connected hub nodes, which become more
numerous as beta increases.
Plot the
Watts-Strogatz model graph, making the size and color of each node
proportional to its degree. This is an effective way to visualize the formation of hubs.
colormap hsv
deg = degree(h2);
nSizes = 2*sqrt(deg-min(deg)+0.2);
nColors = deg;
plot(h2,'MarkerSize',nSizes,'NodeCData',nColors,'EdgeAlpha',0.1)
title('Watts-Strogatz Graph with $N = 500$ nodes, $K = 25$, and $\beta = 0.15$', ...
'Interpreter','latex')
colorbar
5-40
Build Watts-Strogatz Small World Graph Model
See Also
digraph | graph
More About
•
“Directed and Undirected Graphs” on page 5-2
•
Using graph Objects
•
Using digraph Objects
5-41
5
Graph and Network Algorithms
Visualize Breadth-First and Depth-First Search
This example shows how to define a function that visualizes the results of bfsearch and
dfsearch by highlighting the nodes and edges of a graph.
Create and plot a directed graph.
s = [1 2 3 3 3 3 4 5 6 7 8 9 9 9 10];
t = [7 6 1 5 6 8 2 4 4 3 7 1 6 8 2];
G = digraph(s,t);
plot(G)
5-42
Visualize Breadth-First and Depth-First Search
Perform a depth-first search on the graph. Specify 'allevents' to return all events in
the algorithm. Also, specify Restart as true to ensure that the search visits every node
in the graph.
T = dfsearch(G, 1, 'allevents', 'Restart', true)
T =
Event
________________
Node
____
Edge
__________
startnode
discovernode
edgetonew
discovernode
edgetonew
discovernode
edgetodiscovered
edgetonew
discovernode
edgetonew
discovernode
edgetonew
discovernode
edgetonew
discovernode
edgetodiscovered
finishnode
finishnode
finishnode
finishnode
edgetofinished
edgetonew
discovernode
edgetodiscovered
finishnode
finishnode
finishnode
finishnode
startnode
discovernode
edgetofinished
edgetofinished
1
1
NaN
7
NaN
3
NaN
NaN
5
NaN
4
NaN
2
NaN
6
NaN
6
2
4
5
NaN
NaN
8
NaN
8
3
7
1
9
9
NaN
NaN
NaN
NaN
1
NaN
7
NaN
3
3
NaN
5
NaN
4
NaN
2
NaN
6
NaN
NaN
NaN
NaN
3
3
NaN
8
NaN
NaN
NaN
NaN
NaN
NaN
9
9
NaN
NaN
7
NaN
3
NaN
1
5
NaN
4
NaN
2
NaN
6
NaN
4
NaN
NaN
NaN
NaN
6
8
NaN
7
NaN
NaN
NaN
NaN
NaN
NaN
1
6
5-43
5
Graph and Network Algorithms
edgetofinished
finishnode
startnode
discovernode
edgetofinished
finishnode
NaN
9
10
10
NaN
10
9
NaN
NaN
NaN
10
NaN
8
NaN
NaN
NaN
2
NaN
The values in the table, T, are useful for visualizing the search. The function
visualize_search.m shows one way to use the results of searches performed with
bfsearch and dfsearch to highlight the nodes and edges in the graph according to
the table of events, T. The function pauses before each step in the algorithm, so you can
slowly step through the search by pressing any key.
Save visualize_search.m in the current folder.
function visualize_search(G,t)
% G is a graph or digraph object, and t is a table resulting from a call to
% BFSEARCH or DFSEARCH on that graph.
%
% Example inputs:
% g = digraph([1 2 3 3 3 3 4 5 6 7 8 9 9 9 10], [7 6 1 5 6 8 2 4 4 3 7 1 6 8 2]);
% t = dfsearch(g, 1, 'allevents', 'Restart', true);
% Copyright 1984-2015 The MathWorks, Inc.
if isa(G,'graph')
% Replace graph with corresponding digraph, because we need separate
% edges for both directions
G = digraph(adjacency(G));
end
h = plot(G,'NodeColor',[0.5 0.5 0.5],'EdgeColor',[0.5 0.5 0.5]);
for ii=1:size(t,1)
switch t.Event(ii)
case 'startnode'
highlight(h,t.Node(ii),'MarkerSize',min(h.MarkerSize)*2);
case 'discovernode'
highlight(h,t.Node(ii),'NodeColor','r');
case 'finishnode'
highlight(h,t.Node(ii),'NodeColor','k');
case 'edgetonew'
5-44
Visualize Breadth-First and Depth-First Search
highlight(h,t.Edge(ii,1),t.Edge(ii,2),'EdgeColor','b');
case 'edgetodiscovered'
highlight(h,t.Edge(ii,1),t.Edge(ii,2),'EdgeColor',[0.8 0 0.8]);
case 'edgetofinished'
highlight(h,t.Edge(ii,1),t.Edge(ii,2),'EdgeColor',[0 0.8 0]);
end
disp('Strike any key to continue...')
pause
end
disp('Done.')
close all
Use this command to run visualize_search.m on graph G and search result T:
visualize_search(G,T)
The graph begins as all gray, and then a new piece of the search result appears each time
you press a key. The search results are highlighted according to:
• 'startnode' - Starting nodes increase in size.
• 'discovernode' - Nodes turn red as they are discovered.
• 'finishnode' - Nodes turn black after they are finished.
• 'edgetonew' - Edges that lead to undiscovered nodes turn blue.
• 'edgetodiscovered' - Edges that lead to discovered nodes turn magenta.
• 'edgetofinished' - Edges that lead to finished nodes turn green.
See Also
bfsearch | dfsearch | digraph | graph
More About
•
“Directed and Undirected Graphs” on page 5-2
•
Using graph Objects
•
Using digraph Objects
5-45
5
Graph and Network Algorithms
Use Page Rank Algorithm to Rank Websites
This example shows how to use a page rank algorithm to rank a collection of websites.
Although the page rank algorithm was originally designed to rank search engine results,
it also can be more broadly applied to the nodes in many different types of graphs. The
page rank score gives an idea of the relative importance of each graph node based on how
it is connected to the other nodes.
Theoretically, the page rank score is the limiting probability that someone randomly
clicking links on each website will arrive at any particular page. So pages with a high
score are highly connected and discoverable within the network, and it is more likely a
random web surfer will visit that page.
Algorithm Description
The function pageRank.m implements a page rank algorithm for directed graphs. At
each step in the algorithm, the page rank of each page is updated according to,
r =
(1-P)/n + P*(A'*(r./d) + s/n);
• r is a vector of page rank scores.
• P is a scalar damping factor (usually 0.85), which is the probability that a random
surfer clicks on a link on the current page, instead of continuing on another random
page.
• A' is the transpose of the adjacency matrix of the graph.
• d is a vector containing the out-degree of each node in the graph. d is set to 1 for
nodes with no outgoing edges.
• n is the scalar number of nodes in the graph.
• s is the scalar sum of the page rank scores for pages with no links.
In other words, the rank of each page is largely based on the ranks of the pages that link
to it. The term A'*(r./d) picks out the page ranks of the source nodes that link to each
node in the graph, and the page ranks are normalized by the total number of outbound
links of those source nodes. This ensures that the sum of the page rank scores is always
1. For example, if node 2 links to nodes 1, 3, and 4, then it transfers 1/3 of its page rank
score to each of those nodes during each iteration of the algorithm.
Create a graph that illustrates how each node confers its page rank score to the other
nodes in the graph.
5-46
Use Page Rank Algorithm to Rank Websites
s = {'a' 'a' 'a' 'b' 'b' 'c' 'd' 'd' 'd'};
t = {'b' 'c' 'd' 'd' 'a' 'b' 'c' 'a' 'b'};
G = digraph(s,t);
labels = {'a/3' 'a/3' 'a/3' 'b/2' 'b/2' 'c' 'd/3' 'd/3' 'd/3'};
p = plot(G,'Layout','layered','EdgeLabel',labels);
highlight(p,[1 1 1],[2 3 4],'EdgeColor','g')
highlight(p,[2 2],[1 4],'EdgeColor','r')
highlight(p,3,2,'EdgeColor','m')
title('Page Rank Score Transfer Between Nodes')
Save the function pageRank.m in the current folder so you can run it on the graphs in
this example.
5-47
5
Graph and Network Algorithms
% Copyright 2015 The MathWorks, Inc.
function RkG = pageRank(G,numIts,P)
% R = pageRank(G,NUMITS,P) computes a page rank score for each node in
% graph G using NUMITS iterations and damping factor P.
n = numnodes(G);
d = outdegree(G);
id = indegree(G);
% Account for pages with no links.
snks = (d == 0);
d(snks) = 1;
% Initialize page ranks
r = ones(n,1)./n;
% Perform the required iterations
A = adjacency(G);
for k = 1:numIts
s = sum(r(snks));
r = (1-P)/n + P*(A'*(r./d) + s/n);
end
% Generate the output graph with the nodes reordered, and add Score and
% degree variables to the node table.
[r,ind] = sort(r,'descend');
RkG = reordernodes(G,ind);
RkG.Nodes.InDegree = id(ind);
RkG.Nodes.OutDegree = d(ind);
RkG.Nodes.Score = r;
Page Rank with 6 Nodes
Create and plot a directed graph containing six nodes representing fictitious websites.
s = [1 1 2 2 3 3 3 4 5];
t = [2 5 3 4 4 5 6 1 1];
names = {'http://www.example.com/alpha', 'http://www.example.com/beta', ...
'http://www.example.com/gamma', 'http://www.example.com/delta', ...
'http://www.example.com/epsilon', 'http://www.example.com/zeta'};
G = digraph(s,t,[],names)
plot(G,'Layout','layered', ...
'NodeLabel',{'alpha','beta','gamma','delta','epsilon','zeta'})
5-48
Use Page Rank Algorithm to Rank Websites
G =
digraph with properties:
Edges: [9x1 table]
Nodes: [6x1 table]
Run pageRank on this graph using 100 iterations and a damping factor of 0.85. The
function returns a graph containing the scores of each page.
H = pageRank(G,100,0.85)
5-49
5
Graph and Network Algorithms
H =
digraph with properties:
Edges: [9x1 table]
Nodes: [6x4 table]
View the page rank scores and degree information for each page.
H.Nodes
ans =
Name
________________________________
InDegree
________
OutDegree
_________
Score
________
'http://www.example.com/alpha'
'http://www.example.com/epsilon'
'http://www.example.com/beta'
'http://www.example.com/delta'
'http://www.example.com/gamma'
'http://www.example.com/zeta'
2
2
1
2
1
1
2
1
2
1
3
1
0.32102
0.20074
0.17054
0.13679
0.10659
0.064312
The results show that it is not just the number of page links that determines the score,
but also the quality. The alpha and gamma websites both have a total degree of 4,
however alpha links to both epsilon and beta, which also are highly ranked. gamma is
only linked to by one page, beta, which is in the middle of the list. Thus, alpha is scored
higher than gamma by the algorithm.
Page Rank of Websites on MathWorks.com
Load the data in mathworks100.mat and view the adjacency matrix, A. This data was
generated in 2015 using an automatic page crawler. The page crawler began at http://
www.mathworks.com and followed links to subsequent web pages until the adjacency
matrix contained information on the connections of 100 unique web pages.
load(fullfile(matlabroot,'examples','matlab','mathworks100.mat'))
spy(A)
5-50
Use Page Rank Algorithm to Rank Websites
Create a directed graph with the sparse adjacency matrix, A, using the URLs contained
in U as node names.
G = digraph(A,U)
G =
digraph with properties:
Edges: [632x1 table]
Nodes: [100x1 table]
5-51
5
Graph and Network Algorithms
Plot the graph using the force layout.
plot(G,'NodeLabel',{},'NodeColor',[0.93 0.78 0],'Layout','force');
title('Websites linked to http://www.mathworks.com')
Compute the page rank for the graph, G, using 200 iterations and a damping factor of
0.85.
H = pageRank(G,200,0.85)
H =
5-52
Use Page Rank Algorithm to Rank Websites
digraph with properties:
Edges: [632x1 table]
Nodes: [100x4 table]
View the top 25 resulting page ranks.
H.Nodes(1:25,:)
ans =
Name
___________________________________________________________________________
InDe
____
'http://www.mathworks.com'
'http://ch.mathworks.com'
'http://cn.mathworks.com'
'http://jp.mathworks.com'
'http://kr.mathworks.com'
'http://uk.mathworks.com'
'http://au.mathworks.com'
'http://de.mathworks.com'
'http://es.mathworks.com'
'http://fr.mathworks.com'
'http://in.mathworks.com'
'http://it.mathworks.com'
'http://nl.mathworks.com'
'http://se.mathworks.com'
'http://www.mathworks.com/company/aboutus/policies_statements/patents.html'
'http://www.mathworks.com/company/aboutus/policies_statements/trademarks…'
'http://www.mathworks.com/company/aboutus/policies_statements'
'http://www.mathworks.com/company/aboutus/policies_statements/piracy.html'
'http://www.mathworks.com/company/rss/index.html'
'http://ch.mathworks.com/company/aboutus/policies_statements/patents.html'
'http://ch.mathworks.com/company/aboutus/policies_statements/trademarks.…'
'http://ch.mathworks.com/company/aboutus/policies_statements'
'http://ch.mathworks.com/company/aboutus/policies_statements/piracy.html'
'http://ch.mathworks.com/company/rss/index.html'
'http://cn.mathworks.com/company/aboutus/policies_statements/patents.html'
20
20
20
20
20
20
20
20
20
20
20
20
20
20
6
6
5
5
5
5
5
5
5
5
5
Extract and plot a subgraph containing all nodes whose page rank is greater than 0.005.
Color the graph nodes based on their page rank.
5-53
5
Graph and Network Algorithms
H2 = subgraph(H,find(H.Nodes.Score > 0.005));
plot(H2,'NodeLabel',{},'NodeCData',H2.Nodes.Score,'Layout','force');
title('Websites linked to http://www.mathworks.com')
colorbar
The page ranks for the top websites are all quite similar, such that a random web surfer
has about a 4.5% chance to land on each page. This small group of highly connected
pages forms a clique in the center of the plot. Connected to this central clique are several
smaller cliques, which are highly connected amongst themselves.
5-54
Use Page Rank Algorithm to Rank Websites
References
Moler, C. Experiments with MATLAB. Chapter 7: Google PageRank. MathWorks, Inc.,
2011.
See Also
digraph | graph
More About
•
“Directed and Undirected Graphs” on page 5-2
•
Using graph Objects
•
Using digraph Objects
5-55
6
Functions of One Variable
• “Create and Evaluate Polynomials” on page 6-2
• “Roots of Polynomials” on page 6-4
• “Integrate and Differentiate Polynomials” on page 6-10
• “Polynomial Curve Fitting” on page 6-12
• “Roots of Scalar Functions” on page 6-14
6
Functions of One Variable
Create and Evaluate Polynomials
This example shows how to represent a polynomial as a vector in MATLAB® and
evaluate the polynomial at points of interest.
Representing Polynomials
MATLAB® represents polynomials as row vectors containing coefficients ordered by
descending powers. For example, the three-element vector
p = [p2 p1 p0];
represents the polynomial
Create a vector to represent the quadratic polynomial
.
p = [1 -4 4];
Intermediate terms of the polynomial that have a coefficient of 0 must also be entered
into the vector, since the 0 acts as a placeholder for that particular power of x.
Create a vector to represent the polynomial
.
p = [4 0 0 -3 2 33];
Evaluating Polynomials
After entering the polynomial into MATLAB® as a vector, use the polyval function to
evaluate the polynomial at a specific value.
Use polyval to evaluate
polyval(p,2)
ans =
153
6-2
.
Create and Evaluate Polynomials
Alternatively, you can evaluate a polynomial in a matrix sense using polyvalm. The
polynomial expression in one variable,
expression
, becomes the matrix
where X is a square matrix and I is the identity matrix.
Create a square matrix, X, and evaluate p at X.
X = [2 4 5; -1 0 3; 7 1 5];
Y = polyvalm(p,X)
Y =
154392
49001
215378
78561
24104
111419
193065
59692
269614
See Also
poly | polyval | polyvalm | roots
More About
•
“Roots of Polynomials” on page 6-4
•
“Integrate and Differentiate Polynomials” on page 6-10
•
“Polynomial Curve Fitting” on page 6-12
6-3
6
Functions of One Variable
Roots of Polynomials
This example shows several different methods to calculate the roots of a polynomial.
In this section...
“Numeric Roots” on page 6-4
“Roots Using Substitution” on page 6-5
“Roots in a Specific Interval” on page 6-6
“Symbolic Roots” on page 6-8
Numeric Roots
The roots function calculates the roots of a single-variable polynomial represented by a
vector of coefficients.
For example, create a vector to represent the polynomial x2 - x - 6 , then calculate the
roots.
p = [1 -1 -6];
r = roots(p)
r =
3
-2
By convention, MATLAB returns the roots in a column vector.
The poly function converts the roots back to polynomial coefficients. When operating on
vectors, poly and roots are inverse functions, such that poly(roots(p)) returns p
(up to roundoff error, ordering, and scaling).
p2 = poly(r)
p2 =
1
-1
-6
When operating on a matrix, the poly function computes the characteristic polynomial of
the matrix. The roots of the characteristic polynomial are the eigenvalues of the matrix.
6-4
Roots of Polynomials
Therefore, roots(poly(A)) and eig(A) return the same answer (up to roundoff error,
ordering, and scaling).
Roots Using Substitution
You can solve polynomial equations involving trigonometric functions by simplifying
the equation using a substitution. The resulting polynomial of one variable no longer
contains any trigonometric functions.
For example, find the values of
that solve the equation
Use the fact that
functions:
Use the substitution
to express the equation entirely in terms of sine
to express the equation as a simple polynomial equation:
Create a vector to represent the polynomial.
p = [-3 -1 6];
Find the roots of the polynomial.
r = roots(p)
r =
-1.5907
1.2573
To undo the substitution, use
. The asin function calculates the inverse sine.
6-5
6
Functions of One Variable
theta = asin(r)
theta =
-1.5708 + 1.0395i
1.5708 - 0.7028i
Verify that the elements in theta are the values of
(within roundoff error).
that solve the original equation
f = @(Z) 3*cos(Z).^2 - sin(Z) + 3;
f(theta)
ans =
1.0e-14 *
-0.0888 + 0.0647i
0.2665 + 0.0399i
Roots in a Specific Interval
Use the fzero function to find the roots of a polynomial in a specific interval. Among
other uses, this method is suitable if you plot the polynomial and want to know the value
of a particular root.
For example, create a function handle to represent the polynomial
.
p = @(x) 3*x.^7 + 4*x.^6 + 2*x.^5 + 4*x.^4 + x.^3 + 5*x.^2;
Plot the function over the interval
x = -2:0.1:1;
plot(x,p(x))
ylim([-100 50])
grid on
hold on
6-6
.
Roots of Polynomials
From the plot, the polynomial has a trivial root at 0 and another near -1.5. Use fzero
to calculate and plot the root that is near -1.5.
Z = fzero(p, -1.5)
plot(Z,p(Z),'r*')
Z =
-1.6056
6-7
6
Functions of One Variable
Symbolic Roots
If you have Symbolic Math Toolbox, then there are additional options for evaluating
polynomials symbolically. One way is to use the solve function.
syms x
s = solve(x^2-x-6)
s =
-2
3
Another way is to use the factor function to factor the polynomial terms.
6-8
Roots of Polynomials
F = factor(x^2-x-6)
F =
[ x + 2, x - 3]
See “Solve Algebraic Equation” in the Symbolic Math Toolbox documentation for more
information.
See Also
eig | poly | roots
More About
•
“Create and Evaluate Polynomials” on page 6-2
•
“Roots of Scalar Functions” on page 6-14
•
“Integrate and Differentiate Polynomials” on page 6-10
6-9
6
Functions of One Variable
Integrate and Differentiate Polynomials
This example shows how to use the polyint and polyder functions to analytically
integrate or differentiate any polynomial represented by a vector of coefficients.
Use polyder to obtain the derivative of the polynomial
resulting polynomial is
. The
.
p = [1 0 -2 -5];
q = polyder(p)
q =
3
0
-2
Similarly, use polyint to integrate the polynomial
polynomial is
. The resulting
.
p = [4 -3 0 1];
q = polyint(p)
q =
1
-1
0
1
0
polyder also computes the derivative of the product or quotient of two polynomials.
For example, create two vectors to represent the polynomials
and
.
a = [1 3 5];
b = [2 4 6];
Calculate the derivative
c = polyder(a,b)
6-10
by calling polyder with a single output argument.
Integrate and Differentiate Polynomials
c =
8
30
56
38
Calculate the derivative
resulting polynomial is
by calling polyder with two output arguments. The
[q,d] = polyder(a,b)
q =
-2
-8
-2
4
16
40
d =
48
36
See Also
conv | deconv | polyder | polyint
More About
•
“Analytic Solution to Integral of Polynomial” on page 11-114
•
“Create and Evaluate Polynomials” on page 6-2
6-11
6
Functions of One Variable
Polynomial Curve Fitting
This example shows how to fit a polynomial curve to a set of data using polyfit. Use
the polyfit function to find the coefficients of a polynomial that fits a set of data in a
least-squares sense using the syntax
p = polyfit(x,y,n),
where:
• x and y are vectors containing the x and y data to be fitted
• n is the degree of the polynomial to return
Consider the x-y test data
x = [1 2 3 4 5];
y = [5.5 43.1 128 290.7 498.4];
Use polyfit to find a third-degree polynomial that approximately fits the data.
p = polyfit(x,y,3)
p =
-0.1917
31.5821
-60.3262
35.3400
After you obtain the polynomial using polyfit, use polyval to evaluate the polynomial
at other points that might not have been included in the original data.
Compute the values of the polyfit estimate over a finer domain and plot the estimate
over the real data values for comparison.
x2 = 1:.1:5;
y2 = polyval(p,x2);
plot(x,y,'o',x2,y2)
grid on
6-12
Polynomial Curve Fitting
See Also
polyfit | polyval
More About
•
“Programmatic Fitting”
•
“Create and Evaluate Polynomials” on page 6-2
6-13
6
Functions of One Variable
Roots of Scalar Functions
In this section...
“Solving a Nonlinear Equation in One Variable” on page 6-14
“Using a Starting Interval” on page 6-16
“Using a Starting Point” on page 6-17
Solving a Nonlinear Equation in One Variable
The fzero function attempts to find a root of one equation with one variable. You can
call this function with either a one-element starting point or a two-element vector that
designates a starting interval. If you give fzero a starting point x0, fzero first searches
for an interval around this point where the function changes sign. If the interval is found,
fzero returns a value near where the function changes sign. If no such interval is found,
fzero returns NaN. Alternatively, if you know two points where the function value
differs in sign, you can specify this starting interval using a two-element vector; fzero is
guaranteed to narrow down the interval and return a value near a sign change.
The following sections contain two examples that illustrate how to find a zero of a
function using a starting interval and a starting point. The examples use the function
humps.m, which is provided with MATLAB. The following figure shows the graph of
humps.
x = -1:.01:2;
y = humps(x);
plot(x,y)
xlabel('x');
ylabel('humps(x)')
grid on
6-14
Roots of Scalar Functions
Setting Options For fzero
You can control several aspects of the fzero function by setting options. You set options
using optimset. Options include:
• Choosing the amount of display fzero generates — see “Set Options” on page
9-12, “Using a Starting Interval” on page 6-16, and “Using a Starting Point” on
page 6-17.
• Choosing various tolerances that control how fzero determines it is at a root — see
“Set Options” on page 9-12.
• Choosing a plot function for observing the progress of fzero towards a root — see
“Plot Functions” on page 9-26.
6-15
6
Functions of One Variable
• Using a custom-programmed output function for observing the progress of fzero
towards a root — see “Output Functions” on page 9-18.
Using a Starting Interval
The graph of humps indicates that the function is negative at x = -1 and positive at x =
1. You can confirm this by calculating humps at these two points.
humps(1)
ans =
16
humps(-1)
ans =
-5.1378
Consequently, you can use [-1 1] as a starting interval for fzero.
The iterative algorithm for fzero finds smaller and smaller subintervals of [-1 1]. For
each subinterval, the sign of humps differs at the two endpoints. As the endpoints of the
subintervals get closer and closer, they converge to zero for humps.
To show the progress of fzero at each iteration, set the Display option to iter using
the optimset function.
options = optimset('Display','iter');
Then call fzero as follows:
a = fzero(@humps,[-1 1],options)
Func-count
x
2
-1
3
-0.513876
4
-0.513876
5
-0.473635
6-16
f(x)
-5.13779
-4.02235
-4.02235
-3.83767
Procedure
initial
interpolation
bisection
interpolation
Roots of Scalar Functions
6
7
8
9
10
11
12
13
-0.115287
-0.115287
-0.132562
-0.131666
-0.131618
-0.131618
-0.131618
-0.131618
0.414441
0.414441
-0.0226907
-0.0011492
1.88371e-07
-2.7935e-11
8.88178e-16
8.88178e-16
bisection
interpolation
interpolation
interpolation
interpolation
interpolation
interpolation
interpolation
Zero found in the interval [-1, 1]
a =
-0.1316
Each value x represents the best endpoint so far. The Procedure column tells you
whether each step of the algorithm uses bisection or interpolation.
You can verify that the function value at a is close to zero by entering
humps(a)
ans =
8.8818e-16
Using a Starting Point
Suppose you do not know two points at which the function values of humps differ in sign.
In that case, you can choose a scalar x0 as the starting point for fzero. fzero first
searches for an interval around this point on which the function changes sign. If fzero
finds such an interval, it proceeds with the algorithm described in the previous section. If
no such interval is found, fzero returns NaN.
For example, set the starting point to -0.2, the Display option to Iter, and call fzero:
options = optimset('Display','iter');
a = fzero(@humps,-0.2,options)
Search for an interval around -0.2 containing a sign change:
Func-count
a
f(a)
b
f(b)
Procedure
6-17
6
Functions of One Variable
1
3
5
7
9
11
13
15
17
18
-0.2
-0.194343
-0.192
-0.188686
-0.184
-0.177373
-0.168
-0.154745
-0.136
-0.10949
-1.35385
-1.26077
-1.22137
-1.16477
-1.08293
-0.963455
-0.786636
-0.51962
-0.104165
0.572246
-0.2
-0.205657
-0.208
-0.211314
-0.216
-0.222627
-0.232
-0.245255
-0.264
-0.264
-1.35385
-1.44411
-1.4807
-1.53167
-1.60224
-1.69911
-1.83055
-2.00602
-2.23521
-2.23521
initial interval
search
search
search
search
search
search
search
search
search
Search for a zero in the interval [-0.10949, -0.264]:
Func-count
x
f(x)
Procedure
18
-0.10949
0.572246
initial
19
-0.140984
-0.219277
interpolation
20
-0.132259
-0.0154224
interpolation
21
-0.131617
3.40729e-05
interpolation
22
-0.131618 -6.79505e-08
interpolation
23
-0.131618 -2.98428e-13
interpolation
24
-0.131618
8.88178e-16
interpolation
25
-0.131618
8.88178e-16
interpolation
Zero found in the interval [-0.10949, -0.264]
a =
-0.1316
The endpoints of the current subinterval at each iteration are listed under the headings
a and b, while the corresponding values of humps at the endpoints are listed under f(a)
and f(b), respectively.
Note: The endpoints a and b are not listed in any specific order: a can be greater than b
or less than b.
For the first nine steps, the sign of humps is negative at both endpoints of the current
subinterval, which is shown in the output. At the tenth step, the sign of humps is positive
at the endpoint, -0.10949, but negative at the endpoint, -0.264. From this point on,
the algorithm continues to narrow down the interval [-0.10949 -0.264], as described
in the previous section, until it reaches the value -0.1316.
6-18
7
Computational Geometry
• “Overview” on page 7-2
• “Triangulation Representations” on page 7-3
• “Delaunay Triangulation” on page 7-17
• “Spatial Searching” on page 7-50
• “Voronoi Diagrams” on page 7-59
• “Types of Region Boundaries” on page 7-68
• “Computing the Convex Hull” on page 7-76
7
Computational Geometry
Overview
MATLAB software provides a variety of tools to solve problems that are geometric in
nature. These problems encompass simple geometric queries such as point-in-polygon
tests, to more complex problems such as nearest-neighbor queries. Convex hulls,
Delaunay triangulations, and Voronoi diagrams are examples of fundamental geometric
algorithms that MATLAB provides. These algorithms have many practical uses in the
scientific development.
MATLAB provides both function-based and class-based tools for computational geometry.
The function-based tools are convenient when the output from the function is sufficiently
complete to get you to the solution. The class-based tools are more versatile because they
provide complementary methods that are often needed to work with the resulting data.
A function typically takes input, performs some computation, and outputs the result in
matrix format.
In contrast, a class may take input, perform some computation, cache the result and
provide methods that allow you to query and work with the result more efficiently. For
example, the delaunay function creates a triangulation from a set of points and returns
the triangulation in an array. The delaunayTriangulation class also triangulates a set
of points. In addition, it allows you to modify the triangulation and it provides methods
for finding nearest neighbors and traversing the triangulation data structure, etc. These
methods are very efficient because the class holds the triangulation in memory.
7-2
Triangulation Representations
Triangulation Representations
2-D and 3-D Domains
Triangulations are often used to represent 2-D and 3-D geometric domains in application
areas such as computer graphics, physical modeling, geographic information systems,
medical imaging, and more. The map polygon shown here
can be represented by the triangulation on the map shown below.
7-3
7
Computational Geometry
The triangulation decomposes a complex polygon into a collection of simpler triangular
polygons. You can use these polygons for developing geometric-based algorithms or
graphics applications.
Similarly, you can represent the boundary of a 3-D geometric domain using a
triangulation. The figure below shows the convex hull of a set of points in 3-D space.
Each facet of the hull is a triangle.
Triangulation Matrix Format
MATLAB software uses a matrix format to represent triangulations. This format has two
parts:
• The vertices, represented as a matrix in which each row contains the coordinates of a
point in the triangulation.
• The triangulation connectivity, represented as a matrix in which each row defines a
triangle or tetrahedon.
This figure shows a simple 2-D triangulation.
7-4
Triangulation Representations
The following table shows the vertex information.
Vertices
Vertex ID
x-coordinate
y-coordinate
V1
2.5
8.0
V2
6.5
8.0
V3
2.5
5.0
V4
6.5
5.0
V5
1.0
6.5
V6
8.0
6.5
The data in the previous table is stored as a matrix in the MATLAB environment. The
vertex IDs are labels used for identifying specific vertices. They are shown to illustrate
the concept of a vertex ID, but they are not stored explicitly. Instead, the row numbers of
the matrix serve as the vertex IDs.
7-5
7
Computational Geometry
The triangulation connectivity data is shown in this table.
Connectivity
Triangle ID
IDs of Bounding Vertices
T1
5
3
1
T2
3
2
1
T3
3
4
2
T4
4
6
2
The data in this table is stored as a matrix in the MATLAB environment. The triangle
IDs are labels used for identifying specific triangles. They are shown to illustrate the
concept of a triangle ID, but they are not stored explicitly. Instead, the row numbers of
the matrix serve as the triangle IDs.
You can see that triangle T1 is defined by three vertices, {V5, V3, V1}. Similarly,
T4 is defined by the vertices, {V4, V6, V2}. This format extends naturally to higher
dimensions, which require additional columns of data. For example, a tetrahedron in 3-D
space is defined by four vertices, each of which have three coordinates, (x, y, z).
You can represent and query the following types of triangulations using MATLAB
software:
• 2-D triangulations consisting of triangles bounded by vertices and edges
• 3-D surface triangulations consisting of triangles bounded by vertices and edges
• 3-D triangulations consisting of tetrahedra bounded by vertices, edges, and faces
Querying Triangulations Using the triangulation Class
The matrix format provides a compact low-level, array-based representation for
triangulations. When you use triangulations to develop algorithms, you might need more
information about the geometric properties, topology, and adjacency information.
For example, you might compute the triangle incenters before plotting the annotated
triangulation shown below. In this case, you use the incenters to display the triangle
labels (T1, T2, etc.) within each triangle. If you want to plot the boundary in red, you
need to determine the edges that are referenced by only one triangle.
7-6
Triangulation Representations
The triangulation Class
You can use triangulation to create an in-memory representation of any 2-D or 3D triangulation data that is in matrix format, such as the matrix output from the
delaunay function or other software tools. When your data is represented using
triangulation, you can perform topological and geometric queries, which you can use
to develop geometric algorithms. For example, you can find the triangles or tetrahedra
attached to a vertex, those that share an edge, their circumcenters, and other features.
You can create a triangulation in one of two ways:
• Pass existing data that you have in matrix format to triangulation. This data
can be the output from a MATLAB function, such as delaunay or convhull. You
also can import triangulation data that was created by another software application.
When you work with imported data, be sure the connectivity data references the
vertex array using 1-based indexing instead of 0-based indexing.
• Pass a set of points to delaunayTriangulation. The resulting Delaunay
triangulation is a special kind of triangulation. This means you can perform any
triangulation query on your data, as well as any Delaunay-specific query. In
more formal MATLAB language terms, delaunayTriangulation is a subclass of
triangulation.
7-7
7
Computational Geometry
Creating a triangulation from Matrix Data
This example shows how to use the triangulation matrix data to create a triangulation,
explore what it is, and explore what it can do.
Create a matrix, P, that contains the vertex data.
P = [ 2.5
6.5
2.5
6.5
1.0
8.0
8.0
8.0
5.0
5.0
6.5
6.5];
Define the connectivity, T.
T = [5
3
3
4
3
2
4
6
1;
1;
2;
2];
Create a triangulation from this data.
TR = triangulation(T,P)
TR =
triangulation with properties:
Points: [6x2 double]
ConnectivityList: [4x3 double]
Access the properties in a triangulation in the same way you access the fields of a
struct. For example, examine the Points property, which contains the coordinates of
the vertices.
TR.Points
ans =
2.5000
7-8
8.0000
Triangulation Representations
6.5000
2.5000
6.5000
1.0000
8.0000
8.0000
5.0000
5.0000
6.5000
6.5000
Next, examine the connectivity.
TR.ConnectivityList
ans =
5
3
3
4
3
2
4
6
1
1
2
2
The Points and ConnectivityList properties define the matrix data for the
triangulation.
The triangulation class is a wrapper around the matrix data. The real benefit is the
usefulness of the triangulation class methods. The methods are like functions that
accept a triangulation and other relevant input data.
The triangulation class provides an easy way to index into the ConnectivityList
property matrix. Access the first triangle in the triangulation.
TR.ConnectivityList(1,:)
ans =
5
3
1
Another way of getting the first triangle is TR(1,:).
Examine the first vertex of the first triangle.
TR(1,1)
7-9
7
Computational Geometry
ans =
5
Examine the second vertex of the first triangle.
TR(1,2)
ans =
3
Now, examine all the triangles in the triangulation.
TR(:,:)
ans =
5
3
3
4
3
2
4
6
1
1
2
2
Use triplot to plot the triangulation. The triplot function is not a
triangulation method, but it accepts and can plot a triangulation.
figure
triplot(TR)
axis equal
7-10
Triangulation Representations
Use the triangulation method, freeBoundary, to query the free boundary and
highlight it in a plot. This method returns the edges of the triangulation that are shared
by only one triangle. The returned edges are expressed in terms of the vertex IDs.
boundaryedges = freeBoundary(TR)';
Now plot the boundary edges as a red line.
hold on
plot(P(boundaryedges,1),P(boundaryedges,2),'-r','LineWidth',2)
hold off
7-11
7
Computational Geometry
You can use the freeBoundary method to validate a triangulation. For example, if you
observed red edges in the interior of the triangulation, then it would indicate a problem
in how the triangles are connected.
Creating a triangulation Using delaunayTriangulation
This example shows how to create a Delaunay triangulation using
delaunayTriangulation.
When you create a Delaunay triangulation using the delaunayTriangulation
class, you automatically get access to the triangulation methods because
delaunayTriangulation is a subclass of triangulation.
Create a delaunayTriangulation from a set of points.
7-12
Triangulation Representations
P = [ 2.5
6.5
2.5
6.5
1.0
8.0
8.0
8.0
5.0
5.0
6.5
6.5];
DT = delaunayTriangulation(P)
DT =
delaunayTriangulation with properties:
Points: [6x2 double]
ConnectivityList: [4x3 double]
Constraints: []
The resulting delaunayTriangulation object has the properties, Points and
ConnectivityList, just like a triangulation object.
You can access the triangulation using direct indexing, just like triangulation. For
example, examine the connectivity of the first triangle.
DT(1,:)
ans =
5
3
1
Next, examine the connectivity of the entire triangulation.
DT(:,:)
ans =
5
3
1
4
3
4
4
6
1
1
2
2
7-13
7
Computational Geometry
Use the triplot function to plot the triangulation.
triplot(DT)
axis equal
The parent class, triangulation, provides the incenter method to compute the
incenters of each triangle.
IC = incenter(DT)
IC =
1.8787
3.5000
7-14
6.5000
6.0000
Triangulation Representations
5.5000
7.1213
7.0000
6.5000
The returned value, IC, is an array of coordinates representing the incenters of the
triangles.
Now, use the incenters to find the positions for placing triangle labels on the plot.
hold on
numtri = size(DT,1);
trilabels = arrayfun(@(P) {sprintf('T%d', P)}, (1:numtri)');
Htl = text(IC(:,1),IC(:,2),trilabels,'FontWeight','bold', ...
'HorizontalAlignment','center','Color','blue');
hold off
7-15
7
Computational Geometry
Instead of creating a Delaunay triangulation using delaunayTriangulation, you could
use the delaunay function to create the triangulation connectivity data, and then pass
the connectivity data to triangulation. For example,
P = [ 2.5
6.5
2.5
6.5
1.0
8.0
8.0
8.0
5.0
5.0
6.5
6.5];
T = delaunay(P);
TR = triangulation(T,P);
IC = incenter(TR);
Both approaches are valid in this example, but if you want to create a Delaunay
triangulation and perform queries on it, then you should use delaunayTriangulation
for these reasons:
• The delaunayTriangulation class provides additional methods that are useful for
working with triangulations. For example, you can to perform nearest-neighbor and
point-in-triangle searches.
• It allows you to edit the triangulation to add, move, or remove points.
• It allows you to create constrained Delaunay triangulations. This allows you to create
a triangulation for a 2-D domain.
See Also
delaunay | delaunayTriangulation | freeBoundary | triangulation | triplot
More About
7-16
•
“Triangulation Representations” on page 7-3
•
“Delaunay Triangulation” on page 7-17
•
“Spatial Searching” on page 7-50
Delaunay Triangulation
Delaunay Triangulation
In this section...
“Definition of Delaunay Triangulation” on page 7-17
“Creating Delaunay Triangulations” on page 7-19
“Triangulation of Point Sets Containing Duplicate Locations” on page 7-47
Definition of Delaunay Triangulation
Delaunay triangulations are widely used in scientific computing in many diverse
applications. While there are numerous algorithms for computing triangulations, it is the
favorable geometric properties of the Delaunay triangulation that make it so useful.
The fundamental property is the Delaunay criterion. In the case of 2-D triangulations,
this is often called the empty circumcircle criterion. For a set of points in 2-D, a Delaunay
triangulation of these points ensures the circumcircle associated with each triangle
contains no other point in its interior. This property is important. In the illustration
below, the circumcircle associated with T1 is empty. It does not contain a point in its
interior. The circumcircle associated with T2 is empty. It does not contain a point in its
interior. This triangulation is a Delaunay triangulation.
The triangles below are different. The circumcircle associated with T1 is not empty. It
contains V3 in its interior. The circumcircle associated with T2 is not empty. It contains
V1 in its interior. This triangulation is not a Delaunay triangulation.
7-17
7
Computational Geometry
Delaunay triangles are said to be “well shaped” because in fulfilling the empty
circumcircle property, triangles with large internal angles are selected over ones with
small internal angles. The triangles in the non-Delaunay triangulation have sharp angles
at vertices V2 and V4. If the edge {V2, V4} were replaced by an edge joining V1 and V3,
the minimum angle would be maximized and the triangulation would become a Delaunay
triangulation. Also, the Delaunay triangulation connects points in a nearest-neighbor
manner. These two characteristics, well-shaped triangles and the nearest-neighbor
relation, have important implications in practice and motivate the use of Delaunay
triangulations in scattered data interpolation.
While the Delaunay property is well defined, the topology of the triangulation is not
unique in the presence of degenerate point sets. In two dimensions, degeneracies arise
when four or more unique points lie on the same circle. The vertices of a square, for
example, have a nonunique Delaunay triangulation.
7-18
Delaunay Triangulation
The properties of Delaunay triangulations extend to higher dimensions. The
triangulation of a 3-D set of points is composed of tetrahedra. The next illustration shows
a simple 3-D Delaunay triangulation made up of two tetrahedra. The circumsphere of one
tetrahedron is shown to highlight the empty circumsphere criterion.
A 3-D Delaunay triangulation produces tetrahedra that satisfy the empty circumsphere
criterion.
Creating Delaunay Triangulations
MATLAB provides two ways to create Delaunay triangulations:
• The functions delaunay and delaunayn
• The delaunayTriangulation class
The delaunay function supports the creation of 2-D and 3-D Delaunay triangulations.
The delaunayn function supports creating Delaunay triangulations in 4-D and higher.
Tip Creating Delaunay triangulations in dimensions higher than 6-D is generally not
practical for moderate to large point sets due to the exponential growth in required
memory.
7-19
7
Computational Geometry
The delaunayTriangulation class supports creating Delaunay triangulations in 2-D
and 3-D. It provides many methods that are useful for developing triangulation-based
algorithms. These class methods are like functions, but they are restricted to work with
triangulations created using delaunayTriangulation. The delaunayTriangulation
class also supports the creation of related constructs such as the convex hull and Voronoi
diagram. It also supports the creation of constrained Delaunay triangulations.
In summary:
• The delaunay function is useful when you only require the basic triangulation data,
and that data is sufficiently complete for your application.
• The delaunayTriangulation class offers more functionality for developing
triangulation-based applications. It is useful when you require the triangulation and
you want to perform any of these operations:
• Search the triangulation for triangles or tetrahedra enclosing a query point.
• Use the triangulation to perform a nearest-neighbor point search.
• Query the triangulation's topological adjacency or geometric properties.
• Modify the triangulation to insert or remove points.
• Constrain edges in the triangulation—this is called a constrained Delaunay
triangulation.
• Triangulate a polygon and optionally remove the triangles that are outside of the
domain.
• Use the Delaunay triangulation to compute the convex hull or Voronoi diagram.
Using the delaunay and delaunayn functions
The delaunay and delaunayn functions take a set of points and produce a triangulation
in matrix format. Refer to “Triangulation Matrix Format” on page 7-4 for more
information on this data structure. In 2-D, the delaunay function is often used to
produce a triangulation that can be used to plot a surface defined in terms of a set of
scattered data points. In this application, it’s important to note that this approach
can only be used if the surface is single-valued. For example, it could not be used to
plot a spherical surface because there are two z values corresponding to a single (x, y)
coordinate. A simple example demonstrates how the delaunay function can be used to
plot a surface representing a sampled data set.
This example shows how to use the delaunay function to create a 2-D Delaunay
triangulation from the seamount data set. A seamount is an underwater mountain. The
7-20
Delaunay Triangulation
data set consists of a set of longitude (x) and latitude (y) locations, and corresponding
seamount elevations (z) measured at those coordinates.
Load the seamount data set and view the (x, y) data as a scatter plot.
load seamount
plot(x,y,'.','markersize',12)
xlabel('Longitude'), ylabel('Latitude')
grid on
Construct a Delaunay triangulation from this point set and use triplot to plot the
triangulation in the existing figure.
tri = delaunay(x,y);
7-21
7
Computational Geometry
hold on, triplot(tri,x,y), hold off
Add the depth data (z) from seamount to lift the vertices and create the surface. Create a
new figure and use trimesh to plot the surface in wireframe mode.
figure
hidden on
trimesh(tri,x,y,z)
xlabel('Longitude'),ylabel('Latitude'),zlabel('Depth in Feet');
7-22
Delaunay Triangulation
If you want to plot the surface in shaded mode, use trisurf instead of trimesh.
A 3-D Delaunay triangulation also can be created using the delaunay function. This
triangulation is composed of tetrahedra.
This example shows how to create a 3-D Delaunay triangulation of a random data
set. The triangulation is plotted using tetramesh, and the FaceAlpha option adds
transparency to the plot.
X = gallery('uniformdata',[30 3],0);
tet = delaunay(X);
faceColor = [0.6875 0.8750 0.8984];
tetramesh(tet,X,'FaceColor', faceColor,'FaceAlpha',0.3);
7-23
7
Computational Geometry
MATLAB provides the delaunayn function to support the creation of Delaunay
triangulations in dimension 4-D and higher. Two complementary functions tsearchn
and dsearchn are also provided to support spatial searching for N-D triangulations. See
“Spatial Searching” on page 7-50 for more information on triangulation-based search.
Using the delaunayTriangulation Class
The delaunayTriangulation class provides another way to create Delaunay triangulations
in MATLAB. While delaunay and delaunayTriangulation use the same underlying
algorithm and produce the same triangulation, delaunayTriangulation provides
complementary methods that are useful for developing Delaunay-based algorithms.
These methods are like functions that are packaged together with the triangulation
data into a container called a class. Keeping everything together in a class provides
7-24
Delaunay Triangulation
a more organized setup that improves ease of use. It also improves the performance
of triangulation-based searches such as point-location and nearest-neighbor.
delaunayTriangulation supports incremental editing of the Delaunay triangulation.
You also can impose edge constraints in 2-D.
“Triangulation Representations” on page 7-3 introduces the triangulation class,
which supports topological and geometric queries for 2-D and 3-D triangulations.
A delaunayTriangulation is a special kind of triangulation. This means
you can perform any triangulation query on a delaunayTriangulation in
addition to the Delaunay-specific queries. In more formal MATLAB language terms,
delaunayTriangulation is a subclass of triangulation.
This example shows how to create, query, and edit a Delaunay triangulation from the
seamount data using delaunayTriangulation. The seamount data set contains (x, y)
locations and corresponding elevations (z) that define the surface of the seamount.
Load and triangulate the (x, y) data.
load seamount
DT = delaunayTriangulation(x,y)
DT =
delaunayTriangulation with properties:
Points: [294x2 double]
ConnectivityList: [566x3 double]
Constraints: []
The Constraints property is empty because there aren't any imposed edge
constraints. The Points property represents the coordinates of the vertices, and the
ConnectivityList property represents the triangles. Together, these two properties
define the matrix data for the triangulation.
The delaunayTriangulation class is a wrapper around the matrix data, and it offers a
set of complementary methods. You access the properties in a delaunayTriangulation
in the same way you access the fields of a struct.
Access the vertex data.
DT.Points;
7-25
7
Computational Geometry
Access the connectivity data.
DT.ConnectivityList;
Access the first triangle in the ConnectivityList property.
DT.ConnectivityList(1,:)
ans =
205
230
262
delaunayTriangulation provides an easy way to index into the ConnectivityList
property matrix.
Access the first triangle.
DT(1,:)
ans =
205
230
262
Examine the first vertex of the first triangle.
DT(1,1)
ans =
205
Examine all the triangles in the triangulation.
DT(:,:);
Indexing into the delaunayTriangulation output, DT, works like indexing into the
triangulation array output from delaunay. The difference between the two are the extra
methods that you can call on DT (for example, nearestNeighbor and pointLocation).
7-26
Delaunay Triangulation
Use triplot to plot the delaunayTriangulation. The triplot function
is not a delaunayTriangulation method, but it accepts and can plot a
delaunayTriangulation.
triplot(DT);
axis equal
xlabel('Longitude'), ylabel('Latitude')
grid on
Alternatively, you could use triplot(DT(:,:), DT.Points(:,1),
DT.Points(:,2)); to get the same plot.
Use the delaunayTriangulation method, convexHull, to compute the convex hull
and add it to the plot. Since you already have a Delaunay triangulation, this method
7-27
7
Computational Geometry
allows you to derive the convex hull more efficiently than a full computation using
convhull.
hold on
k = convexHull(DT);
xHull = DT.Points(k,1);
yHull = DT.Points(k,2);
plot(xHull,yHull,'r','LineWidth',2);
hold off
You can incrementally edit the delaunayTriangulation to add or remove points.
If you need to add points to an existing triangulation, then an incremental addition is
faster than a complete retriangulation of the augmented point set. Incremental removal
7-28
Delaunay Triangulation
of points is more efficient when the number of points to be removed is small relative to
the existing number of points.
Edit the triangulation to remove the points on the convex hull from the previous
computation.
figure
plot(xHull,yHull,'r','LineWidth',2);
axis equal
xlabel('Longitude'),ylabel('Latitude')
grid on
% The convex hull topology duplicates the start and end vertex.
% Remove the duplicate entry.
k(end) = [];
% Now remove the points on the convex hull.
DT.Points(k,:) = []
% Plot the new triangulation
hold on
triplot(DT);
hold off
DT =
delaunayTriangulation with properties:
Points: [274x2 double]
ConnectivityList: [528x3 double]
Constraints: []
7-29
7
Computational Geometry
There is one vertex that is just inside the boundary of the convex hull that was not
removed. The fact that it is interior to the hull can be seen using the Zoom-In tool in the
figure. You could plot the vertex labels to determine the index of this vertex and remove
it from the triangulation. Alternatively, you can use the nearestNeighbor method to
identify the index more readily.
The point is close to location (211.6, -48.15) Use the nearestNeighbor method to find the
nearest vertex.
vertexId = nearestNeighbor(DT, 211.6, -48.15)
vertexId =
7-30
Delaunay Triangulation
50
Now remove that vertex from the triangulation.
DT.Points(vertexId,:) = []
DT =
delaunayTriangulation with properties:
Points: [273x2 double]
ConnectivityList: [525x3 double]
Constraints: []
Plot the new triangulation.
figure
plot(xHull,yHull,'r','LineWidth',2);
axis equal
xlabel('Longitude'),ylabel('Latitude')
grid on
hold on
triplot(DT);
hold off
7-31
7
Computational Geometry
Add points to the existing triangulation. Add 4 points to form a rectangle around the
triangulation.
Padditional = [210.9 -48.5; 211.6 -48.5; ...
211.6 -47.9; 210.9 -47.9];
DT.Points(end+(1:4),:) = Padditional
DT =
delaunayTriangulation with properties:
Points: [277x2 double]
ConnectivityList: [548x3 double]
7-32
Delaunay Triangulation
Constraints: []
Close all existing figures.
close all
Plot the new triangulation.
figure
plot(xHull,yHull,'r','LineWidth',2);
axis equal
xlabel('Longitude'),ylabel('Latitude')
grid on
hold on
triplot(DT);
hold off
7-33
7
Computational Geometry
You can edit the points in the triangulation to move them to a new location. Edit the first
of the additional point set (the vertex ID 274).
DT.Points(274,:) = [211 -48.4];
Close all existing figures.
close all
Plot the new triangulation
figure
plot(xHull,yHull,'r','LineWidth',2);
axis equal
7-34
Delaunay Triangulation
xlabel('Longitude'),ylabel('Latitude')
grid on
hold on
triplot(DT);
hold off
Use the a method of the triangulation class, vertexAttachments, to find the
attached triangles. Since the number of triangles attached to a vertex is variable, the
method returns the attached triangle IDs in a cell array. You need braces to extract the
contents.
attTris = vertexAttachments(DT,274);
hold on
triplot(DT(attTris{:},:),DT.Points(:,1),DT.Points(:,2),'g')
7-35
7
Computational Geometry
hold off
delaunayTriangulation also can be used to triangulate points in 3-D space. The
resulting triangulation is composed of tetrahedra.
This example shows how to use a delaunayTriangulation to create and plot the
triangulation of 3-D points.
P = gallery('uniformdata',30,3,0);
DT = delaunayTriangulation(P)
faceColor = [0.6875 0.8750 0.8984];
tetramesh(DT,'FaceColor', faceColor,'FaceAlpha',0.3);
7-36
Delaunay Triangulation
DT =
delaunayTriangulation with properties:
Points: [30x3 double]
ConnectivityList: [117x4 double]
Constraints: []
The tetramesh function plots both the internal and external faces of the triangulation.
For large 3-D triangulations, plotting the internal faces might be an unnecessary
use of resources. A plot of the boundary might be more appropriate. You can use the
freeBoundary method to get the boundary triangulation in matrix format. Then pass
the result to trimesh or trisurf.
7-37
7
Computational Geometry
Constrained Delaunay Triangulation
The delaunayTriangulation class allows you to constrain edges in a 2-D triangulation.
This means you can chose a pair of points in the triangulation and constrain an edge to
join those points. You can picture this as “forcing” an edge between one or more pairs of
points. The following example shows how edge constraints can affect the triangulation.
The triangulation below is a Delaunay triangulation because it respects the empty
circumcircle criterion.
Triangulate a set of points with an edge constraint specified between vertex V1 and V3.
Define the point set.
P = [2 4; 6 1; 9 4; 6 7];
Define a constraint, C, between V1 and V3.
C = [1 3];
DT = delaunayTriangulation(P,C);
Plot the triangulation and add annotations.
triplot(DT)
% Label the vertices.
hold on
numvx = size(P,1);
vxlabels = arrayfun(@(n) {sprintf('V%d', n)}, (1:numvx)');
Hpl = text(P(:,1)+0.2, P(:,2)+0.2, vxlabels, 'FontWeight', ...
'bold', 'HorizontalAlignment','center', 'BackgroundColor', ...
'none');
7-38
Delaunay Triangulation
hold off
% Use the incenters to find the positions for placing triangle labels on the plot.
hold on
IC = incenter(DT);
numtri = size(DT,1);
trilabels = arrayfun(@(P) {sprintf('T%d', P)}, (1:numtri)');
Htl = text(IC(:,1),IC(:,2),trilabels,'FontWeight','bold', ...
'HorizontalAlignment','center','Color','blue');
hold off
% Plot the circumcircle associated with the triangle, T1.
hold on
[CC,r] = circumcenter(DT);
theta = 0:pi/50:2*pi;
xunit = r(1)*cos(theta) + CC(1,1);
yunit = r(1)*sin(theta) + CC(1,2);
plot(xunit,yunit,'g');
axis equal
hold off
7-39
7
Computational Geometry
The constraint between vertices (V1, V3) was honored, however, the Delaunay criterion
was invalidated. This also invalidates the nearest-neighbor relation that is inherent in a
Delaunay triangulation. This means the nearestNeighbor search method provided by
delaunayTriangulation cannot be supported if the triangulation has constraints.
In typical applications, the triangulation might be composed of many points, and a
relatively small number of edges in the triangulation might be constrained. Such
a triangulation is said to be locally non-Delaunay, because many triangles in the
triangulation might respect the Delaunay criterion, but locally there might be some
triangles that do not. In many applications, local relaxation of the empty circumcircle
property is not a concern.
7-40
Delaunay Triangulation
Constrained triangulations are generally used to triangulate a nonconvex polygon. The
constraints give us a correspondence between the polygon edges and the triangulation
edges. This relationship enables you to extract a triangulation that represents the region.
The following example shows how to use a constrained delaunayTriangulation to
triangulate a nonconvex polygon.
Define and plot a polygon.
figure()
axis([-1 17 -1 6]);
axis equal
P = [0 0; 16 0; 16 2; 2 2; 2 3; 8 3; 8 5; 0 5];
patch(P(:,1),P(:,2),'-r','LineWidth',2,'FaceColor',...
'none','EdgeColor','r');
% Label the points.
hold on
numvx = size(P,1);
vxlabels = arrayfun(@(n) {sprintf('P%d', n)}, (1:numvx)');
Hpl = text(P(:,1)+0.2, P(:,2)+0.2, vxlabels, 'FontWeight', ...
'bold', 'HorizontalAlignment','center', 'BackgroundColor', ...
'none');
hold off
7-41
7
Computational Geometry
Create and plot the triangulation together with the polygon boundary.
figure()
subplot(2,1,1);
axis([-1 17 -1 6]);
axis equal
P = [0 0; 16 0; 16 2; 2 2; 2 3; 8 3; 8 5; 0 5];
DT = delaunayTriangulation(P);
triplot(DT)
hold on;
patch(P(:,1),P(:,2),'-r','LineWidth',2,'FaceColor',...
'none','EdgeColor','r');
hold off
7-42
Delaunay Triangulation
% Plot the standalone triangulation in a subplot.
subplot(2,1,2);
axis([-1 17 -1 6]);
axis equal
triplot(DT)
This triangulation cannot be used to represent the domain of the polygon because some
triangles cut across the boundary. You need to impose a constraint on the edges that are
cut by triangulation edges. Since all edges have to be respected, you need to constrain all
edges. The steps below show how to constrain all the edges.
Enter the constrained edge definition. Observe from the annotated figure where you need
constraints (between (V1, V2), (V2, V3), and so on).
7-43
7
Computational Geometry
C = [1 2; 2 3; 3 4; 4 5; 5 6; 6 7; 7 8; 8 1];
In general, if you have N points in a sequence that define a polygonal boundary, the
constraints can be expressed as C = [(1:(N-1))' (2:N)'; N 1];.
Specify the constraints when you create the delaunayTriangulation.
DT = delaunayTriangulation(P,C);
Alternatively, you can impose constraints on an existing triangulation by setting the
Constraints property: DT.Constraints = C;.
Plot the triangulation and polygon.
figure('Color','white')
subplot(2,1,1);
axis([-1 17 -1 6]);
axis equal
triplot(DT)
hold on;
patch(P(:,1),P(:,2),'-r','LineWidth',2, ...
'FaceColor','none','EdgeColor','r');
hold off
% Plot the standalone triangulation in a subplot.
subplot(2,1,2);
axis([-1 17 -1 6]);
axis equal
triplot(DT)
7-44
Delaunay Triangulation
The plot shows that the edges of the triangulation respect the boundary of the polygon.
However, the triangulation fills the concavities. What is needed is a triangulation that
represents the polygonal domain. You can extract the triangles within the polygon using
the delaunayTriangulation method, isInterior. This method returns a logical
array whose true and false values that indicate whether the triangles are inside a
bounded geometric domain. The analysis is based on the Jordan Curve theorem, and the
boundaries are defined by the edge constraints. The ith triangle in the triangulation is
considered to be inside the domain if the ith logical flag is true, otherwise it is outside.
Now use the isInterior method to compute and plot the set of domain triangles.
% Plot the constrained edges in red
figure('Color','white')
7-45
7
Computational Geometry
subplot(2,1,1);
plot(P(C'),P(C'+size(P,1)),'-r','LineWidth', 2);
axis([-1 17 -1 6]);
% Compute the in/out status
IO = isInterior(DT);
subplot(2,1,2);
hold on;
axis([-1 17 -1 6]);
% Use triplot to plot the triangles that are inside.
% Uses logical indexing and dt(i,j) shorthand
% format to access the triangulation.
triplot(DT(IO, :),DT.Points(:,1), DT.Points(:,2),'LineWidth', 2)
hold off;
7-46
Delaunay Triangulation
Triangulation of Point Sets Containing Duplicate Locations
The Delaunay algorithms in MATLAB construct a triangulation from a unique set
of points. If the points passed to the triangulation function, or class, are not unique,
the duplicate locations are detected and the duplicate point is ignored. This produces
a triangulation that does not reference some points in the original input, namely
the duplicate points. When you work with the delaunay and delaunayn functions,
the presence of duplicates may be of little consequence. However, since many of the
queries provided by the delaunayTriangulation class are index based, it is important to
understand that delaunayTriangulation triangulates and works with the unique
data set. Therefore, indexing based on the unique point set is the convention. This data is
maintained by the Points property of delaunayTriangulation.
7-47
7
Computational Geometry
The following example illustrates the importance of referencing the unique data set
stored within the Points property when working with delaunayTriangulation:
P = gallery('uniformdata',[25 2],0);
P(18,:) = P(8,:)
P(16,:) = P(6,:)
P(12,:) = P(2,:)
DT = delaunayTriangulation(P)
When the triangulation is created, MATLAB issues a warning. The Points property
shows that the duplicate points have been removed from the data.
DT =
delaunayTriangulation with properties:
Points: [22x2 double]
ConnectivityList: [31x3 double]
Constraints: []
If for example, the Delaunay triangulation is used to compute the convex hull, the indices
of the points on the hull are indices with respect to the unique point set, DT.Points.
Therefore, use the following code to compute and plot the convex hull:
K = DT.convexHull();
plot(DT.Points(:,1),DT.Points(:,2),'.');
hold on
plot(DT.Points(K,1),DT.Points(K,2),'-r');
If the original data set containing the duplicates were used in conjunction with the
indices provided by delaunayTriangulation, then the result would be incorrect. The
delaunayTriangulation works with indices that are based on the unique data set
DT.Points. For example, the following would produce an incorrect plot, because K is
indexed with respect to DT.Points and not P:
K = DT.convexHull();
plot(P(:,1),P(:,2),'.');
hold on
plot(P(K,1),P(K,2),'-r');
It’s often more convenient to create a unique data set by removing duplicates prior
to creating the delaunayTriangulation. Doing this eliminates the potential for
confusion. This can be accomplished using the unique function as follows:
P = gallery('uniformdata',[25 2],0);
P(18,:) = P(8,:)
P(16,:) = P(6,:)
7-48
Delaunay Triangulation
P(12,:) = P(2,:)
[~, I, ~] = unique(P,'first','rows');
I = sort(I);
P = P(I,:);
DT = delaunayTriangulation(P) % The point set is unique
More About
•
“Spatial Searching” on page 7-50
7-49
7
Computational Geometry
Spatial Searching
In this section...
“Introduction” on page 7-50
“Nearest-Neighbor Search” on page 7-50
“Point-Location Search” on page 7-54
Introduction
MATLAB provides the necessary functions for performing a spatial search using either
a Delaunay triangulation or a general triangulation. The search queries that MATLAB
supports are:
• Nearest-neighbor search (sometimes called closest-point search or proximity search).
• Point-location search (sometimes called point-in-triangle search or point-in-simplex
search, where a simplex is a triangle, tetrahedron or higher dimensional equivalent).
Given a set of points X and a query point q in Euclidean space, the nearest-neighbor
search locates a point p in X that is closer to q than to any other point in X. Given a
triangulation of X, the point-location search locates the triangle or tetrahedron that
contains the query point q. Since these methods work for both Delaunay as well as
general triangulations, you can use them even if a modification of the points violates the
Delaunay criterion. You also can search a general triangulation represented in matrix
format.
While MATLAB supports these search schemes in N dimensions, exact spatial searches
usually become prohibitive as the number of dimensions extends beyond 3-D. You should
consider approximate alternatives for large problems in up to 10 dimensions.
Nearest-Neighbor Search
There are a few ways to compute nearest-neighbors in MATLAB, depending on the
dimensionality of the problem:
• For 2-D and 3-D searches, use the nearestNeighbor method provided by the
triangulation class and inherited by the delaunayTriangulation class.
7-50
Spatial Searching
• For 4-D and higher, use the delaunayn function to construct the triangulation
and the complementary dsearchn function to perform the search. While these
N-D functions support 2-D and 3-D, they are not as general and efficient as the
triangulation search methods.
This example shows how to perform a nearest-neighbor search in 2-D with
delaunayTriangulation.
Begin by creating a random set of 15 points.
X = [3.5 8.2; 6.8 8.3; 1.3 6.5; 3.5 6.3; 5.8 6.2; 8.3 6.5;...
1 4; 2.7 4.3; 5 4.5; 7 3.5; 8.7 4.2; 1.5 2.1; 4.1 1.1; ...
7 1.5; 8.5 2.75];
Plot the points and add annotations to show the ID labels.
plot(X(:,1),X(:,2),'ob')
hold on
vxlabels = arrayfun(@(n) {sprintf('X%d', n)}, (1:15)');
Hpl = text(X(:,1)+0.2, X(:,2)+0.2, vxlabels, 'FontWeight', ...
'bold', 'HorizontalAlignment','center', 'BackgroundColor', ...
'none');
hold off
7-51
7
Computational Geometry
Create a Delaunay triangulation from the points.
dt = delaunayTriangulation(X);
Create some query points and for each query point find the index of its corresponding
nearest neighbor in X using the nearestNeighbor method.
numq = 10;
rng(0,'twister');
q = 2+rand(numq,2)*6;
xi = nearestNeighbor(dt, q);
Add the query points to the plot and add line segments joining the query points to their
nearest neighbors.
7-52
Spatial Searching
xnn = X(xi,:);
hold on
plot(q(:,1),q(:,2),'or');
plot([xnn(:,1) q(:,1)]',[xnn(:,2) q(:,2)]','-r');
vxlabels = arrayfun(@(n) {sprintf('q%d', n)}, (1:numq)');
Hpl = text(q(:,1)+0.2, q(:,2)+0.2, vxlabels, 'FontWeight', ...
'bold', 'HorizontalAlignment','center', ...
'BackgroundColor','none');
hold off
7-53
7
Computational Geometry
Performing a nearest-neighbor search in 3-D is a direct extension of the 2-D example
based on delaunayTriangulation.
For 4-D and higher, use the delaunayn and dsearchn functions as illustrated in the
following example:
Create a random sample of points in 4-D and triangulate the points using delaunayn:
X = 20*rand(50,4) -10;
tri = delaunayn(X);
Create some query points and for each query point find the index of its corresponding
nearest-neighbor in X using the dsearchn function:
q = rand(5,4);
xi = dsearchn(X,tri, q)
The nearestNeighbor method and the dsearchn function allow the Euclidean distance
between the query point and its nearest-neighbor to be returned as an optional
argument. In the 4-D example, you can compute the distances, dnn, as follows:
[xi,dnn] = dsearchn(X,tri, q)
Point-Location Search
A point-location search is a triangulation search algorithm that locates the simplex
(triangle, tetrahedron, and so on) enclosing a query point. As in the case of the nearestneighbor search, there are a few approaches to performing a point-location search in
MATLAB, depending on the dimensionality of the problem:
• For 2-D and 3-D, use the class-based approach with the pointLocation method
provided by the triangulation class and inherited by the delaunayTriangulation class.
• For 4-D and higher, use the delaunayn function to construct the triangulation and
the complementary tsearchn function to perform the point-location search. Although
supporting 2-D and 3-D, these N-D functions are not as general and efficient as the
triangulation search methods.
This example shows how to use the delaunayTriangulation class to perform a point
location search in 2-D.
Begin with a set of 2-D points.
X = [3.5 8.2; 6.8 8.3; 1.3 6.5; 3.5 6.3; 5.8 6.2; ...
8.3 6.5; 1 4; 2.7 4.3; 5 4.5; 7 3.5; 8.7 4.2; ...
1.5 2.1; 4.1 1.1; 7 1.5; 8.5 2.75];
7-54
Spatial Searching
Create the triangulation and plot it showing the triangle ID labels at the incenters of the
triangles.
dt = delaunayTriangulation(X);
triplot(dt);
hold on
ic = incenter(dt);
numtri = size(dt,1);
trilabels = arrayfun(@(x) {sprintf('T%d', x)}, (1:numtri)');
Htl = text(ic(:,1), ic(:,2), trilabels, 'FontWeight', ...
'bold', 'HorizontalAlignment', 'center', 'Color', ...
'blue');
hold off
7-55
7
Computational Geometry
Now create some query points and add them to the plot. Then find the index of the
corresponding enclosing triangles using the pointLocation method.
q = [5.9344
2.2143
7.0948
7.6040
6.0724
6.5464
6.4588
4.3534
5.9329
3.0271
6.2363;
2.1910;
3.6615;
2.2770;
2.5828;
6.9407;
6.1690;
3.9026;
7.7013;
2.2067];
hold on;
plot(q(:,1),q(:,2),'*r');
vxlabels = arrayfun(@(n) {sprintf('q%d', n)}, (1:10)');
Hpl = text(q(:,1)+0.2, q(:,2)+0.2, vxlabels, 'FontWeight', ...
'bold', 'HorizontalAlignment','center', ...
'BackgroundColor', 'none');
hold off
ti = pointLocation(dt,q);
7-56
Spatial Searching
Performing a point-location search in 3-D is a direct extension of performing a pointlocation search in 2-D with delaunayTriangulation.
For 4-D and higher, use the delaunayn and tsearchn functions as illustrated in the
following example:
Create a random sample of points in 4-D and triangulate them using delaunayn:
X = 20*rand(50,4) -10;
tri = delaunayn(X);
Create some query points and find the index of the corresponding enclosing simplices
using the tsearchn function:
q = rand(5,4);
7-57
7
Computational Geometry
ti = tsearchn(X,tri,q)
The pointLocation method and the tsearchn function allow the corresponding
barycentric coordinates to be returned as an optional argument. In the 4-D example, you
can compute the barycentric coordinates as follows:
[ti,bc] = tsearchn(X,tri,q)
The barycentric coordinates are useful for performing linear interpolation. These
coordinates provide you with weights that you can use to scale the values at each vertex
of the enclosing simplex. See “Interpolating Scattered Data” on page 8-54 for further
details.
7-58
Voronoi Diagrams
Voronoi Diagrams
In this section...
“Plot 2-D Voronoi Diagram and Delaunay Triangulation” on page 7-59
“Computing the Voronoi Diagram” on page 7-63
The Voronoi diagram of a discrete set of points X decomposes the space around each point
X(i) into a region of influence R{i}. This decomposition has the property that an arbitrary
point P within the region R{i} is closer to point i than any other point. The region of
influence is called a Voronoi region and the collection of all the Voronoi regions is the
Voronoi diagram.
The Voronoi diagram is an N-D geometric construct, but most practical applications are
in 2-D and 3-D space. The properties of the Voronoi diagram are best understood using
an example.
Plot 2-D Voronoi Diagram and Delaunay Triangulation
This example shows the Voronoi diagram and the Delaunay triangulation on the same 2D plot.
Use the 2-D voronoi function to plot the voronoi diagram for a set of points.
figure()
X = [-1.5 3.2; 1.8 3.3; -3.7 1.5; -1.5 1.3; ...
0.8 1.2; 3.3 1.5; -4.0 -1.0;-2.3 -0.7; ...
0 -0.5; 2.0 -1.5; 3.7 -0.8; -3.5 -2.9; ...
-0.9 -3.9; 2.0 -3.5; 3.5 -2.25];
voronoi(X(:,1),X(:,2))
% Assign labels to the points.
nump = size(X,1);
plabels = arrayfun(@(n) {sprintf('X%d', n)}, (1:nump)');
hold on
Hpl = text(X(:,1), X(:,2), plabels, 'FontWeight', ...
'bold', 'HorizontalAlignment','center', ...
'BackgroundColor', 'none');
% Add a query point, P, at (0, -1.5).
P = [0 -1];
7-59
7
Computational Geometry
plot(P(1),P(2), '*r');
text(P(1), P(2), 'P', 'FontWeight', 'bold', ...
'HorizontalAlignment','center', ...
'BackgroundColor', 'none');
hold off
Observe that P is closer to X9 than to any other point in X, which is true for any point P
within the region that bounds X9.
The Voronoi diagram of a set of points X is closely related to the Delaunay triangulation
of X. To see this relationship, construct a Delaunay triangulation of the point set X and
superimpose the triangulation plot on the Voronoi diagram.
dt = delaunayTriangulation(X);
7-60
Voronoi Diagrams
hold on
triplot(dt,'-r');
hold off
From the plot you can see that the Voronoi region associated with the point X9 is defined
by the perpendicular bisectors of the Delaunay edges attached to X9. Also, the vertices
of the Voronoi edges are located at the circumcenters of the Delaunay triangles. You can
illustrate these associations by plotting the circumcenter of triangle {|X9|,|X4|,|X8|}.
To find the index of this triangle, query the triangulation. The triangle contains the
location (-1, 0).
tidx = pointLocation(dt,-1,0);
7-61
7
Computational Geometry
Now, find the circumcenter of this triangle and plot it in green.
cc = circumcenter(dt,tidx);
hold on
plot(cc(1),cc(2),'*g');
hold off
The Delaunay triangulation and Voronoi diagram are geometric duals of each other. You
can compute the Voronoi diagram from the Delaunay triangulation and vice versa.
Observe that the Voronoi regions associated with points on the convex hull are
unbounded (for example, the Voronoi region associated with X13). The edges in this
region "end" at infinity. The Voronoi edges that bisect Delaunay edges (X13, X12) and
7-62
Voronoi Diagrams
(X13, X14) extend to infinity. While the Voronoi diagram provides a nearest-neighbor
decomposition of the space around each point in the set, it does not directly support
nearest-neighbor queries. However, the geometric constructions used to compute the
Voronoi diagram are also used to perform nearest-neighbor searches.
Computing the Voronoi Diagram
This example shows how to compute a 2–D and 3–D Voronoi diagram.
MATLAB software provides functions to plot the Voronoi diagram in 2-D and to
compute the topology of the Voronoi diagram in N-D. In practice, Voronoi computation
is not practical in dimensions beyond 6-D for moderate to large data sets, due to the
exponential growth in required memory.
The voronoi plot function plots the Voronoi diagram for a set of points in 2-D space. In
MATLAB there are two ways to compute the topology of the Voronoi diagram of a point
set:
• Using the MATLAB function voronoin
• Using the the delaunayTriangulation method, voronoiDiagram.
The voronoin function supports the computation of the Voronoi topology for discrete
points in N-D (N ≥ 2). The voronoiDiagram method supports computation of the
Voronoi topology for discrete points 2-D or 3-D.
The voronoiDiagram method is recommended for 2-D or 3-D topology computations as
it is more robust and gives better performance for large data sets. This method supports
incremental insertion and removal of points and complementary queries, such as nearestneighbor point search.
The voronoin function and the voronoiDiagram method represent the topology of the
Voronoi diagram using a matrix format. See “Triangulation Matrix Format” on page 7-4
for further details on this data structure.
Given a set of points, X, obtain the topology of the Voronoi diagram as follows:
• Using the voronoin function
[V,R] = voronoin(X)
• Using the voronoiDiagram method
7-63
7
Computational Geometry
dt = delaunayTriangulation(X);
[V,R] = voronoiDiagram(dt)
V is a matrix representing the coordinates of the Voronoi vertices (the vertices are the
end points of the Voronoi edges). By convention the first vertex in V is the infinite vertex.
R is a vector cell array length size(X,1), representing the Voronoi region associated
with each point. Hence, the Voronoi region associated with the point X(i) is R{i}.
Define and plot the voronoi diagram for a set of points
X = [-1.5 3.2; 1.8 3.3; -3.7 1.5; -1.5 1.3; 0.8 1.2; ...
3.3 1.5; -4.0 -1.0; -2.3 -0.7; 0 -0.5; 2.0 -1.5; ...
3.7 -0.8; -3.5 -2.9; -0.9 -3.9; 2.0 -3.5; 3.5 -2.25];
[VX,VY] = voronoi(X(:,1),X(:,2));
h = plot(VX,VY,'-b',X(:,1),X(:,2),'.r');
xlim([-4,4])
ylim([-4,4])
% Assign labels to the points X.
nump = size(X,1);
plabels = arrayfun(@(n) {sprintf('X%d', n)}, (1:nump)');
hold on
Hpl = text(X(:,1), X(:,2)+0.2, plabels, 'color', 'r', ...
'FontWeight', 'bold', 'HorizontalAlignment',...
'center', 'BackgroundColor', 'none');
% Compute the Voronoi diagram.
dt = delaunayTriangulation(X);
[V,R] = voronoiDiagram(dt);
% Assign labels to the Voronoi vertices V.
% By convention the first vertex is at infinity.
numv = size(V,1);
vlabels = arrayfun(@(n) {sprintf('V%d', n)}, (2:numv)');
hold on
Hpl = text(V(2:end,1), V(2:end,2)+.2, vlabels, ...
'FontWeight', 'bold', 'HorizontalAlignment',...
'center', 'BackgroundColor', 'none');
hold off
7-64
Voronoi Diagrams
R{9} gives the indices of the Voronoi vertices associated with the point site X9.
R{9}
ans =
5
7
17
12
9
The indices of the Voronoi vertices are the indices with respect to the V array.
Similarly, R{4} gives the indices of the Voronoi vertices associated with the point site X4.
R{4}
7-65
7
Computational Geometry
ans =
5
9
11
8
6
In 3-D a Voronoi region is a convex polyhedron, the syntax for creating the Voronoi
diagram is similar. However the geometry of the Voronoi region is more complex. The
following example illustrates the creation of a 3-D Voronoi diagram and the plotting of a
single region.
Create a sample of 25 points in 3-D space and compute the topology of the Voronoi
diagram for this point set.
X = -3 + 6.*gallery('uniformdata',[25 3],0);
dt = delaunayTriangulation(X);
Compute the topology of the Voronoi diagram.
[V,R] = voronoiDiagram(dt);
Find the point closest to the origin and plot the Voronoi region associated with this point.
tid = nearestNeighbor(dt,0,0,0);
XR10 = V(R{tid},:);
K = convhull(XR10);
defaultFaceColor = [0.6875 0.8750 0.8984];
trisurf(K, XR10(:,1) ,XR10(:,2) ,XR10(:,3) , ...
'FaceColor', defaultFaceColor, 'FaceAlpha',0.8)
title('3-D Voronoi Region')
7-66
Voronoi Diagrams
More About
•
“Spatial Searching” on page 7-50
7-67
7
Computational Geometry
Types of Region Boundaries
In this section...
“Convex Hulls vs. Nonconvex Polygons” on page 7-68
“Alpha Shapes” on page 7-72
Convex Hulls vs. Nonconvex Polygons
The convex hull of a set of points in N-D space is the smallest convex region enclosing all
points in the set. If you think of a 2-D set of points as pegs in a peg board, the convex hull
of that set would be formed by taking an elastic band and using it to enclose all the pegs.
x = gallery('uniformdata',20,1,20);
y = gallery('uniformdata',20,1,30);
plot(x,y,'r.','MarkerSize',10)
hold on
k = convhull(x,y);
plot(x(k),y(k))
title('The Convex Hull of a Set of Points')
hold off
7-68
Types of Region Boundaries
A convex polygon is a polygon that does not have concave vertices, for example:
x = gallery('uniformdata',20,1,30);
y = gallery('uniformdata',20,1,40);
k = convhull(x,y);
plot(x(k),y(k))
title('Convex Polygon')
7-69
7
Computational Geometry
You can also create a boundary of a point set that is nonconvex. If you "vacuum pack"
the convex hull from above, you can enclose all of the points in a nonconvex polygon with
concave vertices:
k = boundary(x,y,0.9);
plot(x(k),y(k))
title('Nonconvex Polygon')
7-70
Types of Region Boundaries
The convex hull has numerous applications. You can compute the upper bound on the
area bounded by a discrete point set in the plane from the convex hull of the set. The
convex hull simplifies the representation of more complex polygons or polyhedra. For
instance, to determine whether two nonconvex bodies intersect, you could apply a series
of fast rejection steps to avoid the penalty of a full intersection analysis:
• Check if the axis-aligned bounding boxes around each body intersect.
• If the bounding boxes intersect, you can compute the convex hull of each body and
check intersection of the hulls.
If the convex hulls did not intersect, this would avoid the expense of a more
comprehensive intersection test.
7-71
7
Computational Geometry
While convex hulls and nonconvex polygons are convenient ways to represent relatively
simple boundaries, they are in fact specific instances of a more general geometric
construct called the alpha shape.
Alpha Shapes
The alpha shape of a set of points is a generalization of the convex hull and a subgraph of
the Delaunay triangulation. That is, the convex hull is just one type of alpha shape, and
the full family of alpha shapes can be derived from the Delaunay triangulation of a given
point set.
x = gallery('uniformdata',20,1,10);
y = gallery('uniformdata',20,1,20);
plot(x,y,'r.','MarkerSize',20)
hold on
shp = alphaShape(x,y,100);
plot(shp)
title('Convex Alpha Shape')
hold off
7-72
Types of Region Boundaries
Unlike the convex hull, alpha shapes have a parameter that controls the level of detail,
or how tightly the boundary fits around the point set. The parameter is called alpha
or the alpha radius. Varying the alpha radius from 0 to Inf produces a set of different
alpha shapes unique for that point set.
plot(x,y,'r.','MarkerSize',20)
hold on
shp = alphaShape(x,y,.5);
plot(shp)
title('Nonconvex Alpha Shape')
hold off
7-73
7
Computational Geometry
Varying the alpha radius can sometimes result in an alpha shape with multiple
regions, which might or might not contain holes. However, the alphaShape function in
MATLAB® always returns regularized alpha shapes, which prevents isolated or dangling
points, edges, or faces.
plot(x,y,'r.','MarkerSize',20)
hold on
shp = alphaShape(x,y);
plot(shp)
title('Alpha Shape with Multiple Regions')
hold off
7-74
Types of Region Boundaries
See Also
alphaShape | convhull
More About
•
“Using the delaunayTriangulation Class” on page 7-24
•
“Triangulation Matrix Format” on page 7-4
•
Using alphaShape Objects
7-75
7
Computational Geometry
Computing the Convex Hull
In this section...
“Computing the Convex Hull Using convhull and convhulln” on page 7-76
“Convex Hull Computation Using the delaunayTriangulation Class” on page 7-81
“Convex Hull Computation Using alphaShape” on page 7-84
MATLAB provides several ways to compute the convex hull:
• Using the MATLAB functions convhull and convhulln
• Using the convexHull method provided by the delaunayTriangulation class
• Using the alphaShape function with an alpha radius of Inf.
The convhull function supports the computation of convex hulls in 2-D and 3-D. The
convhulln function supports the computation of convex hulls in N-D (N ≥ 2). The
convhull function is recommended for 2-D or 3-D computations due to better robustness
and performance.
The delaunayTriangulation class supports 2-D or 3-D computation of the convex hull
from the Delaunay triangulation. This computation is not as efficient as the dedicated
convhull and convhulln functions. However, if you have a delaunayTriangulation
of a point set and require the convex hull, the convexHull method can compute the
convex hull more efficiently from the existing triangulation.
The alphaShape function also supports the 2-D or 3-D computation of the convex hull
by setting the alpha radius input parameter to Inf. Like delaunayTriangulation,
however, computing the convex hull using alphaShape is less efficient than using
convhull or convhulln directly. The exception is when you are working with a
previously created alpha shape object.
Computing the Convex Hull Using convhull and convhulln
The convhull and convhulln functions take a set of points and output the indices
of the points that lie on the boundary of the convex hull. The point index-based
representation of the convex hull supports plotting and convenient data access. The
following examples illustrate the computation and representation of the convex hull.
7-76
Computing the Convex Hull
The first example uses a 2-D point set from the seamount dataset as input to the
convhull function.
Load the data.
load seamount
Compute the convex hull of the point set.
K = convhull(x,y);
K represents the indices of the points arranged in a counter-clockwise cycle around the
convex hull.
Plot the data and its convex hull.
plot(x,y,'.','markersize',12)
xlabel('Longitude')
ylabel('Latitude')
hold on
plot(x(K),y(K),'r')
7-77
7
Computational Geometry
Add point labels to the points on the convex hull to observe the structure of K.
[K,A] = convhull(x,y);
convhull can compute the convex hull of both 2-D and 3-D point sets. You can reuse the
seamount dataset to illustrate the computation of the 3-D convex hull.
Include the seamount z-coordinate data elevations.
close(gcf)
K = convhull(x,y,z);
7-78
Computing the Convex Hull
In 3-D the boundary of the convex hull, K, is represented by a triangulation. This is a set
of triangular facets in matrix format that is indexed with respect to the point array. Each
row of the matrix K represents a triangle.
Since the boundary of the convex hull is represented as a triangulation, you can use the
triangulation plotting function trisurf.
trisurf(K,x,y,z,'Facecolor','cyan')
The volume bounded by the 3-D convex hull can optionally be returned by convhull, the
syntax is as follows.
[K,V] = convhull(x,y,z);
7-79
7
Computational Geometry
The convhull function also provides the option of simplifying the representation of
the convex hull by removing vertices that do not contribute to the area or volume. For
example, if boundary facets of the convex hull are collinear or coplanar, you can merge
them to give a more concise representation. The following example illustrates use of this
option.
[x,y,z] = meshgrid(-2:1:2,-2:1:2,-2:1:2);
x = x(:);
y = y(:);
z = z(:);
K1 = convhull(x,y,z);
subplot(1,2,1)
defaultFaceColor = [0.6875 0.8750 0.8984];
trisurf(K1,x,y,z,'Facecolor',defaultFaceColor)
axis equal
title(sprintf('Convex hull with simplify\nset to false'))
K2 = convhull(x,y,z,'simplify',true);
subplot(1,2,2)
trisurf(K2,x,y,z,'Facecolor',defaultFaceColor)
axis equal
title(sprintf('Convex hull with simplify\nset to true'))
7-80
Computing the Convex Hull
MATLAB provides the convhulln function to support the computation of convex hulls
and hypervolumes in higher dimensions. Though convhulln supports N-D, problems
in more than 10 dimensions present challenges due to the rapidly growing memory
requirements.
The convhull function is superior to convhulln in 2-D and 3-D as it is more robust and
gives better performance.
Convex Hull Computation Using the delaunayTriangulation Class
This example shows the relationship between a Delaunay triangulation of a set of points
in 2-D and the convex hull of that set of points.
7-81
7
Computational Geometry
The delaunayTriangulation class supports computation of Delaunay triangulations
in 2-D and 3-D space. This class also provides a convexHull method to derive the
convex hull from the triangulation.
Create a Delaunay triangulation of a set of points in 2-D.
X = [-1.5 3.2; 1.8 3.3; -3.7 1.5; -1.5 1.3; 0.8 1.2; ...
3.3 1.5; -4.0 -1.0; -2.3 -0.7; 0 -0.5; 2.0 -1.5; ...
3.7 -0.8; -3.5 -2.9; -0.9 -3.9; 2.0 -3.5; 3.5 -2.25];
dt = delaunayTriangulation(X);
Plot the triangulation and highlight the edges that are shared only by a single triangle
reveals the convex hull.
triplot(dt)
fe = freeBoundary(dt)';
hold on
plot(X(fe,1), X(fe,2), '-r', 'LineWidth',2)
hold off
7-82
Computing the Convex Hull
In 3-D, the facets of the triangulation that are shared only by one tetrahedron represent
the boundary of the convex hull.
The dedicated convhull function is generally more efficient than a computation based
on the convexHull method. However, the triangulation based approach is appropriate
if:
• You have a delaunayTriangulation of the point set already and the convex hull is
also required.
7-83
7
Computational Geometry
• You need to add or remove points from the set incrementally and need to recompute
the convex hull frequently after you have edited the points.
Convex Hull Computation Using alphaShape
This example shows how to compute the convex hull of a 2-D point set using the
alphaShape function.
alphaShape computes a regularized alpha shape from a set of 2-D or 3-D points. You
can specify the alpha radius, which determines how tightly or loosely the alpha shape
envelops the point set. When the alpha radius is set to Inf, the resulting alpha shape is
the convux hull of the point set.
Create a set of 2-D points.
X = [-1.5 3.2; 1.8 3.3; -3.7 1.5; -1.5 1.3; 0.8 1.2; ...
3.3 1.5; -4.0 -1.0; -2.3 -0.7; 0 -0.5; 2.0 -1.5; ...
3.7 -0.8; -3.5 -2.9; -0.9 -3.9; 2.0 -3.5; 3.5 -2.25];
Compute and plot the convex hull of the point set using an alpha shape with alpha radius
equal to Inf.
shp = alphaShape(X,Inf);
plot(shp)
7-84
Computing the Convex Hull
7-85
8
Interpolation
• “Gridded and Scattered Sample Data” on page 8-2
• “Interpolating Gridded Data” on page 8-4
• “Interpolation of Multiple 1-D Value Sets” on page 8-50
• “Interpolation of 2-D Selections in 3-D Grids” on page 8-52
• “Interpolating Scattered Data” on page 8-54
• “Interpolation Using a Specific Delaunay Triangulation” on page 8-83
• “Extrapolating Scattered Data” on page 8-86
8
Interpolation
Gridded and Scattered Sample Data
Interpolation is a method for estimating the value at a query location that lies within
the domain of a set of sample data points. A sample data set defined by locations X and
corresponding values V can be interpolated to produce a function of the form V = F(X).
This function can then be used to evaluate a query point Xq, to give Vq = F(Xq). This is a
single-valued function; for any query Xq within the domain of X it will produce a unique
value Vq. The sample data is assumed to respect this property in order to produce a
satisfactory interpolation. One other interesting characteristic is that the interpolating
function passes through the data points. This is an important distinction between
interpolation and curve/surface fitting. In fitting, the function does not necessarily pass
through the sample data points.
The computation of the value Vq is generally based on the data points in the
neighborhood of the query point Xq. There are numerous approaches to performing
interpolation. In MATLAB interpolation is classified into two categories depending on
the structure of the sample data. The sample data may be ordered in a axis-aligned grid
or they may be scattered. In the case of a gridded distribution of sample points, you can
leverage the organized structure of the data to efficiently find the sample points in the
neighborhood of the query. Interpolation of scattered data on the other hand requires a
triangulation of the data points, and this introduces an additional level of computation.
The two approaches to interpolation are covered in the following sections:
• The “Interpolating Gridded Data” on page 8-4 section covers 1-D interpolation,
and the N-D (N ≥ 2) interpolation of sample data in axis-aligned grid format:
• The “Interpolating Scattered Data” on page 8-54 section covers the N-D (N ≥ 2)
interpolation of scattered data:
8-2
Gridded and Scattered Sample Data
8-3
8
Interpolation
Interpolating Gridded Data
In this section...
“Gridded Data Representation” on page 8-4
“Grid-Based Interpolation” on page 8-18
“Interpolation with the interp Family of Functions” on page 8-25
“Interpolation with the griddedInterpolant Class” on page 8-37
Gridded Data Representation
• “Grid Representation” on page 8-4
• “Types of Grid Representations” on page 8-13
• “Grid Approximation Techniques” on page 8-15
Grid Representation
This example shows how to create a 2-D grid using meshgrid and ndgrid.
In MATLAB®, gridded data means data ordered in a grid. You can understand ordered
data by thinking about how MATLAB stores data in matrices.
Define some data.
A = gallery('uniformdata',[3 5],0)
A =
0.9501
0.2311
0.6068
0.4860
0.8913
0.7621
0.4565
0.0185
0.8214
0.4447
0.6154
0.7919
0.9218
0.7382
0.1763
MATLAB stores the data in a matrix. You can think of A as a set of places for the
elements that are ordered by the indices of the matrix. The linear indices of A are:
8-4
Interpolating Gridded Data
Any element in the matrix can be retrieved by indexing, that is, by asking for the
element at that place in the matrix. The ith element in A is retrieved by A(i).
Retrieve the 7th element in A.
A(7)
ans =
0.4565
For an m-by-n matrix, you can find the column elements adjacent to the ith element by
offsetting i by 1. To find the row elements adjacent to the ith element, offset i by m.
Retrieve the column elements adjacent to A(7).
A(6),A(8)
ans =
0.7621
ans =
0.0185
MATLAB uses a similar idea for creating data grids. A grid is not just a set of points
that meet certain geometric properties. Rather, a gridded data set relies on an ordered
relationship among the points in the grid. The adjacency information readily available
in the grid structure is very useful for many applications and particularly grid-based
interpolation.
MATLAB provides two functions for creating grids:
8-5
8
Interpolation
• meshgrid creates 2-D and 3-D grids that are Cartesian axis aligned. To create a 2-D
grid, the syntax is [X,Y] = meshgrid(xgv, ygv) where xgv is a vector of length ,
and ygv is a vector of length n. meshgrid replicates xgv to form the n-by-|m| matrix
X, and it replicates ygv to form another n-by-|m| matrix Y. X and Y represent the
coordinates of the grid points. The rows of X are aligned with the horizontal X-axis,
and the columns of Y are aligned with the negative Y-axis.
• ndgrid creates N-D grids that are array space aligned. In array space the axes
are row, column, page, etc. The calling syntax is [X1, X2, X3,...,Xn] =
ndgrid(x1gv, x2gv, x3gv,...,xngv) where x1gv,x2gv,x3gv,...,xngv
are vectors that span the grid in each dimension. X1,X2,X3,...,Xn are output
arrays that can be used for evaluating functions of multiple variables and for
multidimensional interpolation.
Use meshgrid to create a 2-D axis aligned grid from two vectors, xgv and ygv.
xgv = [1 2 3];
ygv = [1 2 3 4 5];
[X,Y] = meshgrid(xgv, ygv)
X =
1
1
1
1
1
2
2
2
2
2
3
3
3
3
3
1
2
3
4
5
1
2
3
4
5
1
2
3
4
5
Y =
Now use ndgrid to create a 2-D space aligned grid from the same two vectors, xgv and
ygv.
[X1,X2] = ndgrid(xgv,ygv)
8-6
Interpolating Gridded Data
X1 =
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
1
1
2
2
2
3
3
3
4
4
4
5
5
5
X2 =
Notice that ndgrid's X1 is the transpose of meshgrid's X. The same is true for X2 and Y.
For a given set of inputs, the meshgrid and ndgrid functions will produce grids with
exactly the same coordinates. The only difference between their outputs is the format of
the coordinate arrays. Plot both outputs and see that they are the same.
figure()
[X1_ndgrid,X2_ndgrid] = ndgrid(1:3,1:5);
Z = zeros(3,5);
mesh(X1_ndgrid,X2_ndgrid,Z,'EdgeColor','black')
axis equal;
% Set the axis labeling and title
h1 = gca;
h1.XTick = [1 2 3];
h1.YTick = [1 2 3 4 5];
xlabel('ndgrid Output')
8-7
8
Interpolation
figure()
[X_meshgrid,Y_meshgrid] = meshgrid(1:3, 1:5);
mesh(X_meshgrid,Y_meshgrid,Z','EdgeColor','black')
axis equal;
% Set the axis labeling and title
h2 = gca;
h2.XTick = [1 2 3];
h2.YTick = [1 2 3 4 5];
xlabel('meshgrid Output')
8-8
Interpolating Gridded Data
Depending on how you intend to use your grid, you may prefer one format or the other.
Some functions in MATLAB might require your data to have a meshgrid format while
others might require an ndgrid format.
Converting Between Grid Formats
To convert a 2-D grid output from meshgrid to the ndgrid format, transpose the
coordinate matrices:
[X_meshgrid,Y_meshgrid] = meshgrid(1:3, 1:5);
[X1_ndgrid,X2_ndgrid] = ndgrid(1:3,1:5);
isequal(X_meshgrid',X1_ndgrid)
ans =
8-9
8
Interpolation
1
isequal(Y_meshgrid',X2_ndgrid)
ans =
1
You can also use the permute function.
isequal(permute(X_meshgrid,[2 1]),X1_ndgrid)
ans =
1
To convert a 3-D meshgrid to ndgrid, transpose each page of the coordinate array. For
a given array my_array, permute(my_array, [2 1 3]) interchanges the rows and
columns, and the net effect is the transposition of every page:
[X_meshgrid,Y_meshgrid,Z_meshgrid] = meshgrid(1:3, 1:5, [1 2]);
[X1_ndgrid,X2_ndgrid,X3_ndgrid] = ndgrid(1:3,1:5, [1 2]);
isequal(permute(X_meshgrid,[2 1 3]),X1_ndgrid)
ans =
1
isequal(permute(Y_meshgrid,[2 1 3]),X2_ndgrid)
ans =
1
isequal(permute(Z_meshgrid,[2 1 3]),X3_ndgrid)
ans =
1
Grid Vectors
The inputs that you pass to the grid functions are called grid vectors. The grid vectors
implicitly define the grid. Consider two vectors, x1gv = (1:3) and x2gv = (1:5).
You can think of these vectors as a set of coordinates in the x1 direction and a set of
coordinates in the x2 direction, like so:
8-10
Interpolating Gridded Data
Each arrow points to a location. You can use these two vectors to define a set of grid
points, where one set of coordinates is given by x1gv and the other set of coordinates is
given by x2gv. When the grid vectors are replicated they form two coordinate arrays that
make up the full grid:
Monotonic and Nonmonotonic Grids
Your input grid vectors may be monotonic or nonmonotonic. Monotonic vectors
contain values that either increase in that dimension or decrease in that dimension.
Conversely, nonmonotonic vectors contain values that fluctuate. If the input grid vector
is nonmonotonic, such as [2 4 6 8 3 1], ndgrid outputs the following:
8-11
8
Interpolation
[X1,X2] = ndgrid([2 4 6 3 1])
X1 =
2
2
2
2
2
4
4
4
4
4
6
6
6
6
6
3
3
3
3
3
1
1
1
1
1
X2 =
2
2
2
2
2
4
4
4
4
4
6
6
6
6
6
3
3
3
3
3
1
1
1
1
1
Your grid vectors should be monotonic if you intend to pass the grid to other MATLAB
functions.
Uniform and Nonuniform Grids
A uniform grid is one in which all neighboring points in a given dimension have equal
spacing. For example, [X1, X2] = ndgrid([1 3 5 9],[11 13 15]) is a uniform
with a spacing of 2 units in each dimension.
It is not necessary for the spacing in a uniform grid to be equal in all dimensions. For
example, [X1, X2] = ndgrid([1 2 3 4],[11 13 15]) is considered uniform even
though the spacing in X1 and X2 are different.
A grid whose spacing varies within any dimension is a nonuniform grid. For example,
[X1, X2] = ndgrid([1 5 6 9],[11 13 15]) creates a nonuniform grid because
the spacing varies along the first dimension.
8-12
Interpolating Gridded Data
Uniform
Uniform
Nonuniform
Types of Grid Representations
MATLAB allows you to represent a grid in one of three representations: full grid,
compact grid, or default grid. The compact grid and default grid are used primarily for
convenience and improved efficiency.
Full Grid
A full grid is one in which the points are explicitly defined. The outputs of ndgrid and
meshgrid define a full grid.
Compact Grid
The explicit definition of every point in a grid is expensive in terms of memory. The
compact grid representation is a way to dispense with the memory overhead of a full
grid. The compact grid representation stores just the grid vectors instead of the full
grid. (For information on how the griddedInterpolant class uses the compact grid
representation, see “Interpolation with the griddedInterpolant Class” on page 8-37.)
Default Grid
For many cases, when you are analyzing data, you care about both the distances between
points in the grid and their value. For example, a data set might represent rainfall at
specific points in a geographic area. In this case, you would care about the value at each
grid point and the distance between a point and its neighbor. In other cases, you might
care only about the value for a given point and not about the relative distances. For
example, you could be working with input data from an MRI scan where the distance
between the points is completely uniform. In this case, you would care about the values
of the points, but you can be certain of a completely uniform grid. In this case, the default
grid representation is useful. The default grid representation stores the value at a grid
point explicitly and creates grid point coordinates implicitly.
This example shows how you can use the default grid instead of the full grid to produce a
plot.
Create a grid and a function that you want to plot.
[X,Y] = meshgrid(11:15,11:16);
Z = X.^2 + Y.^2;
Use the full grid that you created with meshgrid by using X and Y.
8-13
8
Interpolation
figure()
surf(X,Y,Z)
title('Full Grid')
In contrast, have MATLAB create a default grid instead of using the full grid.
figure()
surf(Z)
title('Default Grid')
8-14
Interpolating Gridded Data
Notice the difference in the scaling of the axes. When you plot the full grid the X- and Yaxis have ranges of 11 to 15 and 10 to 16 respectively. When you plot the default grid the
X- and Y-axis have ranges of 1 to m and 1 to n where Z is m-by-|n|.
Grid Approximation Techniques
In some cases, you may need to approximate a grid for your data. An approximate grid
can be idealized by a standard MATLAB grid by choosing an appropriate set of grid
vectors. For example, a grid can have points that lie along curved lines. A data set like
this might occur if your data is longitude and latitude based:
8-15
8
Interpolation
In this case, although the input data cannot be gridded directly, you can approximate
straight grid lines at appropriate intervals:
You can also use the default grid.
Degenerate Grid
A degenerate grid is a special case of grid where one or more dimensions of the grid are
singletons. A singleton dimension can be internal, as in 7:7 in this example:
[X1,X2,X3] = ndgrid(1:2:10,7:7,1:3:15);
or a singleton dimension can be trailing:
[X1,X2,X3] = ndgrid(1:2:10,1:3:15,7:7);
You can create a degenerate grid if you are trying to take a slice of a larger data set. For
example, you may want to analyze just a slice of a 3-D MRI scan. In this case, you will
8-16
Interpolating Gridded Data
need a slice of data from a multidimensional grid, such as the dotted slice in the following
figure:
If you use indexing to extract the desired data, the resultant grid is degenerate in the X3
dimension:
[X1,X2,X3] = ndgrid(1:3);
X1_slice = X1(:,:,2)
X1_slice =
1
1
1
2
2
2
3
3
3
X2_slice = X2(:,:,2)
X2_slice =
1
2
3
1
2
3
1
2
3
X3_slice = X3(:,:,2)
X3_slice =
2
2
2
2
2
2
2
2
2
The concept of data gridding is very important for understanding the ways in which
MATLAB does grid-based interpolation.
8-17
8
Interpolation
Grid-Based Interpolation
• “Benefits of Using Grid-Based Interpolation” on page 8-18
• “Interpolation versus Fit” on page 8-21
• “Interpolation Methods” on page 8-21
In grid-based interpolation, the data to be interpolated is represented by an ordered
grid. For example, an arrangement of temperature measurements over a rectangular
flat surface at 1-cm intervals from top-to-bottom vertically and left-to-right horizontally
is considered 2-D gridded data. Grid-based interpolation provides an efficient way to
approximate the temperature at any location between the grid points.
Benefits of Using Grid-Based Interpolation
Grid-based interpolation provides significant savings in computational overhead because
the gridded structure allows MATLAB to locate a query point and its adjacent neighbors
very quickly. To understand how this works, consider the following points on a 1-D grid:
The lines connecting adjacent points represent the cells of the grid. The first cell occurs
between x = 1 and x = 3, the second occurs between x = 3 and x = 5, and so on.
Each number represents a coordinate in the grid. If you want to query the grid at x = 6,
you would have to use interpolation because 6 is not explicitly defined in the grid. Since
this grid has a uniform spacing of 2, you can narrow down the location of the query point
with a single integer division (6/2 = 3). This tells you that the point is in the 3rd cell
of the grid. Locating a cell in a 2-D grid involves performing this operation once in each
dimension. This operation is called a fast lookup, and MATLAB uses this technique only
when the data is arranged in a uniform grid.
This fast lookup efficiently locates the cell containing a query point Xq. A binary search
proceeds as follows:
8-18
1
Locate the center grid point.
2
Compare Xq to the point at the center of the grid.
Interpolating Gridded Data
3
4
If Xq is less than the point found at the center, eliminate all of the grid points
greater than central point from the search. Similarly, if Xq is greater than the one
found at the center, we eliminate all of the grid points that are less than the central
point. Note that by doing this, we have reduced the number of points we must search
by half.
Find the center of the remaining grid points and repeat from Step 2 until you are left
with one grid point on either side of your query. These two points mark the boundary
of the cell that contains Xq.
To illustrate the power of binary searches, consider the following example. Before the
advent of electronic credit card authorizations, the only protection merchants had
against fraudulent credit card purchases was to compare the account number on each
customer's credit card against a list of "bad" account numbers. These lists were bound
booklets with tens of thousands of card numbers arranged in ascending order. How
many comparisons would be required to search through a list of 10,000 account numbers
for one sale? It turns out that for any list of n ordered items, the maximum number of
8-19
8
Interpolation
comparisons will be no more than the number of times you can divide the list in half,
or log2(n). Therefore, the credit card search will take no more than log2(10e3) or
about 13 comparisons. That's a pretty impressive if you consider how many comparisons
it would take to perform a sequential search.
By contrast, consider a problem with a scattered data set.
x = rand(20,1);
y = rand(20,1);
scatter(x,y)
To find the points in close proximity to a query point would require many more
operations. If your data can be approximated as a grid, grid-based interpolation will
provide substantial savings in computation and memory usage.
8-20
Interpolating Gridded Data
If your data is scattered, you can use the tools detailed in “Interpolating Scattered Data”
on page 8-54.
Interpolation versus Fit
The interpolation methods available in MATLAB create interpolating functions that
pass though the sample data points. If you were to query the interpolation function at
a sample location, you would get back the value at that sample data point. By contrast,
curve and surface fitting algorithms do not necessarily pass through the sample data
points.
Interpolation Methods
Grid-based interpolation offers several different methods for interpolation. When
choosing an interpolation method, keep in mind that some require more memory or
longer computation time than others. However, you may need to trade off these resources
to achieve the desired smoothness in the result. The following table provides an overview
of the benefits, trade-offs, and requirements for each method.
Method
Description
Nearest Neighbor
The interpolated
Discontinuous
value at a query
point is the value
at the nearest
sample grid point.
• Modest
memory
requirements
The interpolated
Discontinuous
value at a query
point is the value
at the next sample
grid point.
Same memory
requirements
and computation
time as nearest
neighbor.
• Available
for 1D
interpolation
only.
Previous Neighbor The interpolated
Discontinuous
value at a query
point is the value
at the previous
sample grid point.
Same memory
requirements
and computation
time as nearest
neighbor.
• Available
for 1D
interpolation
only.
Next Neighbor
Continuity
Memory Usage and Requirements
Performance
• Requires 2 grid
points in each
dimension.
• Fastest
computation
time
• Requires at
least 2 grid
points.
8-21
8
Interpolation
Method
Description
Continuity
Memory Usage and Requirements
Performance
• Requires at
least 2 grid
points.
Linear
The interpolated
value at a
query point is
based on linear
interpolation
of the values
at neighboring
grid points in
each respective
dimension.
C0
• Requires
more memory
than nearest
neighbor.
Pchip
Cubic
8-22
• Requires at
least 2 grid
points in each
dimension.
• Requires more
computation
time than
nearest
neighbor.
The interpolated
C1
value at a query
point is based on a
shape-preserving
piece-wise cubic
interpolation
of the values at
neighboring grid
points.
• Requires more
memory than
linear.
The interpolated
C1
value at a query
point is based on
cubic interpolation
of the values
at neighboring
grid points in
each respective
dimension.
• Requires more
memory than
linear.
• Requires more
computation
time than
linear.
• Requires more
computation
time than
linear.
• Available
for 1D
interpolation
only.
• Requires at
least 4 grid
points.
• Grid must
have uniform
spacing,
though the
spacing in each
dimension does
not have to be
the same.
• Requires
at least 4
points in each
dimension.
Interpolating Gridded Data
Method
Description
Continuity
Spline
The interpolated
C2
value at a query
point is based on a
cubic interpolation
of the values
at neighboring
grid points in
each respective
dimension.
Memory Usage and Requirements
Performance
• Requires more
memory than
cubic.
• Requires 4
points in each
dimension.
• Requires more
computation
time than
cubic.
8-23
8
Interpolation
Comparison of Four Interpolation Methods
MATLAB provides support for grid-based interpolation in several ways:
• The interp family of functions: interp1, interp2, interp3, and interpn.
• The griddedInterpolant class.
Both the interp family of functions and griddedInterpolant support N-D
grid-based interpolation. However, there are memory and performance benefits to
using the griddedInterpolant class over the interp functions. Moreover, the
griddedInterpolant class provides a single consistent interface for working with
gridded data in any number of dimensions.
8-24
Interpolating Gridded Data
Interpolation with the interp Family of Functions
• “The interp1 Function” on page 8-25
• “1-D Extrapolation With interp1” on page 8-26
• “The interp2 Function” on page 8-29
• “The interp3 Function” on page 8-32
• “The interpn Function” on page 8-32
The interp1 Function
This example shows how the interp1 function can be used to interpolate a set of sample
values using the 'pchip' method.
The function interp1 performs one-dimensional interpolation. Its most general form is:
Vq = interp1(X,V,Xq,method)
where X is a vector of coordinates and V is a vector containing the values at those
coordinates. Xq is a vector containing the query points at which to interpolate, and
method is an optional string specifying any of four interpolation methods: 'nearest',
'linear', 'pchip', or 'spline'.
Create a set of 1-D grid points X and corresponding sample values V.
X = [1 2 3 4 5];
V = [12 16 31 10 6];
Interpolate over finer intervals with 0.1 spacing.
Xq = (1:0.1:5);
Vq = interp1(X,V,Xq,'pchip');
Plot the samples and interpolated values.
plot(X,V,'o');
hold on
plot(Xq,Vq,'-');
legend('samples','pchip');
hold off
8-25
8
Interpolation
1-D Extrapolation With interp1
This example shows how to use the 'extrap' option to interpolate beyond the domain of
your sample points.
Define the sample points and values.
X = [1 2 3 4 5];
V = [12 16 31 10 6];
Specify the query points, Xq, that extend beyond the domain of X.
Xq = (0:0.1:6);
Vq = interp1(X,V,Xq,'pchip','extrap');
8-26
Interpolating Gridded Data
Plot the results.
figure
plot(X,V,'o');
hold on
plot(Xq,Vq,'-');
legend('samples','pchip');
hold off
In an alternative approach, you can introduce additional points to gain more control over
the behavior in the extrapolated regions. For example, you can constrain the curve to
remain flat in the extrapolated region by extending the domain with repeated values.
X = [0 1 2 3 4 5 6];
8-27
8
Interpolation
V = [12 12 16 31 10 6 6];
Specify the query points, Xq, that extend further beyond the domain of X.
Xq = (-1:0.1:7);
Interpolate using 'pchip'. You can omit the 'extrap' option because it is the default
with the 'pchip' and 'spline' methods.
Vq = interp1(X,V,Xq,'pchip');
Plot the results.
figure
plot(X,V,'o');
hold on
plot(Xq,Vq,'-');
legend('samples','pchip');
hold off
8-28
Interpolating Gridded Data
The interp2 Function
This example shows how the interp2 function can be used to interpolate the coarsely
sampled peaks function over a finer grid.
The interp2 and interp3 functions perform two and three-dimensional interpolation
respectively, and they interpolate grids in the meshgrid format. The calling syntax for
interp2 has the general form:
Vq = interp2(X,Y,V,Xq,Yq,method)
where X and Y are arrays of coordinates that define a grid in meshgrid format, and V
is an array containing the values at the grid points. Xq and Yq are arrays containing
the coordinates of the query points at which to interpolate. method is an optional string
8-29
8
Interpolation
specifying any of four interpolation methods: 'nearest', 'linear', 'cubic', or
'spline'.
The grid points that comprise X and Y must be monotonically increasing and should
conform to the meshgrid format.
Create a coarse grid and corresponding sample values.
[X,Y] = meshgrid(-3:1:3);
V = peaks(X,Y);
Plot the sample values.
surf(X,Y,V)
title('Sample Grid');
8-30
Interpolating Gridded Data
Generate a finer grid for interpolation.
[Xq,Yq] = meshgrid(-3:0.25:3);
Use interp2 to interpolate at the query points.
Vq = interp2(X,Y,V,Xq,Yq,'linear');
Plot the results.
surf(Xq,Yq,Vq);
title('Refined Grid');
8-31
8
Interpolation
The interp3 Function
This example shows how to use interp3 to interpolate a 3-D function at a single query
point and compare it to the value generated by an analytic expression.
interp3 works in the same way as interp2 except that it takes two additional
arguments: one for the third dimension in the sample grid and the other for the third
dimension in the query points,
Vq = interp3(X,Y,Z,V,Xq,Yq,Zq,method).
As is the case with interp2, the grid points you supply to interp3 must be
monotonically increasing and should conform to the meshgrid format.
Define a function that generates values for X, Y, and Z input.
generatedvalues = @(X,Y,Z)(X.^2 + Y.^3 + Z.^4);
Create the sample data.
[X,Y,Z] = meshgrid((-5:.25:5));
V = generatedvalues(X,Y,Z);
Interpolate at a specific query point.
Vq = interp3(X,Y,Z,V,2.35,1.76,0.23,'cubic')
Vq =
10.9765
Compare Vq to the value generated by the analytic expression.
V_actual = generatedvalues(2.35,1.76,0.23)
V_actual =
10.9771
The interpn Function
This example shows how the interpn function can be used to interpolate a coarsely
sampled function over a finer grid using the 'cubic' method.
8-32
Interpolating Gridded Data
The function interpn performs n-dimensional interpolation on grids that are in the
ndgrid format. Its most general form is:
Vq = interpn(X1,X2,X3,...Xn,V,Y1,Y2,Y3,...,Yn,method)
where X1,X2,X3,...,Xn are arrays of coordinates that define a grid in ndgrid format,
and V is an array containing the values at the grid points. Y1,Y2,Y3,...,Yn are arrays
containing the coordinates of the query points at which to interpolate. method is an
optional string specifying any of four interpolation methods: 'nearest', 'linear',
'cubic', or 'spline'.
The grid points that comprise X1,X2,X3,...Xn must be monotonically increasing and
should conform to the ndgrid format.
Create a set of grid points and corresponding sample values.
[X1,X2] = ndgrid((-5:1:5));
R = sqrt(X1.^2 + X2.^2)+ eps;
V = sin(R)./(R);
Plot the sample values.
mesh(X1,X2,V)
title('Sample Grid');
8-33
8
Interpolation
Create a finer grid for interpolation.
[Y1,Y2] = ndgrid((-5:.5:5));
Interpolate over the finer grid and plot the results.
Vq = interpn(X1,X2,V,Y1,Y2,'cubic');
mesh(Y1,Y2,Vq)
title('Refined Grid');
8-34
Interpolating Gridded Data
interpn has an alternate syntax: Vq = interpn(V,ntimes,method) that allows you
to interpolate over a grid that is an integer number of times finer than the sample grid.
In the previous code, Y1 and Y2 queried the interpolant over a grid that contained one
extra point between each of the samples. The following code demonstrates how you can
achieve the same result with ntimes=1.
Interpolate over a finer grid using ntimes=1.
Vq = interpn(V,1,'cubic');
Plot the result.
mesh(Vq)
8-35
8
Interpolation
title('Refined Grid with NTIMES');
Notice that the plot is scaled differently than in the previous example. This is because we
called mesh and passed the values only. The mesh function used a default grid based on
the dimensions of Vq. The output values are the same in both cases.
You can also supply nonunifom grid of query points. This can be useful if you are
interested in querying the interpolant at a higher resolution in one region of the grid.
The following code shows how this can be done.
Interpolate over a biased grid.
[Y1, Y2] = ndgrid([-5 -4 -3 -2.5 -2 -1.5 -1.25 -1 -0.75 -0.5 -0.20 0]);
8-36
Interpolating Gridded Data
Vq = interpn(X1,X2,V,Y1,Y2,'cubic');
Plot the result.
mesh(Y1,Y2,Vq);
title('Biased Grid');
Interpolation with the griddedInterpolant Class
Like the interpn function, the griddedInterpolant class provides a single interface for
grid-based interpolation in n dimensions. However griddedInterpolant offers the
following additional benefits:
8-37
8
Interpolation
• It offers substantial performance improvements for repeated queries to the
interpolant.
• It offers additional performance improvements and savings in memory consumption
because it stores the sample points as a compact grid.
griddedInterpolant accepts sample data that conforms to the ndgrid format. If you
wish to create a griddedInterpolant with meshgrid data, you will need to convert
the data to the ndgrid format. See “Converting meshgrid Data to the ndgrid Format” on
page 8-39 for a demonstration of how to convert 2-D and 3-D meshgrids.
The griddedInterpolant class supports the five interpolation methods that are
also supported by interpn: nearest, linear, pchip, cubic, and spline. However
griddedInterpolant offers greater performance with less overhead.
Constructing the Interpolant
An interpolant is a function that preforms interpolation. You create the interpolant by
calling the griddedInterpolant constructor and passing the sample data: the grid and
corresponding sample values. You can also specify the interpolation method if you wish to
override the default “linear” method. The calling syntax has the following forms:
• For 1-D interpolation, you can pass x, a set of points, and v, a vector of the same
length containing the corresponding values.
F = griddedInterpolant(x,v)
• For higher dimensions, you can supply a full grid. X1,X2,...,Xn specify the grid as
a set of n n-D arrays. These arrays conform to the ndgrid format and are the same
size as the sample array V.
F = griddedInterpolant(X1,X2,...,Xn,V)
• If you know that the distances between adjacent sample points are uniform, you can
let griddedInterpolant create a default grid by passing only the sample points V.
F = griddedInterpolant(V)
• You can also specify the coordinates of your sample data as a compact grid. The
compact grid is represented by a set of vectors. These vectors are then packaged into a
cell array by enclosing them in curly braces; for example,{x1g,x2g,...,xng} where
vectors x1g,x2g,...,xng define the grid coordinates in each dimension.
F = griddedInterpolant({x1g,x2g,...,xng},V)
8-38
Interpolating Gridded Data
• You can also specify the interpolation method as a final input argument with any of
the calling syntaxes. This example specifies nearest neighbor interpolation.
F = griddedInterpolant({x1g,x2g,x3g},V,'nearest')
Querying the Interpolant
The griddedInterpolant, F, is evaluated in the same way as you would call a function.
Your query points may be scattered or gridded, and you can pass them to F in any of the
following ways:
• You can specify an m-by-n matrix Xq, which contains m scattered points in n
dimensions. The interpolated values Vq are returned as an m-by-1 vector.
Vq = F(Xq)
• You can also specify the query points as a series of n column vectors
x1q,x2q,...,xnq of length m. These vectors represent m points in n dimensions.
The interpolated values Vq are returned as an m-by-1 vector.
Vq = F(x1q,x2q,...,xnq)
• You can specify the query points as a series of n n-dimensional arrays representing
a full grid. The arrays X1q,X2q,...,Xnq are all the same size and conform to the
ndgrid format. The interpolated values Vq will also be the same size.
Vq = F(X1q,X2q,...,Xnq)
• You can also specify the query points as a compact grid. x1gq,x2gq,...,xngq are
vectors that define the grid points in each dimension.
Vq = F({x1gq,x2gq,...,xngq})
For example, in 2-D:
Vq = F({(0:0.2:10),(-5:0.5:5)});
Converting meshgrid Data to the ndgrid Format
The griddedInterpolant class accepts ndgrid formatted sample data. If you want
to create a griddedInterpolant with meshgrid data, you should convert it to the
ndgrid format first.
The following example outlines the steps for converting 2-D meshgrid data to the
ndgrid format. We begin by creating the meshgrid and corresponding sample values:
8-39
8
Interpolation
[X,Y] = meshgrid(-2:.1:2,-1:.1:1);
V=0.75*Y.^3-3*Y-2*X.^2;
To convert X, Y, and V to ndgrid format, follow these steps:
1
Transpose each array in the grid as well as the sample data.
X=X';
Y=Y';
V=V';
2
Now create the interpolant.
F = griddedInterpolant(X,Y,V);
To convert a 3-D meshgrid, we use the permute function. Again, we’ll start by creating
the meshgrid and corresponding sample values:
[X,Y,Z] = meshgrid(-5:5,-3:3,-10:10);
V = X.^3 + Y.^2 + Z;
To convert X, Y, Z, and V to ndgrid format, follow these steps:
1
Use the permute function to interchange the rows and columns of each array. The
net effect will be the transpose of every page.
P
X
Y
Z
V
2
=
=
=
=
=
[2 1 3];
permute(X,P);
permute(Y,P);
permute(Z,P);
permute(V,P);
Now create the interpolant.
F = griddedInterpolant(X,Y,Z,V);
griddedInterpolant in One Dimension
This example shows how to create and plot a 1-D interpolant using
griddedInterpolant with a cubic interpolation method.
Create a coarse grid and sample values.
X = [1 2 3 4 5];
V = [12 6 15 9 6];
8-40
Interpolating Gridded Data
Construct the griddedInterpolant using a cubic interpolation method.
F = griddedInterpolant(X,V,'cubic')
F =
griddedInterpolant with properties:
GridVectors:
Values:
Method:
ExtrapolationMethod:
{[1 2 3 4 5]}
[12 6 15 9 6]
'cubic'
'cubic'
The GridVectors property contains the compact grid specifying the coordinates of the
sample values V. The Method property is a string specifying the interpolation method.
Notice that we specified 'cubic' when we created F. If you omit the Method argument,
the default interpolation method, linear, will be assigned to F.
You can access any of the properties of F in the same way you would access the fields in a
struct.
F.GridVectors;
F.Values;
F.Method;
% Displays the grid vectors as a cell array
% Displays the sample values
% Displays the interpolation method
Interpolate over finer intervals with 0.1 spacing.
Xq = (1:0.1:5);
Vq = F(Xq);
Plot the result.
plot(X,V,'o');
hold on
plot(Xq,Vq,'-');
legend('samples','Cubic Interpolation');
8-41
8
Interpolation
griddedInterpolant in Two Dimensions
This example shows how to create and plot a 2-D interpolant using
griddedInterpolant.
In two dimensions and higher, you can specify the sample coordinates as an ndgrid, a
compact grid, or a default grid. In this example, we'll supply an ndgrid.
Create a coarse grid and sample values.
[X,Y] = ndgrid(-1:.3:1,-2:.3:2);
V = 0.75*Y.^3 - 3*Y - 2*X.^2;
Construct the griddedInterpolant.
8-42
Interpolating Gridded Data
F = griddedInterpolant(X,Y,V,'spline');
Interpolate over finer intervals with 0.1 spacing.
[Xq,Yq] = ndgrid(-1:.1:1,-2:.1:2);
Vq = F(Xq,Yq);
Plot the result.
figure()
surf(X,Y,V);
view(65,60)
title('Sample Data');
figure()
surf(Xq,Yq,Vq);
view(65,60)
title('Refined with Spline');
8-43
8
Interpolation
8-44
Interpolating Gridded Data
griddedInterpolant in Three Dimensions
This example shows how to create a 3-D interpolant and evaluate over a slice plane so
you can plot the values on that plane.
Create a full grid and sample values.
[X,Y,Z] = ndgrid((-5:2:5));
V = X.^3 + Y.^2 + Z.^2;
Construct the griddedInterpolant.
F = griddedInterpolant(X,Y,Z,V,'cubic');
8-45
8
Interpolation
Since we already created the full grid to generate our sample values, we had nothing to
lose in passing it to griddedInterpolant. In practice however, it's common to load the
sample data into MATLAB from disk. The compact grid can very beneficial in such cases
because it allows you to specify the entire grid in a form that is much more economical in
terms of memory. If we had loaded V into MATLAB instead of calculating it from a full
grid, we could have created a compact grid to conserve memory in our workspace. For
example,
gv = {(-5:2:5),(-5:2:5),(-5:2:5)};
F = griddedInterpolant(gv,V,'cubic');
Now interpolate over a plane at Z = 2 with 0.25 spacing.
[Xq,Yq,Zq] = ndgrid((-5:.25:5),(-5:.25:5),2:2);
Vq = F(Xq,Yq,Zq);
Plot the result.
surf(Xq,Yq,Vq);
title('Refined with Linear Interpolation');
8-46
Interpolating Gridded Data
griddedInterpolant in Four Dimensions
In this example, we’ll create a 4-D interpolant and evaluate it at a single point
1
Create a coarse grid and sample values.
[X1,X2,X3,X4] = ndgrid((-5:2:5));
V = X1.^3 + X2.^2 + X3.^2 +X4;
2
Construct the griddedInterpolant.
F = griddedInterpolant(X1,X2,X3,X4,V,'linear');
3
Query the griddedInterpolant at a single point.
Vq = F([-3.2 2.1 4.7 -1.3])
8-47
8
Interpolation
MATLAB outputs the following:
ans =
-10.1000
.
Other Ways of Working with griddedInterpolant
Depending on the arrangement of your query points, you may prefer one evaluation
syntax over the others. For example, if we create the following interpolant:
[X,Y]=ndgrid(-1:.25:1,-2:.25:2);
V=0.75*Y.^3-3*Y-2*X.^2;
F = griddedInterpolant(X,Y,V);
We can query F using a full grid to give the values at the grid points:
[Xq,Yq] = ndgrid(-1:.1:0,-2:.1:0);
Vq = F(Xq,Yq);
We can also interpolate over the same grid using the compact grid format:
gvq = {-1:.1:0,-2:.1:0};
Vq = F(gvq);
We can also query a single point:
Vq =
F(.315,.738)
which returns:
Vq =
-2.1308
or a random set of scattered points:
rng('default')
Vq = F(rand(3,2))
which returns:
Vq =
8-48
Interpolating Gridded Data
-3.4919
-3.3557
-0.3515
We can also examine the Values in F:
F.Values(1,3)
which returns:
ans =
-0.0313
Now we’ll replace the Values array:
F.Values = 2*V;
You can edit the properties in F on-the-fly. For example, you can replace the interpolation
method as follows:
F.Method = 'cubic';
You can also replace the GridVectors in F. First, we’ll examine GridVectors:
gv = F.GridVectors;
gv{1}
gv is a cell array, and gv{1} displays the first grid vector:
ans =
-1.0000
-0.7500
-0.5000
-0.2500
0
0.2500
0.5000
0.7500
1.0000
Now we’ll replace the GridVectors in F by creating a new cell array new_gv:
new_gv = {(0:0.3:1),(0:0.3:1)};
F.GridVectors = new_gv;
8-49
8
Interpolation
Interpolation of Multiple 1-D Value Sets
This example shows how to interpolate three 1-D data sets in a single pass using
griddedInterpolant. This is a faster alternative to looping over your data sets.
Define the x-coordinates that are common to all values sets.
x = (1:5)';
Define the sets of sample points along the columns of matrix V.
V = [x, 2*x, 3*x]
V =
1
2
3
4
5
2
4
6
8
10
3
6
9
12
15
Create a 2-D grid of sample points.
samplePoints = {x, 1:size(V,2)};
This compact notation specifies a full 2-D grid. The first element, samplePoints{1},
contains the x-coordinates for V, and samplePoints{2} contains the y-coordinates. The
orientation of each coordinate vector does not matter.
Create the interpolant, F, by passing the sample points and sample values to
griddedInterpolant.
F = griddedInterpolant(samplePoints,V);
Create a 2-D query grid with 0.5 spacing along x over all columns of V.
queryPoints = {(1:0.5:5),1:size(V,2)};
Evaluate the interpolant at the x-coordinates for each value set.
Vq = F(queryPoints)
Vq =
1.0000
1.5000
8-50
2.0000
3.0000
3.0000
4.5000
Interpolation of Multiple 1-D Value Sets
2.0000
2.5000
3.0000
3.5000
4.0000
4.5000
5.0000
4.0000
5.0000
6.0000
7.0000
8.0000
9.0000
10.0000
6.0000
7.5000
9.0000
10.5000
12.0000
13.5000
15.0000
See Also
griddedInterpolant
Related Examples
•
“Interpolation with the griddedInterpolant Class” on page 8-37
8-51
8
Interpolation
Interpolation of 2-D Selections in 3-D Grids
This example shows how to reduce the dimensionality of the grid plane arrays in 3-D to
solve a 2-D interpolation problem.
In some application areas, it might be necessary to interpolate a lower dimensional
plane of a grid; for example, interpolating a plane of a 3-D grid. When you extract the
grid plane from the 3-D grid, the resulting arrays might be in 3-D format. You can use
the squeeze function to reduce the dimensionality of the grid plane arrays to solve the
problem in 2-D.
Create a 3-D sample grid and corresponding values.
[X,Y,Z] = ndgrid(1:5);
V = X.^2 + Y.^2 +Z;
Select a 2-D sample from the grid. In this case, the third column of samples.
x = X(:,3,:);
z = Z(:,3,:);
v = V(:,3,:);
The 2-D plane occurs at Y=3, so the Y dimension has been fixed. x, z, and v are 5-by-1by-5 arrays. You must reduce them to 2-D arrays before evaluating the interpolant.
Reduce x, z, and v down to 2-D arrays using the squeeze function.
x = squeeze(x);
z = squeeze(z);
v = squeeze(v);
Interpolate the 2-D slice over a finer grid of query points.
[Xq,Zq] = ndgrid(1:0.5:5);
Vq = interpn(x,z,v,Xq,Zq);
Plot the results.
figure
surf(Xq,Zq,Vq);
xlabel('Xq');
ylabel('Zq');
zlabel('Vq');
8-52
Interpolation of 2-D Selections in 3-D Grids
See Also
interpn | squeeze
More About
•
“Gridded Data Representation” on page 8-4
8-53
8
Interpolation
Interpolating Scattered Data
In this section...
“Scattered Data” on page 8-54
“Interpolating Scattered Data Using griddata and griddatan” on page 8-57
“scatteredInterpolant Class” on page 8-61
“Interpolating Scattered Data Using the scatteredInterpolant Class” on page 8-61
“Interpolation of Complex Scattered Data” on page 8-71
“Addressing Problems in Scattered Data Interpolation” on page 8-73
Scattered Data
Scattered data consists of a set of points X and corresponding values V, where the points
have no structure or order between their relative locations. There are various approaches
to interpolating scattered data. One widely used approach uses a Delaunay triangulation
of the points.
This example shows how to construct an interpolating surface by triangulating the points
and lifting the vertices by a magnitude V into a dimension orthogonal to X.
There are variations on how you can apply this approach. In this example, the
interpolation is broken down into separate steps; typically, the overall interpolation
process is accomplished with one function call.
Create a scattered data set on the surface of a paraboloid.
X = [-1.5 3.2; 1.8 3.3; -3.7 1.5; -1.5 1.3; ...
0.8 1.2; 3.3 1.5; -4.0 -1.0; -2.3 -0.7;
0 -0.5; 2.0 -1.5; 3.7 -0.8; -3.5 -2.9; ...
-0.9 -3.9; 2.0 -3.5; 3.5 -2.25];
V = X(:,1).^2 + X(:,2).^2;
hold on
plot3(X(:,1),X(:,2),zeros(15,1), '*r')
axis([-4, 4, -4, 4, 0, 25]);
grid
stem3(X(:,1),X(:,2),V,'^','fill')
hold off
view(322.5, 30);
8-54
Interpolating Scattered Data
Create a Delaunay triangulation, lift the vertices, and evaluate the interpolant at the
query point Xq.
figure('Color', 'white')
t = delaunay(X(:,1),X(:,2));
hold on
trimesh(t,X(:,1),X(:,2), zeros(15,1), ...
'EdgeColor','r', 'FaceColor','none')
defaultFaceColor = [0.6875 0.8750 0.8984];
trisurf(t,X(:,1),X(:,2), V, 'FaceColor', ...
defaultFaceColor, 'FaceAlpha',0.9);
plot3(X(:,1),X(:,2),zeros(15,1), '*r')
8-55
8
Interpolation
axis([-4, 4, -4, 4, 0, 25]);
grid
plot3(-2.6,-2.6,0,'*b','LineWidth', 1.6)
plot3([-2.6 -2.6]',[-2.6 -2.6]',[0 13.52]','-b','LineWidth',1.6)
hold off
view(322.5, 30);
text(-2.0, -2.6, 'Xq', 'FontWeight', 'bold', ...
'HorizontalAlignment','center', 'BackgroundColor', 'none');
This step generally involves traversing of the triangulation data structure to find the
triangle that encloses the query point. Once you find the point, the subsequent steps
8-56
Interpolating Scattered Data
to compute the value depend on the interpolation method. You could compute the
nearest point in the neighborhood and use the value at that point (the nearest-neighbor
interpolation method). You could also compute the weighted sum of values of the three
vertices of the enclosing triangle (the linear interpolation method). These methods and
their variants are covered in texts and references on scattered data interpolation.
Though the illustration highlights 2-D interpolation, you can apply this technique to
higher dimensions. In more general terms, given a set of points X and corresponding
values V, you can construct an interpolant of the form V = F(X). You can evaluate the
interpolant at a query point Xq, to give Vq = F(Xq). This is a single-valued function;
for any query point Xq within the convex hull of X, it will produce a unique value Vq.
The sample data is assumed to respect this property in order to produce a satisfactory
interpolation.
MATLAB provides two ways to perform triangulation-based scattered data interpolation:
• The functions griddata and griddatan
• The scatteredInterpolant class
The griddata function supports 2-D scattered data interpolation. The griddatan
function supports scattered data interpolation in N-D; however, it is not practical in
dimensions higher than 6-D for moderate to large point sets, due to the exponential
growth in memory required by the underlying triangulation.
The scatteredInterpolant class supports scattered data interpolation in 2-D and 3-D
space. Use of this class is encouraged as it is more efficient and readily adapts to a wider
range of interpolation problems.
Interpolating Scattered Data Using griddata and griddatan
The griddata and griddatan functions take a set of sample points, X, corresponding
values, V, and query points, Xq, and return the interpolated values, Vq. The calling
syntax is similar for each function; the primary distinction is the 2-D / 3–D griddata
function lets you define the points in terms of X, Y / X, Y, Z coordinates. These two
functions interpolate scattered data at predefined grid-point locations; the intent is to
produce gridded data, hence the name. Interpolation is more general in practice. You
might want to query at arbitrary locations within the convex hull of the points.
This example shows how the griddata function interpolates scattered data at a set of
grid points and uses this gridded data to create a contour plot.
8-57
8
Interpolation
Plot the seamount data set (a seamount is an underwater mountain). The data set
consists of a set of longitude (x) and latitude (y) locations, and corresponding seamount
elevations (z) measured at those coordinates.
load seamount
plot3(x,y,z,'.','markersize',12)
xlabel('Longitude')
ylabel('Latitude')
zlabel('Depth in Feet')
grid on
Use meshgrid to create a set of 2-D grid points in the longitude-latitude plane and then
use griddata to interpolate the corresponding depth at those points.
8-58
Interpolating Scattered Data
figure
[xi,yi] = meshgrid(210.8:0.01:211.8, -48.5:0.01:-47.9);
zi = griddata(x,y,z,xi,yi);
surf(xi,yi,zi);
xlabel('Longitude')
ylabel('Latitude')
zlabel('Depth in Feet')
Now that the data is in a gridded format, compute and plot the contours.
figure
[c,h] = contour(xi,yi,zi);
clabel(c,h);
xlabel('Longitude')
ylabel('Latitude')
8-59
8
Interpolation
You can also use griddata to interpolate at arbitrary locations within the convex hull of
the dataset. For example, the depth at coordinates (211.3, -48.2) is given by:
zi = griddata(x,y,z, 211.3, -48.2);
The underlying triangulation is computed each time the griddata function is called.
This can impact performance if the same data set is interpolated repeatedly with
different query points. The scatteredInterpolant class described in “Interpolating
Scattered Data Using the scatteredInterpolant Class” on page 8-61 is more efficient
in this respect.
MATLAB software also provides griddatan to support interpolation in higher
dimensions. The calling syntax is similar to griddata.
8-60
Interpolating Scattered Data
scatteredInterpolant Class
The griddata function is useful when you need to interpolate to find the values at a
set of predefined grid-point locations. In practice, interpolation problems are often more
general, and the scatteredInterpolant class provides greater flexibility. The class has the
following advantages:
• It produces an interpolating function that can be queried efficiently. That is, the
underlying triangulation is created once and reused for subsequent queries.
• The interpolation method can be changed independently of the triangulation.
• The values at the data points can be changed independently of the triangulation.
• Data points can be incrementally added to the existing interpolant without triggering
a complete recomputation. Data points can also be removed and moved efficiently,
provided the number of points edited is small relative to the total number of sample
points.
• It provides extrapolation functionality for approximating values at points that fall
outside the convex hull. See “Extrapolating Scattered Data” on page 8-86 for more
information.
scatteredInterpolant provides the following interpolation methods:
• 'nearest' — Nearest-neighbor interpolation, where the interpolating surface is
discontinuous.
• 'linear' — Linear interpolation (default), where the interpolating surface is C0
continuous.
• 'natural' — Natural-neighbor interpolation, where the interpolating surface is C1
continuous except at the sample points.
The scatteredInterpolant class supports scattered data interpolation in 2-D and 3D space. You can create the interpolant by calling scatteredInterpolant and passing
the point locations and corresponding values, and optionally the interpolation and
extrapolation methods. See the scatteredInterpolant reference page for more information
about the syntaxes you can use to create and evaluate a scatteredInterpolant.
Interpolating Scattered Data Using the scatteredInterpolant Class
This example shows how to use scatteredInterpolant to interpolate a scattered
sampling of the peaks function.
8-61
8
Interpolation
Create the scattered data set.
X = -3 + 6.*gallery('uniformdata',[250 2],0);
V = peaks(X(:,1),X(:,2));
Create the interpolant.
F = scatteredInterpolant(X,V)
F =
scatteredInterpolant with properties:
Points:
Values:
Method:
ExtrapolationMethod:
[250x2 double]
[250x1 double]
'linear'
'linear'
The Points property represents the coordinates of the data points, and the Values
property represents the associated values. The Method property represents the
interpolation method that performs the interpolation. The ExtrapolationMethod
property represents the extrapolation method used when query points fall outside the
convex hull.
You can access the properties of F in the same way you access the fields of a struct. For
example, use F.Points to examine the coordinates of the data points.
Evaluate the interpolant.
scatteredInterpolant provides subscripted evaluation of the interpolant. It is
evaluated the same way as a function. You can evaluate the interpolant as follows. In
this case, the value at the query location is given by Vq. You can evaluate at a single
query point:
Vq = F([1.5 1.25])
Vq =
1.3966
8-62
Interpolating Scattered Data
You can also pass individual coordinates:
Vq = F(1.5, 1.25)
Vq =
1.3966
You can evaluate at a vector of point locations:
Xq = [0.5 0.25; 0.75 0.35; 1.25 0.85];
Vq = F(Xq)
Vq =
1.0880
1.8127
2.3472
You can evaluate F at grid point locations and plot the result.
[Xq,Yq] = meshgrid(-2.5:0.125:2.5);
Vq = F(Xq,Yq);
surf(Xq,Yq,Vq);
xlabel('X','fontweight','b'), ylabel('Y','fontweight','b');
zlabel('Value - V','fontweight','b');
title('Linear Interpolation Method','fontweight','b');
8-63
8
Interpolation
Change the interpolation method.
You can change the interpolation method on the fly. Set the method to 'nearest'.
F.Method = 'nearest';
Reevaluate and plot the interpolant as before.
Vq = F(Xq,Yq);
figure
surf(Xq,Yq,Vq);
xlabel('X','fontweight','b'),ylabel('Y','fontweight','b')
zlabel('Value - V','fontweight','b')
title('Nearest neighbor Interpolation Method','fontweight','b');
8-64
Interpolating Scattered Data
Change the interpolation method to natural neighbor, reevaluate, and plot the results.
F.Method = 'natural';
Vq = F(Xq,Yq);
figure
surf(Xq,Yq,Vq);
xlabel('X','fontweight','b'),ylabel('Y','fontweight','b')
zlabel('Value - V','fontweight','b')
title('Natural neighbor Interpolation Method','fontweight','b');
8-65
8
Interpolation
Replace the values at the sample data locations.
You can change the values V at the sample data locations, X, on the fly. This is useful
in practice as some interpolation problems may have multiple sets of values at the
same locations. For example, suppose you want to interpolate a 3-D velocity field that is
defined by locations (x, y, z) and corresponding componentized velocity vectors (Vx, Vy,
Vz). You can interpolate each of the velocity components by assigning them to the values
property (V) in turn. This has important performance benefits, because it allows you to
reuse the same interpolant without incurring the overhead of computing a new one each
time.
The following steps show how to change the values in our example. You will compute the
values using the expression,
8-66
.
Interpolating Scattered Data
V = X(:,1).*exp(-X(:,1).^2-X(:,2).^2);
F.Values = V;
Evaluate the interpolant and plot the result.
Vq = F(Xq,Yq);
figure
surf(Xq,Yq,Vq);
xlabel('X','fontweight','b'), ylabel('Y','fontweight','b')
zlabel('Value - V','fontweight','b')
title('Natural neighbor interpolation of v = x.*exp(-x.^2-y.^2)')
8-67
8
Interpolation
Add additional point locations and values to the existing interpolant.
This performs an efficient update as opposed to a complete recomputation using the
augmented data set.
When adding sample data, it is important to add both the point locations and the
corresponding values.
Continuing the example, create new sample points as follows:
X = -1.5 + 3.*rand(100,2);
V = X(:,1).*exp(-X(:,1).^2-X(:,2).^2);
Add the new points and corresponding values to the triangulation.
F.Points(end+(1:100),:) = X;
F.Values(end+(1:100)) = V;
Evaluate the refined interpolant and plot the result.
Vq = F(Xq,Yq);
figure
surf(Xq,Yq,Vq);
xlabel('X','fontweight','b'), ylabel('Y','fontweight','b');
zlabel('Value - V','fontweight','b');
8-68
Interpolating Scattered Data
Remove data from the interpolant.
You can incrementally remove sample data points from the interpolant. You also can
remove data points and corresponding values from the interpolant. This is useful for
removing spurious outliers.
When removing sample data, it is important to remove both the point location and the
corresponding value.
Remove the 25th point.
F.Points(25,:) = [];
F.Values(25) = [];
8-69
8
Interpolation
Remove points 5 to 15.
F.Points(5:15,:) = [];
F.Values(5:15) = [];
Retain 150 points and remove the rest.
F.Points(150:end,:) = [];
F.Values(150:end) = [];
This creates a coarser surface when you evaluate and plot:
Vq = F(Xq,Yq);
figure
surf(Xq,Yq,Vq);
xlabel('X','fontweight','b'), ylabel('Y','fontweight','b');
zlabel('Value - V','fontweight','b');
title('Interpolation of v = x.*exp(-x.^2-y.^2) with sample points removed')
8-70
Interpolating Scattered Data
Interpolation of Complex Scattered Data
This example shows how to interpolate scattered data when the value at each sample
location is complex.
Create the sample data.
X = -3 + 6 .* gallery('uniformdata',[250 2],0);
V = complex(X(:,1).*X(:,2), X(:,1).^2 + X(:,2).^2);
Create the interpolant.
F = scatteredInterpolant(X,V);
8-71
8
Interpolation
Create a grid of query points and evaluate the interpolant at the grid points.
[Xq,Yq] = meshgrid(-2.5:0.125:2.5);
Vq = F(Xq,Yq);
Plot the real component of Vq.
VqReal = real(Vq);
figure
surf(Xq,Yq,VqReal);
xlabel('X');
ylabel('Y');
zlabel('Real Value - V');
title('Real Component of Interpolated Value');
8-72
Interpolating Scattered Data
Plot the imaginary component of Vq.
VqImag = imag(Vq);
figure
surf(Xq,Yq,VqImag);
xlabel('X');
ylabel('Y');
zlabel('Imaginary Value - V');
title('Imaginary Component of Interpolated Value');
Addressing Problems in Scattered Data Interpolation
Many of the illustrative examples in the previous sections dealt with the interpolation of
point sets that were sampled on smooth surfaces. In addition, the points were relatively
8-73
8
Interpolation
uniformly spaced. For example, clusters of points were not separated by relatively large
distances. In addition, the interpolant was evaluated well within the convex hull of the
point locations.
When dealing with real-world interpolation problems the data may be more challenging.
It may come from measuring equipment that is likely to produce inaccurate readings or
outliers. The underlying data may not vary smoothly, the values may jump abruptly from
point to point. This section provides you with some guidelines to identify and address
problems with scattered data interpolation.
Input Data Containing NaNs
You should preprocess sample data that contains NaN values to remove the NaN values as
this data cannot contribute to the interpolation. If a NaN is removed, the corresponding
data values/coordinates should also be removed to ensure consistency. If NaN values are
present in the sample data, the constructor will error when called.
The following example illustrates how to remove NaNs.
Create some data and replace some entries with NaN:
x = rand(25,1)*4-2;
y = rand(25,1)*4-2;
V = x.^2 + y.^2;
x(5) = NaN; x(10) = NaN; y(12) = NaN; V(14) = NaN;
This code errors:
F = scatteredInterpolant(x,y,V);
Instead, find the sample point indices of the NaNs and then construct the interpolant:
nan_flags = isnan(x) | isnan(y) | isnan(V);
x(nan_flags) = [];
y(nan_flags) = [];
V(nan_flags) = [];
F = scatteredInterpolant(x,y,V);
The following example is similar if the point locations are in matrix form. First, create
data and replace some entries with NaN values.
X = rand(25,2)*4-2;
V = X(:,1).^2 + X(:,2).^2;
8-74
Interpolating Scattered Data
X(5,1) = NaN; X(10,1) = NaN; X(12,2) = NaN; V(14) = NaN;
This code errors:
F = scatteredInterpolant(X,V);
Find the sample point indices of the NaN and then construct the interpolant:
nan_flags = isnan(X(:,1)) | isnan(X(:,2)) | isnan(V);
X(nan_flags,:) = [];
V(nan_flags) = [];
F = scatteredInterpolant(X,V);
Interpolant Outputs NaN Values
griddata and griddatan return NaN values when you query points outside the convex
hull using the 'linear' or 'natural' methods. However, you can expect numeric
results if you query the same points using the 'nearest' method. This is because the
nearest neighbor to a query point exists both inside and outside the convex hull.
If you want to compute approximate values outside the convex hull, you should use
scatteredInterpolant. See “Extrapolating Scattered Data” on page 8-86 for more
information.
Handling Duplicate Point Locations
Input data is rarely “perfect” and your application could have to handle duplicate data
point locations. Two or more data points at the same location in your data set can have
different corresponding values. In this scenario, scatteredInterpolant merges the
points and computes the average of the corresponding values. This example shows how
scatteredInterpolant performs an interpolation on a data set with duplicate points.
1
Create some sample data that lies on a planar surface:
x = rand(100,1)*6-3;
y = rand(100,1)*6-3;
V = x + y;
2
Introduce a duplicate point location by assigning the coordinates of point 50 to point
100:
x(50) = x(100);
y(50) = y(100);
3
Create the interpolant. Notice that F contains 99 unique data points:
8-75
8
Interpolation
F = scatteredInterpolant(x,y,V)
4
Check the value associated with the 50th point:
F.Values(50)
This value is the average of the original 50th and 100th value, as these two data points
have the same location:
(V(50)+V(100))/2
In this scenario the interpolant resolves the ambiguity in a reasonable manner. However
in some instances, data points can be close rather than coincident, and the values at
those locations can be different.
In some interpolation problems, multiple sets of sample values might correspond to the
same locations. For example, a set of values might be recorded at the same locations at
different periods in time. For efficiency, you can interpolate one set of readings and then
replace the values to interpolate the next set.
Always use consistent data management when replacing values in the presence of
duplicate point locations. Suppose you have two sets of values associated with the 100
data point locations and you would like to interpolate each set in turn by replacing the
values.
1
Consider two sets of values:
V1 = x + 4*y;
V2 = 3*x + 5*y
2
Create the interpolant. scatteredInterpolant merges the duplicate locations and
the interpolant contains 99 unique sample points:
F = scatteredInterpolant(x,y,V1)
Replacing the values directly via F.Values = V2 means assigning 100 values to 99
samples. The context of the previous merge operation is lost; the number of sample
locations will not match the number of sample values. The interpolant will require
the inconsistency to be resolved to support queries.
In this more complex scenario, it is necessary to remove the duplicates prior to creating
and editing the interpolant. Use the unique function to find the indices of the unique
points. unique can also output arguments that identify the indices of the duplicate
points.
[~, I, ~] = unique([x y],'first','rows');
8-76
Interpolating Scattered Data
I = sort(I);
x = x(I);
y = y(I);
V1 = V1(I);
V2 = V2(I);
F = scatteredInterpolant(x,y,V1)
Now you can use F to interpolate the first data set. Then you can replace the values to
interpolate the second data set.
F.Values = V2;
Achieving Efficiency When Editing a scatteredInterpolant
scatteredInterpolant allows you to edit the properties representing the sample
values (F.Values) and the interpolation method (F.Method). Since these properties
are independent of the underlying triangulation, the edits can be performed efficiently.
However, like working with a large array, you should take care not to accidentally create
unnecessary copies when editing the data. Copies are made when more than one variable
references an array and that array is then edited.
A copy is not made in the following:
A1 = magic(4)
A1(4,4) = 11
However, a copy is made in this scenario because the array is referenced by another
variable. The arrays A1 and A2 can no longer share the same data once the edit is made:
A1 = magic(4)
A2 = A1
A1(4,4) = 32
Similarly, if you pass the array to a function and edit the array within that
function, a deep copy may be made depending on how the data is managed.
scatteredInterpolant contains data and it behaves like an array—in MATLAB
language, it is called a value object. The MATLAB language is designed to give optimum
performance when your application is structured into functions that reside in files.
Prototyping at the command line may not yield the same level of performance.
The following example demonstrates this behavior, but it should be noted that
performance gains in this example do not generalize to other functions in MATLAB.
This code does not produce optimal performance:
x = rand(1000000,1)*4-2;
8-77
8
Interpolation
y = rand(1000000,1)*4-2;
z = x.*exp(-x.^2-y.^2);
tic; F = scatteredInterpolant(x,y,z); toc
tic; F.Values = 2*z; toc
You can place the code in a function file to execute it more efficiently.
When MATLAB executes a program that is composed of functions that reside in files, it
has a complete picture of the execution of the code; this allows MATLAB to optimize for
performance. When you type the code at the command line, MATLAB cannot anticipate
what you are going to type next, so it cannot perform the same level of optimization.
Developing applications through the creation of reusable functions is general and
recommended practice, and MATLAB will optimize the performance in this setting.
Interpolation Results Poor Near the Convex Hull
The Delaunay triangulation is well suited to scattered data interpolation problems
because it has favorable geometric properties that produce good results. These properties
are:
• The rejection of sliver-shaped triangles/tetrahedra in favor of more equilateral-shaped
ones.
• The empty circumcircle property that implicitly defines a nearest-neighbor relation
between the points.
The empty circumcircle property ensures the interpolated values are influenced by
sample points in the neighborhood of the query location. Despite these qualities, in some
situations the distribution of the data points may lead to poor results and this typically
happens near the convex hull of the sample data set. When the interpolation produces
unexpected results, a plot of the sample data and underlying triangulation can often
provide insight into the problem.
This example shows an interpolated surface that deteriorates near the boundary.
Create a sample data set that will exhibit problems near the boundary.
t = 0.4*pi:0.02:0.6*pi;
x1 = cos(t)';
y1 = sin(t)'-1.02;
x2 = x1;
y2 = y1*(-1);
x3 = linspace(-0.3,0.3,16)';
y3 = zeros(16,1);
8-78
Interpolating Scattered Data
x = [x1;x2;x3];
y = [y1;y2;y3];
Now lift these sample points onto the surface
and interpolate the surface.
z = x.^2 + y.^2;
F = scatteredInterpolant(x,y,z);
[xi,yi] = meshgrid(-0.3:.02:0.3, -0.0688:0.01:0.0688);
zi = F(xi,yi);
mesh(xi,yi,zi)
xlabel('X','fontweight','b'), ylabel('Y','fontweight','b')
zlabel('Value - V','fontweight','b')
title('Interpolated Surface');
8-79
8
Interpolation
The actual surface is:
zi = xi.^2 + yi.^2;
figure
mesh(xi,yi,zi)
title('Actual Surface')
To understand why the interpolating surface deteriorates near the boundary, it is helpful
to look at the underlying triangulation:
dt = delaunayTriangulation(x,y);
figure
plot(x,y,'*r')
axis equal
hold on
8-80
Interpolating Scattered Data
triplot(dt)
plot(x1,y1,'-r')
plot(x2,y2,'-r')
title('Triangulation Used to Create the Interpolant')
hold off
The triangles within the red boundaries are relatively well shaped; they are constructed
from points that are in close proximity and the interpolation works well in this region.
Outside the red boundary, the triangles are sliver-like and connect points that are remote
from each other. There is not sufficient sampling to accurately capture the surface, so it
is not surprising that the results in these regions are poor. In 3-D, visual inspection of
the triangulation gets a bit trickier, but looking at the point distribution can often help
illustrate potential problems.
8-81
8
Interpolation
The MATLAB® 4 griddata method, 'v4', is not triangulation-based and is not affected
by deterioration of the interpolation surface near the boundary.
[xi,yi] = meshgrid(-0.3:.02:0.3, -0.0688:0.01:0.0688);
zi = griddata(x,y,z,xi,yi,'v4');
mesh(xi,yi,zi)
xlabel('X','fontweight','b'), ylabel('Y','fontweight','b')
zlabel('Value - V','fontweight','b')
title('Interpolated surface from griddata with v4 method','fontweight','b');
The interpolated surface from griddata using the 'v4' method corresponds to the
expected actual surface.
8-82
Interpolation Using a Specific Delaunay Triangulation
Interpolation Using a Specific Delaunay Triangulation
In this section...
“Nearest-Neighbor Interpolation Using a delaunayTriangulation Query” on page
8-83
“Linear Interpolation Using a delaunayTriangulation Query” on page 8-84
Nearest-Neighbor Interpolation Using a delaunayTriangulation Query
This example shows how to perform nearest-neighbor interpolation on a scattered set of
points using a specific Delaunay triangulation.
Create a delaunayTriangulation of a set of scattered points in 2-D.
P = -2.5 + 5*gallery('uniformdata',[50 2],0);
DT = delaunayTriangulation(P)
DT =
delaunayTriangulation with properties:
Points: [50x2 double]
ConnectivityList: [87x3 double]
Constraints: []
Sample a parabolic function, V(x, y), at the points specified in P.
V = P(:,1).^2 + P(:,2).^2;
Define 10 random query points.
Pq = -2 + 4*gallery('uniformdata',[10 2],1);
Perform nearest-neighbor interpolation on V using the triangulation, DT. Use
nearestNeighbor to find the indices of the nearest-neighbor vertices, vi, for the set of
query points, Pq. Then examine the specific values of V at the indices.
vi = nearestNeighbor(DT,Pq);
Vq = V(vi)
Vq =
8-83
8
Interpolation
5.3163
0.3453
4.3026
1.2579
1.9435
5.9194
3.9030
0.4172
11.7282
0.8641
Linear Interpolation Using a delaunayTriangulation Query
This example shows how to perform linear interpolation on a scattered set of points with
a specific Delaunay triangulation.
You can use the triangulation method, pointLocation, to compute the enclosing
triangle of a query point and the magnitudes of the vertex weights. The weights are
called barycentric coordinates, and they represent a partition of unity. That is, the sum of
the three weights equals 1. The interpolated value of a function, V, at a query point is the
sum of the weighted values of V at the three vertices. That is, if the function has values,
V1, V2, V3 at the three vertices, and the weights are B1, B2, B3, then the interpolated
value is (V1)(B1) + (V2)(B2) + (V3)(B3).
Create a delaunayTriangulation of a set of scattered points in 2-D.
P = -2.5 + 5*gallery('uniformdata',[50 2],0);
DT = delaunayTriangulation(P)
DT =
delaunayTriangulation with properties:
Points: [50x2 double]
ConnectivityList: [87x3 double]
Constraints: []
Sample a parabolic function, V(x, y), at the points in P.
V = P(:,1).^2 + P(:,2).^2;
Define 10 random query points.
8-84
Interpolation Using a Specific Delaunay Triangulation
Pq = -2 + 4*gallery('uniformdata',[10 2],1);
Find the triangle that encloses each query point using the pointLocation method.
In the code below, ti contains the IDs of the enclosing triangles and bc contains the
barycentric coordinates associated with each triangle.
[ti,bc] = pointLocation(DT,Pq);
Find the values of V(x, y) at the vertices of each enclosing triangle.
triVals = V(DT(ti,:));
Calculate the sum of the weighted values of V(x, y) using the dot product.
Vq = dot(bc',triVals')'
Vq =
5.9456
1.1222
4.7963
0.9373
2.3533
3.4219
2.3104
0.7728
8.0479
1.0886
See Also
delaunayTriangulation | nearestNeighbor | pointLocation
More About
•
“Interpolating Scattered Data” on page 8-54
8-85
8
Interpolation
Extrapolating Scattered Data
In this section...
“Factors That Affect the Accuracy of Extrapolation” on page 8-86
“Compare Extrapolation of Coarsely and Finely Sampled Scattered Data” on page
8-86
“Extrapolation of 3-D Data” on page 8-90
Factors That Affect the Accuracy of Extrapolation
scatteredInterpolant provides functionality for approximating values at points that fall
outside the convex hull. The 'linear' extrapolation method is based on a least-squares
approximation of the gradient at the boundary of the convex hull. The values it returns
for query points outside the convex hull are based on the values and gradients at the
boundary. The quality of the solution depends on how well you’ve sampled your data. If
your data is coarsely sampled, the quality of the extrapolation is poor.
In addition, the triangulation near the convex hull boundary can have sliver-like
triangles. These triangles can compromise your extrapolation results in the same way
that they can compromise interpolation results. See “Interpolation Results Poor Near the
Convex Hull” on page 8-78 for more information.
You should inspect your extrapolation results visually using your knowledge of the
behavior outside the domain.
Compare Extrapolation of Coarsely and Finely Sampled Scattered Data
This example shows how to interpolate two different samplings of the same parabolic
function. It also shows that a better distribution of sample points produces better
extrapolation results.
Create a radial distribution of points spaced 10 degrees apart around 10 concentric
circles. Use bsxfun to compute the coordinates,
theta = 0:10:350;
c = cosd(theta);
s = sind(theta);
8-86
and
.
Extrapolating Scattered Data
r = 1:10;
x1 = bsxfun(@times,r.',c);
y1 = bsxfun(@times,r.',s);
figure
plot(x1,y1,'*b')
axis equal
Create a second, more coarsely distributed set of points. Use the gallery function to
create random samplings in the range, [-10, 10].
x2 = -10 + 20*gallery('uniformdata',[25 1],0);
y2 = -10 + 20*gallery('uniformdata',[25 1],1);
8-87
8
Interpolation
figure
plot(x2,y2,'*')
Sample a parabolic function, v(x,y), at both sets of points.
v1 = x1.^2 + y1.^2;
v2 = x2.^2 + y2.^2;
Create a scatteredInterpolant for each sampling of v(x,y).
F1 = scatteredInterpolant(x1(:),y1(:),v1(:));
F2 = scatteredInterpolant(x2(:),y2(:),v2(:));
Create a grid of query points that extend beyond each domain.
8-88
Extrapolating Scattered Data
[xq,yq] = ndgrid(-20:20);
Evaluate F1 and plot the results.
figure
vq1 = F1(xq,yq);
surf(xq,yq,vq1)
Evaluate F2 and plot the results.
figure
vq2 = F2(xq,yq);
surf(xq,yq,vq2)
8-89
8
Interpolation
The quality of the extrapolation is not as good for F2 because of the coarse sampling of
points in v2.
Extrapolation of 3-D Data
This example shows how to extrapolate a well sampled 3-D gridded dataset using
scatteredInterpolant. The query points lie on a planar grid that is completely
outside domain.
Create a 10-by-10-by-10 grid of sample points. The points in each dimension are in the
range, [-10, 10].
[x,y,z] = ndgrid(-10:10);
8-90
Extrapolating Scattered Data
Sample a function, v(x,y,z), at the sample points.
v = x.^2 + y.^2 + z.^2;
Create a scatteredInterpolant, specifying linear interpolation and extrapolation.
F = scatteredInterpolant(x(:),y(:),z(:),v(:),'linear','linear');
Evaluate the interpolant over an x-y grid spanning the range, [-20,20] at an elevation, z =
15.
[xq,yq,zq] = ndgrid(-20:20,-20:20,15);
vq = F(xq,yq,zq);
figure
surf(xq,yq,vq)
8-91
8
Interpolation
The extrapolation returned good results because the function is well sampled.
8-92
9
Optimization
• “Function Summary” on page 9-2
• “Optimizing Nonlinear Functions” on page 9-3
• “Curve Fitting via Optimization” on page 9-9
• “Set Options” on page 9-12
• “Iterative Display” on page 9-16
• “Output Functions” on page 9-18
• “Plot Functions” on page 9-26
• “Troubleshooting and Tips” on page 9-29
• “Reference” on page 9-30
9
Optimization
Function Summary
The following table lists the MATLAB optimization functions.
Function
Description
fminbnd
Minimize a function of one variable on a fixed interval
fminsearch
Minimize a function of several variables
fzero
Find zero of a function of one variable
lsqnonneg
Linear least squares with nonnegativity constraints
optimget
Get optimization options structure parameter values
optimset
Create or edit optimization options parameter structure
To maximize a function, see “Maximizing Functions” on page 9-6. For information on
solving single-variable nonlinear equations, see “Roots of Scalar Functions” on page 6-14.
9-2
Optimizing Nonlinear Functions
Optimizing Nonlinear Functions
In this section...
“Minimizing Functions of One Variable” on page 9-3
“Minimizing Functions of Several Variables” on page 9-5
“Maximizing Functions” on page 9-6
“fminsearch Algorithm” on page 9-6
Minimizing Functions of One Variable
Given a mathematical function of a single variable, you can use the fminbnd function
to find a local minimizer of the function in a given interval. For example, consider the
humps.m function, which is provided with MATLAB. The following figure shows the
graph of humps.
x = -1:.01:2;
y = humps(x);
plot(x,y)
xlabel('x')
ylabel('humps(x)')
grid on
9-3
9
Optimization
To find the minimum of the humps function in the range (0.3,1), use
x = fminbnd(@humps,0.3,1)
x =
0.6370
You can ask for a tabular display of output by passing a fourth argument created by the
optimset command to fminbnd:
opts = optimset('Display','iter');
9-4
Optimizing Nonlinear Functions
x = fminbnd(@humps,0.3,1,opts)
Func-count
1
2
3
4
5
6
7
8
9
x
0.567376
0.732624
0.465248
0.644416
0.6413
0.637618
0.636985
0.637019
0.637052
f(x)
12.9098
13.7746
25.1714
11.2693
11.2583
11.2529
11.2528
11.2528
11.2528
Procedure
initial
golden
golden
parabolic
parabolic
parabolic
parabolic
parabolic
parabolic
Optimization terminated:
the current x satisfies the termination criteria using OPTIONS.TolX of 1.000000e-04
x =
0.6370
This shows the current value of x and the function value at f(x) each time a function
evaluation occurs. For fminbnd, one function evaluation corresponds to one iteration of
the algorithm. The last column shows what procedure is being used at each iteration,
either a golden section search or a parabolic interpolation. For more information, see
“Iterative Display” on page 9-16.
Minimizing Functions of Several Variables
The fminsearch function is similar to fminbnd except that it handles functions of
many variables, and you specify a starting vector x0 rather than a starting interval.
fminsearch attempts to return a vector x that is a local minimizer of the mathematical
function near this starting vector.
To try fminsearch, create a function three_var of three variables, x, y, and z.
function b = three_var(v)
x = v(1);
y = v(2);
z = v(3);
b = x.^2 + 2.5*sin(y) - z^2*x^2*y^2;
9-5
9
Optimization
Now find a minimum for this function using x = -0.6, y = -1.2, and z = 0.135 as
the starting values.
v = [-0.6 -1.2 0.135];
a = fminsearch(@three_var,v)
a =
0.0000
-1.5708
0.1803
Maximizing Functions
The fminbnd and fminsearch solvers attempt to minimize an objective function. If you
have a maximization problem, that is, a problem of the form
max f ( x),
x
then define g(x) = –f(x), and minimize g.
For example, to find the maximum of tan(cos(x)) near x = 5, evaluate:
[x fval] = fminbnd(@(x)-tan(cos(x)),3,8)
x =
6.2832
fval =
-1.5574
The maximum is 1.5574 (the negative of the reported fval), and occurs at x = 6.2832.
This answer is correct since, to five digits, the maximum is tan(1) = 1.5574, which occurs
at x = 2π = 6.2832.
fminsearch Algorithm
fminsearch uses the Nelder-Mead simplex algorithm as described in Lagarias et al. [1].
This algorithm uses a simplex of n + 1 points for n-dimensional vectors x. The algorithm
first makes a simplex around the initial guess x0 by adding 5% of each component x0(i)
to x0, and using these n vectors as elements of the simplex in addition to x0. (It uses
0.00025 as component i if x0(i) = 0.) Then, the algorithm modifies the simplex repeatedly
according to the following procedure.
9-6
Optimizing Nonlinear Functions
Note: The keywords for the fminsearch iterative display appear in bold after the
description of the step.
1
Let x(i) denote the list of points in the current simplex, i = 1,...,n+1.
2
Order the points in the simplex from lowest function value f(x(1)) to highest f(x(n+1)).
At each step in the iteration, the algorithm discards the current worst point x(n+1),
and accepts another point into the simplex. [Or, in the case of step 7 below, it
changes all n points with values above f(x(1))].
3
Generate the reflected point
r = 2m – x(n+1),
where
m = Σx(i)/n, i = 1...n,
and calculate f(r).
4
If f(x(1)) ≤ f(r) < f(x(n)), accept r and terminate this iteration. Reflect
5
If f(r) < f(x(1)), calculate the expansion point s
s = m + 2(m – x(n+1)),
and calculate f(s).
6
a
If f(s) < f(r), accept s and terminate the iteration. Expand
b
Otherwise, accept r and terminate the iteration. Reflect
If f(r) ≥ f(x(n)), perform a contraction between m and the better of x(n+1) and r:
a
If f(r) < f(x(n+1)) (i.e., r is better than x(n+1)), calculate
c = m + (r – m)/2
and calculate f(c). If f(c) < f(r), accept c and terminate the iteration. Contract
outside Otherwise, continue with Step 7 (Shrink).
b
If f(r) ≥ f(x(n+1)), calculate
cc = m + (x(n+1) – m)/2
and calculate f(cc). If f(cc) < f(x(n+1)), accept cc and terminate the iteration.
Contract inside Otherwise, continue with Step 7 (Shrink).
7
Calculate the n points
v(i) = x(1) + (x(i) – x(1))/2
9-7
9
Optimization
and calculate f(v(i)), i = 2,...,n+1. The simplex at the next iteration is x(1),
v(2),...,v(n+1). Shrink
The following figure shows the points that fminsearch might calculate in the procedure,
along with each possible new simplex. The original simplex has a bold outline. The
iterations proceed until they meet a stopping criterion.
x(n+1)
v(n+1)
cc
x(1)
m
c
r
s
9-8
Curve Fitting via Optimization
Curve Fitting via Optimization
In this section...
“Curve Fitting by Optimization” on page 9-9
“Creating an Example File” on page 9-9
“Running the Example” on page 9-10
“Plotting the Results” on page 9-10
Curve Fitting by Optimization
This section gives an example that shows how to fit an exponential function of the form
Ae–λt to some data. The example uses the fminsearch solver to minimize the sum
of squares of errors between the data and an exponential function Ae–λt for varying
parameters A and λ.
Creating an Example File
To run the example, first create a file that:
• Accepts vectors corresponding to the x- and y-coordinates of the data
• Returns the parameters of the exponential function that best fits the data
To do so, copy and paste the following code into a file and save it as fitcurvedemo in a
directory on the MATLAB path.
function [estimates, model] = fitcurvedemo(xdata, ydata)
% Call fminsearch with a random starting point.
start_point = rand(1, 2);
model = @expfun;
estimates = fminsearch(model, start_point);
% expfun accepts curve parameters as inputs, and outputs sse,
% the sum of squares error for A*exp(-lambda*xdata)-ydata,
% and the FittedCurve. FMINSEARCH only needs sse, but we want
% to plot the FittedCurve at the end.
function [sse, FittedCurve] = expfun(params)
A = params(1);
lambda = params(2);
FittedCurve = A .* exp(-lambda * xdata);
9-9
9
Optimization
ErrorVector = FittedCurve - ydata;
sse = sum(ErrorVector .^ 2);
end
end
The file calls the function fminsearch, which finds parameters A and lambda that
minimize the sum of squares of the differences between the data and the exponential
function A*exp(-lambda*t). The nested function expfun computes the sum of squares.
Running the Example
To run the example, first create some random data to fit. The following commands
create random data that is approximately exponential with parameters A = 40 and
lambda = .5.
xdata = (0:.1:10)';
ydata = 40 * exp(-.5 * xdata) + randn(size(xdata));
To fit an exponential function to the data, enter
[estimates, model] = fitcurvedemo(xdata,ydata)
This returns estimates for the parameters A and lambda,
estimates =
40.1334
0.5025
and a function handle, model, to the function that computes the exponential function
A*exp(-lambda*t).
Plotting the Results
To plot the fit and the data, enter the following commands.
plot(xdata, ydata, '*')
hold on
[sse, FittedCurve] = model(estimates);
plot(xdata, FittedCurve, 'r')
xlabel('xdata')
ylabel('f(estimates,xdata)')
title(['Fitting to function ', func2str(model)]);
9-10
Curve Fitting via Optimization
legend('data', ['fit using ', func2str(model)])
hold off
The resulting plot displays the data points and the exponential fit.
9-11
9
Optimization
Set Options
In this section...
“How to Set Options” on page 9-12
“Options Table” on page 9-12
“Tolerances and Stopping Criteria” on page 9-13
“Output Structure” on page 9-14
How to Set Options
You can specify optimization parameters using an options structure that you create
using the optimset function. You then pass options as an input to the optimization
function, for example, by calling fminbnd with the syntax
x = fminbnd(fun,x1,x2,options)
or fminsearch with the syntax
x = fminsearch(fun,x0,options)
For example, to display output from the algorithm at each iteration, set the Display
option to 'iter':
options = optimset('Display','iter');
Options Table
Option
Description
Solvers
Display
A flag indicating whether intermediate steps
appear on the screen.
fminbnd,
fminsearch,
fzero, lsqnonneg
• 'notify' (default) displays output only if
the function does not converge.
• 'iter' displays intermediate steps (not
available with lsqnonneg). See “Iterative
Display” on page 9-16.
• 'off' displays no intermediate steps.
• 'final' displays just the final output.
9-12
Set Options
Option
Description
Solvers
FunValCheck
Check whether objective function values are
valid.
fminbnd,
fminsearch,
fzero
• 'on' displays an error when the objective
function or constraints return a value that is
complex or NaN.
• 'off' (default) displays no error.
MaxFunEvals
The maximum number of function evaluations
allowed. The default value is 500 for fminbnd
and 200*length(x0) for fminsearch.
fminbnd,
fminsearch
MaxIter
The maximum number of iterations allowed.
The default value is 500 for fminbnd and
200*length(x0) for fminsearch.
fminbnd,
fminsearch
OutputFcn
Display information on the iterations of the
solver. The default is [] (none). See “Output
Functions” on page 9-18.
fminbnd,
fminsearch,
fzero
PlotFcns
Plot information on the iterations of the
solver. The default is [] (none). For available
predefined functions, see “Plot Functions” on
page 9-26.
fminbnd,
fminsearch,
fzero
TolFun
The termination tolerance for the function value. fminsearch
The default value is 1.e-4. See “Tolerances and
Stopping Criteria” on page 9-13.
TolX
The termination tolerance for x. The default
value is 1.e-4. See “Tolerances and Stopping
Criteria” on page 9-13.
fminbnd,
fminsearch,
fzero, lsqnonneg
Tolerances and Stopping Criteria
The number of iterations in an optimization depends on a solver's stopping criteria.
These criteria include several tolerances you can set. Generally, a tolerance is a threshold
which, if crossed, stops the iterations of a solver.
Tip Generally, set the TolFun and TolX tolerances to well above eps, and usually above
1e-14. Setting small tolerances doesn’t guarantee accurate results. Instead, a solver can
9-13
9
Optimization
fail to recognize when it has converged, and can continue futile iterations. A tolerance
value smaller than eps effectively disables that stopping condition.
• TolX is a lower bound on the size of a step, meaning the norm of (xi – xi+1). If the
solver attempts to take a step that is smaller than TolX, the iterations end. Solvers
sometimes use TolX as a relative bound, meaning iterations end when |(xi – xi+1)| <
TolX*(1 + |xi|), or a similar relative measure.
Iterations end
when the last step
• 1 is smaller than
TolFun or TolX
•2
•3
TolFun
45
• •
TolX
• TolFun is a lower bound on the change in the value of the objective function during a
step. If |f(xi) – f(xi+1)| < TolFun, the iterations end. Solvers sometimes use TolFun as
a relative bound, meaning iterations end when |f(xi) – f(xi+1)| < TolFun(1 + |f(xi)|), or
a similar relative measure.
• MaxIter is a bound on the number of solver iterations. MaxFunEvals is a bound on
the number of function evaluations.
Output Structure
The output structure includes the number of function evaluations, the number of
iterations, and the algorithm. The structure appears when you provide fminbnd,
fminsearch, or fzero with a fourth output argument, as in
[x,fval,exitflag,output] = fminbnd(@humps,0.3,1);
The details of each solver’s output structure are on the function reference pages.
9-14
Set Options
The output structure is not an option that you choose with optimset. It is an optional
output for fminbnd, fminsearch, and fzero.
9-15
9
Optimization
Iterative Display
You obtain details of the steps solvers take by setting the Display option to 'iter'
with optimset. The displayed output contains headings and items from the following
list.
Heading
Information Displayed
Solvers
Iteration
Iteration number, meaning the number of steps
the algorithm has taken
fminsearch
Func-count
Cumulative number of function evaluations
fminbnd,
fminsearch,
fzero
x
Current point
fminbnd, fzero
f(x)
Current objective function value
fminbnd, fzero
min f(x)
Smallest objective function value found
fminsearch
Procedure
Algorithm used during the iteration
• initial
fminbnd
• golden (golden section search)
• parabolic (parabolic interpolation)
• initial simplex
fminsearch
• expand
• reflect
• shrink
• contract inside
• contract outside
For details, see “fminsearch Algorithm” on page
9-6.
• initial (initial point)
• search (search for an interval containing a
zero)
• bisection
9-16
fzero
Iterative Display
Heading
Information Displayed
• interpolation (linear interpolation or
inverse quadratic interpolation)
Solvers
a, f(a), b, f(b)
Search points and their function values while
looking for an interval with function values of
opposite signs
fzero
9-17
9
Optimization
Output Functions
In this section...
“What Is an Output Function?” on page 9-18
“Creating and Using an Output Function” on page 9-18
“Structure of the Output Function” on page 9-20
“Example of a Nested Output Function” on page 9-20
“Fields in optimValues” on page 9-23
“States of the Algorithm” on page 9-23
“Stop Flag” on page 9-24
What Is an Output Function?
An output function is a function that an optimization function calls at each iteration of
its algorithm. Typically, you might use an output function to generate graphical output,
record the history of the data the algorithm generates, or halt the algorithm based on the
data at the current iteration. You can create an output function as a function file, a local
function, or a nested function.
You can use the OutputFcn option with the following MATLAB optimization functions:
• fminbnd
• fminsearch
• fzero
Creating and Using an Output Function
The following is a simple example of an output function that plots the points generated
by an optimization function.
function stop = outfun(x, optimValues, state)
stop = false;
hold on;
plot(x(1),x(2),'.');
drawnow
9-18
Output Functions
You can use this output function to plot the points generated by fminsearch in solving
the optimization problem
(
)
min f ( x) = min ex1 4 x12 + 2 x22 + x1 x2 + 2 x2 .
x
x
To do so,
1
2
Create a file containing the preceding code and save it as outfun.m in a directory on
the MATLAB path.
Enter the command
options = optimset('OutputFcn', @outfun);
3
to set the value of the Outputfcn field of the options structure to a function
handle to outfun.
Enter the following commands:
hold on
[email protected](x) exp(x(1))*(4*x(1)^2+2*x(2)^2+x(1)*x(2)+2*x(2));
[x fval] = fminsearch(objfun, [-1 1], options)
hold off
This returns the solution
x =
0.1290
-0.5323
fval =
-0.5689
and displays the following plot of the points generated by fminsearch:
9-19
9
Optimization
Structure of the Output Function
The function definition line of the output function has the following form:
stop = outfun(x, optimValues, state)
where
• stop is a flag that is true or false depending on whether the optimization routine
should quit or continue. See “Stop Flag” on page 9-24.
• x is the point computed by the algorithm at the current iteration.
• optimValues is a structure containing data from the current iteration. “Fields in
optimValues” on page 9-23 describes the structure in detail.
• state is the current state of the algorithm. “States of the Algorithm” on page 9-23
lists the possible values.
The optimization function passes the values of the input arguments to outfun at each
iteration.
Example of a Nested Output Function
The example in “Creating and Using an Output Function” on page 9-18 does not
require the output function to preserve data from one iteration to the next. When this
9-20
Output Functions
is the case, you can write the output function as a function file and call the optimization
function directly from the command line. However, if you want your output function to
record data from one iteration to the next, you should write a single file that does the
following:
• Contains the output function as a nested function—see “Nested Functions” in
MATLAB Programming Fundamentals for more information.
• Calls the optimization function.
In the following example, the function file also contains the objective function as a local
function, although you could also write the objective function as a separate file or as an
anonymous function.
Since the nested function has access to variables in the file that contains it, this method
enables the output function to preserve variables from one iteration to the next.
The following example uses an output function to record the points generated by
fminsearch in solving the optimization problem
(
)
min f ( x) = min ex1 4 x12 + 2 x22 + x1 x2 + 2 x2 .
x
x
The output function returns the sequence of points as a matrix called history.
To run the example, do the following steps:
1
2
Open a new file in the MATLAB Editor.
Copy and paste the following code into the file.
function [x fval history] = myproblem(x0)
history = [];
options = optimset('OutputFcn', @myoutput);
[x fval] = fminsearch(@objfun, x0,options);
function stop = myoutput(x,optimvalues,state);
stop = false;
if isequal(state,'iter')
history = [history; x];
end
end
function z = objfun(x)
9-21
9
Optimization
z = exp(x(1))*(4*x(1)^2+2*x(2)^2+x(1)*x(2)+2*x(2));
end
end
Save the file as myproblem.m in a directory on the MATLAB path.
At the MATLAB prompt, enter
3
4
[x fval history] = myproblem([-1 1]);
The function fminsearch returns x, the optimal point, and fval, the value of the
objective function at x.
x,fval
x =
0.1290
-0.5323
fval =
-0.5689
In addition, the output function myoutput returns the matrix history, which contains
the points generated by the algorithm at each iteration, to the MATLAB workspace. The
first four rows of history are
history(1:4,:)
ans =
-1.0000
-1.0000
-1.0750
-1.0125
1.0000
1.0000
0.9000
0.8500
The final row of points in history is the same as the optimal point, x.
history(end,:)
ans =
0.1290
-0.5323
objfun(history(end,:))
ans =
-0.5689
9-22
Output Functions
Fields in optimValues
The following table lists the fields of the optimValues structure that are provided by all
three optimization functions, fminbnd, fminsearch, and fzero.
The “Command-Line Display Headings” column of the table lists the headings,
corresponding to the optimValues fields that are displayed at the command line when
you set the Display parameter of options to 'iter'.
optimValues Field
(optimValues.field)
Description
Command-Line Display
Heading
funcCount
Cumulative number of
function evaluations
Func-count
fval
Function value at current
point
min f(x)
iteration
Iteration number — starts
at 0
Iteration
procedure
Procedure messages
Procedure
States of the Algorithm
The following table lists the possible values for state:
State
Description
'init'
The algorithm is in the initial state before the first
iteration.
'interrupt'
The algorithm is performing an iteration. In this
state, the output function can interrupt the current
iteration of the optimization. You might want the
output function to do this to improve the efficiency of
the computations. When state is set to 'interrupt',
the values of x and optimValues are the same as at
the last call to the output function, in which state is
set to 'iter'.
'iter'
The algorithm is at the end of an iteration.
'done'
The algorithm is in the final state after the last
iteration.
9-23
9
Optimization
The following code illustrates how the output function might use the value of state to
decide which tasks to perform at the current iteration.
switch state
case 'init'
% Setup for plots or dialog boxes
case 'iter'
% Make updates to plots or dialog boxes as needed
case 'interrupt'
% Check conditions to see whether optimization
% should quit
case 'done'
% Cleanup of plots, dialog boxes, or final plot
end
Stop Flag
The output argument stop is a flag that is true or false. The flag tells the
optimization function whether the optimization should quit or continue. The following
examples show typical ways to use the stop flag.
Stopping an Optimization Based on Data in optimValues
The output function can stop an optimization at any iteration based on the current data
in optimValues. For example, the following code sets stop to true if the objective
function value is less than 5:
function stop = myoutput(x, optimValues, state)
stop = false;
% Check if objective function is less than 5.
if optimValues.fval < 5
stop = true;
end
Stopping an Optimization Based on Dialog Box Input
If you design a UI to perform optimizations, you can make the output function stop an
optimization when a user clicks a Stop button. The following code shows how to do this,
assuming that the Stop button callback stores the value true in the optimstop field of
a handles structure called hObject stored in appdata.
function stop = myoutput(x, optimValues, state)
stop = false;
9-24
Output Functions
% Check if user has requested to stop the optimization.
stop = getappdata(hObject,'optimstop');
9-25
9
Optimization
Plot Functions
In this section...
“What Is A Plot Function?” on page 9-26
“Example: Plot Function” on page 9-26
What Is A Plot Function?
The PlotFcns field of the options structure specifies one or more functions that an
optimization function calls at each iteration to plot various measures of progress while
the algorithm executes. Pass a function handle or cell array of function handles. The
structure of a plot function is the same as the structure of an output function. For more
information on this structure, see “Output Functions” on page 9-18.
You can use the PlotFcns option with the following MATLAB optimization functions:
• fminbnd
• fminsearch
• fzero
The predefined plot functions for these optimization functions are:
• @optimplotx plots the current point
• @optimplotfval plots the function value
• @optimplotfunccount plots the function count (not available for fzero)
To view or modify a predefined plot function, open the function file in the MATLAB
Editor. For example, to view the function file for plotting the current point, enter:
edit optimplotx.m
Example: Plot Function
View the progress of a minimization using fminsearch with the plot function
@optimplotfval:
1
Write a file for the objective function. For this example, use:
function f = onehump(x)
9-26
Plot Functions
r = x(1)^2 + x(2)^2;
s = exp(-r);
f = x(1)*s+r/20;
2
Set the options to use the plot function:
options = optimset('PlotFcns',@optimplotfval);
3
Call fminsearch starting from [2,1]:
[x ffinal] = fminsearch(@onehump,[2,1],options)
4
MATLAB returns the following:
x =
-0.6691
0.0000
ffinal =
-0.4052
9-27
9
Optimization
9-28
Troubleshooting and Tips
Troubleshooting and Tips
Here is a list of typical problems and recommendations for dealing with them.
Problem
Recommendation
The solution found by fminbnd or
fminsearch does not appear to be a
global minimum.
There is no guarantee that you have a global minimum
unless your problem is continuous and has only one
minimum. Starting the optimization from a number
of different starting points (or intervals in the case of
fminbnd) may help to locate the global minimum or
verify that there is only one minimum. Use different
methods, where possible, to verify results.
Sometimes an optimization problem has Modify your function to include a penalty function to
values of x for which it is impossible to give a large positive value to f when infeasibility is
evaluate f.
encountered.
The minimization routine appears
to enter an infinite loop or returns a
solution that is not a minimum (or not a
zero in the case of fzero).
Your objective function (fun) may be returning NaN or
complex values. The optimization routines expect only
real numbers to be returned. Any other values may
cause unexpected results. To determine whether this is
the case, set
options = optimset('FunValCheck', 'on')
and call the optimization function with options as
an input argument. This displays an error when the
objective function returns NaN or complex values.
Optimization problems may take many iterations to converge. Most optimization
problems benefit from good starting guesses. Providing good starting guesses improves
the execution efficiency and may help locate the global minimum instead of a local
minimum.
Sophisticated problems are best solved by an evolutionary approach, whereby a problem
with a smaller number of independent variables is solved first. Solutions from lower
order problems can generally be used as starting points for higher order problems by
using an appropriate mapping.
The use of simpler cost functions and less stringent termination criteria in the early
stages of an optimization problem can also reduce computation time. Such an approach
often produces superior results by avoiding local minima.
9-29
9
Optimization
Reference
[1] Lagarias, J. C., J. A. Reeds, M. H. Wright, and P. E. Wright. “Convergence Properties
of the Nelder-Mead Simplex Method in Low Dimensions.” SIAM Journal of
Optimization, Vol. 9, Number 1, 1998, pp. 112–147.
9-30
10
Function Handles
10
Function Handles
Parameterizing Functions
In this section...
“Overview” on page 10-2
“Parameterizing Using Nested Functions” on page 10-2
“Parameterizing Using Anonymous Functions” on page 10-3
Overview
This topic explains how to store or access extra parameters for mathematical functions
that you pass to MATLAB function functions, such as fzero or integral.
MATLAB function functions evaluate mathematical expressions over a range of values.
They are called function functions because they are functions that accept a function
handle (a pointer to a function) as an input. Each of these functions expects that your
objective function has a specific number of input variables. For example, fzero and
integral accept handles to functions that have exactly one input variable.
Suppose you want to find the zero of the cubic polynomial x3 + bx + c for different values
of the coefficients b and c. Although you could create a function that accepts three input
variables (x, b, and c), you cannot pass a function handle that requires all three of those
inputs to fzero. However, you can take advantage of properties of anonymous or nested
functions to define values for additional inputs.
Parameterizing Using Nested Functions
One approach for defining parameters is to use a nested function—a function completely
contained within another function in a program file. For this example, create a file
named findzero.m that contains a parent function findzero and a nested function
poly:
function y = findzero(b,c,x0)
y = fzero(@poly,x0);
function y = poly(x)
y = x^3 + b*x + c;
end
10-2
Parameterizing Functions
end
The nested function defines the cubic polynomial with one input variable, x. The parent
function accepts the parameters b and c as input values. The reason to nest poly
within findzero is that nested functions share the workspace of their parent functions.
Therefore, the poly function can access the values of b and c that you pass to findzero.
To find a zero of the polynomial with b = 2 and c = 3.5, using the starting point x0 =
0, you can call findzero from the command line:
x = findzero(2,3.5,0)
x =
-1.0945
Parameterizing Using Anonymous Functions
Another approach for accessing extra parameters is to use an anonymous function.
Anonymous functions are functions that you can define in a single command, without
creating a separate program file. They can use any variables that are available in the
current workspace.
For example, create a handle to an anonymous function that describes the cubic
polynomial, and find the zero:
b = 2;
c = 3.5;
cubicpoly = @(x) x^3 + b*x + c;
x = fzero(cubicpoly,0)
x =
-1.0945
Variable cubicpoly is a function handle for an anonymous function that has one input,
x. Inputs for anonymous functions appear in parentheses immediately following the @
symbol that creates the function handle. Because b and c are in the workspace when you
create cubicpoly, the anonymous function does not require inputs for those coefficients.
You do not need to create an intermediate variable, cubicpoly, for the anonymous
function. Instead, you can include the entire definition of the function handle within the
call to fzero:
b = 2;
10-3
10
Function Handles
c = 3.5;
x = fzero(@(x) x^3 + b*x + c,0)
x =
-1.0945
You also can use anonymous functions to call more complicated objective functions that
you define in a function file. For example, suppose you have a file named cubicpoly.m
with this function definition:
function y = cubicpoly(x,b,c)
y = x^3 + b*x + c;
end
At the command line, define b and c, and then call fzero with an anonymous function
that invokes cubicpoly:
b = 2;
c = 3.5;
x = fzero(@(x) cubicpoly(x,b,c),0)
x =
-1.0945
Note: To change the values of the parameters, you must create a new anonymous
function. For example:
b = 10;
c = 25;
x = fzero(@(x) x^3 + b*x + c,0);
More About
10-4
•
“Create Function Handle”
•
“Nested Functions”
•
“Anonymous Functions”
11
Calculus
• “Ordinary Differential Equations” on page 11-2
• “Types of DDEs” on page 11-43
• “Discontinuities in DDEs” on page 11-46
• “DDE with Constant Delays” on page 11-47
• “State-Dependent Delay Problem” on page 11-50
• “Cardiovascular Model with Discontinuities” on page 11-54
• “DDE of Neutral Type” on page 11-58
• “Initial Value DDE of Neutral Type” on page 11-62
• “Boundary-Value Problems” on page 11-66
• “Partial Differential Equations” on page 11-91
• “Selected Bibliography for Differential Equations” on page 11-107
• “Integration to Find Arc Length” on page 11-108
• “Complex Line Integrals” on page 11-109
• “Singularity on Interior of Integration Domain” on page 11-112
• “Analytic Solution to Integral of Polynomial” on page 11-114
• “Integration of Numeric Data” on page 11-115
11
Calculus
Ordinary Differential Equations
In this section...
“Function Summary” on page 11-2
“Initial Value Problems” on page 11-4
“Types of Solvers” on page 11-5
“Solver Syntax” on page 11-8
“Integrator Options” on page 11-9
“Examples” on page 11-9
“Troubleshooting” on page 11-36
Function Summary
• “ODE Solvers” on page 11-2
• “Evaluation and Extension” on page 11-3
• “Solver Options” on page 11-3
• “Output Functions” on page 11-3
ODE Solvers
The following table lists the initial value problem solvers, the kind of problem you can
solve with each solver, and the method each solver uses.
11-2
Solver
Solves These Kinds of Problems
Method
ode45
Nonstiff differential equations
Runge-Kutta
ode23
Nonstiff differential equations
Runge-Kutta
ode113
Nonstiff differential equations
Adams
ode15s
Stiff differential equations and
DAEs
NDFs (BDFs)
ode23s
Stiff differential equations
Rosenbrock
ode23t
Moderately stiff differential
equations and DAEs
Trapezoidal rule
Ordinary Differential Equations
Solver
Solves These Kinds of Problems
Method
ode23tb
Stiff differential equations
TR-BDF2
ode15i
Fully implicit differential
equations
BDFs
Evaluation and Extension
You can use the following functions to evaluate and extend solutions to ODEs.
Function
Description
deval
Evaluate the numerical solution using the output of ODE
solvers.
odextend
Extend the solution of an initial value problem for an ODE
Solver Options
An options structure contains named properties whose values are passed to ODE solvers,
and which affect problem solution. Use these functions to create, alter, or access an
options structure.
Function
Description
odeset
Create or alter options structure for input to ODE
solver.
odeget
Extract properties from options structure created with
odeset.
Output Functions
If an output function is specified, the solver calls the specified function after every
successful integration step. You can use odeset to specify one of these sample functions
as the OutputFcn property, or you can modify them to create your own functions.
Function
Description
odeplot
Time-series plot
odephas2
Two-dimensional phase plane plot
11-3
11
Calculus
Function
Description
odephas3
Three-dimensional phase plane plot
odeprint
Print to command window
Initial Value Problems
• “First Order ODEs” on page 11-4
• “Higher Order ODEs” on page 11-4
• “Initial Values” on page 11-5
First Order ODEs
An ordinary differential equation (ODE) contains one or more derivatives of a dependent
variable y with respect to a single independent variable t, usually referred to as time. The
derivative of y with respect to t is denoted as y ′, the second derivative as y ′′, and so on.
Often y(t) is a vector, having elements y1, y2, ..., yn.
MATLAB solvers handle the following types of first-order ODEs:
• Explicit ODEs of the form y ′ = f (t, y)
• Linearly implicit ODEs of the form M(t, y) y ′ = f (t, y), where M(t, y) is a matrix
• Fully implicit ODEs of the form f (t, y, y′) = 0 (ode15i only)
Higher Order ODEs
MATLAB ODE solvers accept only first-order differential equations. To use the solvers
with higher-order ODEs, you must rewrite each equation as an equivalent system of
first-order differential equations of the form
y′ = f(t,y)
You can write any ordinary differential equation
y(n) = f(t,y,y′,...,y(n − 1))
as a system of first-order equations by making the substitutions
y1 = y, y2 = y′,..., yn = y(n − 1)
y1= y, y2 = y', ... , yn = y(n − 1)
The result is an equivalent system of n first-order ODEs.
11-4
Ordinary Differential Equations
y1¢ = y2
y¢2 = y3
M
y¢n = f (t, y1 , y2 ,… ,yn )
For example, you can rewrite the second-order van der Pol equation
by making the substitution
The resulting system of first-order ODEs is
Initial Values
Generally there are many functions y(t) that satisfy a given ODE, and additional
information is necessary to specify the solution of interest. In an initial value problem,
the solution of interest satisfies a specific initial condition, that is, y is equal to y0 at a
given initial time t0. An initial value problem for an ODE is then
y¢ = f ( t, y)
y ( t0 ) = y0 .
If the function f (t, y) is sufficiently smooth, this problem has one and only one
solution. Generally there is no analytic expression for the solution, so it is necessary to
approximate y(t) by numerical means.
Types of Solvers
• “Nonstiff Problems” on page 11-6
• “Stiff Problems” on page 11-6
11-5
11
Calculus
• “Fully Implicit ODEs” on page 11-7
Nonstiff Problems
There are three solvers designed for nonstiff problems:
ode45
Based on an explicit Runge-Kutta (4,5) formula, the DormandPrince pair. It is a one-step solver – in computing y(tn), it needs
only the solution at the immediately preceding time point, y(tn–1).
In general, ode45 is the best function to apply as a “first try” for
most problems.
ode23
Based on an explicit Runge-Kutta (2,3) pair of Bogacki and
Shampine. It may be more efficient than ode45 at crude
tolerances and in the presence of mild stiffness. Like ode45,
ode23 is a one-step solver.
ode113
Variable order Adams-Bashforth-Moulton PECE solver. It may
be more efficient than ode45 at stringent tolerances and when
the ODE function is particularly expensive to evaluate. ode113
is a multistep solver—it normally needs the solutions at several
preceding time points to compute the current solution.
Stiff Problems
Not all difficult problems are stiff, but all stiff problems are difficult for solvers not
specifically designed for them. Solvers for stiff problems can be used exactly like the
other solvers. However, you can often significantly improve the efficiency of these solvers
by providing them with additional information about the problem. (See “Integrator
Options” on page 11-9.)
There are four solvers designed for stiff problems:
11-6
ode15s
Variable-order solver based on the numerical differentiation
formulas (NDFs). Optionally it uses the backward differentiation
formulas, BDFs (also known as Gear's method). Like ode113,
ode15s is a multistep solver. If you suspect that a problem is stiff
or if ode45 failed or was very inefficient, try ode15s.
ode23s
Based on a modified Rosenbrock formula of order 2. Because it is
a one-step solver, it may be more efficient than ode15s at crude
tolerances. It can solve some kinds of stiff problems for which
ode15s is not effective.
Ordinary Differential Equations
ode23t
An implementation of the trapezoidal rule using a “free”
interpolant. Use this solver if the problem is only moderately stiff
and you need a solution without numerical damping.
ode23tb
An implementation of TR-BDF2, an implicit Runge-Kutta formula
with a first stage that is a trapezoidal rule step and a second
stage that is a backward differentiation formula of order 2. Like
ode23s, this solver may be more efficient than ode15s at crude
tolerances.
Fully Implicit ODEs
The solver ode15i solves fully implicit differential equations of the form
f(t,y,y') = 0
using the variable order BDF method. The basic syntax for ode15i is
[t,y] = ode15i(odefun,tspan,y0,yp0,options)
The input arguments are
odefun
A function that evaluates the left side of the differential equation of
the form f(t,y,y') = 0.
tspan
A vector specifying the interval of integration, [t0,tf]. To obtain
solutions at specific times (all increasing or all decreasing), use
tspan = [t0,t1,...,tf].
y0, yp0
Vectors of initial conditions for y(t0) and y'(t0), respectively. The
specified values must be consistent; that is, they must satisfy
f(t0,y0,yp0) = 0.
options
Optional integration argument created using the odeset function.
See the odeset reference page for details.
The output arguments contain the solution approximated at discrete points:
t
Column vector of time points
y
Solution array. Each row in y corresponds to the solution at a time
returned in the corresponding row of t.
See the ode15i reference page for more information about these arguments.
11-7
11
Calculus
Solver Syntax
All of the ODE solver functions, except for ode15i, share a syntax that makes it easy
to try any of the different numerical methods, if it is not apparent which is the most
appropriate. To apply a different method to the same problem, simply change the ODE
solver function name. The simplest syntax, common to all the solver functions, is
[t,y] = solver(odefun,tspan,y0,options)
where solver is one of the ODE solver functions listed previously.
The basic input arguments are
odefun
function handle that evaluates the system of ODEs. The
function has the form
dydt = odefun(t,y)
where t is a scalar, and dydt and y are column vectors.
tspan
Vector specifying the interval of integration. The solver
imposes the initial conditions at tspan(1), and integrates
from tspan(1) to tspan(end).
y0
Vector of initial conditions for the problem
See also “Initial Value Problems” on page 11-4.
options
Structure of optional parameters that change the default
integration properties.
“Integrator Options” on page 11-9 tells you how to create
the structure and describes the properties you can specify.
The output arguments contain the solution approximated at discrete points:
t
Column vector of time points
y
Solution array. Each row in y corresponds to the solution at a
time returned in the corresponding row of t.
See the reference page for the ODE solvers for more information about these arguments.
11-8
Ordinary Differential Equations
Integrator Options
The default integration properties in the ODE solvers are selected to handle common
problems. In some cases, you can improve ODE solver performance by overriding these
defaults. You do this by supplying the solvers with an options structure that specifies
one or more property values.
For example, to change the value of the relative error tolerance of the solver from the
default value of 1e-3 to 1e-4,
1
Create an options structure using the function odeset by entering
options = odeset('RelTol', 1e-4);
2
Pass the options structure to the solver as follows:
• For all solvers except ode15i, use the syntax
[t,y] = solver(odefun,tspan,y0,options)
• For ode15i, use the syntax
[t,y] = ode15i(odefun,tspan,y0,yp0,options)
For a complete description of the available options, see the reference page for odeset.
Examples
• “van der Pol Equation (Nonstiff)” on page 11-10
• “van der Pol Equation (Stiff)” on page 11-12
• “van der Pol Equation (Parameterizing the ODE)” on page 11-13
• “van der Pol Equation (Evaluating the Solution)” on page 11-14
• “Euler Equations (Nonstiff)” on page 11-15
• “Fully Implicit ODE” on page 11-16
• “Finite Element Discretization” on page 11-17
• “Large Stiff Sparse Problem” on page 11-20
• “Event Location” on page 11-23
• “Advanced Event Location” on page 11-26
• “Differential-Algebraic Equations” on page 11-29
• “Nonnegative Solutions” on page 11-31
• “Additional Examples” on page 11-35
11-9
11
Calculus
van der Pol Equation (Nonstiff)
This example illustrates the steps for solving an initial value ODE problem:
1
Rewrite the problem as a system of first-order ODEs. Rewrite the van der Pol
equation (second-order)
(
)
y1¢¢ - m 1 - y12 y1¢ + y1 = 0,
where μ > 0 is a scalar parameter, by making the substitution y'1 = y2. The resulting
system of first-order ODEs is
y1¢ = y2
y¢2 = m 1 - y12 y2 - y1 .
(
2
)
Code the system of first-order ODEs. Once you represent the equation as a
system of first-order ODEs, you can code it as a function that an ODE solver can use.
The function must be of the form
dydt = odefun(t,y)
Although t and y must be the function's two arguments, the function does not need
to use them. The output dydt, a column vector, is the derivative of y.
The code below represents the van der Pol system in the function, vdp1. The vdp1
function assumes that μ = 1. The variables y1 and y2 are the entries y(1) and y(2)
of a two-element vector.
function dydt = vdp1(t,y)
dydt = [y(2); (1-y(1)^2)*y(2)-y(1)];
3
Note that, although vdp1 must accept the arguments t and y, it does not use t in its
computations.
Apply a solver to the problem.
Decide which solver you want to use to solve the problem. Then call the solver and
pass it the function you created to describe the first-order system of ODEs, the time
interval on which you want to solve the problem, and an initial condition vector.
11-10
For the van der Pol system, you can use ode45 on time interval [0 20] with initial
values y(1) = 2 and y(2) = 0.
Ordinary Differential Equations
[t,y] = ode45(@vdp1,[0 20],[2; 0]);
This example uses @ to pass vdp1 as a function handle to ode45. The resulting
output is a column vector of time points t and a solution array y. Each row in y
corresponds to a time returned in the corresponding row of t. The first column of y
corresponds to y1, and the second column to y2.
4
Note: See “Function Handles” for information on function handles.
View the solver output. You can simply use the plot command to view the solver
output.
plot(t,y(:,1),'-',t,y(:,2),'--')
title('Solution of van der Pol Equation, \mu = 1');
xlabel('time t');
ylabel('solution y');
legend('y_1','y_2')
As an alternative, you can use a solver output function to process the output. The solver
calls the function specified in the integration property OutputFcn after each successful
11-11
11
Calculus
time step. Use odeset to set OutputFcn to the desired function. See Solver Output
Properties, in the reference page for odeset, for more information about OutputFcn.
van der Pol Equation (Stiff)
This example presents a stiff problem. For a stiff problem, solutions can change on a
time scale that is very short compared to the interval of integration, but the solution of
interest changes on a much longer time scale. Methods not designed for stiff problems are
ineffective on intervals where the solution changes slowly because they use time steps
small enough to resolve the fastest possible change.
When μ is increased to 1000, the solution to the van der Pol equation changes
dramatically and exhibits oscillation on a much longer time scale. Approximating
the solution of the initial value problem becomes a more difficult task. Because this
particular problem is stiff, a solver intended for nonstiff problems, such as ode45, is too
inefficient to be practical. A solver such as ode15s is intended for such stiff problems.
The vdp1000 function evaluates the van der Pol system from the previous example, but
with μ = 1000.
function dydt = vdp1000(t,y)
dydt = [y(2); 1000*(1-y(1)^2)*y(2)-y(1)];
Note: This example hardcodes μ in the ODE function. The vdpode example solves the
same problem, but passes a user-specified μ as a parameter to the ODE function.
Now use the ode15s function to solve the problem with the initial condition vector of [2;
0], but a time interval of [0 3000]. For scaling reasons, plot just the first component of
y(t).
[t,y] = ode15s(@vdp1000,[0 3000],[2; 0]);
plot(t,y(:,1),'-');
title('Solution of van der Pol Equation, \mu = 1000');
xlabel('time t');
ylabel('solution y_1');
11-12
Ordinary Differential Equations
van der Pol Equation (Parameterizing the ODE)
The preceding sections showed how to solve the van der Pol equation for two different
values of the parameter µ. In those examples, the values µ = 1 and µ=1000 are hardcoded in the ODE functions. If you are solving an ODE for several different parameter
values, it might be more convenient to include the parameter in the ODE function and
assign a value to the parameter each time you run the ODE solver. This section explains
how to do this for the van der Pol equation.
One way to provide parameter values to the ODE function is to write a MATLAB file that
• Accepts the parameters as inputs.
• Contains ODE function as a nested function, internally using the input parameters.
• Calls the ODE solver.
The following code illustrates this:
function [t,y] = solve_vdp(mu)
tspan = [0 max(20, 3*mu)];
y0 = [2; 0];
11-13
11
Calculus
% Call the ODE solver ode15s.
[t,y] = ode15s(@vdp,tspan,y0);
% Define the ODE function as nested function,
% using the parameter mu.
function dydt = vdp(t,y)
dydt = [y(2); mu*(1-y(1)^2)*y(2)-y(1)];
end
end
Because the ODE function vdp is a nested function, the value of the parameter mu is
available to it.
To run the MATLAB file for mu = 1, enter
[t,y] = solve_vdp(1);
To run the code for µ = 1000, enter
[t,y] = solve_vdp(1000);
See the vdpode code for a complete example based on these functions.
van der Pol Equation (Evaluating the Solution)
The numerical methods implemented in the ODE solvers produce a continuous solution
over the interval of integration [a,b]. You can evaluate the approximate solution, S(x), at
any point in [a,b] using the function deval and the structure sol returned by the solver.
For example, if you solve the problem described in “van der Pol Equation (Nonstiff)” on
page 11-10 by calling ode45 with a single output argument sol,
sol = ode45(@vdp1,[0 20],[2; 0]);
ode45 returns the solution as a structure. You can then evaluate the approximate
solution at points in the vector xint = 1:5 as follows:
xint = 1:5;
Sxint = deval(sol,xint)
Sxint =
1.5081
-0.7803
11-14
0.3235
-1.8320
-1.8686
-1.0220
-1.7407
0.6260
-0.8344
1.3095
Ordinary Differential Equations
The deval function is vectorized. For a vector xint, the ith column of Sxint
approximates the solution y(xint(i)).
Euler Equations (Nonstiff)
rigidode illustrates the solution of a standard test problem proposed by Krogh for
solvers intended for nonstiff problems [8].
The ODEs are the Euler equations of a rigid body without external forces.
y1¢ = y2 y3
y¢2 = - y1 y3
y3¢ = -0 .51 y1 y2 .
For your convenience, the entire problem is defined and solved in a single MATLAB file.
The differential equations are coded as the local function f. Because the example calls
the ode45 solver without output arguments, the solver uses the default output function
odeplot to plot the solution components.
To run this example, type rigidode at the command line.
function rigidode
%RIGIDODE Euler equations: rigid body without external forces
tspan = [0 12];
y0 = [0; 1; 1];
% Solve the problem using ode45
ode45(@f,tspan,y0);
% -----------------------------------------------------------function dydt = f(t,y)
dydt = [ y(2)*y(3)
-y(1)*y(3)
-0.51*y(1)*y(2) ];
11-15
11
Calculus
Fully Implicit ODE
The following example shows how to use the function ode15i to solve the implicit ODE
problem defined by Weissinger's equation
ty2(y')3 – y3(y')2 + t(t2 + 1)y' – t2y = 0
with the initial value y(1) = (3/2)1/2. The exact solution of the ODE is
y(t) = (t2 + 0.5)1/2
The example uses the function weissinger, which is provided with MATLAB, to
compute the left-hand side of the equation.
Before calling ode15i, the example uses a helper function decic to compute a consistent
initial value for y'(t0). In the following call, the given initial value y(1) = (3/2)1/2 is held
fixed and a guess of 0 is specified for y'(1). See the reference page for decic for more
information.
t0 = 1;
y0 = sqrt(3/2);
yp0 = 0;
[y0,yp0] = decic(@weissinger,t0,y0,1,yp0,0);
You can now call ode15i to solve the ODE and then plot the numerical solution against
the analytical solution with the following commands.
[t,y] = ode15i(@weissinger,[1 10],y0,yp0);
11-16
Ordinary Differential Equations
ytrue = sqrt(t.^2 + 0.5);
plot(t,y,t,ytrue,'o');
Finite Element Discretization
fem1ode illustrates the solution of ODEs that result from a finite element discretization
of a partial differential equation. The value of N in the call fem1ode(N) controls the
discretization, and the resulting system consists of N equations. By default, N is 19.
This example involves a mass matrix. The system of ODEs comes from a method of lines
solution of the partial differential equation
e- t
∂u ∂2 u
=
∂t ∂ x2
with initial condition
u(0,x) = sin(x)
and boundary conditions
u(t,0) = u(t,π) = 0.
An integer N is chosen, h is defined as π/(N + 1), and the solution of the partial
differential equation is approximated at xk = kh for k = 0, 1, ..., N+1 by
11-17
11
Calculus
N
u ( t, xk ) =
 ck (t)fk (x).
k=1
Here ϕk(x) is a piecewise linear function that is 1 atxk and 0 at all the otherxj. A Galerkin
discretization leads to the system of ODEs
È c1 ( t) ˘
M ( t) c¢ = Jc, where c( t) = ÍÍ M ˙˙
ÍÎ cN ( t) ˙˚
and the tridiagonal matrices M(t) and J are given by
Ï 2 h -t
Ô 3 e
Ô
h
M i, j = Ì e-t
Ô6
Ô
Ó0
if i = j
if i = j ± 1
otherwise.
and
Ï -2
Ôh
Ô
1
Ji , j = Ì
Ôh
Ô
Ó0
if i = j
if i = j ± 1
otherwise.
The initial values c(0) are taken from the initial condition for the partial differential
equation. The problem is solved on the time interval [0,π].
In the fem1ode example, the properties
options = odeset('Mass',@mass,'MStateDep','none','Jacobian',J)
indicate that the problem is of the form M(t)y' = Jy. The nested function mass(t)
evaluates the time-dependent mass matrix M(t) and J is the constant Jacobian.
11-18
Ordinary Differential Equations
To run this example, type fem1ode at the command line. From the command line, you
can specify a value of N as an argument to fem1ode. The default is N = 19.
function fem1ode(N)
%FEM1ODE Stiff problem with a time-dependent mass matrix
if nargin < 1
N = 19;
end
h = pi/(N+1);
y0 = sin(h*(1:N)');
tspan = [0; pi];
%
e
d
%
J
The Jacobian is constant.
= repmat(1/h,N,1);
% e=[(1/h) ... (1/h)];
= repmat(-2/h,N,1);
% d=[(-2/h) ... (-2/h)];
J is shared with the derivative function.
= spdiags([e d e], -1:1, N, N);
d = repmat(h/6,N,1);
% M is shared with the mass matrix function.
M = spdiags([d 4*d d], -1:1, N, N);
options = odeset('Mass',@mass,'MStateDep','none', ...
'Jacobian',J);
[t,y] = ode15s(@f,tspan,y0,options);
figure;
surf((1:N)/(N+1),t,y);
set(gca,'ZLim',[0 1]);
view(142.5,30);
title(['Finite element problem with time-dependent mass ' ...
'matrix, solved by ODE15S']);
xlabel('space ( x/\pi )');
ylabel('time');
zlabel('solution');
%-------------------------------------------------------------function yp = f(t,y)
% Derivative function.
yp = J*y;
% Constant Jacobian provided by outer function
end
% End nested function f
%-------------------------------------------------------------function Mt = mass(t)
11-19
11
Calculus
% Mass matrix function.
Mt = exp(-t)*M;
% M is provided by outer function
end
% End nested function mass
%-------------------------------------------------------------end
Large Stiff Sparse Problem
brussode illustrates the solution of a potentially large stiff sparse problem. The problem
is the classic “Brusselator“ system [3] that models diffusion in a chemical reaction
2
ui¢ = 1 + ui2vi - 4 ui + a ( N + 1 )
vi¢ = 3ui - ui2vi + a ( N + 1)
2
( ui-1 - 2ui + ui+1 )
( vi-1 - 2vi + vi+1 ) .
and is solved on the time interval [0,10] with α = 1/50 and
ui(0) = 1 + sin(2πxi)
vi(0) = 3
where, for i = 1,...,N, xi = i/(N + 1). There are 2N equations in the system, but the
Jacobian is banded with a constant width 5 if the equations are ordered as u1, v1, u2,
v2, ...
11-20
Ordinary Differential Equations
In the call brussode(N), where N corresponds to N, the parameter N ≥ 2 specifies the
number of grid points. The resulting system consists of 2N equations. By default, N is
20. The problem becomes increasingly stiff and the Jacobian increasingly sparse as N
increases.
The nested function f(t,y) returns the derivatives vector for the Brusselator problem.
The local functionjpattern(N) returns a sparse matrix of 1s and 0s showing the
locations of nonzeros in the Jacobian ∂f/∂y. The example assigns this matrix to the
property JPattern, and the solver uses the sparsity pattern to generate the Jacobian
numerically as a sparse matrix. Providing a sparsity pattern can significantly reduce
the number of function evaluations required to generate the Jacobian and can accelerate
integration.
For the Brusselator problem, if the sparsity pattern is not supplied, 2N evaluations of the
function are needed to compute the 2N-by-2N Jacobian matrix. If the sparsity pattern is
supplied, only four evaluations are needed, regardless of the value of N.
To run this example, type brussode at the command line. From the command line, you
can specify a value of N as an argument to brussode. The default is N = 20.
function brussode(N)
%BRUSSODE Stiff problem modeling a chemical reaction
if nargin < 1
N = 20;
end
tspan = [0; 10];
y0 = [1+sin((2*pi/(N+1))*(1:N));
repmat(3,1,N)];
options = odeset('Vectorized','on','JPattern',jpattern(N));
[t,y] = ode15s(@f,tspan,y0,options);
u = y(:,1:2:end);
x = (1:N)/(N+1);
surf(x,t,u);
view(-40,30);
xlabel('space');
ylabel('time');
zlabel('solution u');
title(['The Brusselator for N = ' num2str(N)]);
11-21
11
Calculus
% -------------------------------------------------------------function dydt = f(t,y)
c = 0.02 * (N+1)^2;
dydt = zeros(2*N,size(y,2));
% preallocate dy/dt
% Evaluate the two components of the function at one edge of
% the grid (with edge conditions).
i = 1;
dydt(i,:) = 1 + y(i+1,:).*y(i,:).^2 - 4*y(i,:) + ...
c*(1-2*y(i,:)+y(i+2,:));
dydt(i+1,:) = 3*y(i,:) - y(i+1,:).*y(i,:).^2 + ...
c*(3-2*y(i+1,:)+y(i+3,:));
% Evaluate the two components of the function at all interior
% grid points.
i = 3:2:2*N-3;
dydt(i,:) = 1 + y(i+1,:).*y(i,:).^2 - 4*y(i,:) + ...
c*(y(i-2,:)-2*y(i,:)+y(i+2,:));
dydt(i+1,:) = 3*y(i,:) - y(i+1,:).*y(i,:).^2 + ...
c*(y(i-1,:)-2*y(i+1,:)+y(i+3,:));
% Evaluate the two components of the function at the other edge
% of the grid (with edge conditions).
i = 2*N-1;
dydt(i,:) = 1 + y(i+1,:).*y(i,:).^2 - 4*y(i,:) + ...
c*(y(i-2,:)-2*y(i,:)+1);
dydt(i+1,:) = 3*y(i,:) - y(i+1,:).*y(i,:).^2 + ...
c*(y(i-1,:)-2*y(i+1,:)+3);
end
% End nested function f
end
% End function brussode
% -------------------------------------------------------------function S = jpattern(N)
B = ones(2*N,5);
B(2:2:2*N,2) = zeros(N,1);
B(1:2:2*N-1,4) = zeros(N,1);
S = spdiags(B,-2:2,2*N,2*N);
end;
11-22
Ordinary Differential Equations
Event Location
ballode models the motion of a bouncing ball. This example illustrates the event
location capabilities of the ODE solvers.
The equations for the bouncing ball are:
y'1 = y2
y'2 = –9.8
In this example, the event function is coded in the local functionevents
[value,isterminal,direction] = events(t,y)
which returns
• A value of the event function
• The information whether or not the integration should stop when value = 0
(isterminal = 1 or 0, respectively)
• The desired directionality of the zero crossings:
-1
Detect zero crossings in the negative direction only
0
Detect all zero crossings
1
Detect zero crossings in the positive direction only
11-23
11
Calculus
The length of value, isterminal, and direction is the same as the number of event
functions. The ith element of each vector, corresponds to the ith event function. For an
example of more advanced event location, see orbitode (“Advanced Event Location” on
page 11-26).
In ballode, setting the Events property to @events causes the solver to stop the
integration (isterminal = 1) when the ball hits the ground (the height y(1) is 0)
during its fall (direction = -1). The example then restarts the integration with initial
conditions corresponding to a ball that bounced.
To run this example, type ballode at the command line.
function ballode
tstart = 0;
tfinal = 30;
y0 = [0; 20];
refine = 4;
options = odeset('Events',@events,'OutputFcn', @odeplot,...
'OutputSel',1,'Refine',refine);
set(gca,'xlim',[0 30],'ylim',[0 25]);
box on
hold on;
tout = tstart;
yout = y0.';
teout = [];
yeout = [];
ieout = [];
for i = 1:10
% Solve until the first terminal event.
[t,y,te,ye,ie] = ode23(@f,[tstart tfinal],y0,options);
if ~ishold
hold on
end
% Accumulate output.
nt = length(t);
tout = [tout; t(2:nt)];
yout = [yout; y(2:nt,:)];
teout = [teout; te];
% Events at tstart are never reported.
yeout = [yeout; ye];
ieout = [ieout; ie];
11-24
Ordinary Differential Equations
ud = get(gcf,'UserData');
if ud.stop
break;
end
% Set the new initial conditions, with .9 attenuation.
y0(1) = 0;
y0(2) = -.9*y(nt,2);
% A good guess of a valid first time step is the length of
% the last valid time step, so use it for faster computation.
options = odeset(options,'InitialStep',t(nt)-t(nt-refine),...
'MaxStep',t(nt)-t(1));
tstart = t(nt);
end
plot(teout,yeout(:,1),'ro')
xlabel('time');
ylabel('height');
title('Ball trajectory and the events');
hold off
odeplot([],[],'done');
% -------------------------------------------------------------function dydt = f(t,y)
dydt = [y(2); -9.8];
% -------------------------------------------------------------function [value,isterminal,direction] = events(t,y)
% Locate the time when height passes through zero in a
% decreasing direction and stop integration.
value = y(1);
% Detect height = 0
isterminal = 1;
% Stop the integration
direction = -1;
% Negative direction only
11-25
11
Calculus
Advanced Event Location
orbitode illustrates the solution of a standard test problem for those solvers that are
intended for nonstiff problems. It traces the path of a spaceship traveling around the
moon and returning to the earth (Shampine and Gordon [8], p. 246).
The orbitode problem is a system of the following four equations:
y1¢ = y3
y2¢ = y4
y3¢ = 2 y4 + y1 -
m * ( y1 + m )
y¢4 = - 2 y3 + y2 -
where
11-26
r13
m * y2
r13
-
-
m y2
r23
m ( y1 - m *)
r23
.
Ordinary Differential Equations
1
82.45
m* = 1 - m
m=
2
+ y22
r1 =
( y1 + m )
r2 =
( y1 - m *)2 + y22 .
The first two solution components are coordinates of the body of infinitesimal mass,
so plotting one against the other gives the orbit of the body. The initial conditions
have been chosen to make the orbit periodic. The value of μ corresponds to a spaceship
traveling around the moon and the earth. Moderately stringent tolerances are necessary
to reproduce the qualitative behavior of the orbit. Suitable values are 1e-5 for RelTol
and 1e-4 for AbsTol.
The nested events function includes event functions that locate the point of maximum
distance from the starting point and the time the spaceship returns to the starting point.
Note that the events are located accurately, even though the step sizes used by the
integrator are not determined by the location of the events. In this example, the ability to
specify the direction of the zero crossing is critical. Both the point of return to the initial
point and the point of maximum distance have the same event function value, and the
direction of the crossing is used to distinguish them.
To run this example, type orbitode at the command line. The example uses the output
function odephas2 to produce the two-dimensional phase plane plot and let you to see the
progress of the integration.
function orbitode
%ORBITODE Restricted three-body problem
mu = 1 / 82.45;
mustar = 1 - mu;
y0 = [1.2; 0; 0; -1.04935750983031990726];
tspan = [0 7];
options = odeset('RelTol',1e-5,'AbsTol',1e-4,...
'OutputFcn',@odephas2,'Events',@events);
[t,y,te,ye,ie] = ode45(@f,tspan,y0,options);
plot(y(:,1),y(:,2),ye(:,1),ye(:,2),'o');
title ('Restricted three body problem')
11-27
11
Calculus
ylabel ('y(t)')
xlabel ('x(t)')
% -------------------------------------------------------------function dydt = f(t,y)
r13 = ((y(1) + mu)^2 + y(2)^2) ^ 1.5;
r23 = ((y(1) - mustar)^2 + y(2)^2) ^ 1.5;
dydt = [ y(3)
y(4)
2*y(4) + y(1) - mustar*((y(1)+mu)/r13) - ...
mu*((y(1)-mustar)/r23)
-2*y(3) + y(2) - mustar*(y(2)/r13) - mu*(y(2)/r23) ];
end
% End nested function f
% -------------------------------------------------------------function [value,isterminal,direction] = events(t,y)
% Locate the time when the object returns closest to the
% initial point y0 and starts to move away; stop integration.
% Also locate the time when the object is farthest from the
% initial point y0 and starts to move closer.
%
% The current distance of the body is
%
%
DSQ = (y(1)-y0(1))^2 + (y(2)-y0(2))^2
%
= <y(1:2)-y0(1:2),y(1:2)-y0(1:2)>
%
% A local minimum of DSQ occurs when d/dt DSQ crosses zero
% heading in the positive direction. Compute d(DSQ)/dt as
%
% d(DSQ)/dt = 2*(y(1:2)-y0(1:2))'*dy(1:2)/dt = ...
%
2*(y(1:2)-y0(1:2))'*y(3:4)
%
dDSQdt = 2 * ((y(1:2)-y0(1:2))' * y(3:4));
value = [dDSQdt; dDSQdt];
isterminal = [1; 0];
% Stop at local minimum
direction = [1; -1];
% [local minimum, local maximum]
end
% End nested function events
end
11-28
Ordinary Differential Equations
Differential-Algebraic Equations
hb1dae reformulates the hb1ode example as a differential-algebraic equation (DAE)
problem. The Robertson problem coded in hb1ode is a classic test problem for codes that
solve stiff ODEs.
y1¢ = -0 .04 y1 + 10 4 y2 y3
y¢2 = 0.04 y1 - 104 y2 y3 - 3 ◊ 107 y22
y¢3 = 3 ◊ 107 y22 .
Note: The Robertson problem appears as an example in the prolog to LSODI [4].
In hb1ode, the problem is solved with initial conditions y1(0) = 1, y2(0) = 0, y3(0) = 0 to
steady state. These differential equations satisfy a linear conservation law that is used to
reformulate the problem as the DAE
11-29
11
Calculus
y1¢ = -0 .04 y1 + 10 4 y2 y3
y¢2 = 0.04 y1 - 104 y2 y3 - 3 ◊ 107 y22
0 = y1 + y2 + y3 - 1 .
These equations do not have a solution for y(0) with components that do not sum to 1.
The problem has the form of My' = f(t,y) with
È1 0 0 ˘
M = ÍÍ0 1 0 ˙˙ .
ÍÎ0 0 0 ˙˚
M is singular, but hb1dae does not inform the solver of this. The solver must recognize
that the problem is a DAE, not an ODE. Similarly, although consistent initial conditions
are obvious, the example uses an inconsistent value y3(0) = 10–3 to illustrate computation
of consistent initial conditions.
To run this example, type hb1dae at the command line. Note that hb1dae
• Imposes a much smaller absolute error tolerance on y2 than on the other components.
This is because y2 is much smaller than the other components and its major change
takes place in a relatively short time.
• Specifies additional points at which the solution is computed to more clearly show the
behavior of y2.
• Multiplies y2 by 104 to make y2 visible when plotting it with the rest of the solution.
• Uses a logarithmic scale to plot the solution on the long time interval.
function hb1dae
%HB1DAE Stiff differential-algebraic equation (DAE)
% A constant, singular mass matrix
M = [1 0 0
0 1 0
0 0 0];
% Use inconsistent initial condition to test initialization.
y0 = [1; 0; 1e-3];
tspan = [0 4*logspace(-6,6)];
% Use the LSODI example tolerances.'MassSingular' is left
11-30
Ordinary Differential Equations
% at its default 'maybe' to test the automatic detection
% of a DAE.
options = odeset('Mass',M,'RelTol',1e-4,...
'AbsTol',[1e-6 1e-10 1e-6],...
'Vectorized','on');
[t,y] = ode15s(@f,tspan,y0,options);
y(:,2) = 1e4*y(:,2);
semilogx(t,y);
ylabel('1e4 * y(:,2)');
title(['Robertson DAE problem with a Conservation Law, '...
'solved by ODE15S']);
xlabel('This is equivalent to the stiff ODEs in HB1ODE.');
% -------------------------------------------------------function out = f(t,y)
out = [ -0.04*y(1,:) + 1e4*y(2,:).*y(3,:)
0.04*y(1,:) - 1e4*y(2,:).*y(3,:) - 3e7*y(2,:).^2
y(1,:) + y(2,:) + y(3,:) - 1 ];
Nonnegative Solutions
If certain components of the solution must be nonnegative, use odeset to set the
NonNegative property for the indices of these components.
11-31
11
Calculus
Note: This option is not available for ode23s, ode15i, or for implicit solvers (ode15s,
ode23t, ode23tb) applied to problems where there is a mass matrix.
Imposing nonnegativity is not always a trivial task. We suggest that you use this option
only when necessary, for example in instances in which the application of a solution or
integration will fail otherwise.
Consider the following initial value problem solved on the interval [0, 40]:
y' = - |y|, y(0) = 1
The solution of this problem decays to zero. If a solver produces a negative approximate
solution, it begins to track the solution of the ODE through this value, the solution
goes off to minus infinity, and the computation fails. Using the NonNegative property
prevents this from happening.
In this example, the first call to ode45 uses the defaults for the solver parameters:
ode = @(t,y) -abs(y);
[t0,y0] = ode45(ode,[0, 40], 1);
The second uses options to impose nonnegativity conditions:
options = odeset('NonNegative',1);
[t1,y1] = ode45(ode,[0, 40], 1, options);
This plot compares the numerical solution to the exact solution.
11-32
Ordinary Differential Equations
Here is a more complete view of the code used to obtain this plot:
ode = @(t,y) -abs(y);
options = odeset('Refine',1);
[t0,y0] = ode45(ode,[0, 40], 1,options);
options = odeset(options,'NonNegative',1);
[t1,y1] = ode45(ode,[0, 40], 1, options);
t = linspace(0,40,1000);
y = exp(-t);
plot(t,y,'b-',t0,y0,'ro',t1,y1,'b*');
legend('Exact solution','No constraints','Nonnegativity', ...
'Location','SouthWest')
The kneeode Example
The kneeode example solves the “knee problem” by imposing a nonnegativity constraint
on the numerical solution. The initial value problem is
ε*y' = (1-x)*y - y^2,
y(0) = 1
11-33
11
Calculus
For 0 < ε < 1, the solution of this problem approaches null isoclines y = 1 - x and
y = 0 for x < 1 and x > 1, respectively. The numerical solution, when computed with
default tolerances, follows the y = 1 - x isocline for the whole interval of integration.
Imposing nonnegativity constraints results in the correct solution.
Here is the code that makes up the kneeode example:
function kneeode
%KNEEODE The "knee problem" with Nonnegativity constraints.
% Problem parameter
epsilon = 1e-6;
y0 = 1;
xspan = [0, 2];
% Solve without imposing constraints
options = [];
[x1,y1] = ode15s(@odefcn,xspan,y0,options);
% Impose nonnegativity constraint
options = odeset('NonNegative',1);
[x2,y2] = ode15s(@odefcn,xspan,y0,options);
figure
plot(x1,y1,'b.-',x2,y2,'g-')
axis([0,2,-1,1]);
title('The "knee problem"');
legend('No constraints','nonnegativity')
xlabel('x');
ylabel('solution y')
function yp = odefcn(x,y)
yp = ((1 - x)*y - y^2)/epsilon;
end
end % kneeode
The derivative function is defined within nested function odefcn. The value of epsilon
used in odefcn is obtained from the outer function:
function yp = odefcn(x,y)
yp = ((1 - x)*y - y^2)/epsilon;
end
11-34
Ordinary Differential Equations
The example solves the problem using the ode15s function, first with the default
options, and then by imposing a nonnegativity constraint. To run the example, type
kneeode at the MATLAB command prompt.
Here is the output plot. The plot confirms correct solution behavior after imposing
constraints.
Additional Examples
The following additional examples are available. Type
edit examplename
to view the code and
examplename
to run the example.
11-35
11
Calculus
Example Name
Description
amp1dae
Stiff DAE — electrical circuit
ballode
Simple event location — bouncing ball
batonode
ODE with time- and state-dependent mass matrix —
motion of a baton
brussode
Stiff large problem — diffusion in a chemical reaction
(the Brusselator)
burgersode
ODE with strongly state-dependent mass matrix
— Burgers' equation solved using a moving mesh
technique
fem1ode
Stiff problem with a time-dependent mass matrix —
finite element method
fem2ode
Stiff problem with a constant mass matrix — finite
element method
hb1ode
Stiff ODE problem solved on a very long interval —
Robertson chemical reaction
hb1dae
Robertson problem — stiff, linearly implicit DAE from
a conservation law
ihb1dae
Robertson problem — stiff, fully implicit DAE
iburgersode
Burgers' equation solved as implicit ODE system
kneeode
The “knee problem” with nonnegativity constraints
orbitode
Advanced event location — restricted three body
problem
rigidode
Nonstiff problem — Euler equations of a rigid body
without external forces
vdpode
Parameterizable van der Pol equation (stiff for large μ)
Troubleshooting
• General Questions
• Memory and Computational Efficiency
• Time Steps for Integration
• Error Tolerance and Other Options
11-36
Ordinary Differential Equations
• Other Types of Equations
• Other Common Problems
General Questions
Question
Answer
How do the ODE solvers differ from integral? integral solves problems of the form y' = f(t).
The ODE solvers handle more general problems
y' = f(t,y), linearly implicit problems that involve
a mass matrix M(t,y)y' = f(t,y), and fully implicit
problems f(t,y,y') = 0.
Can I solve ODE systems in which there are
more equations than unknowns, or vice versa?
No.
Memory and Computational Efficiency
Question
Answer
How large a problem can I solve with the ODE
suite?
The primary constraints are memory and
time. At each time step, the solvers for
nonstiff problems allocate vectors of length
n, where n is the number of equations in the
system. The solvers for stiff problems allocate
vectors of length n but also allocate an n-by-n
Jacobian matrix. For these solvers it may be
advantageous to use the sparse option.
If the problem is nonstiff, or if you are using
the sparse option, it may be possible to solve
a problem with thousands of unknowns. In
this case, however, storage of the result can be
problematic. Try asking the solver to evaluate
the solution at specific points only, or call the
solver with no output arguments and use an
output function to monitor the solution.
I'm solving a very large system, but only care
about a couple of the components of y. Is there
any way to avoid storing all of the elements?
Yes. The user-installable output function
capability is designed specifically for this
purpose. When you call the solver with
no output arguments, the solver does
not allocate storage to hold the entire
solution history. Instead, the solver calls
11-37
11
Calculus
Question
Answer
OutputFcn(t,y,flag) at each time step. To
keep the history of specific elements, write an
output function that stores or plots only the
elements you care about.
What is the startup cost of the integration and
how can I reduce it?
The biggest startup cost occurs as the solver
attempts to find a step size appropriate to the
scale of the problem. If you happen to know an
appropriate step size, use the InitialStep
property. For example, if you repeatedly call the
integrator in an event location loop, the last step
that was taken before the event is probably on
scale for the next integration. See ballode for an
example.
Time Steps for Integration
Question
Answer
The first step size that the integrator takes is
too large, and it misses important behavior.
You can specify the first step size with the
InitialStep property. The integrator tries this
value, then reduces it if necessary.
Can I integrate with fixed step sizes?
No.
Error Tolerance and Other Options
Question
Answer
How do I choose RelTol and AbsTol?
RelTol, the relative accuracy tolerance, controls
the number of correct digits in the answer.
AbsTol, the absolute error tolerance, controls
the difference between the answer and the
solution. At each step, the error e in component
i of the solution satisfies
|e(i)|
≤max(RelTol*abs(y(i)),AbsTol(i))
Roughly speaking, this means that you
want RelTol correct digits in all solution
components except those smaller than
11-38
Ordinary Differential Equations
Question
Answer
thresholds AbsTol(i). Even if you are not
interested in a component y(i) when it is
small, you may have to specify AbsTol(i) small
enough to get some correct digits in y(i) so that
you can accurately compute more interesting
components.
I want answers that are correct to the precision
of the computer. Why can't I simply set RelTol
to eps?
You can get close to machine precision, but not
that close. The solvers do not allow RelTol
near eps because they try to approximate a
continuous function. At tolerances comparable to
eps, the machine arithmetic causes all functions
to look discontinuous.
How do I tell the solver that I don't care about
getting an accurate answer for one of the
solution components?
You can increase the absolute error tolerance
corresponding to this solution component. If the
tolerance is bigger than the component, this
specifies no correct digits for the component.
The solver may have to get some correct digits
in this component to compute other components
accurately, but it generally handles this
automatically.
Other Types of Equations
Question
Answer
Can the solvers handle partial differential
equations (PDEs) that have been discretized by
the method of lines?
Yes, because the discretization produces
a system of ODEs. Depending on the
discretization, you might have a form involving
mass matrices – the ODE solvers provide for
this. Often the system is stiff. This is to be
expected when the PDE is parabolic and when
there are phenomena that happen on very
different time scales such as a chemical reaction
in a fluid flow. In such cases, use one of the four
solvers: ode15s, ode23s, ode23t, ode23tb.
If there are many equations, set the JPattern
property. This might make the difference
between success and failure due to the
11-39
11
Calculus
Question
Answer
computation being too expensive. For an
example that uses JPattern, see “Large Stiff
Sparse Problem” on page 11-20. When the
system is not stiff, or not very stiff, ode23 or
ode45 is more efficient than ode15s, ode23s,
ode23t, or ode23tb.
Parabolic-elliptic partial differential equations
in 1-D can be solved directly with the MATLAB
PDE solver, pdepe. For more information,
see “Partial Differential Equations” on page
11-91.
Can I solve differential-algebraic equation (DAE) Yes. The solvers ode15s and ode23t can solve
systems?
some DAEs of the form M(t,y)y' = f(t,y) where
M(t,y) is singular. The DAEs must be of index 1.
ode15i can solve fully implicit DAEs of index 1,
f(t,y,y') = 0. For examples, see amp1dae, hb1dae,
or ihb1dae.
Can I integrate a set of sampled data?
Not directly. You have to represent the data as a
function by interpolation or some other scheme
for fitting data. The smoothness of this function
is critical. A piecewise polynomial fit like a
spline can look smooth to the eye, but rough to
a solver; the solver takes small steps where the
derivatives of the fit have jumps. Either use a
smooth function to represent the data or use
one of the lower order solvers (ode23, ode23s,
ode23t, ode23tb) that is less sensitive to this.
What do I do when I have the final and not the
initial value?
All the solvers of the ODE suite allow you to
solve backwards or forwards in time. The syntax
for the solvers is [t,y] = ode45(odefun,[t0
tf],y0);and the syntax accepts t0 > tf.
Other Common Problems
11-40
Ordinary Differential Equations
Question
Answer
The solution doesn't look like what I expected.
If you're right about its appearance, you need to
reduce the error tolerances from their default
values. A smaller relative error tolerance is
needed to compute accurately the solution
of problems integrated over “long” intervals,
as well as solutions of problems that are
moderately unstable.
You should check whether there are solution
components that stay smaller than their
absolute error tolerance for some time. If so,
you are not asking for any correct digits in
these components. This may be acceptable for
these components, but failing to compute them
accurately may degrade the accuracy of other
components that depend on them.
My plots aren't smooth enough.
Increase the value of Refine from its default
of 4 in ode45 and 1 in the other solvers. The
bigger the value of Refine, the more output
points. Execution speed is not affected much by
the value of Refine.
I'm plotting the solution as it is computed and it First verify that the ODE function is smooth
looks fine, but the code gets stuck at some point. near the point where the code gets stuck. If it
isn't, the solver must take small steps to deal
with this. It may help to break tspan into pieces
on which the ODE function is smooth.
If the function is smooth and the code is taking
extremely small steps, you are probably trying to
solve a stiff problem with a solver not intended
for this purpose. Switch to ode15s, ode23s,
ode23t, or ode23tb.
My integration proceeds very slowly, using too
many time steps.
First, check that your tspan is not too long.
Remember that the solver uses as many
time points as necessary to produce a smooth
solution. If the ODE function changes on a time
scale that is very short compared to the tspan,
11-41
11
Calculus
Question
Answer
the solver uses a lot of time steps. Long-time
integration is a hard problem. Break tspan into
smaller pieces.
If the ODE function does not change noticeably
on the tspan interval, it could be that your
problem is stiff. Try using ode15s, ode23s,
ode23t, or ode23tb.
Finally, make sure that the ODE function is
written in an efficient way. The solvers evaluate
the derivatives in the ODE function many times.
The cost of numerical integration depends
critically on the expense of evaluating the ODE
function. Rather than recompute complicated
constant parameters at each evaluation, store
them in globals or calculate them once and pass
them to nested functions.
I know that the solution undergoes a radical
change at time t where
t0 ≤ t ≤ tf
If you know there is a sharp change at time t,
it might help to break the tspan interval into
two pieces, [t0 t] and [t tf], and call the
integrator twice.
but the integrator steps past without “seeing” it. If the differential equation has periodic
coefficients or solution, you might restrict the
maximum step size to the length of the period so
the integrator won't step over periods.
11-42
Types of DDEs
Types of DDEs
In this section...
“Constant Delay DDEs” on page 11-43
“Time-Dependent and State-Dependent DDEs” on page 11-43
“DDEs of Neutral Type” on page 11-44
“Evaluating the Solution at Specific Points” on page 11-44
“History and Initial Values” on page 11-44
“Propagation of Discontinuities” on page 11-44
Constant Delay DDEs
A system of differential equations (DDEs) with constant delays has the following form:
y¢( t) = f (t, y( t), y(t - t 1 ),… , y( t - t k )).
Here, t is the independent variable, y is a column vector of dependent variables, and y
′ represents the first derivative of y with respect to t. The delays, τ1,…,τk, are positive
constants.
The dde23 function solves DDEs of the form given by Equation 11-1 with history y(t) =
S(t) for t <t0.
The solutions of DDEs are generally continuous, but they have discontinuities in their
derivatives. The dde23 function tracks discontinuities in low-order derivatives. It
integrates the differential equations with the same explicit Runge-Kutta (2,3) pair
and interpolant used by ode23. The Runge-Kutta formulas are implicit for step sizes
bigger than the delays. When y(t) is smooth enough to justify steps this big, the implicit
formulas are evaluated by a predictor-corrector iteration.
Time-Dependent and State-Dependent DDEs
Equation 11-1 is a special case of
y¢( t) = f (t, y( t), y( dy1 ),..., y( dyp ))
11-43
11
Calculus
that involves delays, dy1,..., dyk, which can depend on both time, t, and state, y. The
delays, dyj(t, y), must satisfy dyj(t, y) ≤ t on the interval [t0, tf] with t0 < tf.
The ddesd function finds the solution, y(t), for DDEs of the form given by Equation 11-2
with history y(t) = S(t) for t < t0. The ddesd function integrates with the classic fourstage, fourth-order explicit Runge-Kutta method, and it controls the size of the residual
of a natural interpolant. It uses iteration to take steps that are longer than the delays.
DDEs of Neutral Type
Delay differential equations of neutral type involve delays in y ′ as well as y:
y¢( t) = f (t, y( t), y( dy1 ),..., y( dyp ), y¢( dyp1 ),..., y¢( dypq )).
The delays in the solution must satisfy dyi(t,y) ≤ t. The delays in the first derivative must
satisfy dypj(t,y) < t so that y ′ does not appear on both sides of the equation.
The ddensd function solves DDEs of neutral type by approximating them with DDEs of
the form given by Equation 11-2. For more information, see Shampine [1].
Evaluating the Solution at Specific Points
Use the deval function and the output from any of the DDE solvers to evaluate the
solution at specific points in the interval of integration. For example, y = deval(sol,
0.5*(sol.x(1) + sol.x(end))) evaluates the solution at the midpoint of the
interval of integration.
History and Initial Values
When you solve a DDE, you approximate the solution on an interval [t0,tf] with t0 < tf. The
DDEs show how y ′(t) depends on values of the solution (and possibly its derivative) at
times prior to t. For example, Equation 11-1 shows that y ′(t0) depends on y(t0 – τ1),…,y(t0
– τk) for positive constants τj. Because of this, a solution on [t0, tk] depends on values it
has at t ≤ t0. You must define these values with a history function, y(t) = S(t) for t <t0.
Propagation of Discontinuities
Generally, the first derivative of the solution has a jump at the initial point. This is
because the first derivative of the history function, S(t), generally does not satisfy the
11-44
Types of DDEs
DDE at this point. A discontinuity in any derivative of y(t) propagates into the future
at spacings of τ1,…, τk when the delays are constant, as in Equation 11-1. If the delays
are not constant, the propagation of discontinuities is more complicated. For neutral
DDEs of the form given by Equation 11-1 or Equation 11-2, the discontinuity appears in
the next higher order derivative each time it is propagated. In this sense, the solution
gets smoother as the integration proceeds. Solutions of neutral DDEs of the form given
by Equation 11-3 are qualitatively different. The discontinuity in the solution does not
propagate to a derivative of higher order. In particular, the typical jump in y ′(t) at t0
propagates as jumps in y ′(t) throughout [t0, tf].
References
[1] Shampine, L.F. “Dissipative Approximations to Neutral DDEs.” Applied Mathematics
& Computation, Vol. 203, 2008, pp. 641–648.
11-45
11
Calculus
Discontinuities in DDEs
If your problem has discontinuities, it’s best to communicate them to the solver using an
options structure. To do this, use the ddeset function to create an options structure
containing the discontinuities in your problem.
There are three properties in the options structure that you can use to specify
discontinuities; InitialY, Jumps, and Events. The property you choose depends on the
location and nature of the discontinuities.
11-46
Nature of Discontinuity
Property
Comments
At the initial value t = t0
InitialY
Generally the initial value y(t0) is the
value S(t0) returned by the history
function, meaning the solution is
continuous at the initial point. If this
is not the case, supply a different
initial value using the InitialY
property.
In the history, i.e., the
solution at t <t0, or in the
equation coefficients for t
>t0
Jumps
Provide the known locations t of the
discontinuities in a vector as the value
of the Jumps property. Applies only to
dde23.
State-dependent
Events
dde23, ddesd, and ddensd use the
events function you supply to locate
these discontinuities. When the solver
finds such a discontinuity, restart
the integration to continue. Specify
the solution structure for the current
integration as the history for the new
integration. The solver extends each
element of the solution structure
after each restart so that the final
structure provides the solution for the
whole interval of integration. If the
new problem involves a change in the
solution, use the InitialY property
to specify the initial value for the new
integration.
DDE with Constant Delays
DDE with Constant Delays
This example shows how to use dde23 to solve a system of DDEs with constant delays.
Click ddex1.m or type edit ddex1.m in a command window to view the code for this
example in an editor.
The differential equations are:
y1¢ (t) = y1 (t - 1)
y2¢ (t) = y1 (t - 1) + y2 (t - 0.2)
y3¢ (t) = y2 (t).
The history of this problem is constant:
y1 (t) = 1
y2 (t) = 1
y3 (t) = 1
for t ≤ 0.
1
Create a new program file in the editor. This file will contain a main function and
two local functions.
2
Define the first-order DDE as a local function.
function dydt = ddex1de(t,y,Z)
ylag1 = Z(:,1);
ylag2 = Z(:,2);
dydt = [ylag1(1); ylag1(1)+ylag2(2); y(2)];
end
3
Define the solution history as a local function.
function S = ddex1hist(t)
S = ones(3,1);
end
4
Define the delays, τ1,…,τk in the main function.
11-47
11
Calculus
lags = [1,0.2];
5
Solve the DDE by calling dde23 in the main function. Pass the DDE function, the
delays, the solution history, and interval of integration, [0,5], as inputs.
sol = dde23(@ddex1de,lags,@ddex1hist,[0,5]);
The dde23 function produces a continuous solution over the whole interval of
integration [t0,tf].
6
Plot the solution returned by dde23. Add this code to your main function.
plot(sol.x,sol.y);
title('An example of Wille and Baker');
xlabel('time t');
ylabel('solution y');
legend('y_1','y_2','y_3','Location','NorthWest');
7
Evaluate the solution at 10 equally spaced points over the interval of integration.
Then plot the results on the same axes as sol.y. Add this code to the main function.
tint = linspace(0,5,10);
Sint = deval(sol,tint)
hold on
plot(tint,Sint,'o');
8
11-48
Run your program to generate and plot the results.
DDE with Constant Delays
Related Examples
•
“Create Functions in Files”
•
“Run Functions in the Editor”
More About
•
“Create Function Handle”
11-49
11
Calculus
State-Dependent Delay Problem
This example shows how to use ddesd to solve a system of two DDEs with a statedependent delay. This system of DDEs was used as a test problem by Enright and
Hayashi [1].
Click ddex3.m or type edit ddex3.m in a command window to view the complete code
for this example in an editor.
The equations for this system are:
y1¢ (t) = y2 (t)
y2¢ (t) = - y2 ( e(1- y2 ( t)) ) ◊ y2 (t)2 ◊ e(1- y2 (t)) .
The analytical solution
y1 ( t) = log(t)
y2 (t) = 1 / t
is used as the history for t ≤ 0.1 and the equations are solved on [0.1, 5] with ddesd
rather than dde23. The ddesd function is appropriate in this case because the first
factor in the second equation has the form y2(d(y)) with a delay that depends on the
second component of the solution.
1
Create a new program file in the editor. This file will contain a main function and
three local functions.
2
Code the system of DDEs as a local function.
function dydt = ddex3de(t,y,Z)
dydt = [y(2); -Z(2)*y(2)^2*exp(1 - y(2))];
end
3
Define the delay as a local function.
function d = ddex3delay(t,y)
d = exp(1 - y(2));
end
4
11-50
Define the solution history as a local function.
State-Dependent Delay Problem
function v = ddex3hist(t)
v = [log(t); 1./t];
end
5
Define the interval of integration and solve the system. Add this code to the main
function in your program file.
tspan = [0.1 5];
sol = ddesd(@ddex3de,@ddex3delay,@ddex3hist,tspan);
6
Use the history function to calculate the analytical solution within the integration
interval. Add this code to the main function.
texact = linspace(0.1,5);
yexact = ddex3hist(texact);
7
Plot the numerical solution on the same axes as the analytical solution. Add this
code to the main function.
figure
plot(texact,yexact,sol.x,sol.y,'o')
legend('y_1, exact','y_2, exact','y_1, ddesd','y_2, ddesd')
xlabel('time t')
ylabel('solution y')
title('D1 problem of Enright and Hayashi')
8
Run your program to generate and plot the results.
11-51
11
Calculus
References
[1] Enright, W.H. and H. Hayashi. “The Evaluation of Numerical Software for Delay
Differential Equations.” In Proceedings of the IFIP TC2/WG2.5 working
conference on Quality of numerical software: assessment and enhancement. (R.F.
Boisvert, ed.). London, UK: Chapman & Hall, Ltd., pp. 179-193.
Related Examples
11-52
•
“Create Functions in Files”
•
“Run Functions in the Editor”
State-Dependent Delay Problem
More About
•
“Create Function Handle”
11-53
11
Calculus
Cardiovascular Model with Discontinuities
This example shows how to use dde23 to solve a cardiovascular model that has a
discontinuous derivative as presented by Ottesen [1].
Click ddex2.m or type edit ddex2.m in a command window to view the code for this
example in an editor.
This is a problem with 1 delay, constant history, and 3 differential equations with 14
physical parameters. The system is heavily influenced by peripheral pressure, R, which
decreases exponentially from 1.05 to 0.84, beginning at t = 600. As a result, the system
has a discontinuity in a low-order derivative at t = 600.
1
Create a new program file in the editor. This file will contain a main function and a
nested function. The main function accepts no inputs and returns no outputs.
2
Define the physical parameters. Add this code to the main function.
p.ca
p.cv
p.R
p.r
p.Vstr
p.alpha0
p.alphas
p.alphap
p.alphaH
p.beta0
p.betas
p.betap
p.betaH
p.gammaH
3
=
=
=
=
=
=
=
=
=
=
=
=
=
=
1.55;
519;
1.05;
0.068;
67.9;
93;
93;
93;
0.84;
7;
7;
7;
1.17;
0;
Define the solution history. Add this code to the main function.
P0 = 93;
Paval = P0;
Pvval = (1 / (1 + p.R/p.r)) * P0;
Hval = (1 / (p.R * p.Vstr)) * (1 / (1 + p.r/p.R)) * P0;
history = [Paval; Pvval; Hval];
4
Define the delay, tau. Add this code to the main function.
tau = 4;
11-54
Cardiovascular Model with Discontinuities
5
Define the location of discontinuity, which occurs at t = 600. Add this code to the
main function.
options = ddeset('Jumps',600);
When your DDE has discontinuities in low-order derivatives, and you know the
locations in advance, it is better to use ddeset with the Jumps property.
6
Solve the DDE over the interval [0, 1000]. Add this code to the main function.
sol = dde23(@ddex2de,tau,history,[0,1000],options);
The function, @ddex2de, which defines the system of DDEs, is the first input
argument. You define this function in 8.
7
Plot the solution. Add this code to the main function.
figure
plot(sol.x,sol.y(3,:))
title('Heart Rate for Baroflex-Feedback Mechanism.')
xlabel('time t')
ylabel('H(t)')
8
Define the system of DDEs as a nested function inside the main function.
function dydt = ddex2de(t,y,Z)
if t <= 600
p.R = 1.05;
else
p.R = 0.21 * exp(600-t) + 0.84;
end
ylag = Z(:,1);
Patau = ylag(1);
Paoft = y(1);
Pvoft = y(2);
Hoft = y(3);
dPadt = - (1 / (p.ca * p.R)) * Paoft ...
+ (1/(p.ca * p.R)) * Pvoft ...
+ (1/p.ca) * p.Vstr * Hoft;
dPvdt = (1 / (p.cv * p.R)) * Paoft...
- ( 1 / (p.cv * p.R)...
+ 1 / (p.cv * p.r) ) * Pvoft;
Ts = 1 / ( 1 + (Patau / p.alphas)^p.betas );
11-55
11
Calculus
Tp = 1 / ( 1 + (p.alphap / Paoft)^p.betap );
dHdt = (p.alphaH * Ts) / (1 + p.gammaH * Tp) ...
- p.betaH * Tp;
dydt = [ dPadt; dPvdt; dHdt];
end
This function is nested so that the main function can access the 14 parameters
defined in 2.
9
Run your program to calculate the solution and display the plot.
References
[1] Ottesen, J. T. “Modelling of the Baroflex-Feedback Mechanism with Time-Delay.” J.
Math. Biol. Vol. 36, Number 1, 1997, pp. 41–63.
Related Examples
11-56
•
“Create Functions in Files”
•
“Run Functions in the Editor”
Cardiovascular Model with Discontinuities
More About
•
“Create Function Handle”
11-57
11
Calculus
DDE of Neutral Type
This example shows how to use ddensd to solve the neutral DDE presented by Paul [1]
for 0 ≤ t ≤ π.
Click ddex4.m or type edit ddex4.m in a command window to view the code for this
example in an editor.
The equation is
y '(t) = 1 + y(t) – 2y(t/2)2 – y '(t – π)
with history:
y(t) = cos (t) for t ≤ 0.
1
Create a new program file in the editor. This file will contain a main function and
four local functions.
2
Define the first-order DDE as a local function.
function yp = ddefun(t,y,ydel,ypdel)
yp = 1 + y - 2*ydel^2 - ypdel;
end
3
Define the solution delay as a local function.
function dy = dely(t,y)
dy = t/2;
end
4
Define the derivative delay as a local function.
function dyp = delyp(t,y)
dyp = t-pi;
end
5
Define the solution history as a local function.
function y = history(t)
y = cos(t);
end
6
Define the interval of integration and solve the DDE using the ddensd function. Add
this code to the main function.
tspan = [0 pi];
sol = ddensd(@ddefun,@dely,@delyp,@history,tspan);
11-58
DDE of Neutral Type
7
Evaluate the solution at 100 equally spaced points between 0 and π. Add this code to
the main function.
tn = linspace(0,pi);
yn = deval(sol,tn);
8
Plot the results. Add this code to the main function.
figure
plot(tn,yn);
xlim([0 pi]);
ylim([-1.2 1.2])
xlabel('time t');
ylabel('solution y');
title('Example of Paul with 1 equation and 2 delay functions')
9
Run your program to calculate the solution and display the plot.
11-59
11
Calculus
References
[1] Paul, C.A.H. “A Test Set of Functional Differential Equations.” Numerical Analysis
Reports. No. 243. Manchester, UK: Math Department, University of Manchester,
1994.
Related Examples
11-60
•
“Create Functions in Files”
•
“Run Functions in the Editor”
DDE of Neutral Type
More About
•
“Create Function Handle”
11-61
11
Calculus
Initial Value DDE of Neutral Type
This example shows how to use ddensd to solve the initial value DDE presented by
Jackiewicz [1] for 0 ≤ t ≤ 0.1.
Click ddex5.m or type edit ddex5.m in a command window to view the code for this
example in an editor.
The equation is
y '(t) = 2cos(2t) y(t/2)2cos(t) + log(y '(t/2)) – log(2cos(t)) – sin(t).
This is an initial value DDE because the delays are zero at t0. The initial conditions are:
y(0) = 1
y '(0) = s,
where s is the solution of:
2 + log(s) – log(2) = 0.
This equation is satisfied by s1 = 2 and s2 = 0.4063757399599599.
1
Create a new program file in the editor. This file will contain a main function and
one local function.
2
Define the DDE as a local function.
function yp = ddefun(t,y,ydel,ypdel)
yp=2*cos(2*t)*ydel^(2*cos(t))+log(ypdel)-log(2*cos(t))-sin(t);
end
3
Define the solution delay and derivative delay. Add this line to the main function.
delay = @(t,y) t/2;
You can use one anonymous function to handle both delays since they are the same
in the equation.
4
Define the initial conditions, y0 and s1, and the interval of integration, tspan. Add
this code to the main function.
y0 = 1;
s1 = 2;
tspan = [0 0.1];
5
Solve the DDE for 0 ≤ t ≤ 0.1, with initial conditions y(0) = 1, and y '(0) = 2. Add this
code to the main function.
sol1 = ddensd(@ddefun,delay,delay,{y0,s1},tspan);
11-62
Initial Value DDE of Neutral Type
6
Solve the equation again, this time using y '(0) = 0.4063757399599599. Add this code
to the main function.
s2 = 0.4063757399599599;
sol2 = ddensd(@ddefun,delay,delay,{y0,s2},tspan);
7
Plot the results. Add this code to the main function.
figure
plot(sol1.x,sol1.y,sol2.x,sol2.y);
legend('y''(0) = 2','y''(0) = .40638','Location','NorthWest');
xlabel('time t');
ylabel('solution y');
title('Two solutions of Jackiewicz''s initial-value NDDE');
8
Run your program to calculate and plot the solutions for each value of s.
11-63
11
Calculus
References
[1] Jackiewicz, Z. “One step Methods of any Order for Neutral Functional Differential
Equations.” SIAM J. Numer. Anal. Vol. 21, Number 3. 1984. pp. 486–511.
Related Examples
11-64
•
“Create Functions in Files”
•
“Run Functions in the Editor”
Initial Value DDE of Neutral Type
More About
•
“Create Function Handle”
11-65
11
Calculus
Boundary-Value Problems
In this section...
“Function Summary” on page 11-66
“Boundary Value Problems” on page 11-67
“BVP Solver” on page 11-67
“Integrator Options” on page 11-70
“Examples” on page 11-71
Function Summary
• “BVP Solver” on page 11-66
• “BVP Helper Functions” on page 11-66
• “BVP Solver Options” on page 11-66
BVP Solver
Solver
Description
bvp4c
Solve boundary value problems for ordinary differential
equations.
bvp5c
Solve boundary value problems for ordinary differential
equations.
BVP Helper Functions
Function
Description
bvpinit
Form the initial guess for bvp4c.
deval
Evaluate the numerical solution using the output of bvp4c.
BVP Solver Options
An options structure contains named properties whose values are passed to bvp4c, and
which affect problem solution. Use these functions to create, alter, or access an options
structure.
11-66
Function
Description
bvpset
Create/alter the BVP options structure.
Boundary-Value Problems
Function
Description
bvpget
Extract properties from options structure created with
bvpset.
Boundary Value Problems
The BVP solver is designed to handle systems of ordinary differential equations
y′ = f(x, y)
where x is the independent variable, y is the dependent variable, and y′ represents the
derivative of y with respect to x dy/dx.
See “First Order ODEs” on page 11-4 for general information about ODEs.
Boundary Conditions
In a boundary value problem, the solution of interest satisfies certain boundary
conditions. These conditions specify a relationship between the values of the solution
at more than one x. In its basic syntax, bvp4c is designed to solve two-point BVPs, i.e.,
problems where the solution sought on an interval [a, b] must satisfy the boundary
conditions
g(y(a), y(b)) = 0
Unlike initial value problems, a boundary value problem may not have a solution,
may have a finite number of solutions, or may have infinitely many solutions. As an
integral part of the process of solving a BVP, you need to provide a guess for the required
solution. The quality of this guess can be critical for the solver performance and even for
a successful computation.
There may be other difficulties when solving BVPs, such as problems imposed on infinite
intervals or problems that involve singular coefficients. Often BVPs involve unknown
parameters p that have to be determined as part of solving the problem
y′ = f(x, y, p)
g(y(a), y(b), p) = 0
In this case, the boundary conditions must suffice to determine the value of p.
BVP Solver
• “The BVP Solver” on page 11-68
• “BVP Solver Syntax” on page 11-68
11-67
11
Calculus
• “BVP Solver Options” on page 11-70
The BVP Solver
The function bvp4c solves two-point boundary value problems for ordinary differential
equations (ODEs). It integrates a system of first-order ordinary differential equations
y′ = f(x, y)
on the interval [a, b], subject to general two-point boundary conditions
bc(y(a),y(b)) = 0
It can also accommodate other types of BVP problems, such as those that have any of the
following:
• Unknown parameters
• Singularities in the solutions
• Multipoint conditions
In this case, the number of boundary conditions must be sufficient to determine the
solution and the unknown parameters.
bvp4c produces a solution that is continuous on [a,b] and has a continuous first
derivative there. You can use the function deval and the output of bvp4c to evaluate the
solution at specific points on the interval of integration.
bvp4c is a finite difference code that implements the 3-stage Lobatto IIIa formula. This
is a collocation formula and the collocation polynomial provides a C1-continuous solution
that is fourth-order accurate uniformly in the interval of integration. Mesh selection and
error control are based on the residual of the continuous solution.
The collocation technique uses a mesh of points to divide the interval of integration into
subintervals. The solver determines a numerical solution by solving a global system
of algebraic equations resulting from the boundary conditions, and the collocation
conditions imposed on all the subintervals. The solver then estimates the error of the
numerical solution on each subinterval. If the solution does not satisfy the tolerance
criteria, the solver adapts the mesh and repeats the process. The user must provide the
points of the initial mesh as well as an initial approximation of the solution at the mesh
points.
BVP Solver Syntax
The basic syntax of the BVP solver is
11-68
Boundary-Value Problems
sol = bvp4c(odefun,bcfun,solinit)
The input arguments are
odefun
A function handle that evaluates the differential equations. It has the
basic form
dydx = odefun(x,y)
where x is a scalar, and dydx and y are column vectors. odefun can
also accept a vector of unknown parameters and a variable number of
known parameters, (see “BVP Solver Options” on page 11-70).
bcfun
Handle to a function that evaluates the residual in the boundary
conditions. It has the basic form
res = bcfun(ya,yb)
where ya and yb are column vectors representing y(a) and y(b),
and res is a column vector of the residual in satisfying the boundary
conditions. bcfun can also accept a vector of unknown parameters and
a variable number of known parameters, (see “BVP Solver Options” on
page 11-70).
solinit
Structure with fields x and y:
x
Ordered nodes of the initial mesh. Boundary
conditions are imposed at a = solinit.x(1) and
b = solinit.x(end).
y
Initial guess for the solution with solinit.y(:,i) a
guess for the solution at the node solinit.x(i).
The structure can have any name, but the fields must be named x
and y. It can also contain a vector that provides an initial guess for
unknown parameters. You can form solinit with the helper function
bvpinit. See the bvpinit reference page for details.
The output argument sol is a structure created by the solver. In the basic case the
structure has fields x, y, yp, and solver.
sol.x
Nodes of the mesh selected by bvp4c
sol.y
Approximation to y(x) at the mesh points of sol.x
sol.yp
Approximation to y′(x) at the mesh points of sol.x
11-69
11
Calculus
sol.solver
'bvp4c'
The structure sol returned by bvp4c contains an additional field if the problem involves
unknown parameters:
sol.parameters
Value of unknown parameters, if present, found by the solver.
The function deval uses the output structure sol to evaluate the numerical solution at
any point from [a,b].
BVP Solver Options
For more advanced applications, you can specify solver options by passing an input
argument options.
options
Structure of optional parameters that change the default integration
properties. This is the fourth input argument.
sol = bvp4c(odefun,bcfun,solinit,options)
You can create the structure options using the function bvpset. The
bvpset reference page describes the properties you can specify.
Integrator Options
The default integration properties in the BVP solver bvp4c are selected to handle
common problems. In some cases, you can improve solver performance by overriding
these defaults. You do this by supplying bvp4c with an options structure that specifies
one or more property values.
For example, to change the value of the relative error tolerance of bvp4c from the default
value of 1e-3 to 1e-4,
1
Create an options structure using the function bvpset by entering
options = bvpset('RelTol', 1e-4);
2
Pass the options structure to bvp4c as follows:
sol = bvp4c(odefun,bcfun,solinit,options)
For a complete description of the available options, see the reference page for bvpset.
11-70
Boundary-Value Problems
Examples
• “Mathieu's Equation” on page 11-71
• “Continuation” on page 11-75
• “Singular BVPs” on page 11-81
• “Multipoint BVPs” on page 11-85
• “Additional Examples” on page 11-89
Mathieu's Equation
• “Solving the Problem” on page 11-71
• “Finding Unknown Parameters” on page 11-74
• “Evaluating the Solution” on page 11-75
Solving the Problem
This example determines the fourth eigenvalue of Mathieu's Equation. It illustrates how
to write second-order differential equations as a system of two first-order ODEs and how
to use bvp4c to determine an unknown parameter λ.
The task is to compute the fourth (q = 5) eigenvalue lambda λ of Mathieu's equation
y′′ + (λ – 2 q cos 2x)y = 0
Because the unknown parameter λ is present, this second-order differential equation is
subject to three boundary conditions
y(0) = 1
y′(0) = 0
y′(π) = 0
Note: The file, mat4bvp.m, contains the complete code for this example. All the functions
required by bvp4c are coded in this file as nested or local functions. To see the code in
an editor, type edit mat4bvp at the command line. To run it, type mat4bvp at the
command line.
1
Rewrite the problem as a first-order system. To use bvp4c, you must rewrite
the equations as an equivalent system of first-order differential equations. Using a
substitution y1 = y and y2 = y′, the differential equation is written as a system of two
first-order equations
y1′ = y2
11-71
11
Calculus
y2′ = –(λ – 2q cos 2x)y1
2
Note that the differential equations depend on the unknown parameter λ. The
boundary conditions become
y1(0) – 1 = 0
y2(0) = 0
y2(π) = 0
Code the system of first-order ODEs. Once you represent the equation as a firstorder system, you can code it as a function that bvp4c can use. Because there is an
unknown parameter, the function must be of the form
dydx = odefun(x,y,parameters)
The following code represents the system in the function, mat4ode. Variable q is
shared with the outer function:
function dydx = mat4ode(x,y,lambda)
dydx = [ y(2)
-(lambda - 2*q*cos(2*x))*y(1) ];
end
% End nested function mat4ode
3
Code the boundary conditions function. You must also code the boundary
conditions in a function. Because there is an unknown parameter, the function must
be of the form
res = bcfun(ya,yb,parameters)
The code below represents the boundary conditions in the function, mat4bc.
function res = mat4bc(ya,yb,lambda)
res = [ ya(2)
yb(2)
ya(1)-1 ];
4
Create an initial guess. To form the guess structure solinit with bvpinit, you
need to provide initial guesses for both the solution and the unknown parameter.
The function mat4init provides an initial guess for the solution. mat4init uses y
= cos4x because this function satisfies the boundary conditions and has the correct
qualitative behavior (the correct number of sign changes).
function yinit = mat4init(x)
yinit = [ cos(4*x)
-4*sin(4*x) ];
11-72
Boundary-Value Problems
In the call to bvpinit, the third argument, lambda, provides an initial guess for the
unknown parameter λ.
lambda = 15;
solinit = bvpinit(linspace(0,pi,10),@mat4init,lambda);
5
This example uses the @ symbol to pass mat4init as a function handle to bvpinit.
Apply the BVP solver. The mat4bvp example calls bvp4c with the functions
mat4ode and mat4bc and the structure solinit created with bvpinit.
sol = bvp4c(@mat4ode,@mat4bc,solinit);
6
View the results. Complete the example by displaying the results:
a
Print the value of the unknown parameter λ found by bvp4c.
fprintf('Fourth eigenvalue is approximately %7.3f.\n',...
sol.parameters)
b
Use deval to evaluate the numerical solution at 100 equally spaced points in
the interval [0, π], and plot its first component. This component approximates
y(x).
xint = linspace(0,pi);
Sxint = deval(sol,xint);
plot(xint,Sxint(1,:))
axis([0 pi -1 1.1])
title('Eigenfunction of Mathieu''s equation.')
xlabel('x')
ylabel('solution y')
The following plot shows the eigenfunction associated with the final eigenvalue λ
= 17.097.
11-73
11
Calculus
Finding Unknown Parameters
The bvp4c solver can find unknown parameters p for problems of the form
y′ = f(x,y,p)
bc(y(a), y (b),p) = 0
You must provide bvp4c an initial guess for any unknown parameters in the vector
solinit.parameters. When you call bvpinit to create the structure solinit, specify
the initial guess as a vector in the additional argument parameters.
solinit = bvpinit(x,v,parameters)
The bvp4c function arguments odefun and bcfun must each have a third argument.
dydx = odefun(x,y,parameters)
res = bcfun(ya,yb,parameters)
While solving the differential equations, bvp4c adjusts the value of unknown parameters
to satisfy the boundary conditions. The solver returns the final values of these unknown
parameters in sol.parameters.
11-74
Boundary-Value Problems
Evaluating the Solution
The collocation method implemented in bvp4c produces a C1-continuous solution over
the whole interval of integration [a,b]. You can evaluate the approximate solution, S(x),
at any point in [a,b] using the helper function deval and the structure sol returned by
bvp4c.
Sxint = deval(sol,xint)
The deval function is vectorized. For a vector xint, the ith column of Sxint
approximates the solution y(xint(i)).
Continuation
• “Introduction” on page 11-75
• “Using Continuation to Solve a BVP” on page 11-75
• “Using Continuation to Verify Consistency” on page 11-78
Introduction
To solve a boundary value problem, you need to provide an initial guess for the solution.
The quality of your initial guess can be critical to the solver performance, and to being
able to solve the problem at all. However, coming up with a sufficiently good guess can
be the most challenging part of solving a boundary value problem. Certainly, you should
apply the knowledge of the problem's physical origin. Often a problem can be solved as a
sequence of relatively simpler problems, i.e., a continuation.
This example shows how to use continuation to:
• Solve a difficult BVP
• Verify a solution's consistent behavior
Using Continuation to Solve a BVP
This example solves the differential equation
εy′′ + xy′ = επ2 cos(πx) – πx sin(πx)
for ε = 10–4, on the interval [–1 1], with boundary conditions y(–1) = –2 and y(1) = 0. For
0 < ε <1, the solution has a transition layer at x = 0. Because of this rapid change in the
solution for small values of ε, the problem becomes difficult to solve numerically.
11-75
11
Calculus
The example solves the problem as a sequence of relatively simpler problems, i.e., a
continuation. The solution of one problem is used as the initial guess for solving the next
problem.
Note: The file, shockbvp.m, contains the complete code for this example. All required
functions are coded as nested functions in this file. To see the code in an editor, type
edit shockbvp at the command line. To run it, type shockbvp at the command line.
Note: This problem appears in [1] to illustrate the mesh selection capability of a well
established BVP code COLSYS.
1
Code the ODE and boundary condition functions. Code the differential
equation and the boundary conditions as functions that bvp4c can use:
The code below represents the differential equation and the boundary conditions in
the functions shockODE and shockBC. Note that shockODE is vectorized to improve
solver performance. The additional parameter ε is represented by e and is shared
with the outer function.
function dydx = shockODE(x,y)
pix = pi*x;
dydx = [ y(2,:)
-x/e.*y(2,:) - pi^2*cos(pix) - pix/e.*sin(pix) ];
end %
End nested function shockODE
function res = shockBC(ya,yb)
res = [ ya(1)+2
yb(1)
];
end %
End nested function shockBC
2
Provide analytical partial derivatives. For this problem, the solver benefits from
using analytical partial derivatives. The code below represents the derivatives in
functions shockJac and shockBCJac.
function jac = shockJac(x,y)
jac = [ 0
1
0 -x/e ];
end %
End nested function shockJac
function [dBCdya,dBCdyb] = shockBCJac(ya,yb)
dBCdya = [ 1 0
11-76
Boundary-Value Problems
0 0 ];
dBCdyb = [ 0 0
1 0 ];
end %
End nested function shockBCJac
shockJac shares e with the outer function.
Tell bvp4c to use these functions to evaluate the partial derivatives by setting the
options FJacobian and BCJacobian. Also set 'Vectorized' to 'on' to indicate that
the differential equation function shockODE is vectorized.
options = bvpset('FJacobian',@shockJac,...
'BCJacobian',@shockBCJac,...
'Vectorized','on');
3
Create an initial guess. You must provide bvp4c with a guess structure that
contains an initial mesh and a guess for values of the solution at the mesh points.
A constant guess of y(x) ≡ 1 and y′(x) ≡ 0, and a mesh of five equally spaced points
on [–1 1] suffice to solve the problem for ε = 10–2. Use bvpinit to form the guess
structure.
sol = bvpinit([-1 -0.5 0 0.5 1],[1 0]);
4
Use continuation to solve the problem. To obtain the solution for the parameter
ε = 10–4, the example uses continuation by solving a sequence of problems for ε = 10–
2
, 10–3, 10–4. The solver bvp4c does not perform continuation automatically, but the
code's user interface has been designed to make continuation easy. The code uses the
output sol that bvp4c produces for one value of e as the guess in the next iteration.
e = 0.1;
for i=2:4
e = e/10;
sol = bvp4c(@shockODE,@shockBC,sol,options);
end
5
View the results. Complete the example by displaying the final solution
plot(sol.x,sol.y(1,:))
axis([-1 1 -2.2 2.2])
title(['There is a shock at x = 0 when \epsilon = '...
sprintf('%.e',e) '.'])
xlabel('x')
ylabel('solution y')
11-77
11
Calculus
Using Continuation to Verify Consistency
Falkner-Skan BVPs arise from similarity solutions of viscous, incompressible, laminar
flow over a flat plate. An example is
f ′′′ + ff ′′ + β(1 – (f ′)2) = 0
for β = 0.5 on the interval [0, ∞] with boundary conditions f(0) = 0, f ′(0) = 0, and f ′(∞) = 1.
The BVP cannot be solved on an infinite interval, and it would be impractical to solve it
for even a very large finite interval. So, the example tries to solve a sequence of problems
posed on increasingly larger intervals to verify the solution's consistent behavior as the
boundary approaches ∞.
The example imposes the infinite boundary condition at a finite point called infinity.
The example then uses continuation in this end point to get convergence for increasingly
larger values of infinity. It uses bvpinit to extrapolate the solution sol for one
value of infinity as an initial guess for the new value of infinity. The plot of each
successive solution is superimposed over those of previous solutions so they can easily be
compared for consistency.
11-78
Boundary-Value Problems
Note: The file, fsbvp.m, contains the complete code for this example. All required
functions are coded as nested functions in this file. To see the code in an editor, type
edit fsbvp at the command line. To run it, type fsbvp at the command line.
1
Code the ODE and boundary condition functions. Code the differential
equation and the boundary conditions as functions that bvp4c can use. The problem
parameter beta is shared with the outer function.
function dfdeta = fsode(eta,f)
dfdeta = [ f(2)
f(3)
-f(1)*f(3) - beta*(1 - f(2)^2) ];
end %
End nested function fsode
function res = fsbc(f0,finf)
res = [f0(1)
f0(2)
finf(2) - 1];
end %
End nested function fsbc
2
Create an initial guess. You must provide bvp4c with a guess structure that
contains an initial mesh and a guess for values of the solution at the mesh points. A
crude mesh of five points and a constant guess that satisfies the boundary conditions
are good enough to get convergence when infinity = 3.
infinity = 3;
maxinfinity = 6;
solinit = bvpinit(linspace(0,infinity,5),[0 0 1]);
3
Solve on the initial interval. The example obtains the solution for infinity =
3. It then prints the computed value of f ′′(0) for comparison with the value reported
by Cebeci and Keller [2]:
sol = bvp4c(@fsode,@fsbc,solinit);
eta = sol.x;
f = sol.y;
fprintf('\n');
fprintf('Cebeci & Keller report that f''''(0) = 0.92768.\n')
fprintf('Value computed using infinity = %g is %7.5f.\n', ...
infinity,f(3,1))
The example prints
11-79
11
Calculus
Cebeci & Keller report that f''(0) = 0.92768.
Value computed using infinity = 3 is 0.92915.
4
Setup the figure and plot the initial solution.
figure
plot(eta,f(2,:),eta(end),f(2,end),'o');
axis([0 maxinfinity 0 1.4]);
title('Falkner-Skan equation, positive wall shear, ...
\beta = 0.5.')
xlabel('\eta')
ylabel('df/d\eta')
hold on
drawnow
shg
5
Use continuation to solve the problem and plot subsequent solutions.
The example then solves the problem for infinity = 4, 5, 6. It uses bvpinit to
extrapolate the solution sol for one value of infinity as an initial guess for the
next value of infinity. For each iteration, the example prints the computed value
of f ′′(0) and superimposes a plot of the solution in the existing figure.
for Bnew = infinity+1:maxinfinity
solinit = bvpinit(sol,[0 Bnew]); % Extend solution to Bnew.
11-80
Boundary-Value Problems
sol = bvp4c(@fsode,@fsbc,solinit);
eta = sol.x;
f = sol.y;
fprintf('Value computed using infinity = %g is %7.5f.\n', ...
Bnew,f(3,1))
plot(eta,f(2,:),eta(end),f(2,end),'o');
drawnow
end
hold off
The example prints
Value computed using infinity = 4 is 0.92774.
Value computed using infinity = 5 is 0.92770.
Value computed using infinity = 6 is 0.92770.
Note that the values approach 0.92768 as reported by Cebeci and Keller. The
superimposed plots confirm the consistency of the solution's behavior.
Singular BVPs
• “Introduction” on page 11-82
11-81
11
Calculus
• “Emden's equation” on page 11-82
Introduction
The function bvp4c solves a class of singular BVPs of the form
1
Sy + f ( x, y)
x
0 = g ( y(0), y(b) )
y¢ =
It can also accommodate unknown parameters for problems of the form
1
Sy + f ( x, y, p)
x
0 = ( g( y(0 ), y(b), p)
y¢ =
Singular problems must be posed on an interval [0,b] with b > 0. Use bvpset to pass the
constant matrix S to bvp4c as the value of the 'SingularTerm' integration property.
Boundary conditions at x = 0 must be consistent with the necessary condition for a
smooth solution, Sy(0) = 0. An initial guess should also satisfy this necessary condition.
When you solve a singular BVP using
sol = bvp4c(@odefun,@bcfun,solinit,options)
bvp4c requires that your function odefun(x,y) return only the value of the f(x, y) term
in Equation 5-2.
Emden's equation
Emden's equation arises in modeling a spherical body of gas. The PDE of the model is
reduced by symmetry to the ODE
y¢¢ +
2
y¢ + y5 = 0
x
on an interval [0,1]. The coefficient 2/x is singular at x = 0, but symmetry implies the
boundary condition y′(0) = 0. With this boundary condition, the term
2
y¢(0)
x
11-82
Boundary-Value Problems
is well-defined as x approaches 0. For the boundary condition y(1) = 3 / 2 , this BVP has
the analytical solution
Ê
x2 ˆ
y( x) = Á 1 +
˜
Á
3 ˜¯
Ë
- 1/ 2
Note: The file, emdenbvp.m, contains the complete code for this example. It contains all
the required functions coded as local functions. To see the code in an editor, type edit
emdenbvp at the command line. To run it, type emdenbvp at the command line.
1
Rewrite the problem as a first-order system and identify the singular term.
Using a substitution y1 = y and y2 = y′, write the differential equation as a system of
two first-order equations
y1¢ = y2
2
y2¢ = - y2 - y15
x
The boundary conditions become
y2 (0) = 0
y1 (1) = 3 / 2
Writing the ODE system in a vector-matrix form
È y ¢ ˘ 1 È 0 0 ˘ È y ˘ È y2 ˘
1
Í 1˙= Í
˙
˙Í ˙ + Í
Í y ¢ ˙ x Î 0 -2 ˚ Î y2 ˚ ÍÎ - y15 ˙˚
Î 2˚
the terms of Equation 5-2 are identified as
È0 0 ˘
S=Í
˙
Î0 - 2˚
11-83
11
Calculus
and
È y2 ˘
f ( x, y) = Í 5 ˙
ÍÎ - y1 ˙˚
2
Code the ODE and boundary condition functions. Code the differential
equation and the boundary conditions as functions that bvp4c can use.
function dydx = emdenode(x,y)
dydx = [ y(2)
-y(1)^5 ];
function res = emdenbc(ya,yb)
res = [ ya(2)
yb(1) - sqrt(3)/2 ];
3
Setup integration properties. Use the matrix as the value of the
'SingularTerm' integration property.
S = [0,0;0,-2];
options = bvpset('SingularTerm',S);
4
Create an initial guess. This example starts with a mesh of five points and a
constant guess for the solution.
y1 ( x) ∫ 3 / 2
y2 ( x) ∫ 0
Use bvpinit to form the guess structure
guess = [sqrt(3)/2;0];
solinit = bvpinit(linspace(0,1,5),guess);
5
Solve the problem. Use the standard bvp4c syntax to solve the problem.
sol = bvp4c(@emdenode,@emdenbc,solinit,options);
6
View the results. This problem has an analytical solution
Ê
x2 ˆ
y( x) = Á 1 +
˜
Á
3 ˜¯
Ë
11-84
- 1/ 2
The example evaluates the analytical solution at 100 equally spaced points and plots
it along with the numerical solution computed using bvp4c.
Boundary-Value Problems
x = linspace(0,1);
truy = 1 ./ sqrt(1 + (x.^2)/3);
plot(x,truy,sol.x,sol.y(1,:),'ro');
title('Emden problem -- BVP with singular term.')
legend('Analytical','Computed');
xlabel('x');
ylabel('solution y');
Multipoint BVPs
In multipoint boundary value problems, the solution of interest satisfies conditions at
points inside the interval of integration. The bvp4c function is useful in solving such
problems.
The following example shows how the multipoint capability in bvp4c can improve
efficiency when you are solving a nonsmooth problem. The following equations are solved
on 0 ≤ x ≤ λ for constant parameters n, κ, λ > 1, and η = λ2/(n × κ2). These are subject to
boundary conditions v(0) = 0 and C(λ) = 1:
v' = (C - 1)/n
C' = (v * C - min(x,1))/ h
The term min(x,1) is not smooth at xc = 1, and this can affect the solver's efficiency.
By introducing an interface point at xc = 1, smooth solutions can be obtained on [0,1]
11-85
11
Calculus
and [1,λ]. To get a continuous solution over the entire interval [0,λ], the example imposes
matching conditions at the interface.
Note: The file, threebvp.m, contains the complete code for this example, and it solves the
problem for λ = 2, n = 0.05, and several values of κ. All required functions are coded as
nested functions in threebvp.m. To see the code in an editor, type edit threebvp at
the command line. To run it, type threebvp at the command line.
The example takes you through the following steps:
1
Determine the interfaces and divide the interval of integration into
regions. Introducing an interface point at xc = 1 divides the problem into two
regions in which the solutions remain smooth. The differential equations for the two
regions are
Region 1: 0 ≤ x ≤ 1
v' = (C - 1)/n
C' = (v * C - x)/ h
Region 2: 1 ≤ x ≤ λ
v' = (C - 1)/n
C' = (v * C - 1)/ h
2
Note that the interface xc = 1 is included in both regions. At xc = 1, bvp4c
produces a left and right solution. These solutions are denoted as v(1-), C(1-) and
v(1+), C(1+) respectively.
Determine the boundary conditions. Solving two first-order differential
equations in two regions requires imposing four boundary conditions. Two of these
conditions come from the original formulation; the others enforce the continuity of
the solution across the interface xc = 1:
v(0) = 0
C( l ) - 1 = 0
v(1-) - v(1+) = 0
C(1-) - C(1+) = 0
Here, v(1-), C(1-) and v(1+), C(1+) denote the left and right solution at the
interface.
11-86
Boundary-Value Problems
3
Code the derivative function. In the derivative function, y(1) corresponds
to v(x), and y(2) corresponds to C(x). The additional input argument region
identifies the region in which the derivative is evaluated. bvp4c enumerates regions
from left to right, starting with 1. Note that the problem parameters n and η are
shared with the outer function:
function dydx = f(x,y,region)
dydx = zeros(2,1);
dydx(1) = (y(2) - 1)/n;
% The definition of C'(x) depends on the region.
switch region
case 1
% x in [0 1]
dydx(2) = (y(1)*y(2) - x)/ h ;
case 2
dydx(2) = (y(1)*y(2) - 1)/ h ;
% x in [1 l ]
end
end
4
% End nested function f
Code the boundary conditions function. For multipoint BVPs, the arguments
of the boundary conditions function, YL and YR, become matrices. In particular, the
kth column YL(:,k) represents the solution at the left boundary of the kth region.
Similarly, YR(:,k) represents the solution at the right boundary of the kth region.
In the example, y(0) is approximated by YL(:,1), while y(λ) is approximated
by YR(:,end). Continuity of the solution at the internal interface requires that
YR(:,1) = YL(:,2). Nested function bc computes the residual in the boundary
conditions:
function res = bc(YL,YR)
res = [YL(1,1)
YR(1,1) - YL(1,2)
YR(2,1) - YL(2,2)
YR(2,end) - 1];
end
5
%
%
%
%
%
v(0) = 0
Continuity of v(x) at x=1
Continuity of C(x) at x=1
C( l ) = 1
End nested function bc
Create an initial guess. For multipoint BVPs, when creating an initial guess using
bvpinit, use double entries in xinit for the interface point xc. This example uses a
constant guess yinit = [1;1]:
xc = 1;
xinit = [0, 0.25, 0.5, 0.75, xc, xc, 1.25, 1.5, 1.75, 2];
solinit = bvpinit(xinit,yinit)
11-87
11
Calculus
For multipoint BVPs, you can use different guesses in different regions. To do that,
you specify the initial guess for y as a function using the following syntax:
solinit = bvpinit(xinit,@yinitfcn)
The initial guess function must have the following general form:
function y = yinitfcn(x,region)
switch region
case 1
% x in [0, 1]
y = [1;1];
% initial guess for y(x) 0 £ x £ 1
case 2 % x in [1, l ]
y = [1;1];
% initial guess for y(x), 1 £ x £ l
end
6
Apply the solver. The bvp4c function uses the same syntax for multipoint BVPs as
it does for two-point BVPs:
sol = bvp4c(@f,@bc,solinit);
7
The mesh points returned in sol.x are adapted to the solution behavior, but the
mesh still includes a double entry for the interface point xc = 1. Corresponding
columns of sol.y represent the left and right solution at xc.
View the results. Using deval, the solution can be evaluated at any point in the
interval of integration.
Note that, with the left and right values computed at the interface, the solution
is not uniquely defined at xc = 1. When evaluating the solution exactly at the
interface, deval issues a warning and returns the average of the left and right
solution values. Call deval at xc-eps(xc) and xc+eps(xc) to get the limit values
at xc.
The example plots the solution approximated at the mesh points selected by the
solver:
plot(sol.x,sol.y(1,:),sol.x,sol.y(2,:),'--')
legend('v(x)','C(x)')
title('A three-point BVP solved with BVP4C')
xlabel(['\ l = ',num2str( l ), ...
', \ k = ',num2str( k ),'.'])
ylabel('v and C')
11-88
Boundary-Value Problems
Additional Examples
The following additional examples are available. Type
edit examplename
to view the code and
examplename
to run the example.
Example Name
Description
emdenbvp
Emden's equation, a singular BVP
fsbvp
Falkner-Skan BVP on an infinite interval
mat4bvp
Fourth eigenfunction of Mathieu's equation
shockbvp
Solution with a shock layer near x = 0
11-89
11
Calculus
Example Name
Description
twobvp
BVP with exactly two solutions
threebvp
Three-point boundary value problem
Additional examples are provided by “Tutorial on Solving BVPs with BVP4C,” available
at http://www.mathworks.com/bvp_tutorial.
11-90
Partial Differential Equations
Partial Differential Equations
In this section...
“Function Summary” on page 11-91
“Initial Value Problems” on page 11-91
“PDE Solver” on page 11-92
“Integrator Options” on page 11-95
“Examples” on page 11-96
Function Summary
• “PDE Solver” on page 11-91
• “PDE Helper Function” on page 11-91
PDE Solver
This is the MATLAB PDE solver.
PDE Initial-Boundary Value
Problem Solver
Description
pdepe
Solve initial-boundary value problems for systems of
parabolic and elliptic PDEs in one space variable and time.
PDE Helper Function
PDE Helper Function
Description
pdeval
Evaluate the numerical solution of a PDE using the output
of pdepe.
Initial Value Problems
pdepe solves systems of parabolic and elliptic PDEs in one spatial variable x and time t,
of the form
∂u ˆ ∂ u
∂ Ê
∂u ˆ ˆ
∂u ˆ
Ê
Ê
Ê
c Á x, t, u, ˜
= x- m Á xm f Á x, t, u, ˜ ˜ + s Á x, t,u, ˜ .
∂
x
∂
t
∂
x
∂
x
∂x ¯
Ë
¯
Ë
¯¯
Ë
Ë
11-91
11
Calculus
The PDEs hold for t0 ≤ t ≤ tf and a ≤ x ≤ b. The interval [a, b] must be finite. m can be 0,
1, or 2, corresponding to slab, cylindrical, or spherical symmetry, respectively. If m > 0,
then a ≥ 0 must also hold.
In Equation 11-5, f(x,t,u,∂u/∂x) is a flux term and s(x,t,u,∂u/∂x) is a source term. The flux
term must depend on ∂u/∂x. The coupling of the partial derivatives with respect to time
is restricted to multiplication by a diagonal matrix c(x,t,u,∂u/∂x). The diagonal elements
of this matrix are either identically zero or positive. An element that is identically zero
corresponds to an elliptic equation and otherwise to a parabolic equation. There must be
at least one parabolic equation. An element of c that corresponds to a parabolic equation
can vanish at isolated values of x if they are mesh points. Discontinuities in c and/or s
due to material interfaces are permitted provided that a mesh point is placed at each
interface.
At the initial time t = t0, for all x the solution components satisfy initial conditions of the
form
u( x, t0 ) = u0 ( x).
At the boundary x = a or x = b, for all t the solution components satisfy a boundary
condition of the form
Ê
∂u ˆ
p( x, t, u) + q( x, t) f Á x, t,u, ˜ = 0 .
∂x ¯
Ë
q(x,t) is a diagonal matrix with elements that are either identically zero or never zero.
Note that the boundary conditions are expressed in terms of the f rather than partial
derivative of u with respect to x ∂u/∂x. Also, of the two coefficients, only p can depend on
u.
PDE Solver
The PDE Solver
The MATLAB PDE solver, pdepe, solves initial-boundary value problems for systems of
parabolic and elliptic PDEs in the one space variable x and time t. There must be at least
one parabolic equation in the system.
The pdepe solver converts the PDEs to ODEs using a second-order accurate spatial
discretization based on a fixed set of user-specified nodes. The discretization method is
described in [9]. The time integration is done with ode15s. The pdepe solver exploits the
11-92
Partial Differential Equations
capabilities of ode15s for solving the differential-algebraic equations that arise when
Equation 11-5 contains elliptic equations, and for handling Jacobians with a specified
sparsity pattern. ode15s changes both the time step and the formula dynamically.
After discretization, elliptic equations give rise to algebraic equations. If the elements
of the initial conditions vector that correspond to elliptic equations are not “consistent”
with the discretization, pdepe tries to adjust them before beginning the time integration.
For this reason, the solution returned for the initial time may have a discretization error
comparable to that at any other time. If the mesh is sufficiently fine, pdepe can find
consistent initial conditions close to the given ones. If pdepe displays a message that it
has difficulty finding consistent initial conditions, try refining the mesh. No adjustment
is necessary for elements of the initial conditions vector that correspond to parabolic
equations.
PDE Solver Syntax
The basic syntax of the solver is:
sol = pdepe(m,pdefun,icfun,bcfun,xmesh,tspan)
Note: Correspondences given are to terms used in “Initial Value Problems” on page
11-91.
The input arguments are
m
Specifies the symmetry of the problem. m can be 0 = slab,
1 = cylindrical, or 2 = spherical. It corresponds to m in
Equation 11-5.
pdefun
Function that defines the components of the PDE. It computes
the terms c, f, and s in Equation 11-5, and has the form
[c,f,s] = pdefun(x,t,u,dudx)
where x and t are scalars, and u and dudx are vectors that
approximate the solution u and its partial derivative with
respect to x. c, f, and s are column vectors. c stores the diagonal
elements of the matrix c.
icfun
Function that evaluates the initial conditions. It has the form
u = icfun(x)
11-93
11
Calculus
When called with an argument x, icfun evaluates and returns
the initial values of the solution components at x in the column
vector u.
bcfun
Function that evaluates the terms p and q of the boundary
conditions. It has the form
[pl,ql,pr,qr] = bcfun(xl,ul,xr,ur,t)
where ul is the approximate solution at the left boundary xl =
a and ur is the approximate solution at the right boundary xr
= b. pl and ql are column vectors corresponding to p and the
diagonal of q evaluated at xl. Similarly, pr and qr correspond to
xr. When m > 0 and a = 0, boundedness of the solution near x = 0
requires that the f vanish at a = 0. pdepe imposes this boundary
condition automatically and it ignores values returned in pl and
ql.
xmesh
Vector [x0, x1, ..., xn] specifying the points at which a numerical
solution is requested for every value in tspan. x0 and xn
correspond to a and b, respectively.
Second-order approximation to the solution is made on the mesh
specified in xmesh. Generally, it is best to use closely spaced
mesh points where the solution changes rapidly. pdepe does
not select the mesh in x automatically. You must provide an
appropriate fixed mesh in xmesh. The cost depends strongly on
the length of xmesh. When m > 0, it is not necessary to use a fine
mesh near x = 0 to account for the coordinate singularity.
The elements of xmesh must satisfy x0 < x1 < ... < xn. The
length of xmesh must be ≥ 3.
11-94
Partial Differential Equations
Vector [t0, t1, ..., tf] specifying the points at which a solution
is requested for every value in xmesh. t0 and tf correspond to t0
and tf , respectively.
tspan
pdepe performs the time integration with an ODE solver
that selects both the time step and formula dynamically. The
solutions at the points specified in tspan are obtained using the
natural continuous extension of the integration formulas. The
elements of tspan merely specify where you want answers and
the cost depends weakly on the length of tspan.
The elements of tspan must satisfy t0 < t1 < ... < tf. The
length of tspan must be ≥ 3.
The output argument sol is a three-dimensional array, such that
• sol(:,:,k) approximates component k of the solution u.
• sol(i,:,k) approximates component k of the solution at time tspan(i) and mesh
points xmesh(:).
• sol(i,j,k) approximates component k of the solution at time tspan(i) and the mesh
point xmesh(j).
PDE Solver Options
For more advanced applications, you can also specify as input arguments solver options
and additional parameters that are passed to the PDE functions.
options
Structure of optional parameters that change the default
integration properties. This is the seventh input argument.
sol = pdepe(m,pdefun,icfun,bcfun,...
xmesh,tspan,options)
See “Integrator Options” on page 11-95 for more information.
Integrator Options
The default integration properties in the MATLAB PDE solver are selected to handle
common problems. In some cases, you can improve solver performance by overriding
these defaults. You do this by supplying pdepe with one or more property values in an
options structure.
11-95
11
Calculus
sol = pdepe(m,pdefun,icfun,bcfun,xmesh,tspan,options)
Use odeset to create the options structure. Only those options of the underlying ODE
solver shown in the following table are available for pdepe. The defaults obtained by
leaving off the input argument options are generally satisfactory. “Integrator Options”
on page 11-9 tells you how to create the structure and describes the properties.
PDE Properties
Properties Category
Property Name
Error control
RelTol, AbsTol, NormControl
Step-size
InitialStep, MaxStep
Examples
• “Single PDE” on page 11-96
• “System of PDEs” on page 11-101
• “Additional Examples” on page 11-106
Single PDE
• “Solving the Equation” on page 11-96
• “Evaluating the Solution” on page 11-101
Solving the Equation
This example illustrates the straightforward formulation, solution, and plotting of the
solution of a single PDE
p2
∂u ∂ 2u
=
.
∂t ∂x2
This equation holds on an interval 0 ≤ x ≤ 1 for times t ≥ 0. At t = 0, the solution satisfies
the initial condition
u( x, 0) = sin p x.
At x = 0 and x = 1, the solution satisfies the boundary conditions
11-96
Partial Differential Equations
u(0, t) = 0
∂u
p e- t +
(1, t) = 0 .
∂x
Note: The file, pdex1.m, contains the complete code for this example. It contains all
the required functions coded as local functions. To see the code in an editor, type edit
pdex1 at the command line. To run it, type pdex1 at the command line. See “PDE Solver
Syntax” on page 11-93 for more information.
1
Rewrite the PDE. Write the PDE in the form
∂u ˆ ∂ u
∂ Ê
∂u ˆ ˆ
∂u ˆ
Ê
Ê
Ê
c Á x, t, u, ˜
= x- m Á xm f Á x, t, u, ˜ ˜ + s Á x, t,u, ˜ .
∂ x ¯ ∂t
∂x Ë
∂x ¯ ¯
∂x ¯
Ë
Ë
Ë
This is the form shown in Equation 11-5 and expected by pdepe. See “Initial Value
Problems” on page 11-91 for more information. For this example, the resulting
equation is
p2
∂u
∂ Ê ∂u ˆ
= x0 Á x0
˜+0
∂t
∂x Ë ∂ x ¯
with parameter m = 0 and the terms
∂u ˆ
Ê
c Á x, t, u, ˜ = p 2
∂x ¯
Ë
Ê
∂u ˆ ∂ u
f Á x, t, u, ˜ =
∂ x ¯ ∂x
Ë
∂u ˆ
Ê
s Á x, t, u, ˜ = 0.
∂x ¯
Ë
2
Code the PDE. Once you rewrite the PDE in the form shown above (Equation 11-5)
and identify the terms, you can code the PDE in a function that pdepe can use. The
function must be of the form
[c,f,s] = pdefun(x,t,u,dudx)
11-97
11
Calculus
where c, f, and s correspond to the c, f, and s terms. The code below computes c, f,
and s for the example problem.
function [c,f,s] = pdex1pde(x,t,u,DuDx)
c = pi^2;
f = DuDx;
s = 0;
3
Code the initial conditions function. You must code the initial conditions in a
function of the form
u = icfun(x)
The code below represents the initial conditions in the function pdex1ic.
function u0 = pdex1ic(x)
u0 = sin(pi*x);
4
Code the boundary conditions function. You must also code the boundary
conditions in a function of the form
[pl,ql,pr,qr] = bcfun(xl,ul,xr,ur,t)
The boundary conditions, written in the same form as Equation 11-7, are
u(0, t) + 0 ◊
∂u
( 0, t) = 0 at x = 0
∂x
and
p e- t + 1 ◊
∂u
(1, t) = 0 at x = 1 .
∂x
The code below evaluates the components p(x,t,u) and q(x,t) of the boundary
conditions in the function pdex1bc.
function [pl,ql,pr,qr] = pdex1bc(xl,ul,xr,ur,t)
pl = ul;
ql = 0;
pr = pi * exp(-t);
qr = 1;
11-98
Partial Differential Equations
5
In the function pdex1bc, pl and ql correspond to the left boundary conditions (x =
0), and pr and qr correspond to the right boundary condition (x = 1).
Select mesh points for the solution. Before you use the MATLAB PDE solver,
you need to specify the mesh points (t,x) at which you want pdepe to evaluate the
solution. Specify the points as vectors t and x.
The vectors t and x play different roles in the solver (see “PDE Solver” on page
11-92). In particular, the cost and the accuracy of the solution depend strongly
on the length of the vector x. However, the computation is much less sensitive to the
values in the vector t.
This example requests the solution on the mesh produced by 20 equally spaced
points from the spatial interval [0,1] and five values of t from the time interval [0,2].
x = linspace(0,1,20);
t = linspace(0,2,5);
6
Apply the PDE solver. The example calls pdepe with m = 0, the functions
pdex1pde, pdex1ic, and pdex1bc, and the mesh defined by x and t at which
pdepe is to evaluate the solution. The pdepe function returns the numerical
solution in a three-dimensional array sol, where sol(i,j,k) approximates the kth
component of the solution, uk, evaluated at t(i) and x(j).
m = 0;
sol = pdepe(m,@pdex1pde,@pdex1ic,@pdex1bc,x,t);
This example uses @ to pass pdex1pde, pdex1ic, and pdex1bc as function handles
to pdepe.
7
Note: See “Function Handles” for more information about function handles.
View the results. Complete the example by displaying the results:
a
Extract and display the first solution component. In this example, the solution
u has only one component, but for illustrative purposes, the example “extracts”
it from the three-dimensional array. The surface plot shows the behavior of the
solution.
u = sol(:,:,1);
surf(x,t,u)
title('Numerical solution computed with 20 mesh points')
11-99
11
Calculus
xlabel('Distance x')
ylabel('Time t')
b
Display a solution profile at tf , the final value of t. In this example, tf = t = 2.
figure
plot(x,u(end,:))
title('Solution at t = 2')
xlabel('Distance x')
ylabel('u(x,2)')
11-100
Partial Differential Equations
Evaluating the Solution
After obtaining and plotting the solution above, you might be interested in a solution
profile for a particular value of t, or the time changes of the solution at a particular point
x. The kth column u(:,k) (of the solution extracted in step 7) contains the time history
of the solution at x(k). The jth row u(j,:) contains the solution profile at t(j).
Using the vectors x and u(j,:), and the helper function pdeval, you can evaluate the
solution u and its derivative ∂u/∂x at any set of points xout
[uout,DuoutDx] = pdeval(m,x,u(j,:),xout)
The example pdex3 uses pdeval to evaluate the derivative of the solution at xout = 0.
See pdeval for details.
System of PDEs
This example illustrates the solution of a system of partial differential equations. The
problem is taken from electrodynamics. It has boundary layers at both ends of the
interval, and the solution changes rapidly for small t.
The PDEs are
11-101
11
Calculus
∂ u1
∂ 2u1
= 0 .024
- F ( u1 - u2 )
∂t
∂x2
∂ u2
∂ 2 u2
= 0.170
+ F ( u1 - u2 )
∂t
∂x2
where F(y) = exp(5.73y) – exp(–11.46y). The equations hold on an interval 0 ≤ x ≤ 1 for
times t ≥ 0.
The solution u satisfies the initial conditions
u1 ( x, 0) ∫ 1
u2 ( x, 0) ∫ 0
and boundary conditions
∂ u1
(0, t) ∫ 0
∂x
u2 (0, t) ∫ 0
u1 (1, t) ∫ 1
∂ u2
(1, t) ∫ 0.
∂x
Note: The file, pdex4.m, contains the complete code for this example. It contains all
the required functions coded as local functions. To see the code in an editor, type edit
pdex4 at the command line. To run it, type pdex4 at the command line.
1
Rewrite the PDE. In the form expected by pdepe, the equations are
È1 ˘ ∂ Èu1 ˘ ∂ È0 .024 ( ∂u1 / ∂x ) ˘ È - F ( u1 - u2 ) ˘
Í
˙+Í
˙.
Í ˙ ◊ * Íu ˙ =
Î1 ˚ ∂ t Î 2 ˚ ∂x Î0 .170 ( ∂ u2 / ∂ x) ˚ Î F ( u1 - u2 ) ˚
The boundary conditions on the partial derivatives of u have to be written in terms of
the flux. In the form expected by pdepe, the left boundary condition is
11-102
Partial Differential Equations
È 0 ˘ È1 ˘ È 0.024 ( ∂ u1 / ∂ x) ˘ È0 ˘
Íu ˙ + Í ˙ ◊ * Í0 .170 ∂u / ∂x ˙ = Í ˙
( 2 )˚ Î0 ˚
Î 2 ˚ Î0 ˚ Î
and the right boundary condition is
Èu1 - 1˘ È0 ˘ È 0.024 ( ∂ u1 / ∂ x) ˘ È0 ˘
˙ = Í ˙.
Í
˙ + Í ˙ ◊*Í
Î 0 ˚ Î1 ˚ Î0 .170 ( ∂u2 / ∂x )˚ Î0 ˚
2
Code the PDE. After you rewrite the PDE in the form shown above, you can code it
as a function that pdepe can use. The function must be of the form
[c,f,s] = pdefun(x,t,u,dudx)
where c, f, and s correspond to the c, f , and s terms in Equation 11-5.
function [c,f,s] = pdex4pde(x,t,u,DuDx)
c = [1; 1];
f = [0.024; 0.17] .* DuDx;
y = u(1) - u(2);
F = exp(5.73*y)-exp(-11.47*y);
s = [-F; F];
3
Code the initial conditions function. The initial conditions function must be of
the form
u = icfun(x)
The code below represents the initial conditions in the function pdex4ic.
function u0 = pdex4ic(x);
u0 = [1; 0];
4
Code the boundary conditions function. The boundary conditions functions
must be of the form
[pl,ql,pr,qr] = bcfun(xl,ul,xr,ur,t)
The code below evaluates the components p(x,t,u) and q(x,t) (Equation 11-7) of the
boundary conditions in the function pdex4bc.
function [pl,ql,pr,qr] = pdex4bc(xl,ul,xr,ur,t)
pl = [0; ul(2)];
ql = [1; 0];
11-103
11
Calculus
pr = [ur(1)-1; 0];
qr = [0; 1];
5
Select mesh points for the solution. The solution changes rapidly for small t.
The program selects the step size in time to resolve this sharp change, but to see this
behavior in the plots, output times must be selected accordingly. There are boundary
layers in the solution at both ends of [0,1], so mesh points must be placed there to
resolve these sharp changes. Often some experimentation is needed to select the
mesh that reveals the behavior of the solution.
x = [0 0.005 0.01 0.05 0.1 0.2 0.5 0.7 0.9 0.95 0.99 0.995 1];
t = [0 0.005 0.01 0.05 0.1 0.5 1 1.5 2];
6
Apply the PDE solver. The example calls pdepe with m = 0, the functions
pdex4pde, pdex4ic, and pdex4bc, and the mesh defined by x and t at which pdepe
is to evaluate the solution. The pdepe function returns the numerical solution in a
three-dimensional array sol, where sol(i,j,k) approximates the kth component
of the solution, μk, evaluated at t(i) and x(j).
m = 0;
sol = pdepe(m,@pdex4pde,@pdex4ic,@pdex4bc,x,t);
7
View the results. The surface plots show the behavior of the solution components.
u1 = sol(:,:,1);
u2 = sol(:,:,2);
figure
surf(x,t,u1)
title('u1(x,t)')
xlabel('Distance x')
ylabel('Time t')
11-104
Partial Differential Equations
figure
surf(x,t,u2)
title('u2(x,t)')
xlabel('Distance x')
ylabel('Time t')
11-105
11
Calculus
Additional Examples
The following additional examples are available. Type
edit examplename
to view the code and
examplename
to run the example.
11-106
Example Name
Description
pdex1
Simple PDE that illustrates the straightforward formulation,
computation, and plotting of the solution
pdex2
Problem that involves discontinuities
pdex3
Problem that requires computing values of the partial
derivative
pdex4
System of two PDEs whose solution has boundary layers at both
ends of the interval and changes rapidly for small t.
pdex5
System of PDEs with step functions as initial conditions
Selected Bibliography for Differential Equations
Selected Bibliography for Differential Equations
[1] Ascher, U., R. Mattheij, and R. Russell, Numerical Solution of Boundary Value
Problems for Ordinary Differential Equations, SIAM, Philadelphia, PA, 1995, p.
372.
[2] Cebeci, T. and H. B. Keller, “Shooting and Parallel Shooting Methods for Solving
the Falkner-Skan Boundary-layer Equation,” J. Comp. Phys., Vol. 7, 1971, pp.
289-300.
[3] Hairer, E., and G. Wanner, Solving Ordinary Differential Equations II, Stiff and
Differential-Algebraic Problems, Springer-Verlag, Berlin, 1991, pp. 5-8.
[4] Hindmarsh, A. C., “LSODE and LSODI, Two New Initial Value Ordinary Differential
Equation Solvers,” SIGNUM Newsletter, Vol. 15, 1980, pp.10-11.
[5] Hindmarsh, A. C., and G. D. Byrne, “Applications of EPISODE: An Experimental
Package for the Integration of Ordinary Differential Equations,” Numerical
Methods for Differential Systems, L. Lapidus and W. E. Schiesser eds., Academic
Press, Orlando, FL, 1976, pp 147-166.
[6] Ottesen, J. T., “Modelling of the Baroflex-Feedback Mechanism with Time-Delay,” J.
Math. Biol., Vol. 36, 1997.
[7] Shampine, L. F., Numerical Solution of Ordinary Differential Equations, Chapman &
Hall Mathematics, 1994.
[8] Shampine, L. F., and M. K. Gordon, Computer Solution of Ordinary Differential
Equations, W.H. Freeman & Co., 1975.
[9] Skeel, R. D. and M. Berzins, “A Method for the Spatial Discretization of Parabolic
Equations in One Space Variable,” SIAM Journal on Scientific and Statistical
Computing, Vol. 11, 1990, pp. 1-32.
[10] W.H. Enright and H. Hayashi, “The Evaluation of Numerical Software for Delay
Differential Equations,” R. Boisvert (Ed.), The Quality of Numerical Software:
Assessment and Enhancement, Chapman & Hall, London, 1997, pp. 179-192.
11-107
11
Calculus
Integration to Find Arc Length
This example shows how to parametrize a curve and compute the arc length using
integral.
Consider the curve parameterized by the equations
x(t) = sin(2t), y(t) = cos(t), z(t) = t,
where t ∊ [0,3π].
Create a three-dimensional plot of this curve.
t = 0:0.1:3*pi;
plot3(sin(2*t),cos(t),t)
The arc length formula says the length of the curve is the integral of the norm of the
derivatives of the parameterized equations.
3p
Ú
4 cos(2 t) 2 + sin( t) 2 + 1 dt.
0
Define the integrand as an anonymous function.
f = @(t) sqrt(4*cos(2*t).^2 + sin(t).^2 + 1);
Integrate this function with a call to integral.
len = integral(f,0,3*pi)
len =
17.2220
The length of this curve is about 17.2.
11-108
Complex Line Integrals
Complex Line Integrals
This example shows how to calculate complex line integrals using the 'Waypoints'
option of the integral function. In MATLAB, you use the 'Waypoints' option to
define a sequence of straight line paths from the first limit of integration to the first
waypoint, from the first waypoint to the second, and so forth, and finally from the last
waypoint to the second limit of integration.
Define the Integrand with an Anonymous Function
Integrate
ez
ÑÚ C z dz,
where C is a closed contour that encloses the simple pole of
ez
at the origin.
z
Define the integrand with an anonymous function.
fun = @(z) exp(z)./z;
Integrate Without Using Waypoints
You can evaluate contour integrals of complex-valued functions with a parameterization.
In general, a contour is specified, and then differentiated and used to parameterize the
original integrand. In this case, specify the contour as the unit circle, but in all cases, the
result is independent of the contour chosen.
g = @(theta) cos(theta) + 1i*sin(theta);
gprime = @(theta) -sin(theta) + 1i*cos(theta);
q1 = integral(@(t) fun(g(t)).*gprime(t),0,2*pi)
q1 =
-0.0000 + 6.2832i
This method of parameterizing, although reliable, can be difficult and time consuming
since a derivative must be calculated before the integration is performed. Even for simple
functions, you need to write several lines of code to obtain the correct result. Since the
result is the same with any closed contour that encloses the pole (in this case, the origin),
11-109
11
Calculus
instead you can use the 'Waypoints' option of integral to construct a square or
triangular path that encloses the pole.
Integrate Along a Contour That Encloses No Poles
If any limit of integration or element of the waypoints vector is complex, then integral
performs the integration over a sequence of straight line paths in the complex plane. The
natural direction around a contour is counterclockwise; specifying a clockwise contour
is akin to multiplying by -1. Specify the contour in such a way that it encloses a single
functional singularity. If you specify a contour that encloses no poles, then Cauchy’s
integral theorem guarantees that the value of the closed-loop integral is zero.
To see this, integrate fun around a square contour away from the origin. Use equal
limits of integration to form a closed contour.
C = [2+i 2+2i 1+2i];
q = integral(fun,1+i,1+i,'Waypoints',C)
q =
2.7756e-16 - 7.7716e-16i
The result is on the order of eps and effectively zero.
Integrate Along a Contour with a Pole in the Interior
Specify a square contour that completely encloses the pole at the origin, and then
integrate.
C = [1+i -1+i -1-i 1-i];
q2 = integral(fun,1,1,'Waypoints',C)
q2 =
0.0000 + 6.2832i
This result agrees with the q1 calculated above, but uses much simpler code.
The exact answer for this problem is 2πi.
2*pi*i
ans =
11-110
Complex Line Integrals
0.0000 + 6.2832i
11-111
11
Calculus
Singularity on Interior of Integration Domain
This example shows how to split the integration domain to place a singularity on the
boundary.
Define the Integrand with an Anonymous Function
The integrand of the complex-valued integral
1 1
ÚÚ
-1 -1
1
x+ y
dxdy
has a singularity when x = y = 0 and is, in general, singular on the line y = -x.
Define this integrand with an anonymous function.
fun = @(x,y) ((x+y).^(-1/2));
Integrate Over a Square
Integrate fun over a square domain specified by - 1 £ x £ 1 , - 1 £ y £ 1 .
format long;
q = integral2(fun,-1,1,-1,1)
Warning: Non-finite result. The integration was unsuccessful.
Singularity likely.
q =
Inf - 3.486553786882412e+06i
If there are singular values in the interior of the integration region, the integration fails
to converge and returns a warning.
Split the Integration Domain into Two Triangles
You can redefine the integral by splitting the integration domain into complementary
pieces and adding the smaller integrations together. Avoid integration errors and
warnings by placing singularities on the boundary of the domain. In this case, you can
split the square integration region into two triangles along the singular line y = -x and
add the results.
11-112
Singularity on Interior of Integration Domain
q1 = integral2(fun,-1,1,-1,@(x)-x);
q2 = integral2(fun,-1,1,@(x)-x,1);
q = q1 + q2
q =
3.771236166328260 - 3.771236166328255i
The integration succeeds when the singular values are on the boundary.
The exact value of this integral is
8 2
(1 - i) .
3
8/3*sqrt(2)*(1-i)
ans =
3.771236166328253 - 3.771236166328253i
11-113
11
Calculus
Analytic Solution to Integral of Polynomial
This example shows how to use the polyint function to integrate polynomial
expressions analytically. Use this function to evaluate indefinite integral expressions of
polynomials.
Define the Problem
Consider the real-valued indefinite integral,
Ú (4x
5
- 2 x3 + x + 4) dx.
The integrand is a polynomial, and the analytic solution is
2 6 1 4 1 2
x - x + x + 4 x + k,
3
2
2
where k is the constant of integration. Since the limits of integration are unspecified, the
integral function family is not well-suited to solving this problem.
Express the Polynomial with a Vector
Create a vector whose elements represent the coefficients for each descending power of x.
p = [4 0 -2 0 1 4];
Integrate the Polynomial Analytically
Integrate the polynomial analytically using the polyint function. Specify the constant of
integration with the second input argument.
k = 2;
I = polyint(p,k)
I =
0.6667
0
-0.5000
0
0.5000
4.0000
2.0000
The output is a vector of coefficients for descending powers of x. This result matches the
analytic solution above, but has a constant of integration k = 2.
11-114
Integration of Numeric Data
Integration of Numeric Data
This example shows how to integrate a set of discrete velocity data numerically using
trapz to approximate the total distance traveled. The integral family only accepts
function handles as inputs, so those functions cannot be used with discrete data sets. Use
trapz when a functional expression is not available for integration.
View the Velocity Data
Consider the following velocity data and corresponding time data.
vel = [0 .45 1.79 4.02 7.15 11.18 16.09 21.90 29.05 29.05 ...
29.05 29.05 29.05 22.42 17.9 17.9 17.9 17.9 14.34 11.01 ...
8.9 6.54 2.03 0.55 0];
time = 0:24;
This data represents the velocity of an automobile (in m/s) taken at 1 s intervals over 24
s.
Plot the velocity data points and connect each point with a straight line.
figure
plot(time,vel,'-*')
grid on
title('Automobile Velocity')
xlabel('Time (s)')
ylabel('Velocity (m/s)')
11-115
11
Calculus
The slope is positive during periods of acceleration, zero during periods of constant
velocity, and negative during periods of deceleration. At time t = 0, the vehicle is at rest
with vel(1) = 0 m/s. The vehicle accelerates until reaching a maximum velocity at t
= 8 s of vel(9) = 29.05 m/s and maintains this velocity for 4 s. It then decelerates to
vel(14) = 17.9 m/s for 3 s and eventually back down to rest. Since this velocity curve
has multiple discontinuities, a single continuous function cannot describe it.
Calculate the Total Distance Traveled
trapz performs discrete integration by using the data points to create trapezoids, so it
is well suited to handling data sets with discontinuities. This method assumes linear
behavior between the data points, and accuracy may be reduced when the behavior
11-116
Integration of Numeric Data
between data points is nonlinear. To illustrate, you can draw trapezoids onto the graph
using the data points as vertices.
xverts = [time(1:end-1);time(1:end-1);time(2:end);time(2:end)];
yverts = [zeros(1,24);vel(1:end-1);vel(2:end);zeros(1,24)];
hold on
p = patch(xverts,yverts,'b','LineWidth',1.5);
trapz calculates the area under a set of discrete data by breaking the region into
trapezoids. The function then adds the area of each trapezoid to compute the total area.
Calculate the total distance traveled by the automobile (corresponding to the shaded
area) by integrating the velocity data numerically using trapz.
11-117
11
Calculus
distance = trapz(time,vel)
distance =
345.2200
The distance traveled by the automobile in t = 24 s is about 345.22 m.
11-118
12
Fourier Transforms
• “Discrete Fourier Transform (DFT)” on page 12-2
• “Fast Fourier Transform (FFT)” on page 12-8
• “Function Summary” on page 12-28
12
Fourier Transforms
Discrete Fourier Transform (DFT)
In this section...
“Introduction” on page 12-2
“Visualizing the DFT” on page 12-3
Introduction
Spectral analysis is the process of identifying component frequencies in data. For discrete
data, the computational basis of spectral analysis is the discrete Fourier transform (DFT).
The DFT transforms time- or space-based data into frequency-based data.
The DFT of a vector x of length n is another vector y of length n:
n -1
yp+1 =
 w jp x j+1
j =0
where ω is a complex nth root of unity:
w = e-2p i / n
This notation uses i for the imaginary unit, and p and j for indices that run from 0 to
n–1. The indices p+1 and j+1 run from 1 to n, corresponding to ranges associated with
MATLAB vectors.
Data in the vector x are assumed to be separated by a constant interval in time or space,
dt = 1/fs or ds = 1/fs, where fs is the sampling frequency. The DFT y is complex-valued.
The absolute value of y at index p+1 measures the amount of the frequency f = p(fs / n)
present in the data.
12-2
Discrete Fourier Transform (DFT)
Time or space
domain
1
dt = 1 fs
n
Data
x
n
Frequency
content
abs(y)
n −1
y p+1 = ∑ ω jp x j +1
j =0
Frequency
domain
1
p+1
df = fs n
The first element of y, corresponding to zero frequency, is the sum of the data in x. This
DC component is often removed from y so that it does not obscure the positive frequency
content of the data.
Visualizing the DFT
The documentation example function fftgui opens a graphical user interface that
allows you to explore the real and imaginary parts of a data vector and its DFT. (Here
fft refers to efficient computation of the DFT by the MATLAB fft function, as
discussed in “Fast Fourier Transform (FFT)” on page 12-8.)
Add the examples folder to your path for access to the function fftgui.
addpath(fullfile(matlabroot,'/help/matlab/math/examples'))
If x is a vector,
fftgui(x)
plots the real and imaginary parts of both x and its DFT (fft(x)). Use your mouse to
drag points in any of the plots and the points in the other plots respond to the changes.
12-3
12
Fourier Transforms
For example, use fftgui to display the DFT of a unit impulse at x(1):
x = [1 zeros(1,11)];
fftgui(x)
12-4
Discrete Fourier Transform (DFT)
The transform is quite different if the unit impulse is at x(2):
x = [0 1 zeros(1,10)];
fftgui(x)
12-5
12
Fourier Transforms
The following commands display DFTs of square and sine waves, respectively:
x = [ones(1,25),-ones(1,25)];
fftgui(x)
12-6
Discrete Fourier Transform (DFT)
t = linspace(0,1,50);
x = sin(2*pi*t);
fftgui(x)
The midpoint of the DFT (or the point just to the right of the midpoint if the length is
even), corresponding to half the sampling frequency of the data, is the Nyquist point. For
real x, the real part of the DFT is symmetric about the Nyquist point, and the imaginary
part is antisymmetric about the Nyquist point.
12-7
12
Fourier Transforms
Fast Fourier Transform (FFT)
In this section...
“Introduction” on page 12-8
“The FFT in One Dimension” on page 12-9
“The FFT in Multiple Dimensions” on page 12-22
Introduction
DFTs with a million points are common in many applications. Modern signal and image
processing applications would be impossible without an efficient method for computing
the DFT.
Direct application of the definition of the DFT (see “Discrete Fourier Transform (DFT)”
on page 12-2) to a data vector of length n requires n multiplications and n additions—a
total of 2n2 floating-point operations. This does not include the generation of the powers
of the complex nth root of unity ω. To compute a million-point DFT, a computer capable
of doing one multiplication and addition every microsecond requires a million seconds, or
about 11.5 days.
Fast Fourier Transform (FFT) algorithms have computational complexity O(n log n)
instead of O(n2). If n is a power of 2, a one-dimensional FFT of length n requires less than
3n log2 n floating-point operations (times a proportionality constant). For n = 220, that is
a factor of almost 35,000 faster than 2n2.
The MATLAB functions fft, fft2, and fftn (and their inverses ifft, ifft2, and
ifftn, respectively) all use fast Fourier transform algorithms to compute the DFT.
When using FFT algorithms, a distinction is made between the window length and
the transform length. The window length is the length of the input data vector. It is
determined by, for example, the size of an external buffer. The transform length is the
length of the output, the computed DFT. An FFT algorithm pads or chops the input to
achieve the desired transform length. The following figure illustrates the two lengths.
12-8
Fast Fourier Transform (FFT)
FFT
x
Buffer
Pad / Chop
Window
length
m
Efficient
DFT
y
Transform
length
n
y = fft(x,n)
The execution time of an FFT algorithm depends on the transform length. It is fastest
when the transform length is a power of two, and almost as fast when the transform
length has only small prime factors. It is typically slower for transform lengths that
are prime or have large prime factors. Time differences, however, are reduced to
insignificance by modern FFT algorithms such as those used in MATLAB. Adjusting the
transform length for efficiency is usually unnecessary in practice.
The FFT in One Dimension
• “Introduction” on page 12-9
• “Basic Spectral Analysis” on page 12-10
• “Spectral Analysis of a Whale Call” on page 12-14
• “Data Interpolation Using FFT” on page 12-18
Introduction
The MATLAB fft function returns the DFT y of an input vector x using a fast Fourier
transform algorithm:
y = fft(x);
In this call to fft, the window length m = length(x) and the transform length
n = length(y) are the same.
The transform length is specified by an optional second argument:
y = fft(x,n);
In this call to fft, the transform length is n. If the length of x is less than n, x is padded
with trailing zeros to increase its length to n before computing the DFT. If the length of x
is greater than n, only the first n elements of x are used to compute the transform.
12-9
12
Fourier Transforms
Basic Spectral Analysis
The FFT allows you to efficiently estimate component frequencies in data from a discrete
set of values sampled at a fixed rate. Relevant quantities in a spectral analysis are listed
in the following table. For space-based data, replace references to time with references to
space.
Quantity
Description
x
Sampled data
m = length(x)
Window length (number of samples)
fs
Samples/unit time
dt = 1/fs
Time increment per sample
t = (0:m-1)/fs
Time range for data
y = fft(x,n)
Discrete Fourier transform (DFT)
abs(y)
Amplitude of the DFT
(abs(y).^2)/n
Power of the DFT
fs/n
Frequency increment
f = (0:n-1)*(fs/n)
Frequency range
fs/2
Nyquist frequency
Consider the following data x with two component frequencies of differing amplitude and
phase buried in noise.
fs = 100;
t = 0:1/fs:10-1/fs;
x = (1.3)*sin(2*pi*15*t) ...
+ (1.7)*sin(2*pi*40*(t-2)) ...
+ 2.5*gallery('normaldata',size(t),4);
%
%
%
%
%
Sample frequency (Hz)
10 sec sample
15 Hz component
40 Hz component
Gaussian noise;
Use fft to compute the DFT y and its power.
m = length(x);
n = pow2(nextpow2(m));
y = fft(x,n);
f = (0:n-1)*(fs/n);
power = y.*conj(y)/n;
%
%
%
%
%
Window length
Transform length
DFT
Frequency range
Power of the DFT
nextpow2 finds the exponent of the next power of two greater than or equal to the
window length (ceil(log2(m))) and pow2 computes the power. Using a power of two
12-10
Fast Fourier Transform (FFT)
for the transform length optimizes the FFT algorithm, though in practice there is usually
little difference in execution time from using n = m.
To visualize the DFT, plots of abs(y), abs(y).^2, and log(abs(y)) are all common. A
plot of power versus frequency is called a periodogram.
plot(f,power)
xlabel('Frequency (Hz)')
ylabel('Power')
title('{\bf Periodogram}')
The first half of the frequency range (from 0 to the Nyquist frequency fs/2) is sufficient
to identify the component frequencies in the data, since the second half is just a reflection
of the first half.
12-11
12
Fourier Transforms
In many applications it is traditional to center the periodogram at 0. The fftshift
function rearranges the output from fft with a circular shift to produce a 0-centered
periodogram.
y0 = fftshift(y);
f0 = (-n/2:n/2-1)*(fs/n);
power0 = y0.*conj(y0)/n;
% Rearrange y values
% 0-centered frequency range
% 0-centered power
plot(f0,power0)
xlabel('Frequency (Hz)')
ylabel('Power')
title('{\bf 0-Centered Periodogram}')
The rearrangement makes use of the periodicity in the definition of the DFT.
12-12
Fast Fourier Transform (FFT)
Use the MATLAB angle and unwrap functions to create a phase plot of the DFT.
phase = unwrap(angle(y0));
plot(f0,phase*180/pi)
xlabel('Frequency (Hz)')
ylabel('Phase (Degrees)')
grid on
Component frequencies are mostly hidden by the randomness in phase at adjacent
values. The upward trend in the plot is due to the unwrap function, which in this case
adds
to the phase more often than it subtracts it.
12-13
12
Fourier Transforms
Spectral Analysis of a Whale Call
This example shows how to perform spectral analysis of audio data.
The documentation example file bluewhale.au contains audio data from a Pacific blue
whale vocalization recorded by underwater microphones off the coast of California. The
file is from the library of animal vocalizations maintained by the Cornell University
Bioacoustics Research Program.
Because blue whale calls are so low, they are barely audible to humans. The time scale in
the data is compressed by a factor of 10 to raise the pitch and make the call more clearly
audible. The following reads and plots the data.
whaleFile = fullfile(matlabroot,'examples','matlab','bluewhale.au');
[x,fs] = audioread(whaleFile);
plot(x)
xlabel('Sample Number')
ylabel('Amplitude')
title('{\bf Blue Whale Call}')
12-14
Fast Fourier Transform (FFT)
An A "trill" is followed by a series of B "moans." You can use sound(x,fs) to play the
data.
The B call is simpler and easier to analyze. Use the previous plot to determine
approximate indices for the beginning and end of the first B call. Correct the time base
for the factor of 10 speed-up in the data.
bCall = x(2.45e4:3.10e4);
tb = 10*(0:1/fs:(length(bCall)-1)/fs); % Time base
plot(tb,bCall)
xlim([0 tb(end)])
12-15
12
Fourier Transforms
xlabel('Time (seconds)')
ylabel('Amplitude')
title('{\bf Blue Whale B Call}')
Use fft to compute the DFT of the signal. Correct the frequency range for the factor of
10 speed-up in the data.
m
n
y
f
p
12-16
=
=
=
=
=
length(bCall);
pow2(nextpow2(m));
fft(bCall,n);
(0:n-1)*(fs/n)/10;
y.*conj(y)/n;
%
%
%
%
%
Window length
Transform length
DFT of signal
Frequency range
Power of the DFT
Fast Fourier Transform (FFT)
Plot the first half of the periodogram, up to the Nyquist frequency.
plot(f(1:floor(n/2)),p(1:floor(n/2)))
xlabel('Frequency (Hz)')
ylabel('Power')
h =gca;
h.XTick = [0 50 100 150 200];
title('{\bf Component Frequencies of a Blue Whale B Call}')
12-17
12
Fourier Transforms
The B call is composed of a fundamental frequency around 17 Hz and a sequence of
harmonics, with the second harmonic emphasized.
Data Interpolation Using FFT
This example shows how to use FFT in a context other than spectral analysis—
estimating coefficients of a trigonometric polynomial that interpolates a set of regularlyspaced data. This approach to data interpolation is described in [1].
Several people discovered fast DFT algorithms independently, and many people have
contributed to their development. A 1965 paper by John Tukey and John Cooley [2] is
generally credited as the starting point for modern usage of the FFT. However, a paper
by Gauss published posthumously in 1866 [3] (and dated to 1805) contains indisputable
use of the splitting technique that forms the basis of modern FFT algorithms.
Gauss was interested in the problem of computing accurate asteroid orbits from
observations of their positions. His paper contains 12 data points on the position of the
asteroid Pallas, through which he wished to interpolate a trigonometric polynomial
with 12 coefficients. Instead of solving the resulting 12-by-12 system of linear equations
by hand, Gauss looked for a shortcut. He discovered how to separate the equations
into three subproblems that were much easier to solve, and then how to recombine the
solutions to obtain the desired result. The solution is equivalent to estimating the DFT of
the data with an FFT algorithm.
Here is the data that appears in Gauss' paper.
asc = 0:30:330;
dec = [408 89 -66 10 338 807 1238 1511 1583 1462 1183 804];
plot(asc,dec,'ro','Linewidth',2)
xlim([0 360])
xlabel('Ascension (Degrees)')
ylabel('Declination (Minutes)')
title('{\bf Position of the Asteroid Pallas}')
grid on
12-18
Fast Fourier Transform (FFT)
Gauss wished to interpolate a trigonometric polynomial of the form
Use fft to perform an equivalent of Gauss' calculation.
d = fft(dec);
m = length(dec);
12-19
12
Fourier Transforms
M = floor((m+1)/2);
a0
an
a6
bn
=
=
=
=
d(1)/m;
2*real(d(2:M))/m;
d(M+1)/m;
-2*imag(d(2:M))/m;
Plot the interpolant with the data.
hold on
x = 0:0.01:360;
n = 1:length(an);
y = a0 + an*cos(2*pi*n'*x/360) ...
+ bn*sin(2*pi*n'*x/360) ...
+ a6*cos(2*pi*6*x/360);
plot(x,y,'Linewidth',2)
legend('Data','DFT Interpolant','Location','NW')
12-20
Fast Fourier Transform (FFT)
References
[1] Briggs, W. and V.E. Henson. The DFT: An Owner's Manual for the Discrete Fourier
Transform. Philadelphia: SIAM, 1995.
[2] Cooley, J.W. and J.W. Tukey. “An Algorithm for the Machine Calculation of Complex
Fourier Series.” Mathematics of Computation. Vol. 19. 1965, pp. 297–301.
[3] Gauss, C. F. “Theoria interpolationis methodo nova tractata.” Carl Friedrich Gauss
Werke. Band 3. Göttingen: Königlichen Gesellschaft der Wissenschaften, 1866.
[4] Heideman M., D. Johnson, and C. Burrus. “Gauss and the History of the Fast Fourier
Transform.” Arch. Hist. Exact Sciences. Vol. 34. 1985, pp. 265–277.
12-21
12
Fourier Transforms
[5] Goldstine, H. H. A History of Numerical Analysis from the 16th through the 19th
Century. Berlin: Springer-Verlag, 1977.
The FFT in Multiple Dimensions
• “Introduction” on page 12-22
• “Diffraction Patterns” on page 12-23
Introduction
This section discusses generalizations of the DFT in one dimension (see “Discrete Fourier
Transform (DFT)” on page 12-2).
In two dimensions, the DFT of an m-by-n array X is another m-by-n array Y:
m-1 n-1
Y p+1, q+1 =
  wmjpwnkq X j +1,k+1
j =0 k =0
where ωm and ωn are complex roots of unity:
wm = e-2p i / m
wn = e-2p i / n
This notation uses i for the imaginary unit, p and j for indices that run from 0 to m–1,
and q and k for indices that run from 0 to n–1. The indices p+1 and j+1 run from 1 to m
and the indices q+1 and k+1 run from 1 to n, corresponding to ranges associated with
MATLAB arrays.
The MATLAB function fft2 computes two-dimensional DFTs using a fast Fourier
transform algorithm. Y = fft2(X) is equivalent to Y = fft(fft(X).').', that is, to
computing the one-dimensional DFT of each column X followed by the one-dimensional
DFT of each row of the result. The inverse transform of the two-dimensional DFT is
computed by ifft2.
The MATLAB function fftn generalizes fft2 to N-dimensional arrays. Y = fftn(X) is
equivalent to:
12-22
Fast Fourier Transform (FFT)
Y = X;
for p = 1:length(size(X))
Y = fft(Y,[],p);
end
That is, to computing in place the one-dimensional DFT along each dimension of X. The
inverse transform of the N-dimensional DFT is computed by ifftn.
Diffraction Patterns
The theory of optics predicts that the diffraction pattern produced by a plane wave
incident on an optical mask with a small aperture is described, at a distance, by the
Fourier transform of the mask. See, for example, [1].
Create a logical array describing an optical mask M with a circular aperture A of radius R.
n = 2^10;
M = zeros(n);
I = 1:n;
x = I-n/2;
y = n/2-I;
[X,Y] = meshgrid(x,y);
R = 10;
A = (X.^2 + Y.^2 <= R^2);
M(A) = 1;
imagesc(M)
axis image
title('{\bf Circular Aperture}')
12-23
12
Fourier Transforms
Use fft2 to compute the two-dimensional DFT of the mask and fftshift to rearrange
the output so that the zero-frequency component is at the center.
D1 = fft2(M);
D2 = fftshift(D1);
imagesc(abs(D2))
axis image
title('{\bf Diffraction Pattern}')
12-24
Fast Fourier Transform (FFT)
The logarithm helps to bring out details of the DFT in regions where the amplitude is
small.
D3 = log2(D2);
imagesc(abs(D3))
axis image
title('{\bf Enhanced Diffraction Pattern}')
12-25
12
Fourier Transforms
Very small amplitudes are affected by numerical round-off. The lack of radial symmetry
is an artifact of the rectangular arrangement of data.
Reference
[1] Fowles, G. R. Introduction to Modern Optics. New York: Dover, 1989.
See Also
angle | fft | fft2 | fftn | fftshift | ifft | ifft2 | ifftn | nextpow2 | pow2
| unwrap
12-26
Fast Fourier Transform (FFT)
More About
•
“Discrete Fourier Transform (DFT)” on page 12-2
12-27
12
Fourier Transforms
Function Summary
MATLAB functions related to Fourier transforms include:
Function
Description
fft
One-dimensional fast Fourier transform
ifft
One-dimensional inverse fast Fourier transform
fft2
Two-dimensional fast Fourier transform
ifft2
Two-dimensional inverse fast Fourier transform
fftn
N-dimensional fast Fourier transform
ifftn
N-dimensional inverse fast Fourier transform
fftshift
Rearrange DFT data to center zero-frequency component
fftw
Interface to FFTW run-time algorithm
abs
Amplitude of the DFT
angle
Phase of the DFT
unwrap
Correct phase angles with jumps greater than or equal to pi
nextpow2
Next power of two greater than or equal to a given length
pow2
Compute powers of two
The MATLAB software also includes demos that use these functions in combination for
Fourier analysis:
• FFT for Spectral Analysis — Reviews basic spectral analysis with the FFT
• Using FFT in MATLAB — Example of time series analysis with the FFT that looks
for periodicity in historical data on sunspot activity
12-28
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement