3/13 ! expanded explanations for examples of performance analysis ! includes an analysis example not presented during lecture ! includes material on 2-D arrays not presented during lecture: ! + pick these up on your own: ! + identity matrix: $eye$ ! + $sortrows$ ! + these will be presented in 3/15 lecture: ! + create a matrix using both horizontal and vertical concatenation ! + transposition $'$ ! + create string matrix from string row vectors: $str2mat$ ! + $size$, $length$ of 2-D arrays ! + replicate matrix: $repmat$ ! + rotate counter-clockwise by multiple of 90 degrees: $rot90$ ! + logical matrix as index + trick to get coordinates of each element ! + 3/15 lecture will also go over reading input from a file announcements + Certification form to receive credit for completing Course&T1 Evaluation is available from Announcements webpage + P3 core scores already sent out; online until after spring break + P3 regrades until thursday (friday if consultants are available) + P5 write-up by end of tonight + E11 posted later today; due Thursday + T2 room splits, by last name -- different from T1 Olin Hall 155: K - Z Olin Hall 255: A - J + prelim seating -- leave ends of every 3rd row empty + not required, but it makes things nicer for *you* topics + performance: + E10 + code in section 2.4 in monster lecture sketch + code in section 3.1 in monster lecture sketch ! + code in section 3.3 in monster lecture sketch + 2-D arrays _______________________________________________________________________________ E10: see solutions and scripts on Exercises webpage _______________________________________________________________________________ analysis of 2.4 code from monster lecture sketch [notes here are a revision of sec 2.5 in monster lecture sketch] technique: + key insight: loops (and function calls) are what make programs slow + without loops (or function calls), programs can run only a constant number of steps, which is fast compared to anything that depends on $n$, e.g. $O(n^2)$. + each loop (potentially) adds a non-constant factor slowdown + therefore: concentrate on loops + work your way inwards from outer loops to inner loops (not "outwards from inner to outer loops", as originally posted) + each loop contributes a slowdown factor code: x = 0; i = 0; while i ~= n x = x + 2*i; i = i+1; end analysis -- work inwards to compute individual contributions: + code before does bounded amount of work, $C1$ + $i$ loop -- factor $n$ since runs about $n$ times (we can tell from code) ($n+1$ times? $n-1$ times? small details don't matter); look inside $i$ loop, at its body: + a bounded amount of work, say $C2$ analysis -- combine contributions: factor slowdown from outside i i loop loop loop body | | | V V V C1 + n * C2 total time: O(C1 + C2 * n) = O(n) /|\ /|\ | | lower order term constant factor _______________________________________________________________________________ analysis of 3.1 code from monster lecture sketch code: sofar = 0; for j = 1:length(s) for i = 1:j % compute $i2j = sum(s(i:j))$ i2j = 0; for k = s(i:j) i2j = i2j + k; end if i2j > sofar sofar = i2j; end end end analysis -- work inwards to compute individual contributions: + let $n$ = $length(s)$ + $j$ loop: factor of $n$ since runs about $n$ times; look inside $j$ loop, at its body: j: + $i$ loop: factor of $n$ since runs at most $j <= n$ times (we see that $j <= n$ by looking at the code); look inside $i$ loop, at its body: j,i: + constant work, say $C1$, to do $i2j = 0$ j,i,k: + $k$ loop: factor of $n$ since runs at most $j-i+1 <= j <= n$ times; look inside $k$ loop, at its body: j,i,k: + constant work, say $C2$, to do body j,i: + constant work, say $C3$, for conditional (assume body of condition is always executed to get upper bound) analysis -- combine contributions: j loop |<----------j body------------->| | i | loop |<------i body--------->| | | | k k | | | | loop body | | | | | | | V V V V V V n * n * (C1 + n * C2 + C3) total time: O((C1+C3) * n^2 + C2 * n^3) = O(n^3) \_____ _____/ /|\ V | lower order term constant factor _______________________________________________________________________________ ! analysis of 3.3 code in monster lecture sketch ! ! code: ! ! S = 0; ! for x = s ! S = [S S(end)+x]; ! end ! sofar = 0; ! for j = 1:length(s)+1 ! for i = 1:j-1 ! i2j = S(j) - S(i); ! if i2j > sofar ! sofar = i2j; ! end ! end ! end ! ! ! analysis -- work inwards to compute individual contributions: ! ! + let $n = length(s)$. ! + constant work, say, $C1$ outside of all loops ! ! + $x$ loop: factor of $n+1$ since runs $n$ times; ! look inside $x$ loop, at its body: ! ! x: + constant amount of work, say $C2$. ! ! + $j$ loop: factor of $n+1$ since runs $n+1$ times; ! look inside $j$ loop, at its body: ! ! j: + $i$ loop: factor of $n$ since runs at most $j-1 <= n$ times; ! look inside $i$ loop, at its body: ! ! j,i: + constant amount of work, say $C3$ ! (assume condition is always true, so body always executed, ! to get upper bound) ! ! ! analysis -- combine contributions: ! ! outside j ! all loop |<-j body-->| ! loops x x | i i ! | loop body | loop body ! | | | | | | ! V V V V V V ! C1 + n * C2 + (n+1) * n * C3 ! ! total time: O(C1 + (C2+C3) n + C3 n^2) = O(n^2) ! \_____ _____/ /|\ ! V | ! lower order terms constant factor %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % note: the rest of this write-up is entirely made of code that you should % copy and paste into the command window -- please experiment! % ====================================================================== % 2-D (two-dimensional) arrays % ====================================================================== % % "matrix" = "(rectangular) two-dimensionsal array" % % ! example: % ! % ! 3-by-5 matrix has 3 rows and 5 columns % ! % ! +-+-+-+-+-+ % ! 1 2 3 4 5 1 | | | | | | 1 2 3 4 5 % ! +-+-+-+-+-+ +-+-+-+-+-+ +-+ +-+ +-+ +-+ +-+ % ! 1 | | | | | | | | | | | | | | | | % ! +-+-+-+-+-+ +-+-+-+-+-+ +-+ +-+ +-+ +-+ +-+ % ! 2 | | | | | | 2 | | | | | | | | | | | | | | | | % ! +-+-+-+-+-+ +-+-+-+-+-+ +-+ +-+ +-+ +-+ +-+ % ! 3 | | | | | | | | | | | | | | | | % ! +-+-+-+-+-+ +-+-+-+-+-+ +-+ +-+ +-+ +-+ +-+ % ! 3 | | | | | | % ! +-+-+-+-+-+ % a rectangular 2-D array is an $m$-by-$n$ table $a$ of values: % + $m$ = height = number of rows in $a$ % + $n$ = width = number of columns in $a$ % + the two dimensions/directions of a 2-D array are % 1 = vertical: $size(a,1)$ = height of $a$ % 2 = horizontal: $size(a,2)$ = width of $a$ % ! + *rectangular* = each row is the same size; each column is the same size % ! here is a non-rectangular matrix: % ! % ! +-+-+-+-+-+ % ! | | | | | | % ! +-+-+-+-+-+ % ! | | | | % ! +-+-+-+-+ % ! | | | | | % ! +-+-+-+-+ % ! | | % ! +-+ % ! | | % ! +-+ % ! careful: row vs column and horizontal vs vertical can be confusing % ! + positions are $(row,col)$ or $(y,x)$, NOT $(col,row)$ or $(x,y)$ % ! [3/14] fixed typo $x<-->y$ ----------------------------> ^^^^^^^ % ! + height = *vertical* measurement = number of *horizontal* rows % ! + width = *horizontal* measurement = number of *vertical* columns % ! careful: what does $length(a)$ mean? % ! + answer: $length(a) = max(size(a,1), size(a,2))$ % ! is the maximum of the height and width of $a$ % ====================================================================== % creation of 2-D arrays % ====================================================================== % % + revisit assignment: matlab automatically extends array to be big enough % + numerical arrays: entries are filled with 0s % + string arrays: entries are filled with blanks ($' '$) k(5,3) = 7 s(5,3) = '*' % ! + new function: create string matrix from string row vectors, $str2mat$: % ! note: since matrices are rectangular, rows are padded with % ! spaces as necessary to make them all the same length x = str2mat('abc','def') y = str2mat('1234','5678') z = str2mat('/-\', '| |', '= =', '| |', '\-/') w = str2mat('spring', 'break', 'is', 'almost', 'here') size(w) % + revisit horizontal concatenation, juxtaposition within $[$ and $]$: % % if $x$ and $y$ have the same height, % they can be "glued together side-by-side" [x y] [x z] % <-- error, different height % + "revisit" vertical concatenation, $;$ within $[$ and $]$: % % if $x$ and $y$ have the same width, % they can be "glued together [x ; z] [x ; y] % <-- error, different width % ! + combination of horizontal and vertical concatenation k = [1 2 3 5; 9 5 7 2] [4 ; 8], [29 30 ; 5 12], [1 ; 4] j = [[4 ; 8] [29 30 ; 5 12] [1 ; 4]] % + revisit: $ones$, $zeros$, $rand$ % + one argument: make square matrix ones(3), zeros(3), rand(3) % + two arguments: height, width, in that order ones(2,4), zeros(2,4), rand(3,5) % ! + new function, $eye$ (for something called the "*i*dentity matrix"): % ! all 0s, except for 1s on diagonal eye(3), eye(3,5), eye(5,3) % ====================================================================== % operations on 2-D arrays % ====================================================================== % % + new operation: $'$, transposition: % + "transpose" = "flip across diagonal" = "interchange rows and columns": % +----------+ % | +------+ | % V V V V % + if $b = a'$, then $b(i,j) = a(j,i)$ % + note: $a'' = a$ w, w', w'' % + bonus new operation: $.'$, complex conjugate transpose % + other operations -- as you expect: operation is applied element-wise % % + revisit arithmetic operations: $+$, $-$, $*$, $.*$, $/$, $./$, $.^$ % % + scalar with matrix: $+$, $-$, $*$, $./$, $.^$ 1 + k, 1 - k, 2 * k, 2 ./ k, 2 .^ k % + matrix with scalar: $+$, $-$, $*$, $/$, $.^$ k + 1, k - 1, k * 2, k / 2, k .^ 2 % + 2 matrices of the same size: $+$, $-$, $.*$, $./$, $.^$ k + j, k - j, k .* j, k ./ j, k .^ j % ! + revisit comparisons: $<$, $<=$, $>$, $>=$, $==$, $~=$ % ! + scalar with matrix 5 < k, 5 <= k, 5 > k, 5 >= k, 5 == k, 5 ~= k % ! + matrix with scalar k < 5, k <= 5, k > 5, k >= 5, k == 5, k ~= 5 % ! + matrix with matrix j < k, j <= k, j > k, j >= k, j == k, j ~= k % ! + revisit logical operations: $&$, $|$, $~$ -- as expect, element-wise (j < k) | (j == k), j <= k (j <= k) & (j ~= k), j < k ~(j < k), j >= k % ====================================================================== % functions on 2-D arrays % ====================================================================== % ! + new function: $size(a,d)$ = size in direction/dimension $d$: % ! 1 = vertical: $size(a,1)$ = height of $a$ % ! 2 = horizontal: $size(a,2)$ = width of $a$ size(k,1), size(k,2) % ! + revisit $length$ -- careful! % ! + $length(a) = max(size(a,1), size(a,2))$ % ! is the maximum of the height and width of $a$ length(k) % ! + new function: replicate, $repmat(a,m,n)$: % ! make "big $m$-by-$n$ matrix" where each entry is $a$ repmat(z, 2, 5) % + revisit: $round$, $ceil$, $floor$, $trunc$ -- as expect: element-wise round(rand(4,2)), ceil(6*rand(3,5)) % ! + revisit: $rem$ -- as expect: element-wise rem(k, 3), rem(113, k) % ! new function: $sortrows$ -- sort rows "lexicographically" % ! + for string matrix, this means sort rows in dictionary order w, sortrows(w) % ! + revisit: $flipud$, $fliplr$ -- as expect w, flipud(w), fliplr(w) % ! + new function: $rot90$ -- rotate multiple of 90 degrees % ! + $rot90(a)$ -- rotate counter-clockwise 90 degrees % ! + $rot90(a,k)$ -- rotate counter-clockwise $k*90* degrees rot90(w), rot90(w,1), rot90(w,-1), rot90(2) % ! + general rule for functions listed below: % ! + operate column-wise if given just matrix % ! + else operate in direction/dimension specified % + revisit: $sum$, $prod$, $cumsum$, $cumprod$, $max$, $min$ sum(k), prod(k), cumsum(k), cumprod(k), max(k), min(k) sum(k,1), prod(k,1), cumsum(k,1), cumprod(k,1) sum(k,2), prod(k,2), cumsum(k,2), cumprod(k,2) % + careful! 2nd argument to $max$, $min$ --> element-wise $max$ or $min$: max(k,2), min(k,2) max(k,4), min(k,4) % + empty vector for 2nd argument, 3rd argument to $max$, $min$: % which dimension/direction to compute answers for max(k,[],1), max(k,[],2) min(k,[],1), min(k,[],2) % ! + revisit $any$, $all$ any(w == 's') any(w == 's',1) any(w == 's',2) all(k < 6) all(k < 6, 1) all(k < 6, 2) % ! + revisit $sort$ sort(w), sort(w,1) sort(w,2) % ====================================================================== % 2-D indexing % ====================================================================== % (matrix variables below are named % $p$ for "*p*icture", % $pc$ for "*p*icture of column(s)", % $pr$ for "*p*icture of row(s)" % ) % recall, in 1-D vectors: % + $p(r)$ % = 1-D matrix of values in $x$ at the positions specified in vector $r$ % + special case: $r$ is a scalar % $p(r)$ % = value in $x$ at the single position $r$ % + special case: $r$ is a logical array % "positions specified by $r$" = positions $i$ where $r(i)$ is true % now, in 2-D matrices: % + $p(r,c)$ = 2-D matrix of values in $x$ at the intersections of % the rows specified in vector $r$ and % the columns specified in vector $c$ % + special case: $r, $c are each a scalar % $p(r,c)$ = value in $x$ at row $r$ and column $c$ % = value in $x$ at intersection of row $r$ and column $c$ % + special case: $r$ and/or $c$ is a logical array % places specified by logical array = places where logical value is true % make 10-by-20 string matrix of $o$s to help illustrate points p0(10,20) = ' '; p0(:,:) = 'o'; % note: matlab automatically replicates 'o' to 10-by-20 matrix % note: in all cases below, after $r$ and $c$ are set, the code for % $pr$,$pc$,$p$ is *exactly* the same % illustration of $p(r,c)$ -- $r$, $c$ scalars r = 2; c = 5; p = p0; pr = p0; pc = p0; r, pr(r, :) = '-', p(r, :) = '-'; % row(s) $r$ c, pc(:, c) = '|', p(:, c) = '|'; % column(s) $c$ p(r,c) = '#' % intersection of row(s) $r$ and column(s) $c$ % illustration of $p(r,c)$ -- $r$ a scalar, $c$ a vector r = 2; c = [3 5 19]; p = p0; pr = p0; pc = p0; r, pr(r, :) = '-', p(r, :) = '-'; % row(s) $r$ c, pc(:, c) = '|', p(:, c) = '|'; % column(s) $c$ p(r,c) = '#' % intersection of row(s) $r$ and column(s) $c$ % illustration of $p(r,c)$ -- $r$ a vector, $c$ a scalar r = [2 7 9]; c = 3; p = p0; pr = p0; pc = p0; r, pr(r, :) = '-', p(r, :) = '-'; % row(s) $r$ c, pc(:, c) = '|', p(:, c) = '|'; % column(s) $c$ p(r,c) = '#' % intersection of row(s) $r$ and column(s) $c$ % illustration of $p(r,c)$ -- $r$ a vector, $c$ a vector r = [2 7 9]; c = [3 5 19]; p = p0; pr = p0; pc = p0; r, pr(r, :) = '-', p(r, :) = '-'; % row(s) $r$ c, pc(:, c) = '|', p(:, c) = '|'; % column(s) $c$ p(r,c) = '#' % intersection of row(s) $r$ and column(s) $c$ % ! ====================================================================== % ! logical matrix as index + trick to get coordinates of each element % ! ====================================================================== % ! if $cond$ is a logical matrix, % ! then $p(cond)$ = elements in $p$ at the positions $(i,j)$ where % ! $cond(i,j)$ is true % ! here is a useful trick: % ! + define $r(i,j)=i$ and $c(i,j)=j$ % ! + then: $(r(i,j), c(i,j)) = (i,j)$ % ! + that is, pairing elements $r(i,j)$ and $c(i,j)$ yields the coordinates % ! $(i,j)$ of those elements r = repmat((1:10)', 1, 20) % r(i,j) = i = which row $(i,j)$ is in c = repmat(1:20, 10, 1) % c(i,j) = j = which column $(i,j)$ is in % ! examples of logical arrays using trick above p = p0; % prepare $p$ for examples % ! assign '*' to every position $(i,j)$ where $i+j$ is even p(rem(r + c, 2) == 0) = '*' % ! assign 'E' to every position $(i,j)$ where $i$ is even or $j$ is even p(rem(r,2) == 0 | rem(c,2) == 0) = 'E' % ! assign ' ' to every position $(i,j)$ where $i$ is even and $j$ is even p(rem(r,2) == 0 & rem(c,2) == 0) = ' '