4
$\begingroup$

For later conversion into a programming language where if is the only conditional construct, I would like to convert a Piecewise into a nested If in Mathematica. For instance, how can I convert:

f = Piecewise[{{x^3, x < -1}, {-x^2, -1 <= x < 0}, {x, 0 <= x < 1}, {Sqrt[x], 1 <= x}}]

into

If[x < -1, x^3, If[-1 <= x < 0, -x^2, If[0 <= x < 1, x, If[1 <= x, Sqrt[x], 0]]]]

?

$\endgroup$
2
$\begingroup$

Note the structure of Piecewise. The first element is a list of {value, condition} pairs and the second element is the "default" value for when no other condition applies. If you view it as a list, here's how f looks:

f /. Piecewise -> List

{{{x^3, x < -1}, {-x^2, -1 <= x < 0}, {x, 0 <= x < 1}, {Sqrt[x], 1 <= x}}, 0}

First, here is a recursive function to nest each list at the third position of the previous list, stopping at the deepest list.

nestLists[lists_] := If[Length[lists] == 1, lists[[1]], {Sequence @@ lists[[1]], nestLists[Rest[lists]]}]

This lets us do this:

nestLists[Map[Reverse,f[[1]]]

yielding

{x < -1, x^3, {-1 <= x < 0, -x^2, {0 <= x < 1, x, {1 <= x, Sqrt[x]}}}}

We still need to insert the default value into the third position of the deepest list, then convert the Lists to Ifs.

pwti[pw_] := ReplaceAll[Insert[#, pw[[2]], ConstantArray[-1, Length[Flatten[#]]/2]] &[nestLists[Map[Reverse, pw[[1]]]]], List -> If]

Now the Piecewise can be directly converted thus:

pwti[f]

If[x < -1, x^3, If[-1 <= x < 0, -x^2, If[0 <= x < 1, x, If[1 <= x, Sqrt[x], 0]]]]

Note that this will probably be broken if any of the values or conditions contains a list...

$\endgroup$
  • $\begingroup$ Does anyone know a better way? $\endgroup$ – ArgentoSapiens Mar 6 '15 at 1:56
1
$\begingroup$
ifs = Reverse /@ (f /. Piecewise -> List /. {{x__, v_}, e_} :> {x, Join[{e}, v]});
Hold @@ Quiet@(ifs //. {x___, {a__, b__}, {c__, d__}, e___} :> {x, {a, b, {c, d}}, e} /. List -> If)

(* Hold[If[x < -1, x^3, If[-1 <= x < 0, -x^2, If[0 <= x < 1, x, If[1 <= x, Sqrt[x], 0]]]]]*)
$\endgroup$
  • $\begingroup$ Try on my f3 case... $\endgroup$ – ciao Mar 6 '15 at 2:50
  • $\begingroup$ @rasher He's migrating the code, so no lists on the new platform either :)} $\endgroup$ – Dr. belisarius Mar 6 '15 at 2:58
  • $\begingroup$ Just joking. Or not :) $\endgroup$ – Dr. belisarius Mar 6 '15 at 2:58
1
$\begingroup$

My quick-n-dirty (meaning pretty untested on anything but simple cases):

toif = With[{if = If @@@ (Reverse /@ #[[1]]), l = #[[2]]}, 
    Nest[{Insert[#[[1]], if[[Length@#[[2]] + 1]], #[[2]]], 
        Append[#[[2]], -1]} &, {if[[1]], {-1}}, Length@if - 1] //
        Insert[#[[1]], l, #[[2]]] &] &;

Seems a bit more robust than your solution:

f1 = Piecewise[{{x^3, x < -1}, {-x^2, -1 <= x < 0}, {x, 
     0 <= x < 1}, {Sqrt[x], 1 <= x}}];

f2 = Piecewise[{{x*2, x[1] == 2}, {x*3, x[2] == 3}}];

f3 = Piecewise[{{2, x == {1, 2, 3}}, {{1, 2, 3}, x == {3, 2, 1}}, {x, 
     True}}];

Column[{toif[f1],pwti[f1]," ",
        toif[f2],pwti[f2]," ",
        toif[f3],pwti[f3]}]

(*

If[x<-1,x^3,If[-1<=x<0,-x^2,If[0<=x<1,x,If[1<=x,Sqrt[x],0]]]]
If[x<-1,x^3,If[-1<=x<0,-x^2,If[0<=x<1,x,If[1<=x,Sqrt[x],0]]]]

If[x[1]==2,2 x,If[x[2]==3,3 x,0]]
0

If[x=={1,2,3},2,If[x=={3,2,1},{1,2,3},x]]
x

*)

I'll ponder further when lounging later, gut tells me there's an elegant way to do this.

Much prettier:

toif2 = Fold[Insert[#2, #1, {-1}] &, Prepend[If @@@ Reverse /@ #[[1]], #[[2]]]] &;

toif2[f3]

(* If[x == {3, 2, 1}, {1, 2, 3}, If[x == {1, 2, 3}, 2, x]] *)

N.b.: this reorders terms, end result is the same. Completely untested - gotta go eat!

$\endgroup$
1
$\begingroup$
pwToIf = With[{fpw = Reverse@Transpose@Internal`FromPiecewise@#}, 
              Fold[If[## & @@ #2, #] &, fpw[[1, 2]], fpw[[2 ;;]]]] &;

Examples:

pw = Piecewise[{{x^3, x < -1}, {-x^2, -1 <= x < 0}, {x, 0 <= x < 1}, {Sqrt[x], 1 <= x}}];
pwToIf@pw
(* If[x < -1, x^3, If[-1 <= x < 0, -x^2, If[0 <= x < 1, x, If[1 <= x, Sqrt[x], 0]]]] *)

pw2 = Piecewise[{{x^3, x < -1}, {-x^2, -1 <= x < 0}, {x,  0 <= x < 1}, {Sqrt[x], 1 <= x}}, 100];
pwToIf@pw2
(* If[x < -1, x^3, If[-1 <= x < 0, -x^2, If[0 <= x < 1, x, If[1 <= x, Sqrt[x], 100]]]]*)

pw3 = Piecewise[{{2, x == {1, 2, 3}}, {{1, 2, 3}, x == {3, 2, 1}}, {x, True}}]; (* rasher's f3*)
pwToIf@pw3
(* If[x == {1, 2, 3}, 2, If[x == {3, 2, 1}, {1, 2, 3}, x]] *)
$\endgroup$
0
$\begingroup$
(Fold[{Sequence @@ (Reverse@#2), #1} &, f[[2]], Reverse@f[[1]]]) /.List -> If
(*If[x < -1, x^3,If[-1 <= x < 0, -x^2, If[0 <= x < 1, x, If[1 <= x, Sqrt[x], 0]]]]*)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.