I was running into a problem using the \ (linear system solver) operator in Julia. I guess I wrongly assumed the \ operator was overloaded for matrices/vectors with entries of type <: Number (witch unitful types are). Is there any way to easily overload the \ operator to accept unitful types, or perhaps a different operator/function that works for all types that are subtypes of Number (since I plan on using Sym and Float/Integer types in my code as well)
Environment: Pluto on MacOS
Packages: Unitful, Sympy, Plots, PlutoUI
Code:
let
a11 = 1u"m"
a12 = 2u"ft"
a21 = 5u"mm"
a22 = 0u"inch"
A = [a11 a12; a21 a22]
b = [3u"inch"; 1u"mm"]
x = A \ b # This line throws error
end
Error: MethodError: no method matching (Unitful.Quantity{Rational{Int64}})(::Rational{Int64})
I don’t think there is an easy way to define a unique, unambiguous solution to that example problem. Which should the units of the elements of x? Moreover, in this case it’s only a matter of scale between units of the same kind, but for arbitrary units in A and b, it might be impossible to solve.
Oh yeah, it makes sense that the ‘b’ vector would be in units of Length*mysteryunit since Ax = b, and x is unknown. Maybe x can be solved given the units of b?
Using the one-argument ustrip method is generally a bad idea: you don’t know what you’re stripping, it works well only for the trivial case where you have all homogeneous quantities.
Thanks for the advice! I changed up the method a little bit to ensure that all unit of elements in the matrices A and B are the same before using the system solver.
function Base.:\(A::Matrix{Quantity{T,U,V}}, B::AbstractVecOrMat) where {T,U,V}
if typeof(unit(eltype(A))) ≠ Unitful.FreeUnits{(), NoDims, nothing}
A = map(x -> uconvert(unit(eltype(A)), x), A)
B = map(x -> uconvert(unit(eltype(B)), x), B)
return Quantity.(ustrip(A)\ustrip(B), unit(eltype(B))/unit(eltype(A)))
end
end
There should be another definition of \ covering the case when A is a non-Unitful matrix and B is Unitful. Should be pretty similar to the one already defined.