3/28 bonus material topics + $sparse$, permutations, inverse permutations, $sort$ + Instant Runoff Voting $sparse$ + we usually use it with $full$ + $sparse$ is roughly an inverse (opposite) of $find$ + $full(sparse(i,j,v,m,n))$ throws values into an array of 0s: + create $m$-by-$n$ matrix of 0s + throw each value $v(k)$ into position $(i(k), j(k))$ + combine numbers landing on the same position by addition + $i,j,v$ are positions and values as in $find$ + conceptually, vectors of the same length (can be row and/or column) + one or two of them can be scalars: matlab replicates as necessary + $m,n$ can be omitted: matlab makes result as small as possible example (run it! make changes!): i = [1 2 3 2 3 2], j = [3 3 1 2 3 3], v = [-7 4 2 1 6 5] y=full(sparse(i,j,v)) picture: y 1 2 3 1 2 3 4 5 6 +---+---+----+ +-+-+-+-+-+-+ | | | | i |1|2|3|2|3|2| 1 | 0 | 0 | -7 | v(1)=-7 at (i(1),j(1))=(1,3) +-+-+-+-+-+-+ | | | | +---+---+----+ +-+-+-+-+-+-+ | | | | v(2)=4 at (i(2),j(2))=(2,3) <-\ same place, j |3|3|1|2|3|3| 2 | 0 | 1 | 9 | v(4)=1 at (i(4),j(4))=(2,2) > so add: +-+-+-+-+-+-+ | | | | v(6)=5 at (i(6),j(6))=(2,3) <-/ 0+4+5 = 9 +---+---+----+ +--+-+-+-+-+-+ | | | | v |-7|4|2|1|6|5| 3 | 2 | 0 | 6 | v(3)=2 at (i(3),j(3))=(3,1) +--+-+-+-+-+-+ | | | | v(5)=6 at (i(5),j(5))=(3,3) +---+---+----+ example: birthday problem ($sparse$ seems to be faster than $hist$) % throw $nd$ darts into $nb$ buckets: d = ceil(nbuckets*rand(1,nd)); % $i$-th dart lands in $d(i)$-th bucket b = full(sparse(1,darts,1,1,nb)); % $b(j)$ = #darts in $j$-th bucket _______________________________________________________________________________ permutations + note: we mostly use pseudocode, to emphasize the direction that data flows + to *permute* = to re-arrange + a *permutation* + = a specification of how to re-arrange elements, e.g. "swap first and last elements" or "flip left-to-right", or + = a re-arrangement of elements, i.e. the result of applying a specificied re-arrangement + let $a$, $b$ be vectors of the same length $n$ + $a$ is a permutation (re-arrangement) of $b$ = $b$ is a permutation (re-arrangement) of $a$ = ignoring order, $a$ and $b$ contain exactly the same elements + a permutation (specification) can be represented as a vector $i$ that is a permutation (re-arrangement) of $1:n$ + $b <-- a(i)$ = $b(1:n) <-- a(i)$ = re-arrange $a$ according to $i$ to obtain $b$ = *permute* $a$ by permutation $i$ to obtain $b$ = *apply* permutation $i$ to $a$ to obtain $b$ = $j$-th element of $b$ gets $i(j)$-th element of $a$, i.e. $b(j) <-- a(i(j))$ for each $j$ = $i(j)$ is source position in $a$ of destination position $j$ in $b$, i.e. $a(i(j)) --> b(j)$ for each $j$ matlab examples (run them! make changes!): a = [6 8 9 7 2 4], a(1:6), a([6 2:5 1]), a(6:-1:1), a([5 6 1 4 2 3]) picture: 1 2 3 4 5 6 +------+------+------+------+------+------+ a | 6 | 8 | 9 | 7 | 2 | 4 | +------+------+------+------+------+------+ +------+------+------+------+------+------+ indices into $a$ are a(1:6) | a(1) | a(2) | a(3) | a(4) | a(5) | a(6) | 1:6 = [1 2 3 4 5 6] | = 6 | = 8 | = 9 | = 7 | = 2 | = 4 | +------+------+------+------+------+------+ +------+------+------+------+------+------+ indices into $a$ are a([6 2:5 1])| a(6) | a(2) | a(3) | a(4) | a(5) | a(1) | [6 2:5 1]=[6 2 3 4 5 1] | = 4 | = 8 | = 9 | = 7 | = 2 | = 6 | +------+------+------+------+------+------+ +------+------+------+------+------+------+ a(6:-1:1) | a(6) | a(5) | a(4) | a(3) | a(2) | a(1) | indices into $a$ are | = 4 | = 2 | = 7 | = 9 | = 8 | = 6 | 6:-1:1 = [6 5 4 3 2 1] +------+------+------+------+------+------+ +------+------+------+------+------+------+ indices into $a$ are a([5 6 1... | a(5) | a(6) | a(1) | a(4) | a(2) | a(3) | [5 6 1 4 2 3] 4 2 3]) | = 2 | = 4 | = 6 | = 7 | = 8 | = 9 | +------+------+------+------+------+------+ inverse permutations + suppose we want the *inverse* (opposite) of a permutation? + Q: if we have $b$ and $i$, how do we compute $a$ such that $b$ = $a(i)$? + A: undo/reverse the movement of each element: $b <-- a(i)$ $b --> a(i)$ = = $for j = 1:n, b(j) <-- a(i(j))$ $for j = 1:n, b(j) --> a(i(j))$ matlab: $b = a(i)$ $a(i) = b$ + Q: if we have just $i$, how do we compute permutation (specification) $k$ such that for all possible vectors $a$: if $b$ = $a(i)$, then $b(k)$ = $a$? + A: it turns out we want $k(i)$ = $1:n$, which gives us the concise matlab solution $k(i) = 1:n$! !+ bonus derivation of answer: ! ! (0) setup: ! + let $a$ be a vector of length $n$ with distinct elements ! + let $i$ be a permutation (specification), ! i.e. a re-arrangement of $1:n$ ! + let $b$ = $a(i)$: note that $b$ also has distinct elements ! (1) fact: $c(x)$ = $c(y)$ exactly when $x$ = $y$ if $c$ has distinct elements ! (2) know: a(i(j)) = b( j ) for $j$ from $1:n$ (by setup: $b$ = $a(i)$) ! (3) want: a( h ) = b(k(h)) for $h$ from $1:n$ (this is the goal $b(k) = a$; ! use new variable $h$ to avoid confusion with $j$) ! (4) choice: let $h$ be any legal value, i.e. any value from $1:n$ ! (5) choice: let $j$ be the unique value from $1:n$ such that $i(j)$ = $h$: ! $j$ exists since $i$ contains each value from $1:n$ ! (6) know: $a(i(j))$ = $a(h)$ by $i(j)$ = $h$ from (5) ! (7) want: $b(j)$ = $b(k(h))$ by (6), (2), and (3) ! (8) want: $j$ = $k(h)$ by (7) and (1) for $c$ = $b$ ! (9) want: $j$ = $k(i(j))$ by (8) and $i(j)$ = $h$ from (5) !(10) want: $1:n$ = $k(i(1:n))$ by substituting $j$ = $1:n$ into (9), which ! makes sense since as $h$ varies over each value from $1:n$ in (4), ! $j$ varies over each value from $1:n$ in (5) !(11) matlab solution: $k(i) = 1:n$ from (10) and $i(1:n)$ = $i$. _______________________________________________________________________________ $sort$ $[b,i] = sort(a)$ returns the elements of $a$ rearranged to be in ascending sorted order $b$ and also returns the corresponding positions $i$, i.e. the permutation (specification) $i$ such that $b$ = $a(i)$ example (run it! make changes!): a = [6 8 9 7 2 4], [b,i] = sort(a), a(i) k(i) = 1:length(a), b(k) % <-- inverse permutation example picture: 1 2 3 4 5 6 +------+------+------+------+------+------+ a | 6 | 8 | 9 | 7 | 2 | 4 | +------+------+------+------+------+------+ +------+------+------+------+------+------+ i | 5 | 6 | 1 | 4 | 2 | 3 | +------+------+------+------+------+------+ +------+------+------+------+------+------+ a(i) | a(5) | a(6) | a(1) | a(4) | a(2) | a(3) | = b | = 2 | = 4 | = 6 | = 7 | = 8 | = 9 | +------+------+------+------+------+------+ +------+------+------+------+------+------+ k | 3 | 5 | 6 | 4 | 1 | 2 | +------+------+------+------+------+------+ +------+------+------+------+------+------+ b(k) | b(3) | b(5) | b(6) | b(4) | b(1) | b(2) | = a | = 6 | = 8 | = 9 | = 7 | = 2 | = 4 | +------+------+------+------+------+------+ example: + suppose $i,j,v$ for $sparse$ or from $find$ + suppose want $v$ to be in ascending order: [v,order] = sort(v); % original $v$ is permuted by $order$ i = i(order); % permute $i$ by $order$ j = j(order); % permute $j$ by $order$ _______________________________________________________________________________ IRV (Instant Runoff Voting) + candidates are consecutive letters starting at 'A', ignoring case + ballot = ordered list of candidates in descending order of preference + top choice on ballot = first candidate listed algorithm: count top choices while no top choice has a majority of votes compute lowest top choice $drop$ delete $drop$ from all ballots matlab code, given $election$ where each row is a ballot election = lower(election) - 'a' + 1; % convert candidates to consecutive % integers 1.. nc = max(max(election)); % number of candidates remaining nv = size(election,2); % number of voters while 1 % $nvotes(i)$ = #times $i$ is top choice nvotes = full(sparse(1, election(:,1), 1)); [n, win] = max(nvotes); % $win$ has max #votes $n = count(win)$ if n > nv/2, break; end [bogus, drop] = min(nvotes); % $drop$ has min #votes election(election == drop) = []; % delete $drop$ from each ballot end winner = char(win + 'a' - 1); % convert candidate# back to letter