• 为了保证你在浏览本网站时有着更好的体验,建议使用类似Chrome、Firefox之类的浏览器~~
    • 如果你喜欢本站的内容何不Ctrl+D收藏一下呢,与大家一起分享各种编程知识~
    • 本网站研究机器学习、计算机视觉、模式识别~当然不局限于此,生命在于折腾,何不年轻时多折腾一下

MatLab元编程简介

cv admin 4年前 (2015-05-30) 1459次浏览 0个评论 扫描二维码

这篇文章对 Matlab 中的元编程进行了简单的介绍。Matlab 是一个古老而又高度专业化的语言。由于这一原因,缺乏很多在现代或者通用语言中拥有的特性。然而,用一些简单的工具,我们可以发现 Matlab 也可以足够灵活去进行非常简单的元编程。

什么是元编程?为什么用 Matlab 来做

粗浅的说,元编程是将程序视为数据的过程——意味着一个程序可以像一个普通的数据片段一样被制造并且被操作。像 Ruby 语言就显示出了一些作为元编程语言的特性。Matlab 未能提供这样的一套工具用于进行元编程。然而事实上用一点创造性就能实现,用一些简单的工具箱完成这一点。

注意如果把这一部分的内容称为元编程的话,可能会有一些夸张,但是我认为内容上已经足够接近去自证这样的标签。

前提条件

本文的代码能运行是基于如下条件的:

  • 函数是可实例化的(first class objects)
  • 函数可以被匿名定义
  • 符号表达式可以变作程序执行.

粗略的讲, 这些使我们可以定义符号表达式,修改他们,而且使他们变为函数。这就是这篇文章的核心观点

使用和修改符号表达式

首先定义一个符号变量

x = sym('x');

MATLAB 将会将 x 当做符号来处理,而不是数字。 然后我们可以构造更复杂的表达式,例如:

>> x + x
ans =
2*x
>> x * x
ans =
x^2
>> sin(x)^2 + cos(x)^2
ans =
sin(x)^2 + cos(x)^2

当然,最后一个表达式恒等于 1. MATLAB 也知道:

>> simplify(sin(x)^2 + cos(x)^2)
ans =
1

而且可以做微积分:

>> diff(3*x^2 + sin(x))
ans =
6*x + cos(x)
>> int(6*x + cos(x))
ans =
sin(x) + 3*x^2
>> taylor(exp(x), x, 0, 'Order', 10)
ans =
x^9/362880 + x^8/40320 + x^7/5040 + x^6/720 + x^5/120 + x^4/24 + x^3/6 + x^2/2 + x + 1

symbolic 工具箱有一个叫 matlabFunction 的函数,可以把表达式专为一个函数:

>> p = matlabFunction(x^2 + 2*x + sin(x))
p =
@(x)x.*2.0+sin(x)+x.^2
>> p(0.2)
ans =
0.6387

有此利器在手,我们就可以编写,能写程序的程序了。

傅里叶级数逼近

傅里叶级数是一种函数逼近,由不同周期的正弦、余弦进行线性组合构成。 一个实际函数 f(x) 可以由如下级数逼近:

f(x)≈a02+∑n=1∞ancos(nx)+∑n=1∞bnsin(nx)

where:

a0=1π∫π−πf(x)dx an=1π∫π−πf(x)cos(nx)dx bn=1π∫π−πf(x)sin(nx)dx

这个近似已经精确地由这几个函数描述了, 但是我们准备写一个程序来近似一个随机的真实的函数,就用这个级数的截断的版本。

元编程实现傅里叶级数近似

现在,我们要实现一个函数,接收一个函数作为参数,返回另一个函数,是输入函数的截断的傅里叶级数近似。 有些更好的方法来实现元编程, 这里只是作为元编程的优雅的示例。

这个函数应按照如下形式工作

>> g = fourierapprox(f, N);

其中 f 是一个函数, N 是 f 逼近中的最高项,g 为得到的近似函数。

首先, 我们创建一个符号表达式(最终会被转为 MATLAB 函数), 定义为一个独立变量 x 。然后添加 series 的第一项:

function [fn] = fourierapprox(f, N)
    series = sym();
    x = sym('x');
    a_0 = (1/pi) * integral(f, -pi, pi);
    series = series + (1/2)*a_0;
    ...
end

(注意,我们使用 MATLAB 自带的数值方法来计算必要的积分。)

下一步, 我们需要向 series 中添加有限项 (N)的正弦跟余弦的线性组合 :

function [fn] = fourierapprox(f, N)
    series = sym();
    x = sym('x');
    a_0 = (1/pi) * integral(f, -pi, pi);
    series = series + (1/2)*a_0;
    for n = 1:N
        a_n = (1/pi) * integral(@(x) f(x) .* cos(n*x), -pi, pi);
        series = series + a_n * cos(n*x);
        b_n = (1/pi) * integral(@(x) f(x) .* sin(n*x), -pi, pi);
        series = series + b_n * sin(n*x);
    end
    fn = matlabFunction(series);
end

最后一行很关键: 他将一个单纯的符号变量转为一个可执行的函数。 这意味着 fn 表现的跟硬编码的函数一样! 称之为 ‘元编程’ 是没问题的, 因为我们通过程序生成了这个函数。

执行这个函数

我们来用刚才的函数生成一些近似函数看看。

下面这个函数将使用特定的间距在同一坐标系内绘出原函数跟傅里叶近似函数

function [ output_args ] = plotfourierapprox(f, N, a, b)
    fplot(f, [a b], 'r');
    hold on;
    pn = fourierapprox(f, N);
    fplot(pn, [a b], 'b');
end

方波

>> plotfourierapprox(@square, 5, -5, 5)

MATLAB 元编程介绍

>> plotfourierapprox(@square, 15, -5, 5)

MATLAB 元编程介绍

f(x)=x3

>> plotfourierapprox(@(x) x.^3, 10, -4, 4)

MATLAB 元编程介绍

最后的话

元编程不是 MATLAB 中典型的编程范式。 我想展示的是,这不但可能,而且实用。

转自:http://www.codeceo.com/article/matlab-meta-programming.html


Deeplearn, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明MatLab 元编程简介
喜欢 (0)
admin
关于作者:
互联网行业码农一枚/业余铲屎官/数码影音爱好者/二次元

您必须 登录 才能发表评论!