I have a piecewise function that is continuous and strictly monotonic, like this:
f[t_] = Piecewise[{{t/4, t < 0}, {t/2, t < 3}, {3/2 + (t - 3)*3, True}}]
Now, I would like to get the inverse of that function. I would like an expression like this:
fInverse[x_] = Piecewise[{{4*x, x < 0}, {2*x, x < 1.5}, {5/2 + x/3, True}}]
(I later want to convert that expression or something derived from it of it to C code that will run on a microprocessor. So I need symbolic result, not a numerical one.)
I have tried InverseFunction[f]
, but I think it the result is a numerical inverse. I also tried Solve[f[t] == x, t]
, but it returns no result at all.
Simplify[Reduce[f[t] == x, t]]
with proper assumptions ($Assumptions = {t ∈ Reals, x ∈ Reals}
) is promising:
(t == 2 x && 0 <= x < 3/2) || (t == 4 x && x < 0) || (6 t == 15 + 2 x && 2 x >= 3)
but it's not a piecewise expression.
My next step would be to write a function piecewiseInvert
that iterates through the alternatives in the Piecewise
expression, solves each one for t
, changes the conditions appropriately, and creates a new Piecewise
, but I'm hoping that there's a simpler way to do this.
Answer
I think you're on the right track with Reduce
. If the domain Reals
is specified, Reduce
will return results that can be converted to a Piecewise
expression straightforwardly.
Clear[f];
f[t_] = Piecewise[{{t/4, t < 0}, {t/2, t < 3}, {3/2 + (t - 3)*3, True}}];
invPW[f_] := Evaluate @ Module[{t},
Piecewise[
List @@ Reduce[# == f[t], t, Reals] /. {cond_ && t == expr_ :> {expr, cond}}]] &;
fInverse = invPW[f]
fInverse[x]
One can remove the extraneous True
case by replacing the last condition by True
:
invPWC[f_] := Evaluate @ Module[{t},
Piecewise[
ReplacePart[
List @@ Reduce[# == f[t], t, Reals] /. {cond_ && t == expr_ :> {expr, cond}},
{-1, -1} -> True]]] &;
fInverse = invPWC[f]
fInverse[x]
Note: Solve
almost does it, also yielding a result that can be converted to Piecewise
easily. But it does not include the end points of the intervals when appropriate.
Solve[x == f[t], t, Reals]
(* {{t -> ConditionalExpression[2 x, 0 < x < 3/2]},
{t -> ConditionalExpression[4 x, x < 0]},
{t -> ConditionalExpression[1/6 (15 + 2 x), x > 3/2]}} *)
Comments
Post a Comment