On adjoints and custom postfix and infix operators

I’d like ' to be a post-fix operator that maps f' to '(f) where Base.:'(x::AbstractMatrix) = adjoint(x) and the user is free to add other methods that have nothing to do with adjoints. (For example, some people might like f' to refer to df/dt.)

Of course it is possible to overload adjoint to the same effect, but aesthetically this is less satisfying. It looks like I’m saying “the adjoint of my object is …” when really I’m saying “the effect of the postfix ' on my object is …”

Edit: With the operator suffixes introduced in 0.7, I would also like f'ᵃ to map to 'ᵃ(f), and so on, allowing the user to define his own postfix operators. This would make it possible to have Base.:'ᵀ(x::AbstractMatrix) = transpose(x).

8 Likes

That’s much better! I thought you wanted everyone to write adjoint(A) * b instead of A' * b, so I almost fell out of my chair :smiley:

1 Like

Maybe we could have self-defined operators like Haskell in the future? And you can define your own operators rather then hard-coded operators.

2 Likes

Though I am not against different meanings for postfix ' per se, I used ApproxFun in combination with matrix-valued functions, say A(x), and was bitten by A' not being the adjoint but the derivative of that function more than once.

1 Like

Overloading functions and operators can always lead to ambiguous situations, but all other functions and operators in Julia (as far as I know) can be overloaded directly. The ' is a special case in a language that otherwise avoids special-casing whenever possible.

Oh, and while we’re on the subject, I would have liked to be a postfix operator as well. This would have been a pain for everyone who currently names their variable Aᵀ in order to indicate that it is using row-major storage, but I feel they could re-write their code to make A a Transpose object which would probably make Aᵀ behave just as before with no performance penalty.

This seems like a pretty obvious improvement. Has it been decided against, or is it just not prioritized?

Oh then we can also have as a postfix operator instead of adjoint. But why not just let the parser support Haskell like self defined operators…

Yes this is an issue in ApproxFun and hopefully future versions of Julia allows overriding and adjoint separately. Until then, there might be a work around possible by supporting Adjoint(f)

Edit: or just use transpose(f)

1 Like

No, many operators are overloaded indirectly.
getindex, hcat, vcat, vect, braces and bracescat.
They are all a bit nontradition as far as operators go, as they are circumfix.
But adjoint is also a bit nontraditional as the only postfix operator.
It might be nice. It is what it is.

I would have liked to be a postfix operator as well.

That also might be nice.
But AFAIK it won’t happen until julia 2.0.
0.7 has now been cut, and is not taking not features.
That would require a deprecation.
1.0 is not going to be introducing any new deprecations.
1.x might, but that kinda language level change can’t be resolved without a major release (via semver rules).

1 Like

They were complex-matrix-valued :slight_smile:

1 Like

They were complex-matrix-valued :slight_smile:

Ah, conj(transpose(f)) or better yet adjoint.(f)?

This makes more sense than using adjoint as it’s not clear what the “adjoint” of a function (or matrix-valued function) should actually mean.

Note adjoint(::Matrix{<:Fun}) is completely broken since adjoint is recursive…

As long as existing code still works (which wouldn’t be affected by adding postfix operators like ) then semver says adding it to 1.x is fine.

But existing code wouldn’t work, because Aᵀ is currently a legal variable name.

3 Likes

Personally, I think this won’t be solved until Julia can add self-defined operators by users, people may want more and this cannot always done by asking the parser to parse an operator.

We have already have a bunch of operators written in the parser, but they won’t be used frequently. And since they are all defined globally, it can be ambiguous like '. Asking to parse a new operator each time does not look like sustainable.

That would be cool, but would at minimum require spaces around operators to avoid ambiguity.

As it is, you can easily create a macro that lets you write, for example: my_syntax" Aᵀb " and have that expand to transpose(A)*b.

Actually, the QuDirac.jl did so. However, manipulating raw strings is painful… I remember there was someone asking for supporting Dirac notation in the parser: |>. But this is quite painful…

And as a Julian, I would like to define our operators in Julia rather than flisp :wink:

1 Like

But we can work around this in the following 1.x versions in this way I guess

syntax"Aᵀb"

Maybe your guys will want some utils for this kind of personal operator syntax? We can make a package.

1 Like

There exists a Julia parser written in Julia (MIT license). It has no recent commits, so some work would be required to bring it up to 0.7…

1 Like

I have no idea. I have a vague memory of having suggested this some time ago, but I can’t seem to find the discussion, and I don’t even remember if it was on discourse or github. At any rate, it would be a non-breaking change and it only affects aesthetics, so there’s no rush.