Hi!
I’ve been working on some code that makes use of the dual number implementation in ForwardDiff.Dual
. I end up using the dual numbers directly rather than through the functions provided by ForwardDiff
as I’ve found it allows for more flexibility and possibilities for optimization on my specific application. In this regard, I can set up a Dual number and perform a multiplication with a scalar,
a1 = 1
a2 = 2
a3 = 3
A = ForwardDiff.Dual{:tag1}(a1,a2,a3)
b1 = 4
b1*A
This creates a dual number with a value of 1 and two partials equal to 2 and 3, and correctly returns a Dual with a value of 4 and partials 8 and 12. Now, I want to further make use of the machinery I have to allow the value and individual partials themselves to be Duals rather than floats, for example
a1 = ForwardDiff.Dual{:tag1}(1.0,1.0)
a2 = ForwardDiff.Dual{:tag1}(2.0,1.0)
a3 = ForwardDiff.Dual{:tag1}(3.0,1.0)
A = ForwardDiff.Dual{:tag2}(a1,a2,a3)
b1 = 4
b1*A
which works as I’d want. The broad idea here is that my code can receive a parameter x<:Real
, and compute something based on that parameter which internally uses automatic differentiation. If I provide a Float64
value of x
then I would get a single float as a result. If instead I provide x
as a Dual number ForwardDiff.Dual{:tag1}(a,1.0)
(where a
is a Float64
), then the result would be a Dual number containing the result for a
along with the partial derivative with respect to the parameter.
Now my problem is when I try to have b1
itself be a dual number,
a1 = ForwardDiff.Dual{:tag1}(1.0,1.0)
a2 = ForwardDiff.Dual{:tag1}(2.0,1.0)
a3 = ForwardDiff.Dual{:tag1}(3.0,1.0)
A = ForwardDiff.Dual{:tag2}(a1,a2,a3)
b1 = ForwardDiff.Dual{:tag1}(1.0,1.0)
A*b1
I was naively expecting that the result of this operation would be a Dual number with a value a1*b1
(which would be a dual with tag :tag1), while the partials would be equal to a2*b1
and a3*b1
(also duals with tag :tag1). However this throws an exception:
ERROR: Cannot determine ordering of Dual tags tag1 and tag2
Am I abusing too much the intended use of ForwardDiff.Dual
in here or is there a way to do this? I’ve made use of the tags in Dual
somewhat arbitrarily here, just to differentiate the dual number types, not sure if applying tags smartly could sort this out (looking at the implementation I’m actually unsure how tagging is used internally).