{ "cells": [ { "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": null, "metadata": { "collapsed": false }, "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", " 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]])\n", " ax.plot([polygon[i+1][0], polygon[0][0]], [polygon[i+1][1], polygon[0][1]])\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()\n", "\n", "Re_y = np.array([[-1, 0], [0,1]])" ] }, { "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": null, "metadata": { "collapsed": false }, "outputs": [], "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": { "collapsed": false }, "source": [ "Now, let's rotate the square by some arbitrary angle, say, 60 degrees." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "#R is a \"rotation matrix\".\n", "angle = np.pi/3 # 60 degrees in radians\n", "R = np.array([[np.cos(angle), -np.sin(angle)], [np.sin(angle), np.cos(angle)]])\n", "rotated_square = transform_the_polygon(unit_square, R)\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": false }, "outputs": [], "source": [ "reflected_square = transform_the_polygon(unit_square, Re_y)\n", "plot_the_polygon(reflected_square)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#Part 2: Commutativity of Transformations\n" ] }, { "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": false }, "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)], [np.sin(rotation_angle), np.cos(rotation_angle)]])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "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": false }, "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": false }, "outputs": [], "source": [ "#S is a \"scalar matrix\".\n", "S = np.array([[2, 0], [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 3", "language": "python", "name": "python3" }, "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.4.5" } }, "nbformat": 4, "nbformat_minor": 0 }