MATLAB: È possibile sovraccaricare gli operatori su costrutti nativi (cellule, strutture, ecc.)?
-
27-10-2019 - |
Domanda
Sto usando le celle per gestire i dati in alcune cose su cui sto lavorando. Mi piacerebbe poter fare cose come:
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 );
Tuttavia, non voglio che la sintassi estremamente verbosa lo faccia. Sembra un po 'esagerato creare una nuova classe per questo quando tutto quello che voglio fare è fornire una definizione per gli operatori di matematica sulle celle.
La domanda: una classe è l'unico modo per farlo?
Se scrivo una classe per farlo, certamente rende più facile scrivere il codice. I maggiori negativi che vedo sono legati alle ottimizzazioni, anche se ci sono alcune altre cose che mi infastidiscono ..
Eventuali ottimizzazioni in corso dietro le quinte (ad esempio, quando la giacca compila qualcosa da eseguire su una GPU) avrebbe potenzialmente più difficile determinare quali ottimizzazioni fare. Ad esempio, supponiamo di avere due cellule (a, b) contenenti una serie di matrici di dimensione appropriata. Se scrivo codice per produrre una nuova cella:
Z = c1*A + c2*B
... Con gli scalari {C1, C2}, posso scriverlo in modo tale che la giacca (o qualsiasi altra cosa) determinerà facilmente che dovrebbe fare i calcoli come:
Z{kk} = c1*A{kk} + c2*B{kk}
O forse un'ottimizzazione ancora migliore di così. Altrimenti. Può finire con qualcosa di più lento e/o meno efficiente della memoria, ad esempio:
temp1 = cellfun( @(X)( c1*X ), A );
temp2 = cellfun( @(X)( c2*X ), B );
Z = cellfun( @plus, temp1, temp2 );
Supponendo che matlab o giacca non siano in grado di ottimizzarlo, ciò finirebbe per usare troppa memoria.
Soluzione
È in effetti possibile creare nuovi operatori o sovraccaricare quelli esistenti per tipi di dati integrati in MATLAB. Descrivo un esempio di questo in la mia risposta a un'altra domanda così su Modifica del comportamento di overflow predefinito dei tipi interi.
Innanzitutto, potresti voler guardare quali metodi esistono attualmente per gli array di celle. Puoi farlo usando la funzione Metodi, ed ecco cosa ottengo in 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
I metodi dell'operatore aritmetico verrebbero visualizzati nell'elenco sopra come loro Equivalenti della funzione, piace plus
per il +
operatore o times
per il .*
operatore. Solo il transpose
metodo (.'
operatore) è definito per gli array di celle. Dovresti creare il resto da solo, definendo come un determinato operatore si comporterà per gli argomenti di array di celle.
Puoi farlo prima creando una nuova cartella chiamata @cell
e posizionandolo in una cartella esistente sul tuo Matlab Path. Positeresti quindi i tuoi nuovi metodi in @cell
cartella. Ad esempio, a molto semplice implementazione di a plus
Metodo per array di celle (senza alcun controllo input, controllo degli errori, ecc.) Sarebbe questo:
function C = plus(A,B)
C = cellfun(@plus,A,B,'UniformOutput',false); %# Apply plus cell-wise
end
Nel codice sopra, probabilmente vorresti prima verificare che gli operandi A
e B
sono array di celle della stessa dimensione. Tuttavia, potresti creare qualsiasi funzionalità unica che desideri, come consentire B
essere un valore scalare che verrebbe aggiunto a ogni cella di A
. Sta totalmente a te definire come il +
L'operatore si comporterà per gli array di celle.
Ciò ti consentirebbe quindi di scrivere il tuo codice in un modo molto più compatto, come in questo esempio:
>> 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
Non posso davvero parlare con le ottimizzazioni dietro le quinte e come ciò possa influenzarle. So che la documentazione "Tecniche per migliorare le prestazioni" lo menziona specificamente su sovraccarico di funzioni integrate:
Il sovraccarico di funzioni integrate MATLAB su una qualsiasi delle classi di dati MATLAB standard può influire negativamente sulle prestazioni. Ad esempio, se sovraccarichi il
plus
Funzione per gestire una qualsiasi delle classi intera in modo diverso, è possibile ostacolare alcune ottimizzazioni nel codice funzione integrato MATLAB perplus
, e quindi può rallentare tutti i programmi che utilizzano questo sovraccarico.
Tuttavia, nel tuo caso non stai sovraccaricando esistente funzioni per una classe. Stai semplicemente creando di nuovi che non esistevano per quella classe, quindi è difficile dire quale effetto ciò possa avere alla fine sulle prestazioni.