2009-05-10 6 views
3

I ont pour écrire un script MATLAB qui fait cela:matrices multiples dans Matlab sans récursion

L'entrée est de 2, les matrices A (m x n) et D (m x 1). La sortie est une matrice, C (m x n). C est calculé comme ceci:

function c = scanrow(a,d) 
[rows columns] = size(d); 
for i=1:columns 
a(i,:) = a(i,:).*d(i); 
end 
c = a; 
end 

Le besoin n'utilise pas la récursivité. Je n'ai aucune idée pour résoudre ce problème. Content que tu puisses aider. Merci.

+0

J'ai des problèmes pour voir quelle partie du code/problème est récursive. Peut-être pourriez-vous clarifier cela. – Accipitridae

+1

Vous voulez probablement dire sans boucle plutôt que sans récursion. (accompli en utilisant "vectorisation" dans matlab) –

Répondre

3

Si le problème est « multiplier chaque élément de chaque rangée de A avec l'élément correspondant sur la ligne correspondante de D » alors je suggérer ce qui suit:

dd = repmat(d, 1, size(a, 2)) 
c = a.*dd 

Exemple:

>> a = [1 2; 3 4; 5 6]; 
>> d = [1 2 3]'; 
>> dd = dd = repmat(d, 1, size(a, 2)) 
dd = 
    1 1 
    2 2 
    3 3 
>> a.*dd 
ans = 
    1 2 
    6 8 
    15 18 
0

Êtes-vous certain que le code inclus dans la question est correcte? Ceci est ce qu'il semble faire:

Je suppose que les entrées un et d représentent les matrices A (dimension m-par-n) et D (dimension m-par-1) vous avez mentionné. Puisque vous avez défini d comme ayant toujours 1 colonne, la boucle for est inutile car elle ne boucle qu'une seule fois. Le passage unique à travers la boucle va simplement multiplier les valeurs dans la première ligne de par par la première valeur en d. La pièce entière de code dans la question peut donc être remplacé par ce qui suit:

c = a; 
c(1,:) = c(1,:).*d(1); 
10

Tout comme un FYI - poignées bsxfun + fonction est la nouvelle hotness pour effectuer des opérations sur des matrices et des vecteurs où Au moins une dimension de matrice correspond à une dimension de vecteur. Cela évite de explicites de rempat qui peuvent être lents et inutiles:

 
a = 1:5; 
b = magic(5); 

c = bsxfun(@times,a,b); 

Mais attention - c'est uniquement disponible dans les versions plus récentes relativement Matlab. -Pete

+1

Ou, voir le blog de Loren Shure sur bsxfun: http://blogs.mathworks.com/loren/2008/08/04/comparing-repmat-and-bsxfun-performance/ – Pete

+0

+1 pour mentionner BSXFUN. En outre, vous pouvez trouver des soumissions sur MathWorks File Exchange (http://www.mathworks.com/matlabcentral/fileexchange/) pour BSXFUN qui fonctionnera avec les anciennes versions de MATLAB. – gnovice

3

(je vais répondre, malgré le fait que ce soit des devoirs. Je pense que beaucoup n'apprécient pas pourquoi bsxfun a été créé.)

Il existe d'autres solutions par la voie à la multiplication. Les typiques seraient d'utiliser repmat, d'utiliser une boucle, ou de multiplier par une matrice diagonale. Mieux vaut si la matrice diagonale est faite pour être une matrice clairsemée. Cependant, bsxfun est définitivement la bonne solution. Il a été écrit pour résoudre des problèmes comme celui-ci. Le problème est que quand vous faites des choses comme

A = magic(3) + 5 

Matlab comprend qu'il doit ajouter 5 à tous les éléments de la magie (3). De même, lorsque vous faites

A = magic(4).*2 

nouveau, MATLAB comprend que la multiplication doit être étendue à tous les éléments. En substance, MATLAB étend implicitement le scalaire dans un tableau de la même taille que son partenaire dans l'addition ou la multiplication, puis effectue l'opération.C'est ce qui a été fait explicitement par le solveur de repmat. Le problème avec une expansion scalaire explicite est que cela prend du temps et de la mémoire pour faire cette expansion. Donc, les temps et les plus sont assez intelligents pour reconnaître que l'expansion scalaire est appropriée, mais pas réellement l'opération explicite de la mémoire. Matlab ne sait pas quoi faire lorsque vous essayez

A = magic(3).*rand(1,3) 

Dans le passé, la solution était d'utiliser repmat. Mais, quand vous utilisez repmat pour faire une expansion explicite d'un vecteur dans une matrice, vous consommez beaucoup de mémoire pour résoudre un problème de manière vectorisée. Oui, il est courant que les vectorisations échangent de la mémoire pour le temps dans MATLAB, mais cela peut être une mauvaise chose si vous avez déjà une mémoire limitée et que vous travaillez sur un gros problème. Forcer MATLAB (et votre OS) à se déplacer dans la mémoire virtuelle est une très mauvaise idée quand ce n'est pas nécessaire. Donc, quand vous essayez de multiplier un tableau comme magic (3) par une ligne ou un vecteur colonne, MATLAB devrait-il comprendre qu'il devrait faire une expansion implicite du vecteur dans un tableau? Ou MATLAB devrait-il supposer que vous avez fait une erreur et l'indiquer comme tel? Ce problème, connu sous le nom d'expansion des dimensions singleton est le problème. (Une dimension singleton est trouvée dans un vecteur, où l'une des dimensions était 1.) Renvoyer un message d'erreur est une bonne idée pour de nombreux utilisateurs, car cela indique souvent qu'un bogue a été trouvé, une erreur a été commise. L'expansion simple et automatique de toutes les dimensions singleton pour s'adapter au problème semble dangereuse. En fait, il y avait beaucoup de discussions sur ce qu'il fallait faire. Par exemple, MATLAB devrait-il créer une préférence, où l'utilisateur pourrait activer l'expansion de dimensions singleton dans leur version de MATLAB? Ce serait une mauvaise idée, car cela rendrait le code non-portable à travers les systèmes.

De même, si les opérateurs MATLAB de base étaient modifiés pour toujours développer toutes les dimensions singleton, le code MATLAB serait fortement non-portable vers les anciennes versions.

Nous avons même discuté de la création d'un nouvel ensemble d'opérateurs MATLAB, comme. * Existe en parallèle à *, pour effectuer une opération tout en développant des dimensions singleton. C'était aussi une mauvaise idée, et justement évitée.

La solution consistait à créer BSXFUN (Binary Scalar eXpansion FUNction) pour permettre à cette opération d'être exécutée efficacement lorsque cela est souhaité. Il y a un bsxfun trouvé sur l'échange de fichiers qui permet aux utilisateurs de versions plus anciennes d'obtenir ce comportement, donc la portabilité est maintenue aussi bien que possible. BSXFUN vous permet d'opérer sur n'importe quelle paire d'arguments, en appliquant une fonction fournie par l'utilisateur entre eux. Donc, il vous permet de faire des choses comme ceci:

A = rand(5,1); 
B = rand(1,3); 
C = bsxfun(@plus,A,B); 

pour créer une matrice 5x3 de la somme des éléments dans chacun des groupes A et B. Vous pouvez utiliser une fonction comme premier opérande aussi, donc BSXFUN est très puissant. Enfin, une autre façon de voir BSXFUN est la variation d'un produit externe. Ainsi, cette opération est parfaitement Matlab défini:

A = rand(5,1); 
B = rand(1,3); 
C = A*B; 

Cependant, l'une de ces opérations

D = A-B; 
E = A^B; 

va générer une erreur. BSXFUN vous permet de les faire efficacement sans accumulation de dimension singleton monopolisant la mémoire.

D = bsxfun(@minus,A,B); 
E = bsxfun(@power,A,B); 
+0

"Créer un nouvel ensemble d'opérateurs MATLAB, comme. * Existe en parallèle de *, pour faire une opération tout en développant des dimensions singleton." C'était aussi une mauvaise idée, et justement évité_ ": Je me demande pourquoi c'était un" mauvais " idée –