       Re: piecewise function

• To: mathgroup at smc.vnet.net
• Subject: [mg109250] Re: piecewise function
• From: Ray Koopman <koopman at sfu.ca>
• Date: Mon, 19 Apr 2010 02:49:39 -0400 (EDT)
• References: <hq61qs\$3j0\$1@smc.vnet.net> <hq9c1l\$qen\$1@smc.vnet.net>

```On Apr 18, 2:57 am, Albert Retey <a... at gmx-topmail.de> wrote:
> Am 17.04.2010 12:02, schrieb Ray Koopman:
>> On Apr 16, 2:52 am, Ray Koopman <koop... at sfu.ca> wrote:
>>> On Apr 14, 8:40 pm, mircea <mircea.da... at gmail.com> wrote:
>>>> I want a define a piecewise constant function on an interval [a,b].
>>>> What I did is:
>>>>
>>>> s[x_] := Module[{out}, out = 0;
>>>>    For[i = 1, i <= N, i++,
>>>>     If[mesh[[i]] <= x < mesh[[i + 1]],
>>>>      out = (mesh[[i]] + mesh[[i + 1]])/2; Break[]]]; out];
>>>>
>>>> where:
>>>>
>>>> mesh = {x_1,x_2,..,x_{N+1} }, a = x_1 < x_2 < .. < x_{N+1} = b
>>>>
>>>> However
>>>>
>>>> PiecewiseExpand /@ s[x]
>>>>
>>>> gives me 0.....
>>>>
>>>> Thanks,
>>>> Mirela
>>>
>>> Here is a translation of your procedural s[x] into functional code:
>>>
>>> s1[x_] := First[  Cases[ Transpose@{Most@mesh,Rest@mesh},
>>>           {a_,b_} /; a <= x < b :> (a+b)/2, {1}, 1] /. {} -> {0} ]
>>>
>>> If you want it to use Piecewise then this will do it:
>>>
>>> makefunc[mesh_] := ToExpression["Function[x, Piecewise[" <>
>>>          Block[{x}, ToString[{Mean@#, #[] <= x < #[]}& /@
>>>                Transpose@{Most@mesh,Rest@mesh}]] <> "]]" ]
>>>
>>> mesh = Sort@RandomReal[{0,1},10]
>>>
>>> {0.0731222,0.0955697,0.184462,0.369542,0.476,
>>>  0.568679,0.725734,0.784328,0.860571,0.901895}
>>>
>>> s2 = makefunc[mesh]
>>>
>>> Function[x, Piecewise[{
>>> {0.084346, 0.0731222 <= x < 0.0955697},
>>> {0.140016, 0.0955697 <= x < 0.184462 },
>>> {0.277002, 0.184462  <= x < 0.369542 },
>>> {0.422771, 0.369542  <= x < 0.476    },
>>> {0.52234,  0.476     <= x < 0.568679 },
>>> {0.647207, 0.568679  <= x < 0.725734 },
>>> {0.755031, 0.725734  <= x < 0.784328 },
>>> {0.822449, 0.784328  <= x < 0.860571 },
>>> {0.881233, 0.860571  <= x < 0.901895 }}]]
>>
>> This will do the same thing, but a little more efficiently.
>>
>> makefunk[mesh_] := ToExpression["Function[x, Piecewise[" <>
>>          Block[{x}, ToString@MapThread[{#1, x < #2}&,
>>                {Prepend[(Most@mesh+Rest@mesh)/2,0],mesh}]] <> "]]" ]
>>
>> s3 = makefunk[mesh]
>>
>> Function[x, Piecewise[{
>> {0,        x < 0.0955697},
>> {0.084346, x < 0.0955697},
>> {0.140016, x < 0.184462 },
>> {0.277002, x < 0.369542 },
>> {0.422771, x < 0.476    },
>> {0.52234,  x < 0.568679 },
>> {0.647207, x < 0.725734 },
>> {0.755031, x < 0.784328 },
>> {0.822449, x < 0.860571 },
>> {0.881233, x < 0.901895 }}]]
>>
>
> It think it has several advantages to not convert to strings and back,
> which is hardly ever necessary. Here is a version which does the same
> thing without converting to strings:
>
> makefunc2[mesh_] := Block[{x},
>   Apply[
>    Function, {x,
>     Piecewise[{Mean[{##}], #1 <= x < #2} & @@@ Partition[mesh, 2, 1]]}
>    ]
>   ]
>
> If you plot the difference between the two version you will find that
> the result differs in the range of about 10^-7 which may or may not
> be a problem for your application, but shows one of the problems with
> the string conversion. Another problem with converting from strings
> to expression is that this will often fail when you decide to make a
> package of your functionb ...
>
> hth,
>
> albert

You're right, it is a little kludgy, and converting & reconverting
Reals does lose precision. Here's a revised version of makefunk:

makefunk2[mesh_] := Block[{x}, Function @@ {x, Piecewise@Transpose@
{Prepend[(Most@mesh+Rest@mesh)/2,0], Thread[x < mesh]} } ]

```

• Prev by Date: Re: ArrayPlot coordinates scaling for overlays
• Next by Date: Re: Nest and Fold don't respect HoldFirst?
• Previous by thread: Re: piecewise function
• Next by thread: Re: Equation problem