# Need help understanding the function in linked answer (that symbolically inverts a piecewise function)

This Answer provides the following code

invPWC[f_] := Evaluate @ Module[{t},
Piecewise[
ReplacePart[
List @@ Reduce[# == f[t], t, Reals] /. {cond_ && t == expr_ :> {expr, cond}},
{-1, -1} -> True]]] &;


I get that the {-1,-1} -> True replaces the last condition with "True", and I think I get that # is being used so that the function doesn't need to define another variable.

What I am most confused about though is the following

• What is {cond_ && t == expr_ :> {expr, cond}} doing?

• List @@ is reducing the head of the Reduce output with "list", but what is the head of the Reduce output?

With regards to my first question, I figure cond_ and express_ are defined by Reduce, and here we are just accessing them (and replacing them with something?) but I have no idea what they do

With regards to my second question, I tried using FullForm on some Reduce examples, but sometimes the head seems to be And, other times Or...

It's useful to have a test input on hand when taking apart code like the one in the OP.

ff = Function[t, Piecewise[{{t/4, t < 0}, {t/2, t < 3}, {3/2 + (t - 3)*3, True}}]];


First (with a slight change of variables to help clarify the operations),

Reduce[x == ff[y], y, Reals]
(x <= 0 && y == 4 x) || (0 < x <= 3/2 && y == 2 x) || (x > 3/2 && y == 1/6 (15 + 2 x))


This generates a bunch of conditions in disjunctive normal form (DNF), corresponding to the pieces of the function to be inverted.

List @@ %
{x <= 0 && y == 4 x, 0 < x <= 3/2 && y == 2 x, x > 3/2 && y == 1/6 (15 + 2 x)}


Here, Apply[] (@@) converts the disjunction (Or[]) into a list of conditions.

% /. {cond_ && y == expr_ :> {expr, cond}}
{{4 x, x <= 0}, {2 x, 0 < x <= 3/2}, {1/6 (15 + 2 x), x > 3/2}}


We match each conjunction (And[], &&), and extract the pieces required to build a Piecewise[] function out of them. Taking the first piece x <= 0 && y == 4 x as an example, and using the pattern cond_ && y == expr_ :> {expr, cond}, cond_ corresponds to x <= 0, and expr_ corresponds to 4 x.

ReplacePart[%, {-1, -1} -> True]
{{4 x, x <= 0}, {2 x, 0 < x <= 3/2}, {1/6 (15 + 2 x), True}}


As you mentioned, this just converts the last condition to True (corresponding to the "default" case of the Piecewise[] function). Finally, this can be fed to Piecewise[] directly:

Piecewise[%]
Piecewise[{{4 x, x <= 0}, {2 x, 0 < x <= 3/2}}, (15 + 2 x)/6]


The rest of the function with its (Evaluate[(* stuff *)] & is just one way to produce a pure function instead of a function with an explicit variable.

With regards to my second question, I tried using FullForm on some Reduce examples, but sometimes the head seems to be And, other times Or...

That's actually a weakness of the current approach. The function as currently implemented assumes the output of Reduce[] is always DNF. One way to ensure that this is always the case is to use BooleanConvert[], e.g. BooleanConvert[Reduce[x == ff[y], y, Reals], "DNF"].

• I'm still confused on one thing: Why do we need y=expr_ as opposed to just expr_ -- for example, we don't have a y=cond_.. Also, This is a really good answer, thanks. – majmun Jan 29 at 19:52
• Look carefully at the structure of e.g. x <= 0 && y == 4 x. y == cond_ does not match x <= 0 (i.e. MatchQ[x <= 0, y == cond_] returns False). However, y == 4 x does match y == expr_ (i.e. MatchQ[y == 4 x, y == expr_] returns True), but you don't need the y == portion, so you peel out the required piece in the replacement rule. – J. M.'s discontentment Jan 29 at 22:58
• That makes sense. Thanks – majmun Jan 29 at 23:01