-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add +/-
for Number
and AbstractMatrix
to LinearAlgebra
#29951
Conversation
I think this would be a wonderful change, and would love to be able to do A - z. I also think it should not be made, because the ratio of potential confusion to added convenience is just too high. 1 it would be very idiosyncratic to julia, I don't know of any other language that does this, and in matlab A+x means A .+ x. |
I also tend to think that the possible confusion this could cause outweigh the benefits here although I'm sympathetic to this change. Coming up with a compelling example might tip the balance, though. As it stands, I'm not convinced by Regarding @antoine-levitt's comments:
Probably true for most languages but PARI/GP actually does this
This is also the case for
I suspect this is also true for many of the existing linear algebra operations and is something we'll have to live with to allow that |
Agreed, which is why I think we should strive to minimize the potential confusion, and that anyone not familiar with the specific idiosyncrasies of julia should be able to know what the code does without reading the docs. I tend to think |
(+)(a::Number, A::AbstractMatrix) = UniformScaling(a) + A | ||
(+)(A::AbstractMatrix, a::Number) = A + UniformScaling(a) | ||
(-)(a::Number, A::AbstractMatrix) = UniformScaling(a) - A | ||
(-)(A::AbstractMatrix, a::Number) = A - UniformScaling(a) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this could/should be done via the promotion mechanism. Interestingly, that would address the behavior of scaling a matrix by a scalar as well.
I'm not 100% sure about whether we should do this but I like it and think that we should definitely have the discussion now that we have room for the feature. I wonder if it would be best to leave room for it and make it a pirate package, say, |
I’m in favour. We’ve always strived for a syntax in common with mathematical language (and yes, most languages screw this up, even MATLAB). IMO gaining the distributive law would plug a relatively major inconsistency. |
@andyferris I was writing a statement along the same lines: I think Julia has in total done well will the fundamental approach to have algebraic reasoning to be a major motivation regarding the meaning of |
Doesn't this go both ways? My initial expectation, without reading the docs, was that The way I see it, the argument for the current behaviour (erroring) is that people who think like me repeatedly forgot that EDIT: And if it does, how does it compare to, say, potential errors due to |
This change seems like an invitation for bugs and confusion. Since It also seems weird to me to allow |
Why can't these definitions live in an opt-in package? |
I think the opt-in package with a license to pirate is the best solution. If/when LinearAlgebra gets completely pulled out from base, then I think it would be reasonable to put the definitions in there, though. |
😂 ❤️ |
Privateer.jl? :) If the opt in package option is chosen, it'd be great to move the matrix functions (exp/log/etc) there eventually (although that would be a breaking change) |
Technically, this should be called a letter of marque. |
As I understood, this would not be trivial: any package which uses the pirate package would become a pirate. |
So it should be a copy-left marque? |
I have been thinking about the piracy issue, and I think it would be a lot simpler if exported functions from base, etc. could be overridden by other exports without qualification. To prevent unintended exports, this should only be allowed from special pirate modules. I. e., a module could be granted the letter of marque by declaring it as a piratemodule LinearAlgebraOperators
export +
using LinearAlgebra
@inline +(args...) = Base.:+(args...)
@inline +(x::Number, A::AbstractMatrix) = Base.:+(UniformScaling(x), A)
end The splatting here doesn't seem to have any performance issues and produce the exact same It would also resolve this issue on Discourse: https://discourse.julialang.org/t/option-to-start-repl-in-baremodule-mode/17244/3 As an afterthought, I guess it wouldn't really be piracy anymore, just intrusion. EDIT: It would work really badly with things that rely on dispatching on |
That is already possible:
|
That has the explicit julia> module LinearAlgebraOperators
using LinearAlgebra
+(args...) = Base.:+(args...)
+(x::Number, A::AbstractMatrix) = Base.:+(x*I, A)
end
Main.LinearAlgebraOperators
julia> 1 + 2
3
julia> using .LinearAlgebraOperators: +
WARNING: ignoring conflicting import of LinearAlgebraOperators.+ into Main |
Well, in general yes I'm in favour of developing as many features outside of Base and porting in the ones that made sense. Even vector transposes was developed/prototyped in a package. (Matrix transpose in a package quickly proved impossible...) But this is a tiny four method change. We've strived very hard for consistent and reliable mathematical syntax where
Of course there's no real type
I didn't particularly agree, since if we use the old (broadcasting) meaning of
I'd note that in taking matrix transposes seriously it seemed to me that there was an expression that we would be attempting to take a very linear algebraic view of things, beyond (I also feel that there won't be a huge wave of contusion if we implemented this... people dealt with all the transpose and adjoint and permutedims changes quite well, as well the switch away from auto-broadcasting operations, and the community has embraced whole-heartedly the beautiful generalization of |
While I ❤️ this view very much, to play devil's advocate, there are a lot of Matlab converts who are already kind of bent out of shape that |
OK, let's address that. If I understand, the main reason people are against this is due to a fear of people expecting different behavior and creating bugs in their code. I may be wrong, but I'd actually expect ex-MATLAB users to be least likely to get actual production bugs out of this. By-and-large, MATLAB users will come with at least a basic understanding of linear algebra. They are already familar with the difference between I'd be more worried about people from a more pure software background and who have used systems with auto-broadcasting in the past, and for whom the concept of adding a scalar to the diagonal of matrix would never have occured to them as a likely operation that people use (because they haven't had much linear algebra exposure). Of course, a pure software engineer will frequently be solving problems using non-square arrays (where the error message will set them on the right track), they know they should at least skim-read the docs of the interfaces they employ, they may have some unit tests around their production code, and so on. They will encounter that other operations don't auto-broadcast, and note that Then of course, there is the occasional typo, where one types The one thing we can say about software engineers and scientists and that we are good at pattern recognition. We've got a pretty consistent system in Julia. All elementwise operations use broadcasting, all the time. Linear algebra is typically done with To explain why I'm writing so much about this: To me, ultimately, this change is the final stage in an evolution of our array and linear algebra system involving many steps, such as JuliaLang/LinearAlgebra.jl#42, the removal of auto-broadcasting ops in favour of dot notation, the replacement of |
Personally, I would love it if Julia 2.0 established equivalence between scalar numbers and Going half-way and only overloading |
Frankly, |
I agree that Unless |
@perrutquist In my view, promotion and conversion (which AFAICT kinda defines equivalence between different Julia types) are quite different things. The proposal of this PR is to have numbers promote to |
I think the reason why I feel resistance towards setting I think the transitive property is more important than the implied comparative relationship between scalars and matrices. I don't think |
W. r. t. Matlab users, then I asked one of the Matlab users in my local circle what they would expect This is an anecdote, of course, and since I'm obviously biased, I cannot rule out the possibility that my framing of the question had some influence. However, I think that if the argument against this PR is that Matlab converts will get bugs in their code, then it should be backed up by stronger data than feelings and anecdotes. Does anyone know if a related community survey has been conducted? |
Very good point about the transitive property of equivalence. I guess that means it is impossible to define (Note that this transitive property is already broken is Somewhat related: The fact that |
Again, this won't work for software engineering tasks. Arrays are also our lists, and it's perfectly valid to ask whether two lists are the same, even if they have different lengths. (Also note that when you want this comparison on
This is unfortunate, yes... I can't remember where (or what the conclusion was), but it was once discussed whether |
I think this is the discussion you are thinking of, @andyferris? JuliaLang/LinearAlgebra.jl#449 But perhaps it would be better to figure out if the automatic promotion should happen first or not, and then use that as a springboard to see if EDIT: It seems like there was very little discussion surrounding the introduction of |
Here's another idea: Let The documentation should state that these types refer to matrices that are square in the linear algebra sense. For example, an image that happens to be square should probably not use a
|
Seems to be a lot of contention here, with more down-votes than upvotes. |
This is a follow-up to: JuliaLang/LinearAlgebra.jl#449.
With the deprecation of automatic broadcasting and things having seemingly settled, it is now possible to introduce automatic promotion of
Number
toUniformScaling
. The arguments for this can be found in the issue linked above, but distils to:+
to obey the common distributive property of(A + B)*C == A*C + B*C
for all mathematical objects in Julia where this is generally valid; this does not currently hold for(matrix + scalar)*vector == matrix*vector + scalar*vector
f(x, y) = x^2 + y^2 + 2*x*y
which does not require special casing on scalars and matrices; the "generic" definitionf(x, y) = (I*x)^2 + (I*y)^2 + 2*(I*x)*(I*y)
will promotef(::Number, ::Number)
to aUniformScaling
.The type piracy done here currently has the unfortunate side–effect of adding these methods to the method table of
+
and-
without the user doingusing LinearAlgebra
, similar to how matrix multiplication is also exported.Ideally, I think the feature implemented in this PR should only be available after
using LinearAlgebra
, but I have not been able to find a good way to do it.