Introduction to MATLAB Programming Techniques

Course notes for the course organized by KEDIMA UCY in October 2012

Copyright 2010-2012 Timos Papadopoulos

Contents

  • Introductory Notes
  • PART 1. MATLAB bacics
  • PART 2. Introduction to Programming in MATLAB
  • PART 3. Programming for Efficiency and Speed
  • PART 4. Interfacing with external data containers - Using the Appropriate Data Type
  • PART 5. Data Visualisation - Advanced plotting
  • Wrap Up Notes

Introductory Notes

  • The course addresses students with different levels of experience in MATLAB and programming.
  • The priority is to not leave anybody behind, the pace is suited to the least experienced among those attending.
  • Not all parts of the course are for everybody attending. Easier parts for beginners and optional parts for advanced.
  • MATLAB offers a very kind learning curve but certainly not a flat one; it is not a fool's ticket to a Nobel Prize!
  • Its main strength is the very high level programming language environment it offers.
  • We aim to cover the programming essentials quite thoroughly and only give pointers to some more advanced topics.
  • My main concern is user-friendliness, not rigour; in some points we are cutting corners.
  • These notes are not a textbook; they are not 100% sequential and they work best with explanations during the lecture.
  • The main objective of the course is to get our hands dirty.
  • Feel free to interrupt at any point!

PART 1. MATLAB bacics

In this part we will briefly go over the basics of MATLAB's working environment including the MATLAB desktop, variables, the workspace, .mat files and the basic MATLAB data types.

Section 1.1 - Variables, Vectors and Matrices, Computations in the Command Window

Let's start by spending a bit of time to familiarize ourselves with the MATLAB environment and to make sure we are confident with:

  • The MATLAB desktop layout
  • The Command Window
  • The Workspace
  • The Folder Browser
  • The Command History

Make sure you are familiar with docking and undocking the different windows of the MATLAB Desktop. This can be quite confusing for MATLAB beginners and instances have been reported of hair pulling desperation in front of windows that simply do not go where they are told to. If you find yourselves in such a situation keep in mind that you can always go back to the factory default by Desktop -> Desktop Layout -> Default.

The simplest thing to start with if you are first using MATLAB would be to use it as a calculator. Try the following in the Command Window:

1 + 1

ans =

2

2 * 2

ans =

4

3^3

ans =

27

sqrt(2)

ans =

1.4142

What is the difference between the examples above and the ones below?

a = 3 + 5

a =

8

b = 2 * 4;

c = a + b

c =

16

d = sqrt(c);

d == c

ans =

0

e = d ~= a

e =

1

10^(d==b)

ans =

1

We have assigned values to the variables a, b, c and d. These now appear in the Workspace and are available for further computations.

Can you figure out what the 'ans' workspace variable corresponds to?

Observe the difference in the Class of these variables. Observe also their dimensions. They are scalars. In the very core of MATLAB's design is the notion of the Numeric Array or Matrix (MATLAB was coined as short for MATrix LABoratory).

clear

a = [1 2 3]

a =

1 2 3

b = [3:5].'

b =

3

4

5

c = a*b

c =

26

d = b*a

d =

3 6 9

4 8 12

5 10 15

randn(3)

ans =

-1.4132 0.8488 1.5191

-1.1923 -0.4851 -2.3766

0.5190 -1.6008 0.9954

randn(3)

ans =

0.7829 0.4553 0.1634

-1.4753 -0.2978 0.3359

-0.0175 0.7505 -0.5959

a = magic(6)

a =

35 1 6 26 19 24

3 32 7 21 23 25

31 9 2 22 27 20

8 28 33 17 10 15

30 5 34 12 14 16

4 36 29 13 18 11

sum(a,1)

ans =

111 111 111 111 111 111

sum(a,2)

ans =

111

111

111

111

111

111

From the superclass of 'numerics' we will only be concerned with the class of 'doubles'. These are double-precision 64bit floating point representations of the real numbers and they are the default number representation in MATLAB. Note that the number precision displayed in the prompt is not the actual precision of MATLAB's internal number representation.

sqrt(3)

ans =

1.7321

format long

sqrt(3)

ans =

1.732050807568877

format

sqrt(3)

ans =

1.7321

We will also go over the most important of the other classes, i.e. 'chars', 'cells', 'logicals' and 'structs'

A few moments ago we used the command 'clear' to empty the workspace from all the variables it contained. The same happens when we exit MATLAB, all variables in the workspace (and hence all the data they contain) are cleared. What if we want to keep some of those variables for future use?

Right-click on a selection of variables from the Workspace and choose 'Save as...' to save them in a .mat file (you can use any valid filename and the default is 'matlab.mat'). The same can be done from the prompt using the command 'save'.

save('my_variables','a','b','c','d')

Use the 'help' command to check its syntax and use. Execute help save in the Command Window or look it up in the help browser (menu 'Help -> Product Help' in version R2011b or similar in other versions).

Usually a Google search of the notion in question preceded by the word 'matlab' will directly land upon the relevant MathWorks website documentation page. In this case Googling 'matlab save' should return this as the first hit.

Now after exiting and reopening MATLAB one can start working on the data contained in the saved variables. Make sure you can do this by using the 'File -> Open ... ' menu or the 'load' command (again, use the various options for getting help on how to use these commands).

PART 2. Introduction to Programming in MATLAB

We now move on to the MATLAB's main intended mode of use, i.e. the use of Scripts and Functions .

Section 2.1 - A slightly more interesting problem

Consider, as an example, the (still quite rudimentary) technical computation corresponding to numerically solving the equation

in the interval [-10 10] for and two given parameters.

Before solving the equation, it may be worth giving a simple depiction of how the function behaves for different values of the parameter . We create the plot using the function ExpFuncPlot (we will go over functions and graphics later on in the course).

ExpFuncPlot

Clearly, for given values of the parameters and , the equation can have 0, 1, or 2 roots. We can use the fzero function to check that. You can type help fzero in the prompt to check how fzero is used.

For instance, in the case the quantity becomes linear and the equation has a unique solution for every

A = 0;

B = 0.1;

fzero(@(x)x*exp(-A*x)-B,0)

ans =

0.1000

A = 0;

B = 0.1;

fzero(@(x)x*exp(-A*x)-B,-5)

ans =

0.1000

A = 0;

B = 0.1;

fzero(@(x)x*exp(-A*x)-B,10)

ans =

0.1000

Whereas for positive values of the equation can have 0, 1, or 2 roots. You can play around choosing values of the parameters and check for yourselves. A few examples are:

A = 2;

B = 0.1;

fzero(@(x)x*exp(-A*x)-B,0)

ans =

0.1296

A = 2;

B = 0.1;

fzero(@(x)x*exp(-A*x)-B,1)

ans =

1.2713

A = 2;

B = 1;

fzero(@(x)x*exp(-A*x)-B,0)

Exiting fzero: aborting search for an interval containing a sign change

because NaN or Inf function value encountered during search.

(Function value at -463.41 is -Inf.)

Check function or try again with a different starting value.

ans =

NaN

A = 2;

B = -10;

fzero(@(x)x*exp(-A*x)-B,0)

ans =

-1.1025

A = 2;

B = 0.1;

fzero(@(x)x*exp(-A*x)-B,-20)

Exiting fzero: aborting search for an interval containing a sign change

because NaN or Inf function value encountered during search.

(Function value at -429.6 is -Inf.)

Check function or try again with a different starting value.

ans =

NaN

Section 2.2 - MATLAB Scripts

What we have just done is a typical example of a first look into a (very simplistic) problem. We devised a rough solution and we started checking it out by playing around with different values of the parameters involved in order to get a feeling of whether the solution is satisfactory. With any luck some of the cases we have checked are of interest and we would like to put them together as a first answer to the problem at hand. For instance, we migh want to present those selected cases to a colleague or our supervisor as a solution to the problem. How would we do that? Would we need to keep retyping the same commands every time? That wouldn't be very practical really...

This is where scripts come into play. A MATLAB script is a essentially a text file but one that rather than having a .txt extension has by a .m extension. Lines in that file are MATLAB commands as we would type them in MATLAB's command window (and it can also have comment lines). We can create a new script file by File -> New (this can vary slightly across different versions of MATLAB but is always self evident).

Let's try and create such a file that will contain the equation solution cases we checked just above. (If you run into difficulties open IntroScript.m in the CourseData material. That file does exactly that. To open a file use File -> Open (again this can vary slightly across different versions of MATLAB).

To execute a script we just type the name of the script (i.e. the filename withouth the .m extension) on the prompt of the Command Window and press Enter. Important Note: The script has to reside either in the Current Folder or in the Matlab Path otherwise it will not run.

Experiment a bit on creating, opening, editing, saving and executing scripts as described above. Make sure you are confident in managing the cases described above.

Section 2.3 - For Loop

We saw above that the solution returned by our algorithm depends not only on the parameter values but also on the value of ot the initial point we choose. So say that our job is to compute the root computed for a list of parameter pairs and for given initial values and keep the computed values as indicated in the table below

A / B / x0 = 0 / x0 = 1 / x0 = 10 / x0 = 20
0 / -0.2
0 / +0.1
0 / +0.2
1 / -0.2
1 / +0.1
1 / +0.2
2 / -0.2
2 / +0.1
2 / +0.2
5 / -0.2
5 / +0.1
5 / +0.2

How would we do that? One (rather stupid) way would be to go over each one of the 15 rows of this table separately, execute the corresponding command in the Command Window and populate the corresponding table entry. Another (only slightly) more convenient way would be to edit a script like the one we saw above with the required computation lines and then execute the script. The appropriate way would be to use the workhorse of technical computation, namely a 'for loop'. (Type help for in the Command Window for a brief explanation).

Depending on your level of experience in programming and in MATLAB this task can range from 'A walk in the park' to 'Climbing Mount Everest'. We will go over this until all of us have somehow managed to make it work (or are adequately close to that...).

For your reference, a fairly optimised solution is given the ForLoopScript.m in the CourseData material. Reverse engineering that solution with the 'help' options of MATLAB should do the trick if you are stuck in any point. When you get it right your code should return this result...

clear

ForLoopScript

0 -0.2000 -0.2000 -0.2000 -0.2000 -0.2000

0 0.1000 0.1000 0.1000 0.1000 0.1000

0 0.2000 0.2000 0.2000 0.2000 0.2000

1.0000 -0.2000 -0.1689 -0.1689 -0.1689 -0.1689

1.0000 0.1000 0.1118 0.1118 3.5772 3.5772

1.0000 0.2000 0.2592 0.2592 2.5426 2.5426

2.0000 -0.2000 -0.1486 -0.1486 -0.1486 -0.1486

2.0000 0.1000 0.1296 1.2713 1.2713 NaN

2.0000 0.2000 NaN NaN NaN NaN

5.0000 -0.2000 -0.1134 -0.1134 -0.1134 -0.1134

5.0000 0.1000 NaN NaN NaN NaN

5.0000 0.2000 NaN NaN NaN NaN

... which as you can see is the table defined above populated with the equation solutions (not all of which are correct)

In order to run the ForLoopscript.m file you have to make sure it is either in the current directory or in a directory of the MATLAB path (you can check that in File -> Set Path...). This can be verified by running which ForLoopScript at the prompt. This is also a good point to spend a bit of time to familiarize yourselves with MATLAB's Function Precedence Order

Section 2.4 - Basic Programming - MATLAB Functions

To conclude this part of the course we go over the fundamental notion of the 'function'.

Simply speaking, a MATLAB function is quite similar to a MATLAB script with the very important difference that it accepts input and output arguments and it has its own Workspace.

To create a function we go about in pretty much the same way as above with scripts but we include a first line that starts with the reserved word function followed by the list of output arguments, the function name and the list of input arguments. For instance, to convert the ForLoopScript.m to a function we include the first line function eq_sol_results = ForLoopFunction(As,Bs,x0) in the .m file and save it (preferably) as ForLoopFunction.m. Spend a bit of time to:

  1. Work out any other changes needed to create the function corresponding to the previous script
  2. Run the function in the prompt and make sure you become familiar with the fact that is has its own workspace
  3. Check the basic functionality of MATLAB's debugger
  4. Check the provided ForLoopFunction.m file in the CourseNotes folders
  5. See what the help preamble amounts to
  6. See what the validateattributes functionality amounts to

PART 3. Programming for Efficiency and Speed

The programming language offered by the MATLAB environment is what we call an 'Interpreted Language' unlike the more typical 'Compiled Languages' such as C/C++, JAVA etc. In conjunction with other features and characteristics of MATLAB, this has as a consequence that MATLAB code is much easier to start writing and faster to develop in a prototyping application stage, but slower in running/executing, especially when it comes to computations involving for-loops. As this speed disadvantage can prove very problematic in computationally demanding cases, we list below possible ways to mitigate it and we present the details for the easier ones (those that you should be following pretty much always).

Section 3.1 - Vectorization

In the MATLAB world (practically) everything revolves around the notion of matrices. All elementary operations (in fact nearly every operation, elementary or not) can be written in what is called a 'vectorized form', i.e. as a sequence of linear algebraic operations involving whole matrices and vectors rather than loops over their individual elements. Such vectorized form computations can be very much faster than the corresponding ones using loops.

See for example the four ways to do the same thing (assign a sinusoid sequence to a vector in the variable name x) that are listed in the script CheckSpeed1.m

CheckSpeed1

Non-vectorized (for loop) assignment: 0.49348[s]

Vectorized assignment: 0.039664[s]

Non-vectorized (for loop) preallocated assignment: 0.16933[s]

(Repeated) non-vectorized (for loop) assignment: 0.48736[s]

Evidently the vectorized assignment (second case) is about 25 time faster than the non-vectorized equivalent. Notice how the preallocation of an appropriately sized vector to the variable x also has a dramatic effect in the efficiency of the assingment (comparison of third and fourth cases). We will return to the technique of preallocation in a bit.

The efficiency associated with vectorization becomes even more striking when an actual computation is used an an example, i.e. the inner product of two vectors

Examine the three ways to implement that inner product computation listed in the script CheckSpeed2.m

CheckSpeed2

Non-vectorized (2 for loops) inner product: 0.47596[s]

Non-vectorized (for loop) inner product: 0.021636[s]

Vectorized inner product: 0.0026821[s]

Notice how the computation of unnecessary quantities (first case) can make the computation tens of times slower than a non-vectorized implementation (second case) and hundreds of time slower than the proper vectorized computation (these ratios can change in implementations in different computers).

You have probably noticed the orange underlinings in the CheckSpeed1.m and CheckSpeed2.m files and you wonder what they are. This is a feature of MATLAB's Code Analyzer. Hover over the underlined variables to read the issue identified by the analyzer. In the next example we discuss the technique of 'preallocation' and that should help you understand what's going on and how you can address this issue.

Section 3.2 - Preallocation

When using MATLAB extensively vectorization becomes second nature and it turns out it is possible to vectorize most computations (even more so with the use of tools such as arrayfun, cellfun, structfun etc. which are not covered in this course) . Nevertheless, there are cases where the use of one or more loops is dictated either by necessity or convenience. In newer versions of MATLAB this turns out to not be completely detrimental as long as the arrays are properly preallocated, i.e. they are not allowed to change dimensionality inside the loop. Such an example was very briefly given in the CheckSpeed1.m example and it is further elaborated in CheckSpeed3.m which computes the external product of two vectors.

CheckSpeed3

Non-vectorized (for loop) non-preallocated outer product: 1.7519[s]

Non-vectorized (for loop) preallocated outer product: 0.032799[s]

Vectorized outer product: 0.010563[s]

Evidently, when preallocation is used the many tens of times speed ratio between the vectorized computation and the for loop (third v. first cases) reduces to a just a few times speed ratio (again these ratios can change in implementations in different computers).

Section 3.3 - Use of the Profiler to identify Bottlenecks

MATLAB offers a powerful tool to check the execution time used by the code we write in the form of the Command Window function profile and it Graphical User Interface counterpart Profiler. To give an example of this tool we go to Desktop -> Profiler, we type CheckSpeed3 in the Run this code: box and we hit Start Profiling. We should then get something like this. Spend a bit of time in exploring that report you just generated and making sense of the information it provides.

Section 3.4 - Simple parallelization using parfor

Another option offered by recent versions of MATLAB (so long as the installation includes the Parallel Computing Toolbox) is that of parallizing the code over multiple CPU cores on a single computer. This is done by converting the for in for-loops to parfor and it can achieve a maximum execution speed up ratio equal to the number of cores present in the CPU. Note that parfor loops come with certain restrictions and that not every for loop can be directly converted to a parfor loop (far from it actually).

An example of a parfor implementation compared to a standard for that does the same thing sequentially is given in the ParForExample.m file. Note that these timing are specific to the 4core CPU where the notes where created and will vary considerably in other computers.

[time_seq, time_par] = ParForExample

Starting matlabpool using the 'local' configuration ... connected to 2 labs.

Sending a stop signal to all the labs ... stopped.

time_seq =

3.0867

time_par =

2.2337

Moving slightly off topic, we note that the last example silently introduced two new concepts namely those of: