# Is matrix multiplication not associative?

**URL:** <https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231>\
**Category:** New to Julia\
**Tags:** question, error, matrix\
**Created:** [March 21, 2025, 4:09pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231 "2025-03-21T16:09:38Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Yeguarr](https://avatars.discourse-cdn.com/v4/letter/y/46a35a/32.png) [@Yeguarr](https://discourse.julialang.org/u/Yeguarr)\
**Post date:** [March 21, 2025, 4:09pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/1 "2025-03-21T16:09:38Z")

</div>

Hi! I have a very simple code snippet:

```julia
let
	B = [1;1]
	K = [1 2]
	x = [1;2]

	(B*K)*x #Works fine
	B*(K*x) #MethodError: no method matching *(::Vector{Int64}, ::Vector{Int64})
end

```

It seems that Julia automatically converts the matrix to a vector for the second case. Is there a way to stop this behavior? I want to define a variable u = K\*x, but this breaks my code.

Julia version: 1.11.4.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [March 21, 2025, 4:20pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/2 "2025-03-21T16:20:43Z")

</div>

The issue is that `[1 2]` is a matrix, not a row vector, so `[1 2] * [1; 2]` returns a vector of length one, not a scalar. To get a row vector, type `[1; 2]'` or `transpose([1; 2])` or `adjoint([1; 2])`.

```julia-repl
julia> let
           B = [1; 1]
           K = [1; 2]'
           x = [1; 2]

           @show (B * K) * x # Works fine
           @show B * (K * x) # Works fine
       end;
(B * K) * x = [5, 5]
B * (K * x) = [5, 5]

```

---

<div class="post-metadata">

**Author:** ![Yeguarr](https://avatars.discourse-cdn.com/v4/letter/y/46a35a/32.png) [@Yeguarr](https://discourse.julialang.org/u/Yeguarr)\
**Post date:** [March 21, 2025, 4:24pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/3 "2025-03-21T16:24:35Z")

</div>

Wow! Thank you!

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [March 21, 2025, 4:34pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/4 "2025-03-21T16:34:42Z")

</div>

The inconsistency is arguably that `B * K` does _not_ error here—a column vector left-multiplied with a matrix doesn’t really make sense. But since it’s possible to interpret every column vector as a single-column matrix, there apparently exists a multiplication method that treats `B` as such and computes the resulting matrix product.

The converse “demotion” of `K` to a row vector would not make sense because `K * x` is a regular, valid matrix-vector product returning a vector, and Julia can’t know that you actually meant to think of `K` as a row vector instead.

---

<div class="post-metadata">

**Author:** ![apo383](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/apo383/32/11272_2.png) [@apo383](https://discourse.julialang.org/u/apo383)\
**Post date:** [March 21, 2025, 6:49pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/5 "2025-03-21T18:49:21Z")

</div>

> [@danielwe](#):
>
> The inconsistency is arguably that `B * K` does _not_ error

This is a common pattern in control systems, which has a slightly different interpretation. `B * K` is intended to be an outer product (a column multiplied by a row) that yields a matrix. People use it a lot and know what it means, so it shouldn’t error.

Rather, I think the issue is that @Yeguarr intends `x = [1; 2]` as a 1-column matrix (as in Matlab) and not a vector. In Julia, `K*x` is a 1-element vector and neither a scalar nor a 1x1 matrix, which both work and mean the same in Matlab. In Julia, a way to do it is here:

```julia
julia> B = [1;1] # vector
julia> K = [1 2] # row
julia> x1col = [1 2]' # ugly but means 1 column matrix not a Julia vector
julia> (B*K)*x1col # works fine
julia> B*(K*x1col) # also works fine
2×1 Matrix{Int64}:
 5
 5

```

This is one of the rare cases where Matlab does “what you want.” I do believe Julia’s vector approach is otherwise far superior to Matlab overall, but it’s a bit unwieldy for this common controls pattern.

I avoid `x = [1; 2]` in Julia because it means the same as `x = [1, 2]`. I mentally want to parse semicolon as row delimiter in a matrix, which it usually is, just not here. Likewise I would still say `B = [1, 1]` to be clear to myself. Even though `(B*K)` works fine with `B` as a vector, I don’t want to fool myself or others into thinking it’s a 1-column matrix.

For controls people, Matlab’s “everything is a matrix” approach works out remarkably well. It also has a bunch of unfortunate ambiguities outside of controls.

---

<div class="post-metadata">

**Author:** ![Yeguarr](https://avatars.discourse-cdn.com/v4/letter/y/46a35a/32.png) [@Yeguarr](https://discourse.julialang.org/u/Yeguarr)\
**Post date:** [March 21, 2025, 6:57pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/6 "2025-03-21T18:57:10Z")

</div>

Thank you for your comment! You are right, I’m coming from Matlab where exactly the same code works fine, never thought it would be an issue here.

I think in my case it would be better to define both B and K as matrices (because they are transformations in my case) and leave x as a vector. So updated code:

```julia
B = [1 1]' #wish there was a better way
K = [1 2]
x = [1;2]

(B*K)*x #Works fine
B*(K*x) #Works fine

```

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [March 21, 2025, 7:23pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/7 "2025-03-21T19:23:45Z")

</div>

> [@apo383](#):
>
> `B * K` is intended to be an outer product (a column multiplied by a row) that yields a matrix.

An outer product maps two vectors to a matrix. It’s equivalent to a matrix product between a single-column matrix and a single-row matrix. But what’s happening in this case is neither of these—`B * K` multiplies a _(column) vector_ on the left by a _matrix_ on the right. This implies contracting over a dimension that isn’t actually there. I agree that it’s convenient, and it’s likely harmless because it’s unambiguous—how else would you make sense of column vector times matrix? But formally speaking it’s inconsistent—Julia usually enforces the distinction between a vector and a single-column matrix, but not here—and this inconsistency is what breaks associativity in the original example.

In Matlab, everything is a matrix, including “scalars”, so you can’t run into these subtleties. Convenient in many cases, absurd in others.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [March 21, 2025, 7:24pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/8 "2025-03-21T19:24:35Z")

</div>

> [@Yeguarr](#):
>
> `B = [1 1]' #wish there was a better way`

Here’s how:

```julia-repl
julia> [1; 2;;]
2×1 Matrix{Int64}:
 1
 2

```

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [March 21, 2025, 7:42pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/9 "2025-03-21T19:42:01Z")

</div>

> [@danielwe](#):
>
> ```julia
> julia> [1; 2;;]
> 2×1 Matrix{Int64}:
> 1
> 2
> 
> ```

To elaborate on this syntax: in array literals, n semicolons increments the n-th index. Thus, you can instantiate arrays of arbitrary dimension:

```julia-repl
julia> [1; 2;;; 3; 4]
2×1×2 Array{Int64, 3}:
[:, :, 1] =
 1
 2

[:, :, 2] =
 3
 4

```

In `[1; 2;;]`, the final `;;` forces the existence of a second index, obtaining a column matrix.

The Matlab-like matrix literal syntax is just extra sugar: spaces increment the second index, like `;;`, and line breaks increment the first index, like `;` (with the extra subtlety that if you use spaces instead of `;;` you should enter elements by row instead of by column).

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 21, 2025, 7:47pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/10 "2025-03-21T19:47:15Z")

</div>

> [@apo383](#):
>
> Rather, I think the issue is that @Yeguarr intends `x = [1; 2]` as a 1-column matrix (as in Matlab) and not a vector. In Julia, `K*x` is a 1-element vector and neither a scalar nor a 1x1 matrix

There’s an argument that we should have a `vector * vector` method that treats the left vector as a 1-column matrix and works if the right vector has 1 element, throwing an error otherwise. This would be more consistent with other methods treating vectors as 1-column matrices when the shapes work.

---

<div class="post-metadata">

**Author:** ![digital\_carver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/digital_carver/32/33818_2.png) [@digital\_carver](https://discourse.julialang.org/u/digital_carver)\
**Post date:** [March 22, 2025, 4:16am UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/11 "2025-03-22T04:16:25Z")

</div>

Just for future reference, another practical solution that works with the original arrays as they are is:

```julia
let
	B = [1;1]
	K = [1 2]
	x = [1;2]

	@show (B*K)*x 
	@show B*only(K*x) 
end;

```

It sounds like turning `B` into a `Matrix` works better conceptually for you in this case, but `only` is a generally useful function to keep in mind, to turn a single element `Array` into a scalar value.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [March 22, 2025, 4:56am UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/12 "2025-03-22T04:56:48Z")

</div>

I have a question: Does `x'` always resolves into `transpose(x)`, as long as Complex numbers are not involved?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 22, 2025, 7:27am UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/13 "2025-03-22T07:27:16Z")

</div>

> [@Yeguarr](#):
>
> `x = [1;2]`

Just for notational clarity: the standard syntax for vector literals is `[1, 2]`, that is, commas instead of semicolons. They end up doing the same thing, but using commas sets them apart visually, which might be beneficial.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 22, 2025, 12:19pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/14 "2025-03-22T12:19:34Z")

</div>

> [@WalterMadelim](#):
>
> I have a question: Does `x'` always resolves into `transpose(x)`, as long as Complex numbers are not involved?

`x'` always corresponds to `adjoint(x)`, but yes: `adjoint` is (recursive) transposition for real numbers.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [March 22, 2025, 1:45pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/15 "2025-03-22T13:45:37Z")

</div>

Maybe I’ll stick to `transpose`, for being rigorous, although lengthy.  
(I don’t work with Complex numbers)

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 22, 2025, 4:46pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/16 "2025-03-22T16:46:36Z")

</div>

Why do you think `transpose` is more “rigorous” for real arrays?

(For most applications in linear algebra, I would say that adjoint is generally what you want, for either real or complex arrays. The reason this is an important operation in linear algebra is its relationship to inner products.)

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [March 22, 2025, 11:18pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/17 "2025-03-22T23:18:17Z")

</div>

> [@stevengj](#):
>
> For most applications in linear algebra, I would say that adjoint is generally what you want

In the exact literal meaning, `transpose` is the essentially desired operation (since Complex number is _not_ involved in my context). At least they show up differently in Julia REPL

```julia
julia> transpose(x)
1×3 transpose(::Vector{Float64}) with eltype Float64:
 0.715859 0.0920015 0.183793

julia> x'
1×3 adjoint(::Vector{Float64}) with eltype Float64:
 0.715859 0.0920015 0.183793

```

> [@stevengj](#):
>
> an important operation in linear algebra is its relationship to inner products

Not only inner product, maybe equally important in _outer product_ as well.  
I may `transpose` other objects as well (e.g. `Array{JuMP.GenericVariableRef{Float64}, 1}` in [this](https://discourse.julialang.org/t/inner-product-grammar-is-neater-than-sum-index-in-jump-modeling-but-triggers-warning/124528/28) post)

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 22, 2025, 11:24pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/18 "2025-03-22T23:24:10Z")

</div>

> [@WalterMadelim](#):
>
> In the exact literal meaning, `transpose` is the essentially desired operation (since Complex number is _not_ involved in my context).

Couldn’t you just as easily say that the adjoint is the desired operation?

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [March 22, 2025, 11:31pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/19 "2025-03-22T23:31:38Z")

</div>

`transpose` is deemed a more fundamental operation, e.g., in my post link above  
`adjoint` comprises `transpose` and `conjugate`. (the latter is provisionally not needed for me)

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 22, 2025, 11:38pm UTC](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231/20 "2025-03-22T23:38:10Z")

</div>

> [@WalterMadelim](#):
>
> `transpose` is deemed a more fundamental operation

I would disagree. In linear algebra, the more fundamental operation is the adjoint ^\* (`'` in Julia), which is defined by the inner product \langle x, y \rangle = x^\* y for vectors, and \langle x, A y \rangle = \langle A^\* x, y\rangle for any linear operator A.

For real vectors with the usual Euclidean inner product, the adjoint coincides with what people call the “transpose”, and this is the main reason why transposition is so common and has a special name. (As opposed to many other rearrangements you could imagine, like flipping a matrix or vector upside down or rotating a matrix 90°, which don’t have a standard name.) Every time you see a transpose in linear algebra, there’s a good chance that (a) you’re working with real numbers, (b) there is an inner product lurking implicitly nearby, and (c) if you had complex numbers you’d probably need the conjugate-transpose instead.

But anyway, this is a philosophical point. You are free to write `transpose(x)` instead of `x'` in Julia if you want; the two are functionally and computationally equivalent for real vectors and matrices.

(There are fairly rare exceptions where you transpose complex vectors without conjugation; that’s why it’s still useful for Julia to have a separate `transpose` function. If you’re not dealing with linear algebra at all and just want to rearrange a container, there is `permutedims`.)

[Next page](https://discourse.julialang.org/t/is-matrix-multiplication-not-associative/127231.md?page=2)
