--------------------- CSCE 121H - Fall 2019 Project 8 - Matrices due: Fri Nov 8, 8:00am --------------------- The objective of this assignment is to write a Matrix class for 2D matrices of arbitrary size, and to use it for a) calculation of correlations matrices for the Iris database, and b) rotating geometrical objects (2D points) with rotation matrices. Matrix class design. You will want several constructors, including a constructor that takes dimensions P and Q and allocates space on the heap for P*Q floats, and a copy constructor. You will want to implement setter and getter functions that look like this float Matrix::get(int row,int col); void Matrix::set(int row,int col,float val); You will want to implement a print() function. You will need to be able to generate the transpose of a matrix, where the rows and columns are swapped. Finally, our calculations will rely on matrix multiplication, so you will want to implement a prod() function. Matrix Multiplication. Two matrices, A and B, can be multiplied if the number of columns of A matches the number of rows of B. If the dimensions of A are (rA x cA) and the dimensions of B are (rB x cB), the the dimenions of the product will be (rA x cB). The pseudocode for matrix multiplication is this (using 1-based indexing): for i = 1..rA for j = 1..cB C[i,j] = 0 for k = 1..cA C[i,j] += A[i,k]*B[k,j] (Of course, your C++ program will probably want to use 0-based indexing.) Application 1: Data Science (correlation matrix of Iris attributes) Read in the Iris database. Select only the "iris-setosa" records. Extract the 4 floats. Use them to initialize an Nx4 matrix. Then "center" the data (for the values in each column, subtract the mean of the column). If X is a centered (M x N) data matrix (with M instances as rows and N attributes as columns), then the covariance matrix is defined cov(X) = X^T * X or in other words, the transpose of the matrix times itself. This produces a symmetric NxN matrix that looks like this: S(1,1) S(1,2) S(1,3) ... S(2,1) S(2,2) S(3,1) ... ... S(N,N) Where S(i,j) is the covariance between attributes i and j, and the variances of each attribute are on the diagonals, S(i,i). Finally, the correlation matrix consists of entries cor(i,j) where: cor(i,j) = S(i,j)/sqrt(S(i,i)*S(j,j)) In other words, each entry in the covariance matrix is normalized by dividing by variances on the diagonal. The correlation matrix should have 1's on the diagonal. Here is my output for the iris-setosa subset: covariance matrix: 6.088 4.915 0.791 0.517 4.915 7.114 0.572 0.560 0.791 0.572 1.475 0.279 0.517 0.560 0.279 0.563 correlation matrix: 1.000 0.747 0.264 0.279 0.747 1.000 0.177 0.280 0.264 0.177 1.000 0.306 0.279 0.280 0.306 1.000 See the bottom of this web page for a visual depiction of the correlations among the attributes for different subsets of the Iris database: http://rstudio-pubs-static.s3.amazonaws.com/376329_7bd791576b7240d2b8e6d251d6929aab.html Application 2: Rotating Geometrical Objects (2D Points) Operations on 2D points can be doing using matrices. Derive subclasses for Point2D and Rot2D. A Point2D is a 1x2 matrix that can be initialized with 2 floats, x and y (e.g. coordinates). A Rot2D is a 2x2 rotation matrix. A matrix representing a rotation by theta (in radians) looks like this: cos(theta) -sin(theta) sin(theta) cos(theta) To rotate a point, take the product of the vector (as a 1d matrix) with the rotation matrix. Here are some test cases. Let A B C and D be matrices corresponding to rotations of 30, 60, 90, and -60 degrees. Then A*B should equal C and B*D should equal the identity matrix: A 0.866 -0.500 0.500 0.866 B 0.500 -0.866 0.866 0.500 C -0.000 -1.000 1.000 -0.000 D 0.500 0.866 -0.866 0.500 A*B -0.000 -1.000 1.000 -0.000 B*D 1.000 0.000 0.000 1.000 Use this to calculate the coordinates of one of the hands of a clock on each hour. Define the hand by 3 points: (0,5) A /|\ / | \ / | \ / | \ / | \ (-1,0)=|=(1,0) B C The coordinates at each hour can be computed by rotating by 30 degrees. Here is example output: ---------------- hour=1 2.500 4.330 -0.866 0.500 0.866 -0.500 ---------------- hour=2 4.330 2.500 -0.500 0.866 0.500 -0.866 ---------------- hour=3 5.000 0.000 0.000 1.000 0.000 -1.000 ... ---------------- hour 12 0.000 5.000 -1.000 0.000 1.000 0.000 What to turn-in: ---------------- As usual, check your code into Github. You should make SEPARATE SOURCE FILES for you classes and main programs. You should have a matrix.hpp file with the class interface(s), and matrix.cpp with the implementations of the class methods. Put this all in a distinct directory for Project8. Don't forget check-in your makefile. For the first application, call the executable 'iriscorr', which takes 2 command-line arguments: name of iris data file (I can run your program on my copy of the file, so you don't have to check it in), and the name of the species to select records. For example: > iriscorr iris.data Iris-virginica This will print out the correlation matrix for the 4 attributes for the instances of this species (lines containing Iris-virginica). For the second program, call the executable 'HourlyRotation', which takes a file name on the command-line containing a list of coordinates for an arbitrary number of 2D Points. The program will print out the rotation of the coordinates for each hour, as shown above. > HourlyRotation clockhand.txt Here are the contents of the test file: clockhand.txt: 0.000 5.000 -1.000 0.000 1.000 0.000