Matlab: Est-il possible de surcharger les opérateurs sur les constructions indigènes (cellules, structs, etc.)?
-
27-10-2019 - |
Question
J'utilise les cellules pour gérer les données dans des choses que je travaille sur. Je voudrais pouvoir faire des choses comme:
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 );
Cependant, je ne veux pas la syntaxe extrêmement verbeux pour le faire. Il semble un peu trop loin de créer une nouvelle classe pour quand tout ce que je veux faire est de fournir une définition pour les opérateurs de mathématiques sur les cellules.
La question: est une classe la seule façon d'aller à ce sujet
Si j'écris une classe pour ce faire, il est certainement plus facile d'écrire le code. Les plus grands négatifs que je vois sont liés à des optimisations, mais il y a quelques autres choses qui me bug à ce sujet ..
Les optimisations en cours dans les coulisses (par exemple, quand veste compile quelque chose à exécuter sur un GPU) serait potentiellement avoir plus de difficulté à déterminer les optimisations à faire. A titre d'exemple, supposons que j'ai deux cellules (A, B) contenant un certain nombre de matrices de dimension appropriée. Si je écrire du code pour produire une nouvelle cellule:
Z = c1*A + c2*B
... avec {scalaires, c2} c1, je peux l'écrire dans une telle façon que veste (ou autre) détermineront facilement qu'il devrait faire les calculs:
Z{kk} = c1*A{kk} + c2*B{kk}
ou peut-être une optimisation encore mieux que cela. Autrement. il peut se retrouver avec quelque chose de plus lent et / ou moins efficace de la mémoire, par exemple:
temp1 = cellfun( @(X)( c1*X ), A );
temp2 = cellfun( @(X)( c2*X ), B );
Z = cellfun( @plus, temp1, temp2 );
En supposant Matlab ou veste ne parviennent pas à optimiser, cela finirait par utiliser trop de mémoire.
La solution
Il est en effet possible de créer de nouveaux opérateurs ou surcharge ceux qui existent déjà pour les types de données intégrés dans MATLAB. Je décris un exemple dans ma réponse à une autre question de SO à propos de modifier le comportement de débordement par défaut de types entiers .
D'abord, vous voudrez peut-être regarder quelles méthodes existent actuellement pour réseaux de cellules. Vous pouvez le faire en utilisant la fonction METHODES , et ce qui est ici, je reçois dans 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
Les méthodes de l'opérateur arithmétique apparaîtrait dans la liste ci-dessus que leurs équivalents de fonction , comme plus
pour l'opérateur de +
ou times
pour l'opérateur .*
. Seule la méthode de transpose
(opérateur .'
) est définie pour des réseaux de cellules. Vous devez créer le reste vous-même, comment définir un opérateur donné se comportera pour les arguments des réseaux de cellules.
Vous pouvez le faire en faisant d'abord un nouveau dossier appelé @cell
et en le plaçant dans un dossier existant sur votre chemin Matlab. Vous pouvez ensuite placer vos nouvelles méthodes dans le dossier @cell
. Par exemple, très mise en œuvre simple d'une méthode plus
pour réseaux de cellules (sans vérification d'entrée, vérification des erreurs, etc.) serait ceci:
function C = plus(A,B)
C = cellfun(@plus,A,B,'UniformOutput',false); %# Apply plus cell-wise
end
Dans le code ci-dessus, vous auriez probablement d'abord vouloir vérifier que les opérandes A
et B
sont des réseaux de cellules de la même taille. Cependant, vous pouvez créer toutes les fonctionnalités uniques que vous voulez, par exemple en permettant B
d'être une valeur scalaire qui sont ajoutés à chaque cellule de A
. Il est tout à fait à vous de définir comment l'opérateur +
se comportera pour les tableaux de cellules.
Cela vous permettra d'écrire votre code d'une manière beaucoup plus compacte, comme dans cet exemple:
>> 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
Je ne peux pas vraiment parler aux arrière-scènes optimisations et comment cela pourrait les affecter. Je sais que la documentation « Techniques pour améliorer les performances » spécifique mentionne ceci à propos surcharge des fonctions intégrées :
Surcharge intégré Matlab fonctions sur l'une des données standard Matlab les classes peuvent avoir une incidence négative performance. Par exemple, si vous surcharger la fonction de poignée pour
plus
une des classes entières autrement, vous pouvez empêcher certains optimisations du Matlab intégré dans code de fonction pourplus
, et peut donc ralentir tous les programmes qui utilisent de cette surcharge.
Cependant, dans votre cas, vous ne surchargez pas existants fonctions pour une classe. Vous créez simplement de nouvelles qui n'existaient pas pour cette classe, il est donc difficile de dire quel effet cela peut en fin de compte sur les performances.