MATLAB: Можно ли перегружать операторы собственных конструкций (ячеек, структур и т. д.)?

Я использую ячейки для управления данными в некоторых вещах, над которыми я работаю. Я хотел бы иметь возможность делать такие вещи, как:

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 );

Однако я не хочу, чтобы слишком многословный синтаксис делал это. Создавать для этого новый класс кажется немного чрезмерным, когда все, что я хочу сделать, это дать определение математическим операторам в ячейках.

Вопрос: Является ли класс единственным способом сделать это?

Если я напишу класс для этого, это, безусловно, облегчит написание кода. Самые большие недостатки, которые я вижу, связаны с оптимизацией, хотя есть несколько других вещей, которые меня беспокоят.

Любая оптимизация, происходящая за кулисами (например, когда куртка компилирует что-то для запуска на графическом процессоре), потенциально может затруднить определение того, какую оптимизацию сделать. В качестве примера предположим, что у меня есть две ячейки (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 не смогут его оптимизировать, это приведет к использованию слишком большого объема памяти.


person Brian Vandenberg    schedule 19.03.2011    source источник
comment
я не понимаю вопрос здесь? что ты хочешь сделать? все команды, которые вы перечислили, вполне допустимы.   -  person    schedule 20.03.2011
comment
Я немного изменил вопрос. Каждая из линий «cellfun» — это то, как это нужно делать сейчас. Строка чуть выше - это то, что я бы предпочел написать.   -  person Brian Vandenberg    schedule 20.03.2011


Ответы (1)


На самом деле можно создавать новые операторы или перегружать существующие для встроенных типов данных в MATLAB. Я описываю один пример этого в мой ответ на другой вопрос SO о изменение поведения переполнения по умолчанию для целочисленных типов.

Во-первых, вы можете посмотреть, какие методы в настоящее время существуют для массивов ячеек. Вы можете сделать это, используя функцию МЕТОДЫ, и вот что я получаю в 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

В приведенном выше коде вы, вероятно, сначала захотите проверить, что операнды A и B являются массивами ячеек одинакового размера. Однако вы можете создать любую уникальную функциональность, какую захотите, например разрешить 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 для plus и, таким образом, замедлить работу любых программ, использующих эту перегрузку.

Однако в вашем случае вы не перегружаете существующие функции для класса. Вы просто создаете новые, которых не было для этого класса, поэтому трудно сказать, какое влияние это может в конечном итоге оказать на производительность.

person gnovice    schedule 21.03.2011
comment
Ух ты. Это именно то, что мне нужно, и вы даже рассказали немного об оптимизации. Жаль, что я не могу дать бонусные баллы за это. - person Brian Vandenberg; 24.03.2011