Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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