# Transform Piecewise[] into sum of indicators

I'm interested in transforming a piecewise defined function into a sum of indicator functions, ultimately with the aim to be better able to integrate them.

As an example I would like to transform the function

f = Piecewise[{{x, 3*x > y && x < 2*y}, {y, 2*x > y && x < 3*y}}, 0]


into

x Boole[3 x > y && x < 2 y] + y Boole[x >= 2 y && x < 3 y].


For this specific example, this could be achieved by

f[[1,1,1]]Boole[f[[1,1,2]]] + f[[1,2,1]]Boole[f[[1,2,2]] && !f[[1,1,2]]]


but I don't know how to efficiently generalize this to functions with more than two cases, in particular how to ensure that the term corresponding to the $n$th case contains the negated conditions of the first $n-1$ cases.

In a second step, assuming that the conditions of the piecewise function are linear inequalities, I would like to decompose each Boole[] into a sum of Boole[]'s of disjoint intervals for, say, the variable $x$.

In my example above this would mean

Boole[3 x > y && x < 2 y] == Boole[y/3 < x < y/2]
Boole[x >= 2 y && x < 3 y] == Boole[2y < x < 3y]


This is maybe a trivial example, but in more complex situations one will have to deal with more than one disjoint interval. In non-Mathematica notation I'd like a decomposition of the form $$f(x) = \sum_i f_i(x) \sum_j\mathbf{1}_{\left\{x_{i,j}^{\min}<x<x_{i,j}^\max\right\}}(x).$$ where the $f_i$ are given by f[[1,All,1]].

• For a start you can try Cases[Piecewise[{{x, 3*x > y && x < 2*y}, {y, 2*x > y && x < 3*y}}, 0] /. Piecewise -> Plus, {a_, b_} -> a Boole[b]] – Sejwal Oct 6 '13 at 18:47
• Thanks @Blackbird: Does your method also give the correct result if the conditions of the piecewise function are not mutually exclusive? In the example, if x < 2y && 2x > y I think your result would give {x,y} (or x+y) whereas the original function would evaluate to x because of sequential evaluation of cases. – Eckhard Oct 6 '13 at 19:05
• Try to run above snippet and do %/.{x->2,y->4}.I didn't actually understand this mutual exclusion you said,but may be this helps. – Sejwal Oct 6 '13 at 19:11
• %/.{x->2,y->3} gives {2,3} – Eckhard Oct 6 '13 at 19:13
• Boole is deciding what you will get so, may be you need correct combination of x,y that you get only one +ive numerical result,eg {x->2,y->4} .This will get you {2,0}. – Sejwal Oct 6 '13 at 19:26

## 4 Answers

Making up a three-piece function,

f = Piecewise[{{x, x < 0}, {x^2, 0 <= x < 3}, {x^3, 3 <= x}}, 0];


we can map Boole onto the conditions of f and use Dot to sum the products of the values and the 0/1 values of the conditions thus:

Dot @@ MapAt[Boole, Transpose @ First @ f, 2]
(* x^2 Boole[0 <= x < 3] + x Boole[x < 0] + x^3 Boole[3 <= x] *)


Check:

% /. x -> 2
(* 4 *)


Update

To get an expression that is equivalent to Piecewise, one needs to nest the expressions similar to the psuedo-formula

Boole[cond] exp + (1 - Boole[cond]) (rest)


Example:

f2 = Piecewise[{{x, x < 0}, {x^2, 0 < x < 3}, {x^3, 2 <= x}}, 1000];

f2exp = Fold[(1 - Boole[Last @ #2]) #1 + Boole[Last @ #2] First[#2] &,
Last @ f2, Reverse @ First @ f2]
(* x Boole[x < 0] +
(1 - Boole[x < 0]) (x^2 Boole[0 < x < 3] +
(1 - Boole[0 < x < 3]) (1000 (1 - Boole[3 <= x]) + x^3 Boole[2 <= x])) *)

Table[f2 /. x -> i, {i, -1, 4}]
Table[f2exp /. x -> i, {i, -1, 4}]
(* {-1, 1000, 1, 4, 27, 64} *)
(* {-1, 1000, 1, 4, 27, 64} *)


Note the default value for x = 0.

• Thank you. Would this work if the conditions of the piecewise function are not mutually exclusive, as in your example. – Eckhard Oct 6 '13 at 19:08
• No, it wouldn't produce a expression equivalent to Piecewise if the conditions were not mutually exclusive, for the same reason that the method in your example would not work: Order matters in Piecewise but not in Plus. – Michael E2 Oct 6 '13 at 20:57

Another option is to express Piecewise in terms of UnitStep.

In:= f = Piecewise[{{x,3*x>y&&x<2*y},{y,2*x>y&&x<3*y}},0];

In:= SimplifyPWToUnitStep[f]
Out= x (1-UnitStep[x-2 y]) (1-UnitStep[-3 x+y])+
y ((1-UnitStep[x-3 y]) UnitStep[x-2 y] (1-UnitStep[-2 x+y])+(1-UnitStep[x-3 y])
UnitStep[-3 x+y] (1-UnitStep[-2 x+y])-(1-UnitStep[x-3 y])^2 UnitStep[x-2 y]
UnitStep[-3 x+y] (1-UnitStep[-2 x+y])^2)

• Thanks. Is this usage documented anywhere? Also, the expression multiplying y seems quite complicated. Can it be further simplified? Simplify transforms the expression back into its piecewise form. – Eckhard Oct 6 '13 at 19:25
• This is an undocumented function. – Chip Hurst Oct 8 '13 at 15:16
• I don't think it can be simplified further. Trying Simplify[x (1 - UnitStep[x - 2 y]) (1 - UnitStep[-3 x + y]) + y ((1 - UnitStep[x - 3 y]) UnitStep[ x - 2 y] (1 - UnitStep[-2 x + y]) + (1 - UnitStep[x - 3 y]) UnitStep[-3 x + y] (1 - UnitStep[-2 x + y]) - (1 - UnitStep[x - 3 y])^2 UnitStep[ x - 2 y] UnitStep[-3 x + y] (1 - UnitStep[-2 x + y])^2), ComplexityFunction -> (LeafCount[#] + 10^4 Count[#, _Piecewise, {0, \[Infinity]}] &)] doesn't make any changes. – Chip Hurst Oct 8 '13 at 15:17

Also

Dot @@ {Boole /@ #, #2} & @@ InternalFromPiecewise[f]


or

Dot @@ MapAt[Boole, InternalFromPiecewise[f], 1] (* thanks: @J.M.*)


y Boole[2 x > y && x < 3 y] + x Boole[3 x > y && x < 2 y]

• Equivalently: Dot @@ MapAt[Boole, InternalFromPiecewise[f], 1]. – J. M.'s torpor Mar 22 '17 at 9:25
• Thank you @J.M. Added your suggestion. – kglr Mar 22 '17 at 9:29

You can use PiecewiseExpand to make sure the conditions are disjoint. For your example:

pw = Piecewise[{{x, 3*x > y && x < 2*y}, {y, 2*x > y && x < 3*y}}, 0];
disjoint = PiecewiseExpand[
pw,
Method -> {"OrderlessConditions"->True, "ConditionSimplifier"->FullSimplify}
];
disjoint //TeXForm


$$\begin{cases} x & 3 x>y\land x<2 y \\ y & x\geq 2 y\land x<3 y \end{cases}$$

Since the default is 0, you can easily convert the output to your desired sum of Boole form:

bool = Replace[
disjoint,
HoldPattern @ Piecewise[c_, d_] :> Total @ Replace[c, {a_, b_} :> a Boole[b], {1}]
]


x Boole[3 x > y && x < 2 y] + y Boole[x >= 2 y && x < 3 y]

Check:

FullSimplify[pw == bool, (x|y) \[Element] Reals]


True

However, if the default isn't zero, than the above won't work. It is possible to patch things up by negating all of the non-default conditions and adding a Boole term for the default. But instead, I will suggest a small modification of @kglr's answer. His answer used the internal, undocumented function InternalFromPiecewise. The problem with his answer is that one argument usage of InternalFromPiecewise will not properly handle non-disjoint conditions. Instead, when there are non-disjoint conditions, you need to use the two argument version. Consider a small modification of Michael's example:

pw = Piecewise[{{x, x < 0}, {x^2, 0 < x < 3}, {x^3, 2 <= x}}, 1000];
pw //TeXForm


$$\begin{cases} x & x<0 \\ x^2 & 0

Using the one argument version:

kglr = Dot @@ MapAt[Boole, InternalFromPiecewise[pw], 1]


1000 + x Boole[x < 0] + x^2 Boole[0 < x < 3] + x^3 Boole[2 <= x]

This result is not equal to the original Piecewise expression:

FindInstance[pw != kglr, {x, y}, Reals]


{{x -> -1, y -> 0}}

Using the two argument version:

s = Dot @@ MapAt[Boole, InternalFromPiecewise[pw, True], 1]


x^2 Boole[x > 0 && x < 3] + 1000 Boole[x == 0] + x^3 Boole[x >= 3] + x Boole[x < 0]

Check that the result is equal to the original Piecewise expression:

FullSimplify[pw == s, (x|y) \[Element] Reals]


True

So, a function that converts piecewise expressions to a sum of indicator functions would be:

sumOfBoole[pw_Piecewise] := Dot @@ MapAt[
Boole @* FullSimplify,
InternalFromPiecewise[pw, True],
1
]


where I also included a FullSimplify call. Michael's example again:

sumOfBoole[pw]
`

1000 Boole[x == 0] + x^3 Boole[x >= 3] + x^2 Boole[0 < x < 3] + x Boole[x < 0]