Find the inverse of a 3 by 3 matrix

22

2

Challenge

Given nine numbers, a, b, c, d, e, f, g, h, i, as input which correspond to the square matrix:

$$\mathbf{M} = \begin{pmatrix}a& b& c\\ d& e& f\\ g& h& i\end{pmatrix}$$

Find the inverse of the matrix, \$\mathbf{M}^{-1}\$ and output its components.

Inverse Matrix

The inverse of a matrix 3 by 3 obeys the following equation:

$$\mathbf{MM}^{-1} = \mathbf{M}^{-1}\mathbf{M} = \mathbf{I} = \begin{pmatrix}1&0&0\\0&1&0\\0&0&1\end{pmatrix}$$

And can be calculated as:

$$\mathbf{M}^{-1} = \frac{1}{\det(\mathbf{M})}\mathbf{C}^T$$

Where \$\mathbf{C}\$ is the matrix of cofactors:

$$\mathbf{C}=\begin{pmatrix}ei-fh&fg-di&dh-eg\\ch-bi&ai-cg&bg-ah\\bf-ce&cd-af&ae-bd\end{pmatrix}$$

And \$\mathbf{C}^T\$ is the transpose of \$\mathbf{C}\$:

$$\mathbf{C}^T = \begin{pmatrix}ei-fh&ch-bi&bf-ce\\fg-di&ai-cg&cd-af\\dh-eg&bg-ah&ae-bd\end{pmatrix}$$

And \$\det(\mathbf{M})\$ is the determinant of \$\mathbf{M}\$:

$$\det(\mathbf{M}) = a(ei-fh)-b(di-fg)+c(dh-eg)$$

Worked Example

For example, let's say the input is 0, -3, -2, 1, -4, -2, -3, 4, 1. This corresponds to the matrix:

$$\mathbf{M} = \begin{pmatrix}0&-3&-2\\1&-4&-2\\-3&4&1\end{pmatrix}$$

Firstly, let's calculate what's known as the determinant using the formula above:

$$\det(\mathbf{M}) = 0(-4\times1-(-2)\times4) - (-3)(1\times1-(-2)\times-3) + (-2)(1\times4-(-4)\times-3) = 1$$

Next let's calculate the matrix of cofactors:

$$\mathbf{C} = \begin{pmatrix}-4\times1-(-2)\times4& -(1\times1-(-2)\times-3)&1\times4-(-4)\times-3\\-(-3\times1-(-2)\times4)&0\times1-(-2)\times-3&-(0\times4-(-3)\times-3)\\-3\times-2-(-2)\times-4&-(0\times-2-(-2)\times1)&0\times-4-(-3)\times1\end{pmatrix}$$

$$= \begin{pmatrix}4&5&-8\\-5&-6&9\\-2&-2&3\end{pmatrix}$$

We then need to transpose \$\mathbf{C}\$ (flip the rows and columns) to get \$\mathbf{C}^T\$:

$$\mathbf{C}^T = \begin{pmatrix}4&-5&2\\5&-6&-2\\-8&9&3\end{pmatrix}$$

Finally, we can find the inverse as:

$$\mathbf{M}^{-1} = \frac{1}{\det(\mathbf{M})}\mathbf{C}^T = \frac{1}{1}\begin{pmatrix}4&-5&2\\5&-6&-2\\-8&9&3\end{pmatrix}=\begin{pmatrix}4&-5&2\\5&-6&-2\\-8&9&3\end{pmatrix}$$

So the output would be 4, -5, -2, 5, -6, -2, -8, 9, 3.

Rules

  • The given matrix will always have an inverse (i.e. non-singular). The matrix may be self-inverse

  • The given matrix will always be a 3 by 3 matrix with 9 integers

  • The numbers in the input will always be integers in the range \$-1000 \leq n \leq 1000\$

  • Non-integer components of the matrix may be given as a decimal or a fraction

Examples

Input > Output
1, 0, 0, 0, 1, 0, 0, 0, 1 > 1, 0, 0, 0, 1, 0, 0, 0, 1
0, -3, -2, 1, -4, -2, -3, 4, 1 > 4, -5, -2, 5, -6, -2, -8, 9, 3
1, 2, 3, 3, 1, 2, 2, 1, 3 > -1/6, 1/2, -1/6, 5/6, 1/2, -7/6, -1/6, -1/2, 5/6
7, 9, 4, 2, 7, 9, 3, 4, 5 > -1/94, -29/94, 53/94, 17/94, 23/94, -55/94, -13/94, -1/94, 31/94

Winning

The shortest code in bytes wins.

Beta Decay

Posted 2018-07-18T16:04:39.733

Reputation: 21 478

Answers

18

MATL, 54 bytes

th3LZ)t,3:q&XdpswP]w-lw/GtY*tXdsGXdsUw-IXy*2/+GtXds*-*

Try it online!

Just to keep it interesting, doesn't use the inbuilt matrix division or determinant functions to do it.

Instead, computes the determinant using the Rule of Sarrus.

Rule of Sarrus demonstration

And the adjugate (transposed cofactor matrix) using Cayley–Hamilton formula.

$$ {\displaystyle \operatorname {adj} (\mathbf {A} )={\frac {1}{2}}\left((\operatorname {tr} \mathbf {A} )^{2}-\operatorname {tr} \mathbf {A} ^{2}\right)\mathbf {I} _{3}-\mathbf {A} \operatorname {tr} \mathbf {A} +\mathbf {A} ^{2}.} $$

Commented code:

% Finding determinant
th    % concatenate the matrix to itself sideways
3LZ)  % chop off the last column (since the Rule of Sarrus doesn't need it)
t     % duplicate this matrix (say S)
,     % do this twice:
  3:q&Xd  % get the first three diagonals of S
  ps      % multiply each diagonal's values and add the results
  wP      % switch and flip the matrix (to get the popposing diagonals next time)
]w    % close loop, switch to have correct order of sums
-     % subtract - we now have the determinant
lw/   % invert that

% Finding adjugate using Cayley–Hamilton formula
GtY*  % A^2 term (last term of the formula)
tXds  % trace(A^2) for term 1 of formula
GXdsU % (trace(A))^2 for term1 of formula
w-    % (trace(A))^2 - trace(A^2)
IXy*  % multiply that by the identity matrix
2/    % divide that by 2 - term 1 complete
+
GtXds* % A*trA for term 2 of formula
-      % subtract to get adj(A)

*      % multiply by the inverse of determinant we found earlier
       % implicit output

We could go even more insane purer by replacing the matrix multiplication GtY* done for \$ A^2 \$, with something like 3:"Gt!@qYS*!s] 3$v t&v 3:K-&Xd (Try it on MATL Online).

The more direct and obvious way:

4 bytes

-1Y^

Try it online!

(-1 byte thanks to @Luis Mendo.)

-1 - Push the literal -1

Y^ - Raise input to that power (implicit input, implicit output)

sundar - Reinstate Monica

Posted 2018-07-18T16:04:39.733

Reputation: 5 296

Interesting, I never knew it was called the “Rule of Sarrus”. My teacher taught us it, but he had made it up himself while at uni. – Beta Decay – 2018-07-18T23:44:13.333

@LuisMendo Thanks, replaced the short version (tbh the previous version was just a blind implementation of the MATL manual's suggestion for inverse, no actual thinking went into that one :) ). For the long version, I think it's a tiny bit clearer to leave it as such, enough to be worth taking a 1 byte hit. – sundar - Reinstate Monica – 2018-07-19T12:28:29.897

1@sundar Heh, I didn't even remember that suggestion. I'll add the suggestion of matrix power too – Luis Mendo – 2018-07-19T12:31:23.753

13

APL(Dyalog Classic),1 byte

Try it online!

if a flat lis is required this is 8 bytes

,∘⌹3 3∘⍴

Try it online!

jslip

Posted 2018-07-18T16:04:39.733

Reputation: 721

9Welcome to PPCG! – Beta Decay – 2018-07-18T19:07:31.140

9

R, 51 35 27 8 5 bytes

solve

Try it online!

First go at doing one of these golf challenges. Sorry if my formatting is wrong!

Saved a total additional 11 bytes thanks to Giuseppe! Saved an additional 19 bytes thanks to JAD!

Robert S.

Posted 2018-07-18T16:04:39.733

Reputation: 1 253

5Welcome to PPCG! – Beta Decay – 2018-07-18T20:40:02.527

Removed the parameter variable names from the matrix function which subtracted 16 bytes! – Robert S. – 2018-07-18T20:56:40.880

can you put m inside solve entirely? why do you need to define variable – aaaaa says reinstate Monica – 2018-07-18T21:36:46.513

1

Nice! You can remove most of the variables to save bytes since you're really just chaining the operations together: try it online!

– Giuseppe – 2018-07-18T21:38:42.113

Irritating that the input format requires the ,T here. Ah well ¯\(ツ) – CriminallyVulgar – 2018-07-19T14:21:59.610

1If you're going to use solve, the solution is just solve, as it fulfills all the requirements of the question. It takes a matrix as input and returns a matrix. – JAD – 2018-07-20T12:21:47.933

@JAD Didn't think of that. Thanks! – Robert S. – 2018-07-20T15:00:08.653

Welcome to PPCG! looking at other recent R answers will give you a good sense of the acceptable program/function format. – JayCe – 2018-07-20T15:46:27.073

To add to @JAD 's point this answer should just be solve, as a function is an acceptable solution. – Giuseppe – 2018-07-20T16:10:15.453

@Giuseppe Can you maybe give an example on what you mean? I changed my answer based on what I thought JAD meant. – Robert S. – 2018-07-20T16:17:25.673

1like this – Giuseppe – 2018-07-20T16:18:54.853

@Giuseppe Ah I see. Some of the syntax used here will take awhile to get used to. Thanks! – Robert S. – 2018-07-20T16:28:31.247

4

Jelly, 3 bytes

æ*-

Try it online!

Assuming we can take input and provide as a 2D list of integers. If a flat list of integers is really required for both input and output, then this works for 6 bytes.

Mr. Xcoder

Posted 2018-07-18T16:04:39.733

Reputation: 39 774

Explanation (I don't think it's worth including in the answer): æ* - matrix exponentiation, - - exponent, which equals $-1$. - is a syntax character for negative literals but it defaults to $-1$ when there is no number right after it. – Mr. Xcoder – 2018-07-18T19:17:57.187

12Comments aren't necessarily meant to be long lived. If you're including an explanation in the comments, you should move it to the answer instead. – Poke – 2018-07-18T19:22:10.053

4

JavaScript (ES6), 123 bytes

Saved 2 bytes thanks to @Mr.Xcoder
Saved 1 byte thanks to @ETHproductions

Takes input as 9 distinct values.

(a,b,c,d,e,f,g,h,i)=>[x=e*i-h*f,c*h-b*i,b*f-c*e,y=f*g-d*i,a*i-c*g,d*c-a*f,z=d*h-g*e,g*b-a*h,a*e-d*b].map(v=>v/=a*x+b*y+c*z)

Try it online!

Arnauld

Posted 2018-07-18T16:04:39.733

Reputation: 111 334

Hey, i've allowed built-in matrix functions now. That is, if JS has any – Beta Decay – 2018-07-18T17:25:44.040

@BetaDecay JS has none. :-) – Arnauld – 2018-07-18T17:28:29.047

Are those brackets really needed?

– Mr. Xcoder – 2018-07-18T18:09:05.657

4

J, 2 bytes

%.

Just a built-in primitive

Try it online!

Galen Ivanov

Posted 2018-07-18T16:04:39.733

Reputation: 13 815

3

Python 2, 139 bytes

def F(a,b,c,d,e,f,g,h,i):x=e*i-f*h;y=f*g-d*i;z=d*h-e*g;print[j/(a*x+b*y+c*z)for j in x,c*h-b*i,b*f-c*e,y,a*i-c*g,c*d-a*f,z,b*g-a*h,a*e-b*d]

Try it online! (Has return instead of print for ease of testing.)

Lynn

Posted 2018-07-18T16:04:39.733

Reputation: 55 648

1

Clean, 143 bytes

import StdEnv
$a b c d e f g h i#p=e*i-h*f
#q=f*g-d*i
#r=d*h-g*e
=[v/(a*p+b*q+c*r)\\v<-[p,c*h-b*i,b*f-c*e,q,a*i-c*g,d*c-a*f,r,g*b-a*h,a*e-d*b]]

Try it online!

Οurous

Posted 2018-07-18T16:04:39.733

Reputation: 7 916

1

Python 3, 77 bytes

import numpy
lambda l:(numpy.matrix(l).reshape(-1,3)**-1).ravel().tolist()[0]

Takes input as a flat list.

It's 63 bytes if input is taken as a 2D array:

import numpy
lambda l:(numpy.matrix(l)**-1).ravel().tolist()[0]

Beta Decay

Posted 2018-07-18T16:04:39.733

Reputation: 21 478

0

Pari/GP, 6 bytes

m->1/m

Takes multiplicative inverse in the matrix ring \$\mathrm{M}_n\$.

Try it online!

alephalpha

Posted 2018-07-18T16:04:39.733

Reputation: 23 988

0

Perl, 226 + 4 (-plF, flag) = 230 bytes

$_=join', ',map$_/($a*$x+$b*$y+$c*$z),$x=($e=$F[4])*($i=$F[8])-($f=$F[5])*($h=$F[7]),($c=$F[2])*$h-($b=$F[1])*$i,$b*$f-$c*$e,$y=$f*($g=$F[6])-($d=$F[3])*$i,($a=$F[0])*$i-$c*$g,$c*$d-$a*$f,$z=$d*$h-$e*$g,$b*$g-$a*$h,$a*$e-$b*$d

Try it online.

Denis Ibaev

Posted 2018-07-18T16:04:39.733

Reputation: 876

0

Perl 5, 179 bytes

sub{($a,$b,$c,$d,$e,$f,$g,$h,$i)=@_;map$_/($a*$x+$b*$y+$c*$z),$x=$e*$i-$f*$h,$c*$h-$b*$i,$b*$f-$c*$e,$y=$f*$g-$d*$i,$a*$i-$c*$g,$c*$d-$a*$f,$z=$d*$h-$e*$g,$b*$g-$a*$h,$a*$e-$b*$d}

Try it online.

Denis Ibaev

Posted 2018-07-18T16:04:39.733

Reputation: 876

0

Noether, 168 bytes

I~aI~bI~cI~dI~eI~fI~gI~hI~iei*fh*-a*di*fg*-b*-dh*eg*-c*+~zei*fh*-z/P","~nPch*bi*-z/PnPbf*ce*-z/PnPfg*di*-z/PnPai*cg*-z/PnPcd*af*-z/PnPdh*eg*-z/PnPbg*ah*-z/PnPae*bd*-z/P

Try it online

Beta Decay

Posted 2018-07-18T16:04:39.733

Reputation: 21 478

0

Google Sheets, 16 bytes

=MINVERSE(A1:C3)

Input is in the range A1:C3

Built-ins are boring

Engineer Toast

Posted 2018-07-18T16:04:39.733

Reputation: 5 769

0

Clojure, 165 bytes

(fn[a b c d e f g h i](let[M map C(M -(M *[e f d c a b b c a][i g h h i g f d e])(M *[f d e b c a c a b][h i g i g h e f d]))](for[i C](/ i(apply +(M *[a b c]C))))))

I'm sorry this outputs C in transpose, and I'm feeling lazy to re-do those long character sequences to fix it at the moment.

NikoNyrh

Posted 2018-07-18T16:04:39.733

Reputation: 2 361

0

APL (Dyalog), 7 bytes

,⌹3 3⍴⎕

Takes input as a flat list and outputs as a flat list

Try it online!

Beta Decay

Posted 2018-07-18T16:04:39.733

Reputation: 21 478