# Help making ForwardDiff.derivative work

**URL:** <https://discourse.julialang.org/t/help-making-forwarddiff-derivative-work/125167>\
**Category:** Optimization (Mathematical)\
**Tags:** forwarddiff, autodiff\
**Created:** [January 24, 2025, 1:34pm UTC](https://discourse.julialang.org/t/help-making-forwarddiff-derivative-work/125167 "2025-01-24T13:34:26Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![miguelborrero](https://avatars.discourse-cdn.com/v4/letter/m/eb9ed0/32.png) [@miguelborrero](https://discourse.julialang.org/u/miguelborrero)\
**Post date:** [January 24, 2025, 1:34pm UTC](https://discourse.julialang.org/t/help-making-forwarddiff-derivative-work/125167/1 "2025-01-24T13:34:26Z")

</div>

Hi there,

I define my custom parametric types as follows:

```julia
struct Parameters{T}
    """ 
    inmutable type to pack the parameters estimated.
    """
    ϕ::T 
    λ::T 
    γ₁::T
end

struct MarketPostEstimation{T}
    """ 
    inmutable type to pack the data from each market after estimation.
    """
    s::T 
    p::T 
    x::T 
    z::T
    ξ::T
    ω::T
end

parameters = Parameters(rand(3)...)
market_1 = MarketPostEstimation(rand(6)...)

```

Then I define the following functions:

```julia
function s_func(p, market; β₀ = 1.5, β₁ = 0.5, α = -0.5)
    """
    function to compute theoretical market shares 
    inputs:
        1) p -> price_vector
        2) x -> product characteristic 
        3) ξ -> unobserved demand shock
    outputs:
        1) market share vector 
    """
    δ = β₀ + β₁ * market.x + market.ξ
    temp = map(pₖ -> exp(δ + α * pₖ), p)
    denominator = 1 + sum(temp)
    return temp ./ denominator
end

function solve_price_eq_duopoly(τ, market, parameters; α = - 0.5)
    """
    solve for the equilibrium prices for a given (τ₁, τ₂) by first solving for the "markup" and then computing the prices.
    inputs:
        1) τ tuple 
        2) market 
        3) parameter instance
    outputs:
        1) optimal (p₁, p₂) 
    """
    initial_guess = 0.0
    Δ = find_zero(Δ -> 1 + α * (Δ - parameters.λ)*(1 - sum(s_func((τ[1] + Δ, τ[2] + Δ), market))), initial_guess)
    return τ .+ Δ
end

p_1_star(τ₁, τ₂, market, parameters) = solve_price_eq_duopoly((τ₁, τ₂), market, parameters)[1]
p_2_star(τ₁, τ₂, market, parameters) = solve_price_eq_duopoly((τ₁, τ₂), market, parameters)[2]

```

and my objective is to be able to use `ForwardDiff.derivative` on those functions like:

```julia
ForwardDiff.derivative(x -> p_1_star(x, 3.4, market_1, parameters), 4.5)

```

but I get the following error:

```julia
ERROR: MethodError: no method matching Float64(::ForwardDiff.Dual{ForwardDiff.Tag{var"#67#68", Float64}, Float64, 1})
The type `Float64` exists, but no method is defined for this combination of argument types when trying to construct it.

Closest candidates are:
  (::Type{T})(::Real, ::RoundingMode) where T<:AbstractFloat
   @ Base rounding.jl:265
  (::Type{T})(::T) where T<:Number
   @ Core boot.jl:900
  Float64(::IrrationalConstants.Logten)
   @ IrrationalConstants ~/.julia/packages/IrrationalConstants/vp5v4/src/macro.jl:112
  ...

Stacktrace:
  [1] convert(::Type{Float64}, x::ForwardDiff.Dual{ForwardDiff.Tag{var"#67#68", Float64}, Float64, 1})
    @ Base ./number.jl:7
  [2] update_state
    @ ~/.julia/packages/Roots/E1WQf/src/DerivativeFree/secant.jl:38 [inlined]
  [3] update_state
    @ ~/.julia/packages/Roots/E1WQf/src/DerivativeFree/secant.jl:29 [inlined]
  [4] solve!(𝐙::Roots.ZeroProblemIterator{Secant, AlefeldPotraShi, Roots.Callable_Function{…}, Roots.UnivariateZeroState{…}, Roots.UnivariateZeroOptions{…}, Roots.NullTracks}; verbose::Bool)
    @ Roots ~/.julia/packages/Roots/E1WQf/src/hybrid.jl:54
  [5] solve!
    @ ~/.julia/packages/Roots/E1WQf/src/hybrid.jl:30 [inlined]
  [6] solve(𝑭𝑿::ZeroProblem{var"#12#13"{Float64, Tuple{…}, MarketPostEstimation{…}, Parameters{…}}, Float64}, M::Order0, p::Nothing; verbose::Bool, kwargs::@Kwargs{tracks::Roots.NullTracks})
    @ Roots ~/.julia/packages/Roots/E1WQf/src/find_zero.jl:492
  [7] find_zero(f::Function, x0::Float64, M::Order0, p′::Nothing; p::Nothing, verbose::Bool, tracks::Roots.NullTracks, kwargs::@Kwargs{})
    @ Roots ~/.julia/packages/Roots/E1WQf/src/find_zero.jl:220
  [8] find_zero (repeats 2 times)
    @ ~/.julia/packages/Roots/E1WQf/src/find_zero.jl:210 [inlined]
  [9] find_zero
    @ ~/.julia/packages/Roots/E1WQf/src/find_zero.jl:243 [inlined]
 [10] solve_price_eq_duopoly(τ::Tuple{ForwardDiff.Dual{ForwardDiff.Tag{var"#67#68", Float64}, Float64, 1}, Float64}, market::MarketPostEstimation{Float64}, parameters::Parameters{Float64}; α::Float64)
    @ Main ./REPL[13]:12
 [11] solve_price_eq_duopoly
    @ ./REPL[13]:1 [inlined]
 [12] p_1_star(τ₁::ForwardDiff.Dual{ForwardDiff.Tag{var"#67#68", Float64}, Float64, 1}, τ₂::Float64, market::MarketPostEstimation{Float64}, parameters::Parameters{Float64})
    @ Main ./REPL[57]:1
 [13] (::var"#67#68")(x::ForwardDiff.Dual{ForwardDiff.Tag{var"#67#68", Float64}, Float64, 1})
    @ Main ./REPL[99]:1
 [14] derivative(f::var"#67#68", x::Float64)
    @ ForwardDiff ~/.julia/packages/ForwardDiff/UBbGT/src/derivative.jl:14
 [15] top-level scope
    @ REPL[99]:1
Some type information was truncated. Use `show(err)` to see complete types.

```

It seems like my function checks out the requirements in the documentation but maybe I’m missing something?

Thanks a lot!  
Miguel.

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [January 24, 2025, 1:38pm UTC](https://discourse.julialang.org/t/help-making-forwarddiff-derivative-work/125167/2 "2025-01-24T13:38:42Z")

</div>

> [@miguelborrero](#):
>
> `initial_guess = 0.0`

Try providing an initial guess that has the same type as the `Dual` number, e.g.,

```julia
initial_guess = zero(eltype(τ))

```

If `τ` is the variable that is being differentiated w.r.t.

The tells the root finder that it has to setup its internal variables using this number type, instead of `Float64`, the type of `0.0`.

---

<div class="post-metadata">

**Author:** ![miguelborrero](https://avatars.discourse-cdn.com/v4/letter/m/eb9ed0/32.png) [@miguelborrero](https://discourse.julialang.org/u/miguelborrero)\
**Post date:** [January 24, 2025, 1:42pm UTC](https://discourse.julialang.org/t/help-making-forwarddiff-derivative-work/125167/3 "2025-01-24T13:42:45Z")

</div>

> [@baggepinnen](#):
>
> `initial_guess = zero(eltype(τ))`

Aha! Thanks a lot!
