Matrix multiplication - inconsistent behaviour

If I multiply a 1 by m matrix by an m by 1 matrix, that should give a number.
Unfortunately, not in Julia.

Consider below:

julia> mat1=randn(3,3); mat2=randn(3,2);

julia> mat1*mat2
3×2 Array{Float64,2}:
  1.55168    0.492743
  2.08276   -0.515072
 -0.504023  -1.6547  

julia> mat1[1,:]*mat2[:,2]
ERROR: MethodError: no method matching *(::Array{Float64,1}, ::Array{Float64,1})
Closest candidates are:
  *(::Any, ::Any, ::Any, ::Any...) at operators.jl:529

It appears that single-row or single-column matrices automatically convert to vectors. This is obviously a decision which has been made by Julia developers. I don’t agree with it (but far be it for me to question).

Fortunately, Julia is a very flexible platform and (although the developers hate my doing it) I have managed to solve many of my ‘niggles’ by function overloading. I am wondering if someone can help me by showing me how to overload Matrix Multiplication to make this work like I would like it to?

It has caused me no end of inconvenience.

Thanks in advance for any help.

1 Like

And it does (well a 1x1 matrix at least which is the correct answer), but your example tries to do a vector times a vector which doesn’t make sense.

I’m guessing you meant to write

julia> mat1[1:1,:]*mat2[:,2:2]
1×1 Array{Float64,2}:
 -0.7729831803824689

Or use dot if that is the semantics you want.

julia> dot(mat1[1,:], mat2[:,2])
-0.7729831803824689
2 Likes

Thanks for that.

So I guess I need know how to overload mat1[1,:] to behave as mat1[1:1,:] (obviously only at the top level).

Thanks

If I understand correctly, what you want to do is type piracy, which is strongly discouraged.

Just use transpose or dot or something. The decision about the behavior of slicing was thoroughly discussed and thought-through. ‘Fixing’ it with type piracy is risky.

5 Likes

Thanks. What if I am willing to accept the risks? I would prefer for this change only to happen in the context of matrix multiplication. I do very much appreciate your help, but wouldn’t dream of asking you to help me with something you do not approve of.

If I have a situation where I have an indices ‘ind1’ and ‘ind2’

mat1[ind1,:]*mat2[:,ind2]

and ind1 and ind2 may be of any dimension (including 1) then I don’t
want my program to fall over , and I don’t want to always have
to anticipate the special cases of one or both of them being of length 1.

[Perhaps someone on here of a less judgemental disposition (i.e., a fellow hacker) might like to help?]

But you misunderstand. It is not the lengths of ind1 and ind2 that matter, but their types. The slice will be a matrix if ind1 is a vector, and a vector if ind1 is a scalar. So it does not come down to special cases, but to behavior predictable from types.

1 Like

Hi and thank for that. While that explanation is very informative, it still doesn’t answer my question of how I might force it to behave as I would like an a very specialised instance.

No it doesn’t answer it. The only help I can offer is “don’t do it”.

1 Like

All you need to do is define the multiplication of two vectors to be the dot product. That said, there almost certainly is a much cleaner solution to do what you actually want without going down this path.

I think you got very good advice from various people already. Asking for “someone on here of a less judgemental disposition” is a bit rude in this context. If you want help from specific people (or do not want help from some people), you may want to consider options for paid support.

Here, specifically, the issue is that modifying what mat1[1, :] does would break >90% of Julia instantly, which is why it is not recommended as a solution.

5 Likes

Thanks Tamas, and I certainly do not mean any disrespect. However, if I choose to tailor my own interface to Julia so that it is easier for me to work with, and I am willing to accept the risks, this should be not looked down-upon. Julia is a platform, not a dogma.

Also, I have, on occasion, paid for help, but why are you questioning my right to ask the community first? If you don’t like what I am trying to do, just don’t engage, and let someone else on here try to help (or not).
[With respect]

The solution to what you want is not overloading but to just define your own function.

function mymatmul(A, B)
    # do what you want
end

and use that.

5 Likes

Just to clarify: I am of course not questioning your right to ask these questions here. However, I do not believe that you are entitled to specify who responds to your questions, or complain that they are “judgemental” just because they pointed out something perfectly valid and idiomatic in Julia.

Before getting into an argument about this in the abstract, I am wondering if you actually tried what you are proposing (ie overwriting Base.getindex(::AbstractArray, ::Int, ::Colon)).

2 Likes

Thanks for your suggestion.

Perhaps I will do that.

Regards,
DrE
PS What if, within the context of a particular function, I wanted to make
my own definition the default (i.e., notationally)? How might I do this?

Thanks Tamas, I will have fun playing around with that (inside functions only, obviously).

Method overloading is global and affect all callers in the Julia session.

1 Like

Maybe what I really need is for a vector of length 1 not to automatically morph into a scalar. Is there a way to do that in a limited context?
[Never mind… just wondering!]

What do you mean? What circumstance are you seeing this? Length 1 vectors and scalars are very different in Julia. Did you perhaps overload something that caused this to break?

I guess what I am looking for is an assertion… that a particular vector not be converted to a scalar just because it only has length 1

Length 1 vectors are never “converted to scalars” implicitly by default in Julia.

3 Likes