Matrix Multiplication
matrixmultiplication.xyz
matrixmultiplication.xyz
/edit: I just noticed the OP is built by andrestaltz with Cycle.js. Cycle is a really nice reactive programming js framework that is very great to work with.
If you put matrix B over (or under) the Result matrix, the relationship between rows in A, columns in B, and elements in Result would be even more directly visualized.
You could even show the intermediate products to be summed as a diagonal between matrices A and B as you step through them. Also with direct visual alignment.
This is the way I multiply matrices on paper - it's a lot easier to keep track of the current row and column that way.
Isn’t that pretty much the same as the dot-product explanation?
Is that what you had in mind by the dot-product explanation? To me, the dot product explanation is that in Ax = b, b1 = <row1 of A> dot x, b2 = <row2 of A> dot x, and b3 = <row3 of A> dot x.
Of course these (and all other valid) interpretations of matrix multiplication are "the same", but this is less geometrically intuitive to me.
I always start with Ax, which is just a linear combination of the columns, like the first figure here https://eli.thegreenplace.net/2015/visualizing-matrix-multip...
For those who want to make their own cheat sheet:
Matrix $\times$ vector is linear combination of the columns:
\begin{align}
Ax &= \begin{pmatrix}
a_{1,1} & a_{1,2}\\
a_{2,1} & a_{2,2}\\
a_{3,1} & a_{3,2}
\end{pmatrix}
\begin{pmatrix} x_1\\x_2
\end{pmatrix}\\&= x_1\begin{pmatrix}
a_{1,1}\\
a_{2,1}\\
a_{3,1}\\
\end{pmatrix}
+
x_2\begin{pmatrix}
a_{1,2}\\
a_{2,2}\\
a_{3,2}\\
\end{pmatrix}
\end{align}
Intuitively, this example maps a point in $\mathbb{R}^2$ to $\mathbb{R}^3$
Another way to see $Ax$: Columns of $A$ form a basis, and $x$ is a coordinate vector in that basis.
Maybe what's missing is a slick animation...
Slick animations, but it needs to be slower and simpler.
In my experience, math is taught by people who are good understanding abstract concepts. It's hard for me to pick up abstract concepts, so a lot of traditional math education / exercises / tutorials work poorly for me.
- Learn how to multiply a matrix M by a column vector v.
- Generalise that by noticing that M[u|v|...] = [Mu|Mv|...].
That's matrix multiplication.
Yours is an important one.
Matrix Multiplication - https://news.ycombinator.com/item?id=24141472 - Aug 2020 (1 comment)
Matrix Multiplication - https://news.ycombinator.com/item?id=13036386 - Nov 2016 (131 comments)
Matrix Multiplication - https://news.ycombinator.com/item?id=13033725 - Nov 2016 (2 comments)
Posts like this seem to get upvoted on HN just because "oooh, a pretty animation" and/or they struggled with college math "See? This is how they should've taught it! Pictures are better than lectures!"
IOW, what matrix multiplication tries to achieve by doing this manipulation which looks like rotation visually? Why not doing it w/o rotation instead (with the precondition that numbers of columns in two matrices should be equal, instead of column vs row)?
The operation you're describing is nevertheless equal to A^T B. In other words, it can be expressed using a combination of matrix multiplication and matrix transpose. I don't see what it could be used for, though.
Look: consider two functions, f(x, y) = (x + 2y, 3x + 4y), and g(x, y) = (-x + 3y, 4x - y). What's f(g(x, y))? Well, let's work it out, it's simple algebra:
f(g(x, y)) = f(-x+3y, 4x-y) = ((-x+3y)+2(4x-y), 3(-x+3y) + 4(4x-y)) = (-x + 3y + 8x - 2y, -3x + 9y + 16x - 4y) = (7x + y, 13x + 5y).
Whew, that was some hassle to keep track of everything. Now, here's what mathematicians typically do instead: they introduce matrices to make it much easier to keep track of the operations:
Let e_0 = (1, 0), and e_1 = (0, 1). Then f(e_0) = f(1, 0) = (1, 3) = e_0 + 3 e_1, and f(e_1) = f(0, 1) = (2, 4) = 2 e_0 + 4 e_1. Thus, mathematicians would write that f in basis e_0, e_1 is represented by the matrix
[1 2] [3 4]
so that when you multiply it by the (coulmn) vector [x, y], you get
[x]
* [y]
[1 2][x + 2y]
[3 4][3x + 4y]
Similarly, g(e_0) = (-1, 4) = -e_0 + 4e_1, g(e_1) = (3, -1) = 3e_0 - e_1, so it's represented by the matrix:[-1 3] [ 4 -1]
Now, let's multiply matrix of f by matrix of g:
[-1 3]
* [ 4 -1]
[1 2][-1*1+2*4 3*1-1*2] = [7 1]
[3 4][-1*3+4*4 3*3-1*4] [13 5]
and when we multiply the resulting matrix by column vector [x, y]: [x]
* [y]
[7 1][7x + y]
[13 5][13x + 5]
So, what did we get was in fact our original calculation of f(g(x, y)) = (7x + y, 13x + 5y).The conclusion here is that matrix multiplication is what the function composition forces it to be.
My early understanding after reading your responses and the wiki article, it that's useful if we have some input data (vector), which then undergoes some sequential manipulation by several functions, and we want to know the result in one step, instead of many?
The longer answer is that matrix multiplication is essentially 2 different operations. Consider the linear funtions:
f :: R3 -> R3
h :: R3 -> R3
As well as the point x :: R3
If we fix a set a basis vectors, we can represent f and h as 3x3 matrices, and x as a 3x1 matrix.The product [f][x]=[f(x)] then represents the result of a function application, while [f][h] = [f∘h] represents function composition.
For the function application portion, there is no problem with your proposal. We simply represent the point as a 1x3 vector instead of a a 3x1 vector (or similarly transpose the convention for representing a function as a matrix).
The problem comes with the function composition use-case. For your proposal to work, we would need to transpose only one of the two matrices, which means that the matrix representation of a function is determined both by the basis vectors, and a transposition parity bit. With multiplication as composition only making sense when the transposition parities don't match.
https://en.m.wikipedia.org/wiki/Convolution_theorem
> the convolution theorem states that under suitable conditions the Fourier transform of a convolution of two functions (or signals) is the pointwise product of their Fourier transforms.
https://en.wikipedia.org/wiki/Sch%C3%B6nhage%E2%80%93Strasse...
But my question (which wasn't about asymptotic complexity) stands: can we think about matrix multiplication as a convolution? If so, we can do pointwise multiplication sandwiched between Fourier transforms -- I don't expect it to be fast, I just expect it to be possible.
...for general matrices. Fourier transforms do indeed diagonalize circulant matrices[1], making their multiplications O(2 n log n + n) -> O(n log n).
Hmm. I'm not convinced yet...
The "convolution" of two functions M and N -- let's notate it as M <> N, because ASCII -- will itself be a function, where for each index `i` we consider indices of M and N that sum to `i`. At each index `i`, we "sum" the "products" of M and N at indices summing to `i`; so if `i` is 2 (and we start indexing at 0, for sanity), we have `(M <> N)(2) = M(0)*N(2) + M(1)*N(1) + M(2)*N(0)`.
https://betterexplained.com/articles/intuitive-convolution/
Now consider a matrix multiplication M * N. We can think of M as an array of row vectors, and N an array of column vectors; in both cases, they're functions from (a subset of) the naturals to matrix elements.
To instantiate convolution on our matrices, we can take multiplication as dot-product, and addition as a formal (uninterpreted) sum. (So, technically, we need to lift the elements of our input matrices to these sums as well, but there's a canonical way to do this.) Then M <> N is an array of formal sums of vectors; each formal sum gives an anti-diagonal band of elements in the matrix product, and the whole array runs along the main diagonal.
There are almost certainly faults in the remaining details -- for example, it's not really clear that this is associative yet, due to the formal sum -- but this seems to cast matrix multiplication in the shape of a convolution.
Why simply don't go procedural and skip the matrix representation altogether? Using matrixes in physics calculations, for example, feels like disassociating the intuitiveness of the physics for the sake of the matrix calculation tools. When I look at a matrix of values I don't see anything.
a b c d
a 1 0 1 0
b 1 1 0 0
c 0 0 1 1
d 1 0 0 1
Written another way, the above graph has these directed edges: a -> a, a -> c
b -> a, b -> b
c -> c, c -> d
d -> a, d -> d
In a Markov chain, the possible state transitions (graph edges) are represented in the same way, but instead of a 1 or 0 (connects or doesn't connect) a probability is assigned to each possible transition.https://en.wikipedia.org/wiki/Examples_of_Markov_chains - Several examples with a mix of prose, graphical presentation, and the matrix representation.
In some cases making a matrix in physics is a quite sterile representation, like you suggest, like plugging in the numbers in an otherwise generally stated question. The matrix values depend on choices of coordinate system and everything, quite inelegant in that way.
Why practically use matrixes on the computer? It's efficient to compute in blocks instead of one by one.
Suppose you have two linear functions:
f :: R3 -> R3
h :: R3 -> R2
and a point: x :: R3
The first problem you have if you want to work with these functions is how to represent them. As it turns out, assuming you have a set of basis vectors, any linear function Rn -> Rm can be represented by exactly n * m real numbers. Further, if we arrange these numbers in a grid it is easy to fill in the grid if you know how the function acts on the basis vectors, and it is easy to read off how the function acts on the basis vectors from the grid.Similarly, a point in Rn can be represented by exactly n real numbers. Again, this representation depends on a choice of basis vectors.
For simplicity, let [?] represent the matrix representation of ?.
The second problem you want to tackle is how to compute function application y = f(x). Given the representations defined above, y is the point in R3 that is represented by the result of the matrix multiplication [f][x].
The third problem you want to solve is how to compute the function composition g = f∘h. Again, g is the function given by the matrix representation [g] = [f][h]
Unfortunately, engineers insist on designing devices which are neither perfect spheres nor perfectly flat planes (ridiculous!), and they might only have equations to describe how properties change in time or space. In this case, it can be easier to discretize the thing into a mesh, and use a matrix to describe how the physical phenomena at the points of that mesh relate to each other.
[[1,1],[1,-1]] @ [[x,y]] = [[2,3]]
@ is of course matrix multiplication but what it does does not really matter. Only that it performs some "function". But is this notation helpful? It turns out this function is really useful to answer other questions. From here, we can go on to show very interesting things like how to find the answers for x and y. It turns out that it has a recursive process similar to when solving it by hand (isolate one of the variables, plug into another equation, isolate another, ...) and part of this recursive process has a pattern we will call the determinant. Turns out that when the determinant is 0, funny things happen. The point is that it all started by trying to solve these equations which are interesting from a mathematical point of view but also show up naturally in many business applications. See Leontief's Model [1] for how this could be useful. Consumption equals production and bills being linear (#apples * $apples + #bananas * $bananas + ... = total spent) make linear systems arise naturally. All the things that come later, eigenvalues, SVD, etc. were all discovered as mathematical curiosities and later realized that they had very useful applications such as solving OLS and compression.
Optimizing for simplicity of procedure can make computers quite happy, and reduce errors by humans (they can still make arithmetic errors, but will make fewer errors of procedure)... and also lets you build reusable optimizations to that simple procedure (math theory about matricies) that can then be shared across multiple domains (a lot of work has been put into optimizing e.g. sparse matricies.)
Figuring out an intuitive understanding of matrix values can be done, although it depends on the problem domain you're applying them to. My problem domain of choice is computer graphics. Rotating a vertex of a triangle can be done using a 3x3 matrix:
[ ux_x, ux_y, ux_z ]
[v_x, v_y, v_z] [ uy_x, uy_y, uy_z ] = [o_x, o_y, o_z]
[ uz_x, uz_y, uz_z ]
v_{...} is an input vertex position
o_{...} is an output vertex position
Can this be visualized? Yes! ux_{...} is where a unit x vector (1,0,0) will end up at
uy_{...} is where a unit y vector (0,1,0) will end up at
uz_{...} is where a unit z vector (0,0,1) will end up at
What if I want to add an offset/position to all the verticies? Well, we don't want the multiplication bits then, so we need a 1 to have a noop multiply: [v_x, v_y, v_z, 1.0]
And then we can use that 1.0 to add a new row to our matrix which will get added to the final output: [ ux_x, ux_y, ux_z ]
[ uy_x, uy_y, uy_z ]
[ uz_x, uz_y, uz_z ]
[ t_x, t_y, t_z ]
Bam, we added [t_x, t_y, t_z] to [o_x, o_y, o_z]. t_{...} is then easily visualized as the new position where verticies were at the origin (0,0,0) will end up at, and u{...} becomes the position of the unit vectors relative to that origin, instead of in absolute coordinates.EDIT: Adding a 4th column becomes useful for projection matricies in a way I don't have a super great intuition for... but it also lets us multiply transformation matricies together. This is quite useful: We can simplify "transform this vertex from the original mesh, into it's position relative to this larger model, into it's position in worldspace, into it's position relative to this camera" to "multiply against this single 4x4 matrix that we constructed using matrix multiplication."
1) How you do it by hand, which this page offers a very handy and easy to remember recipe for.
2) And why you do it in such a weird and not very multiplicative way.
Matrix multiplication is so arbitrary when first introduced. Every time I see it work for some real life application I am surprised how mathematicians came up with it in the first place.
(A B)_ij = A_ik B_kj.
The underlying data structure made all the difference, but I still wasn't quite happy with how I approached it, with a bunch of nested loops and iterators.
At the very least each result and RC should be in a different colour.