Skip to content

Can't inverse a piecewiese defined function #54

@femtotrader

Description

@femtotrader

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-4

raises

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)])

Function looks like:
image

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")
	
end

image

f(1000.0) == 1078.0
but f_inv_numerical(1078.0) == 980.0 (and not 1000.0)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions