我如何在MATLAB中创建分段内联函数? [英] How can I create a piecewise inline function in MATLAB?

查看:424
本文介绍了我如何在MATLAB中创建分段内联函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在MATLAB中有一个函数,它将另一个函数作为参数。我想以某种方式定义一个可以传入的分段内联函数。这在MATLAB中有些可能吗?



编辑:我想表示的函数是:

  f(x)= {1.0,0.0 <= x <= 0.5,
-1.0,0.5 < ; x <= 1.0

其中0.0 <= x <= 1.0


解决方案

你确实已经定义了一个具有三个断点的分段函数,即在[0,0.5,1]处。但是,您尚未定义中断之外的函数值。 (顺便说一句,我在这里使用了break这个术语,因为我们确实定义了一个简单形式的样条,一个分段恒定的样条。我也可能使用了knot这个词,这是spline世界中另一个常用词。 )



如果您绝对知道您永远不会评估[0,1]之外的函数,那么就没有问题。那么就用x = 0.5定义一个具有一个断点的分段函数。定义像您的分段常量函数的简单方法是使用逻辑运算符。因此,测试(x> 0.5)返回一个常数,即0或1.通过缩放和翻译结果,很容易生成一个你想要的功能。

  constfun = @(x)(x> 0.5)* 2  -  1; 

内联函数做类似的事情,但内联函数与匿名函数相比非常慢。我强烈建议使用匿名表单。作为测试,试试这个:

  infun = inline('(x> 0.5)* 2  -  1','x ); 
x = 0:.001:1;

tic,y = constfun(x); toc
经过的时间为0.002192秒。

tic,y = infun(x); toc
已用时间为0.136311秒。

是的,内联函数花费的时间比匿名表单要多得多。



我在这里使用的简单分段常数形式存在的一个问题是,当你有更多的断点时,难以扩展到。例如,假设你想定义一个函数,它取决于点落在哪个时间间隔内的三个不同值。虽然这也可以通过创造性地使用测试来完成,但要小心地移动和缩放它们,它会变得很讨厌。例如,当x <1时,如何定义返回的分段函数

  -1。 0,
2当0 <= x < 1,
1当1 <= x

一个解决方案是使用一个单位<一个href =http://en.wikipedia.org/wiki/Heaviside_step_function =noreferrer> Heaviside 功能。首先,定义一个基本单位Heaviside函数。

  H = @(x)(x> = 0); 

我们的分段函数现在从H(x)派生而来。
$ (x)-1 + H(x)* 3 + H(x-1)*( - 1); b $ b

  

看到P(x)有三块。第一项是x在第一个转折点以下发生的情况。然后我们添加一个效果在零以上的作品。最后,第三部分在上面x == 1的另一个偏移量中添加。它很容易被绘制出来。

  ezplot(P, [-3,3])

从一开始就可以轻松生成更复杂的样条曲线。 Se我再次调用这个构造样条。真的,这是我们可能领先的地方。事实上,这是导致这种情况的原因。样条线是一个分段函数,仔细连接在一个节点或断点列表中。特别是样条通常具有指定的连续性顺序,所以例如,三次样条在整个中断处将是两次可微的(C2)。也有分段立方函数只有C1函数。我的观点是我已经描述了一个简单的起点来形成任何分段函数。它对于多项式样条很好,但可能需要一点点数学来选择这些函数的系数。

另一种创建这个函数的方法是显式分段多项式。在MATLAB中,我们有很少的已知函数mkpp。尝试一下......

  pp = mkpp([0 .5 1],[1; -1]); 

如果您使用样条线工具箱,那么fnplt会直接为您绘制。假设你没有这种结核病,那就这样做:

  ppfun = @(x)ppval(pp,x); 
ezplot(ppfun,[0 1])$ ​​b $ b

回顾mkpp调用,毕竟是相当简单的。第一个参数是曲线中断点的列表(作为ROW向量)。第二个参数是一个COLUMN向量,在这两个间隔之间定义的间隔中曲线将采用分段常量值。几年前,我发布了另一个选项, piecewise_eval 。它可以从MATLAB Central文件交换中下载。这是一个函数,它允许用户将分段函数完全指定为断点列表,以及这些断点之间的功能块。因此,对于在x = 0.5处有单个中断的函数,我们可以这样做:

  fun = @(x)piecewise_eval (X,0.5%,{1,-1}); 

请参阅第三个参数提供每个段中使用的值,但这些段不一定是纯常数功能。如果你希望这个函数在感兴趣的时间间隔之外返回NaN,这也很容易实现。

  fun = @ (x)piecewise_eval(x,[0 0.5 1],{NaN,1,-1,NaN}); 

在这个相当漫长的游览中,我的观点是理解分段函数是什么,以及几种方法在MATLAB中构建一个。


I have a function in MATLAB which takes another function as an argument. I would like to somehow define a piecewise inline function that can be passed in. Is this somehow possible in MATLAB?

Edit: The function I would like to represent is:

f(x) = { 1.0,  0.0 <= x <= 0.5,
         -1.0, 0.5 < x <= 1.0

where 0.0 <= x <= 1.0

解决方案

You really have defined a piecewise function with three break points, i.e., at [0, 0.5, 1]. However, you have not defined the value of the function outside of the breaks. (By the way, I've used the term "break" here, because we are really defining a simple form of spline, a piecewise constant spline. I might also have used the term knot, another common word in the world of splines.)

If you absolutely know that you will never evaluate the function outside of [0,1], then there is no problem. So then just define a piecewise function with ONE break point, at x = 0.5. The simple way to define a piecewise constant function like yours is to use a logical operator. Thus the test (x > 0.5) returns a constant, either 0 or 1. By scaling and translating that result, it is easy to generate a function that does what you wish.

constfun = @(x) (x > 0.5)*2 - 1;

An inline function does a similar thing, but inline functions are VERY slow compared to an anonymous function. I would strongly recommend use of the anonymous form. As a test, try this:

infun = inline('(x > 0.5)*2 - 1','x');
x = 0:.001:1;

tic,y = constfun(x);toc
Elapsed time is 0.002192 seconds.

tic,y = infun(x);toc
Elapsed time is 0.136311 seconds.

Yes, the inline function took wildly more time to execute than did the anonymous form.

A problem with the simple piecewise constant form I've used here is it is difficult to expand to when you have more break points. For example, suppose you wished to define a function that took on three different values depending on what interval the point fell in? While this can be done too with creative use of tests, carefully shifting and scaling them, it can get nasty. For example, how might one define the piecewise function that returns

-1 when x < 0,
2 when 0 <= x < 1,
1 when 1 <= x

One solution is to use a unit Heaviside function. So first, define a basic unit Heaviside function.

H = @(x) (x >= 0);

Our piecewise function is now derived from H(x).

P = @(x) -1 + H(x)*3 + H(x-1)*(-1);

See that there are three pieces to P(x). The first term is what happens for x below the first break point. Then we add in a piece that takes effect above zero. Finally, the third piece adds in another offset in above x == 1. It is easily enough plotted.

ezplot(P,[-3,3])

More sophisticated splines are easily generated from this beginning. Se that I've called this construct a spline again. Really, this is where we might be leading. In fact, this is where this leads. A spline is a piecewise function, carefully tied together at a list of knots or break points. Splines in particular often have specified orders of continuity, so for example, a cubic spline will be twice differentiable (C2) across the breaks. There are also piecewise cubic functions that are only C1 functions. My point in all of this is I've described a simple beginning point to form any piecewise function. It works quite well for polynomial splines, although there may be a wee bit of mathematics required to choose the coefficients of these functions.

Another way to create this function is as an explicit piecewise polynomial. In MATLAB, we have the little known function mkpp. Try this out...

pp = mkpp([0 .5 1],[1;-1]);

Had you the splines toolbox, then fnplt will plot this directly for you. Assuming that you don't have that TB, do this:

ppfun = @(x) ppval(pp,x);
ezplot(ppfun,[0 1])

Looking back at the mkpp call, it is rather simple after all. The first argument is the list of break points in the curve (as a ROW vector). The second argument is a COLUMN vector, with the piecewise constant values the curve will take on in these two defined intervals between the breaks.

Several years ago I posted another option, piecewise_eval. It can be downloaded from the MATLAB Central file exchange. This is a function that will allow a user to specify a piecewise function purely as a list of break points, along with functional pieces between those breaks. Thus, for a function with a single break at x = 0.5, we would do this:

fun = @(x) piecewise_eval(x,0.5,{1,-1});

See that the third argument provides the value used in each segment, although those pieces need not be purely constant functions. If you wish the function to return perhaps a NaN outside of the interval of interest, this too is easily accomplished.

fun = @(x) piecewise_eval(x,[0 0.5 1],{NaN,1,-1,NaN});

My point in all of this rather lengthy excursion is to understand what a piecewise function is, and several ways to build one in MATLAB.

这篇关于我如何在MATLAB中创建分段内联函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆