Overload LinearAlgebra.cross for ProductMeasure
This package defines ×(μ::AbstractMeasure{X}, ν::AbstractMeasure{Y}). This will collide with LinearAlgebra.cross, which is aliased to ×, which is exported. The solution we used in Manifolds.jl was to overload LinearAlgebra.cross and then re-export ×.
Could we use the classical ⊗?
We should probably use whatever the standard notation is for product measures (I don't know what that is). I also feel strongly that unicode symbols as operators should only be convenient aliases of functions with descriptive names (among other things, having non-unicode function names makes it easier for other languages with less unicode support to interop with the package).
Thanks for catching this, @sethaxen .
I also feel strongly that unicode symbols as operators should only be convenient aliases of functions with descriptive names (among other things, having non-unicode function names makes it easier for other languages with less unicode support to interop with the package).
This is ProductMeasure, which has Base.* as shorthand. @mschauer makes a great point here, I think ⊗ is more common in this context. I'm sure we'll have the same issue, since other libraries use ⊗, but I guess we can just figure that out as we go.
I am against using LinearAlgebra.cross. The measure product is isn't a cross product at all, and I don't usually think of measures as elements of a vector space (that works for signed measures only, IIRC?). I believe the measure product is much closer to a tensor product -- induced by a pairing operation on the underlying spaces.
As for the notation, I prefer \otimes, but I'm not completely against \times either.
× and * can easily be confused with products of random variables, that is one reason
@phipsgabler As I understand, the only reason @sethaxen metioned overloading LinearAlgebra.cross was to more easily allow overloading of \times. But as you and @mschauer point out, \otimes is probably more appropriate here anyway, so I think the point about cross is now moot.
I've also been using * for this, because it's literally a product of measures (in the category-theoretic sense) and distributes over superposition. But I haven't thought further about it than this. Does it make sense to take polynomials over a measure? What about exp(μ)? I don't see it yet.
Hmm... I may have jumped the gun on this - I'm seeing a fair number of texts using \times, for example https://terrytao.files.wordpress.com/2011/01/measure-book1.pdf
@mschauer do you see a particular context where \otimes is more common? There's no rush on this, but we'll need to nail down the notation at some point.
I think majority of the literature uses ⊗ but × is of course also reasonable. The reason for ⊗ is that the cartesian product of sigma fields 𝔉 × 𝔅 is not a sigma field yes and one defines 𝔉 ⊗ 𝔅 = σ(𝔉 × 𝔅) as the completion. And then it is very natural to also call the product measure by ⊗, because it also doesn't only measure the elements of 𝔉 × 𝔅 but all of 𝔉 ⊗ 𝔅.
I would suggest implementing TensorCore.tensor for product measures and reexport both TensorCore.tensor and its alias TensorCore.:⊗. This would allow to construct product measures both with the unicode operator ⊗ and its alias tensor. TensorCore is a lightweight package that contains default implementations for tensor operations. Originally, the code was merged in https://github.com/JuliaLang/julia/pull/35150 which was later reverted in https://github.com/JuliaLang/julia/pull/35744 and moved to its own package. It will be implemented in KernelFunctions such that users can construct tensor product kernels in a more convenient way (https://github.com/JuliaGaussianProcesses/KernelFunctions.jl/pull/232).
Thanks @devmotion . Between × and ⊗, I think issues are
×
The semantics here are fundamentally different than LinearAlgebra.cross. I'd guess that being exported invalidates its use in lots of cases, and the real solution is probably for LinearAlgebra to not export the symbol, to allow its use in other contexts.
⊗
This seems pretty good, and I mostly like the idea of extending a lightweight package.
In addition to pairs, we'll often store the data for a ProductMeasure in an array. In particular, a MappedArray corresponds to Soss's For, and a FillArray is like iid. And it seems to work out, because we could just have
⊗(μ::ProductMeasure, ν::ProductMeasure) = ProductMeasure(μ.data ⊗ ν.data)
But this makes me think we could benefit from a more efficient implementation, for example https://github.com/MichielStock/Kronecker.jl
OTOH this is wrong; the notation here gets very tricky
The product of two univariate measure is bivariate, so the dimensions add. So the operation on the support is a (standard) product, not a Kronecker product.
But it is bilinear, if we consider weighted measure as scalar multiplication and superposition as addition.
I am more used to the notation ⊗ than × and agree with the explanation given by @mschauer above, therefore personally I would rather implement TensorCore.:⊗ than LinearAlgebra.:×.
Apart from that, I don't understand why the implementation should be problematic in any of these cases. There is nothing wrong with LinearAlgebra defining ×, you can just extend it for the types you own (such as ProductMeasure or whatever) in the same way as you can extend any function from Base. The same can be done with TensorCore.:⊗. You don't have to use or fall back to any of the default implementations in LinearAlgebra and TensorCore; e.g., in KernelFunctions we never use any array-related functionality in TensorCore. The only problem with the unicode operators is if packages start to define and export them (such as MeasureTheory or Kronecker...) even though the names are so generic that they should either be defined in Base, one of the standard libraries, or a lightweight interface such as TensorCore.
There is something like "name piracy". If print(a) doesn't give a method error, it is really expected to print, even if you own the type of A. So that is against ×.