2013-12-13 9 views
6

Ich habe ein Problem. Ich versuche, dieses kurze Stück Code zu implementieren. enter image description hereErweiterung von bsxfun auf bestimmte Indizes in einer Matrix

Die grundlegenden Schritte habe ich bereits getan. Bitte überprüfen Sie meinen Code unten:

clc;clear all;close all; 
A=round(-3+(6).*rand(5,5)); 
B=round(-3+(6).*rand(5,5)); 
%//The check matrix stores the conditions present on the right side of the equation. 
check = A.*B 
%//upd_max and upd_min are the given as the del_max and del_min in the equation 
upd_max = 0.5; 
upd_min = 0.1; 
%//eta_plus and eta_minus are denoted as nplus and nminus 
nplus = 1.2; 
nminus = 0.5; 
%del_(k-1)_i matrix is given as update_mat 
update_mat = (0.1+(0.4).*rand(size(check))).*ones(size(check)) 
update_new = update_mat.*(check==0) + bsxfun(@min,(nplus.*update_mat.*(check>0)),upd_max)... 
      + bsxfun(@max,nminus.*(update_mat.*(check<0)),upd_min) 

ich unter einer Probe Ergebnis meines Stückes Code gebe:

check = 

    2 -6  0 -1  2 
    -3 -4  3 -3  4 
    0  2 -2  6  0 
    2 -1 -4 -1 -3 
    -2 -4 -3  0  6 


update_mat = 

    0.4102 0.4173 0.1126 0.2268 0.4964 
    0.4622 0.3750 0.4282 0.3422 0.1495 
    0.4760 0.3820 0.2903 0.3143 0.1473 
    0.3603 0.2861 0.3122 0.3527 0.2908 
    0.3602 0.3696 0.3220 0.2046 0.4746 
update_new = 

    0.5922 0.2087 0.2126 0.1134 0.6000 
    0.2311 0.1875 0.6000 0.1711 0.2794 
    0.5760 0.5584 0.1452 0.4772 0.2473 
    0.5324 0.1431 0.1561 0.1763 0.1454 
    0.1801 0.1848 0.1610 0.3046 0.6000 

Doch diese Antwort nicht korrekt ist !! Um zu erklären, ich meine Antwort in drei Teile geteilt:

update_mat.*(check==0) 

ans = 

     0   0 0.1126   0   0 
     0   0   0   0   0 
    0.4760   0   0   0 0.1473 
     0   0   0   0   0 
     0   0   0 0.2046   0 

bsxfun(@min,(nplus.*update_mat.*(check>0)),upd_max) 

ans = 

    0.4922   0   0   0 0.5000 
     0   0 0.5000   0 0.1794 
     0 0.4584   0 0.3772   0 
    0.4324   0   0   0   0 
     0   0   0   0 0.5000 

Wie deutlich zu sehen ist die first beiden Begriffe sind richtig. Der dritte Begriff ist jedoch falsch. Der dritte Term wie dies kommt:

bsxfun(@max,nminus.*(update_mat.*(check<0)),upd_min) 

ans = 

    0.1000 0.2087 0.1000 0.1134 0.1000 
    0.2311 0.1875 0.1000 0.1711 0.1000 
    0.1000 0.1000 0.1452 0.1000 0.1000 
    0.1000 0.1431 0.1561 0.1763 0.1454 
    0.1801 0.1848 0.1610 0.1000 0.1000 

Die richtige dritte Begriff sollte gib mir

 0 0.2087   0 0.1134   0 
0.2311 0.1875   0 0.1711   0 
    0   0 0.1452   0   0 
    0 0.1431 0.1561 0.1763   0 
0.1801 0.1848 0.1610   0 0.1000 

Ich möchte das bsxfun das Element weise maximal für die Nicht-Null-Elemente von der nur zu berechnen, Matrix nminus.*(update_mat.*(check<0)) und nicht die ganzen Matrizen. Ist es möglich?

Vielen Dank im Voraus! PS: Bitte gib Ideen für besser optimierten Code.

Antwort

6

Sie brauchen nicht bsxfun, da Sie mit einem Skalar zu tun haben, müssen Sie nur logische Indizierung benötigen:

M=nminus.*(update_mat.*(check<0)) 
M((~~M) & (M < upd_min)) = upd_min %// ~~M is the same as M~=0 

(btw setzt dies voraus, dass Sie für Ihre Beispieldaten einen Fehler in der vorletzten Reihe gemacht der letzten Spalte, wo Sie 0 haben, aber ich denke, Sie wollen 0.1454)

+0

Ich verstehe Ihre Idee und es funktioniert auch! aber kann ich bsxfun nicht benutzen? Wie ich es verstehe, ist es deutlich schneller. – roni

+2

@roni das ist nicht was bsxfun tut. Ich bezweifle stark, dass es schneller als logische Indexierung wäre. Es ist oft schneller als mit "repmat" oder Schleifen, aber wenn Sie mit einem Skalar zu tun haben, ist es sinnlos. Dies ist der Weg zu gehen. – Dan

+3

@roni Bsxfun wird verwendet, wenn Sie ** Vektoren ** erweitern müssen, um sie an Dimensionen anzupassen. Mit Skalaren ist es sinnlos und erhöht den Overhead. – Oleg