Before the lab
- Complete the Making 3D plots part of last lab.
Background
- GOBG Chapter 2 (Cell arrays)
- Index expressions
- Variable-length argument lists
- Optional Arguments
Using arrayfun
- Time
- 25 minutes
- Activity
- individual
Start with your solution to Making 3D plots part of last lab or use mine (delta)
Use an anonymous function to define
f
so that the following octave code produces the same plot as before. The nicer (although perhaps slightly slower) solution doesn't involve copy pasting the definition ofdelta
.
a = [4;4];
beta = 7.5;
range = [-4:0.1:8];
[X Y] = meshgrid(range,range);
f=
Z=arrayfun(f,X,Y);
surf(X,Y,Z);
Use the techniques from L18 to measure the speedup from the
for
loop version. You probably want to comment out the actual plotting step and just measure the matrix computation.How sensitive are both versions to the number of elements in
range
? If you double the size (half the step size), does the time double?
Fully vectorizing
- Time
- 25 minutes
- Activity
- individual
If we expand out a single call to delta
in our for loop, we get
Z(i,j) = beta * (a(1)*X(i,j) + a(2)*Y(i,j)) - (beta-1) * (X(i,j)^2 + Y(i,j)^2)
- Use this equation to complete the vectorized function
arraydelta
that satisfies the following test.
function ret = arraydelta(beta,a,X,Y)
ret =
endfunction
%!test
%! a = rand(2,1)
%! X = [2,2;2,2]
%! Y = [-1,-1;-1,-1]
%! assert (arraydelta(0, a, X,Y),[5,5; 5,5],eps)
- Use the anonymous function trick from above to complete the following test
%!test
%! a = rand(2,1);
%! beta = rand*6;
%! X = rand(10,10);
%! Y = rand(10,10);
%! assert (arraydelta(beta, a, X,Y), arrayfun( , X, Y), eps)
- Finally measure the speedup for new version. How sensitive is it to the size of
range
?
a = [4;4];
beta = 7.5;
range = [-4:0.1:8];
[X Y] = meshgrid(range,range);
Z=arraydelta(beta,a,X,Y);
surf(X,Y,Z);
Cell Arrays
- Time
- 15 minutes
- Activity
- Demo
So far we have mainly concentrated on arrays
, which in Octave
consist entirely of numbers. These have efficiency advantages for
certain computations, but they're not very flexible. Roughly speaking,
cell arrays are like multidimensional versions of Python's lists. They
support elements of different types, along with random access.
One slightly surprising, but useful application of cell arrays is to use them as lists of vectors.
data = [0,0,0; 0,0,1; 0,1,0; 1,1,1]
cells = num2cell(data,2)
cellfun(@sum,cells)
- How can we change this example to find the column sums?
- Generalize the example to take the function and matrix as a parameter
function out=rowfun(fun,mat)
endfunction
%!test
%!shared data
%! data = [0,0,0; 0,0,1; 0,1,0; 1,1,1];
%! assert(rowfun(@norm,data), [0;1;1;sqrt(3)], eps)
%!assert(rowfun(@(v)(dot(v,v)),data), [0;1;1;3], eps)
%!assert(rowfun(@prod,data), [0;0;0;1], eps)
Variable-length argument lists
- Time
- 15 minutes
- Activity
- Demo
It turns out that the function timeit
we used in Lab 20 is
not quite general enough, since it works only for single argument
functions. Octave provides a special input argument varargin
, which
collects all remaining arguments into a cell array, providing similar
functionality to the . rest
argument in racket, or the ...rest
argument in JavaScript ES2015.
Use
varargin
to complete the following code for an updated timeit
function
# Based on an example from the Julia microbenchmark suite.
function timeit(reps, func, )
times = zeros(reps, 1);
for i=1:reps
tic(); func( ); times(i) = toc();
end
times = sort(times);
fprintf ('%s\tmedian=%.3fms median=%.3fms total=%.3fms\n',func2str(func), median(times)*1000,
mean(times)*1000, sum(times)*1000);
endfunction
%!test "nullary function"
%! timeit(10000,@rand)
%!test "unary function"
%! timeit(10000,@rand,1)
%!test "Binary function"
%! timeit(10000,@plus,1,2)
%!test "Ternery function"
%! timeit(10000,@plus,1,2,3)