Assignment: 04: Due: Language Level: Files To Submit: Practice Exercises
Assignment: 04: Due: Language Level: Files To Submit: Practice Exercises
Assignment: 04: Due: Language Level: Files To Submit: Practice Exercises
Assignment: 04
Due: Tuesday, October 20 at noon (Waterloo time)
Language level: Beginning Student with List Abbreviations
Files to submit: vector.rkt, recognize.rkt
Practice exercises: HtDP 12.2.1, 12.2.2, 12.3.1, 12.3.2, 12.4.1
• This assignment covers concepts up to the end of Module 08. You should change your Racket
language to Beginning Student with List Abbreviations. You may use the (list val val
...) construct to create lists.
• Read the OFFICIAL A04 post on Piazza for answers to frequently asked questions, especially
before you post to Piazza.
• Recall the policy on plagiarism and check all coding you do against the style guide.
• Submit early and often. Once the submission system closes we do not accept further
submissions for marks, so submitting early is always a good idea.
• It is very important that your function names, strings, and symbols match ours. Basic
tests results will catch many, but not necessarily all of these types of errors.
• Unless otherwise stated, all policies from Assignment 03 carry forward.
2. For this question, recall that a vector is an object with a magnitude and a direction. We are
going to be representing a vector as a list of numbers. Note that this means the list for a vector
of degree n would be of length n.
(a) [4% Correctness] The Euclidean Norm of a vector is the square root of the sum
of squares of the vector’s components. So for a vector v composed composed of
x0 , x1 , ..., xn , the Euclidean Norm formula is
. r
ENorm (v) = ∑ xi2
i=0...n
(c) [4% Correctness] ] Let A and B be vectors of the same degree n with a1 , a2 , ..., an and
b1 , b2 , ..., bn being their respective components. The dot product of a and b is:
n
A · B = ∑ (ai )(bi )
i=1
The cosine of the angle between a and b is the dot product of the unit vectors aligned
with vector a and vector b. Define a function cos-between which, given two non zero
vectors a and b of positive length, produces the cosine of the angle between a and b. For
example:
(check-within (cos-between (list 3 4) (list 0 6)) 0.8 0.01)
In order to test cases with inexact numbers, you should use check-within with a tolerance
of 0.01 for your test cases.
Place your code in a file vector.rkt.
clicking in the middle of the page, selecting view source, and then copying the source to a text editor. The code is
very loosely based upon an online example, heavily modified from https://stackoverflow.com/questions/
2368784/draw-on-html5-canvas-using-a-mouse
In your starter code, we include the following data definition for Point:
;; A Point is a (list Num Num) that represents an (x, y) coordinate.
• A single gesture (i.e. a uni-stroke) that creates a diamond shape in a box positioned
from (list 0 0) to (list 200 200) would be represented by the gesture:
(list (list 100 0) (list 200 100) (list 100 200) (list 0 100) (list
100 0))
In your starter code, we include the following data definition for Gesture:
;; A Gesture is a (listof Point).
• The Bounding Box of the above figure would be (list (list 0 0) (list 200 200)),
i.e. a box defined by two points, the top left point located at point (list min-x min-y)
and the bottom right point located at (list max-x max-y).
;; A BoundingBox is a (list Point Point).
;; requires: the coordinate values in the first point are less
;; than the respective values in the second point
Tasks
As noted above, download your starter files. Also, whenever your calculations involve inexact
numbers, always use check-within with tolerance 0.01.
(a) In part a, you will write a series of helper functions. Because these are helper functions,
you should have a purpose, one or two examples, and a contract. You do not need to
fully test the helper functions; just provide one or two examples for each.
i. [2% Correctness] Write two helper functions get-x and get-y which consume a
Point and produce, respectively, the x-coordinate and the y-coordinate of the point.
ii. [2% Correctness] To translate a gesture, you add or subtract a number from each
Point’s x-value and a second number from each Point’s y-value. Write a function,
translate-gesture, that consumes a Gesture and two numbers, an x-offset and
a y-offset, and produces a new gesture such that each Point ((list x y)) in the
original gesture now has value (list (+ x x-offset) (+ y y-offset)) in the
new gesture.
iii. [3% Correctness] To scale a gesture, you multiply each component by a scale value.
The x and y scale values need not be identical. Define a function scale-gesture
that consumes a Gesture and two numbers, x-scale and y-scale, and produces
a new stroke such that each Point ((list x y)) in the original gesture now has
value (list (* x x-scale) (* y y-scale)) in the new gesture. x-scale and
y-scale should be positive, non-zero values.
iv. [3% Correctness] Write a function get-b-box which consumes a non-empty
Gesture and produces the gesture’s BoundingBox, as defined above.
(b) Write the following two functions. Include the full design recipe.
i. [5% Correctness] Write a function gesture-length which consumes a Gesture
and calculates its length. To calculate the length of a list of points, you may find
the Euclidean formula helpful:
q
d(p1 , p2 ) = (x2 − x1 )2 + (y2 − y1 )2
where d is the distance between two points, p1 and p2 , defined by points (x1 , y1 )
and (x2 , y2 ). Gesture length is the sum of the distances between adjacent points in
the gesture. A Gesture of one point has gesture-length → 0. A Gesture of 0
Points can also be defined to have length 0.
;; example
(check-expect (get-points mygest (list 0 0 2 4 4))
(list (list 100 0) (list 100 0) (list 100 200) (list 100 50)
(list 100 50)))
(c) Now, it’s time to write your recognizer. There are three functions which form the core
of your recognizer. The first function is five-sample which, consumes a Gesture of
arbitrary number of points and produces a new Gesture that has exactly 5 points. The
second is normalize-gesture which consumes a Gesture and produces a translated and
scaled Gesture such that the produced Gesture is normalized in position and size. Finally,
the third is five-point-rec which consumes a Gesture and a TemplateLibrary and
produces the symbol whose sample Gesture in the template library is closest to the
Gesture.
i. [5% Correctness] Write a function, five-sample. five-sample consumes a non-
empty Gesture containing any number of points and produces a new Gesture with
exactly five points such that:
• The first point in the new Gesture is equal to the first point in the original
gesture.
• If the original gesture has n points, then the second point in the new gesture is
equal to the (floor (* 0.25 n))-th point in the original gesture.
• Likewise, the third point in the new gesture is (floor (* 0.5 n))-th point in
the original gesture and the fourth point is the (floor (* 0.75 n))-th point.
• The last point in the new Gesture is equal to the last point in the original gesture.
ii. [5% Correctness] Define a function move-and-scale which consumes a Gesture
and two positive numbers, an x-scale, and a y-scale and produces a new gesture
positioned at (0, 0) and scaled in size by factors x-scale and y-scale. Note that
you should first translate the gesture to (0, 0) and then scale!!.
iii. [5% Correctness] Consider the Grafitti alphabet depicted above. For most gestures,
normalizing in width and height causes no particular problem. However, for the ’i
symbol, there is a problem. It is a vertical line.
Given the drawing pad at https://cs.uwaterloo.ca/~lank/canvas.html
iv. [5% Correctness] Define a function geometric-5match which takes two gestures
and produces a number that represents the average distance between points on the
two gestures. Note, again, that for each gesture, one of width or height must be
greater than its corresponding minimum value. It does this as follows:
A. It five-samples the two gestures.
B. It normalizes the two sub-sampled gestures.
C. It calculates the average distance between the points on the two gestures. If the
two gestures, g and g0 are composed of k points, such that the points of g are
pi = (xi , yi ) and the points of g0 are p0i = (xi0 , y0i ) where i = 0 . . . (k − 1), then it
computes:
1
average-distance(g, g0 ) = ∑ d(pi, p0i)
k i=0...k−1
For this part of the question, k equals five.
(d) [5% Correctness] You can test your recognizer at this point by copying points that you
draw in the web app and pasting them into the interactions window in Dr Racket as
follows:
(five-point-rec <paste your stroke here> templates)
However, you may find that your recognizer works very poorly. It may work well on ’a,
’c, ’i, and other simple symbols, but longer symbols cause problems – because it doesn’t
use enough points! five-sample, geometric-5match, and five-point-rec assume 5
points, when more would be (definitely) better.
Define three new function sub-sample, geometric-match, and k-point-rec. These
are identical to the previous variants except that they should also consume a Nat, k,
which defines the number of points you want to sub-sample over during recognition. k
must be greater than 2.
You must include a purpose, examples (preferably two or three per function) and
contracts. You should fully test sub-sample. geometric-match and k-point-rec do
not require a full test suite as these functions are straightforward.
Submit the file recognize.rkt with all functions clearly documented as per the Style
In our above code, if we draw a square and try to recognize on 8 points, the square we draw
will have one point at about the middle of each edge and one point at each corner (ideally).
And, in fact, depending on how fast we draw, it may have more or fewer points at different
locations along the gesture. In contrast, when we sub-sample perfect-square we will get
two points at each corner. This will mean that the Gesture that we draw, even if we use a
ruler or trace a perfect square, may not have a good match to the perfect-square we defined
above because of the way we are sub-sampling points.
There is a way to correct this. Rather than sub-sampling points from our gestures, we can
sub-sample in distance along the gesture. To understand this idea of spatial sampling, if
k = 5 the following three gestures:
Define a function spatial-sub-sample which consumes a gesture and a value k and produces
a new gesture that has k points that are equally spaced along the path of the original gesture.
You should set the parameter k to 5 for initial testing, but then change it to at least 10 for
recognition.
Hint The first point in your newly sub-sampled gesture should be (x0 , y0 ), i.e. the first point
in your original gesture. You should be able to figure out the distance between any two points
in your new sub-sampled stroke using gesture-length and k − 1, call it dss .
Now, think about the distance between the first point and the second point in the original
stroke (call it d0−1 ). If d0−1 > dss , you need to move a fraction of the distance between
dss
x1ss = x0 + (x1 − x0 )
d0−1
dss
y1ss = y0 + (y1 − y0 )
d0−1
where (x1ss , y1ss ) is the second point on your new subsampled gesture. But what happens if
d0−1 > dss ?
Here’s a test to check your work. Let’s say someone draws a perfect square as defined above.
You can run the following example to verify you have created the correct triangle:
(check-within (spatial-sub-sample perfect-square 4)
(list (list 50 100) (list 250 166.66) (list 116.66 300)
(list 50 100)) 0.01)
5. Enhancements
(a) Add another function to your code, n-best which consumes a gesture, a template-library,
and a number, n, and produces an n-best list, i.e. a list of n gestures ordered from closest
to nth-closest match.
(b) Try creating your own set of templates. For example, you can create the digits from
0...9 as unistroke gestures as follows:
The program that you created in question 3 implements a geometric template matcher, or,
in more formal artificial intelligence terms, “an instance-based nearest-neighbor classifier
with a 2-D Euclidean distance function”. The algorithm that you created above is very similar
to an algorithm called the 1$ recognizer created by Jacob Wobbrock of the University of
Washington, Andy Wilson of Microsoft Research, and Yang Li of Google Research. You can
read more about the algorithm that you recreated here:
http://depts.washington.edu/acelab/proj/dollar/index.html
The big difference between your algorithm and the 1$ recognizer is that the 1$ recognizer also
seeks to “pose-align” the bounding box, i.e to rotate the template to find the best alignment
with the gesture. The neat thing about the 1$ recognizer is that it implements a geometric
template recognizer in about 100 lines of code.
More generally, up to this point in CS 135, you’ve learned quite a bit of programming. In fact,
check out this video on support vector machines, a concept from machine learning (fourth
year course).
https://youtu.be/efR1C6CvhmE
You already know most of the basic programming concepts necessary to implement support
vector machine algorithms. A list can be an n-dimensional data set representing a sample that
you want to classify (based on the above video). For example, if you are trying to classify
people, it could be their age (1D), or it could be their age and height (2D), or it could be
their age, height and shoe size (3D), etc. If you have n-features, it’s just a list of n values
(listof Num). You can move this data into higher dimensions by manipulating the data
according to a function that you are given (see, for example, the polynomial kernel in the
video). If you can compute the Euclidean distance between two points in (x, y), then you can
do it in any number of dimensions – it’s the same formula.
Once you understand what concepts like cross-validation, the kernel trick, hyperplanes, etc.
are (and that’s what you’ll study in a fourth year machine learning course), then the actual
process of implementing something like support vector machines relies, in large part, on the
programming concepts you have learned to date in CS 135.
Before you get too excited, this is not to say that we won’t teach you a lot over the next four
years. We will! (At least we hope so). In particular, we will teach you how to take what