extension of bsxfun to cater to particular indices in a matrix

249 views Asked by At

I have a problem. I am trying to implement this short piece of code. enter image description here

The basic steps I have already done. Please check my code below:

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)

I am giving below a sample result of my piece of code:

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

However this answer is not correct!! To explain I am dividing my answer into three parts:

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

As can be seen clearly the first two terms are correct . However the third term is wrong. The third term comes as this :

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

The correct third term should give me

     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

I want the bsxfun to compute the element wise maximum only for the non-zero elements of the matrix nminus.*(update_mat.*(check<0)) and not the whole matrices. Is it possible to do so?

Thanks in advance! PS: Please give ideas for better optimized code.

1

There are 1 answers

4
Dan On BEST ANSWER

You don't need bsxfun since you're dealing with a scalar, you just need logical indexing:

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

(btw this assumes that for your example data you made a mistake in the second last row of the last column where you have 0 but I think you want 0.1454)