10
$\begingroup$

Setting. Imagine that we have several arbitrary linear functions in 2D that can be changed manually (say, slopes are parameters). Their Min (or Max) gives a sort of piecewise continuous function.

Example. Let us take three functions.

try = {3 (1 - q), 2 (1 - q) + q, 1 + 1.5 q}

We can get a piecewise function as

Min[try]

It is fine to see it on the plot (for the domain 0<=q<=1):

Plot[{try, Min[try]}, {q, 0, 1}, Frame -> True]

enter image description here

Problem. Is there a simple way (or built-in functionality) to dynamically get coordinates (i.e., q's) of all 'breaking' points of the piecewise function?

$\endgroup$
5
  • $\begingroup$ Is Min[try] // PiecewiseExpand (and manipulation of that result) what you're after? $\endgroup$
    – ciao
    Commented Aug 9, 2015 at 7:58
  • $\begingroup$ @ciao. General and lapidary manipulation of that result would suffice. $\endgroup$
    – garej
    Commented Aug 9, 2015 at 8:09
  • 1
    $\begingroup$ With[{rt = Rationalize[try]}, {#, Reduce[Min[rt] == #]} & /@ rt] might also float your boat - in either case, you'll need to massage the results to pull out the items of interest.... $\endgroup$
    – ciao
    Commented Aug 9, 2015 at 8:12
  • $\begingroup$ @ciao, that is the 'massage' that puzzles me =) I see, that I have to collect all 'unique' bounds of intervals, but a bit confused how to do that efficiently. any ideas? $\endgroup$
    – garej
    Commented Aug 9, 2015 at 8:19
  • $\begingroup$ In example, one needs to transform @ciao result into something like {q -> 1/2, q -> 2/5} $\endgroup$
    – garej
    Commented Aug 9, 2015 at 8:37

3 Answers 3

8
$\begingroup$

I have a kind of cheating way, which assumes that the function is differentiable except at the join-points and is not differentiable at the join-points:

Reduce[Not@Reduce[D[Min[try], q] \[Element] Reals, q], q] // ToRules // List

This works for your specified "linear functions" scenario; with your given function, it returns {{q -> 2/5}, {q -> 1/2}}.

$\endgroup$
1
  • $\begingroup$ Smart solution. Thank you. $\endgroup$
    – garej
    Commented Aug 9, 2015 at 14:19
12
$\begingroup$

The undocumented function Internal`FromPiecewise seems to take a Piecewise function in the standard form returned by PiecewiseExpand and return a list consisting of a partition of the real numbers into intervals and a list of corresponding values.

try = {3 (1 - q), 2 (1 - q) + q, 1 + 1.5 q};
Internal`FromPiecewise@ PiecewiseExpand@ Min[try]
(*  {{0.4 <= q < 1/2, q >= 1/2, q < 0.4}, {2 - q, -3 (-1 + q), 1 + 1.5 q}}  *)

Since each break point occurs one at an equality (i.e. <= or >=), we can extract them and solve. The function ineqToEq converts an inequality like those above to an equality or to False (which signifies no end point).

ineqToEq[ie_] := Replace[
  LogicalExpand@ ie /. Less | Greater -> (True &),
   {(GreaterEqual | LessEqual)[a_, b_] :> a == b, True -> False}
  ]

Applied to the OP's example:

Or @@ ineqToEq /@ First@ Internal`FromPiecewise@ PiecewiseExpand@ Min[try] // Solve
(*  {{q -> 0.4}, {q -> 1/2}}  *)

This following passes Patrick Stevens's clever D test, but this method finds the break point:

f = Piecewise[{{q^3, q < 0}}, q^2];
Or @@ ineqToEq /@ First@ Internal`FromPiecewise@ PiecewiseExpand@ f // Solve
(*  {{q -> 0}}  *)

Another internal alternative

There are many functions in Mathematica that process the discontinuities of a piecewise function. You would think there would be an easy way to do it, but there doesn't seem to be one. Well, here's a different function, again internal, undocumented, and subject to change, which is used by NIntegrate. One advantage is that it handles Min with the user first converting it to a Piecewise function.

Here's how it works on the OP's function:

NIntegrate`PiecewiseNIntegrateMultipleRanges[
 Min[try], {{q, -Infinity, Infinity}}, {(* options *)}, {(* piecewise options *)}]
(*  {{2 - q, {q, 2/5, 1/2}}, {-3 (-1 + q), {q, 1/2, ∞}}, {1/2 (2 + 3 q), {q, -∞, 2/5}}} *)

General function and example:

pwBreaks[f_, x_] := 
 DeleteCases[Infinity | -Infinity]@*Union @@ 
  NIntegrate`PiecewiseNIntegrateMultipleRanges[
    f, {{x, -Infinity, Infinity}}, {}, {}][[All, 2, 2 ;; 3]]

pwBreaks[Min[try], q]
(*  {2/5, 1/2}  *)
$\endgroup$
4
  • $\begingroup$ I was waiting for somebody to bring up FromPiecewise[]… :) $\endgroup$ Commented Aug 14, 2015 at 15:37
  • $\begingroup$ @J.M. Thanks. You'd think there would a common internal way to turn an inequality into an iterator {x, a, b} or return the end points -- I can't find one. Dealing with the multiplicity of forms of inequalities is irritating. Know of something? $\endgroup$
    – Michael E2
    Commented Aug 14, 2015 at 16:01
  • 1
    $\begingroup$ None offhand; a function that converts inequalities to a standard form (e.g. entirely in terms of </<=) would be very handy. $\endgroup$ Commented Aug 14, 2015 at 16:07
  • $\begingroup$ Now, that, I haven't tried using. Nice find! $\endgroup$ Commented Aug 14, 2015 at 16:56
5
$\begingroup$
try = {3 (1 - q), 2 (1 - q) + q, 1 + 1.5 q} // Rationalize;

breaks = Cases[
   Last /@ (Min[try] // PiecewiseExpand)[[1]], _?NumericQ, {2}] // 
  Union

{2/5, 1/2}

$\endgroup$
2
  • $\begingroup$ Rule[q, #] & /@ breaks. Very nice, thank you. $\endgroup$
    – garej
    Commented Aug 9, 2015 at 14:18
  • 1
    $\begingroup$ Sorry, I have to break the rule and say very impressive! $\endgroup$ Commented Aug 16, 2015 at 0:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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