4

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

?

ArgentoSapiens
  • 7,780
  • 1
  • 32
  • 49

5 Answers5

2

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

ArgentoSapiens
  • 7,780
  • 1
  • 32
  • 49
1
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]]]]]*)
Dr. belisarius
  • 115,881
  • 13
  • 203
  • 453
1

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!

ciao
  • 25,774
  • 2
  • 58
  • 139
1
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]] *)
kglr
  • 394,356
  • 18
  • 477
  • 896
0
(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]]]]*)
Basheer Algohi
  • 19,917
  • 1
  • 31
  • 78