7

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

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
Eckhard
  • 83
  • 4
  • 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]] – Pankaj Sejwal Oct 06 '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 06 '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. – Pankaj Sejwal Oct 06 '13 at 19:11
  • %/.{x->2,y->3} gives {2,3} – Eckhard Oct 06 '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}. – Pankaj Sejwal Oct 06 '13 at 19:26
  • Yes, the idea was to obtain an expression that gives the same result for all values of x and y, though. – Eckhard Oct 06 '13 at 19:30
  • Boole returns True or False, but you have x,y multiplied, so how can result be same ? Or you might be saying same as x,y per x,y replaced. For example {x->1,y->1} returns {1,1}. – Pankaj Sejwal Oct 06 '13 at 19:38
  • In Mathematica, Boole[] returns 1 or 0. – Eckhard Oct 06 '13 at 19:45

4 Answers4

9

Another option is to express Piecewise in terms of UnitStep.

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

In[2]:= Simplify`PWToUnitStep[f]
Out[2]= 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)
Greg Hurst
  • 35,921
  • 1
  • 90
  • 136
  • 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 06 '13 at 19:25
  • 1
    This is an undocumented function. – Greg Hurst Oct 08 '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. – Greg Hurst Oct 08 '13 at 15:17
1

Also

Dot @@ {Boole /@ #, #2} & @@ Internal`FromPiecewise[f]

or

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

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

kglr
  • 394,356
  • 18
  • 477
  • 896
1

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 Internal`FromPiecewise. The problem with his answer is that one argument usage of Internal`FromPiecewise 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<x<3 \\ x^3 & 2\leq x \\ 1000 & \text{True} \end{cases}$

Using the one argument version:

kglr = Dot @@ MapAt[Boole, Internal`FromPiecewise[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, Internal`FromPiecewise[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,
    Internal`FromPiecewise[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]

Carl Woll
  • 130,679
  • 6
  • 243
  • 355
1

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.

Michael E2
  • 235,386
  • 17
  • 334
  • 747
  • Thank you. Would this work if the conditions of the piecewise function are not mutually exclusive, as in your example. – Eckhard Oct 06 '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 06 '13 at 20:57