MGM.02 2D Matrix Action
 LITERACY

Needs["LinearAlgebra`MatrixManipulation`"];
Needs["Graphics`Colors`"];
Off[General::"spell"];
Off[General::"spell1"];
Off[ParametricPlot3D::"ppcom"];
Off[ParametricPlot::"ppcom"];
Off[Plot::"plnr"];
SetOptions[Limit, Analytic -> True];
$Pre = Chop;

CMView = {2.7, 1.6, 1.2};

Vector Drawer

\(\(\( (*\ \(\(:\)\(Date : \ \ Copyright\ 2001\)\), \ 
      Math\ Everywhere, \ \(\(Inc\)\(.\)\)\ 
*) \)\(
\)\( (*
Original\ Conception\ to\ create\ a\ vector\ drawer\ is\ due\ to\ Bill\ Davis . 
Current\ code\ is\ by\ Bruce\ \(\(Carpenter\)\(.\)\)
*) \)\(
\)\( (*\ \ \(\(\(:\)\(Drawbacks : \ \ Since\ the\ vectors\ are\ drawn\ out\ of\)\)\ 

      \ \ \ \ \ context\), \ 
      the\ shapes\ of\ the\ arrowheads\ are\ only\ 
\ \ \ \ \ correct\ with\ AspectRatio\ set\ to\ \(\(Automatic\)\(.\)\)
*) \)\)\)

BeginPackage["Vector3D`","Graphics`Colors`"];

Axes3D::usage = "Axes3D[a, b] creates a Graphics3D object of cartesian axes with x, y, and z running from -a/3 to a, and with axes labels b units beyond the tips of the axes.  Axes3D[a] is Axes3D[a, a/8].";

Perpend::usage = "Perpend[a] returns a unit vector which is perpendicular to the vector a.";

Arrow::usage = "Arrow[a] produces a 2 or 3 dimensional vector from the origin to a. Arrow[a, Tail -> tail] gives a vector from tail to a.";
	
Vector::usage = "Vector[a, b] gives a 2D or 3D vector from a to b.";

ArrowHead::usage = "ArrowHead[a, vec] produces an arrowhead with its tip placed at the point a, pointing in the direction of the vector vec.";

Tail::usage = "Tail -> point puts the tail of the vector at point.";

Norm::usage = "Norm[vec] returns the Euclidean length of vec.";

Normalize::usage = "Normalize[vec] returns a unit vector in the direction of vec, provided vec is nonzero.";

Aperture::usage = "Aperture is the ratio of the radius of the base to the length of the head of a vector.";

TipSize::usage = "TipSize specifies an absolute size for the inner tip length of the head of a vector.";

TipRatio::usage = "TipRatio is the ratio of the inner length of the arrowhead to the length of the shaft of a vector.";

HeadRatio::usage = "HeadRatio is the ratio of the outer length of the arrowhead to the length of the shaft of a vector.";

HeadSize::usage = "HeadSize specifies an absolute size for the head of a vector.";

ScaleFactor::usage = "ScaleFactor specifies the amount to scale a vector in length and may be either a number or a pure function.";

ZeroVectorPointSize::usage = "ZeroVectorPointSize is the size of the point used to represent a zero vector.";

Options[Vector] = Options[Arrow] = Options[ArrowHead] =
{HeadRatio -> 0.18, TipRatio -> 0.14, Aperture -> 0.3, ScaleFactor -> 1, HeadType -> Polygon, ShaftQ -> True, EdgesQ -> True, VectorColor -> RGBColor[0,0,1], ShaftWidth -> 0.005, ZeroVectorPointSize -> 0.01};
		
Begin["`Private`"];

SetOptions[ParametricPlot,AspectRatio -> Automatic];
SetOptions[Plot,AspectRatio -> Automatic];
SetOptions[Graphics,AspectRatio -> Automatic];

Axes3D[u_,v_] := 
      Graphics3D[{
            {Blue,Line[{{-u/3,0,0},{u,0,0}}]},
                    Text["x",{u + v,0,0}],
            {Blue,Line[{{0,-u/3,0},{0,u,0}}]},
                    Text["y",{0, u + v,0}],
            {Blue,Line[{{0,0,-u/3},{0,0,u}}]},
                    Text["z",{0,0,u + v}]}]; 
Axes3D[u_] := Axes3D[u,u/8];
				
Norm[a_?VectorQ] := N[Sqrt[a.a]];

Normalize[a_?VectorQ] := If[a.a == 0, a, a/Norm[a]];

Perpend[a_?VectorQ] := Normalize[{a[[2]],-a[[1]]}]/;Length[a]==2;

Perpend[a_?VectorQ]:=
    Normalize[If[a[[1]]==0,{1,0,0},{a[[2]],-a[[1]],0}]]/;
      Length[a]==3;
      
Base3D = Table[{Cos[2 k Pi/8.], Sin[2 k Pi/8.]},{k,0,8}]; 

Vector[from_?VectorQ, to_?VectorQ, opts___] := Module[
   {sq, sw, ht, hs, hr, tr, ap, sf, vc, zvps, diff = to - from, tip},
   {sq, sw, ht, hs, hr, ts, tr, ap, sf, vc, zvps} = {ShaftQ, ShaftWidth, HeadType, HeadSize, HeadRatio, TipSize, TipRatio, Aperture, ScaleFactor, VectorColor, ZeroVectorPointSize} /. {opts} /. Options[Vector];
   If[from==to, Return[Graphics[{PointSize[zvps],vc,Point[from]}]]];
   diff = If[NumberQ[N[sf]], sf diff, sf[diff]];
   tip = from + diff;
   If[NumberQ[hs], hr = hs/Norm[diff]; tr = 0.75 hr];
   If[NumberQ[ts], tr = ts/Norm[diff]];
   Graphics[{If[sq,{vc,Thickness[sw],Line[{from,tip - tr diff}]},{}],
      With[{trans = ap hr Norm[diff] Perpend[diff]},
      {vc, Thickness[sw], ht[{tip,
                   (tip - hr diff + trans),
                   (tip - tr diff),
                   (tip - hr diff - trans),tip}]}]}]
] /; Length[from]==Length[to]==2

Vector[from_?VectorQ, to_?VectorQ, opts___] := Module[
   {sq, eq, sw, hs, hr, tr,ap, sf, vc, zvps, diff = to - from, tip},
   {sq, eq, sw, hs, hr, ap, sf, vc, zvps} = {ShaftQ, EdgesQ, ShaftWidth, HeadSize, HeadRatio, Aperture, ScaleFactor, VectorColor, ZeroVectorPointSize} /. {opts} /. Options[Vector];
   If[from==to, Return[Graphics3D[{PointSize[zvps],vc,Point[from]}]]];
   diff = If[NumberQ[N[sf]], sf diff, sf[diff]];
   tip = from + diff;
   If[NumberQ[hs], hr = hs/Norm[diff]];
   tr = hr/2;
   Graphics3D[{If[sq,{vc,Thickness[sw],Line[{from,tip-tr diff}]},{}], If[eq, {}, EdgeForm[]], {SurfaceColor[vc],
      With[{temp = Perpend[diff]},
      Polygon[Append[#,tip]]& /@ Partition[(tip - hr diff + #)&/@((ap hr Norm[diff] Base3D) . {temp,Normalize[Cross[temp,diff]]}),2,1]]}}]
] /; Length[from]==Length[to]==3


Arrow[a_, Tail->b_, opts___] := Vector[b,a+b,opts]

Arrow[a_, opts___] := Vector[Table[0,{Length[a]}],a,opts]

ArrowHead[a_, b_, opts___] := Vector[a-b,a,ShaftQ->False,opts];

End[];

EndPackage[];
Null

Graphics`Colors`GosiaGreen = 
        RGBColor[0,  0.392187,  0];

ThreeAxes[u,v]

ThreeAxes[u_, v_] := 
        Graphics3D[{{Blue, Line[{{-u, 0, 0}, {u, 0, 0}}]}, 
            Text["x", {u + v, 0, 0}], {Blue, 
              Line[{{0, -u, 0}, {0, u, 0}}]}, 
            Text["y", {0, u + v, 0}], {Blue, 
              Line[{{0, 0, 0}, {0, 0, u}}]}, 
            Text["z", {0, 0, u + v}]}];
ThreeAxes[u_] := ThreeAxes[u, (u/8)];
ThreeAxes::"usage" = "ThreeAxes[a,b] makes a standard cartesian \
axis graphics object with x, y, and z running from -a to a, and with axis \
labels b units beyond the tips of the axes.  ThreeAxes[a] is \
ThreeAxes[a,a/8].";

What you need to know when you're away from the machine.

L.1)

Here is a random 2D matrix:

\(\(A = {{N[Random[Real, {\(-2\), 2}], 3], 
            N[Random[Real, {\(-2\), 2}], 3]}, {N[Random[Real, {\(-2\), 2}], 
              3], N[Random[Real, {\(-2\), 2}], 3]}};\)
\)
MatrixForm[A]

The first horizontal row of A is:

row1 = A[[1]]

The second horizontal row of A is:

row2 = A[[2]]

L.2)

Here is a random 2D matrix:

A = {{N[Random[Real, {-2, 2}], 3], 
            N[Random[Real, {-2, 2}], 3]}, {N[Random[Real, {-2, 2}], 
              3], N[Random[Real, {-2, 2}], 3]}};
MatrixForm[A]

The first vertical column of A is:

column1 = Transpose[A][[1]]

The second vertical column of A is:

column2 = Transpose[A][[2]]

L.3)

Here is a  2D matrix A:
         A=(({{2.0, 1.0}, {-1.0, 0.0}})).

A={{2.0, 1.0}, {-1.0, 0.0}};
MatrixForm[
      A]
Null

And here's a random 2D vector X:

X  =  {-1, -1}

When you hit X with A by calculating A.X, you get

A . X

L.4)

Here is a  2D matrix A:
         A=(({{2.7, 0.5}, {-1.4, 1.3}})).

A={{2.7, 0.5}, {-1.4, 1.3}};
MatrixForm[A]

And here's a random 2D vector X:

X  =  {-0.1, -0.5}

A . X

.There are numbers a and b so that you can calculate A . X via
           A . X = a {2.7, -1.4} +  b {0.5, 1.3}.
The correct numbers a and b are

a = X[[1]]
b =  X[[2]]

L.5)

Here is a random 2D matrix:

A=(({{-1.51, -0.345}, {1.15, -1.95}}));

The numbers a, b, c and d that make
          (A^t)=(({{a, b}, {c, d}}))
are

At = Transpose[A];
MatrixForm[%]
a = At[[1, 1]]
b = At[[1, 2]]
c = At[[2, 1]]
d = At[[2, 2]]

L.6)

Given a 2D matrix A, then the horizontal rows of 
         (A^t) (= Transpose[A]) 
 are the vertical columns of A.
 Agree..........<==
 Disagree.......

A = {{N[Random[Real, {-2, 2}], 3], 
            N[Random[Real, {-2, 2}], 3]}, {N[Random[Real, {-2, 2}], 
              3], N[Random[Real, {-2, 2}], 3]}};
MatrixForm[A]
At = Transpose[A];
MatrixForm[%]

L.7)

Given a 2D matrix A, then the vertical columns of 
         (A^t) (= Transpose[A]) 
 are the horizontal rows of A.
 Agree..........<==
 Disagree.......

A = {{N[Random[Real, {-2, 2}], 3], 
            N[Random[Real, {-2, 2}], 3]}, {N[Random[Real, {-2, 2}], 
              3], N[Random[Real, {-2, 2}], 3]}};
MatrixForm[A]
At = Transpose[A];
MatrixForm[%]

L.8)

When you hit a circle with a matrix you get
a) Another circle.
b) An ellipse
c) An ellipse,a line or just one point
d) A hyperbola, ellipse,a line or just one point.
Your response:.............(c)

L.9)

When you hit a rectangle with a matrix you get
a) Another rectangle.
b) An ellipse
c) An ellipse,a line or just one point
d) A parallelogram, a line or just one point.
Your response:.............(d)

L.10)

Here's the unit circle waiting to be hit with a matrix:

xstretch = (1/2) Random[Integer, {1, 5}];
ystretch = (1/6) Random[Integer, {1, 5}];
Clear[x, y, t, hitplotter, hitpointplotter, pointcolor, 
        matrix2D];
{tlow, thigh} = {0, 2 π};
ranger = Max[{xstretch, ystretch, 1.2}];
{x[t_], y[t_]} = {Cos[t], Sin[t]};
hitplotter[matrix2D_] := 
        ParametricPlot[matrix2D . {x[t], y[t]}, {t, tlow, thigh}, 
          PlotStyle -> {{Thickness[0.01], Blue}}, 
          PlotRange -> {{-ranger, ranger}, {-ranger, ranger}}, 
          AxesLabel -> {"x", "y"}, 
          DisplayFunction -> Identity];
Show[hitplotter[IdentityMatrix[2]], PlotLabel -> "Before", 
        DisplayFunction -> $DisplayFunction];

Here's an xystretcher A:

\(A\  = \ DiagonalMatrix[{xstretch, ystretch}]; 
\ MatrixForm[A]\)

Here's what you get when you hit the unit circle A

Show[hitplotter[A], PlotLabel -> "After the hit with A", 
        DisplayFunction -> $DisplayFunction];

Given that the area of the unit circle measures out to π square units, what does the area of the ellipse plotted above measure out to?  (π /2 square units)

L.11)

Go with  this matrix A:

xstretch = (1/2) Random[Integer, {1, 5}];
ystretch = (1/6) Random[Integer, {1, 5}];
Clear[x, y, t, hitplotter, hitpointplotter, pointcolor, 
        matrix2D];
{tlow, thigh} = {0, 2 π};
ranger = Max[{xstretch, ystretch, 1}];
{x[t_], y[t_]} = {Cos[t], Sin[t]};
hitplotter[matrix2D_] := 
        ParametricPlot[matrix2D . {x[t], y[t]}, {t, tlow, thigh}, 
          PlotStyle -> {{Thickness[0.01], Blue}}, 
          PlotRange -> {{-ranger, ranger}, {-ranger, ranger}}, 
          AxesLabel -> {"x", "y"}, 
          DisplayFunction -> Identity];
A = DiagonalMatrix[{xstretch, ystretch}];
MatrixForm[A]

B is a rotation matrix whose hits rotate everything by (π/6) counterclockwise radians.
Here's what you get when you hit the unit circle with B.A:

s  =  Pi/6;
\(\({perpframe[1], 
          perpframe[
            2]}\  = \ 
\ \ \ \ \ \ \ \ \ \ \ N[{{Cos[s], 
              Sin[s]}, {Cos[s\  + \ Pi/2], Sin[s\  + \ Pi/2]}}];\)\)
{a, c}  =  perpframe[1];
{b, d}  =  perpframe[2];
\(\(B\  = \ {{a, b}, {c, d}};\)
\)
\(\ \(Show[hitplotter[B . A], 
        PlotLabel -> "After the hit with B.A", 
\ \ \ \ \ \ \ \ DisplayFunction -> $DisplayFunction];\)\)

Given that the area of the unit circle measures out to π square units, what does the area of the ellipse plotted above measure out to? (π /12 square units)

L.12)

Go with  this matrix A:

xstretch = (1/2) Random[Integer, {1, 5}];
ystretch = (1/6) Random[Integer, {1, 5}];
Clear[x, y, t, hitplotter, hitpointplotter, pointcolor, 
        matrix2D];
{tlow, thigh} = {0, 2 π};
ranger = Max[{xstretch, ystretch, 1}];
{x[t_], y[t_]} = {Cos[t], Sin[t]};
pointcolor[t_] = 
        RGBColor[0.5 (Cos[t] + 1), 0.5 (Sin[t] + 1), 
          0];
jump = ((thigh - tlow)/8);
hitplotter[matrix2D_] := 
        ParametricPlot[matrix2D . {x[t], y[t]}, {t, tlow, thigh}, 
          PlotStyle -> {{Thickness[0.01], Blue}}, 
          PlotRange -> {{-ranger, ranger}, {-ranger, ranger}}, 
          AxesLabel -> {"x", "y"}, 
          DisplayFunction -> Identity];
hitpointplotter[matrix2D_] := 
        Table[Graphics[{pointcolor[t], PointSize[0.035], 
              Point[matrix2D . {x[t], y[t]}]}], {t, tlow, thigh - jump, 
            jump}];
A = DiagonalMatrix[{xstretch, ystretch}];
MatrixForm[A]

B is the rotation matrix whose hits rotate everything by (π/4) counterclockwise radians.
Here's what you get when you hit the unit circle with A.B:

s  =  Pi/4;
\(\({perpframe[1], 
          perpframe[
            2]}\  = \ 
\ \ \ \ \ \ \ \ \ \ \ N[{{Cos[s], 
              Sin[s]}, {Cos[s\  + \ Pi/2], Sin[s\  + \ Pi/2]}}];\)\)
{a, c}  =  perpframe[1];
{b, d}  =  perpframe[2];
\(\(B\  = \ {{a, b}, {c, d}};\)
\)
\(\ \(Show[hitplotter[A . B], 
        PlotLabel -> "After the hit with A.B", 
\ \ \ \ \ \ \ \ DisplayFunction -> $DisplayFunction];\)\)

Given that the area of the unit circle measures out to π square units, what does the area of the ellipse plotted above measure out to? (π /3 square units)
Why is this ellipse not tilted? Because it was first rotated and then stretched, whereas above it was first stretched and then 
rotated.

L.13)

For a given 2D matrix A, the inverse matrix  (A^(-1))is the matrix you hit with to undo whatever a hit with A did.
For instance, when you hit with this stretcher matrix A:

{xstretch, ystretch} = {Random[Integer, {4, 6}], 
          Random[Integer, {1, 3}]};
stretcher = DiagonalMatrix[{xstretch, ystretch}];
MatrixForm[stretcher]

A={{4, 0}, {0, 1}};
MatrixForm[
      A]

The numbers a, b, c and d that make
          (A^(-1))=(({{a, b}, {c, d}}))
are
           a = 1/4	 b = 0
           c = 0  		 d = 1

MatrixForm[Inverse[A]]

L.14)

Hits with the following matrix rotate everything about {0,0} by s counterclockwise radians:

Clear[s, rotator, perpframe];
{perpframe[1], perpframe[2]} = 
        N[{{Cos[s], Sin[s]}, {Cos[s + (π/2)], 
              Sin[s + (π/2)]}}];
{a, c} = perpframe[1];
{b, d} = perpframe[2];
rotator[s_] = {{a, b}, {c, d}};
MatrixForm[rotator[s]]

rotaror={{Cos[s], -1.  Sin[s]}, {Sin[s], Cos[s]}};
MatrixForm[rotaror]

Take the trasnpose.  The entries a, b, c and d that make
          rotator[s]^(-1)=(({{a, b}, {c, d}}))
are
           a = Cos[s]		  b = Sin[s]
           c = -1.Sin[s]		  d = Cos[s]

MatrixForm[Inverse[rotaror]] // Simplify

L.15)

Remembering that 
         shear[a] . shear[b] = shear[a + b]
and that 
         shear[0] =   (({{1, 0}, {0, 1}})),
come up with the b that makes
          shear[a]^(-1)  =  shear[b].

From the last relation we have:
shear[a] shear[a]^(-1)  =  shear[a] shear[b]
I = shear[0] =  shear[a] shear[b]
shear[0] =  shear[a + b]
b = -a

L.16)

Given two invertible matrices A and B, the inverse of A.B is
a)  (A^(-1)). (B^(-1))
b)  (B^(-1)). (A^(-1)).
My choice is (b)

L.17)

Here's the square with corners at {0,0}, {1,0}, {1,1} and {0,1} with lots of points inside:

jump = 0.1;
Clear[parallelogramplotter, basepoint, side1, side2, 
        pointcolor];
ranger = 2.5;
pointcolor[r_, t_] = 
        RGBColor[0.5 (Cos[π t] + 1), 0.5 (Cos[π r] + 1), 
          0.5 (Sin[π t] + 1)];
parallelogramplotter[basepoint_, side1_, 
          side2_] := {Table[
            Graphics[{PointSize[0.025], pointcolor[r, t], 
                Point[basepoint + t side1 + r side2]}], {t, 0, 1, 
              jump}, {r, 0, 1, jump}], 
          Graphics[{Thickness[0.01], Blue, 
              Line[{basepoint, basepoint + side1, basepoint + side1 + side2, 
                  basepoint + side2, basepoint}]}]};
basepoint = {0, 0};
squareside1 = {1, 0};
squareside2 = {0, 1};
Show[parallelogramplotter[basepoint, squareside1, squareside2], 
        PlotRange -> {{-ranger, ranger}, {-ranger, ranger}}, 
        Axes -> True, 
        AxesLabel -> {"x", "y"}];

Here's a random 2D matrix A:

A = 
      N[{{Random[Real, {0.4, 1.2}], -Random[Real, {0.4, 1.5}]}, {
            Random[Real, {0.4, 1.2}], Random[Real, {0.5, 1.5}]}}, 3]; MatrixForm[A]

Here's what you get when you hit this square and the points inside with A:

basepoint = {0, 0};
squareside1 = {1, 0};
squareside2 = {0, 1};
hitsquare = 
        Show[parallelogramplotter[A . basepoint, A . squareside1, 
            A . squareside2], 
          PlotRange -> {{-ranger, ranger}, {-ranger, ranger}}, 
          Axes -> True, 
          AxesLabel -> {"x", "y"}];

Look at A again:

MatrixForm[A]

Use what you see to identify the vectors that define the parallelogram. The first column of matrix A (0.826,1.18) is perpframe[1] and the
second column of A (-0.443,1.1) is perpframe[2]. These two vectors define the parallelogram.

L.18)

Here is a cleared 2D matrix A:

Clear[a, b, c, d];
A = {{a, b}, {c, d}};
MatrixForm[A]

Here's another 2D matrix B:

\(\(B = 
      \ {{Random[Integer, {1, 4}], Random[Integer, {1, 4}]}, 

        		\ \ \ {Random[Integer, {1, 4}], Random[Integer, {1, 4}]}}; 

    MatrixForm[B]
			\)\)

B = {{4, 2}, {3, 2}}

When you calculate A.B, you get another 2D matrix 
                (({{x, y}, {z, w}})).
 Your job is to write down what the values of x,y,z and w are.
 x = .....................................................
 y = .....................................................
 z = .....................................................
 w = .....................................................

MatrixForm[A . B]

L.19)

Here are calculations of A.B and B.A for two random 2D matrices A and B:

A = {{Random[Real, {-8, 8}], Random[Real, {-8, 8}]}, {
          Random[Real, {-8, 8}], Random[Real, {-8, 8}]}}; B = {{Random[Real, {-8, 8}], Random[Real, {-8, 8}]}, {
          Random[Real, {-8, 8}], Random[Real, {-8, 8}]}}; MatrixForm[A . B]MatrixForm[B . A]

Does the outcome surprise you? No.
Why or why not? Because in general A.B ≠ B.A