S.R. Otto and J.P. Denier
An Introduction to Programming and Numerical Methods in MATLAB With 111 Figures
S.R. Otto, BSc, PhD The R & A St Andrews Fife KY16 9JD Scotland J.P. Denier, BSc (Hons), PhD School of Mathematical Sciences The University of Adelaide South Australia 5005 Australia
British Library Cataloguing in Publication Data Otto, S. R. (Stephen Robert) An introduction to programming and numerical methods in MATLAB 1. MATLAB (Computer file) 2. Numerical analysis — Data processing I. Title II. Denier, J. P. 518′.02855 ISBN 1852339195 Library of Congress Control Number: 2005923332 Apart from any fair dealing for the purposes of research or private study, or criticism or review, as permitted under the Copyright, Designs and Patents Act 1988, this publication may only be reproduced, stored or transmitted, in any form or by any means, with the prior permission in writing of the publishers, or in the case of reprographic reproduction in accordance with the terms of licences issued by the Copyright Licensing Agency. Enquiries concerning reproduction outside those terms should be sent to the publishers. ISBN-10: 1-85233-919-5 ISBN-13: 978-185233-919-7 Springer Science+Business Media springeronline.com © Springer-Verlag London Limited 2005 The use of registered names, trademarks, etc. in this publication does not imply, even in the absence of a specific statement, that such names are exempt from the relevant laws and regulations and therefore free for general use. The publisher makes no representation, express or implied, with regard to the accuracy of the information contained in this book and cannot accept any legal responsibility or liability for any errors or omissions that may be made. Typesetting: Camera-ready by authors Printed in the United States of America 12/3830-543210 Printed on acid-free paper SPIN 11317333
For Julie and Jill and Megan.
Preface
This text provides an introduction to the numerical methods that are typically encountered (and used) in science and engineering undergraduate courses. The material is developed in tandem with MATLAB which allows rapid prototyping and testing of the methods. The package MATLAB (matrix laboratory) provides an environment in which students can learn to programme and explore the structure of the numerical methods. The methods included here are of a basic nature and only rely on material which should have been explored prior to the first year undergraduate stage. The methods presented are supplemented with a set of tasks at the end of each chapter (full solutions of these are given in Appendix C). The tasks are introduced in such a way as to allow students to explore the topics as they evolve. Some are of a mathematical nature, but in the main they involve manipulating codes which are given in the text of the chapter (or section). Those tasks which we regard as being harder are marked with an asterisk. Throughout the text MATLAB commands appear using this font in the text. In the main the names of MATLAB commands reflect the commands rˆ ole. We have taken particular care to highlight many of the problems that occur with interpreting the syntax of MATLAB commands. In Appendix B we provide a glossary of all MATLAB commands within the text and short examples of how these commands can be used. Reference is made to the comprehensive help facility within MATLAB: however examples are given which are similar to those given in other places within the text. Throughout the text we derive the numerical techniques we use, but also emphasise that MATLAB’s rich vocabulary provides commands for performing most of the fundamental tasks encountered in numerical methods. This approach serves to introduce students to the methods and also provides an
viii
Preface
understanding of their inner workings.
Why Do We Need Numerical Methods? Mathematics is an elegant and precise subject: however when numerical answers are required one sometimes needs to rely on approximate methods to obtain useable answers. There are many problems which simply do not have analytical solutions, or those whose exact solution is beyond our current state of knowledge. There are also many problems which are too long (or tedious) to solve by hand. When such problems arise we can exploit numerical analysis to reduce the problem to one involving a finite number of unknowns and use a computer to solve the resulting equations. The text starts with a description of how we could perform some very basic calculations (that is, simply using the computer as a calculator). It then moves on to solving problems which cannot, in practice, be solved by hand. Sometimes the solution of these problems can become as intricate and involved as the original problems and requires almost as much finesse and care to obtain a solution. There are several options available to us, both in terms of language and also overall approach. In this book we elect to express our ideas in terms of the syntax of the computer package MATLAB. Once you have mastered the syntax of MATLAB it will be easier for you to learn other languages, if you should decide you need to.
The Structure of This Text This text is designed to be used as a source of reference for MATLAB commands (mainly through the glossary in Appendix B) and the examples given in the chapters. This is an approach we have found works well with our students. The text gives an introduction to numerical methods and the manipulation of the quantities used therein (for instance matrices). At each stage, short codes are given to allow the reader to try their own examples. Examples of code which can be typed at the MATLAB prompt will appear within the general text in this font (this font is also used for the names of MATLAB codes), while longer examples will be written >> commands to be entered Results
Preface
ix
Those codes which are designed to be saved to a file will appear in boxes a = 1; (sometimes wider boxes will be used for codes with longer lines). At the end of each section, or chapter, there are a variety of tasks which are designed to help the reader understand the topics they have just read. Solutions of these are given in Appendix C. Chapter 2 concentrates on some aspects of programming. We also introduce another of MATLAB’s powerful tools, namely its ability to produce high quality plots of data. Students are shown how to create codes and functions, which serve to augment MATLAB’s built-in vocabulary. This chapter concludes with a discussion of the important topic of errors, both from the perspective of classical numerical analysis and also from human interaction which arise in the action of coding. We have found that students benefit enormously from debugging programmes and it is hoped that this will help them to hone these skills, which we consider to be essential. The third chapter contains a discussion of looping and logical structures within MATLAB. Again the mathematics is developed in tandem. Finally concluding the first part of the book we give some examples of how MATLAB can be used to solve problems (using just algebra and exploiting MATLAB as an advanced calculator). In Chapters 4 and 5 we meet some classical numerical methods, in the form of root finding and interpolation (and extrapolation). Although MATLAB has intrinsic functions which will perform most of these operations (fzero and polyfit) we have included a detailed description of both topics. This is aimed at helping the students to understand how these methods work, and where they can potentially fail. In Chapter 5 we discuss the general form of Newton forward differences, which are used in this chapter and subsequent ones (for instance to derive the formula for integration). In the next two chapters we explore the numerical analysis associated with integration and differentiation. In Chapter 6 we return to the topic of matrices. We start by discussing the mathematical concepts of rank and linear independence. We also discuss eigenvalues and eigenvectors (and their interpretation for 2-by-2 matrices). The topic of numerical integration is taken up in Chapter 7 and in Chapter 8 methods for the numerical solution of ordinary differential equations are explored. Finally in Chapter 9 we use MATLAB to calculate some basic statistical quantities and also to explore some maps, some of which may be exhibit chaotic behaviour. The text finishes with appendices containing an introduction to the basics
x
Preface
of matrix algebra, a glossary of useful terms and solutions to all the tasks contained within the text. These appendices have deliberately been made quite wordy, since we believe that the material they contain is one of the important aspects of the book. At the outset we expect readers to be mathematically literate to the level of being able to: and solve algebraic equations (for instance determine the roots of a quadratic and solve simultaneous equations); integrate and differentiate simple functions; solve separable differential equations (although examples are given within the text). Although exposure to complex numbers and matrices would be useful at the start of the text, it is not necessary as these concepts are introduced in some detail in the introductory chapter. We would like to thank students of the University of Birmingham whose patience and comments have been invaluable in the construction of this text. In particular we would like to identify Sukhjinder Chana and Rob Ackeroyd for their careful proof reading and comments. St Andrews, UK Adelaide, Australia
S. R. Otto J. P. Denier
Contents
1.
2.
Simple Calculations with MATLAB . . . . . . . . . . . . . . . . . . . . . . . . 1.1 Introduction and a Word of Warning . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Scalar Quantities and Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.1 Rules for Naming of Variables . . . . . . . . . . . . . . . . . . . . . . . . 1.2.2 Precedence: The Order in Which Calculations Are Performed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.3 Mathematical Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Format: The Way in Which Numbers Appear . . . . . . . . . . . . . . . . 1.4 Vectors in MATLAB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4.1 Initialising Vector Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4.2 Manipulating Vectors and Dot Arithmetic . . . . . . . . . . . . . 1.5 Setting Up Mathematical Functions . . . . . . . . . . . . . . . . . . . . . . . . . 1.6 Some MATLAB Specific Commands . . . . . . . . . . . . . . . . . . . . . . . . 1.6.1 Looking at Variables and Their Sizes . . . . . . . . . . . . . . . . . . 1.7 Accessing Elements of Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.8 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1 1 2 4 5 8 12 13 13 14 17 20 22 23 24
Writing Scripts and Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1 Creating Scripts and Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.2 Brief Aside . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Plotting Simple Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1 Evaluating Polynomials and Plotting Curves . . . . . . . . . . . 2.2.2 More on Plotting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Functions of Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27 27 30 35 36 41 44 49 51
xii
Contents
2.4.1 Numerical Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 2.4.2 User Error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 2.5 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 3.
Loops and Conditional Statements . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Loops Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Summing Series . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . N 3.3.1 Sums of Series of the Form jp, p ∈ N . . . . . . . . . . . . . . .
63 63 63 68 73
j=1
3.4
3.5 3.6 3.7 3.8
3.3.2 Summing Infinite Series . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.3 Summing Series Using MATLAB Specific Commands . . . 3.3.4 Loops Within Loops (Nested) . . . . . . . . . . . . . . . . . . . . . . . . Conditional Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.1 Constructing Logical Statements . . . . . . . . . . . . . . . . . . . . . 3.4.2 The MATLAB Command switch . . . . . . . . . . . . . . . . . . . . Conditional loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.1 The break Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MATLAB Specific Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Error Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
76 79 82 83 85 88 90 92 92 94 97
4.
Root Finding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 4.2 Initial Estimates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 4.3 Fixed Point Iteration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 4.4 Bisection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 4.5 Newton–Raphson and Secant Methods . . . . . . . . . . . . . . . . . . . . . . 117 4.5.1 Derivation of the Newton–Raphson Method . . . . . . . . . . . . 117 4.6 Repeated Roots of Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 4.7 Zeros of Higher-Dimensional Functions(*) . . . . . . . . . . . . . . . . . . . 125 4.8 MATLAB Routines for Finding Zeros . . . . . . . . . . . . . . . . . . . . . . . 128 4.8.1 Roots of a Polynomial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 4.8.2 The Command fzero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 4.9 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
5.
Interpolation and Extrapolation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 5.2 Saving and Reading Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 5.3 Which Points to Use? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 5.4 Newton Forward Differences and Lagrange Polynomials . . . . . . . 141 5.4.1 Linear Interpolation/Extrapolation . . . . . . . . . . . . . . . . . . . 147
Contents
xiii
5.5 5.6 5.7 5.8
Calculating Interpolated and Extrapolated Values . . . . . . . . . . . . 148 Splines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 Curves of Best Fit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 Interpolation of Non-Smooth Data . . . . . . . . . . . . . . . . . . . . . . . . . . 155 5.8.1 Insufficient Data Points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 5.9 Minimisation of Functions and Parameter Retrieval . . . . . . . . . . . 161 5.9.1 Parameter Retrieval . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 5.9.2 Using fmins for Parameter Retrieval . . . . . . . . . . . . . . . . . . 164 5.10 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 6.
Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 6.1.1 Initialising Matrices Within MATLAB . . . . . . . . . . . . . . . . 169 6.1.2 Matrix Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 6.1.3 Operations on Elements of Matrices . . . . . . . . . . . . . . . . . . 180 6.1.4 More on Special Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 6.1.5 Matrices Containing Strings . . . . . . . . . . . . . . . . . . . . . . . . . 185 6.2 Properties of Matrices and Systems of Equations . . . . . . . . . . . . . 186 6.2.1 Determinants of Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190 6.3 Elementary Row Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 6.3.1 Solving Many Equations at Once . . . . . . . . . . . . . . . . . . . . . 198 6.4 Matrix Decomposition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 6.5 Eigenvalues and Eigenvectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 6.6 Specific MATLAB Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 6.7 Characteristic Polynomials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 6.8 Exponentials of Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 6.9 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
7.
Numerical Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 7.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 7.2 Integration Using Straight Lines . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 7.2.1 Errors in the Trapezium Method . . . . . . . . . . . . . . . . . . . . . 229 7.3 Integration Using Quadratics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 7.4 Integration Using Cubic Polynomials . . . . . . . . . . . . . . . . . . . . . . . . 235 7.5 Integrating Using MATLAB Commands . . . . . . . . . . . . . . . . . . . . . 237 7.6 Specific Examples of Integrals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238 7.6.1 Infinite Integrals and Removable Singularities . . . . . . . . . . 238 7.6.2 Indefinite Integrals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 7.7 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
xiv
Contents
8.
Solving Differential Equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 8.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 8.2 Euler’s Method and Crank–Nicolson . . . . . . . . . . . . . . . . . . . . . . . . 247 8.2.1 Analytical Comparisons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 8.3 Banded Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 8.4 Runge–Kutta Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 8.5 Higher-Order Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 8.5.1 Second-Order Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 8.5.2 Bessel’s equation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 8.5.3 Airy’s Equation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273 8.5.4 Shooting Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274 8.6 Boundary-Value Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 8.7 Population Dynamics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 8.8 Eigenvalues of Differential Systems . . . . . . . . . . . . . . . . . . . . . . . . . 285 8.9 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
9.
Simulations and Random Numbers . . . . . . . . . . . . . . . . . . . . . . . . . 291 9.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 9.2 Statistical quantities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 9.2.1 Averages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 9.2.2 Other Statistical Measures . . . . . . . . . . . . . . . . . . . . . . . . . . . 293 9.3 Random Numbers and Distributions . . . . . . . . . . . . . . . . . . . . . . . . 295 9.3.1 Normal Distribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298 9.3.2 Calculating Probabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 9.3.3 Permutations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300 9.4 Maps and White Noise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300 9.4.1 Modelling Discrete Systems . . . . . . . . . . . . . . . . . . . . . . . . . . 307 9.4.2 Periodicity and Chaos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 9.4.3 Random Motion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316 9.5 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
A. A Mathematical Introduction to Matrices . . . . . . . . . . . . . . . . . . 323 A.1 Special Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330 A.2 Inverses of Matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 B. Glossary of Useful Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335 B.1 Arithmetic and Logical Operators . . . . . . . . . . . . . . . . . . . . . . . . . . 335 B.2 Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343 B.3 Plotting Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347 B.4 General MATLAB Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
Contents
xv
C. Solutions to Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 C.1 Solutions for Tasks from Chapter 1 . . . . . . . . . . . . . . . . . . . . . . . . . 389 C.2 Solutions for Tasks from Chapter 2 . . . . . . . . . . . . . . . . . . . . . . . . . 394 C.3 Solutions for Tasks from Chapter 3 . . . . . . . . . . . . . . . . . . . . . . . . . 400 C.4 Solutions for Tasks from Chapter 4 . . . . . . . . . . . . . . . . . . . . . . . . . 408 C.5 Solutions for Tasks from Chapter 5 . . . . . . . . . . . . . . . . . . . . . . . . . 414 C.6 Solutions for Tasks from Chapter 6 . . . . . . . . . . . . . . . . . . . . . . . . . 418 C.7 Solutions for Tasks from Chapter 7 . . . . . . . . . . . . . . . . . . . . . . . . . 429 C.8 Solutions for Tasks from Chapter 8 . . . . . . . . . . . . . . . . . . . . . . . . . 436 C.9 Solutions for Tasks from Chapter 9 . . . . . . . . . . . . . . . . . . . . . . . . . 454 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
1
Simple Calculations with MATLAB
1.1 Introduction and a Word of Warning MATLAB is an incredibly powerful tool, but in order to use it safely you need to be able to understand how it works and to be very precise when you enter commands. Changing the way you enter a command, even subtly can completely change its meaning. The main aim of this text is to teach you to converse with MATLAB and understand its responses. It is possible to interact with MATLAB using a “phrase book” approach, which is fine if the answer is what you expect. However it is far better to learn the language so that you can understand the response. As well as learning the language it is essential that you learn the grammar or syntax; this is perhaps even more important with computer languages than conventional languages! MATLAB uses an interpreter to try to understand what you type and this can come back with suggestions as to where you might have gone wrong: sometimes what you have written makes sense to MATLAB but does not mean what you expect! So you need to be careful. It is crucial that you formulate ideas clearly in your head (or on paper) before trying to translate them into MATLAB (or any other language). We begin by discussing mathematical operations performed on scalars1 . It is crucial that the material in this chapter is understood before proceeding, as it forms the basis of all that is to follow2 . 1 2
That is numbers. MATLAB has a wealth of introductory material available to the user that can
2
1. Simple Calculations with MATLAB
We shall start by introducing MATLAB commands which can be typed at the MATLAB prompt; these will ultimately form part of our vocabulary of MATLAB commands. MATLAB already has an extensive vocabulary: however we will learn that we can expand this set. As the name MATLAB (MATrix LABoratory) suggests, most of the commands work with matrices and these will be discussed in due course. We shall start with scalar operations, for which MATLAB acts like a very powerful calculator.
1.2 Scalar Quantities and Variables We will begin with the basic ideas of equations and variables. Try entering the commands as they are given. Consider the following two commands: >> a = 3 a = 3 >> b = 4; 3
These two commands are entered on separate lines; the MATLAB prompt is denoted by >> (which does not need to be typed), as distinguished from the standard greater than sign >. The command on the first line sets the variable a to be equal to three (3) and that on the second line sets the variable b to be equal to four (4). The two commands also differ because the second one ends with a semicolon. This instructs MATLAB to execute the command but suppress any output; whereas above we can see that the value of a has been set to 3. These commands can be read as set a equal to 3 set b equal to 4 (and suppress output) Reading the commands in this way it should be clear that it is not possible to have a command of the form 7 = x (set 7 equal to x), whereas we could have x = 7 (set x equal to 7). These variables can now be used again, for instance
3
be accessed using the commands demo or tour. There is also a good help facility which, unsurprisingly, can be accessed by typing help followed by the command in question. There is also a facility to use a web browser (helpdesk or helpbrowser). Here, you would type a = 3, and then press RETURN, and then type b = 4; and press RETURN again. The spaces are included purely for clarity.
1.2 Scalar Quantities and Variables
3
>> a = 3; >> b = a+1; >> x = a+b; The first line sets the variable a to be equal to 3, the semicolon instructing MATLAB to execute the command but to suppress the output. The second line sets b to be equal to a plus one, namely 4: again the semicolon suppresses output. The third line sets x to be a+b which is 7 (again output is suppressed). MATLAB can be used as a very powerful calculator and its operations fall into two basic groups: unary and binary, the former operating on one quantity and the latter on two. We shall begin by considering simple arithmetic operations, which are binary. For instance typing 3*4 generates >> 3*4 ans = 12 Notice here that we have multiplied the two integers 3 and 4, and the answer has been returned correctly as 12. MATLAB uses the variable ans to store the result of our calculation, in this case the value 12, so that it can be used in the subsequent commands. For instance the command ans*3 will generate the result 36 (and now the variable ans will have the value 36). We could also have used the commands a = 3; b = 4; x = a*b which can be typed on one line and read as set a equal to 3 (don’t output anything), set b equal to 4 (don’t output anything) and set x equal to a times b Division works in exactly the same way as in the multiplication example above. If we try the command 3/4, MATLAB returns the value 0.75. It is a good idea to use meaningful variable names and we shall shortly discuss valid forms for these.
Example 1.1 Try entering the following commands into MATLAB, but before you do so try to work out what output you would expect. >> >> >> >> >>
3*5*6 z1 = 34; z2 = 17; z3 = -8; z1/z2
4
1. Simple Calculations with MATLAB
>> z1-z3 >> z2+z3-z1 Hopefully you should get the answers, 90, 2, 42 and −25. Example 1.2 Here we give an example of the simple use of brackets: >> >> >> >> >> >> >>
format rat a = 2; b = 3; c = 4; a*(b+c) a*b+c a/b+c a/(b+c) format
In this example you should get the answers, 14, 10, 14/3 and 2/7. Hopefully this gives you some idea that brackets make MATLAB perform those calculations first. (The command format rat has been used to force the results to be shown as rationals, the final command format reverts to the default, which happens to be format short.)
1.2.1 Rules for Naming of Variables In the examples we have seen so far we have simply used variable names which seemed to suit the task at hand with no mention of restrictions on allowable variable names in MATLAB. The rules for naming variables in MATLAB can be summarised as follows: 1. Variable names in MATLAB must start with a letter and can be up to 31 characters long. The trailing characters can be numbers, letters or underscores (some other characters are also available but in this text we shall stick to these). There are many choices which are forbidden as variable names, some for very obvious reasons (such as a*b which signifies a multiplication of the variables a and b) and others for more subtle reasons (a good example is4 a.b). The rules for naming variables also hold for naming MATLAB files. However, in this case a single dot is allowed within the name of the file; everything after the dot is used to tell MATLAB what type of file it is dealing 4
The reason this is not a valid variable name lays in the fact that MATLAB supports object orientated programming. Because of this a.b refers to the value of the “b” component of the object a.
1.2 Scalar Quantities and Variables
5
with (whether it be a file containing MATLAB code, or data etc). We will see more on this later in the section on script files. 2. Variable names in MATLAB are case sensitive, so that a and A are two different objects. 3. It is good programming practise to employ meaningful variable names. In our initial examples we have only used very simple (but appropriate) names: however as the examples become more complex our variable names will be more informative. 4. Variables names should not coincide with a predefined MATLAB command or with any user-defined subroutines. To see whether a variable name is already in use we can use the command type variable name, but it may be better to use the command which variable name (this will tell you whether the name variable name corresponds to an existing code or intrinsic function.
1.2.2 Precedence: The Order in Which Calculations Are Performed This represents one of the most common sources of errors and it is often the most difficult to detect. Before proceeding we briefly comment on the question of precedence, or the order in which commands are executed. Consider the mathematical expression a(b + c) which you might read as “a times b plus c” which would appear to translate to the MATLAB command a*b+c. Hopefully you can see that this actually is equal to ab+c. The correct MATLAB command for a(b + c) is a*(b+c). The brackets have been used to force MATLAB to first evaluate the expression (b+c) and then to multiply the result by a. We should avoid falling into the trap of assuming that commands are performed from leftto-right, for instance c+a*b is equal to c + ab (not (c + a)b as if the addition was performed first). At this point we should pause briefly and make sure the ideas of brackets are firmly in place. Brackets should always appear in pairs and the mathematics contained within brackets (or equivalently MATLAB) will be evaluated first. Hopefully this concept is familiar to you: however it is worth reiterating, since one of the most common problems in using MATLAB occurs due to either unbalanced or incorrectly placed brackets. For example the commands (3+4/5) and (3+4)/5 are obviously different, the former being 3 45 and the latter being 3+4 5 . The most critical use of brackets, which circumvents another popular source
6
1. Simple Calculations with MATLAB
of error, is in terms of division. We should note that in the syntax of MATLAB a a/b*c is not equal to bc but ab c. In order to ensure that the denominator of the fraction is calculated first we would need to use a/(b*c), which is equal to a bc . Similarly for examples like a/b+c versus a/(b+c). Example 1.3 Determine the value of the expression a(b + c(c + d))a, where a = 2, b = 3, c = −4 and d = −3. Although this is a relatively simple example it is worth constructing the MATLAB statement to evaluate the expression: >> a = 2; b = 3; c = -4; d = -3; >> a*(b+c*(c+d))*a This gives the answer 124. It is worth pausing here to consider the syntax of these commands. In the first line of this code we initialize the four variables a, b, c and d to have the values 2, 3, −4 and −3 respectively. The commands each end with semicolons; we have chosen to place all four commands on one line: however they could just as easily be placed on separate lines. With the variables assigned values we can now use them to perform calculations, such as in the second line where we form the mathematical expression a(b + c(c + d))a. Note all multiplications must be denoted by an asterisk and brackets have been used to force precedence of the operation; of course the brackets must balance (for each left bracket there is a corresponding right bracket) for the expression to make sense.
Example 1.4 Evaluate the MATLAB expressions ' $ 1+2/3*4-5 1/2/3/4 1/2+3/4*5 5-2*3*(2+7) (1+3)*(2-3)/3*4 (2-3*(4-3))*4/5 & % by hand and then check answers with MATLAB. Recall that the operations of division and multiplication take precedence over addition and subtraction (type help precedence at the MATLAB prompt for more details).
1.2 Scalar Quantities and Variables
7
The expressions are given by 2 4 1+2/3*4-5 = 1 + 4 − 5 = − , 3 3 1 , 1/2/3/4 = (((1/2)/3)/4) = 24 1 3 17 1/2+3/4*5 = + 5 = , 2 4 4 5-2*3*(2+7) = 5 − 6(9) = −49, 16 4 × (−1) 4=− , 3 3 4 4 (2-3*(4-3))*4/5 = (2 − 3 × 1) = − ; 5 5 (1+3)*(2-3)/3*4 =
which can be verified in MATLAB; we can use the command format rat to force MATLAB to output the results as rational numbers (that is, fractions). We mention here MATLAB has a number of intrinsic constants which the programmer can use, for instance pi and eps. The former is merely π = 3.14159265 · · · and the latter is the distance from unity to the next real number in MATLAB5 . It is also possible to enter numbers using the exponent-mantissa form. This uses the fact that numbers can be written as “mantissa × 10exponent ”, for example Number 789.34 0.0001 4 400000000000
mantissa - exponent 7.8934 × 102 1 × 10−4 4 × 100 4 × 1011
MATLAB form 7.8934e2 1e-4 4 4e11
Example 1.5 Write 3432.6 in exponent-mantissa form and write 100 × 1010 in normal form. We have 3432.6 ≡ 3.4326 × 103 and 100 × 1010 ≡ 1, 000, 000, 000, 000. 5
The smallest positive number that MATLAB can store which is different from zero is realmin which is approximately 10−308 , whilst the largest number is realmax which approximately 10308 . These intrinsic constants may be dependent upon your version of MATLAB and/or your computer’s operating system.
8
1. Simple Calculations with MATLAB
Example 1.6 Use MATLAB to calculate the expression a b− b + b+a ca where a = 3, b = 5 and c = −3. The code for this purpose is: a = 3; b = 5; c = -3; x = b-a/(b+(b+a)/(c*a)); with the solution being contained in the variable x.
Example 1.7 Enter the numbers x = 45 × 109 and y = 0.0000003123 using the exponent-mantissa syntax described above. Calculate the quantity xy using MATLAB and by hand. This is accomplished using the code x = 45e9; y = 3.123e-7; xy = x*y; Notice that here we have used a variable name xy which should not be confused with the mathematical expression xy (that is x × y). We can now set the values of variables and perform basic arithmetic operations. We now proceed to discuss other mathematical operations.
1.2.3 Mathematical Functions Before we proceed let us try some more of the “calculator” functions (that is, those which are familiar from any scientific calculator). Arithmetic functions +, -, / and *. Trigonometric functions sin (sine), cos (cosine) and tan (tangent) (with their inverses being obtained by appending an a as in asin, acos or atan). These functions take an argument in radians, and the result of the inverse functions is returned in radians. It should be noted these are functions and as such should operate on an input; the syntax of the commands is sin(x) rather than sin x.
1.2 Scalar Quantities and Variables
9
Exponential functions exp, log, log10 and ˆ. These are largely self explanatory, but notice the default in MATLAB for a logarithm is the natural logarithm ln x. The final command takes two arguments (and hence is a binary operation) so that aˆb gives ab . Other functions There are a variety of other functions available in MATLAB that are not so commonly used, but which will definitely be useful:
round(x) ceil(x) floor(x) fix(x) rem(x,y) mod(x,y) abs(x) sign(x) factor(x)
Rounds a number to the nearest integer Rounds a number up to the nearest integer Rounds a number down to the nearest integer Rounds a number to the nearest integer towards zero The remainder left after division The signed remainder left after division The absolute value of x The sign of x The prime factors of x
There are many others which we will meet throughout this book. We note that the final command factor gives multiple outputs. We now construct some more involved examples to illustrate how these functions work. Example 1.8 Calculate the expressions: sin 60◦ (and the same quantity squared), exp(ln(4)), cos 45◦ − sin 45◦ , ln exp(2 + cos π) and tan 30◦ /(tan π/4 + tan π/3). We shall give the MATLAB code used for the calculation together with the results: >> x = sin(60/180*pi) x = 0.8660 >> y = xˆ2 y = 0.7500 >> exp(log(4))
10
1. Simple Calculations with MATLAB
ans = 4 >> z = 45/180*pi; cos(z)-sin(z) ans = 1.1102e-16 >> log(exp(2+cos(pi))) ans = 1 >> tan(30/180*pi)/(tan(pi/4)+tan(pi/3)) ans = 0.2113 √ √ The values of these expressions should be 3/2, 3/4, 4, 0, 1 and 1/(3 + 3). Notice that zero has been approximated by 1.1102e-16 which is smaller than the MATLAB variable eps, which reflects the accuracy to which this calculation is performed. It is worth going through the previous example in order to practise the command syntax. Getting this right is crucial since it is only through mastering the correct syntax (that is, the MATLAB language) that you will be able to communicate with MATLAB. When you first start programming it is common to get the command syntax confused. To emphasise this let’s consider some of the commands above in a little more detail. Let us start with f (x) = x sin x: the MATLAB command to return a value of this expression is x*sin(x) and not x*sinx or xsin(x). The command x*sinx would try to multiply the variable x by the variable sinx; unless the variable sinx is defined (it isn’t) MATLAB would return an error message ??? Undefined function or variable ’sinx’. Similarly the command xsin(x) tries to evaluate the MATLAB function xsin, which isn’t defined, at the point x. Again MATLAB would return an error
1.2 Scalar Quantities and Variables
11
message, in this case ??? Undefined function or variable ’xsin’. In cases such as these MATLAB provides useful information as to where we have gone wrong; information we can use to remedy the syntax error in our piece of code. This simple example emphasises the need to read your code very carefully to ensure such syntax errors are avoided. Important Point It is essential that arguments for functions are contained within round brackets, for instance cos(x) and that where functions are multiplied together an asterisk is used, for instance f (x) = (x + 2) cos x should be written (x+2)*cos(x).
Example 1.9 The functions we used in the previous example all took a single argument as input, for example sin(x). Mathematically we can define functions of two or more variables. MATLAB has a number of intrinsic functions of this type (such as the remainder function rem). To see how these are employed in MATLAB we consider two examples of such functions, one of which takes multiple inputs and returns a single output and the other which takes a single input and returns multiple outputs. Our first example is the MATLAB function rem. The command rem(x,y) calculates the remainder when x is divided by y. For example 12345 = 9 × 1371 + 6, so the remainder when 12345 is divided by 9 is equal to 6. We can determine this with MATLAB by simply using rem(12345,9). An example of a command which takes a single input and returns multiple outputs is factor which provides the prime decomposition of an integer. For example >> factor(24) ans = [2 2 2 3] Here the solution is returned as an array of numbers as the answer is not a scalar quantity. We could just as easily used the command x = factor(24) to set x equal to the array [2 2 2 3]. We can now check MATLAB has correctly
12
1. Simple Calculations with MATLAB
determined the prime decomposition of the number 24 by multiplying the elements of the array x together; this is most readily achieved by using another intrinsic function prod(x).
1.3 Format: The Way in Which Numbers Appear Before we proceed we stop to discuss this important topic. This can be simply illustrated by the following example:
Example 1.10 Consider the following code # s = [1/2 1/3 pi sqrt(2)]; format short; s format long; s format rat; s format ; s " this generates the output
!
>> format short; s s = 0.5000
0.3333
3.1416
1.4142
>> format long; s s = 0.50000000000000
0.33333333333333
3.14159265358979
>> format rat; s s = 1/2
1/3
355/113
>> format ; s s = 0.5000
0.3333
3.1416
1.4142
1393/985
1.41421356237310
1.4 Vectors in MATLAB
13
There are other options for format which you can see by typing help format. The default option is format short (which can be reverted back to by simply typing format). The above options are short – 5 digits long – 15 digits rat – try to represent the answer as a rational. You should note that whilst format rat is very useful, it can lead to misleading answers (in the above example clearly π is not equal to 355/113). At the start of a calculation it is a good idea to ensure that the data is being displayed in the appropriate format. In this example we have performed an operation on four numbers at once using the vector construction in MATLAB. We now proceed to discuss this further.
1.4 Vectors in MATLAB One of the most powerful aspects of MATLAB is its use of vectors (and ultimately matrices) as objects. In this section we shall introduce the idea of initiating vectors and how they can be manipulated as “MATLAB objects”.
1.4.1 Initialising Vector Objects We shall start with simple objects and construct these using the colon symbol: r = 1:5;
This sets the variable r to be equal to the vector [1 2 3 4 5] (and the semicolon suppresses output, as normal). This is a row vector, which we can see by typing size(r) (which returns [1 5], indicating that r has one row and five columns). This simple way of constructing a vector r = a:b creates a vector r which runs from a to b in steps of one. We can change the step by using the slightly more involved syntax r = a:h:b, which creates the vector r running from a to b in steps of h, for instance r = 1:2:5; s = 1:0.5:3.5;
14
1. Simple Calculations with MATLAB
gives r = [1 3 5] and s = [1 1.5 2 2.5 3 3.5]. We note that if the interval b-a is not exactly divisible by h, then the loop will run up until it exceeds b, for instance t = 1:2:6 gives t = [1 3 5]. We can also initiate vectors by typing the individual entries; this is especially useful if the data is irregular, for instance t = [14 20 27 10];. There are many other ways of setting up vectors and for the moment we shall only mention one more. This is the command linspace: this has two syntaxes s = linspace(0,1); t = linspace(0,1,10); Here s is set up as a row vector which runs from zero to one and has one hundred elements and t again runs from zero to one but now has ten elements. Note here that to set up a vector which runs from zero to one in steps of 1/N , we can use w = 0:1/N:1 or W = linspace(0,1,N+1). (For example trying typing s=0:0.1:1.0; length(s). You will find that s has eleven elements!). The command linspace is especially useful when setting up mathematical functions as we shall discover in the next section.
1.4.2 Manipulating Vectors and Dot Arithmetic We shall now talk about the idea of calculations involving vectors and for this purpose we shall discuss dot arithmetic. This allows us to manipulate vectors in an element-wise fashion rather than treating them as mathematical objects (in fact for addition and subtraction this is the same thing). To see how dot arithmetic works let’s consider a simple example: >> a = [1 2 3]; >> 2*a; ans = 2
4
6
Suppose now we try to multiply a vector by a vector, as in >> a = [1 2 3]; >> b = [4 5 6]; >> a*b ??? Error using ==> * Inner matrix dimensions must agree.
1.4 Vectors in MATLAB
15
An error message appears because both a and b are row vectors and therefore cannot be multiplied together. Suppose however that what we really want to achieve is to multiply the elements of vector a by the elements of vector b in an element by element sense. We can achieve this in MATLAB by using dot arithmetic as follows >> a = [1 2 3]; >> b = [4 5 6]; >> a.*b ans = 4
10
18
A glance at the answer shows that MATLAB has returned a vector containing the elements [a1 b1 , a2 b2 , a3 b3 ]. The . indicates to MATLAB to perform the operation term by term and the * indicates we require a multiplication. We can also do a term by term division with >> a = [1 2 3]; >> b = [4 5 6]; >> a./b ans = 0.2500
0.4000
0.5000
The result is, as we would expect, a1 a2 a3 . , , b1 b2 b3 Example 1.11 We shall create two vectors running from one to six and from six to one and then demonstrate the use of the dot arithmetical operations:
16
1. Simple Calculations with MATLAB
' s = 1:6; t = 6:-1:1; s+t s-t s.*t s./t s.ˆ2 1./s s/2 s+1 & This produces the output
$
%
>> s+t ans = 7
7
7
7
7
7
-3
-1
1
3
5
10
12
12
10
6
>> s-t ans = -5 >> s.*t ans = 6 >> s./t ans = 0.1667
0.4000
0.7500
1.3333
>> s.ˆ2 ans = 1
4
9
16
25
36
2.5000
6.0000
1.5 Setting Up Mathematical Functions
17
>> 1./s ans = 1.0000
0.5000
0.3333
0.2500
0.2000
0.1667
1.0000
1.5000
2.0000
2.5000
3.0000
>> s/2 ans = 0.5000 >> s+1 ans = 2
3
4
5
6
7
These represent most of the simple operations which we may want to use. We note that in order for these operations to be viable the vectors need to be of the same size (unless one of them is a scalar – as in the last three examples).
1.5 Setting Up Mathematical Functions Following on from the previous section we discuss how one might evaluate a function. It is crucial that you understand this section before you proceed. We revisit the topics introduced in the previous section and discuss the ways in which you can set up the input to the function
Example 1.12 Set up a vector x which contains the values from zero to one in steps of one tenth. This can be done in a variety of ways:
18
1. Simple Calculations with MATLAB
' % Firstly just list all the values: x = [0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0];
$
% Use the colon construction x = 0:0.1:1.0; % Or use the command linspace x = linspace(0,1,11); & % As noted previously we note that there are eleven values between zero and one (inclusive) for a step length of one tenth. You may want to try linspace(0,1,10) and see what values you get. Each of these methods are equally valid (and more importantly will produce the same answer) but the latter two are probably preferable, since they are easily extended to more elements. We now wish to set up a simple mathematical function, say for instance y = x2 . Initially you may want to type xˆ2 but this will generate the error message ??? Error using ==> ˆ Matrix must be square. This is because this operation is trying to perform the mathematical operation x × x and this operation is not possible. Instead we need to use y=x.ˆ2 which gives >> y = x.ˆ2 y = Columns 1 through 7 0
0.0100
0.0400
0.0900
0.8100
1.0000
0.1600
0.2500
0.3600
Columns 8 through 11 0.4900
0.6400
Here we see that each element of x has been squared and stored in the array y. Equivalently we could use y = x.*x;. Example 1.13 Construct the polynomial y = (x + 2)2 (x3 + 1) for values of x from minus one to one in steps of 0.1.
1.5 Setting Up Mathematical Functions
19
Here it would be laborious to type out all the elements of the vector so instead we use the colon construction. We shall also define f = (x + 2) and g = x3 + 1, so that we have the code: x = -1:0.1:1; f = x+2; g = x.ˆ3+1; y = (f.ˆ2).*(g); In the construction of g we have used the dot arithmetic to cube each element and then add one to it. When constructing y we firstly square each element of f (with f.ˆ2) and then multiply each element of this by the corresponding element of g. You should make sure that you are able to understand this example.
Example 1.14 Construct the function y =
x2 for values of x from one to x3 + 1
two in steps of 0.01. Here we merely give the solution: x = 1:0.01:2; f = x.ˆ2; g = x.ˆ3+1; y = f./g; (We could have combined the last three lines into the single expression y = x.ˆ2./(x.ˆ3+1);). For the moment it may be a good idea to use intermediate functions when constructing complicated functions.
Example 1.15 Construct the function x cos x y(x) = sin , x2 + 3x + 1 for values of x from one to three in steps of 0.02. Here, again, we use the idea of intermediate functions
20
1. Simple Calculations with MATLAB
x = 1:0.02:3; f = x.*cos(x); g = x.ˆ2+3*x+1; y = sin(f./g);
NB MATLAB will actually calculate f/g and in this case it will return a scalar value of −0.1081. Unfortunately this will not generate an error but it will mean that the answer is not a vector as we should be expecting.
1.6 Some MATLAB Specific Commands We shall now introduce a couple of commands which can be used to make calculations where the input can take a variety of forms. The first command is polyval. This command takes two inputs, namely the coefficients of a polynomial and the values at which you want to evaluate it. In the following example we shall use a cubic but hopefully you will be able to see how this generalises to polynomials of other orders. Example 1.16 Evaluate the cubic y = x3 + 3x2 − x − 1 at the points x = (1, 2, 3, 4, 5, 6). We provide the solution to this example as a commented code: ' $ % Firstly set up the points at which the polynomial % is to be evaluated x = 1:6; % % % c
Enter the coefficients of the cubic (note that these are entered starting with the coefficient of the highest power first = [1 3 -1 -1];
% Now perform the evaluation using polyval y = polyval(c,x) &
%
Note that in this short piece of code everything after the % is treated by MATLAB as a comment and so is ignored. It is good practice to provide brief, but meaningful, comments at important points within your code.
1.6 Some MATLAB Specific Commands
21
Important Point It is important that you remember to enter the coefficients of the polynomial starting with the one associated with the highest power and that zeros are included in the sequence. We might want to plot the results of this calculation and this can be simply accomplished using the plot command. Consider the following example: Example 1.17 Plot the polynomial y = x4 + x2 − 1 between x = −2 and x = 2 (using fifty points). x = linspace(-2,2,50); c = [1 0 1 0 -1]; y = polyval(c,x); plot(x,y) This produces the output 20
15
10
5
0
−5 −2
−1.5
−1
−0.5
0
0.5
1
1.5
2
In the next chapter we shall discuss plotting in more detail and show how plots can be customised. There are many other commands which allow us to manipulate polynomials: perhaps one of the most useful ones is the roots. The polynomial is defined in the same way as in the previous examples. The input to the routine is simply these coefficients and the output is the roots of the polynomial. Example 1.18 Find the roots of the polynomial y = x3 − 3x2 + 2x using the
22
1. Simple Calculations with MATLAB
command roots. c = [1 -3 2 0]; r = roots(c) This returns the answers as zero, two and one.
In fact the converse command also exists, which is poly. This takes the roots and generates the coefficients of the polynomial having those roots (which is monic, that is the coefficient of the highest term is unity).
1.6.1 Looking at Variables and Their Sizes Before we proceed we mention a couple of useful commands for seeing which variables are defined. To list the variables which are currently defined we can use the command whos. This will give a list of the variables which are currently defined (a shorter output can be obtained by using the command who). This command can be used to list certain variables only, for instance whos re* lists only the variables whose names start with re.
Example 1.19 The following code # clear all a = linspace(0,1,20); b = 0:0.3:5; c = 1.; whos " gives the output Name
Size
Bytes
a b c
1x20 1x17 1x1
160 136 8
! Class double array double array double array
Grand total is 38 elements using 304 bytes Here we have used the clear all command to remove all previously defined variables. To look at the size of one variable we can use the command length, for instance with the previous example length(a) will give the answer 20. We note that the command size(a) will give two dimensions of the array, that is
1.7 Accessing Elements of Arrays
23
in this case [1 20]; this will be particularly useful when we consider matrices in due course.
1.7 Accessing Elements of Arrays This is one of the most important ideas in MATLAB and other programming languages which is often misunderstood. Let us start by considering a simple array x = 0:0.1:1.;. The elements of this array can be recalled by using the format x(1) through to x(11). The number in the bracket is the index and refers to which value of x we require. A convenient mathematical notation for this would be xj where j = 1, · · · , 11. This programming notation should not be confused with x(j); that is x is a function of j. Let us consider the following illustrative example: Example 1.20 Construct the function f (x) = x2 +2 on the set of points x = 0 to 2 in steps of 0.1 and give the value of f (x) at x = 0, x = 1 and x = 2. The code to construct the function is: ' $ x = 0:0.1:2; f = x.ˆ2+2; % Function at x=0 f(1) % Function at x=1 f(11) % Function at x=2 f(21) & Note that the three points are not f(0), f(1) and f(2)!
%
In this example we have noted that xj = (j − 1)/10 and hence x1 = 0, x11 = 1 and x21 = 2. These three indices are the ones we have used to find the value of the function. Important Point In MATLAB f(j) the value of j refers to the index within the array rather than the function f(.) evaluated at the value j!
24
1. Simple Calculations with MATLAB
The expression end is very useful at this point, since it can be used to refer to the final element within an array. In the previous example f(end) gives the value of f(21) since the length of f is 21.
Example 1.21 We now show how to extract various parts of the array x. # x = linspace(0,1,10); y = x(1:end); % Whole of x y = x(1:end/2); % First half y = x(2:2:end); % Even indices only y = x(2:end-1); % All but the last one " !
1.8 Tasks In this introductory chapter we shall give quite a few details (at least initially) concerning these suggested tasks. However, as the reader’s grasp of the MATLAB syntax develops the tasks will be presented more like standard questions (the solutions are given at the back of the book in Appendix C).
Task 1.1 Calculate the values of the following expressions (to find the MATLAB commands for each function you can use the Glossary, see for instance the entry for tan on page 386 or the help command, help tan). p(x) = x2 + 3x + 1 at x = 1.3, y(x) = sin(x) at x = 30◦ , f (x) = tan−1 (x) at x = 1, √ −1 3 g(x) = sin cos (x) at x = . 2 Task 1.2 Calculate the value of the function y(x) = |x| sin x2 for values of x = π/3 and π/6 (use the MATLAB command abs(x) to calculate |x|). Task 1.3 Calculate the quantities sin(π/2), cos(π/3), tan 60◦ and ln(x + √ x2 + 1) where x = 1/2 and x = 1. Calculate the expression x/((x2 + 1) sin x) where x = π/4 and x = π/2. (If you are getting strange answers in the form
1.8 Tasks
25
of rationals you may well have left the format as rat, so go back to the default by typing format).
Task 1.4 Explore the use of the functions round, ceil, floor and fix for the values x = 0.3, x = 1/3, x = 0.5, x = 1/2, x = 1.65 and x = −1.34. Task 1.5 Compare the MATLAB functions rem(x,y) and mod(x,y) for a variety of values of x and y (try x = 3, 4, 5 and y = 3, 4, −4, 6). (Details of the commands can be found using the help feature).
Task 1.6 Evaluate the functions 1. y = x3 + 3x2 + 1 2. y = sin x2 3. y = (sin x)2 4. y = sin 2x + x cos 4x 5. y = x/(x2 + 1) 6. y =
cos x 1+sin x
7. y = 1/x + x3 /(x4 + 5x sin x) for x from 1 to 2 in steps of 0.1
Task 1.7 Evaluate the function y=
x , x + x12
for x = 3 to x = 5 in steps of 0.01.
Task 1.8 Evaluate the function 1 1 3 + 2+ , 3 x x x for x = −2 to x = −1 in steps of 0.1. y=
Task 1.9 (D) The following code is supposed to evaluate the function f (x) =
(x3
x2 cos πx , + 1)(x + 2)
26
1. Simple Calculations with MATLAB
for x ∈ [0, 1] (using 200 steps). Correct the code and check this by evaluating the function at x = 1 using f(200) which should be −1/6. ' $ x = linspace(0,1); clear all g = xˆ3+1; H = x+2; z = x.ˆ2; y = cos xpi; f = y*z/g*h & %
Task 1.10 (D) Debug the code which is supposed to plot the polynomial x4 − 1 between x = −2 and x = 2 using 20 points. x = -2:0.1:2; c = [1 0 0 -1]; y = polyval(c,x); plot(y,x) Task 1.11 (D) Debug the code which is supposed to set up the function f (x) = x3 cos(x + 1) on the grid x = 0 to 3 in steps of 0.1 and give the value of the function at x = 2 and x = 3. ' $ x = linspace(0,3); f = xˆ3.*cos x+1; % x = 2 f(2) % x = 3 f(End) & %
2
Writing Scripts and Functions
2.1 Creating Scripts and Functions With the preliminaries out of the way we now turn our attention to actually using MATLAB by writing a short piece of code. Most of the commands in this section have purposely been written so they can be typed at the prompt, >>. However, as we develop longer codes or ones which we will want to run many times it becomes necessary to construct scripts. A script is simply a file containing the sequence of MATLAB commands which we wish to execute to solve the task at hand; in other words a script is a computer program written in the language of MATLAB. To invoke the MATLAB editor1 we type edit at the prompt. This editor has the advantage of understanding MATLAB syntax and producing automatic formatting (for instance indenting pieces of code as necessary). It is also useful for colour coding the MATLAB commands and variables. Both of these attributes are extremely useful when it comes to debugging code. The MATLAB editor also has the feature that once a piece of code has been run the values of variables can be displayed by placing the mouse close to the variable’s location within the editor. This is extremely useful for seeing what is going on and provides the potential to identify where we might have made a mistake (for instance, if we had set a variable to be the wrong size). 1
You can of course make use of any other editor you have available on your computer. We have chosen to use the built-in MATLAB editor. Its implementation may differ slightly from platform to platform. If you are unsure of its use try typing help edit at the MATLAB prompt.
28
2. Writing Scripts and Functions
Example 2.1 We begin by entering and running the code: a = input(’First number ’); b = input(’Second number ’); disp([’ Their sum is ’ num2str(a+b)]) disp([’ Their product is ’ num2str(a*b)]) This simple code can be entered at the prompt, but that would defeat our purpose of writing script files. We shall therefore create our first script and save it in a file named twonums.m. To do this, first we type edit at the MATLAB prompt to bring the editor window to the foreground (if it exists) or invoke a new one if it doesn’t. Along the base of the typing area are a set of tabs. These allow you to switch between multiple codes you may be simultaneously working on. Since this is our first use of the editor, MATLAB will have given this code the default name Untitled.m. To proceed we type the above code into the editor and then use the File Menu (sub item Save As) to change the name of the code and Save it as twonums.m. We will need to erase the current default name (Untitled.m) and type the new filename. After a code has been named we can use the save icon (a little picture of a disc) to save it, without the need to use the File Menu. If we now return to the MATLAB window and enter the command twonums at the prompt, our code will be executed; we will be asked to enter two numbers and MATLAB will calculate, and return, their product and sum. The contents of the file can be displayed by typing type twonums. This simple example has introduced two new commands, input and num2str. The input command prompts the user with the flag contained within the quotes ’ ’ and takes the user’s response from the standard input, in this case the MATLAB window. In the first example it then stores our response in the variable a. The second command num2str stands for number-to-string and instructs MATLAB to convert the argument from a number, such as the result of a+b, to a character string. This is then displayed using the disp. Important Point
It is very important you give your files a meaningful name and that the files end with .m. You should avoid using filenames which are the same as the variables you are using and which coincide with MATLAB commands. Make sure you do not use a dot in the body of the filename and that it does not start with a special character or a number.
2.1 Creating Scripts and Functions
29
For instance myfile.1.m and 2power.m are not viable filenames (good alternatives would be myfile 1.m and twopower.m respectively). Filenames also have the same restrictions which we met earlier for variable names (see page 4). When processing a command, MATLAB searches to see if there is a userdefined function of that name by looking at all the files in its search path with a .m extension. If you are in any doubt whether something is a MATLAB command use either the command help or the command which in combination with the filename, for instance help load or which load for the MATLAB command load. You should consider creating a directory for your MATLAB work. For instance on a Unix machine the sequence of commands (at the Unix prompt) mkdir Matlab_Files cd Matlab_Files matlab will create a directory (which obviously only needs to be done once), the second command changes your working directory to Matlab Files and the third command invokes MATLAB (to check that you are in the correct directory use the command pwd to ‘print working directory’). In a Windows environment you can use Explorer to create a new folder and then invoke MATLAB by clicking on the MATLAB icon. On a Macintosh you can simply create a new directory as you would a new folder2 . Depending upon your computing platform you will probably need to change to your new folder; the cd within MATLAB allows you to change directories. In MATLAB6 you can use the ... symbol at the top of the control environment to change the working directory and this is displayed to the left of this symbol. It is also possible to access files from other directories by augmenting MATLAB’s search path. Again, this is platform-specific; the following works on our Unix platforms path(path,’/home/sro/MyMatlabFiles’)
On a Macintosh you can set the path by choosing Set Path from the MATLAB File menu. With the search paths set it is possible to create and manage a central resource of user written library functions which can be accessed from any directory on your computer. One of the most common sources of problems for the novice programmer occurs when the wrong script is being run or when the computer cannot find the program you have just entered. This is usually because the file isn’t in the correct directory, or is misnamed. You can check that a file is the correct 2
Under MacOS X you can use the standard Unix commands given above.
30
2. Writing Scripts and Functions
one by using the command type. The syntax for this command is simply type file1; this will produce a listing of the MATLAB file file1.m. If the text is not what you are expecting you may well be using a filename which clashes with an existing MATLAB command. In order to see which file you are looking at, type the command which file1. This will tell you the full pathname of the listed files which can be compared with the current path by typing pwd. You can also list the files in the current directory by typing dir or alternatively all the available MATLAB files can be listed by using what: for more details see help what.
Example 2.2 If we create a MATLAB file called power.m using the editor it can be saved in the current directory: however the code will not work. The reason for this can be seen by typing which power which produces the output >> which power power is a built-in function. So MATLAB will try to run the built-in function.
2.1.1 Functions In the previous sections we wrote codes which could be legitimately run at the MATLAB prompt. We now discuss the important class of codes which actually act as functions. These codes take inputs and return outputs. We shall start with a very simple example: function [output] = xsq(input) output = input.ˆ2; which we will save as xsq.m. It is important that we get the syntax for functions correct so we’ll go through this example in some detail. - The first line of xsq.m tells us this is a function called xsq which takes an input called input and returns a value called output. The input is contained in round brackets, whereas the output is contained within square brackets. It is crucial for good practice that the name of the function xsq corresponds to the name of the file xsq.m (without the .m extension), although there is some flexibility here. - The second line of this function actually performs the calculation, in this case squaring the value of the input, and storing this result in the variable output. Notice that the function uses dot arithmetic .ˆ so that this function
2.1 Creating Scripts and Functions
31
will work with both vector and matrix inputs (performing the operation element by element). Notice also that we have suppressed the output of the calculation by using a semicolon; in general all communication between a function subroutine and the main calling program should be done through the input and output. Having written our function we can now access it from within MATLAB. Consider the following: x = 1:10; y = xsq(x) Here we have initialised the vector x to contain the first ten integers. We call the function in the second line and assign the result, in this case x.ˆ2, to the variable y. Notice that we have called the function with the argument x and not something called input. The variables input and output are local variables that are used by the function; they are not accessible to the general MATLAB workspace3 . When the function is run it merely looks at what is given as the argument. It is therefore important the function has the correct input; in our example scalar, vector or matrix inputs are allowed. In other cases, if the function expects an argument of a certain type then it must be given one otherwise an error will occur (which will not always be reported by MATLAB). Of course it is not possible to call the function just using xsq since the code cannot possibly know what the input is. MATLAB will return an error stating that the Input argument ’input’ is undefined. As noted above this function can also be used for scalars, for instance xsq(2) returns the value 4, and for vectors >> A = [1 2 3 4 5 6]; >> y = xsq(A) y = 1
4
9
16
25
36
Functions can also take multiple inputs and give multiple outputs. Consider the following examples:
Example 2.3 Suppose we want to plot contours of a function of two variables z = x2 + y 2 . We can use the code 3
You can find out what variables are in use by MATLAB by typing who, which lists all variables in use, or whos, which lists all variables along with their size and type.
32
2. Writing Scripts and Functions
function [output] = func(x,y) output = x.ˆ2 + y.ˆ2; which should be saved in the file func.m. The first line indicates this is a function which has two inputs x and y, and returns a single output output. The next line calculates the function x2 + y 2 ; again we have used dot arithmetic to allow for the possibility of vector or matrix arguments. For the calculation to be valid the vectors x and y must have the same size. To plot the contours (that is the level curves) of the function z = x2 + y 2 we would proceed as follows: $ ' x = 0.0:pi/10:pi; y = x; [X,Y] = meshgrid(x,y); f = func(X,Y); contour(X,Y,f) axis([0 pi 0 pi]) axis equal & % This gives us the plot 3
2.5
2
1.5
1
0.5
0
0
0.5
1
1.5
2
2.5
3
For the moment we do not need to worry about the plotting commands used to display the curves: we will return to plotting in more detail later in this chapter.
2.1 Creating Scripts and Functions
33
Important Point It is just as important that the function receives the correct number of inputs as it is that they are of the correct type. For example, we cannot call our function using func or func(1) (or with arguments of different size). In all these cases MATLAB will give an error message.
Example 2.4 Suppose we now want to construct the squares and cubes of the elements of a vector. We can use the code function [sq,cub] = xpowers(input) sq = input.ˆ2; cub = input.ˆ3; Again, the first line defines the function xpowers, which has two outputs sq and cub and one input. The second and third lines calculates the values of input squared and cubed. This function file must be saved as xpowers.m and it can be called as follows: x = 1:10; [xsq,xcub] = xpowers(x); This gives >> xsq xsq = 1
4
9
16
25
36
49
64
81
100
>> xcub xcub = Columns 1 through 6 1
8
27
64
512
729
1000
125
216
Columns 7 through 10 343
The output is two row vectors, one containing the values of the first ten integers squared and the second the values of the first ten integers cubed. Notice that when the function is called we must know what form of output we expect,
34
2. Writing Scripts and Functions
whether it be a scalar, a vector or a matrix. The expected outputs should be placed within square brackets.
Example 2.5 As you might expect a function can have multiple inputs and outputs: function [out1,out2] = multi(in1,in2,in3) out1 = in1 + max(in2,in3); out2 = (in1 + in2 + in3)/3; which should be saved as multi.m. This gives us a function called multi that takes three inputs in1, in2 and in3 and returns two outputs out1 and out2. The first output is the sum of the first input and the maximum of the latter two, calculated using the MATLAB intrinsic function max. The second output is simply the arithmetic mean (the average) of the inputs. We can call this function in the following way x1 = 2; x2 = 3; x3 = 5; [y1,y2] = multi(x1,x2,x3); y1, y2 For this example we obtain y1=7 and y2=3.3333. The input and output of a function do not have to be the same size (although in most cases they will be). Consider the following example:
Example 2.6 Consider a code which returns a scalar result from a vector input. For example function [output] = sumsq(x) output = sum(x.ˆ2); Our function sumsq takes a vector (or potentially a scalar) as an input and returns the sum of the squares of the elements of the vector. The MATLAB intrinsic function sum calculates the sum of its vector argument. For instance x = [1 2 4 5 6]; y = sumsq(x) sets y equal to the scalar 12 + 22 + 42 + 52 + 62 = 82.
2.1 Creating Scripts and Functions
35
2.1.2 Brief Aside For those of you familiar with matrices we pause here and note that the command in the previous example will also work with matrices: >> A=[1 2 3; 4 5 6]; >> sumsq(A) ans = 17
29
45
The command has squared (and summed) the elements of the matrix A, which is two-by-three. This has exploited the property that the sum command sums the columns of a matrix. If we want to sum the rows of a matrix we use sum(A,2), so that we have >> sum(A,1)
% which is equivalent to sum(A)
ans = 5
7
9
>> sum(A,2) ans = 6 15 Notice that the answers are the shape we would expect: the first is a row vector whereas the second is a column vector. Many of the MATLAB commands we shall meet in this text, in general those commands which reduce the dimension of the input object by one, can operate along the rows or the columns; which is specified using an additional argument. Many of MATLAB’s intrinsic commands work in the same way and so care is needed to ensure that the correct number and form of inputs to functions are used.
36
2. Writing Scripts and Functions
2.2 Plotting Simple Functions One of the most powerful elements of MATLAB is its excellent plotting facilities which allow us to easily and rapidly visualise the results of calculations. We have already met some examples of plotting (the line graph plotting of the functions and the contour plot on page 32). We pause here to try some examples of the plotting facilities available within MATLAB. We start with the simplest command plot and use this as an opportunity to revisit the ways in which functions can be initialised. We start with initialising an array, in this case x x = 0:pi/20:pi;
which as we know sets up a vector whose elements are π π π 0, , 2 , · · · , 19 , π , 20 20 20 (that is, a vector whose elements range from 0 to π in steps of π/20). This array is of size one-by-twenty one, which can be confirmed by using the command size(x) or, if we know it is a one-dimensional array as is the case here, by using the command length(x) (in general length gives the maximum of the dimensions of a matrix). We can plot simple functions, for instance plot(x,sin(x)) or more complicated examples such as plot(x,sin(3*x),x,x.ˆ2.*sin(3*x)+cos(4*x)) (this plots sin 3x and x2 sin 3x + cos 4x). Try these examples out for yourself. Now we have an array x we begin using it as an argument to other functions. We start with calculating the point on a straight line 3x − 1 using y = 3*x-1;
Again size(y), or length(y), confirms that this array has the same dimensions as the vector x. We can plot y versus x using the command plot(x,y) to produce a straight line (in the default colour blue). You can change the colour or style of the line, or force the individual data points to be plotted, using a third argument for the plot command; more details will be given later on page 45. Proceeding to polynomials, the code y = x.ˆ2+3;
2 produces a vector y whose elements are given by the quadratic x + 3. Notice that by using the dot before the operator (here exponentiation ˆ) we are performing the operation element by element on the array x.
2.2 Plotting Simple Functions
37
Example 2.7 To plot the quadratic x2 + 7x − 3 from x equals −3 to 3 in steps of 0.2 we use the code x = -3:0.2:3; y = x.ˆ2+7*x-3; grid on plot(x,y) The resulting plot is given below 30
25
20
15
10
5
0
−5
−10
−15 −3
−2
−1
0
1
2
3
We have given the plot a grid by using the command grid on; this can be removed using the command grid off. MATLAB provides an excellent computing environment for producing results which can be viewed quickly and easily. This is essential when we come to analyse the results of our calculations, a task that is usually necessary in order to obtain useful information from an otherwise mathematical calculation. MATLAB is capable of producing very intricate and clear plots, as the following example illustrates.
Example 2.8 Consider the following code:
38
2. Writing Scripts and Functions
' $ x = 0:pi/20:pi; n = length(x); r = 1:n/7:n; y = x.ˆ2+3; plot(x,y,’b’,x(r),y(r),’r*’) axis([-pi/3 pi+pi/3 -1 15]) xlabel(’x values’) ylabel(’Function values’) title(’Demonstration plot’) text(pi/10,0,’\alpha=\betaˆ2’) & % If we dissect this piece of code we see the first line initializes the vector x. The second and third lines pick out every third integer value between 1 and length(x). The fourth line computes the values of the quadratic y = x2 + 3 at the points in the vector x (using dot arithmetic to achieve this). We then reach the plot command. Here we are telling MATLAB to plot the curve y versus x and to colour the plot blue (using the flag ’b’). The second part of the plot command tells MATLAB to plot every third point on the curve (here represented by x(r) and y(r)) as points which are labelled with a red asterisk using ’r*’. The commands directly following the plot command are used to manipulate the final look of the plot. The command axis sets the start and end points of the horizontal (from −π/3 to π + π/3) and then the vertical axis (from −1 to 15). The commands xlabel and ylabel add labels to the horizontal and vertical axes and the command title, not surprisingly adds the title to the figure. The command text allows the user to add text to the figure at a coordinate specified within the units of the plot. The arguments of these commands include a string which starts and ends with a quotation mark. The text can include many characters but here we have included Greek letters, using the LATEX4 construction \alpha for α and \beta for β. The properties of a figure can be edited using the drop down menus on its window. This includes being able to increase the size of the characters used in labels. By changing the line which sets the title to title(’Demonstration plot’,’FontSize’,24) we see quite a dramatic change in the size of the characters in the title. 4
LATEX is a language that is almost universally used for typesetting mathematics. It is available for almost all computing platforms and operating systems. Further details can be found by consulting any good LATEX text.
2.2 Plotting Simple Functions
39
Demonstration plot 15
Function values
10
5
2
α=β
0 −1
−0.5
0
0.5
1
1.5 x values
2
2.5
3
3.5
4
There are a wide variety of other plotting options available. For instance loglog(x,y) produces a log-log plot. Similarly semilogx and semilogy produces a log plot for the x and y-axis, respectively. You should also be aware of the commands clf which clears the current figure and hold which holds the current figure. We will explore the use of these commands in the tasks at the end of this section. One of the excellent features of MATLAB is the way in which it handles two and three-dimensional graphics. Although we will have little need to exploit the power of MATLAB’s graphical rendering we should be aware of the basic commands. Examples serve to highlight some of the many possibilities: ' $ x = linspace(-pi/2,pi/2,40); y = x; [X,Y] = meshgrid(x,y); f = sin(X.ˆ2-Y.ˆ2); figure(1) contour(X,Y,f) figure(2) contourf(X,Y,f,20) figure(3) surf(X,Y,f) & % This gives the three figures
40
2. Writing Scripts and Functions
1.5
1
0.5
0
−0.5
−1
−1.5 −1.5
−1
−0.5
0
0.5
1
1.5
−1.5
−1
−0.5
0
0.5
1
1.5
1.5
1
0.5
0
−0.5
−1
−1.5
1
0.5
0
−0.5
−1 2 2
1 1
0 0 −1
−1 −2
−2
These figures are, respectively, a contour plot (created using contour(X,Y,f)), a filled contour plot with 20 contour levels (created using contourf(X,Y,f,20) and a surface plot (created using surf(X,Y,f)). The function f is plotted on a grid generated using the command meshgrid(x,y). As the name suggests
2.2 Plotting Simple Functions
41
meshgrid sets up a grid of points by generating copies of the x and y values; see help meshgrid for details of this command. To further explore the potential of MATLAB’s plotting facilities see the MATLAB demo topics Visualization and Language/Graphics.
2.2.1 Evaluating Polynomials and Plotting Curves We return to the topic of functions by first constructing a simple program to evaluate a quadratic. We shall start with a code to generate the value of a specific quadratic at a specific point: x = 3; y = xˆ2+x+1; disp(y) 2 This code sets x equal to 3, calculates x + x + 1 and then displays the answer. We now expand the above code so that the user can enter the point and the coefficients of the quadratic. In general suppose we have the general quadratic y = a2 x2 + a1 x + a0 . Firstly we need to define the quadratic and this is done by fixing the three coefficients a0 , a1 and a2 . This can be done using the following script, which we will call quadratic.m ' $ % quadratic.m % This program evaluates a quadratic % at a certain value of x % The coefficients are stored in a2, a1 and a0. % SRO & JPD % str = ’Please enter the ’; a2 = input([str ’coefficient of x squared: ’]); a1 = input([str ’coefficient of x: ’]); a0 = input([str ’constant term: ’]); x = input([str ’value of x: ’]); y = a2*x*x+a1*x+a0; % Now display the result disp([’Polynomial value is: ’ num2str(y)]) & % Again we have a code where the first few lines of the code start with a percent sign %. MATLAB treats anything coming after a % sign as a comment.
42
2. Writing Scripts and Functions
Comments at the start of a code have a special significance in that they are used by MATLAB to provide the entry for the help manual for that particular script. The manual entry can then be accessed by typing help quadratic at the MATLAB prompt to produce quadratic.m This programme evaluates a quadratic at a certain value of x The coefficients are stored in a2, a1 and a0. SRO & JPD Notice the manual entry terminates once MATLAB reaches a line in the file quadratic.m in which the first character is not a % sign. The line later on in the code which starts with a percent sign is again a comment. In this case we have inserted this line to provide information to the user about the calculation which is to be performed; in this case display the result of our calculation. Judicious use of comments throughout a code makes it readable by a person who may not be fully conversant with the precise details of the calculations to be performed. It is good programming practice to insert text as a manual entry at the start of any code as well as including comments on particular aspects of the calculation which may not be transparent to the user of the code. Note it is also possible to obtain a complete listing of the code from within MATLAB by typing type quadratic at the prompt. Back to our code. The first three non-comment lines use the input command to prompt the user to enter the values of the constants a2, a1 and a0. As we saw earlier the input command takes an argument in the form of a character string, contained between quotes, that acts as the prompt which appears on the screen. Here we have introduced a variable str which is equal to ’Please enter the ’, a phrase which is common to each of the input statements. The argument to input is then a vector containing strings. Notice in this example we have appended to the prompt a colon followed by a space so that when the user types the values, rather than them being flush against the final character, there is a space. This is not necessary but simply a style convention we will usually adopt. For the moment we shall assume the user responds to the prompts by entering values which are reasonable. The user is then prompted for the value of x at which they wish to evaluate the polynomial. The following line actually does the calculation of evaluating the polynomial; at this stage we have used the fact that x2 = x×x, but of course we could use a2*xˆ2+a1*x+a0. There are many ways of writing polynomials, for instance this could have been written recursively as a0 + x(a1 + xa2 ). (2.1)
2.2 Plotting Simple Functions
43
This general recursive form goes under the name of Horner’s method. With the function evaluated the answer is displayed, using the function num2str (‘number-to-string’) which takes as input a number and returns a character string which is then appended to the phrase ’Polynomial value is: ’. The concatenation (joining together) of strings is achieved by writing them as elements in a row vector and then using the disp function to write them to the screen. There is no obvious reason why we couldn’t type the commands given above at the MATLAB prompt and enter all the values required for the calculation to proceed. However, it is preferable to carry out the calculation by simply typing the command quadratic; this also allows us to have access to a general program which calculates the value of a quadratic. An even better approach is to write a user callable function. We will use this example to build up the level of complexity of the function until we have one which is as general as we can possibly make it. Firstly let’s suppose the values of the coefficients in the quadratic are known a priori5 . For example, suppose we want to evaluate the quadratic y = 3x2 + 2x + 1. We could then use the function # % % evaluate_poly.m % function [value] = evaluate_poly(x) value = 3*x.ˆ2+2*x+1; " ! Here we have again used dot arithmetic in the construction x.ˆ2, thus making this function able to take both a scalar or vector (or even a matrix) argument. As we have seen earlier if this function is called with a vector, then a vector is returned as output. Now we can use the function evaluate poly, in the form evaluate poly(2) or x = 2;y = evaluate poly(x). Note within MATLAB we are able to call a function with a variety of different inputs; whether this is valid depends upon the structure of the function6 . With this in mind we can now use our function to generate a vector containing the values of the polynomial at a number of x points and plot the result using >> x = -5:0.5:5; 5 6
A very similar command already exists in MATLAB, namely polyval, but this function is developed to demonstrate the construction. This is similar to the idea of overloading which is intrinsic to object orientated languages like C++ and Java. However, in those languages a different function is called depending on the type of input, whereas here it is one function which apparently deals with all the cases.
44
2. Writing Scripts and Functions
>> y = evaluate_poly(x); >> plot(x,y) which gives 90
80
70
60
50
40
30
20
10
0 −5
−4
−3
−2
−1
0
1
2
3
4
5
2.2.2 More on Plotting At this point we briefly return to the problem of generating plots using MATLAB. The simple code given above first sets up a vector which runs from x = −5 to x = 5 in steps of 0.5. The value of the quadratic at each point is then calculated, using our newly defined function. The final plot(x,y) command ‘simply’ draws a line through these points. The way the plot is constructed can best be seen by making the x-grid coarser (that is, with less points); we then find the plot is constructed by drawing a straight line through each pair of points. MATLAB is slightly more subtle than this in that it checks whether there is a window open ready for plotting, and if not it opens one. The axes are automatically rescaled and tick marks are drawn. The default settings are generally fine, although at some points you may want to look at certain regions of the plot. At the moment we will not worry about the details of how this is achieved7 . In general we shall introduce the features of the plotting package as we need them. Here we extend our plotting capability by considering the impact of a 7
Try the commands h = gca. This returns what MATLAB calls a ‘handle’ to the current axis, and then the function get(h) lists all the properties of the axis. There is also a command gcf which returns a handle to the entire figure.
2.2 Plotting Simple Functions
45
third argument of the plot command, such as in plot(x,y,’r.’). The string which is passed as the third argument conveys information as to how the plot should be presented: here the first character r is the colour (red) and the second is the symbol (in this case a dot .) to be used at each point (as opposed to a line joining the points). The colour options are y c g w
yellow cyan green white
m r b k
magenta red blue black
and the choice of symbols are . o x + * s d
point circle x-mark plus star square diamond
v X < > p h
triangle (down) triangle (up) triangle (left) triangle (right) pentagram hexagram
It is also possible to control the line style. Instead of using a symbol, as in the previous command, we can draw the line using one of the following options: : -. --
solid dotted dashdot dashed
As we saw earlier (on page 38) we can also plot more than one curve on the same graph. One simple way of achieving this is through the following code >>x = -pi:pi/20:pi; >>plot(x,sin(x),’r-’,x,cos(x),’b:’) This generates the plot
46
2. Writing Scripts and Functions
1
0.8
0.6
0.4
0.2
0
−0.2
−0.4
−0.6
−0.8
−1 −4
−3
−2
−1
0
1
2
3
4
from which the command syntax can be deduced; a plot of sin(x) versus x using a solid red line and a plot of cos(x) versus x using a blue dotted line (if the plot were to be viewed in colour). This could have been achieved in another way ' $ x = -pi:pi/20:pi; clf plot(x,sin(x),’r-’) hold on plot(x,cos(x),’b:’) hold off & % As you might infer from this, using the command plot clears the current plot and replaces it with the new figure, unless the figure is being “held”. So here we plot sin(x), hold this current figure using hold on and then plot cos(x). The current figure is released using hold off. We could add a legend to this plot to help us identify which line is which. This is accomplished with the command legend(’sine’,’cosine’) which now gives
2.2 Plotting Simple Functions
47
1
sine cosine
0.8
0.6
0.4
0.2
0
−0.2
−0.4
−0.6
−0.8
−1 −4
−3
−2
−1
0
1
2
3
4
In this case the legend has been placed in the top right corner, however its location can be changed, see help legend for details. We now return to our discussion of functions and consider in more detail functions which can be called with more than one argument and return as many arguments as we wish. In constructing functions we do need to take some care with how our outputs are returned; we have already seen that if the function is called with a vector then the “output” is, in general, a vector. However, there is no reason why there should not be two (or more) outputs returned. Consider the following modification to the function evaluate poly from page 43 ' $ % % evaluate_poly2.m % function [f, fprime] = evaluate_poly2(x) f = 3*x.ˆ2+2*x+1; fprime = 6*x+2; & % This MATLAB function calculates the values of the polynomial and its derivative. This could be called using the sequence of commands x = -5:0.5:5; [func,dfunc] = evaluate_poly2(x); We can further generalise our code by passing the coefficients of the quadratic to the function, either as individual values or a vector. The code then becomes
48
2. Writing Scripts and Functions
' $ % % evaluate_poly3.m % function [f,fprime] = evaluate_poly3(a,x) f = a(1)*x.ˆ2+a(2)*x+a(3); fprime = 2*a(1)*x+a(2); & % which can be called using x = -5:0.5:5; a = [1 2 1]; [f,fp] = evaluate_poly3(a,x); Before proceeding, we make one final comment regarding the general form for function files. The only communication between the function and the calling program is through the input and output variables; the function should not prompt a user for input nor should it echo the result of any calculation. This is not a necessary constraint on MATLAB functions but more a useful programming convention which is worth following. This fairly simple routine evaluate poly3(x) was chosen to demonstrate some of the particulars of MATLAB function files because MATLAB has a built-in function, called polyval, which also evaluates polynomials. The extract from help polyval yields the information Y = POLYVAL(P,X), when P is a vector of length N+1 whose elements are the coefficients of a polynomial, is the value of the polynomial evaluated at X. Y = P(1)*XˆN + P(2)*Xˆ(N-1) + ... + P(N)*X + P(N+1) Care needs to be taken with the order in which the coefficients of the polynomial are presented. In fact these are in the same order as in our routine. This example provides a good opportunity to investigate the full code for this builtin function; the code listing can be obtained using type polyval. Compare this with our three-line function evaluate poly3(x).
Example 2.9 We can use polyval to evaluate polynomials. We will use it to test a hypothesis that the values of n2 + n + 41, where n is an integer, are prime (at least for the first few integer values of n: obviously this is not so for n = 41). Consider
2.3 Functions of Functions
49
p = [1 1 41]; x = 1:40; f = polyval(p,x); isprime(f)
the function isprime(f) returns a value of 1 if the element of f is a prime and 0 if it is not. The result of our calculation is a string of 39 ones demonstrating that all but the value for n = 40 are prime (402 + 40 + 41 = 40 × (40 + 1) + 41 = 41 × (40 + 1) = 412 ). We note that the value of quadratic n2 − n + 41 is also prime for all integers up to and including n = 40.
2.3 Functions of Functions One MATLAB command which provides us with considerable freedom in writing versatile code is the command feval which loosely translates as function evaluation. The simplest use for this command is y= feval(’sin’,x);
evaluate the function sin at x. This is equivalent to sin(x). In general the arguments for feval are the name of the function, which must be either a MATLAB built-in function or a user defined function, contained between quotes, and the value (or values in the case of a vector) at which the function is to be evaluated. The utility of feval is that it allows us to use function names as arguments. By way of introduction we provide an example. Consider the function h(x) = 2 sin2 x + 3 sin x − 1. One way of writing code that would evaluate this function is function [h] = fnc(x) h = 2*sin(x).*sin(x)+3*sin(x)-1
However we can recognise this function as a composition of two functions g(x) = sin(x) and f (x) = 2x2 + 3x − 1 so that h(x) = f (g(x)). We can easily write a function file f.m to evaluate f (x) function [y] = f(x) y = 2*x.ˆ2+3*x-1;
50
2. Writing Scripts and Functions
(using dot arithmetic to allow for the possibility of vector arguments x). To use this in calculating the value of the composite function h(x) we need to be able to pass the function name to f as an argument. We can do this with the following modification to our code function [y] = f(fname,x) z = feval(fname,x); y = 2*z.ˆ2+3*z-1; Calculating the function h(x) is now as simple as x = -pi:pi/20:pi; y = f(’sin’,x); plot(x,y) This gives a plot of the function h(x) as 4
3
2
1
0
−1
−2
−3 −4
−3
−2
−1
0
1
2
A more useful example is given by the function plotf ' function plotf(fname,x) y = feval(fname,x) plot(x,y) grid on axis([min(x) max(x) min(y) max(y)]) xlabel(’x’) ylabel([fname ’(x)’]) &
3
4
$
%
2.4 Errors
51
This function takes as input a function name and a vector x and produces a labelled plot. Notice although there are two inputs for this function there are no values output; the figure is the output. 1
0.8
0.6
0.4
sin(x)
0.2
0
−0.2
−0.4
−0.6
−0.8
−1
−3
−2
−1
0 x
1
2
3
The command feval has a wide range of uses, some of which we will exploit later throughout the text.
2.4 Errors 2.4.1 Numerical Errors We mentioned right at the start of this text that numerical methods are usually not exact (that is, they are approximate methods). In fact it is very hard to get computers to perform exact calculations. If we add (or subtract) integers then a computer can be expected to get the exact answer, but even this operation has its limits. Once we try to perform the division operation we run into trouble. We are happy with the fact that one divided by three is a third, which we can write as 1/3, but if we need to store this on a computer we run into difficulties. For the moment let’s suppose we have a virtual computer that works in decimal. By this we mean that any number which can be written as a terminating decimal (that is, one which stops), can be stored ‘exactly’ (provided we do not require too many digits). We know that a third does not have a finite representation, so there is no way we can store this number in our imaginary
52
2. Writing Scripts and Functions
computer other than by truncating the sequence. We would use the notation 1/3 ≈ 0.3333. Obviously the more three’s we retain the more accurate the answer. Almost all numerical schemes are prone to some kind of error. It is important to bear this in mind and understand the possible extent of the error. Intrinsic to this has to be the knowledge of how much we can trust the results which are produced. Errors can be expressed as two basic types: Absolute error: This is the difference between the exact answer and the numerical answer. Relative error: This is the absolute error divided by the size of the answer (either the numerical one or the exact one), which is often converted to a percentage. (In each case we take the modulus of the quantity.)
Example 2.10 Suppose an error of £1 is made in a financial calculation of interest on £5 and on £1,000,000. In each case the absolute error is £1, whereas the relative errors are 20% and 0.0001% respectively.
Example 2.11 Suppose a relative error of 20% is made in the above interest calculations on £5 and £1,000,000. The corresponding absolute errors are £1 and £200,000.
Example 2.12 Estimate the error associated with taking 1.6 to be a root of the equation x2 − x − 1 = 0. √ The exact values for the roots are (1 ± 5)/2 (let us take the positive root). As such the absolute error is
1 + √5
− 1.6 ≈ 0.01803398874989
2
and the relative error is the absolute error divided by the value 1.6 (or alternatively the exact root) which is approximately equal to 0.01127124296868 or 1.127%. We could also substitute x = 1.6 into the equation to see how wrong it is: 1.62 − 1.6 − 1 = −0.04. Although it is difficult to understand how this can be used, it is often the only option (particularly if the exact answer cannot be found). This method can be used to determine roots of a function. We now discuss an example which uses this technique:
2.4 Errors
53
Example 2.13 Determine a value of x such that f (x) = x2 + 4x = 40. We start by guessing that x = 6 is the root we require: x = 6, f (6) = 60 > 40 which is too big, try x = 5. x = 5, f (5) = 45 > 40 which is still too big, try x = 4. x = 4, f (4) = 32 < 40 now this is too small, so we shall try x = 4.5. x = 4.5, f (4.5) = 38.25 < 40 a bit too small, try x = 4.75 x = 4.75, f (4.75) = 41.5625 > 40 a bit too big, back down again to x = 4.625 x = 4.625, f (4.625) = 39.890625 < 40 a bit too small, back up again to x = (4.75 + 4.625)/2 x = 4.6875, f (4.6875) = 40.72265625 > 40 and we can continue this process. Here we have just moved around to try to find the value of x such that f (x) = 40, but we could have done this in a systematic manner (actually using the size of the errors). It appears that in order to work out the error one needs to know the exact answer in which case the whole idea of an error would seem to be superfluous. In fact when we focus on errors we are merely trying to work out their size (or magnitude) rather than their actual numerical value. Before we move on we revisit the MATLAB variable eps. This is defined as the smallest positive number such that 1+eps is different from 1. Consider the calculations: x1 = 1+eps; y1 = x1-1 x2 = 1+eps/2; y2 = (x2-1)*2 In both cases using simple algebra you would expect to get the same answer, namely eps; but in fact y2 is equal to zero. This is because MATLAB cannot distinguish between 1 and 1+eps/2. The quantity eps is very useful, especially when it comes to testing routines.
Example 2.14 Calculate the absolute errors associated with the following calculations:
54
2. Writing Scripts and Functions
sin(15*pi) (sqrt(2))ˆ2 1000*0.001 1e10*1e-10 To calculate the absolute errors we need to know the exact answers which are 0, 2, 1 and 1 respectively. We can use the code: abs(sin(15*pi)) abs((sqrt(2))ˆ2-2) abs(1000*0.001-1) abs(1e10*1e-10-1) (notice in the last case the exponent form of the number takes precedence in the calculation: we could of course make sure of this using brackets). The errors are 10−15 , 10−16 and zero (in the last two cases).
2.4.2 User Error The elimination of user error is critical in achieving accurate results. In practice user error is usually more critical than numerical errors, and after some practise their identification and elimination becomes easier. User error is avoidable, whereas many numerical errors are intrinsic to the numerical techniques or the computational machinery being employed in the calculation. The most severe user errors will often cause MATLAB to generate error messages; these can help us to understand and identify where in our code we have made a mistake. Once all the syntax errors have been eliminated within a code (that is MATLAB is prepared to run the code), the next level of errors are harder to find. These are usually due to: 1. An incorrect use of variable names. This may be due to a typographical error which has resulted in changes during the coding. 2. An incorrect use of operators. The most common instance of this error occurs with dot arithmetic. 3. Syntactical errors which still produce feasible MATLAB code. For instance in order to evaluate the expression cos x, we should use cos(x): unfortunately the expression cos x also yields an answer (which is incor-
2.4 Errors
55
rect); somewhat bizarrely cos pi yields a row vector (which has the cosines of the ASCII values of the letters p and i as elements). 4. Mathematical errors incorporated into the numerical scheme the code seeks to implement. These usually occur where the requested calculation is viable but incorrect (see the example on page 181). 5. Logical errors in the algorithm. This is where an error has occurred during the coding and we find we are simply working out what is a wrong answer. Avoiding all of these errors is something which only comes with practice and usually after quite a lot of frustration. The debugging of any program is difficult, fortunately in MATLAB we have the luxury of being able to access variables straight away. This allows us to check results at any stage. Simply removing the semicolons from a code will cause the results to be printed. Although this is not recommended for codes which will produce a deluge of results, it can be very useful. In Task 2.10 at the end of this chapter and similarly in other chapters8 , we have included some codes with deliberate errors. They also contain commands from future chapters: however most of the errors do not rely on understanding the nuances of these unfamiliar commands. Hopefully by trying to locate the errors in these you should start to develop the debugging skills which will eventually ensure you become a competent programmer. We shall start with a couple of examples which demonstrate some of the most common sources of problems. Of course it is impossible to predict all possible errors which could be made, but the more you are aware of the better!
Example 2.15 This code purports to obtain three numbers a, b and c from a user and then produce the results a + b + c, a/((b + c)(c + a)) and a/(bc). 8
These tasks are marked with (D).
56
2. Writing Scripts and Functions
' a = input(’ Please entere a ) b = 1nput(’ Please enter b ) a = Input ’ Please enter c ’
$
v1 = a+ B+d v2 = a/((b+c)(c+a) v3 = a/b*c disp(’ a + b + c= ’ int2str(v1)]) disp([’v2 = ’ num2str v2 ] disp([’v3 = num2str(v4) ]); & % We shall now work through the lines one-by-one detailing where the errors are and how they can be fixed. a = input(’ Please entere a ) Firstly the single left-hand quote mark should be balanced by a corresponding right-hand quote mark. The command should also end with a semicolon. This will stop the value of a being printed out after it is entered. The misspelling of the word enter is annoying but will not actually affect the running of the code: however it is worth correcting if only for presentation’s sake. b = 1nput(’ Please enter b ) Again we have an imbalance in the single quote mark and the lack of a semicolon. We also have the fact that input has become 1nput. a = Input ’ Please enter c ’ Here we have a capitalised command (which MATLAB will actually point out in its error message – try typing Input in MATLAB). Again we are missing the semicolon, but the more severe errors here are the lack of brackets around the message and the fact that we are resetting the variable a. This erases the previous value of a and also does not set the value of c as we intended. v1 = a+ B+d The spacing is unimportant and is merely a matter of style. Here again we should add a semicolon. The main problem here is that the variable b has been capitalized to B and since MATLAB is case sensitive these are treated as different variables. Another new variable d has also slipped in. This means MATLAB will either complain that the variable has not been initialised or will use a previous value which has nothing to do with this calculation. To avoid this it is a good idea to start the code with clear all to clear all variables from memory. v2 = a/((b+c)(c+a) This command presents a number of errors in the evaluation of the denominator of the fraction. The first of these is the missing
2.5 Tasks
57
asterisk between the two factors and secondly we have a unbalanced bracket. v3 = a/b*c This has one error but it is one of the most common ones. As mentioned previously this evaluates ab c. We need to force the calculation bc to be performed first by using brackets. With this (and the previous two commands we might want to elect to add semicolons to stop extra output). disp(’ a + b + c= ’ int2str(v1)]) This command is missing a left square bracket to show that we are going to display a vector (with strings as elements). We have used the command int2str which takes an integer and returns a character string. However at no point have we specified that a, b and c are integers. We should instead use the command num2str which converts a general number to a character string. disp([’v2 = ’ num2str v2 ] This command is missing a round bracket from the end of the expression and a pair of brackets to show that num2str is being applied to the variable v2. disp([’v3 = num2str(v4) ]); Here we are missing a single quote to show that the string has ended (after the equals sign). We have also erroneously introduced a new variable v4 which should be v3. The semicolon on the end of this line is superfluous since the disp command displays the result. The corrected code looks like: ' clear all a = input(’ Please enter a ’); b = input(’ Please enter b ’); c = input(’ Please enter c ’);
$
v1 = a+b+c; v2 = a/((b+c)*(c+a)); v3 = a/(b*c); disp([’ a + b + c= ’ num2str(v1)]) disp([’ v2 = ’ num2str(v2)]) disp([’ v3 = ’ num2str(v3)]) &
2.5 Tasks Task 2.1 Enter and run the code
%
58
2. Writing Scripts and Functions
' $ a = input(’Enter a : ’); b = input(’Enter b : ’); res = mod(a,b); str1 = ’The remainder is ’; str2 = ’ when ’ ; str3 = ’ is divided by ’; disp([str1 num2str(res) str2 ... num2str(a) str3 num2str(b)]); & % which should be saved as remainders.m. Experiment with this code by running it with various values for a and b. Make sure you understand how this code works, in particular the mod command and the disp command. Task 2.2 Modify the code in Task 2.1 so it returns the answer to ab and change the character strings str1, str2 and str3 so that the format of the answer is ‘The answer is ab when a is raised to the power b’.
Task 2.3 Write a code which takes a variable x and returns the value of 2x . Make sure that your code works for variables which are scalars, vectors and matrices.
Task 2.4 By modifying the function func.m (given earlier on page 32) repeat the example for the functions x2 − y 2 and then sin(x + y) (extending the range to [0, 2π] in the latter case).
Task 2.5 Modify the code xpowers.m to simultaneously give the values of the functions sin x, cos x and sin2 x + cos2 x.
Task 2.6 Modify the code multi.m in Example 2.5 to work out the values of the map: x → (x + y)|1 y → (x + 2y)|1, where (a|b) is the remainder when a is divided by b and can be calculated using the MATLAB function mod. If b is unity this is the fractional part. This new function will take two inputs and return two outputs.
2.5 Tasks
59
Task 2.7 The code clear x y x = -2:0.1:2; y = 9-x.ˆ2; plot(x,y) 2 plots the function y = 9 − x for x ∈ [−2, 2] in steps of 1/10. Modify the code so the function y = x3 + 3x is plotted between the same limits and then for x ∈ [−4, 6] in steps of 1/4. (If you can’t see the current figure, type figure(1) which should bring it to the foreground). This code can be run from the prompt or can be entered using edit and then saved. Task 2.8 Consider the quartic y = x4 + x2 + a. For which values of a does the equation have two real roots? Task 2.9 Plot on the same graph the functions f (x) = x + 3, g(x) = x2 + 1, f (x)g(x) and f (x)/g(x) for the range x ∈ [−1, 1]. (You need to decide how many points to use to get a smooth curve, and whether to set up the vector x either using the colon construction or linspace). You also need to remember to use dot arithmetic since you are operating on vectors.
Task 2.10 (D) This task contains codes which are written with deliberate mistakes. You should try to debug the codes so that they actually perform the calculations they are supposed to: 1. Perform the calculations x=4 x+2=y 1 z= 2 y π x=4 x+2=y z=1/yˆ2Pi 2. Calculate the sum
N 1 i=1
i
+
1 (i + 2)(i + 3)
60
2. Writing Scripts and Functions
where the user inputs N . ' N=input(’Enter N )
$
for i=1:n sum = 1/j + 1/(j+2)*(j+3) end disp( ’ The answer is ’ s]) &
%
Make sure the code gives the correct answer, for instance for N = 1. 3. Calculate the function f (x) =
(x2
x cos x + 1)(x + 2)
for x from 0 to 1 in steps of 0.1.
x==0.0:0.1:1.0; f=xcos x/*([xˆ2+1]*(x+2)
4. Set up the vector 1 3 3 3 5 3 7 3 9 '
$
w = ones(9); w(1) = 1; for j = 1:4 w(2j) = 3: w(2j+1) = 2j+1: &
%
Make sure that the code returns the correct values of the entries of w.
Task 2.11 The following codes should be written to produce conversion between speeds in different units.
2.5 Tasks
61
(a) Construct a code which converts a speed in miles per hour to kilometres per hour. (b) Write a code which converts metres per second to miles per hour and use it to determine how fast a sprinter who runs the 100 metres in 10 seconds is travelling in miles per hour (on average). (c) Rewrite your code from part (a) so that it is now a function that takes a single input, the speed in miles per hour, and returns a single output, the speed in kilometres per hour. (d) Now modify the code you wrote in part (b) to determine the sprinter’s speed in kilometres per hour by calling the function from the previous part. (NB: 1 mile = 1760 yards; 1 yard = 36 inches; 1 inch = 2.54 cm; 1 m = 100 cm)
Task 2.12 The functions f (x) and g(x) are defined by f (x) =
x and g(x) = tan x. 1 + x2
Write MATLAB codes to calculate these functions and plot them on the interval (−π/2, π/2). Also plot the functions f (g(x)) and g(f (x)) on this interval.
Task 2.13 Write a code which enables a user to input the coefficients of a quadratic q(x) = ax2 + bx + c and plot the function q(x) for x = sin y where y ∈ [0, π].
3
Loops and Conditional Statements
3.1 Introduction We now consider how MATLAB can be used to repeat an operation many times and how decisions are taken. We shall conclude with a description of a conditional loop. The examples we shall use for demonstrating the loop structures are by necessity simplistic and, as we shall see, many of the commands can be reduced to a single line. The true power of computers comes into play when we need to repeat calculations over and over again. In order to help you to understand the commands in this chapter, it is suggested that you work through the codes on paper. You should play the rˆ ole of the computer and make sure that you only use values which are assigned at that time. Remember that computers usually operate in a serial fashion and that they can only use a variable once it has been defined and given a value. This kind of thought process is very helpful when designing your own codes.
3.2 Loops Structures The basic MATLAB loop command is for and it uses the idea of repeating an operation for all the elements of a vector. A simple example helps to illustrate this:
64
3. Loops and Conditional Statements
' % % looping.m % N = 5; for ii = 1:N disp([int2str(ii) ’ squared equals ’ int2str(iiˆ2)]) end & This gives the output 1 2 3 4 5
squared squared squared squared squared
equals equals equals equals equals
$
%
1 4 9 16 25
The first three lines start with % indicating that these are merely comments and are ignored by MATLAB. They are included purely for clarity, and here they just tell us the name of the code. The fourth line sets the variable N equal to 5 (the answer is suppressed by using the semicolon). The for loop will run over the vector 1:N, which in this case gives [1 2 3 4 5], setting the variable ii to be each of these values in turn. The body of the loop is a single line which displays the answer. Note the use of int2str to convert the integers to strings so they can be combined with the message “ squared equals ”. Finally we have the end statement which indicates the end of the body of the loop. We pause here to clarify the syntax associated with the for command: for ii = 1:N commands end This repeats the commands for each of the values in the vector with ii= 1, 2, · · · , N . If instead we had for ii = 1:2:5 then the commands would be repeated with ii equal to 1, 3 and 5. Notice in the code above we have indented the disp command. This is to help the reading of the code and is also useful when you are debugging. The spaces are not required by MATLAB. If you use MATLAB built-in editor (using the command edit) then this indentation is done automatically.
Example 3.1 The following code writes out the seven times table up to ten seven’s.
3.2 Loops Structures
' str = ’ times seven is ’;
65
$
for j = 1:10 x = 7 * j ; disp([int2str(j) str int2str(x)]) end & % The first line sets the variable str to be the string “ times seven is ” and this phrase will be used in printing out the answer. In the code this character string is contained within single quotes. It also has a space at the start and end (inside the quotes); this ensures the answer is padded out. The start of the for loop on the third line tells us the variable j is to run from 1 to 10 (in steps of the default value of 1), and the commands in the for loop are to be repeated for these values. The command on the fourth line sets the variable x to be equal to seven times the current value of j. The fifth line constructs a vector consisting of the value of j then the string str and finally the answer x. Again we have used the command int2str to change the variables j and x into character strings, which are then combined with the message str.
Example 3.2 The following code prints out the value of the integers from 1 to 20 (inclusive) and their prime factors. To calculate the prime factors of an integer we use the MATLAB command factor for i = 1:20 disp([i factor(i)]) end This loop runs from i equals 1 to 20 (in unit steps) and displays the integer and its prime factors. There is no need to use int2str (or num2str) here since all of the elements of the vector are integers. The values for which the for loop is evaluated do not need to be specified inline, instead they could be set before the actual for statement. For example r = 1:3:19; for ii = r disp(ii) end displays the elements of the vector r one at a time, that is 1, 4, 7, 10, 13, 16 and 19; of course we could have used more complicated expressions in the loop.
66
3. Loops and Conditional Statements
The following simple example shows how loops can be used not only to repeat instructions but also to operate on the same quantity.
Example 3.3 Suppose we want to calculate the quantity six factorial (6! = 6 × 5 × 4 × 3 × 2 × 1) using MATLAB. One possible way is fact = 1; for i = 2:6 fact = fact * i; end To understand this example it is helpful to unwind the loop and see what code has actually executed (we shall put two commands on the same line for ease) fact i=2; i=3; i=4; i=5; i=6;
= 1; fact fact fact fact fact
= = = = =
fact fact fact fact fact
* * * * *
i; i; i; i; i;
At At At At At
this this this this this
point point point point point
fact fact fact fact fact
is is is is is
equal equal equal equal equal
to to to to to
2 6 24 120 720
The same calculation could be done using the MATLAB command factorial(6). Example 3.4 Calculate the expression n Cm for a variety of values of n and m. This is read as ‘n choose m’ and is the number of ways of choosing m objects from n. The mathematical expression for it is n
Cm =
n! . m!(n − m)!
We could rush in and work out the three factorials in the expression, or we could try to be a little more elegant. Let’s consider n!/(n − m)! is equal to n × (n − 1) × (n − 2) × · · · × (n − m + 1). We can therefore use the loop structure. Note also that there are m terms in this product, as there are in m!, so we can do both calculations within one loop
3.2 Loops Structures
67
' $ prod = 1; mfact = 1; for i = 0:(m-1) mfact = mfact * (i+1); prod = prod * (n-i); end soln = prod/mfact; & % Breaking up the calculation like this can lead to problems for large values of m and so it is often best to work out the answer directly: soln = 1; for i = 0:(m-1) soln = soln * (n-i) / (i+1); end This product could also be written as: soln = 1; for i = 0:(m-1) soln = soln * (n-i) / (m-i); end This version may have a slight computational advantage since the terms appearing in the fractions are closer in magnitude. That these two versions are identical can be seen by rewriting the product as n n − 1 n−m+2 n−m+1 t= ··· 1 2 m−1 m or as s=
n n − 1 m
m−1
···
n−m+2 2
n−m+1 1
.
This example could also be done using the MATLAB command prod, which calculates the product of the elements of a vector; in fact MATLAB has a command nchoosek designed for just this calculation. In order to use prod we could use: M = 1:m; t = (n-1+M)./M; prod(t) s = (n-1+M)./(m-M+1); prod(s)
68
3. Loops and Conditional Statements
where t and s correspond to the two expressions above. So far we have dealt with products: in the next example we shall consider a simple summation.
Example 3.5 Determine the sum of the geometric progression 6
2n .
n=1
This is accomplished using the code: total = 0 for n = 1:6 total = total + 2ˆn; end which gives the answer 126, as you might expect from the formula for the sum of a geometric progression 1 − rn S=a 1−r where a is the first term, r is the ratio of the terms and n is the number of terms. In our case a = 2, r = 2 and n = 6, which gives S = 126. We now go through the ideas of summing series more thoroughly since it provides important information on how loop structures work.
3.3 Summing Series In Example 3.5 we have summed a series: we now describe this topic in more detail. We start by constructing a code to evaluate N
i2 .
i=1
Firstly, we note that we do not necessarily know N so this will need to be entered by the user or on a command line. We will first do one case by “hand”. Let us consider N = 4, so we wish to determine 4 i=1
i2 .
3.3 Summing Series
69
If we were to do this on paper we would probably write down all the terms in the summation and then add them up: evaluating the terms in the series 4
i2 = 1 + 4 + 9 + 16
i=1
and adding them up we obtain 30. At this stage we can add the terms up in our heads: however, what would happen if N was larger, for instance 10. In this case note the answer is given by 10 i2 = 1 + 4 + 9 + 16 + 25 + 36 + 49 + 64 + 81 + 100. i=1
But in fact we may actually do it like this: - The first term corresponds to i = 1, for which i2 = 1. - The second term, that is i = 2, has i2 = 4 and adding to the previous answer gives 1 + 4 = 5. - The third term, that is i = 3, has i2 = 9 and adding to our previous answer gives 5 + 9 = 14, etc. We can automate this process by using the MATLAB code: ' N = input(’Enter the number of terms required: ’); s = 0;
$
for i = 1:N s = s + iˆ2; end disp([’Sum of the first ’ int2str(N) ... ’ squares is ’ int2str(s)]) & % As we mentioned earlier the command int2str converts an integer to a string. This means we can concatenate these strings into a sentence. If we tried apple = 8;disp([’I have ’ apple ’ apples’]) MATLAB misses out the number and gives “I have apples”, whereas the command
70
3. Loops and Conditional Statements
disp([’I have ’ int2str(apple) ’ apples’]) gives “I have 8 apples”, as required: for more information on this command see page 185. We can break down our summation code as follows: – The first line simply asks the user to enter the value of N when prompted with the string contained in the input statement. – The second line sets a variable s to be zero: this will be used to store the cumulative sum. The blank line is included to make our code more readable. – The next three lines form a loop. The loop variable is i which runs from 1 to N. This means the command in the loop will be repeated for each of these values. The value of iˆ2 will be added to the previous value of s. – After the loop there is another blank line (again purely for readability). – Finally, we display our results using the disp command. We have constructed a row vector with four elements: the first and third elements are merely the strings ’Sum of the first ’ and ’ squares is ’ whereas the second and fourth are the values N and s converted from integers to strings using the MATLAB command int2str. We can now modify the above code to determine the value of the summation 7
i3 .
i=3
Previously we were asked to calculate the sum of square terms and now we need the sum of cubes so the line s = s + iˆ2; needs to be modified to s = s + iˆ3;. We also need to change the range which the loop runs over from 1:N to 3:7, which is accomplished by changing the argument of the for loop to i = 3:7. The modified code will now work, however it will ask for a value of N which is no longer relevant. We can comment out this line by prepending it with a percentage sign. This instructs MATLAB to ignore everything else on this line. This can be very useful when you want to change a code but do not want to just delete lines. It can also be used to include comments so you can understand the code. Finally, we need to change the line which outputs the results, the amended code looks like this: ' $ % N = input(’Enter the number of terms required: ’); s = 0; for i = 3:7 s = s + iˆ3; end disp([’Required value of the summation is ’ int2str(s)]) & %
3.3 Summing Series
71
Again we have used the command int2str to change the variable s into a string. This only works correctly if s is an integer. If s is not an integer we need to use the command num2str which changes a general number to a string. In all the cases so far we have only been interested in the final answer. Let’s consider instead the problem of determining the values of IN =
N
f (i),
i=1
where the f(i) are defined by the problem at hand. At the moment we will stick to f(i) = iˆ2. Again we shall start by doing an example by hand, let us determine the values of I N for N equals one to four. Firstly N = 1 I1 =
1
i2 = 1,
i=1
and now N = 2, which is I2 =
2
i2 = 1 + 4 = 5,
i=1
and N = 3, I3 =
3
i2 = 1 + 4 + 9 = 14,
i=1
and finally N = 4, which gives I4 =
4
i2 = 1 + 4 + 9 + 16 = 30.
i=1
You should have noticed that I 2 = I 1+2ˆ2, I 3 = I 2+3ˆ2 and I 4 = I 3+4ˆ2: These are just like the elements of an array (or vector). In general IN = IN −1 + N 2 .
(3.1)
It is exactly this kind of recursion relation which a computer can take advantage of. In order to calculate these values we can use the code:
72
3. Loops and Conditional Statements
' maxN = input(’Enter the maximum value of N required: ’); I(1) = 1ˆ2;
$
for N = 2:maxN I(N) = I(N-1) + Nˆ2; end disp([’Values of I_N’]) disp([1:N; I]) & % This code uses a vector I to store the results of the calculation. It first prompts the user to input the value of N, which it stores in the variable maxN. The first value of the vector is then set as 12 . Equation (3.1) now tells us the relation between the first and second elements of I, which we exploit in the loop structure. The final two lines display the string Values of I N and the actual values. The answers are given as a matrix, the first row of which contains the numbers 1 to N and the second row gives the corresponding values of I N. This produces the results: Enter the maximum value of N required: 10 Values of I_N 1 2 3 4 5 6 7 1 5 14 30 55 91 140
8 204
9 285
10 385
(for N = 10). This can be compared with the analytical solution, see equation (3.4). Up until now we have considered very simple summations. Let’s now see how we can sum the series where the terms are defined by some function f(i). We use a separate MATLAB program to construct the series. Let’s consider IN =
N i=1
i sin
iπ . 4
We start by using a code f.m which will return the coefficients we are going to sum. You should enter this code and save it as f.m. function [value] = f(inp) value = inp * sin(inp*pi/4); – The first line tells the computer this program is a function, which should take as input a value inp and return the variable value (if value is undefined MATLAB will complain).
3.3 Summing Series
73
– The second line simply works out the required value. Notice that MATLAB already has a variable pi. The above code is now modified to: ' maxN = input(’Enter the maximum value of N required: ’); I(1) = f(1);
$
for N=2:maxN I(N) = I(N-1) + f(N); end disp([’Values of I_N’]) disp([1:N; I]) & This produces the result
%
Enter the maximum value of N required: 5 Values of I_N 1.0000 2.0000 3.0000 4.0000 0.7071 2.7071 4.8284 4.8284
5.0000 1.2929
(for N = 5). We note that here we have a good example of the differing meanings of the command y(n). In the case of I(N), this refers to the N th entry of the array I, whereas for f(N), it refers to the function f evaluated at the point N. This subtle difference is critical!
3.3.1 Sums of Series of the Form
N j=1
j p, p ∈ N
Let’s consider the simple code which works out the sum of the first N integers raised to the power p:
74
3. Loops and Conditional Statements
' % Summing series
$
N = input(’Please enter the number of terms required ’); p = input(’Please enter the power ’); sums = 0; for j = 1:N sums = sums + jˆp; end disp([’Sum of the first ’ int2str(N) ... ’ integers raised to the power ’ ... int2str(p) ’ is ’ int2str(sums)]) & so this produces N SN = jp.
%
j=1
We note the formula when p = 1 is given by N (N + 1)/2. We pause here to think how we could work this out. If we substitute in the values N = 1, N = 2 and N = 3 (all for p = 1) we would obtain three points on the ‘curve’ and these will uniquely determine its coefficients (assuming it is a quadratic). We assume that SN = aN 2 + bN + c and use the three values above to give three simultaneous equations from which we can determine the coefficients a, b and c, these equations are: N =1
a + b + c = S1 = 1,
(3.2a)
N =2
4a + 2b + c = S2 = 1 + 2 = 3,
(3.2b)
N =3
9a + 3b + c = S3 = 1 + 2 + 3 = 6.
(3.2c)
From (3.2a) we see that c = 1 − a − b and this can be substituted into the other two equations to yield 3a + b = 2,
(3.3a)
8a + 2b = 5.
(3.3b)
Now using (3.3a) in (3.3b) we find a = 1/2 and then in (3.3a), b = 1/2 and finally using (3.2a) we have c = 0. Hence SN =
1 2 1 N + N, 2 2
for N = 1, 2, 3.
In order to prove that this is true for all N we can use proof by induction.
3.3 Summing Series
75
It seems reasonable to expect that the sum for a certain power of p will be of degree p + 1. In order to determine the coefficients of a polynomial of degree p + 1 we require p + 2 points. Consider this example: ' $ clear all format rat p = input(’Please enter the power you require ’); points = p+2; n = 1:points; for N=n sums(N)=0; for j = 1:N sums(N) = sums(N) + jˆp; end end [coe] = polyfit(n,sums,p+1) format & % This code is worth dissecting, since it is our first example of nested loops. – The first line ensures all values of variables have been cleared. This is good programming practice since it means undeclared variables will be noticed rather than used incorrectly. – The second line sets the format for the duration of this run to be rat, forcing MATLAB to try to print the answers as rationals (notice this is coupled with the final line which merely resets the formatting to the default). – The next line asks the user for the value of p. As noted above we need to determine p + 2 coefficients and as such we need p + 2 equations. A vector n is set up running over these values. – We now have a nested for loop structure which sets up the points (from 1 to p + 2). – The next line sets the initial value of the element of the array sums to be zero, ready to be set to the required cumulative sum. This sum is calculated within the inner loop. We note again that each for statement needs to be balanced with an end. – Now we use the MATLAB intrinsic command polyfit which gives the coefficients of the required polynomial. The syntax of this command is
76
3. Loops and Conditional Statements
polyfit(x,y,n) which returns the coefficients of order n through the points in (x, y). For the examples p = 2 and p = 3 we have >> sumser2 Please enter the power you require 2 coe = 1/3
1/2
1/6
*
>> sumser2 Please enter the power you require 3 coe = 1/4
1/2
1/4
*
*
Notice here we have asked the code to try to give us rational answers. The asterisks are merely where MATLAB cannot express zero (or something close to it) as a rational. In the first case we have N
j2 =
j=1
N2 N N N3 + + = (2N + 1)(N + 1), 3 2 6 6
(3.4)
(where we have factorised our answer) and in the second case N j=1
j3 =
N4 N3 N2 N2 + + = (N + 1)2 . 4 2 4 4
We could use this procedure for any integer value of p: however a rigorous proof requires mathematical induction (or another similar process).
3.3.2 Summing Infinite Series We now consider examples where we need to truncate the series.
Example 3.6 The Taylor series for a function f (x) about a point x = a is given by ∞ (x − a)n (n) f (x) = f (a) + f (a). n! n=0
3.3 Summing Series
77
We can use this to approximate sin x by an infinite series in x as sin x = lim
N →∞
N n=0
(−1)n
x2n+1 . (2n + 1)!
Of course in using a computer we cannot actually take N to be infinity, but we shall take it to be large in the hope that the error will be small. We can write the above series (taking N = 10) and evaluate the series at the points 0, 0.1, 0.2, 0.3, 0.4 and 0.5 using ' $ v = 0.0:0.1:0.5; sinx = zeros(size(v)); N = 10; range = 0:N; ints = 2*range+1; for n = range sinx = sinx+(-1)ˆn*v.ˆints(n+1)... /(factorial(ints(n+1))); end & % This is perhaps the most complicated code we have produced so far, so we shall pause and break it down. v = 0.0:0.1:0.5; sets up the vector v running from zero to a half in steps of a tenth. sinx = zeros(size(v)); In order to understand this command it is best to start with what’s inside the brackets. The command size(v) gives the size of the vector v and then the command zero sets up sinx as an array of zeros of the same size. N = 10; range = 0:N; sets a variable N to be equal to 10 and then sets up a vector range which runs from zero to N. ints = 2*range+1; This gives the mathematical expression 2n + 1 for all the elements of the vector range and puts them in ints. for n = range ..... end This loop structure repeats its arguments for n equal to all the elements of range. sinx = sinx+(-1)ˆn*v.ˆints(n+1)/(factorial(ints(n+1))); This mathematical expression evaluates the subject of the summation as a function of n. (Notice the necessary offset when referring to the elements of ints, for instance ints(1) refers to the value when n = 0). Also note the use of .ˆ when operating on v as this is a vector. Running this gives
78
3. Loops and Conditional Statements
>> sinx sinx = 0
0.0998
0.1987
0.2955
0.3894
0.4794
These values can be compared to those calculated directly by MATLAB to give >> sin(v) ans = 0
0.0998
0.1987
0.2955
0.3894
0.4794
0.1388
0.2776
0
-0.5551
0
>> sinx-sin(v) ans = 1.0e-16 * 0
Since all the elements of the vector sinx-sin(v) share a factor of 1.0e-16 this has been extracted. This results shows that our approximation has worked very well (for relatively few terms). For larger values of x more terms might be needed. For a value of x = π we find the same number of terms as used above produces a value of ∼ 10−11 , which is still a good approximation (since the actual value of sin π is zero), but not quite as good as those shown above. The infinite series given above actually converges for all values of x.
Example 3.7 Calculate the sum ∞
e−n .
n=0
This poses a problem for us since we can obviously not add up an infinite number of terms, we need to truncate the calculation. In this case we do not need very many terms since e−x gets very small very quickly. We can use the code:
3.3 Summing Series
79
# N = 10; total = 0; for n = 0:N total = total + exp(-n); end " ! To test for convergence of our results we should compare our answer for different values of N. Fortunately, in this case, we are able to work out the value of the truncated series, since it is merely a geometric progression (the formula for the sum of a geometric progression is given on page 68). The first term is e0 = 1 and the ratio between successive terms is 1/e, hence the sum is SN =
1 − e−(N +1) . 1 − e−1
In the limit as N → ∞ this tends to S∞ =
1 e ≈ 1.581977. = −1 1−e e−1
If we compare the results for N = 10 the error is already ∼ 10−5 . To find a formula for the error we need to calculate |SN − S∞ |, which is
1 − e−(N +1) 1
e−N
, = |SN − S∞ | =
− 1 − e−1 1 − e−1 e − 1
which decreases (exponentially fast) as N increases.
3.3.3 Summing Series Using MATLAB Specific Commands So far we have used commands which are common to many programming languages (or at least similar to) and have not exploited the power of MATLAB. In the first example, given above, we mentioned the idea of adding things up in our head. MATLAB is very good at this type of exercise. Consider the previous example 10 i2 . i=1
Firstly we set up a vector running from one to ten: i = 1:10; and now a vector which contains the values in i squared:
80
3. Loops and Conditional Statements
i_squared = i.ˆ2; Now we use the MATLAB command sum to evaluate this: value = sum(i_squared) (notice here we have left off the semicolon so the result is displayed automatically). The full code for this example is i = 1:10; i_squared = i.ˆ2; value = sum(i_squared) This can all be contracted on to one line sum((1:10).ˆ2): you should make sure you know how this works! Using the command sum allows us to simplify our codes: however it is essential we understand exactly what it is doing. Consider a problem where we have a set of values y1 , y2 up to yN , where for the sake of argument N is taken to be odd. The problem is to work out the sum of the series N
yi f (i),
i=1
where f (i) = 1 when i is odd and f (i) = 2 when i is even. We can set up these values of f using the commands: # N = 11; iodd = 1:2:N; ieven = 2:2:(N-1); f(iodd) = 1; f(ieven) = 2; " ! which gives f = 1
2
1
2
1
2
1
2
1
2
1
This can be achieved in one command, namely 2-mod(1:11,2). We can now use a similar code to those we wrote earlier to sum the series. For example if y = x2 , we have x = 1:11; y = x.ˆ2; sum(y.*f)
3.3 Summing Series
81
This kind of expression will prove to be very useful when we come to consider numerically evaluating integrals in a later chapter.
Example 3.8 Evaluate the expression N
1+
n=1
2 n
for N = 10 (the symbol means the product of the terms, much in the same way means summation). This can be done using the code: n = 1:10; f = 1+(2)./n; pr = prod(f) The first line sets up a vector with elements running from 1 to 10; the second line sets up a vector f whose elements have the values 1 + 2/n; notice f is the same shape as n. We have divided 2 by a vector and so we have used “./” rather than just “/”. If you want to see what the code does, just leave off the semicolons; this will show you the vectors which are generated. Finally, the last line gives the product of all the elements of the vector f. This gives the answer 66. This can be seen by a slight rearrangement of the expression N n=1
1+
2 n
=
N n+2 n=1
n
N
=
n+2
n=1 N
, n
n=1
where we have used the fact the products:
an bn = ( an )( bn ). Now actually evaluating (N + 2)(N + 1) · · · 3 N (N − 1) · · · 1 (N + 2)!/(2.1) (N + 2)(N + 1) = = . N! 2 =
When N = 10 this gives a value of 66.
82
3. Loops and Conditional Statements
3.3.4 Loops Within Loops (Nested) Many algorithms require us to use nested loops (loops within loops), as in the example of summing series on page 75. We illustrate this using a simple example of constructing an array of numbers: # for ii = 1:3 for jj = 1:3 a(ii,jj) = ii+jj; end end " ! Notice that the inner loop (that is, the one in terms of the variable jj) is executed three times with ii equal to 1, 2 and then 3. These structures can be extended to have further levels. Notice each for command must be paired within an end, and for the sake of readability these have been included at the same level of indentation as their corresponding for statement.
Example 3.9 Calculate the summations N
jp
j=1
for p equal to one, two and three for N = 6. We could perform each of these calculations separately but since they are so similar it is better to perform them within a loop structure: ' $ N = 6; for p = 1:3 sums(p) = 0.0; for j = 1:N sums(p) = sums(p)+jˆp; end end disp(sums) & % The order in which the loops occur should be obvious for each problem but in many examples the outer loop and inner loop could be reversed.
3.4 Conditional Statements
83
3.4 Conditional Statements MATLAB has a very rich vocabulary when it comes to conditional operations but we shall start with the one which is common to many programming languages (even though the syntax may vary slightly). This is the if command which takes the form: if (expression) commands ... end As you might expect, if the expression is true then the commands are executed, otherwise the programme continues with the next command immediately beyond the end statement. There are more involved forms of the command, but before proceeding with these let’s first discuss the construction of the expression. Firstly there are the simple mathematical comparisons a a a a a a
< b <= b > b >= b == b ∼= b
True True True True True True
if if if if if if
a a a a a a
is is is is is is
less than b less than or equal to b greater than or equal to b greater than or equal to b equal to b not equal to b
More often than not we will need to form compound statements, comprising more than one condition. This is done by using logical expressions, these are: and(a,b) or(a,b) not(a) xor(a,b)
Logical AND Logical OR NOT Logical exclusive OR
a & b a | b ∼a
The effect of each of these commands is perhaps best illustrated by using tables AND false true
false false false
true false true
OR false true
false false true
true true true
XOR false true
false false true
true true false
84
3. Loops and Conditional Statements
NOT (∼) This simply changes the state so ∼(true)=false and ∼(false)=true. We pause and just run through these logical operators: a AND b This is true if both a and b are true a OR b This is true if one of a and b is true (or both). a XOR b This is true if one of a and b is true, but not both. In many languages you can define Boolean (named after George Boole) variables and these will have actual logical meaning. For instance in Excel you can set values to be True or False. In MATLAB zero represents False and any other value implies True. We shall adopt the convention that 1 (one) is true and 0 (zero) is false. In fact sometimes it is useful to define variables such that false=0; true= (∼false). This statement is read as set true to be equal to not false; we have added the brackets for clarification.
Example 3.10 In the following examples it may be helpful to draw pictures, but we should at least teach you to read these statements. We recall that in this context a square bracket means a closed set (that is, including the end point) whereas a round bracket indicates an open set (that is, not including the end point). Determine the sets for which these statements are true: 1. x>1 & x<2 We can read this command as “x is greater than one and less than two”. This is obviously true only for values between one and two (not inclusive). This is the open set (1, 2). 2. x<0 | x>=1 This command can be read as “x less than zero or greater than (or equal to) one”. This set has two parts: x strictly negative or x greater than (or equal to one). Hence the set is (−∞, 0) ∪ [1, ∞). 3. x>1 | x<2 This command can be read as “x greater than 1 or x less than 2”. In fact all values of x are greater than one or less than 2, hence the answer is (−∞, ∞). 4. x<=1 | x>=1 This one says “x is less than (or equal to) 1 or x is greater than (or equal to 1)”. This again is true for all values of x, hence the answer is (−∞, ∞). 5. x<=1 & x>=1 This one is similar to the previous one with one word changed so it now reads:“x is less than (or equal to) 1 and x is greater than (or equal to 1)”.
3.4 Conditional Statements
85
The only value which is less than (or equal to) one and greater than (or equal to) one is one itself. The answer is the single value one, written as {1}. 6. ∼(x>2) This is our first example of negation, which is read as “x is not greater than 2”, which is true for values of x less than (or equal to) 2, that is the set (−∞, 2]. 7. (x>1) & (∼(x<2)) Here we have “x is greater than 1 and x is not less than 2”. The second part of this expression means that x is greater than (or equal to 2) (and the first part is always true for this range), so the solution is [2, ∞). 8. abs(x-1) < 2 Here we have an expression involving a mathematical function: this one is read as: “the modulus of x minus 1 is less than two”. This means points which are within 2 units of the point 1, that is (−1, 3). 9. rem(n,4) == 1 This command calculates the remainder when divided by 4 and checks to see if this is equal to 1. The values for which this is true are {4n + 1 : n ∈ Z}.
3.4.1 Constructing Logical Statements We shall now actually construct logical arguments which can be used in if statements.
Example 3.11 Let us consider a command which is only executed if a value x lies between 1 and 2 or it is greater than or equal to 4. We shall try to describe the thought processes involved: – In order that a value lies between one and two, it has to be greater than one and less than two, so this component is written as: (x>1) & (x<2)
– If x is greater than or equal to 4, which is written simply as x>=4. – Finally, we need to combine these conditions and this is done using the logical operation or, since the value of x could lie in one or the other of the regions. Hence we have
86
3. Loops and Conditional Statements
((x>1) & (x<2)) | (x>=4)
We could use the commands in a different form a = and(x>1,x<2); b = (x>=4); c = or(a,b)
by making use of the and and or commands. Notice here we have actually set “Boolean” variables a, b and c (in fact they are only normal variables which take the values zero or one). We can also use these commands for vectors and matrices (comparing them element-wise). Consider the following >> x = [1 2 0 3]; >> and(x>1,x<4) ans = 0 1 0 >> A = eye(2); >> and(A==1,A>0)
1
ans = 1 0
0 1
If two sets do not intersect then by definition A ∩ B = ∅ (the null, or empty, set). In terms of logical statements we say that the conditions are mutually exclusive. For instance, the condition (x>1)&(x<0) is never true, since x cannot be greater than one and less than zero. Notice that we have used brackets to group the terms in the previous example. This is not always necessary but it is very good practice, especially since we cannot guarantee that the precedence in other languages will be the same. In fact although the expression (x>=4) | ((x>1) & (x<2)) is the same as that given above, removing the brackets from both of them yields different results. In the former case the expression still works, whereas in the latter case
3.4 Conditional Statements
87
MATLAB complains about precedence and invites the user to find out more by using help precedence. It is convenient at this stage to introduce some of the other commands which are available to us when constructing conditional statements, namely else and elseif. The general form of these is given by: ' $ if (expression) commands ... elseif (expression) commands ... else commands ... end & % Notice that each if statement must be paired with an end statement, but we can use as many elseif statements as we like, but only one else (within a certain level). We are also able to nest if statements: again it is recommended that the new levels are indented so as to aid readability.
Example 3.12 Consider the following piece of code which determines which numbers between 2 and 9 go into a specified integer exactly: ' $ str = ’Divisible by ’; x = input(’Number to test: ’); for j = 2:9 if rem(x,j) == 0 disp([str int2str(j)]) end end & % The results of this code can be checked using the factor command. We have used the command rem to obtain the remainder.
Example 3.13 Here we construct a conditional statement which evaluates the function: ⎧ 0 x<0 ⎪ ⎪ ⎨ x 0x1 f (x) = ⎪ 2 − x 1<x2 ⎪ ⎩ 0 x>2 One of the possible solutions to this problem is:
88
3. Loops and Conditional Statements
' $ if x >= 0 & x <= 1 f = x; elseif x > 1 & x <= 2 f = 2-x; else f = 0; end & % Notice that it has not been necessary to treat the end conditions separately; they are both included in the final else clause.
Example 3.14 (Nested if statements) The ideas behind nested if statements is made clear by the following example ' $ if raining if money_available > 20 party elseif money_available > 10 cinema else comedy_night_on_telly end else if temperature > 70 & money_available> 40 beach_bbq elseif temperature>70 beach else you_must_be_in_the_UK end end & %
3.4.2 The MATLAB Command switch MATLAB has a command called switch which is similar to the BASIC command select (the syntax is virtually identical). The command takes the form:
3.4 Conditional Statements
89
' $ switch switch_expr case case_expr1 commands ... case {case_expr2,case_expr3} commands ... otherwise commands ... end & % We shall work through the example given in the manual documentation for this command: ' $ switch lower(METHOD) case {’linear’,’bilinear’} disp(’Method is linear’) case ’cubic’ disp(’Method is cubic’) case ’nearest’ disp(’Method is nearest’) otherwise disp(’Unknown method.’) end & % This code assumes that METHOD has been set as a string. The first command lower(METHOD) changes the string to be lower case (there is also the corresponding command upper). This value is then compared to each case in turn and if no matches are found the otherwise code is executed.
Example 3.15 We refer to the old rhyme that allows us to remember the number of days in a particular month. Thirty days hath September April, June and November All the rest have thirty-one Except February alone which has twenty-eight days clear and twenty-nine on leap year This is exploited in the code:
90
3. Loops and Conditional Statements
' $ msg = ’Enter first three letters of the month: ’; month = input(msg,’s’); month = month(1:3); % Just use the first three letters if lower(month)==’feb’ leap = input(’Is it a leap year (y/n): ’,’s’); end switch lower(month) case {’sep’,’apr’,’jun’,’nov’} days = 30; case ’feb’ switch lower(leap) case ’y’ days = 29; otherwise days = 28; end otherwise days = 31; end & % Before we proceed it is worth discussing a couple of the commands used above. The MATLAB command lower forces the characters in the string to be lower case: for instance if the user typed ’Feb’ the command lower would return ’feb’. We have also included a command which makes sure the code only considers the first three characters of what the user inputs. The command input is used here with a second argument ’s’ which tells MATLAB that a string is expected as an input; without this the user would need to add single quotes at the start and end of the string. You might want to consider what you would need to do to check the user has input a valid month. The next command is very useful for this kind of problem.
3.5 Conditional loops Suppose we now want to repeat a loop until a certain condition is satisfied. This is achieved by making use of the MATLAB command while, which has the syntax while (condition) commands... end
3.5 Conditional loops
91
This translates into English as: while condition holds continue executing the commands.... The true power of this method will be found when tackling real examples, but here we give a couple of simple examples. Example 3.16 Write out the values of x2 for all positive integer values x such that x3 < 2000. To do this we will use the code $ ' x = 1; while xˆ3 < 2000 disp(xˆ2) x = x+1; end value = floor((2000)ˆ(1/3))ˆ2; & % This first sets the variable x to be the smallest positive integer (that is one) and then checks whether x3 < 2000 (which it is). Since the condition is satisfied it executes the command within the loop, that is it displays the values of x2 and then increases the value of x by one. The final line uses some mathematics to check the answer, with the MATLAB command floor (which gives the integer obtained by rounding down; recall the corresponding command to find the integer obtained by rounding up is ceil).
Example 3.17 Consider the one-dimensional map: xn+1 =
xn 3 , + 2 2xn
subject to the initial condition xn = 1. Let’s determine what happens as n increases. We note that the fixed points of this map, that is the points where xn+1 = xn , are given by the solutions of the equation: xn =
xn 3 , + 2 2xn
√ which are xn = ± 3. We can use the code ' xold = 2; xnew = 1;
while abs(xnew-xold) > 1e-5 xold = xnew; xnew = xnew/2+3/(2*xnew); end &
$
%
92
3. Loops and Conditional Statements
This checks to see if xn+1 = xn to within √ a certain tolerance. This procedure gives a reasonable approximation to 3 and would improve if the tolerance (1e-5) was reduced.
3.5.1 The break Command A command which is of great importance within the context of loops and conditional statements is the break command. This allows loops to stop when certain conditions are met. For instance, consider the loop structure ' $ x = 1; while 1 == 1 x = x+1; if x > 10 break end end & % The loop structure while 1==1 ... end is very dangerous since this can give rise to an infinite loop, which will continue ad infinitum; however the break command allows control to jump out of the loop.
3.6 MATLAB Specific Commands We could have coded the Example 3.16 using the MATLAB command find, which returns an array of locations at which a certain condition is satisfied. The condition is formed as above using logical expressions and combinations of them.
Example 3.18 Find all integers between 1 and 20 for which their sine is negative. Firstly we set up the array of integers, then calculate their sines and subsequently test whether these values are negative. ii = 1:20; f = sin(ii); il = find(f<0); disp(ii(il))
3.6 MATLAB Specific Commands
93
We briefly dissect this code. – In the first line set up a vector which runs from one to twenty; – the second line calculates the sine of the elements in vector ii and stores the result in the vector f; – in the third line we use find to determine the locations in the vector f where the sine is negative. The command returns a list of positions in the vector f (and equivalently ii) where the condition is true. – The final command prints out a list of these integers. Other similar commands are any and all. Examples of their use are: ' $ x = 0.0:0.1:1.0; v = sin(x); if any(v<0) disp(’Found a negative value’) else disp(’All values zero or positive’) end if all(v>0) disp(’All values positive’) else disp(’One value is zero or negative’) end & % Some care is needed with the logic at this point and these commands seem to be, in some sense, complements of each other. There are many other commands which test the properties of a variable, for instance isempty, isreal etc.
Example 3.19 Now we evaluate the expression f (x) =
1 (x − 1)(x − 2)(x − 3)
on a grid of points n/10 for n = 1 to n = 40 for which the expression is finite, else the function is to be returned as ’NaN’. This is accomplished using the code:
94
3. Loops and Conditional Statements
' $ x = (1:40)/10; g = (x-1).*(x-2).*(x-3); izero = find(g==0); ii = find(g˜=0); f(izero) = NaN; f(ii) = 1./g(ii); & % This allows us to plot the function whilst missing out the infinite parts. This would be accomplished using the command plot(x,f) 15
10
5
0
−5
−10
−15
0
0.5
1
1.5
2
2.5
3
3.5
4
3.7 Error Checking To this point we have assumed the data made available to a code is suitable; this is generally a very dangerous assumption. We have found MATLAB will object to mathematically impossible tasks: however it will happily perform operations provided they are viable (which unfortunately they are more often than not). Now that we have seen conditional statements we can make sure our codes are more robust. The ultimate aim would be to make them totally “idiot proof”, but this is virtually impossible. No matter how many different scenarios a programmer comes up with, they can never predict everything a user will do. MATLAB gives us three very useful commands in this context: break, warning and error. The first of these we have already met. The latter two
3.7 Error Checking
95
allow us to either warn the user of a problem or actually stop the code because of an irretrievable problem, respectively. Both the commands warning and error are used with an argument, which is displayed when the command is encountered. The typical structure might be: # if code_fails error(’ Irretrievable error ’) elseif code_problem warning(’ Results may be suspect ’) end " ! The actual use of the commands is perhaps best demonstrated by a couple of examples:
Example 3.20 Let’s now write a code which asks the user for an integer and returns the prime factors of that integer. ' $ msg = ’Please enter a strictly positive integer: ’; msg0 = ’You entered zero’; msg1 = ’You failed to enter an integer’; msg2 = ’You entered a negative integer’; x = input(msg); if x==0 error(msg0) end if round(x)˜= x error(msg1) end if sign(x)==-1 warning(msg2) x = -x; end disp(factor(x)) & % Fortunately the command input has its own error checking routine and will only let you input numbers (if you try inputting a string it will complain). We now check to see whether zero is entered, in which case the code stops after having informed the user that they entered a zero. Similarly, if the user enters a non integer the code will stop. If the user enters a negative integer the code warns the user they have done so but simply makes it equal to the corresponding positive value.
96
3. Loops and Conditional Statements
The command input allows us to input a matrix, which would cause our program to fail (in fact the routine factor issues an error message). We could incorporate a check to ensure that what is entered is a scalar. This could be accomplished by using the condition that the length of a scalar is unity. To this end we could add (below the input statement): msg3 = ’Code needs a scalar integer’; if length(x) ˜= 1 | x ˜= floor(x) error(msg3) end When MATLAB encounters these commands it produces a message which indicates on which line they occurred and in which code. This is very helpful when debugging codes.
Example 3.21 Now consider a code which compels the user to enter a four character string and until they have the code will not proceed. ' $ msg = [’Please enter a ’ ... ’four character string ’]; msg0 = ’ is not valid, please re-enter’; str = first while if
’X’; % Clearly not valid = 1; length(str) ˜= 4 ˜(first) warning([str msg0])
end first = 0; str = input(msg,’s’); end &
%
In order to avoid the warning message during the first run, we have used the flag first which basically says if this is the first time through don’t issue the warning. This uses a while loop to repeat until the user enters a string of length 4. As we can see this additional code can make the program cumbersome, but sometimes it is necessary, especially if other users are going to read and use your codes. Again, it also helps when it comes to debugging.
3.8 Tasks
97
Another very useful command in this context is exist. This can be used to check whether the requisite variables exist. This is particularly useful if input is required from another code.
Example 3.22 Let us consider this header for a code: # msg = [’The variable z does not exist ’ ... ’and will be required for this code’]; if ˜(exist(’z’)) error(msg) end " ! We note this code will not work at the prompt, since the command error will only run during the execution of an m-file.
3.8 Tasks Task 3.1 Modify the code on page 71 to calculate the value of the summation 100 1 . i2 i=1
(Notice the answer will probably not be an integer, so you will have to modify the display line to use num2str).
Task 3.2 Modify the code from Task 3.1 to only sum the values corresponding to odd values of i. (Hint: This only involves a very minor change to the for loop. You should check the answer you get is smaller than the one from the previous task.)
Task 3.3 Modify the function f.m (on page 72) to calculate the values of: IN = for N up to N=20.
N sin iπ 2 , 2+1 i i=1
98
3. Loops and Conditional Statements
Task 3.4 Construct a program to display the values of the function f (x) = x2 + 1 for x = 0 to x = π in steps of π/4. The key here is to set up an array of points from a to b in steps of h (you can either use the colon command or linspace). Make sure you remember to use the dot operator.
Task 3.5 Change the code given in Example 3.6, used to evaluate sin x, to one that calculates cos x whose series expansion is given by cos x = lim
N →∞
N
(−1)n
n=0
x2n . (2n)!
Compare the approximations to the values calculated directly from MATLAB for x = 0, 1/4, 1/2 and 3/4. As for Example 3.6 you will need to truncate the summation, choosing N to be suitably large.
Task 3.6 Calculate the sum of the series SN , where SN =
N 1 2 n n=1
for different values of N . Given that as N → ∞, SN → π 2 /c where c is a constant. Determine the value of c. (Here you should modify one of the codes for summation: the best one is probably the solution to Task 3.1.)
Task 3.7 Calculate the summations p+1
jp
j=1
for p equal to one, two, three and four (using a nested loop structure).
Task 3.8 Show that, to within the accuracy permitted by MATLAB, N N (−1)n 1 = − ln 2 and lim = 2. N →∞ N →∞ n n(n + 1) n=1 n=1
lim
Task 3.9 Write down (on paper) a logic expression which is true for values of x such that 2 < x < 4. Make sure your expression works for x = 1, 3 and 5. Repeat the exercise for the union of the sets x > 3 and x < −1. (You need to write the answers in the form of the combination of x is greater than something and/or x is less than something else).
3.8 Tasks
99
Task 3.10 Write down a logical expression which is true for even values of n. Extend this to only be true for even values of n greater than 20. (Hint: Try using the MATLAB command mod: for information on the command type help mod.)
Task 3.11 Try to work out what value of x the following code returns (initially without running it). ' $ x = 1; if tan(73*pi*x/4) >= 0 x = 2; else x = pi; end if floor(x) == x x = 10; else x = 7; end if isprime(x) x = ’True’; else x = ’False’; end & % Is this result true whichever value of x we start with? (You can find out about the command isprime by typing help isprime.) Task 3.12 (*) Write a loop structure which iterates xn+1 = 5xn |1 for xn = 1/7 until it returns to the same value (use while). Task 3.13 (*) Determine all integers between 1 and 50 for which n3 − n2 + 40 is greater than 1000 and n is not divisible by 3. Are any integers between 1 and 50 perfect (that is, are they equal to the sum of their factors)?
Task 3.14 Write a code which only allows the user to input an integer n between 1 and 10 (inclusive) and then prints out a string of the first n letters of the alphabet. (Hint: You could start with a string of the form “abcdefghij”.)
100
3. Loops and Conditional Statements
Task 3.15 (*) Write a code which allows the user to input a two character string, the first being a letter and the second being a digit. (Note that to check if a character is a letter we can use inequalities on strings.)
Task 3.16 (*) By modifying the plot the function ⎧ ⎪ ⎪ ⎨ f (x) = ⎪ ⎪ ⎩
code on page 88 use the find command to 0 x2 1 0
x < −1 −1 x 1 1<x<4 x4
for the range x ∈ [−3, 5] using one hundred points (try using the command linspace to set up the array of points).
Task 3.17 (*) Using the command find, and modifying the code on page 93, plot the function 1 f (x) = cos πx for x ∈ [−3, 3]. You will need to change the code to determine when the denominator becomes small, rather than when it is identically zero.
Task 3.18 (D) The following code is supposed to evaluate the function ⎧ 0 x<0 ⎪ ⎪ ⎨ x 0x1 f (x) = ⎪ 2 − x 1x2 ⎪ ⎩ 0 x>2 ' $ x=lnspace(-4,4); N = length x for j = 1;N if x(j)>=0 and x(i)<=1 f(j) = x(j); elseif x(j)>1 or x(i)<2 f(j) = 2 - x else f(j) = zero; end &
%
3.8 Tasks
101
Correct the code so that it accomplishes this. This can be checked by using the command plot(x,f) and comparing the figure to what you expect the function to look like.
4
Root Finding
4.1 Introduction In many problems we are required to determine when a function is zero. It should have become clear even for relatively simple examples there were many subcases. It is our intention to discuss methods which are in some sense robust and so the form of the actual function we are studying is not important, at least in the construction of the method. We now re-introduce the MATLAB function feval which may seem a little like an extra step, but it will enable us to write more general codes. This function has the syntax feval(f,x1,...,xn) and as you might expect from the name evaluates the function f using the arguments x1,...,xn. It is normally used within other functions which require a function name to be passed to them. This function can be used as feval(’sin’,0.3) feval(’mycode’,0.2,0.3) In the first example this gives sin(0.3) and in the second it returns the value of mycode(0.2,0.3).
104
4. Root Finding
4.2 Initial Estimates In order to determine a root it is usually essential to have an initial estimate of its value. In some cases you may have more than one root (or none) and you wish to identify which one you are concerned with. The method we will describe now involves user interaction and is used as an illustration. As we are developing the ideas in this chapter we could consider how they could be generalised to include root selection. In general the methods we will consider will require either an initial guess for the root or a bracketing interval containing a root. We will use the graphical capabilities of MATLAB to identify the root (or this bracketing interval). Firstly, we shall set up a small m-file called userfn.m, which will used to specify an example function. function [value] = userfn(x,par1,par2) value = x-par1*sin(x.ˆpar2); This gives f (x) = x − α1 sin xα2 , where α1 and α2 are parameters, which the user will specify. Now in order to plot the function we select a range and use the plot command. The commands are x = -2.0:0.01:2.0; y = feval(’userfn’,x,2,2); plot(x,y) grid on This code sets up a vector x running from −2 to 2 in steps of 0.01. The next line calculates the value of the function x − 2 sin x2 at these points and puts the answer in y. Note we could also have used the command y = userfn(x,2,2); for this purpose. We have used the feval format so that we could potentially vary the function name. The next two lines plot the graph and add the grid lines.
4.2 Initial Estimates
105
4
3
2
1
0
−1
−2
−3
−4 −2
−1.5
−1
−0.5
0
0.5
1
1.5
2
From this initial figure it is not that clear where the zeros lie. There appears to be one at the origin, which we can see straight away from consideration of the function, f (x) = x − 2 sin x2 . By adding the command grid on (either to the programme testplot.m or at the command line) we can see two additional zeros (one near 0.5 and another near 1.5: there is also a hint of an extra one to the left of the figure, which could be determined by extending the range leftwards). In order to investigate further we use the zoom on command. By clicking the left-hand mouse button we can enlarge areas of the figure, and using the right-hand button we can pull back. Typing zoom off disables this feature. This can give us a good idea of where the roots lie. Notice this command is only working using the original data and if we zoom too close we will be able to see the straight line segments used for the plotting. Here we have exploited 401 points, so this should not be a problem. We can now use another command ginput to actually return a value rather than just using our eyes. The syntax we will exploit is
106
4. Root Finding
' $ % Modified testplotm.m x = -2.0:0.01:2.0; y = feval(’userfn’,x,2,2); disp(’Click the mouse near the zero’) disp(’and when you have finished press’) disp(’the return key’) plot(x,y) grid on [xvalues,yvalues] = ginput [yy,ii] = min(abs(yvalues)); disp(xvalues(ii)) & % The first few lines are the same as testplot.m and the next line uses the command ginput. The way ginput works is to allow the user to select points in the window (using a cross hair) by clicking one of the mouse buttons. This is terminated by pressing the return button. The results are stored in the arrays xvalues and yvalues; these essentially contain the x and y coordinates of all the points which the user clicks. The next command finds the minimum value of the function and its integer location within the array. Finally the value of x at this location is displayed. This gave a guess of 0.4977 for the zero near 0.5 and 1.4931 for the zero near 1.5. Using these initial guesses we can now proceed with our description of some of the techniques available to use. We shall also comment on the likely failings of the methods and we should be mindful of how these failings could manifest themselves and how we might monitor them.
Example 4.1 Determine initial estimates for the zeros of the function f (x) = √ x sin x − x between 0 and 10. Firstly we construct the MATLAB code: function [value] = userf1(x) value = x.*sin(x)-sqrt(x); and now run the commands x = linspace(0,10); y = feval(’userf1’,x); plot(x,y) grid on which yield
4.2 Initial Estimates
107
6
4
2
0
−2
−4
−6
−8
−10
0
1
2
3
4
5
6
7
8
9
10
We can see that there are zeros at 0 and near 1.2, 2.5, 6.7 and 9.3. We could use the above data set but it would seem sensible to consider each point separately. For this purpose we use the code: ' $ a = input(’Start of interval ’); b = input(’End of interval ’); x = linspace(a,b); y = feval(’userf1’,x); clf plot(x,y) grid on zoom on & % Running this code with the inputs 1 and 2, we obtain: 0.5
0.4
0.3
0.2
0.1
0
−0.1
−0.2
1
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
2
108
4. Root Finding
0.15
0.1
0.05
0
−0.05
−0.1
−0.15
1
1.05
1.1
1.15
1.2
1.25
1.3
1.35
1.4
1.45
1.5
0.08
0.06
0.04
0.02
0
−0.02
−0.04
−0.06
−0.08 1.1
1.15
1.2
1.25
1.3
0.04
0.03
0.02
0.01
0
−0.01
−0.02
−0.03
−0.04 1.12
1.14
1.16
1.18
1.2
1.22
0.02
0.015
0.01
0.005
0
−0.005
−0.01
−0.015
−0.02 1.15
1.16
1.17
1.18
1.19
1.2
4.3 Fixed Point Iteration
109
0.01 0.008 0.006 0.004 0.002 0 −0.002 −0.004 −0.006 −0.008 −0.01 1.16
1.165
1.17
1.175
1.18
1.185
1.19
after successive clicks of the left mouse button. This allows us to obtain a better estimate of the root, namely 1.175. You should try this interval and repeat the exercise for the other roots. In reality you should plot the function and then use a combination of the grid and zoom commands to obtain estimates for the root or intervals which contain them. This also helps to ensure that the answers you obtain are sensible.
4.3 Fixed Point Iteration Most of the techniques we will discuss are iterative in nature and the first one is called the fixed point iteration scheme. Instead of looking for a zero of the function f (x), it determines a fixed point of an equivalent equation. The equation is rewritten in the form x = g(x), so when x is substituted in the function g(x) it returns the value x, hence the nomenclature fixed point. The conversion of the equation f (x) = 0 into one of the form x = g(x) is not always straightforward and definitely can be done in many ways. For instance the previous example, for which f (x) = x −2 sin x2 could be rewritten as x = 2 sin x2 (where g(x) = 2 sin x2 ) or x = sin−1 x2 . Although the former version might be more intuitive, there are many examples in which this choice is not so. For instance consider the quadratic f (x) = x2 + 2x − 3, which could √ be manipulated to give x = (3 − x2 )/2 or x = 3 − 2x. With these two forms neither of them seems to have any advantages over the other. Further the equation could be written as x = 3/(x + 2) and so on. Before we try to resolve this issue let us say how this is then implemented as a numerical scheme. We rewrite the equation as xn+1 = g(xn )
n = 0, 1, · · · ,
110
4. Root Finding
which is a recursion formula. It starts with an initial guess, namely x0 (which may be determined graphically or by another means). Just about the simplest code for this purpose would be x0 = 1; for j=1:10 x0 = g(x0); end where we have a routine g.m which defines the function g(x) and x0 = 1 is a suitable initial guess. This runs through the iterative process ten times. This kind of code presupposes that it is going to work and will converge in ten steps (or an appropriate number). You will quickly learn that you can’t rely on this kind of thing. We need to pause here to think what we mean by convergence. We could work out the value of the function f (x) at the current iterate as a check. We would require this to be less than a certain tolerance (the accuracy to which we would expect to know the answer). Notice that this is slightly different to knowing the root to within a certain tolerance. Alternatively in this case the code may be deemed to be successful when the difference between xn+1 and xn is less than a certain tolerance. In this case we have xn+1 ≈ xn ⇒ xn ≈ g(xn ) ⇒ f (xn ) ≈ 0. This tolerance reflects how well we want to know the answer and the parameter maxits is how many times we are prepared to perform the iterations. This is to eliminate problems with cases which don’t converge and hence cause infinite loops. The code we shall use for this is:
4.3 Fixed Point Iteration
' % % fixed.m % function [answer,iflag] = fixed(g,xinit) global tolerance maxits iflag = 0; iterations = 0 ; xnext = feval(g,xinit); while (iterations<maxits) & abs(xnext-xinit)>tolerance iterations = iterations + 1; xinit = xnext; xnext = feval(g, xinit); end if iterations == maxits iflag = -1; answer = NaN; else iflag = iterations; answer = xnext; end & # % % eqn.m % function [g] = eqn(x) g = 2*sin(x.ˆ2); " and the main function
111
$
%
!
112
4. Root Finding
' % % mfixed.m % global tolerance maxits tolerance = 1e-4; maxits = 30; [root,iflag] = fixed(’eqn’,0.2); switch iflag case -1 disp(’Root finding failed’) otherwise disp([’ Root = ’ num2str(root) ... ’ found in ’ num2str(iflag) ’ iterations’]) end &
$
%
We have exploited the new command global which allows variables to be used by any routine which contains a global statement referring to the same variables, or a subset of them. This is useful when a quantity (or group of quantities) is unlikely to change and it saves on long argument lists. We have also used the number 1e-4 which is 1 × 10−4 (refer to page 7). The code above is run and gives the result of ≈ 1 × 10−14 after only four iterations. In order to identify the other roots (near 1/2 and 3/2) we must use guesses close to these values. Starting around 0.5 (for instance guesses of 0.4 and 0.6 lead to the code finding the root at zero again). Starting close to the other root has a variety of outcomes: starting below it produces the zero root, whereas above leads to the iterations diverging. The reason for this is linked to the derivative of g(x). In fact the errors are multiplied by |g (x)| at each iteration and if this value is greater than one, the method will fail. In this case we recall that g(x) = 2 sin x2 so that g (x) = 4x cos x2 which when x = 12 equals 1.9378 and when x = 32 gives −3.7690. Near the origin the derivative is very small and consequently the technique works well. It appears this method is only able to find one root and is thus not very useful. However, at this stage we could change the code eqn.m to # % % eqn.m % function [g] = eqn(x) g = sqrt(abs(asin(x/2))); " !
4.4 Bisection
113
This form of the code is a simple alternative way of writing the equation f (x) = 0 as given above. We use the function abs to ensure that the square root function will not lead to imaginary quantities1 . In this case the code finds the root near x = 1/2 but again fails to obtain the other one. There may well be a form of the function which gets this root but any method which requires this amount of manipulation and user interaction is not suitable for detailed calculations. There are many flaws with this method and consequently it is not widely used for one-dimensional problems. However, there are some higherdimensional (and more complex) problems for which it is the only feasible option. We shall discuss whereby this method is improved upon and instead of using substitution into a function it uses the fact that a zero corresponds to a change in sign.
4.4 Bisection In the previous example we used an initial estimate for a root: here we shall use a bracketing interval. Our initial assumption is that this interval contains a single root. In order to check this hypothesis we shall build in checks at each stage. If the initial interval is between x = a and x = b we know that f (a) and f (b) are of different signs (for the interval to contain a single root): in which case their product must be negative. As the name of the method suggests we bisect the interval and define the point c = (b + a)/2. We can now evaluate the function to obtain f (c). 1
To evaluate the arcsine we have used the MATLAB command asin, as you might expect there are also acos and atan, as mentioned previously.
114
4. Root Finding
a c=
a+b 2
b
This must either be positive or negative (or if we are very lucky zero). In which case f (c) will have the same sign as either f (a) or f (b). The new interval can then be defined as c and whichever end of the previous interval represents a change in sign of the function. A simple version of a code to use this method in an interval [a, b] would be ' $ a = 1; b = 5; for j = 1:10 c = (a+b)/2; if f(c)*f(a) > 0 a = c; else b = c; end end & % where in this case a = 1, b = 5 and the function f (x) is defined in a routine f.m. This method is perfectly adequate if you know that the method will converge in ten steps, the interval [a, b] actually contains a root and no future iterations actually coincide with a root (see Task 4.8). If we wish to be slightly more careful we would use the codes
4.4 Bisection
115
' % % bisect.m % function [answer,iflag] = bisect(fun,a,b) global tolerance maxits iflag = 0; iterations = 0 ; f_a = feval(fun,a); f_b = feval(fun,b); while ((f_a*f_b<0) & iterations<maxits) & (b-a)>tolerance iterations = iterations + 1 ; c = (b+a)/2; f_c = feval(fun,c); if f_c*f_a<0 b=c; f_b = f_c; elseif f_b*f_c<0 a=c; f_a = f_c; else iflag = 1; answer = c; end end switch iterations case maxits iflag = -1; answer = NaN; case 0 iflag = -2; answer = NaN; otherwise iflag = iterations; answer = c; end & # % % func.m % function [f] = func(x) f = x-2*sin(x.ˆ2); " and the main controlling function
$
%
!
116
4. Root Finding
' % % mbisect.m % global tolerance maxits tolerance = 1e-4; maxits = 30; xlower = 0.4; xupper = 0.6;
$
[root,iflag] = bisect(’func’,xlower,xupper); switch iflag case -1 disp(’Root finding failed’) case -2 disp(’Initial range does not only contain one root’) otherwise disp([’ Root = ’ num2str(root) ... ’ found in ’ num2str(iflag) ’ iterations’]) end & % This method is guaranteed to work provided only one root is in the relevant interval and the function is continuous. It may work if there are three roots but this is not recommended: in fact it appears to work provided there are an odd number of roots, because each iteration may remove a number of roots which is guaranteed to be even. We note that the length of the interval after n iterations is (b − a)/2n . Hence if we wish to know the root to within a given tolerance we can work out how many iterations we need to perform. For instance if the required tolerance is , we find that we need 1 b−a n> . ln ln 2 Example 4.2 To determine a root of a continuous function f (x) between zero and one, given that f (0)f (1) < 0 to within 1×10−4 requires n > ln(104 )/ ln 2 ≈ 13.28: in other words fourteen iterations. We shall now discuss other methods for solving equations of the form f (x) = 0 which exploit the form of the derivative (or at least an approximation to it) as well as the function.
4.5 Newton–Raphson and Secant Methods
117
4.5 Newton–Raphson and Secant Methods These methods are related and often confused. We shall derive them in tandem, since in reality they only differ in the last stage. The central premise for both methods is that the function is locally linear and the next iteration for the required value can be attained via linear extrapolation (or interpolation).
4.5.1 Derivation of the Newton–Raphson Method We will start using a Taylor series to derive the Newton–Raphson technique2 . We assume the current guess is x and this is incorrect by an amount h, so that x + h is the required value. It now remains for us to determine h or at least find an approximation to it. The Taylor expansion for the function f (x) at the point x + h is given by f (x + h) = f (x) + hf (x) + O(h2 ). This can be interpreted as: the value of the function at x + h is equal to the value of the function at x plus the gradient times the distance between the points. This can be considered to include further terms; at the moment we are fitting a straight line. In this expression we have used the term O(h2 ): loosely this means something the same size as h2 and also the prime means differentiated with respect to the argument of the function. We now note that x + h is supposedly the actual root so f (x + h) = 0, and discarding the higher-order terms we find that h≈−
f (x) . f (x)
(4.1)
This presumes we are close to the actual root, and consequently we can discard the terms proportional to h2 since these should be smaller than those proportional to h. This allows us to construct the iterative scheme xn+1 = xn −
f (xn ) , f (xn )
n = 0, 1, 2, · · · .
This method can also be derived using geometric arguments. In these derivations the function is taken to be approximated by a straight line in order to determine the next point. 2
If you haven’t seen Taylor series refer to the geometric argument on the next page.
118
4. Root Finding
f(xn )
xn+1
h
xn
The value of h is determined by using the fact that the ratio of the two sides h and f (xn ) has to be equal to f (xn ). At the moment we shall presume that we have two routines func.m and func prime.m which give us the function and its derivative. For ease let us consider the function f (x) = x − 2 sin x2 , so f (x) = 1 − 4x cos x2 (using the chain rule). The code func.m is given on page 115 and the other one is: # % % func_prime.m % function [value] = func_prime(x) value = 1 - 4*x.*cos(x.ˆ2); " ! Notice that we have used the dot operators, even though this routine is only ever likely to be called in this context using a scalar. This permits the routine to be used from other codes in a portable fashion. This can be coded simply using x = 1; for j = 1:10 x = x - func(x)/func_prime(x); end where we have set the initial guess to be x = 1 and supposed that the method will converge in ten iterations. We now give a more robust code to perform the
4.5 Newton–Raphson and Secant Methods
119
iterations ' $ % % Newton_Raphson.m % x = input(’Starting guess :’); tolerance = 1e-8; iterations = 0; while (iterations<30) & (abs(func(x))>tolerance) x = x-func(x)/func_prime(x); iterations = iterations + 1; end if iterations==30 disp(’No root found’) else disp([’ Root = ’ num2str(x,10) ’ found in ’ ... int2str(iterations) ’ iterations.’]) end & % Hopefully you can see the difference between the two codes and see that ultimately the second version is more useful. By entering the values 0.1, 0.6 and 1.5 we can obtain the three roots we are concerned with. Notice we have increased the number of digits printed in the answer to 10 using the form of the MATLAB command num2str which accepts two arguments. We shall discuss the possibilities open to us when we do not know the derivative of the function, but we are able to evaluate the function. This relies on the classical definition of the derivative, which we shall write as f (x) = lim
δ→0
f (x + δ) − f (x) . δ
This allows the previous routine to be rewritten without using func prime.m, but we need to define a practical value of δ for this purpose. In general a value of around 10−6 is suitable, but this may need to be changed depending on the problem. There is also a version of the method whereby δ is changed during the iteration process (dependent on the current value of h, see Equation (4.1)). The previous code is now changed to be
120
4. Root Finding
' $ % % Newton_Raphson_S.m % x = input(’Starting guess :’); tolerance = 1e-8; iterations = 0; delta = 1e-6; while (iterations<30) & (abs(func(x))>tolerance) f0 = func(x); f1 = func(x+delta); x = x-f0*delta/(f1-f0); iterations = iterations + 1; end if iterations==30 disp(’No root found’) else disp([’ Root = ’ num2str(x,10) ’ found in ’ ... num2str(iterations) ’ iterations.’]) end & % or alternatively the short version would be # del = 1e-6; x = 1; for j = 1:10 x = x-del*func(x)/(func(x+del)-func(x)); end " ! We have changed the name of this method to Newton Raphson S.m since it is similar to the next method we will discuss, namely the secant technique. This method starts with two values of x, namely x = x0 and x = x1 . A straight line is drawn between the points (x0 , f (x0 )) and (x1 , f (x1 )), which has the equation y − f (x0 ) x − x0 = . f (x1 ) − f (x0 ) x1 − x0 We wish to find the value of x (x2 say) for which y = 0 which is given by x2 = x0 − f (x0 )
x1 − x0 . f (x1 ) − f (x0 )
We then move on so that we are going to use x = x1 and x = x2 as the next two points. This is coded to give:
4.5 Newton–Raphson and Secant Methods
121
' $ % % Secant.m % x0 = input(’Starting guess point 1 :’); x1 = input(’Starting guess point 2 :’); tolerance = 1e-8; iterations = 0; while (iterations<30) & (abs(func(x1))>tolerance) iterations = iterations + 1 ; f0 = func(x0); f1 = func(x1); x2 = x0-f0*(x1-x0)/(f1-f0); x0 = x1; x1 = x2; end if iterations==30 disp(’No root found’) else disp([’ Root = ’ num2str(x1,10) ’ found in ’ ... num2str(iterations) ’ iterations.’]) end & % This method works far better if the two initial points are on opposite sides of the root. In the above method we have merely chosen to proceed to use x1 and the newly attained point x2 : however we could equally have chosen x0 and x2 . In order to determine which we should use we require that the function changes sign between the two ends of the interval. This is done by changing the lines where the next interval is chosen.
122
4. Root Finding
' % % False_Position.m % x0 = input(’Starting guess point 1 :’); x1 = input(’Starting guess point 2 :’); x2 = x0; tol = 1e-8; iters = 0; while ((iters<30) & (abs(func(x2))>tol))|(iters==0) iterations = iterations + 1 ; f0 = func(x0); f1 = func(x1); x2 = x0-f0*(x1-x0)/(f1-f0); if func(x2)*f0 < 0 x1 = x2; else x0 = x2; end end if iters==30 disp(’No root found’) else disp([’ Root = ’ num2str(x2,10) ’ found in ’ ... num2str(iters) ’ iters.’]) end &
$
%
Example 4.3 We consider the function f (x) = xm − a where a > 0. The roots √ of this equation are m a or, written another way, a1/m . For this equation we can write the Newton–Raphson scheme as: xn+1 = xn −
xm n −a , mxm−1 n
which can be simplified to yield: xn+1 = xn
1 1− m
+
a . mxm−1 n
Notice this is exactly the map solved in the example on page 91, with a = 3 and m = 2.
4.6 Repeated Roots of Functions
123
Example 4.4 Using the Newton–Raphson routine determine the zero of the function f (x) = ex − e−2x + 1. This can be done by setting up the functions function [value] = func(x) value = exp(x)-exp(-2*x)+1; function [value] = func_prime(x) value = exp(x)+2*exp(-2*x); This yields the result >> Newton_Raphson Starting guess :-2 Root = -0.2811995743 found in 8 iterations. (with a tolerance of 1×10−10 ). In fact we can solve this equation by introducing the variable X = ex , and noting that X is never zero. We can rewrite f (x) as f (x) =
1 3 X − 1 + X2 . 2 X
This equation can be solved directly and the real root is found to be √ 3 100 + 12 69 1 2 X= + √ − , 3 6 3 100 + 12 69 3 or by using the MATLAB code co=[1 1 0 -1]; roots(co). Then to retrieve the root of the equation we use the fact that x = ln X.
4.6 Repeated Roots of Functions Here we shall briefly discuss an additional technique which can be used to determine repeated roots. We shall presume the function is known analytically. We note the bisection method requires the function to change sign and the Newton–Raphson method requires that the first derivative is non-zero. Both of these limitations pose potential problems. Consider a polynomial p(x) with a repeated root (of order n > 1) at the point x = λ. This means that we can write p(x) as n (x − λ) q(x),
124
4. Root Finding
where q(λ) = 0 (since the root is of order n). Let us now consider the derivative of p(x) at x = λ, so that dp n−1 n dq = n (x − λ) q(x) + (x − λ) dx dx so evaluating at x = λ, we find
dp
= 0. dx x=λ This means the methods which use the derivative are bound to fail. Let us return to the derivation of the techniques using a Taylor series, where we recall that x + h is deigned to be the correct solution, so that 0 = f (x + h) = f (x) + hf (x) +
h2 f (x) + O(h3 ). 2
We now note that near the required repeated root f (x) will be almost zero, so we consider the extra term which is proportional to h2 . To find h we solve the quadratic: −f (x) ± (f (x))2 − 2f (x)f (x) (±) h = . 2f (x) And we can define the next point in the sequence as (±)
xn+1 = xn + h(±) . But we do not know whether to take the positive or negative root. In the follow(±) ing code we calculate the value of the function at each of xn+1 and determine which has the smaller magnitude. ' $ x=1.1; for its=1:20 [f,fp,fpp] = fun2(x); h1 = (-fp+sqrt(fpˆ2-2*f*fpp))/(2*fpp); h2 = (-fp-sqrt(fpˆ2-2*f*fpp))/(2*fpp); [f1,f1p,f1pp] = fun2(x+h1); [f2,f2p,f2pp] = fun2(x+h2); if abs(f1)
4.7 Zeros of Higher-Dimensional Functions(*)
125
which calls function [f,fp,fpp] = fun2(x); f = x.ˆ4+3*x.ˆ3-12*x.ˆ2-20*x+48; fp = 4*x.ˆ3+9*x.ˆ2-24*x-20; fpp = 12*x.ˆ2+18*x-24; We note that the above code is not limited to real numbers. In this example we have considered the case p(x) = x4 + 3x3 − 12x2 − 20x + 48 which has roots at x = −3, x = −4 and x = 2 (twice). There are other methods of getting round these problems, and indeed these can be applied for higher-order zeros.
4.7 Zeros of Higher-Dimensional Functions(*) We note that the Newton–Raphson scheme is readily extended to a technique whereby one can locate the zero of a higher-dimensional function. Let us consider the zero to occur at x = x∗ and the function is f (x). For instance f (x, y) = (sin(x + y), x2 − y 2 ), which has zero at the origin (0, 0). We can derive this scheme using the multi-dimensional Taylor series. We presume that we have a current iterate xg and that x∗ = xg + h. By definition f (x∗ ) = 0, hence 0 = f (xg + h) = f (xg ) + ∇f |xg · h + O(|h|2 ) where we shall explain the notation ∇f · h in due course, but we note that this can be written as a matrix A times the vector h. We can solve the above equation for the h (where we assume that O(|h|2 ) is sufficiently small enough to neglect). This gives h = −A−1 f (xg ). We now discuss the entries of the matrix A. Let us consider f : Rn → Rn , in other words f (x) = (f1 (x1 , · · · , xn ), · · · , fn (x1 , · · · , xn )) . The elements of the matrix A are ai,j =
∂fi . ∂xj
The guess for the value of xg is then updated.
126
4. Root Finding
Example 4.5 Determine the zeros of the function f : R2 → R2 such that f (x) = (f, g) = (x2 − y 2 + 3, (x + 2)2 − y) where we have used (x1 , x2 ) = (x, y). In this case the matrix A is ∂f ∂f 2x −2y ∂x ∂y = . ∂g ∂g 2(x + 2) −1 ∂x ∂y The code for solving this is: ' xg = 1; yg = 1; for its = 1:10 f = [xgˆ2-ygˆ2+3; (xg+2)ˆ2-yg]; A = [2*xg -2*yg; 2*(xg+2) -1]; h = -A\f; xg = xg+h(1); yg = yg+h(2); end &
$
% −15
This gives values (−0.6410, 1.8469) and the value of f of the order of 10 . We can check this by noting that y = (x + 2)2 and then substituting into f (x, y) we have x2 − (x + 2)4 + 3 = x2 − (x4 + 8x3 + 24x2 + 32x + 16) + 3 = −x4 − 8x3 − 23x2 − 32x − 13. The roots of which can be found using the commands a = [-1 -8 -23 -32 -13]; x = roots(a) y = (x+2).ˆ2; which we shall meet in due course. This gives: >> x x = -4.1124 -1.6233 + 1.5154i -1.6233 - 1.5154i -0.6410
4.7 Zeros of Higher-Dimensional Functions(*)
127
>> y y = 4.4623 -2.1546 + 1.1417i -2.1546 - 1.1417i 1.8469 Notice we find another real root and pairs of complex answers. In this example we have just performed 10 iterations: however in reality we would wish to stop once a certain tolerance is achieved. This could be accomplished by adding an if statement: if norm(f) < 1e-12 break end The command norm calculates the magnitude of the vector (see help norm). This code should be added after the line evaluating f. We should also check whether the calculation has actually converged or merely exceeded the maximum number of iterations. This can be done by adding the code ' $ if norm(f) > 1e-12 disp(’Routine did not converge’) else disp(’Answer is’) disp([’ x=’ num2str(xg)]) disp([’ y=’ num2str(yg)]) end & % In general we will not be able to determine the partial derivatives of the functions analytically and we rely on the local approximations to the derivatives such that ∂f ∂f f (x + δ, y) − f (x, y) f (x, y + δ) − f (x, y) and = lim . = lim δ→0 ∂x δ→0 δ ∂y δ We note that this method can be used to find turning points of functions, in higher dimensions. For instance consider f : R2 → R the turning points are such that ∂f /∂x = ∂f /∂y = 0, so we define f as (∂f /∂x, ∂f /∂y) and seek zeros of f .
128
4. Root Finding
4.8 MATLAB Routines for Finding Zeros 4.8.1 Roots of a Polynomial As we have seen MATLAB has a specific command for finding the roots of a polynomial, namely roots. The coefficients of the polynomial are placed in a vector c and the routine returns the corresponding roots. It is very simple to use, but care is need when entering the coefficients. Example 4.6 Find the roots of the quintic equation f (x) = x5 − x4 + x3 + 2x2 − 1. This is accomplished using the code: c = [1 -1 1 2 0 -1]; roots(c)
There are a couple of things to note from this example: – The polynomial’s coefficients are listed starting with the one corresponding to the largest power. – It is crucial that zeros are included in the sequence where necessary (in the above we have included the zero times x term). – As a simple check, a polynomial of order p has p + 1 coefficients, i.e. a quadratic has three coefficients and a polynomial of degree p will have p roots. So as long as the coefficients of the polynomial are real, the roots will be real or occur in complex conjugate pairs.
4.8.2 The Command fzero The MATLAB command fzero is very powerful. It actually chooses which scheme should be used to solve a given problem. Let us try the form of the command fzero(’func’, 0.4, optimset(’disp’,’iter’))
This produces
4.8 MATLAB Routines for Finding Zeros
Func-count 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
x 0.4 0.388686 0.411314 0.384 0.416 0.377373 0.422627 0.368 0.432 0.354745 0.445255 0.336 0.464 0.30949 0.49051 0.272 0.528
f(x) 0.0813636 0.0876803 0.0745675 0.0901556 0.071613 0.0935142 0.067296 0.0979791 0.0609148 0.103721 0.0513434 0.110687 0.0367268 0.118215 0.0139394 0.124167 -0.0223736
129
Procedure initial search search search search search search search search search search search search search search search search
Looking for a zero in the interval [0.272, 0.528] 18 0.488914 0.0153797 interpolation 19 0.504837 0.000616579 interpolation 20 0.505484 -1.5963e-06 interpolation 21 0.505482 1.80934e-09 interpolation 22 0.505482 5.32907e-15 interpolation 23 0.505482 0 interpolation Zero found in the interval: [0.272, 0.528]. ans = 0.50548227233930 The command uses many different forms but here we are looking for a root of the function defined in func.m near the value x = 0.4 and the options are set to display iterations. Example 4.7 Determine the zero of the function f (x) = x − x2 sin x nearest to x = 1. We need to set up the code
130
4. Root Finding
function [val] = myfunc(x) val = x-x.ˆ2.*sin(x); and then use the inline command fzero(’myfunc’,1). This gives
>> fzero(’myfunc’,1) Zero found in the interval: [0.84, 1.16]. ans = 1.1142
4.9 Tasks Task 4.1 Modify the codes userfn.m and testplotm.m to determine the locations of the roots of the function f (x) = x sin x between 0 and 10. Use the ginput command to make sure that you have reasonable estimates of the locations of the zeros. Notice the code userfn.m as it stands takes two input parameters, whereas this function does not need any parameters and as such the function can be changed to only have one input, namely x. You should also make sure you use a dot in the calculation, since the function will be applied to vectors. Task 4.2 Given that ex > 0 ∀x show that cosh x has no zeros and sinh x has only one. Consequently comment on the zeros of the function f (x) = coshm x sinhn x where n, m ∈ N. Task 4.3 Determine the location of the roots of the polynomial f (x) = x2 + bx + 1, b ∈ R, giving details of when you expect there to be no real roots, one roots or two real roots. (Attempt this mathematically but then use MATLAB’s plotting routine to verify your findings.) Task 4.4 Consider the function f (x) = sin x + β cos x β ∈ R and derive an expression for the value of the zeros of f (x) mathematically. Use MATLAB to verify your answer for certain values of β (perhaps using zero and one as a start).
4.9 Tasks
131
Task 4.5 Modify the code eqn.m (page 112) to determine the zeros of the function f (x) = 2 cos x − sin x between −2π and 2π using the fixed point method. (You may need to use a plot of the function to identify initial guesses for the values.)
Task 4.6 Consider, using the fixed point method, the zeros of the function f (x) = x2 + bx + 1 and the two ways of rewriting the function in the required form as g(x) = −(x2 + 1)/b and g(x) = − −(bx + 1). Using the results from Task 4.3 state which method is appropriate (if either) for a given value of b. (Recall we require |g (x)| < 1 for the method to work.) Task 4.7 Use the bisection method to determine the zero of the function f (x) = 2x2 − x3 + sin x between one and three. You will need to enter the codes bisect.m, mbisect.m and func.m. The code bisect.m does not need modification: however you need to change func.m to evaluate the function f (x) at a point x (again remember to use the dots in the correct place). You also need to change mbisect.m to reflect the fact that we are seeking a zero of the function defined in func.m in the range 1 to 3.
Task 4.8 Consider the function f (x) = cos 3x between 0 and π. Comment on the bisection method using the ranges [0, π], [0, 7π/8] and finally [π/8, π]. It is not necessary to write a code to solve this problem; you should sketch the curve and work out what is likely to happen.
Task 4.9 Using the Newton–Raphson method calculate the roots of the functions f (x) = x cos x − sin x and g(x) = (x3 − x) sin x. These should be done as two separate calculations. You will need to write two MATLAB functions for each case to evaluate the function and its derivative. These should be called func.m and func prime.m so that they can be called from Newton Raphson.m (alternatively you could change the line in Newton Raphson.m to reflect that you are using different function names).
Task 4.10 Using the method of False Position find the roots of the function sin(x − x3 ) between x = 0 and x = 6. Task 4.11 Using the knowledge that the polynomial p(x) = x3 − 4x2 + 5x − 2 has a repeated root, determine its location.
132
4. Root Finding
Task 4.12 Using the command roots calculate the solutions of the equations x3 + x2 + x + 1 = 0 and − 2x + x5 + x2 = 4. Here you need to be careful that the coefficients of the polynomials are entered correctly as vectors.
Task 4.13 Using the command fzero investigate the roots of the functions x sin x + cos x, (sin x)3 − sin x and (x2 − 4x + 5)/(x − 1). Task 4.14 (*) The solutions of the differential equation d2 y dy 1 y=0 x2 2 + x + x2 − dx dx 4 are given by J1/2 (x) and Y1/2 (x), which are called Bessel functions. Using the MATLAB command besselj(nu,x) (where nu is equal to 1/2 in this case) and fzero determine the zeros of the function J1/2 (x) in the interval (0, 20]. Task 4.15 (D) The following codes are designed to find a root of the function f (x) = x sin x − x2 cos x − 1 using the Newton–Raphson method f.m function [out] = f(in) f = x*sin x - xˆ2 cos x:
fp.m function [out] = fp(in) fp = (x+1)*cos x - 2*x sin x: ' $ x = 0; for j = 1:1 x = x - fp(x)/f(x); end &
%
5
Interpolation and Extrapolation
5.1 Introduction We shall now consider the problem where we know the values of a function at a certain set of predetermined points, (x1 , f1 ), (x2 , f2 ), · · · through to (xN , fN ). The question to be answered in this chapter is what values does the function take at intermediate values of x (which is called interpolation), or alternatively what values does the function take external to this range (which is called extrapolation). It is worth pausing here to think how we would determine an intermediate data value in practice: 10
9
8
7
y
6
5
4
3
2
1
0
0
1
2
3
4
x
5
6
7
8
134
5. Interpolation and Extrapolation
If we presume we are given the original data set, shown here as circles, we might join them together with straight lines (as shown). In order to work out the value at x = 3.5 say, we would draw a vertical line and see where it crossed the appropriate segment. Then a horizontal line would be drawn and the value read off the y-axis. In the main this is exactly the technique used: however differing degrees of approximations are used to create the lines between the points. We shall start by discussing how we might obtain the original data.
5.2 Saving and Reading Data In this Chapter we will generally need to read data from a file. Within the context of MATLAB there are two routes open to us for this procedure and it will depend on how the data was initially saved. For illustration we shall presume we have a MATLAB session which has created a set of variables: >> whos Name
Size
a a1 b c z
3x4 2x2 6x6 1x5 1x1
Bytes 96 32 288 40 16
Class double double double double double
array array array array array (complex)
Grand total is 58 elements using 472 bytes Here we have used the command whos to list all the current variables, and it gives information concerning: their size (both in terms of dimensions and in memory, given in bytes) and their class. Most of these are classed as “double array” which means they are real matrices. The final variable z is a one-by-one matrix which is complex. The command also gives information concerning the total number of elements (that is the sum of the product of the dimensions of the matrices) and the total memory. If we wished to only list those variables starting with a we could use: >> whos a* Name a a1
Size 3x4 2x2
Bytes 96 32
Class double array double array
5.2 Saving and Reading Data
135
Grand total is 16 elements using 128 bytes or if we just wanted the names of the variables we could use: who Your variables are: a
a1
b
c
z
If we only wanted information about one variable we could just use the construction whos a1, for instance. In order to save the data we use the command save. The help command is very helpful here (help save). However, we shall give a synopsis here of the main points. To save all the variables which are currently in use: % Save all current variables in a file % session_vars.mat save session_vars This creates a file called session vars.mat, where the first part of this filename is user-defined to reflect the contents of the file and the second part .mat defines it as a MATLAB file containing variables. Note this suffix may also be used by another package and as such it will be difficult to use the Open menu. This file now contains the actual variables, which means both their names and values are stored. They can be reloaded using the command % Loads the variables stored in the % file session_vars.mat load session_vars We note the default file name for files of this type end with .mat and as such we are asking MATLAB to load the file session vars.mat. This file is very special since it actually contains information concerning the variables as well. If we wish to save only certain variables we can list them:
136
5. Interpolation and Extrapolation
' % Save the variables a & a1 to the % file session_vars.mat save session_vars a a1
$
% Save all variables starting with b % to session_vars.mat save session_vars b* % Append all variables starting with ca % to the file session_vars.mat save session_vars ca* -append & % This last command is particularly useful since it adds the variables to the file whereas the previous ones erase all the other variables currently stored in the files. If we merely want to save the data from variables (rather than their names) we can again use save but with a different syntax. This time we shall specify the entire filename, which needs to be enclosed within single quotes. save ’session_vals.dat’ a a1 -ascii
This produces an ASCII (American Standard Code for Information Interchange – basically human readable) file containing the values of the variables a and a1. This creates a file whose contents looks like: 1.0000000e+000 1.0000000e+000 1.0000000e+000 1.0000000e+000 1.0000000e+000 1.0000000e+000 1.0000000e+000
1.0000000e+000 1.0000000e+000 1.0000000e+000 1.0000000e+000 1.0000000e+000 1.0000000e+000 1.0000000e+000
1.0000000e+000 1.0000000e+000 1.0000000e+000 1.0000000e+000 1.0000000e+000 1.0000000e+000 1.0000000e+000
1.0000000e+000 1.0000000e+000 1.0000000e+000 1.0000000e+000
where the variables were defined as a = ones(3); a1 = ones(4). The problem with this technique is we cannot read this back into MATLAB directly using load (it complains there are not the same number of pieces of data in each line). It cannot know this is a three-by-three matrix followed by a four-byfour one. There are other options for this command which allow extra precision, for instance -double. The problem here is that we need to have knowledge about the data in the file to understand the form we wish to read it in. For example consider a file containing the data
5.2 Saving and Reading Data
1.0000000e+000 1.0000000e+000
2.0000000e+000 4.0000000e+000
137
3.0000000e+000 9.0000000e+000
4.0000000e+000 1.6000000e+001
(this was created using the code: x = 1:4; y = x.ˆ2; save ’bob1.dat’ x y -ascii). This contains two rows vectors and we can load this using: load ’bob1.dat’
Now using the command whos we can see that we have a two-by-four array called bob1. We can now extract the data using a = bob1(1,:); b = bob1(2,:); clear bob1. These commands give us the first row and the second row in the row vectors a and b; finally we clear the array bob1 since we have extracted the requisite data. Whilst this last stage is not necessary it is good practice to keep track of the variables you have. Notice there is no requirement that the variables are called the same as when they were saved (since usually you won’t know what they were called). This is probably the best way of reading in data from another source, provided the data is rectangular in shape. However, there is a further method which can be used. This involves the commands fopen, fprintf, fscanf and fclose. These commands are very powerful and as you might expect quite complicated to use: ' $ x = 0:.4:2; y = [x; exp(x).*cos(2*x)]; fid = fopen(’data.dat’,’w’); fprintf(fid,’%6.2f %12.8f\n’,y); fclose(fid); & % In the first two lines we set up a vector x running from 0 to 2 in steps of 0.4 and then a matrix y comprising two columns (first x and then the corresponding values of the function ex cos 2x). The next line opens a file data.dat using the command fopen (note the fact that the filename must be enclosed in single quotes). The first argument is the filename and the second one reflects what we are going to do: in this case write to the file. The options for this second argument are:
138
5. Interpolation and Extrapolation
’r’ ’w’ ’a’ ’r+’ ’w+’ ’a+’ ’W’ ’A’
read write (create if necessary) append (create if necessary) read and write (do not create) truncate or create for read and write read and append (create if necessary) write without automatic flushing append without automatic flushing
(this list can be obtained by typing help fopen). The variable fid is an identifier or handle for the file and as such will be used in all commands related to that file. If the command fopen is successful fid will be a scalar integer (it will have value minus one if it is unsuccessful). We can now refer to this file merely using this variable (you can actually use the integer value but this is not advisable). The next line uses the command fprintf which has three arguments: the file identifier (fid), the format and the variable to be written. We need to ensure the format matches the data. The format here prints two numbers per line, the first one ‘%6.2f’ corresponds to a fixed point number with 2 places after the decimal point using six characters in total; the second one ‘%12.8f’ has eight places after the decimal point and uses 12 characters in total. There are several other formats and these are based on those from the C language. The other option of the most use is e, so the line would be changed to: fprintf(fid,’%6.2e %12.8e \n’,y)
which produces floating point versions of the above. The command \n gives a new line after printing the two numbers, whilst we could place a tab between the characters using \t. Finally we use the command fclose(fid) to close the file corresponding to the the file identifier fid. It is very good practice to close the files we are using as soon as we have finished with them. This produces a file called data.dat which contains: 0.00 0.40 0.80 1.20 1.60 2.00
1.00000000 1.03936428 -0.06498473 -2.44823335 -4.94458639 -4.82980938
We could read the data back into MATLAB using the command fscanf: this is similar syntactically to fprintf except we now specify the shape of what is to be read in. The simplest way of reading in the above data would be:
5.3 Which Points to Use?
139
clear all load ’data.dat’ x = data(:,1); f = data(:,2); since it is rectangular. We shall now presume we do not know the functional form of our data. The following sections will use the data contained within data.dat as an example. It is suggested that you type the above code to create the file (or you can directly enter the data).
5.3 Which Points to Use? We pause here to discuss the problem of which points to use for the process, in general we apply the following method. Important Point Pick those closest! This can be done by hand, or can be automated. For this purpose we use the routine findrange.m:
140
5. Interpolation and Extrapolation
' function [ibot,itop] = findrange(x,z,N) if mod(N+1,2)˜=0 disp(’Must use odd N’) break end points = (N+1)/2; % Half number of points in stencil [ii] = find(x>z); if isempty(ii) itop = length(x); else i = ii(1); end
$
itop = i+points-1; ibot = i-points; if itop>length(x) itop = length(x); ibot = length(x)-2*points+1; elseif ibot<1 itop = 2*points; ibot = 1; end & % This takes three arguments: x (the data points); z (the point at which the function is required) and N (the order of the interpolating polynomial; for linear interpolation N would be 1 and 3 for cubic interpolation). First we check that the interpolating polynomial is of odd order. This is accomplished by checking that one plus N is even. The number of points in half the stencil is then calculated as the variable points. We use the command [ii] = find(x>z); to list the points contained within x which are greater than z. If there are no points for which this is true (in which case ii is empty), we can infer that z is greater than all the values of x and we need to extrapolate using the last few points. Else we use the first value for which x is greater than z (stored in the first element of the array ii). We now have a marker i and we work out the top and bottom of the stencil as itop and ibot respectively. We now need to deal with the cases for which the stencil extends beyond the limits of x, that is if itop is greater than length(x) or if ibot is less than 1 (the first element of x). We now use the end 2*points. This routine can now be used in other programs to give the extent of the stencil.
5.4 Newton Forward Differences and Lagrange Polynomials
141
5.4 Newton Forward Differences and Lagrange Polynomials We shall now discuss the operation of fitting an N th order polynomial through N + 1 points and remark again this will yield a unique answer. We consider the set of data points: (x0 , f0 ), (x1 , f1 ), · · · , (xN , fN ). We now introduce the difference operator ∆ such that ∆f0 = f1 − f0 or in general ∆fj = fj+1 − fj . These are called forward differences, since points forward of the current value are used (there are also backward differences and central differences, which we shall meet in our discussion of the solution of differential equations). We consider the composition of the operator whereby ∆2 f0 = ∆(∆f0 ) = ∆(f1 − f0 ) = ∆f1 − ∆f0 = (f2 − f1 ) − (f1 − f0 ) = f2 − 2f1 + f0 . Of course we can now proceed to define ∆n f0 in an iterative manner. We introduce the polynomial f (x) = f0 + (x − x0 )
(x − x0 )(x − x1 ) ∆2 f0 ∆f0 + + ··· h 2! h2
,
which will ultimately terminate after N terms. Alternatively this can be written as: N −1 n−1 ∆n f0 f (x) = f0 + (x − xj ). (5.1) hn n! j=0 n=1 We consider the data values to be equally spaced, so the value of ∆xj is h ∀j. This analysis can be extended to irregularly spaced points, but we shall not attempt that here. We are now able to construct the polynomial (5.1) for a set of points. We start with a simple example.
Example 5.1 Let us consider the points (0, 1), (1, 3) and (2, 4). Here we have three points and as such we would expect to obtain a quadratic. We use a tabular form, which gives: x 0 1 2
f 1 3 4
∆f 2 1
∆2 f −1
142
5. Interpolation and Extrapolation
Thus we have 2 (x − 0)(x − 1) (−1) f (x) = 1 + (x − 0) + , 1 2! 12 x(x − 1) f (x) = 1 + 2x − , 2 where h = 1, f0 = 1, ∆f0 = 2 and ∆2 f0 = −1 (reading from the top row of the table). It is possible to prove that the polynomial (5.1) goes through each of the set of points, but we shall not include that proof here. We remark that various conclusions can be drawn from the data by using the forward differences; for instance whether it was generated using a polynomial (in which case the differences truncate). We now construct a polynomial which goes through a set of points which are not necessarily evenly spaced. Let us consider the polynomial f (z)
=
(z − x2 )(z − x3 )(z − x4 ) (z − x1 )(z − x3 )(z − x4 ) f1 + f2 (x1 − x2 )(x1 − x3 )(x1 − x4 ) (x2 − x1 )(x2 − x3 )(x2 − x4 ) (z − x1 )(z − x2 )(z − x4 ) f3 + (x3 − x1 )(x3 − x2 )(x3 − x4 ) (z − x1 )(z − x2 )(z − x3 ) f4 . + (5.2) (x4 − x1 )(x4 − x2 )(x4 − x3 )
It is worth pausing at this point and checking that this curve goes through each of the points (xj , fj ). For example for j = 3, we set z = x3 and only the third term is non-zero and we have f (x3 ) =
(x3 − x1 )(x3 − x2 )(x3 − x4 ) f3 = 1 × f3 = f3 . (x3 − x1 )(x3 − x2 )(x3 − x4 )
Hence the value of the polynomial at z = x3 is f3 (as we would hope). This is an example of a Lagrange polynomial; which could have equally been written as 4 4 z − xj f (z) = fi . x − xj i=1 j=1 i j=i
This is a convenient way to write out the cubic we require (as it is relatively easily extended to higher-order cases) and in order to evaluate it we can use the MATLAB code:
5.4 Newton Forward Differences and Lagrange Polynomials
' ip = 1:4; f_z = 0.0; for ii = 1:4 jj = find(ip˜=ii); prod = f(ip(ii)); for kk = jj prod = prod *(z-x(ip(kk)))/(x(ip(ii))-x(ip(kk))); end f_z = f_z + prod; end & This code probably needs some explanation.
143
$
%
– Firstly we set up a vector ip=1:4 which runs from one to four, – and then we have a new variable f z which will ultimately contain our estimate of the function at the point z. – We now run through the terms in Equation (5.2). – Inside the loop we construct a vector jj = find(ip∼=ii), which now contains the indices of the locations in vector ip which are not equal to the current value of ii. The initial value of the variable prod is set equal to the function evaluated at the corresponding grid point ip(1) etc. – We then go through the individual terms in the product – and then finally add this onto the value f z until we have gone through the four terms. This code has been written in this way so it could be extended to as many points as we want. For z = 0.6 we find a value of f z=0.6386, which is shown on the figure as an asterisk:
144
5. Interpolation and Extrapolation
2
1
0
−1
−2
−3
−4
−5
0
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
2
As mentioned we can write this expression as a summation of products and this is easily extended to N points as f (z) ≈
N i=1
Consider the code:
fi
N z − xj . x − xj j=1 i j=i
5.4 Newton Forward Differences and Lagrange Polynomials
' function [value] = poly_int(z,N) global x f imax = length(x); if mod(N,2) ˜= 0 disp(’ N should be even ’) break elseif N >= imax; disp(’Too many points used’) break end M = N/2; [ibottom,itop] = findrange(x,z,N); ip = ibottom:itop; il = 1:N; f_z = 0.0; for ii = 1:N jj = find(il˜=ii); prod = f(ip(ii)); for kk = jj prod = prod *(z-x(ip(kk))) ... /(x(ip(ii))-x(ip(kk))); end f_z = f_z + prod; end value = f_z; & And now test the code using 1
145
$
%
1
We have re-introduced the command isempty, which is true if its argument is empty.
146
5. Interpolation and Extrapolation
' global x f load data.dat x = data(:,1); f = data(:,2); N = length(x); xmin = x(1); xmax = x(N); xtest = linspace(xmin,xmax,20); for ii = 1:20 [ftest(ii)] = poly_int(xtest(ii),N); end plot(x,f,’r’,xtest,ftest,’b’) & This gives the plot
$
%
2
1
0
−1
−2
−3
−4
−5
−6
0
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
2
As you can see using six points works quite well at fitting the data. Although as we will see in subsequent examples using high-order polynomials can lead to significant errors.
5.4 Newton Forward Differences and Lagrange Polynomials
147
5.4.1 Linear Interpolation/Extrapolation We consider the simplest case wherein we have two points (x1 , y1 ) and (x2 , y2 ). The straight line through these is given by y=
x − x1 x − x2 y1 + y2 , x1 − x2 x2 − x1
which here we have constructed in a Lagrange polynomial style. We note that the answer is independent of the process here and provided x1 = x2 we will always get a straight line. This can be continued for quadratics and higher order functions. This is a plot of the data we shall use for this discussion: 2
1
0
−1
−2
−3
−4
−5
0
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
2
This was obtained using the commands: ' $ clear all load ’data.dat’ plot(data(:,1),data(:,2),’o’,’MarkerSize’,12) hold on plot(data(:,1),data(:,2)) hold off grid on print -dps2 data.ps & % The first two commands merely load the data as discussed in the previous section (the code to generate this data is given on page 137). The next command plots the data (the first column against the second) using circles, whose size is specified by ’MarkerSize’ (and set equal to 12). We then hold the figure on which stops any future plotting commands overwriting the figure. Instead
148
5. Interpolation and Extrapolation
they augment the current image. The next plotting command adds the straight lines. We then turn the holding off so the figure will be destroyed if we execute another plot command. We also add a grid to the figure. Finally, we print the results to a Postscript file so that it can be included in another document (for instance this text) or sent to a printer. There are many options for this command, for instance we could use print -djpeg90 data.jpg to generate a JPEG file. As mentioned above for convenience we can extract the data from the array data using: x = data(:,1); f = data(:,2); clear data
5.5 Calculating Interpolated and Extrapolated Values We shall now describe how MATLAB can be used to determine the interpolating polynomial for a set of points. We shall presume that we have the requisite number of points to perform this operation, that is two points for a line, three for a quadratic and four for a cubic, etc. We shall make use of the MATLAB command polyfit. The syntax for this command is polyfit(x,y,N), where the points are defined in x and y, and N is the order of the interpolating polynomial. We note that this function actually uses a least squares approach and fits the best polynomial (see page 152). This gives the curve we want provide the number of points represented in x,y is N + 1. Let us consider the interpolation of data points using a straight line.
Example 5.2 We seek to find the value of the function at x = 4.5 where the data points are (1, −3), (3, 4), (5, 5), (7, −8), (9, −3) and (11, 0), using linear interpolation.
5.5 Calculating Interpolated and Extrapolated Values
' x = [1 3 5 7 9 11]; y = [-3 4 5 -8 -3 0];
149
$
xi = 4.5; r = 2:3; % xi lies between the 2nd and 3rd point of x. p = polyfit(x(r),y(r),1); yi = polyval(p,xi) & % This gives p=[0.5000 2.5000] (representing the line y = x/2 + 5/2) and yi=4.75. We note that here we have determined the range r by hand but we could employ the function findrange (see page 140). We have used the command polyval(p,xi) to calculate the value of the interpolating polynomial (represented by its coefficients p) and xi. We can easily extend this method to use higher-order curves.
Example 5.3 Using the data in the previous example now calculate the value of the interpolating polynomial at x = 4.5 using cubic interpolation. ' $ x = [1 3 5 7 9 11]; y = [-3 4 5 -8 -3 0]; xi = 4.5; [ibot,itop] = findrange(x,y,3); r = ibot:itop; p = polyfit(x(r),y(r),3); yi = polyval(p,xi) & This gives p=[-0.1667 0.75 2.667 -6.25] and yi=5.75.
%
We note that this is quite different to the answer given by linear interpolation and one might argue that linear interpolation is better here. This of course depends on the underlying function.
150
5. Interpolation and Extrapolation
5.6 Splines We now mention another form of interpolation: this fits a curve in an interval where the data at the end of the interval coincides with the data points and also matches the available derivatives with the next interval. If we consider the points (xi , fi ) and (xi+1 , fi+1 ) and fit a straight line this will match the function values with the intervals on each side (but not necessarily the derivative). We need to use a higher-order curve. In order to satisfy the requirements we need at least a cubic, and this is often the preferred option. If we consider the points to be (xi , fi ) for i = 1 to N , we have N − 1 intervals. Let us consider the cubic valid over the interval [xi , xi+1 ] to be yi (x) = ai + (x − xi )bi + (x − xi )2 ci + (x − xi )3 di . We note that we have N − 1 cubics each with four unknowns; that is 4N − 4 unknowns in total. We now proceed to give details of the conditions which we can use to specify the values of the coefficients. Firstly we require that the cubic matches the data values at the ends of the interval: yi (xi ) = fi and yi (xi+1 ) = fi+1 for i = 1, · · · , N − 1; this in effect fixes the ai and yields 2(N − 1) equations. Secondly we require the gradient and the curvature to match at the interior points: yi (xi+1 ) = yi+1 (xi+1 ) and yi (xi+1 ) = yi+1 (xi+1 ) for i = 1, · · · , N − 2.
This yields a further 2(N − 2) equations. Unfortunately we only have 4N − 6 equations and as such our system is not totally specified. We elect to consider natural splines, for which the curvature is taken to be zero at the ends of the domain, that is y1 (x1 ) = 0 and yN −1 (xN ) = 0. We can construct a matrix system in order to determine the coefficients. This can be coded: however the algorithm is quite involved and again MATLAB comes to our rescue with the command spline. Example 5.4 Fit a cubic spline to the data x = (1, 2, 3, 5)T , f = (4, 2, 0, 3)T and plot the interpolated function on a grid z = 0, 0.1, 0.2, · · · , 5. # x = [1 2 3 5]; f = [4 2 0 3]; z = 0.:0.1:5; y = spline(x,f,z); plot(z,y,x,f,’MarkerSize’,12) " !
5.6 Splines
151
This yields the results 4.5
4
3.5
3
2.5
2
1.5
1
0.5
0
−0.5
0
0.5
1
1.5
2
2.5
3
3.5
4
4.5
5
By way of illustration we shall now construct the splines through the points (x1 , y1 ), (x2 , y2 ), (x3 , y3 ). These curves are taken to have the equations yj (x) = aj + bj (x − xj ) + cj (x − xj )2 + dj (x − xj )3 , where j = 1, 2 and 3. This gives us 12 undetermined coefficients and we shall now describe the equations which they satisfy. yj (xj ) = fj , j = 1, 2, 3: This represents the condition that the spline goes through the data point at its left-hand end and these give the equations: a1 = f1 ,
(5.3a)
a2 = f2 ,
(5.3b)
a3 = f3 .
(5.3c)
yj (xj+1 ) = fj+1 , j = 1, 2, 3: This gives a similar condition at the right-hand ends: a1 + h1 b1 + h21 c1 + h31 d1 = f2 ,
(5.3d)
h22 c2 h23 c3
= f3 ,
(5.3e)
= f4 .
(5.3f)
a2 + h2 b2 + a3 + h3 b3 +
+ +
h32 d2 h33 d3
Here we have introduced hj = xj+1 − xj for convenience.
152
5. Interpolation and Extrapolation
yj (xj+1 ) = yj+1 (xj+1 ), j = 1, 2: This is the matching of the first derivative at the internal points, which gives
b1 + 2h1 c1 + 3h21 d1 = b2 , b2 + 2h2 c2 +
3h22 d2
(5.3g)
= b3 .
(5.3h)
yj (xj+1 ) = yj+1 (xj+1 ), j = 1, 2: This is a similar condition for the second derivative at the internal points:
2c1 + 6h1 d1 = c2 ,
(5.3i)
2c2 + 6h2 d2 = c3 .
(5.3j)
y1 (x1 ) = 0 and y3 (x4 ) = 0: These are the conditions that the splines at the ends of the domain are linear at the end points, which gives: c1 = 0,
(5.3k)
2c3 + 3h3 d3 = 0.
(5.3l)
The solution of the above equations gives the required coefficients. Notice that these coefficients could also have been retrieved using the spline command and then using the elements of the answer coefs pp = spline(x,f); pp.coefs Note that the coefficients correspond to a cubic without the −xj factors. This is an example of an object rather than a variable, that is pp.
5.7 Curves of Best Fit In all of the examples so far we have forced the curves to go through all the data points. We now relax that requirement. We shall start with a straight line and optimise the coefficients used to define it. The straight line is given by fL (x) which will be of the form ax + b. Let us assume that the error at a 2 certain point xj is given by (fL (xj ) − fj ) , so the total error is Error: e =
N
e2i
=
i=1
N
2
(fL (xi ) − fi )
i=1
=
N i=1
2
(axi + b − fi ) .
(5.4)
5.7 Curves of Best Fit
153
We wish to minimise this expression by choosing a and b accordingly. In order to determine the actual values of a and b we differentiate with respect to each one and set the result equal to zero.
e
1
e
2
e
5
e3
e
4
We need to be very careful at this point, and this is included purely for interest: ∂e = 2xi (axi + b − fi ) = 0 ∂a i=1 N
and
∂e = 2 (axi + b − fi ) = 0. ∂b i=1 N
These equations can be manipulated to give the simultaneous equations a
N
x2i + b
i=1
a
N
xi
=
i=1 N i=1
xi + bN
N
xi fi
i=1
=
N i=1
fi .
154
5. Interpolation and Extrapolation
We could solve these equations by hand but we shall exploit MATLAB for this purpose, so that we solve the matrix form of the equation: ⎛ N ⎞ ⎛ N ⎞ N 2 xi xi ⎟ xi fi ⎟ ⎜ ⎜ i=1 ⎜ i=1 ⎟ a ⎜ i=1 ⎟ = N N ⎝ ⎠ b ⎝ ⎠ xi N fi i=1
i=1
This is coded as: ' load data.dat; x = data(:,1); f=data(:,2); N = length(x); A = ([sum(x.ˆ2) sum(x); sum(x) N]); rhs = ([sum(x.*f); sum(f)]); vect = inv(A)*rhs; a = vect(1); b = vect(2); fss = a*x+b; plot(x,f,’r’,x,fss,’b’) & This yields the plot:
$
%
2
1
0
−1
−2
−3
−4
−5
−6
0
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
2
As you can see the curve is a reasonable approximation to the points but does not pass through many (if any) of the actual grid points. This method can be extended to assume other forms of data. We could have also used the MATLAB command polyfit which automates the previous procedure. This is called using [p,s] = polyfit(x,y,n) and fits a polynomial of degree n for y = y(x). The coefficients for the polynomial are returned in p and the second variable is associated with the structure and is used by other commands to assess the level of the error. We can now use
5.8 Interpolation of Non-Smooth Data
155
the command polyval to determine the value of the fitted polynomial at an intermediate point. This can be called simply as y = polyval(p,x) or in a more sophisticated form as [y,delta] = polyval(p,x,s), where delta is in some sense representative of the error and the input argument s is generated by polyfit. If we know more about a function we can use higher-order approximations, or can use combinations of functions. Example 5.5 Given that a set of data is of the form y = ax + be−x + c state how one would determine the constants a, b and c. As with the linear example we define the sum of the squares of the errors e=
N
axi + be−xi + c − fi
2
i=1
and seek the values of the constants which minimises this expression. Again we construct the partial derivatives: ∂e = 2xi axi + be−xi + c − fi , ∂a i=1 N
∂e −xi = axi + be−xi + c − fi , 2e ∂b i=1 N
∂e 2 axi + be−xi + c − fi . = ∂c i=1 N
These equations can then be combined into a matrix form to give: ⎛ 2 ⎞ ⎞⎛ ⎞ ⎛ x x e−xi x a xf −xii i−2xi −xi i −xi i i ⎝ ⎠⎝ b ⎠ = ⎝ e xi e e e fi ⎠ . −xi xi e 1 c fi
5.8 Interpolation of Non-Smooth Data We will demonstrate in this example how one might encounter problems with seemingly simple data. Let us consider
156
5. Interpolation and Extrapolation
x 0 1 2 3 4 5 6 7
f 1 1 1 1 0 0 0 0
This is a simple step function which has a value of 1 from x = 0 to x = 3 and a value of 0 from x = 4 to x = 7. It is tempting to say 1 x3 f (x) = . 0 x>3 However we are not sure so we shall try to determine the values of the function in a systematic fashion. We shall use the command poly int which was introduced on page 145. This will be supplemented with the code: ' $ global x f str = ’No. of points for interpolation (even): ’; x = 0:1:7; f = zeros(size(x)); ii = find(x<4); f(ii) = 1; z = 0:0.2:7; nz = length(z); N = input(str); for j = 1:nz f_z(j) = poly_int(z(j),N); end figure(1) t = [’Using ’ num2str(N) ’ points’]; plot(x,f,’o’,z,f_z,’r’) title(t,’FontSize’,20) axis([-1 8 min(f_z)-1 max(f_z)+1]) &
%
5.8 Interpolation of Non-Smooth Data
157
Using 2 points
Using 4 points
2
2
1.5
1.5
1
1
0.5
0.5
0
0
−0.5
−0.5
−1 −1
−1 0
1
2
3
4
5
6
7
8
−1
0
1
2
Using 6 points
3
4
5
6
7
8
5
6
7
8
Using 8 points
2
2.5
2 1.5 1.5 1 1
0.5
0.5
0 0 −0.5 −0.5 −1
−1.5
−1 −1
0
1
2
3
4
5
6
7
8
−1
0
1
2
3
4
As you can see as more points are used in the interpolation, the approximation gets steadily worse and the effect extends far from the discontinuity (which is causing the problem): in fact less points seem to produce less error. The question remains as to what is the “real” data (it could actually look like the figure in the bottom right – although this is not likely). Let us consider the problem with x 0 1 2 3 4 5 6 7 In this case we have
f 1 -0.2 0.05 0.01 0.01 0.01 0.005 0.005
158
5. Interpolation and Extrapolation
Using 2 points
Using 4 points
2
2
1.5
1.5
1
1
0.5
0.5
0
0
−0.5
−0.5
−1
−1 −1
0
1
2
3
4
5
6
7
8
−1
0
1
2
Using 6 points 2
2
1.5
1.5
1
1
0.5
0.5
0
0
−0.5
−0.5
4
5
6
7
8
5
6
7
8
−1
−1 −1
3
Using 8 points
0
1
2
3
4
5
6
7
8
−1
0
1
2
3
4
Here we note that the lower-order polynomials produce reasonable approximations; it is only when we try to fit an octic to the data we observe the problems at the right-hand end. We need to be aware the accuracy of our interpolated values is very dependent on the fidelity and resolution of the starting data.
5.8.1 Insufficient Data Points Let us consider the example f (x) approximated for an interval from −1 to 1, using N points and at each stage approximating the curve using all the points.
5.8 Interpolation of Non-Smooth Data
' global x f for n = 2:1:10 x = linspace(-1,1,n); f = sin(2*x*pi); z = linspace(-1,1,100); if mod(n,2)==0 ni = n; else ni = n-1; end for j = 1:100 f_z(j) = poly_int(z(j),ni); end clf plot(x,f,’o’,’MarkerEdgeColor’,’k’,... ’MarkerFaceColor’,[.49 1 .63],... ’MarkerSize’,12) hold on plot(z,f_z,z,sin(2*z*pi),’--’) hold off yrange_max = max(max(f_z),1); yrange_min = min(min(f_z),-1); axis([-1.2 1.2 yrange_min-0.2 yrange_max+0.2]) t = [’Interpolated using ’ num2str(n) ’ data points ’]; title(t) ti = [’int’ num2str(n) ’.ps’]; h = gcf; print(h,’-dps2’,ti) pause end &
159
$
%
This program waits for the user to press a key between each plot. It also uses gcf which returns a handle to the current figure. This allows a different form of the print command to be used which permits the filename to be passed as a string, namely ti which is changed depending on how many points are used. This code gives
160
5. Interpolation and Extrapolation
Interpolated using 2 data points
Interpolated using 3 data points
1
Interpolated using 4 data points
1 1
0.8
0.8
0.6
0.6
0.4
0.4
0.2
0.2
0
0
−0.2
−0.2
−0.4
−0.4
−0.6
−0.6
−0.8
−0.8
0.5
0
−0.5
−1 −1
−1
−1
−0.8
−0.6
−0.4
−0.2
0
0.2
0.4
0.6
0.8
1
−1
−0.8
Interpolated using 5 data points
−0.6
−0.4
−0.2
0
0.2
0.4
0.6
0.8
1
−1
−0.8
Interpolated using 6 data points 2
1 0.8
−0.6
−0.4
−0.2
0
0.2
0.4
0.6
0.8
1
0.8
1
Interpolated using 7 data points 1.5
1.5 1
0.6 1 0.4 0.5 0.5
0.2 0
0
0
−0.2
−0.5 −0.5
−0.4 −1 −0.6 −1 −1.5
−0.8 −1
−1.5
−2 −1
−0.8
−0.6
−0.4
−0.2
0
0.2
0.4
0.6
0.8
1
−1
−0.8
Interpolated using 8 data points
−0.6
−0.4
−0.2
0
0.2
0.4
0.6
0.8
1
−1
Interpolated using 9 data points 1
1
0.5
0.5
0.5
0
0
0
−0.5
−0.5
−0.5
−1
−1
−0.8
−0.6
−0.4
−0.2
0
0.2
0.4
0.6
0.8
1
−0.6
−0.4
−0.2
0
0.2
0.4
0.6
Interpolated using 10 data points
1
−1
−0.8
−1
−1
−0.8
−0.6
−0.4
−0.2
0
0.2
0.4
0.6
0.8
1
−1
−0.8
−0.6
−0.4
−0.2
0
0.2
0.4
0.6
0.8
1
It should be noted that when we have very few grid points (denoted by the large circles) we cannot possibly hope to realise the exact form of the underlying data (shown as the dashed curve). To highlight this we have included the interpolated curve (shown as the solid line) using the highest-order polynomial possible. We note when only two points are used there is no hope of resolving any variation: similarly when three points are used the interpolation routine still thinks the data is equal to zero. Even when four points are used, the interpolation routine gives completely misleading results (these are far closer to being − sin πx rather than sin 2πx). Unfortunately with five points these are coincident with the zeros of the function and again the interpolation routine believes it is looking at a set of zero data. It is only when ten points are used that the interpolation could be considered to be accurate. In fact five points per period are the minimum points required to resolve a sine wave, which in this case corresponds to nine points (due to the overlap). It is also possible to use other functions than polynomials. We could have plotted the previous function using a sine expansion and got very accurate results, with effectively only one term, but that would require a knowledge of the form of the function. If the function was changed to sin(2.3πx) then trying to fit sine waves using n ∈ Z would be prone to severe errors. Some knowledge of where the underlying data was generated from and its likely form can help
5.9 Minimisation of Functions and Parameter Retrieval
161
significantly. We can then consider the idea of parameter retrieval.
5.9 Minimisation of Functions and Parameter Retrieval In the previous example we discussed the method of least squares: this is where the distance from the data to a function of a given form is minimised. We shall now discuss how we could minimise a function of several variables. This is a vast topic and rather than deriving the techniques from first principles we just exploit MATLAB from the outset. We shall use the MATLAB command fmins (which is going to revert to fminsearch in future editions of MATLAB). Consider the simple function of two variables f (x1 , x2 ) = x21 + x22 , which has a global minimum at the origin. The minimum is such that both of the partial derivatives ∂f /∂x1 and ∂f /∂x2 are zero (together with other conditions to ensure that the point is a minimum). In this case the minimum is obvious and can be found using the code: function [f] = func(x) f = x(1)ˆ2+x(2)ˆ2; and the command [x] = fmins(’func’,[1 1]) (where the array [1 1] is the initial guess). This uses the default tolerances and returns a value of x = 1.0e-04 * -0.2102
0.2548
We shall now discuss how we could improve this value. The input options have values: The parameters are: options(1)-Display parameter (Default:0). 1 displays some results. options(2)-Termination tolerance for X.(Default: 1e-4). options(3)-Termination tolerance on F.(Default: 1e-4). options(4)-Termination criterion on constraint violation.(Default: 1e-6) options(5)-Algorithm: Strategy: Not always used. options(6)-Algorithm: Optimizer: Not always used. options(7)-Algorithm: Line Search Algorithm. (Default 0) options(8)-Function value. (Lambda in goal attainment. ) options(9)-Set to 1 if you want to check user-supplied gradients options(10)-Number of Function and Constraint Evaluations. options(11)-Number of Function Gradient Evaluations.
162
5. Interpolation and Extrapolation
options(12)-Number of Constraint Evaluations. options(13)-Number of equality constraints. options(14)-Maximum number of function evaluations. (Default is 100*number of variables) options(15)-Used in goal attainment for special objectives. options(16)-Minimum change in variables for finite difference gradients. options(17)-Maximum change in variables for finite difference gradients. options(18)-Step length. (Default 1 or less).
We shall now use the code options = foptions; options(2) = 1e-8; options(3) = 1e-8; [x] = fmins(’func’,[1 1],options); which unsurprisingly gives a better value of [0.2892e-8,-0.0997e-8]. Here the options(2) and options(3) set the tolerances on the answers and the function respectively.
Example 5.6 Determine the minimum value of the function x1 f (x1 , x2 , x3 ) = sin − cos(x3 ) x22 + 1 in the neighbourhood of the origin to within a tolerance of 10−6 . Firstly we construct the code to evaluate the function: function [f] = func2(x) f = sin(x(1)/(x(2)ˆ2+1))+cos(x(3)); and options = foptions; options(2) = 1e-6; options(3) = 1e-6; [x,opts] = fmins(’func2’,[0 0 0],options) which gives the answer [-5.5897 1.5995 3.1416]. We can substitute this back into the function func2 to check the value associated with the minimum. This gives −2 so that both cos and sin take the value of −1, hence x3 = −π and x1 /(x22 + 1) = −π/2. In the above example we have also returned details of the iteration which are stored in the array opts. We also note that using the option option(1) = 1; generates a vast amount of information concerning the iterative procedure.
5.9 Minimisation of Functions and Parameter Retrieval
163
This is a very powerful and useful function.
5.9.1 Parameter Retrieval In this topic we will exploit the idea of minimising the distance between two functions. We have already met this where we can specify functions as linear combinations and then minimise the errors using the method of least squares. Let us presume we have some data which we know to be of the form sin ax on the range x = 0 to x = π, where a is unknown. Let us simply construct a function which conveys how close another function sin bx is to this. ' $ a = 1.45; % Usually unknown x = 0.0:pi/20:pi; data = sin(a*x); b = 0.0:0.02:3.0; for j = 1:length(b) trial = sin(b(j)*x); f(j) = norm(trial-data); end & % The plot of f against b clearly shows a minimum near b = 1.5, which is unsurprising in this case. 6
5
4
3
2
1
0
0
0.5
1
1.5
2
2.5
3
We now remark that in order to find the values of this minimum we could use search methods. But here we make the observation that one is seeking a minimum of the function, which is associated with a zero of the derivative of the function. We shall use the Newton–Raphson method modified for looking for zeros of f (x), which is xn+1 = xn −
f (xn ) . f (xn )
164
5. Interpolation and Extrapolation
Here we use f (x + h) − f (x − h) f (x + h) − 2f (x) + f (x − h) and f (x) ≈ . 2h h2 ' $ a = 1.45; % Usually unknown x = 0.0:pi/20:pi; data = sin(a*x); b = 1.5; % Initial guess del = 0.1; tol = 1e-6; for its = 1:20 f0 = norm(sin(b*x)-data); fp = norm(sin((b+del)*x)-data); fm = norm(sin((b-del)*x)-data); df = (fp-fm)/(2*del); if abs(df)
5.9.2 Using fmins for Parameter Retrieval We shall now discuss how we might use the aforementioned MATLAB function fmins to retrieve parameters, see page 161. Initially we shall consider the sample example again:
Example 5.7 We shall try to determine the value of the constant a given that the data has been generated using sin(a*x). In general this value will not be known.
5.9 Minimisation of Functions and Parameter Retrieval
165
' global x data a = 1.45; x = 0.0:pi/20:pi; data = sin(a*x); clear a [a] = fmins(’func’,[1]); & used in conjunction with the program function [f] = func(a) global x data trial = sin(a*x); f = norm(trial-data); This gives the value of a very accurately (to within 10
$
%
−14
).
We shall now describe an example with more parameters:
Example 5.8 We start with the data f (x) = 0.2 sin 3.2x + 0.45x and using the fact that the data is generated using a sin bx + c we try to recover the above values. The main code is: global x data x = linspace(0,10); data = 0.2*sin(3.2*x)+0.45*x; [co] = fmins(’func3’,[0.1 3. 0.5]); and the code func3.m is # function [f] = func3(co) global x data trial = co(1)*sin(co(2)*x)+co(3)*x; f = norm(trial-data); "
!
This recovers the starting values, since we have used a good starting guess. We note that using other starting locations will lead to other answers, which correspond to local minima. It is difficult to guarantee that we have obtained a global minimum.
166
5. Interpolation and Extrapolation
5.10 Tasks Task 5.1 Calculate the quadratic which passes through the points (0, 0), (2, −1) and (5, 5) (by hand). Task 5.2 Generate the data x2 + 3x + 2 on the points x = 0, 1, 2, · · · , 10 using the code x = 0:10; y = x.ˆ2+3*x+2; Calculate the error associated with using straight lines in the intervals at x equals 1/2, 3/2 and 5/2. This involves working out which intervals should be used to calculate the approximate values. The error is given by using the fact that the exact form of the data is actually known (i.e. as the above quadratic).
Task 5.3 Calculate the quadratic which passes through the points (0, 0), (π/2, 1) and (π, 0). It would be a good idea to do this by hand and using MATLAB (using polyfit). Task 5.4 Calculate the cubic which passes through the points (−π/2, −1), (0, 0), (π/2, 1) and (π, 0). Task 5.5 Plot the spline which goes through the points (−π, 0), (−π/2, −1), (0, 0), (π/2, 1) and (π, 0) at the points (−π, π) in steps of π/20. You could use the MATLAB command spline for this purpose.
Task 5.6 Given that the data
5.10 Tasks
167
x 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
y 3.16 3.01 2.73 2.47 2.13 1.82 1.52 1.21 0.76 0.43 0.03
was generated using an expression of the form a sin x + b cos x determine the values of a and b.
Task 5.7 (*) Calculate the splines associated with the points (xj , yj ) j = 1, · · · , 5. Plot these splines for the points (−π, 0), (−π/2, −1), (0, 0), (π/2, 1) and (π, 0) on a grid of points in steps of π/10 from −π to π. Given that the initial data is given by y = sin x, determine the sum of the squares of the total errors over these points. Task 5.8 (D) The following code should construct the function f (x) = x3 + sin x − 1 on the grid of integers from 2 to 11, and then works out the value of the function at x = 4.5 and x = 15 using linear interpolation and extrapolation. ' $ x = 1:11+1; f = polyvalue([1 0 0 -1],x) + sin x; % x = 4.5 r = 4:5; c = polyfit(x(r),f(r),1); yy = polyvalue(c,4.5) % x = 15 r = 14:15; c = polyfit(x(r),f(r),1); yy = polyvalue(c,15); &
%
6
Matrices
6.1 Introduction As noted earlier MATLAB derives its name from the term MATrix LABoratory. It is therefore not surprising that it is in the area of matrix operations that the true power of MATLAB is brought to light. We now turn our attention to matrices within MATLAB but we provide a brief mathematical introduction to the subject of matrices in the Appendix (see page 322)1 . We now describe how matrices are constructed and manipulated within MATLAB.
6.1.1 Initialising Matrices Within MATLAB Before we proceed with a description of matrix operations it is important to first discuss how we set up and access matrices within MATLAB. The simplest method involves simply typing the elements: >> A = [2 3 4; 5 4 3] A = 2 1
3
4
Even if you are comfortable with the theory of matrices we still recommend you read this section as it provides the important details of the correct syntax for entering and manipulating matrices within MATLAB.
170
6. Matrices
5
4
3
Here the elements in the first row are separated by a space and the end of the first row is denoted by a semicolon. The second row is then typed, again with a space between successive elements. The whole matrix is contained within square brackets. The variable A is now initialised to be a two-by-three matrix; we can see this by using the command size(A). >> size(A) ans = 2
3
Here the command size returns two values; the number of rows followed by the number of columns. In the main we have just let the answer to our calculations appear on the screen (in fact they are also put into a variable called ans). We could have used the code: >> >> >> >> >>
A = [2 3 4; 5 4 3]; b = size(A); disp(b) [rows,columns] = size(A); disp([rows columns])
The variable b is actually a one-by-two matrix (that is, a row vector containing two elements). The elements of this vector are b(1) and b(2) and these are used to store the number of rows and columns of A, respectively. Thus we can determine the number of rows of matrix A, in this case 2, by simply typing b(1) at the MATLAB prompt. We could also call the function size(A) and assign the values to a vector whose elements are called rows and columns. This is done in the fourth line of code. In this example we again encounter the MATLAB function disp, which literally displays its argument (which in this case is a row vector); we shall again return to the disp command a little later. We now return to the question of initialising matrices (and vectors) using the method of just typing in the elements. We need to take some care with vectors, as MATLAB differentiates between column and row vectors (as should we). To enter a column vector we could use any of: >> column_vector = [4 5 6]; >> column_vector = [4;5;6];
6.1 Introduction
171
>> column_vector = [4 5 6]’; The first command is self-explanatory. In the second we enter the first row, terminated by a semicolon, and then the second row, terminated by a semicolon, etc. The third version first creates the row vector [4 5 6] and then takes its transpose (interchanges rows and columns) to produce the column vector. We can use any of these methods but since our ultimate aim will be to write computer code in MATLAB, rather than entering commands at the prompt, we will generally not use the first method. In general we shall, throughout the text, employ the second form. We now turn our attention to how we access elements (or parts of a matrix). Let us start with the matrix >> A = [11 12 13 14; 21 22 23 24; 31 32 33 34]; so that
⎛
11 A = ⎝ 21 31
12 22 32
13 23 33
⎞ 14 24 ⎠ . 34
There is no significance to these numbers, other than that they provide an indication of their location within the matrix; we have purely used them so we will be able to check that we have got the correct elements. The simplest way of obtaining an element is using parentheses, so that A(2,3) returns the value in the second row, third column (in this case 23). Note also that it is necessary to use round brackets. This is exactly as we would expect, and follows the convention that ai,j refers to the element in the ith row and the j th column. It is also possible to refer to a whole row (or column) of a matrix. For example >> A(2,:) ans = 21
22
23
24
returns the second row of the matrix A. Here the colon indicates all the elements along a particular row. Alternatively to refer to a particular column we could use >> A(:,4) ans = 14 24
172
6. Matrices
34 to return the fourth column of matrix A. Note that in both cases the answers are the same “shape” as they would appear in the matrix, that is the second row has been returned as a row vector and the fourth column has been returned as a column vector. With the colon operator we can create row vectors which can then be used as arguments in other commands. For instance >> r = 1:3; >> A(r,1) ans = 11 21 31 This yields the same result as A(1:3,1) or A(:,1). We could also use r = 1:2 to get the first two elements of the first column, or r = 1:2:3 to get the first and last (noting that r = 1:2:3 gives the row vector r = [1 3]). The possibilities are extensive; for example if we want to obtain the top left hand two-by-two corner of A, we could employ the following: >> r = 1:2; >> B = A(r,r) B = 11 21
12 22
We now return to the problem of initialising matrices. Although it is not necessary in MATLAB, it is good programming practise to set up an empty matrix before accessing the elements. In many programming languages this is crucial and is referred to as dimensionalising variables and the syntax for how this is done varies considerably between languages. There are many special commands in MATLAB which aid in the initialisation of matrices and we start looking at these by using the colon (which refers to the entire row or column, depending on context) in some examples.
6.1 Introduction
173
Example 6.1 Enter the matrix in ⎛ 1 ⎜ 2 ⎜ ⎝ 3 4
MATLAB 2 0 0 0
3 0 0 0
⎞ 4 0 ⎟ ⎟ 0 ⎠ 0
In order to achieve this we use the commands >> >> >> >>
A = zeros(4); r = 1:4; A(:,1) = r’; A(1,:) = r
% First column % First row
A = 1 2 3 4
2 0 0 0
3 0 0 0
4 0 0 0
The first command here initialises the matrix A to be a four-by-four matrix whose elements are all equal to zero. The matrix we want to enter has the first row and column having the same elements 1, 2, 3, 4. We therefore set up a vector, in this case r, to contain these values. We now want to assign the first column of the matrix A which we can do with the third command. Notice here that we are now assigning to the matrix A to have the first column equal to the transpose of the vector r; we have used the transpose because we want a column vector. The final command assigns the first row of A to be equal to the vector r and to print out the resulting matrix A which, as we see, is precisely the matrix we required. We could have entered the matrix in many different ways. One way would be to simply type the matrix in element by element: >> A 2 3 4
= 0 0 0
[1 2 3 4; 0 0; 0 0; 0 0];
This is fine for small matrices but not practical for when we need to set up larger matrices. Another variant which can be used to set up the matrix is >> A = [1 2 3 4; 2 zeros(1,3); 3 zeros(1,3); 4 zeros(1,3)]; Here the command zeros(1,3) sets up a row vector (one-by-three) full of zeros. This example serves to emphasise there is no unique way to go about setting up a particular matrix; some ways are more elegant (and sometimes less readable) than others.
174
6. Matrices
6.1.2 Matrix Operations We shall now consider how matrix operations are performed within MATLAB, referring to the mathematical definitions given in the Appendix. We shall start with addition and subtraction, using simple examples:
Example 6.2 Consider the addition (C = A + B) and subtraction (D = A − B) of the matrices 1 2 4 3 A= and B = . 3 4 2 1 We shall start by working through these by hand and then proceed to give the MATLAB code. Firstly the addition 1 2 4 3 C= + , 3 4 2 1 1+4 2+3 5 5 = = ; 3+2 4+1 5 5 and now the subtraction 1 2 4 3 D= − , 3 4 2 1 1−4 2−3 −3 = = 3−2 4−1 1 The MATLAB code to achieve these operations is >>A = [1 2; 3 4]; B = [4 3; 2 1]; >>C = A+B C = 5 5 >>D = A-B
5 5
D = -3 1
-1 3
−1 3
.
6.1 Introduction
175
We note that matrices need to be the same size to perform addition or subtraction since there needs to be a corresponding element in each matrix. Example 6.3 Consider the expression A − 3BT where ⎛ ⎞ −3 2 3 8 −1 A= and B = ⎝ 2 2 ⎠ . 5 2 0 −1 3 The MATLAB code is: A = [3 8 -1; 5 2 0]; B = [-3 2; 2 2; -1 3]; C = A-3*transpose(B);
Note that although the matrix B is not the same size as A, its transpose BT is. Before we proceed we add this word of caution within the context of MATLAB. As we have already seen MATLAB will adapt its variable structure to accommodate solutions. However, it will object to calculations that are impossible (that is, not well defined). For instance if we try to add a three-by-three matrix to a two-by-two one (both full of 1’s)2 >>A = ones(3); B = ones(2); >>C = A+B ??? Error using ==> + Matrix dimensions must agree. This example demonstrates that MATLAB is not able to add a two-by-two matrix to a three-by-three one and it returns a sensible error message if we try to do so; in this case the dimension (or size) of the matrices are not the same. The only operation of this kind which is possible within MATLAB involves >>A = ones(1); B = ones(2); >>C = A+B 2
We will use the command ones(n) which sets up an n-by-n matrix full of ones. The other form of this command takes two arguments, ones(m,n), which unsurprisingly gives a m-by-n matrix with all elements equal to one. This is similar to the command zeros(n) that we saw earlier. An associated command that generates an n-by-n matrix with entries made up of random numbers between zero and one is rand(n). The precise structure of these commands can be found by using the help command.
176
6. Matrices
C = 2 2
2 2
In this case although the variable A is a one-by-one matrix it is treated as a scalar. In this case the command is interpreted by MATLAB as i = 1, · · · , m
ci,j = λ + bi,j ,
and j = 1, · · · , n; where C = λ1 + B, with 1 a matrix full of ones (which can be obtained in MATLAB using ones ). This operation is mathematically correct and it is also a well-defined operation within MATLAB. Similarly if a matrix is multiplied by a scalar then each element is multiplied by that scalar (that is ci,j = λai,j where C = λA and again the calculation is viable in mathematical terms). Before proceeding to matrix multiplication within MATLAB we note that this idea of applying and performing an operation on every element extends to functions. We can demonstrate this with a simple example: >> A = [pi/4 pi/2; pi pi/3] A = 0.7854 3.1416
1.5708 1.0472
>> B = sin(A) B = 0.7071 0.0000
1.0000 0.8660
Here we have set up the matrix3
A= and it returns the matrix B as sin π4 B= sin π 3
sin π2 sin π3
π 4
π
π 2 π 3
=
√1 2
0
1
√ 3 2
.
Notice that the variable pi is predefined in MATLAB and returns the value of π = 3.1415926535897 · · · .
6.1 Introduction
177
We shall return to this method in due course, but we now turn our attention to matrix multiplication within MATLAB. The operation C = A*B is performed as one might expect and returns the “normal” result of matrix multiplication so that if A is n-by-m and B is m-by-p then C is n-by-p whose elements are defined on page 326. We need to remember that when taking the product of two matrices the number of columns of the left-hand matrix must match the number of rows in the right-hand matrix. If this is not so then MATLAB will give an error message: Inner matrix dimensions must agree. This is somewhere we need to be very careful and although most of the time our errors will be flagged by MATLAB, sometimes the calculations will proceed even though the results are not as we would expect: for instance >> A = [1 2 3]; >> B = [4; 5; 6]; >> A*B ans = 32 >> B*A ans = 4 5 6
8 10 12
12 15 18
In each case MATLAB is prepared to make the calculation (as it should): however the exchange of the two matrices yields very different results. Because MATLAB is willing to proceed with calculations with scalars or matrices as arguments, it may well be some time before this error is realised.
Example 6.4 Calculate ⎛ 1 5 A=⎝ 0 2 −1 0
3A − B and AB where ⎞ ⎛ 6 0 and B=⎝ 1 3 ⎠ 0 1
The code for this should be relatively self explanatory: >> A = [1 5 6; 0 2 3; -1 0 0]; >> B = [0 -3 2; 1 0 -2; 1 0 -4];
⎞ −3 2 0 −2 ⎠ . 0 −4
178
6. Matrices
>> disp(3*A-B) >> disp(A*B) Note that it is not necessary to use the command disp here. Dot arithmetic can be readily extended to work with matrices. With matrices A and B the matrix C = A.*B is given by ci,j = ai,j bi,j ,
i = 1, · · · , m and j = 1, · · · , n
and similarly those of D = A./B by di,j =
ai,j , bi,j
i = 1, · · · , m and j = 1, · · · , n.
In addition to multiplication .* and division ./ we can also use dot arithmetic for exponentiation using .ˆas in >> A = [1 2; 3 4]; >> B = [1 2; 3 4]; >> A.ˆB ans = 1 27
4 256
Of course in using dot arithmetic in MATLAB we must ensure the matrices are of the same size for the operation to be defined. We note either of the arguments can be scalars: >> A = [1 2; 3 4]; >> B = A.ˆ2; % square all entries >> C = 2.ˆA; % [2 4; 8 16] We note these are effectively new binary operations and the addition of the dot should be thought of as changing the variables. It might help to think of them as separate operations: that is C = A*B performs the mathematical multiplication A × B whereas C = A.*B gives ci,j = ai,j bi,j . With practice you will come to appreciate the difference between these two operations. It is not necessary to have a .+ or a .- command since using the definitions above these give the same results, since the elements of C = A + B are exactly ci,j = ai,j + bi,j .
6.1 Introduction
179
Example 6.5 Given the matrices A = I and B =
1 3
2 4
,
compare the results of the MATLAB calculations A*B, A.*B, A/B and A./B. For the multiplications we have the code: >>A = eye(2); B = [1 2; 3 4]; >>C = A*B C = 1 3
2 4
>> C = A.*B C = 1 0
0 4
Here we have introduced the command eye(n) which gives an n-by-n identity matrix4 . For the division operations we have >> C = A/B C = -2.0000 1.5000
1.0000 -0.5000
>> C = A./B C = 1.0000 0 4
0 0.2500
This could also have been obtained using the command diag.
180
6. Matrices
Hopefully this example makes it clear that the straightforward asterisk operation performs the mathematical operation of multiplication, with multiplication by the identity matrix A leaving B unchanged, whereas multiplying using .* performs the operation element-wise, so that 1×1 0×2 1 0 C = A. ∗ B = = . 0×3 1×4 0 4 We have previously skirted the issue of division of matrices, but now that we have introduced the element-wise operation this can be dealt with naturally and it works in the same way as multiplication. Above we have the results of the calculation 1 0 1 2 −2 1 A/B = ‘/’ = 3 0 1 3 4 − 12 2 which is AB−1 and the other calculation is 1 0 1 2 A./B = ‘./’ = 0 1 3 4
1 1 0 3
0 2 1 4
=
1 0
0 1 4
.
We note when using the division operator / without the dot we are, in fact, constructing the inverse of the matrix B. In order to calculate the transpose of a matrix we can use the command transpose or we can use an apostrophe, A’. If the elements of the matrix are complex numbers, then this operation constructs the complex conjugate of the transpose of A. If the elements of the matrix are real this is then equal to the transpose of the matrix. To obtain the transpose without conjugation, in the case of a complex matrix, we use the construction A.’.
6.1.3 Operations on Elements of Matrices In the previous section we have talked about dot arithmetic but we have also met other examples such as where we added a scalar quantity to each element of a matrix and where we took the sine of each element. We are now in a position to apply the functions we have discussed to all of the elements of a matrix (or pairs of elements for binary operations). We can use any unary operation on a matrix to return a matrix of the same size. We shall consider a few examples to illustrate this.
6.1 Introduction
181
Example 6.6 Investigate the behaviour of the unary operations abs, sign, cos , sin, exp and sinh on the matrix ⎛ ⎞ 1 −.5 −3.2 A=⎝ 0 1 −π ⎠ . π −2 7.25 2 This is done with the MATLAB code: >> A = [1 -0.5 -3.2; 0 1 -pi; pi/2 -2 7.25]; >> abs(A) >> sign(A) >> cos(A) >> sin(A) >> exp(A) >> sinh(A) We have not included the answers which MATLAB displays, but you should try entering these commands in order to understand how MATLAB interprets a function of a matrix. We need to take some care when using the dot command as some commands may be allowable within MATLAB but may produce results which are not what we expected, or wanted. The following example provides a good illustration of this point.
Example 6.7 Consider the matrix A=
π 4 π 3
π 2 π 6
.
We wish to determine the matrix whose elements take the values sin x/x where x corresponds to the elements of the matrix A. In other words we want to calculate the matrix 4 π π 2 π sin 4 π sin 2 . 3 π π 6 π sin 3 π sin 6 This can be accomplished using the commands >> A = [pi/4 pi/2; pi/3 pi/6]; >> sin(A)./A ans =
182
6. Matrices
0.9003 0.8270
0.6366 0.9549
However, if we had missed out the dot and simply typed sin(A)/A we would still obtain an “answer”: >> sin(A)/A ans = 0.5487 0.0569
0.2637 0.7843
which is not what we had in mind. What this last calculation has done is to construct the matrix BA−1 where the elements of B are sines of those of A.
6.1.4 More on Special Matrices In the main, to this point in the text, we have constructed matrices by simply typing in their entries. However, there are commands in MATLAB which allow us to make use of special matrices. The simplest ones, and those that are most often used, are eye(n) The identity matrix of size n-by-n, In . This matrix has the property that for any square matrix A of size n-by-n AIn = In A = A. ones(n,m) A matrix filled with ones of size n-by-m. Note that ones(n) gives a square n-by-n matrix filled with ones and that ones(n,1) gives a column vector of ones and ones(1,n) a row vector. zeros(n,m) A matrix filled with zeros of size n-by-m. This command operates in the same manner to ones when used as zeros(n), zeros(n,1) and zeros(1,n). A matrix whose definition is slightly more involved is that given by the command diag(x,n). This produces an appropriately sized matrix whose nth diagonal is set to be the vector x. The commands diag(x,0) and diag(x) produce identical results, that is the vector x on the leading diagonal (that is the one running from the top left to the bottom right; the elements of the form ai,i ). The value of n being positive means that we are considering the nth super-diagonal and similarly negative values of n gives the nth sub-diagonal. It
6.1 Introduction
183
should be noted that the nth diagonal is shorter by |n| than the leading diagonal, for instance if x = ones(3,1) then diag(x) produces a three-by-three matrix whereas diag(x,1) produces a four-by-four matrix as does diag(x,-1). Considering an N -by-N matrix: The nth super-diagonal consists of the elements ai,i+n where i = 1, · · · , N − n and the nth sub-diagonal consists of the elements ai+n,i where i = 1, · · · , N − n. Notice it does not matter whether the vector is a row or column vector.
Example 6.8 If x = ones(4,1) then we have: diag(x,0) is given by
⎛
1 ⎜ 0 ⎜ ⎝ 0 0 diag(x(1:3),1)
⎛
0 ⎜ 0 ⎜ ⎝ 0 0
0 1 0 0
0 0 1 0
⎞ 0 0 ⎟ ⎟ 0 ⎠ 1
1 0 0 0
0 1 0 0
⎞ 0 0 ⎟ ⎟ 1 ⎠ 0
0 0 1 0
0 0 0 1
⎞ 0 0 ⎟ ⎟. 0 ⎠ 0
and similarly diag(x(1:3),-1)
⎛
0 ⎜ 1 ⎜ ⎝ 0 0
We can use this command to produce combinations such as diag(x,0)+diag(x(1:3)*2,1)+diag(x(1:3)*(-2),-1) ⎛ ⎞ 1 2 0 0 ⎜ −2 1 2 0 ⎟ ⎜ ⎟. ⎝ 0 −2 1 2 ⎠ 0
0 −2
1
Notice we have been very careful to only try viable combinations. In the above we have used the fact that we can extract parts of a matrix or vector. The command ones(4,1) sets up a column vector (four-by-one) full of ones and then x(1:3) gives the first three elements of that vector, that is [1 1 1].
184
6. Matrices
Example 6.9 Consider the matrices constructed using the commands: >> x = 2*ones(3,1); >> y = -2*ones(4,1); >> A = diag(y,0)+diag(x,1); >> B = diag(y,1)+diag(x,-2); The first command sets x to be a column vector (three-by-one) full of 2’s and the second one sets y to be a column vector (four-by-one) full of −2’s. It is worth typing these commands (and leaving the semicolon off to see what is happening). It is possible to see the contents of a variable by merely typing its name at the prompt and pressing return. Let’s now dissect the command A = diag(y,0)+diag(x,1);. The first component of the right-hand side puts the contents of the column vector y down the leading diagonal of a matrix (which will be a a four-by-four matrix since the vector y is four-by-one). The second command on the right-hand side constructs a matrix which has the components of the column vector x down the super-diagonal; notice the vector x is three-byone which is one shorter than the leading diagonal. Finally, these two matrices are added together (to give A) which is a valid operation as both matrices are four-by-four. If you are having difficulty following this try typing diag(y,0) and diag(x,1) separately, and look at the resulting matrices. In the second command the matrix B is constructed with a super-diagonal and a second sub-diagonal. These commands give >> A A = -2 0 0 0
2 -2 0 0
0 2 -2 0
0 0 2 -2
-2 0 0 2 0
0 -2 0 0 2
0 0 -2 0 0
>> B B = 0 0 2 0 0
0 0 0 -2 0
6.1 Introduction
185
Notice the sizes of the matrices have been determined by the length of the diagonals. If we had attempted to use the command diag(y,0)+diag(x,0) we would have been asking MATLAB to add two matrices of different sizes, and as such it would have produced an error message. There are several other special matrices which can be easily constructed using MATLAB. The command magic(n) gives a magic square of size n-by-n. This matrix has the property that the sum of all the elements along any row or column is identical (and along diagonals). The commands hilb(n) and invhilb(n) produce what are known as a Hilbert matrix and its inverse. The elements of the Hilbert matrix A are given by ai,j = 1/(i + j); the inverse of these matrices are notoriously hard to calculate. Other examples of special matrices exist within MATLAB; a full list of matrix functions can be found by using lookfor matrix. This lists all the functions which include the word matrix in their description.
6.1.5 Matrices Containing Strings We briefly note we can form vectors containing strings. This is useful when we wish to construct arguments to produce prompts for the user. Let us consider a simple example
Example 6.10 This code gets the user to input a value of a and simply print it out again. # str = ’Please enter the value of a: ’; a = input(str); sol = ’The value of a is equal to ’; soln = [sol num2str(a)]; disp(soln) " ! Here we have formed a row vector using the two strings ’The value of a is equal to ’ and num2str(a); the latter of which is the conversion of the value of a to a string. We note the size of the row vector sol is one-by-twenty seven and as such we could access parts of the vector sol(1,1:3) is the word The. There are numerous commands which can be used to operate on strings:
186
6. Matrices
STR2MAT Form blank padded character matrix from strings. STRCAT Concatenate strings. STRCMP Compare strings. STRCMPI Compare strings ignoring case. STRINGS Character strings in MATLAB. STRNCMP Compare first N characters of strings. STRNCMPI Compare first N characters of strings ignoring case. STRVCAT Vertically concatenate strings. (this was generated using the command lookfor strings). In this chapter we shall tackle the problems involved in the consideration of matrices and provide details of how they might be inverted. We shall mention a few concepts but shall not deal with them in depth, electing to leave those to subsequent books on linear algebra. We will also discuss the concept of eigensolutions and also show how these occur within differential systems.
6.2 Properties of Matrices and Systems of Equations We shall discuss the way certain characteristics of systems can be used to determine whether they have solutions or not. We start by considering a couple of simple systems: x=1 (6.1a) this system is in one variable (that is x) and has one solution, that is x equal to 1. The number of variables equals the number of unknowns. Now we consider the system x=1 (6.1b) y=2 again this system has the same number of variables as equations, and hopefully we can work out the solution as x equals 1 and y equals 2. In both of these cases the solution exists and it is unique. These systems are ridiculously simple. Let us again consider a system with the same number of variables as equations x−y =1 (6.1c) x+y =2 This has a unique solution x = 3/2 and y = 1/2: however the system x+y =1 x+y =2
(6.1d)
6.2 Properties of Matrices and Systems of Equations
187
clearly does not have a solution, since x + y cannot equal both one and two. Further considering the system x+y =1 (6.1e) x+y =1 has solutions: in fact x = α and y = 1 − α is a solution for any value of α. In this case we say there are an infinite number of solutions. The question we now pose is what is the difference between these sets of equations. We start with a couple of definitions:
Definition 6.1 (Linear Independence) Consider the set of vectors aj , j = 1, · · · , n and the linear combination n
aj cj .
j=1
This summation is zero if all the cj ’s are zero, and the set of vectors aj are said to be linearly independent if this is the only set of constants for which this is true.
Example 6.11 Consider the vectors a1 a2 a3 a4
= = = =
(1 0 1 (1 0 −1 (1 0 0 (0 1 0
0), 0), 0), 1).
We note that a1 + a2 − 2a3 = 0, that is c1 = 1, c2 = 1, c3 = −2 and c4 = 0; hence there are values of the cj ’s for which the linear combination of the aj are zero, and hence these vectors are linearly dependent. We can now introduce a further term:
Definition 6.2 (Rank of a Matrix) The rank of a matrix is the maximum number of linearly independent rows of a matrix. This can be calculated using the MATLAB command rank. We can determine the rank of the system above using the commands
188
6. Matrices
# a = [1 0 1 0; ... 1 0 -1 0; ... 1 0 0 0; ... 0 1 0 1]; rank(a) " ! This gives the answer 3, so this tells us that one of the rows depends on the others (since there are four rows): as noted above a1 = 2a3 − a2 . We now consider a system of linear equations: a11 x1 + a12 x2 + · · · + a1n xn a21 x1 + a22 x2 + · · · + a2n xn .. .
= = .. .
am1 x1 + am2 x2 + · · · amn xn
= bm ,
b1 , b2 , .. .
which we can write as Ax = b, where A is an m-by-n matrix and the vectors x and b are column vectors of lengths n and m respectively. In simple terms this represents a system of m equations in n unknowns. We also construct the matrix A|b which is the augmented matrix. We now state the results that: 1. The system above has solutions if and only if rank(A) = rank(A|b). 2. If this rank is equal to the number of variables then the system has a unique solution. 3. If the rank is less than the number of variables then there are an infinite number of solutions. In fact the difference between these numbers gives the number of degrees of freedom (which we can think of as the number of variables like α