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..... >>>> >>>> Can you please help me? >>>> 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@#, #[[1]] <= x < #[[2]]}& /@ >>> 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]} } ]