%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Design pattern} Many code fragments are variations of some basic pattern. These pattern are used in many different variations in many different contexts. In this chapter we summarize a few of these \enterm[design pattern]{design pattern}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Looping over vector elements} Iterating over vector elements by means of a \mcode{for}-loop is a very commen pattern: \begin{lstlisting}[caption={\varcode{for}-loop for accessing vector elements by indices}] x = [2:3:20]; % Some vector. for i=1:length(x) % For loop over the indices of the vector. i % This is the index (an integer number) % to be used for accessing vector elements. x(i) % This is the value of the i-th element of the vector. a = x(i); % The value of the i-th vector element % is assigned to the variable a. % Use the value of the i-th vector element by passing it % as an argument to a function: do_something(x(i)); end \end{lstlisting} If the result of the computation within the loop are single numbers that are to be stored in a vector, you should create this vector with the right size before the loop: \begin{lstlisting}[caption={\varcode{for}-loop for writing a vector}] x = [1.2 2.3 2.6 3.1]; % Some vector. % Create a vector for the results, as long as the number of loops: y = zeros(length(x),1); for i=1:length(x) % Write the result of the computation at % the i-th position in the y vector: y(i) = get_something(x(i)); end % Now the result vector can be further processed: mean(y); \end{lstlisting} The computation within the loop could also result in a vector of some length and not just a single number. If the length of this vector (here 10) is known beforehand, then you should create a matrix of appropriate size for storing the results: \begin{lstlisting}[caption={\varcode{for}-loop for writing rows of a matrix}] x = [2:3:20]; % Some vector. % Create space for results - % as many rows as loops, as many columns as needed: y = zeros(length(x), 10); for i=1:length(x) % Write the return value of the function get_something - now a % column vector with 10 elements - into the i-th row of the matrix y: y(i, :) = get_some_more(x(i)); end % Process the results stored in matrix y: mean(y, 1) \end{lstlisting} Another possibility is that the result vectors (here of unknown size) need to be combined into a single large vector: \begin{lstlisting}[caption={\varcode{for}-loop for appending vectors}] x = [2:3:20]; % Some vector. y = []; % Empty vector for storing the results. for i=1:length(x) % The function get_something() returns a vector of unspecified size: z = get_somehow_more(x(i)); % The content of z is appended to the result vector y: y = [y; z(:)]; % The z(:) syntax ensures that we append column-vectors. end % Process the results stored in the vector z: mean(y) \end{lstlisting} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Scaling and shifting random numbers, zeros, and ones} Random number generators usually return random numbers of a given mean and standard deviation. Multiply those numbers by a factor to change their standard deviation and add a number to shift the mean. \begin{lstlisting}[caption={Scaling and shifting of random numbers}] % 100 random numbers drawn from a normal distribution % with mean 0 and standard deviation 1: x = randn(100, 1); % 100 random numbers drawn from a normal distribution % with mean 4.8 and standard deviation 2.3: mu = 4.8; sigma = 2.3; y = randn(100, 1)*sigma + mu; \end{lstlisting} The same principle can be useful for in the context of the functions \mcode{zeros()} or \mcode{ones()}: \begin{lstlisting}[caption={Scaling and shifting of \varcode{zeros()} and \varcode{ones()}}] x = -1:0.01:2; % Vector of x-values for plotting plot(x, exp(-x.*x)); % Plot for the same x-values a horizontal line with y=0.8: plot(x, zeros(size(x))+0.8); % ... or a line with y=0.5: plot(x, ones(size(x))*0.5); \end{lstlisting} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Plotting a mathematical function} A mathematical function $y=f(x)$ assigns to each value of $x$ a single $y$-value. For drawing a function with the computer we need compute a table of values with many $x$-values and the corresponding function values $y=f(x)$. We first create a vector with useful $x$-values. They range from the smallest to the largest value we want to plot. We also need to set a step size that is small enough to result in a smooth plot of the function. We then compute for each value $x_i$ of this vector the corresponding function value $y_i$ and store them in a vector. We then can plot the values of the $y$ vector against the ones of the $x$ vector. The following scripts compute and plot the function $f(x)=e^{-x^2}$: \begin{lstlisting}[caption={Plotting a mathematical function --- very detailed}] xmin = -1.0; xmax = 2.0; dx = 0.01; % Step size x = xmin:dx:xmax; % Vector with x-values. y = exp(-x.*x); % No for loop! '.*' for multiplying the vector elements. plot(x, y); \end{lstlisting} \begin{lstlisting}[caption={Plotting a mathematical function --- shorter}] x = -1:0.01:2; y = exp(-x.*x); plot(x, y); \end{lstlisting} \begin{lstlisting}[caption={Plotting a mathematical function --- compact}] x = -1:0.01:2; plot(x, exp(-x.*x)); \end{lstlisting} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Normalizing histograms} For estimating probabilities or probability densities from histograms we need to normalize them appropriately. The \mcode{histogram()} function does this automatically with the appropriate arguments: \begin{lstlisting}[caption={Probability density with the \varcode{histogram()}-function}] x = randn(100, 1); % Some real-valued data. histogram(x, 'Normalization', 'pdf'); \end{lstlisting} \begin{lstlisting}[caption={Probability with the \varcode{histogram()}-function}] x = randi(6, 100, 1); % Some integer-valued data. histogram(x, 'Normalization', 'probability'); \end{lstlisting} Alternatively one can normalize the histogram data as returned by the \code{hist()}-function manually: \begin{lstlisting}[caption={Probability density with the \varcode{hist()}- and \varcode{bar()}-function}] x = randn(100, 1); % Some real-valued data. [h, b] = hist(x); % Compute histogram. h = h/sum(h)/(b(2)-b(1)); % Normalization to a probability density. bar(b, h); % Plot the probability density. \end{lstlisting} \begin{lstlisting}[caption={Probability with the \varcode{hist()}- and \varcode{bar()}-function}] x = randi(6, 100, 1); % Some integer-valued data. [h, b] = hist(x); % Compute histogram. h = h/sum(h); % Normalize to probability. bar(b, h); % Plot the probabilities. \end{lstlisting}