-
Notifications
You must be signed in to change notification settings - Fork 7
Closed
Description
Hello,
I'm trying to inverse a piecewiese defined function using InverseFunctions.jl
using Test
using InverseFunctions
function get_rate_multiplier(amount::Float64, tiers::Vector{Tuple{Float64, Float64}})
rate_mult = 1.0
for (threshold, multiplier) in sort(tiers)
if amount >= threshold
rate_mult = multiplier
end
end
return rate_mult
end
# Calculate the final amount
function calculate_amount(amount, base_rate, tiers, fee)
return amount * base_rate * get_rate_multiplier(amount, tiers) - fee
end
base_rate = 1.1
tiers = [
(1000.0, 0.98), # 2% discount
(10000.0, 0.95), # 5% discount
]
fee = 0.0
f = amount -> calculate_amount(amount, base_rate, tiers, fee)
@test f(100.0) ≈ 110.0
@test f(1000.0) ≈ 1078.0
@test f(10000.0) ≈ 10450.0
# Inverse function
@test inverse(f)(110.0) ≈ 100.0 rtol=1e-4
@test inverse(f)(1078.0) ≈ 1000.0 rtol=1e-4
@test inverse(f)(10450.0) ≈ 10000.0 rtol=1e-4raises
Error During Test at C:\Users\femto\.julia\dev\CcyConv\mini.jl:34
Test threw exception
Expression: ≈((inverse(f))(110.0), 100.0, rtol = 0.0001)
inverse of #1 is not defined
Stacktrace:
[1] error(::String, ::Function, ::String)
@ Base .\error.jl:44
[2] (::NoInverse{var"#1#2"})(x::Float64)
@ InverseFunctions C:\Users\femto\.julia\packages\InverseFunctions\4sFsZ\src\inverse.jl:70
[3] macro expansion
@ C:\Users\femto\.julia\juliaup\julia-1.11.1+0.x64.w64.mingw32\share\julia\stdlib\v1.11\Test\src\Test.jl:676 [inlined]
[4] top-level scope
@ C:\Users\femto\.julia\dev\CcyConv\mini.jl:515
ERROR: LoadError: There was an error during testing
in expression starting at C:\Users\femto\.julia\dev\CcyConv\mini.jl:34
julia> x = 0.0:1.0:12_000.0
0.0:1.0:12000.0
julia> plot(x, [x, f.(x)])I'm aware that function is not monotonic but I'm looking to get for a y given, the lowest x value that fit f(x) = y.
Any idea what is wrong ?
Kind regards
PS : trying also with Roots.jl (in Pluto.jl)
begin
using Plots
using Roots
using InverseFunctions
# Define the original function and its inverse
#function f(x)
# return x^2
#end
function get_rate_multiplier(amount::Float64, tiers::Vector{Tuple{Float64, Float64}})
rate_mult = 1.0
for (threshold, multiplier) in sort(tiers)
if amount >= threshold
rate_mult = multiplier
end
end
return rate_mult
end
# Calculate the final amount
function calculate_amount(amount_in, base_rate, tiers, fee)
rate_multiplier = get_rate_multiplier(amount_in, tiers)
return amount_in * base_rate * rate_multiplier - fee
end
base_rate = 1.1
tiers = [
(1000.0, 0.98), # 2% discount
(10000.0, 0.95), # 5% discount
]
fee = 0.0
f = amount -> calculate_amount(amount, base_rate, tiers, fee)
function f_inv_numerical(y; initial_guess=0.0) # using Roots.jl
return fzero(x -> f(x) - y, initial_guess)
end
#function f_inv_numerical(y) # using InverseFunctions.jl
# return inverse(f)(y)
#end
# Define a range of values for y and compute f_inv numerically
x_vals_finv = 0:10.0:12_000.0
y_vals_finv = [f_inv_numerical(x) for x in x_vals_finv]
# Plot the original function f and its numerical inverse
x_vals_f = 0:10.0:12_000.0
plt = plot(x_vals_f, f.(x_vals_f), label="f", lw=2, legend=:topleft)
plot!(plt, x_vals_finv, y_vals_finv, label="f⁻¹", lw=2, linestyle=:dash)
# Plot identity function y = x
x_vals_x = 0:10.0:12_000.0
plot!(plt, x_vals_x, x_vals_x, label="y = x", lw=1, linestyle=:dot, color=:gray)
# Set labels and title
xlabel!("x")
ylabel!("y")
title!("Function f and Its Numerical Inverse")
endf(1000.0) == 1078.0
but f_inv_numerical(1078.0) == 980.0 (and not 1000.0)
Metadata
Metadata
Assignees
Labels
No labels

