MATLAB:是否可以在本地结构(单元格,结构体等)上重载运算符?

17

我正在使用单元格来管理一些工作中的数据。我希望能够做到以下几点:

A = cellfun( @(X)( randn( 5,5 ) ), cell( 5,1 ), 'UniformOutput', 0 );
B = cellfun( @(X)( randn( 5,5 ) ), cell( 5,1 ), 'UniformOutput', 0 );
%#
%# Each of the following would fail if cell member dimensions
%# don't match up
%#
%# matrix sums for each cell entry
%# C = A + B;
C = cellfun( @(X,Y)( X + Y ), A, B, 'UniformOutput', 0 );
%#
%# direct/hadamard product
%# D = A .* B;
D = cellfun( @(X,Y)( X .* Y ), A, B, 'UniformOutput', 0 );
%#
%# matrix-matrix products (not across all entries)
%# E = A * B;
E = cellfun( @(X,Y)( X * Y ), A, B, 'UniformOutput', 0 );

然而,我不想使用过于冗长的语法。为了提供单元格上的数学运算符定义,创建一个新类似乎有些过头了。
问题是:创建一个类是唯一的方法吗?
如果我写一个类来完成这个任务,编写代码就会变得更容易。但最大的负面影响可能与优化有关,还有其他一些问题也会困扰我。
任何在幕后进行的优化(例如,当Jacket将某些内容编译为在GPU上运行时)都可能更难确定要进行哪些优化。例如,假设我有两个包含适当维度矩阵的单元格(A,B)。如果我编写代码以生成新单元格:
Z = c1*A + c2*B

如果我有一个包含标量 {c1,c2} 的向量,我可以这样写它,让Jacket(或其他工具)很容易地确定应该如何进行计算:

Z{kk} = c1*A{kk} + c2*B{kk}

或许还有更好的优化方法。否则,可能会得到一些速度较慢和/或内存效率较低的结果,例如:

temp1 = cellfun( @(X)( c1*X ), A );
temp2 = cellfun( @(X)( c2*X ), B );
Z     = cellfun( @plus, temp1, temp2 );

假设MATLAB或Jacket无法进行优化,那么这将会使用过多的内存。

我不明白这里的问题?你想要做什么?你列出的所有命令都是完全有效的。 - user564376
我稍微修改了问题。现在每个“cellfun”行都是需要完成的方式。它上面的那一行是我更愿意写的。 - Brian Vandenberg
1个回答

25

事实上,在MATLAB中可以创建新的运算符或重载现有运算符以用于内置数据类型。我在我的答案中描述了一个关于修改整数类型默认溢出行为的SO问题的例子。

首先,您可能希望查看当前存在于单元数组中的方法。您可以使用函数METHODS来完成此操作,以下是我在MATLAB R2010b中获得的结果:

>> methods cell

Methods for class cell:

aa2nt            issorted         regexptranslate  strfind          
accumarray       newdepfun        reshape          strjust          
cell2struct      nt2aa            rna2dna          strmatch         
ctranspose       nwalign          seq2regexp       strtok           
display          permute          setdiff          transpose        
dna2rna          regexp           setxor           union            
intersect        regexpi          sort             unique           
ismember         regexprep        strcat           

算术运算符方法将出现在上述列表中,其函数等效物,例如plus表示+运算符或times表示.*运算符。仅为单元数组定义了transpose方法(.'运算符)。您必须自己创建其余部分,定义给定运算符对于单元数组参数的行为。
您可以通过首先创建一个名为@cell的新文件夹并将其放置在MATLAB路径上的现有文件夹中来完成此操作。然后,您将把新方法放在@cell文件夹中。例如,单元数组的plus方法的非常简单的实现(没有任何输入检查、错误检查等)如下:
function C = plus(A,B)
  C = cellfun(@plus,A,B,'UniformOutput',false);  %# Apply plus cell-wise
end

在上面的代码中,您可能首先想要检查操作数AB是否是相同大小的单元数组。但是,您可以创建任何想要的独特功能,例如允许B成为标量值,该值将添加到A的每个单元格中。完全由您定义单元数组的+运算符的行为方式。

这将使您能够以更紧凑的方式编写代码,如以下示例所示:

>> A = {[1 2 3] [4 5] 6};  %# One 3-element cell array
>> B = {5 [4 5] 2};        %# Another 3-element cell array
>> C = A+B;                %# Use the new plus operator
>> C{:}                    %# Display the cell contents

ans =

     6     7     8

ans =

     8    10

ans =

     8

我无法真正了解幕后的优化及其可能对其产生的影响。我知道"提高性能的技术"文档特别提到了重载内置函数的问题:

重载任何标准MATLAB数据类的MATLAB内置函数可能会对性能产生负面影响。例如,如果您重载plus函数以处理任何整数类别,则可能会阻碍MATLAB内置函数代码中某些优化,从而可能使使用此重载的任何程序变慢。

然而,在您的情况下,您并没有为类重载现有函数。您只是创建了该类别中不存在的新函数,因此很难说这最终可能对性能产生什么影响。

哇,这正是我需要的,而且你甚至还涉及了优化的问题。太可惜了,我不能为此额外加分。 - Brian Vandenberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接