{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# EE16A Discussion 3B" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Visualizing Matrices as Operations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This exercise is going to help you visualize matrices as operations. For example, when we multiply a vector by a rotation matrix, we will see it \"rotate\" in the true sense here. Similarly, when we multiply a matrix by a scalar matrix, we will see it \"scale\". The way we will see this is by applying the operation to all the vertices of a polygon and seeing how the polygon changes.\n", "Let's first do the necessary imports and define some useful functions to do this." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "%matplotlib inline\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "\"\"\"Function that takes the vertices of a polygon and applies a matrix \"transformation\" to each of them, effectively\n", "\"transforming\" the polygon.\"\"\"\n", "def transform_the_polygon(polygon, T):\n", " \n", " transformed_polygon = []\n", " for point in polygon:\n", " transformed_point = np.dot(T, point)\n", " transformed_polygon.append(transformed_point)\n", " return transformed_polygon\n", "\n", "\"\"\"Function that plots a polygon in the x-y plane, given its vertices as x-y coordinates. The plot is defined in terms\n", "of line segments connecting all adjacent vertices of the polygon.\"\"\"\n", "def plot_the_polygon(polygon):\n", " fig = plt.figure(figsize=(5,5))\n", " ax = fig.add_subplot(111, xlim = [-4, 4], ylim = [-4, 4])\n", " for i in range(len(polygon) - 1):\n", " ax.plot([polygon[i][0], polygon[i+1][0]],\n", " [polygon[i][1], polygon[i+1][1]], linewidth=4)\n", " ax.plot([polygon[i+1][0], polygon[0][0]], [polygon[i+1][1], polygon[0][1]], linewidth=4)\n", " ax.grid(True)\n", " ax.axhline(y=0, color='k', linestyle = '--', linewidth = 2)\n", " ax.axvline(x=0, color='k', linestyle = '--', linewidth = 2)\n", " #plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we define our starting polygon, a square whose side is of length 1. Let's see what the square looks like." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\nAAAAAElFTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "unit_square = [np.array([0,0]), np.array([1,0]), np.array([1,1]), np.array([0,1])]\n", "plot_the_polygon(unit_square)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Part 1: Rotation Matrices as Rotations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Code for the following sections:\n", "\n", "(a) Given T1 (15 degree rotation) and T2 (30 degree rotation), describe how to rotate the unit square by 45 degrees. How about 60 degrees?\n", "\n", "(b) Try to rotate the unit squre by 60 degrees using only one matrix." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "ename": "SyntaxError", "evalue": "invalid syntax (, line 15)", "output_type": "error", "traceback": [ "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m15\u001b[0m\n\u001b[0;31m T3 = ?????\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" ] } ], "source": [ "# R is a \"rotation matrix.\"\n", "# Example:\n", "# angle = np.pi/2 # 90 degrees in radians\n", "# R = np.array([[np.cos(angle), -np.sin(angle)],\n", "# [np.sin(angle), np.cos(angle)]])\n", "\n", "angle1 = np.pi/12 # 15 degrees in radians\n", "T1 = np.array([[np.cos(angle1), -np.sin(angle1)],\n", " [np.sin(angle1), np.cos(angle1)]])\n", "\n", "angle2 = np.pi/6 # 30 degrees in radians\n", "T2 = np.array([[np.cos(angle2), -np.sin(angle2)],\n", " [np.sin(angle2), np.cos(angle2)]])\n", "\n", "T3 = ?????\n", "\n", "rotated_square = transform_the_polygon(unit_square, T3)\n", "plot_the_polygon(rotated_square)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And finally, we can \"reflect\" the square about the y-axis:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "Re_y = np.array([[-1, 0], [0,1]])\n", "reflected_square = transform_the_polygon(unit_square, Re_y)\n", "plot_the_polygon(reflected_square)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Part 2: Commutativity of Operations" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "The next natural question to ask is the following: Does the *order* in which you apply these operations matter?\n", "\n", "a) Let's see what happens to the unit square when we rotate the matrix by 60 degrees, and then reflect it along the y-axis." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# As the name indicates, R_60 rotates the matrix by 60 degrees.\n", "rotation_angle = np.pi/3 # 60 degrees in radians\n", "R_60 = np.array([[np.cos(rotation_angle), -np.sin(rotation_angle)],\n", " [np.sin(rotation_angle), np.cos(rotation_angle)]])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "reflected_after_rotated_square = transform_the_polygon(unit_square, R_60)\n", "reflected_after_rotated_square = transform_the_polygon(reflected_after_rotated_square, Re_y)\n", "plot_the_polygon(reflected_after_rotated_square)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "b) Now, let's reflect *before* rotating." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "rotated_after_reflected_square = transform_the_polygon(unit_square, Re_y)\n", "rotated_after_reflected_square = transform_the_polygon(rotated_after_reflected_square, R_60)\n", "plot_the_polygon(rotated_after_reflected_square)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also scale the square: " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# S is a \"scalar matrix.\"\n", "S = np.array([[2, 0],\n", " [0, 2]])\n", "scaled_square = transform_the_polygon(unit_square, S)\n", "plot_the_polygon(scaled_square)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python [Root]", "language": "python", "name": "Python [Root]" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2" } }, "nbformat": 4, "nbformat_minor": 1 }