2017-08-28 3 views
2

I zwei Vektoren x gegeben werde, y und i schaffen die DistanzmatrixEvaluieren arrayfun nur bei Nicht-Null-Einträge zu unterschiedlichen Ergebnissen

B=pdist2(x,y); 

Jetzt bewerten i eine bestimmte Funktion f (x),

s=5; 
if s-x > 0 
    y=(1-x/s)^4*(1+4*x/s)/20; 
else 
    y=0; 
end 

wo ist s etwas parameter. Durch Vordefinieren von s und Verwenden von

ist die Matrix A positiv definierbar wie gewünscht.

Da die Matrix spärlich ist, möchte ich f (x) nur bei den Werten auswerten, die ungleich Null zurückgegeben werden. Mein Versuch war

B=pdist2(x,y); 
B(B>s)=0; 
B=B/s; 
indexB=find(B); 
Atmp=arrayfun(@f,B(indexB)); 
A(indexB)=Atmp; 

Aber jetzt A ist nicht positiv definit und hat weniger Einträge ungleich Null als zuvor. Kann mir jemand erklären, was ich mache?

Danke allen, ich habe den Fehler gefunden. Da waren einige Null Einträge auf der Diagonale in B, die ich separat berechnen musste.

+0

Bitte schreiben Sie die Antwort * als Antwort *, damit andere sehen, dass diese Frage gelöst ist, oder markieren Sie die nützlichste Antwort als akzeptiert – Wolfie

Antwort

2

Sie sollten die Matrix A mit der gleichen Größe wie B preallocate, sonst MATLAB nicht die richtige Größe weiß für A:

A=zeros(size(B)); 

Beachten Sie, dass find kehrt linear indices, so A einen Vektor anstelle einer wurde Matrix.

4

Ich frage mich, warum Sie versuchen, Index B, und wenden Sie dann eine Funktion auf jedes einzelne Element. Stattdessen lassen Sie uns vectorize Code

% Same setup 
B = pdist2(x,y); s = 5; 
B(B >= s) = 0; B = B/s; 
% Don't use arrayfun, instead use vectorised code 
% The previous line already dealt with the 'else' case from f(x) 
B = ((1-B/s).^4).*(1+4*B/s)/20; 

Beachten Sie, dass jedes Mal, wenn wir zwischen zwei nicht-Skalare arbeiten wir elementweise Operationen .^ oder .* verwenden. Die anderen Divisionen und Multiplikationen sind alle mit Skalaren, aber wir könnten sicher sein und uns angewöhnen, sie alle zu benutzen!

B = ((1-B./s).^4).*(1+4.*B./s)./20; 

Ein Hinweis auf MATLAB Terminologie: Seien Sie vorsichtig sagen, dass Sie eine "Sparse Matrix" haben hier, das ist ein special variable type in MATLAB. Sie haben eine Standardmatrix, die mathematisch spärlich ist! Das Arbeiten auf einer spärlichen Matrix könnte etwas anders sein.

+0

Vielen Dank für diese Notiz. Aber ich muss mehr als nur diese eine Funktion auf jedes Element der Matrix anwenden. Also benutze etwas wie B = ((1-B./s).^4).*(1 +4.*B./s)./20; wäre langweilig, denke ich. – stish

+0

Warum wäre es mühsamer, als es innerhalb einer Funktion 'f (x)' anzuwenden? Wenn Sie mehr als eine Funktion anwenden müssen, können Sie sie alle gleichzeitig anwenden? Bitte geben Sie ein Beispiel, was Sie meinen (als Frage editieren, wenn es etwas ist, das formatiert werden muss) – Wolfie

2

Statt arrayfun können Sie spfun verwenden, um eine Funktion zu Null verschiedene Sparse Matrix Elemente anwenden:

A = spfun(@f, B); 

Obwohl Vektorisierung effizienter sein kann.

  • spfun arbeitet auch mit dichten Matrizen sowie spärlich diejenigen, aber Ausgang es eine spärliche Matrix

Dank @Wolfie einige Tests zur Verfügung gestellt und für ihre Klarstellung.

+1

Wie ich unten bemerkte, ist die Ausgabe 'B', die sie von' pdist2' bekommen, wahrscheinlich keine MATLAB-Matrix ... nicht sicher, ob das Ihre Antwort betrifft. – Wolfie

+0

@Wolfie Guter Punkt, aber 'spfun' arbeitet mit dichten Matrizen sowie spärlichen in Octave. Ich bin mir nicht sicher für MATLAB ... – rahnema1

+1

Habe gerade einen minimalen Test in MATLAB gemacht ('s = [1 2; 3 4]; spfun (@ exp, s);') und es scheint gut zu funktionieren, Ausgabe eines spärlich Matrixobjekt (auch wenn die Eingabe eine dichte Matrix war). Das sollte also eine vernünftige Lösung sein, aber der Benutzer sollte sich des Ausgabevariablentyps bewusst sein – Wolfie

Verwandte Themen