define custom model in simulink - matlab

let us consider following simulink model
i have following matrix
A=[2 1 3;1 4 5]
A =
2 1 3
1 4 5
and its singular value decomposition
>> [U E V]=svd(A)
U =
-0.4719 -0.8817
-0.8817 0.4719
E =
7.2965 0 0
0 1.6617 0
V =
-0.2502 -0.7772 -0.5774
-0.5480 0.6053 -0.5774
-0.7982 -0.1720 0.5774
>>
in custom matlab function taken form this link
http://www.mathworks.com/help/simulink/slref/matlabfunction.html
i have created my own function
function [U,E,V]=singular_decomposition(A)
%#codegen
[U E V]=svd(A);
numeric values and dimension of matrices are same,but at some point there is sign different,how can i fix this?

There's nothing wrong. SVD decomposition of a matrix is in general not unique.
If you perform U*E*V' you'll get the same value of A in both cases.

Related

Using vector as indices not working as expected, matlab

Given a nXm matrix A and a mX2 matrix B and a matrix C of size mX1 containing 1s and 2s C=[1 2 1 2 1...], depending on which column, I want every row of A to be multiplied with. How can this be done? Or equivalently, given D = A*B how can I access only the values dictated by C. I tried D(:,C), but the result is not the expected.
Example a =[1 2; 3 4; 5 6] . c = [1 2 1] . a(?) = [1 4 5]
Any idea?
%example data
n=10;m=20;
A=rand(n,m)
B=rand(m,2)
C=round(rand(m,1))+1;
%solution:
B2=B(:,1); %multiplication vector
B2(C==2)=B(C==2,2) %change the ones where C==2
A*B2
You can run the following command for the last example:
a(sub2ind([3,2],1:3,c))'
In general case you can do like the following:
% n is the length of the D which is nx2 matrix
D(sub2ind([n,2],1:n,C))'

Vector Function is Always Constant

New to MATLAB, and I need help with the following issue.
I want to create a function val=F(v,e) that takes in two inputs v, a 1xn vector, and a scalar e, and outputs a scalar val that counts the nonzero entries of the vector v-e, i.e. the vector v with e subtracted from all each of its entries. My code for the function is below:
function val = eff(vec, e)
val = sum( (vec - e > 0) );
end
When I evaluate the function at a single point it works as it should. but I want a plot of this function on (0,1). Plotting it gives a constant value over the entire range of e. I am using the following code on the main
figure
e = linspace(0,1);
plot(e, eff(rand(1,100),e),'o',e, e)
Also, when I use a small vector, say, rand(1,10), I get the following error message:
>Error using -
>
>Matrix dimensions must agree.
>
>Error in eff (line 3)
>
>val = sum( (vec - e > 0 ));
Is my function being too careless with matrix dimensions? Or is there an easier way to evaluate eff over a vector range?
Thanks in advance.
You have created a function which is designed to be applied only with a scalar e argument, and where passing e as an array would potentially cause errors ... but then you call it with e = linspace(0,1) which is an array.
The particular error when e is of size 10 is telling you that you cannot subtract it from a matrix of size 100.
When e happens to have the same size as vec, your function subtracts two equal-sized arrays, and returns their sum, which is a scalar. Therefore your plot is essentially doing something like plot(a_range, a_scalar), which is why it looks constant.
Instead, you should probably collect an array V for each value of e in a for loop, or using arrayfun, e.g.
e = linspace(0,1);
V = arrayfun(#eff, e);
and then plot e against V
Alternatively, you could rewrite your function such that it expects e to be an array, and your return value is an array of the same size as e, filled with the appropriate values.
without using arrayfun, your task can also be accomplished using broadcasting. I noticed you had this question tagged Octave as well as Matlab. Octave uses automatic broadcasting when you attempt elementwise operations with vectors in different dimensions. Matlab can do broadcasting with the bsxfun function. (if you want code that will run in either program, Octave also can use bsxfun.) Also, according to the release notes I believe Matlab 2016b will now include automatic broadcasting, although I cannot confirm yet that it will behave the same as Octave does.
Because your vectors vec and e are both row vectors, when you try to subtract them Matlab/Octave will subtract each element if they have the same size, or give a size mismatch error if they do not.
If you instead create one of the vectors as a column vector, broadcasting can take over. a simple example:
>> a = [1:4]
a =
1 2 3 4
>> b = [1:4]'
b =
1
2
3
4
>> a-b //Error in Matlab versions before 2016b
ans =
0 1 2 3
-1 0 1 2
-2 -1 0 1
-3 -2 -1 0
>> bsxfun(#minus,a,b) //works under Octave or Matlab
ans =
0 1 2 3
-1 0 1 2
-2 -1 0 1
-3 -2 -1 0
So, if you are running Octave, your code will run correctly if you just rewrite your function so the vectors use different dimensions. There are a number of ways to do this, but since both Matlab and Octave default to column ordering, you can use the : operator to force them to work the way you want. E.g.:
>> a = [1:4]
a =
1 2 3 4
>> a(:)
ans =
1
2
3
4
>> a(:)'
ans =
1 2 3 4
>> b = [1:4]'
b =
1
2
3
4
>> b(:)
ans =
1
2
3
4
>> b(:)'
ans =
1 2 3 4
So, after all that, you can rewrite your function:
function val = eff(vec, e)
vec = vec(:);
e = e(:)';
val = sum ( (vec-e ) > 0 );
end
If you're running matlab, or you want code that could run in both Octave and Matlab, you can just replace the last line of the function with:
sum ( bsxfun(#minus,vec,e) > 0 )
Finally, if you want, you can add some 'isvector' error checking at the beginning of the function in case you accidentally pass it an array. And note that had I chosen to make 'vec' a row vector and 'e' a column vector I would have had to tell the sum function which dimension to sum over. (it defaults to summing each column and returning a row vector, which matches the choices I made above.)
you function works fine as long as e is a scaler and not an array or matrix. You can then you looping or arrayfun (as already answered) to get a final answer
figure
e = rand(1,10); % create 10 random e numbers
vec = rand(1,100);
for inc = 1:length(e)
v(inc) = eff(vec,e(inc));
end
scatter(e,v);

matlab: sum of f(k_i,x) where k_i are scalars and x is a matrix

Any idea how to formulate this sum other than using a loop?
sum(i) f(k(i),x) where k_i are some entries of a vector and x is a matrix.
Currently what I'm doing is this, but I'd rather have a general solution:
for ii=1:length(k)
psi=psi+f(k(ii),x)
end
If it's any concern:
f(k,x)=g(k)*exp(k*x)
Assuming g can take a vector input and returns a vector result of the same size, and that x is just a scalar
f=#(k,x) g(k).*exp(k*x);
psi=sum(f(k,x))
or if g can't be or isn't able to take vector input, you can do
g=#(k) arrayfun(g,k);
and then define f as before.
Do you mean that you want to sum only specific rows?
If so, this will do it:
a= [1 2 3 4;
5 2 7 2;
0 0 2 3];
k= [1 3]; %rows selection for sum
result= sum(a(k,:))

neighbor analysis in MATLAB

I have an m-by-n matrix named A, with values 1s and 0s. I want to convert all 0s values to 1s if at least 5 out of 8 neighbor pixels are 1s. What I tried is to use the nlfilter function, but I'm not getting how the arg fun should be used, and I would need a help.
I created a function as handle for nlfilter as following:
function b = gap_fill(A)
b=A;
index= A([1 2 3 4 6 7 8 9]);
if sum(index)>=5
b(5)= 1
end
end
Then I tried to do this:
B= nlfilter(A,[3 3],#gap_fill)
But it gave this error:
??? Subscripted assignment dimension mismatch.
Error in ==> nlfilter at 75
b(i,j) = feval(fun,x,params{:});
Any suggestion? The main problem is I'm not used to handle functions.
= UPDATING =
I finally came up with a good result. I changed my function to output a scalar and when I use it as fun arg in nlfilter it work the way I want. This is my code, thanks for helping and I hope it could be useful for anybody:
function b = gap_fill(A)
index= A([1 2 3 4 6 7 8 9]);
if sum(index)>=5
A(5)= 1;
end
b=A(5);
end
In MATLAB:
b= nlfilter (A,[3 3],'gap_fill')
You can do it in one line with blockproc:
B = blockproc(A,[1 1],#(x)sum(x.data(:)),'BorderSize',[1 1],'TrimBorder',0)-A>=5;
For example,
A =
1 0 1 1 0
0 0 0 1 1
1 1 1 1 1
0 1 0 1 1
gives the result
B =
0 0 0 0 0
0 1 1 1 0
0 0 1 1 1
0 0 1 0 0
Note that border pixels of the image are handled correctly, thanks to using the 'BorderSize' option of blockproc.
To keep the original ones in A, apply a final "or" operation:
B = B|A;
I think it is because the documentation for nlfilter says that the user function must return a scalar and you are trying to return a matrix.
B = nlfilter(A, [m n], fun) applies the function fun to each m-by-n sliding block
of the grayscale image A. fun is a function that accepts an m-by-n matrix as input
and returns a scalar (!!!) result.
For a solution that's slightly faster than blockproc, you can use a 2D convolution:
mask = ones(3);
mask(5) = 0;
B = conv2(A,mask,'same') >= 5;
To make this even faster (you'll only notice this if the arrays become larger), you can make use of the fact that an average filter is separable:
B = conv2(conv2(A,ones(1,3),'same'),ones(3,1),'same') - A >= 5;
The fun function must return an scalar in your case it returns a matrix. from matlab
B = nlfilter(A, [m n], fun) applies the function fun to each m-by-n sliding block of the grayscale image A. fun is a function that accepts an m-by-n matrix as input and returns a scalar result.
c = fun(x)
so your code shoud be There are better ways to code it,specially with amtrix but following your sample:
function b = gap_fill(A)
index= A([1 2 3 4 6 7 8 9]);
if A(5)sum(index)>=5
b = 1;
else
b = A(5);
end
end
Sorry for the error I change b = 0 to b= A(5)

Solving for variables in an over-parameterised system

I am trying to write a Matlab program that accepts variables for a system from the user, but there are more variables than system parameters. To be specific, six variables in three equations:
w - d - M = 0
l - d - T = 0
N - T + M = 0
This could be represented in matrix form as A*x=0 where
A = [1 0 0 -1 0 -1;
0 1 0 -1 -1 0;
0 0 1 0 -1 1];
x = [w l N d T M]';
I would like to be able to solve this system given a known subset of the variables. For example, if the user gives d, T, M, then the system is trivially solved for the other three variables. If the user supplies w, N, M, then it becomes a solvable 3-DOF system. And so on. (If the user over- or under-specifies the system then an error may of course result.)
Given any one of these combinations it's simple to (a priori) use matrix algebra to calculate the unknown quantities. But I don't know how to solve the general case, aside from using the symbolic toolbox (which I prefer not to do for compatibility reasons).
When I started with this approach I thought this step would be easy, but my linear algebra is rusty; am I missing something simple?
First, let x be a vector with NaN for the unknown values. This allows you to use ISNAN to find the indeces of the unknowns. If you calculate A*x for only the user-specified terms, that gives you a column of constants b. Take those constants to the right-hand side of the equation, and you have an equation of the form A*x = -b.
A = [1 0 0 -1 0 -1;
0 1 0 -1 -1 0;
0 0 1 0 -1 1];
idx = ~isnan(x);
b = A(:,idx)*x(idx); % user provided constants
z = A(:,~idx)\(-b); % solution of Ax = -b
x(~idx) = z;
With input x = [NaN NaN NaN 1 1 1]', for instance, you get the result [2 2 0 1 1 1]'. This uses MLDIVIDE, I'm not well versed enough in linear algebra to know whether PINV or something else would be better.
Given the linear system
A = [1 0 0 -1 0 -1;
0 1 0 -1 -1 0;
0 0 1 0 -1 1];
A*x = 0
Where the elements of x are identified as:
x = [w l N d T M]';
Now, suppose that {d,T,M} have known, fixed values. What we need are the indices of these elements in x. We've chosen the 4th, 5th and 6th elements of x to be knowns.
known_idx = [4 5 6];
unknown_idx = setdiff(1:6,known_idx);
Now, let me pick some arbitrary numbers for those known variables.
xknown = [1; -3; 7.5];
We will partition A into two submatrices, corresponding to the known and unknown variables.
Aknown = A(:,known_idx);
Aunknown = A(:,unknown_idx);
Now, move the known values to the right hand side of the equality, and solve. See that Aknown is a 3x3 matrix, so the problem is (hopefully) well posed.
xunknown = Aunknown\(-Aknown*xknown)
xunknown =
-8.5
2
10.5
Combine it all into the final solution.
x = zeros(6,1);
x(known_idx) = xknown;
x(unknown_idx) = xunknown;
x =
-8.5
2
10.5
1
-3
7.5
Note that I've expanded this all out into a few lines to show what is happening more clearly. But I could have done it all in just a line or two of code had I wanted to be parsimonious.
Finally, see that had I chosen some other sets of numbers to be the knowns, such as {l,d,T}, then the resulting system would be singular. So you must watch for that event. A test on the rank of Aunknown might be useful to weed out the problems. Or you might choose to employ pinv to build the solution.
The system of equations is fixed? What if you store the variables present in your three equations in a list per equation:
(w, d, M)
(l, d, T)
(N, T, M)
Then you get the user input and you can calculate the number of variables given in each equation:
User input: w, N, M
Given variables:
(w, d, M) -> 2
(l, d, T) -> 0
(N, T, M) -> 1
This would trivially give you d from the first equation. Therefore you end up with two equations containing two variables and you know you the equation system you have to solve.
It's basically your own simple symbolic solver for a single system of equations.