How to provide the list of diff between 2 lists - matlab

I have 2 cells
exp = {'test','tat','toto'};
act = {'test','toto','tat','pto'};
and would like to check these lists are equal. How could I provide the list of differences when they don't have the same number of elements?

With setdiff the order of the input matters. setdiff(A,B) returns a list of entries in A which are not in B only, it does not return those entries in B which are not in A.
exp = {'test','tat','toto'};
act = {'test','toto','tat','pto'}
setdiff(exp,act); % empty because there is nothing in exp which isn't in act
setdiff(act,exp); %returns 1 x 1 cell, 'pto'.
Instead, use setxor(A,B), which returns values not in the intersection of A and B. Order of inputs doesn't matter:
exp = {'test','tat','toto','pta'};
act = {'test','toto','tat','pto'};
setxor(exp,act) % returns 'pta','pto'

You can use the setdiff command.
exp = {'test', 'tat', 'toto'};
act = {'test', 'toto', 'tat', 'pto'};
diff = setdiff(exp, act);
You can find it in the documentation:
http://www.mathworks.com/help/matlab/ref/setdiff.html?refresh=true

In short, usesetdiff; see the documentation, there is an example on exactly what you want to do.
EDIT
Explanation is needed about setdiff. According to the documentation:
C = setdiff(A,B) returns the data in A that is not in B.
This sentence must be understood exactly: it returns the data of A not in B. So setdiff is NOT symmetric with its arguments! For your problem, if all elements of A are in B, even if B is bigger, the result set is empty.
To get the differences between two sets, in other words you want a symmetric function wrt their arguments, Matlab offers another function, setxor:
C = setxor(A,B) returns the data of A and B that are not in their intersection (the symmetric difference).

Related

Calling if else output to other script

I have written a function called "tension.m" in which I have used if else condition as shown below.
function [T,T_earlyvalues,T_latervalues] = tension(u,sigma,G,N,K)
%the values of sigma,G,N,K can be taken arbitrary.
sigma=2; G=3;N=8;K=1; v=1;
w=2.2;
if u<w
T =v*sqrt(sigma+G^2/(N-K));
T_earlyvalues=T;
else
T=(2*v)*sqrt(sigma+G^2/(N+K));
T_latervalues=T;
end
Now in another script "myvalues.m" I need to call T_earlyvalues and T_latervalues separately.
%have some coding before this part
sigma0=2400; lambda=1.3; v=2; sigma=2; G=3;N=8;K=1;
u=0:0.01:5;
T=tension(u,sigma,G,N,K);
T_earlyvalues=tension(u,sigma,G,N,K);
T_latervalues=tension(u,sigma,G,N,K);
deltaA=T_earlyvalues*sigma0*pi;
deltaB=T_latervalue*lambda*pi/2;
%have some coding after this part
How could I call the said values which are under if-else statement from tension.m function to myvalues.m script?
You have defined the tension function such that it returns three outputs.
If you call that function by requiring only one output, the function returns the first value, in your case, T
This implies that
T=tension(u,sigma,G,N,K);
shoud work since T is the first output parameter
T_earlyvalues=tension(u,sigma,G,N,K);
T_latervalues=tension(u,sigma,G,N,K);
are not working, since, actually tension returns the first value (T, whjikle you are expecting the second and the third respectively.)
You can cahnge the two above calls this way:
[~,T_earlyvalues,~]=tension(u,sigma,G,N,K);
[~,~,T_latervalues]=tension(u,sigma,G,N,K);
The ~ allows to avoid the function return the output paraemter.
You can find additional information here
Notice that in your function T_earlyvalue is not set in the else block, same for T_latervalue in the if block.
This will generate an error such as
Output argument T_earlyvalue (and maybe others) not assigned during call to tension
or
Output argument T_latervalues (and maybe others) not assigned during call to tension
You can initialize the output values to default values, at the beginning of the function, for example:
T=NaN
T_earlyvalue=NaN
T_latervalues=NaN
You can then use these special values (or any other you want to use) to trace, for example, if the if block has been executed or the else.
There seem to be a number of issues here, not the least of which is some confusion about how output argument lists work when defining or calling functions. I suggest starting with this documentation to better understand how to create and call functions. However, this issue is somewhat moot because the larger problem is how you are using your conditional statement...
You are trying to pass a vector u to your function tension, and from what I can tell you want to return a vector T, where the values of T for u < w are computed with a different formula than the values of T for u >= w. Your conditional statement will not accomplish this for you. Instead, you will want to use logical indexing to write your function like so:
function [T, index] = tension(u, sigma, G, N, K)
T = zeros(size(u)); % Initialize T to a vector of zeroes
w = 2.2;
index = (u < w); % A logical vector, with true where u < w, false where u >= w
T(index) = u(index)*v*sqrt(sigma+G^2/(N-K)); % Formula for u < w
T(~index) = 2*(u(~index)-v)*sqrt(sigma+G^2/(N+K)); % Formula for u >= w
end
Now you can call this function, capturing the second output argument to use for identifying "early" versus "late" values:
sigma0 = 2400; lambda = 1.3; v = 2; sigma = 2; G = 3; N = 8; K = 1;
u = 0:0.01:5;
[T, earlyIndex] = tension(u, sigma, G, N, K); % Call function
T_earlyvalues = T(earlyIndex); % Use logical index to get early T values
T_latervalues = T(~earlyIndex); % Use negated logical index to get later T values
And you can then use the subvectors T_earlyvalues and T_latervalues however you like.

while loop until certain condition on the function value is met

I'm trying to fit some data with Matlab, using the least square method.
I found best fit parameters, and I want to determine the uncertainty on them now.
To determine the uncertainty on the first parameter, say a, we have seen in course that one should apply a variation to one parameter, until the difference between the function (evaluated at that variation) minus the original function value equals 1.
That is, I have a vector called [bestparam] in my Matlab code, containing the four parameters a, b, c and d.
I also have a function defined in another file, called chi-square, which I evaluated at the best parameters.
I now want to apply a small variation to the parameter a, and keep doing this until chi-square(a + variation) - chi-square = 1. The difference must be exactly one. I implemented for this the following code:
i = 0;
a_new = a + i;
%small variation on the parameter a
new_param = [a_new b c d];
%my new parameters at which I want the function chisquare to be evaluated
newchisquare = feval(#chisquare, [new_param], X, Y, dY);
%the function value
while newchisquare - chisquarevalue ~= 1
i = i + 0.0001;
a_new = a_new + i;
new_param = [a_new b c d];
newchisquare = feval(#chisquare, [new_param], X, Y, dY);
end
disp(a_new);
disp(newchisquare);
But when I execute this loop, it never stops running. When I change the condition to < 1, i.e. that the difference should be larger than one, then it does stop after like 5 seconds. But then the difference between the function values is no longer exactly one. For example, my original function value is 63.5509 and the new one is then 64.6145 which is not exactly 1 larger.
So is there some way to implement the code, and to keep updating the parameter a until the difference is exactly one? Help is appreciated.
Performing numerical methods I wouldn't recommend using operations like == or ~= unless you are sure that you are comparing two integers. Only small deviations of your value may cause your code to never stop. You can apply some tolerance treshold to make your code stop if it is approximately correct:
TOL = 1e-2;
while (abs(newchisquare - chisquarevalue) <= 1 - TOL)
% your code
end

Make this matlab code run without a for loop

Lets say that I have an array x with some data values.
I performed a clustering algorithm that has produced a label map with the label names - labelMap. Each point in the data now has a unique cluster label associated to it.
I then perform the function foo(subset, secondArg) over each subset. The function foo returns a new array with the result which has the same size as its given the argument (its a map() function which also recieves a second argument).
What follows is the current implementation:
x = rand(1,1000);
numClusters = 3; % specified in advance by the user, for example using a clustering algorithm such as K-Means, this is a given.
fooSecondArg = [1,2,3]; % second argument for foo().
labelMap = kmeans(x,numClusters);
res = zeros(size(x));
%% make me run without a for loop :)
for ind = 1:numClusters
res(labelMap == ind) = foo(x(labelMap == ind), fooSecondArg(ind));
end
My question is as follows:
As there is no overlap between the indices in x foo() acts upon, is there a way to perform foo over x without using a for or a parfor loop? (I don't want to use a parfor loop as It takes quite a while to start the additional matlab processes and I cannot later on deploy it as a stand alone application).
Many thanks!
Edit:
I was asked for an example of foo() because I was told the solution may depend on it. A good viable example you may use in your answer:
function out = foo(x,secondArg)
out = x.^2/secondArg;
Whether the loop can be removed or not depends on the function you have. In your case the function is
function out = foo(x,secondArg)
out = x.^2/secondArg;
where secondArg depends on the cluster.
For this function (and for similar ones) you can indeed eliminate the loop as follows:
res = x.^2 ./ fooSecondArg(labelMap);
Here
labelMap is the same size of x (indicates the cluster label for each entry of x);
fooSecondArg is a vector of length equal to the number of clusters (indicates the second argument for each cluster).
Thus fooSecondArg(labelMap) is an array the same size of x, which for each point gives the second argument corresponding to that point's cluster. The operator ./ performs element-wise division to produce the desired result.

Indexing elements of parameters of a function within nested for loops

I have two matrices of results, A = 128x631 and B = 128x1014 and I have a function SSD that takes two elements (x,y) as parameters and then calculates the sum of squared differences. I also have a 631x1014 matrix of 0s, called SSDMatrix, ready to put the results of my SSD function into.
What I'm trying to do is compare each element of A with each element of B by passing them into SSD, but I can't figure out how to structure my for loops to get the desired results.
When I try:
SSDMatrix = SSD(A, B);
I get exactly the result I'm looking for, but only for the first cell. How can I repeat this process for each element of A and B?
Currently I have this:
SSDMatrix = zeros(NumFeatures1,NumFeatures2);
for i = 1:631
for j = 1:1014
SSDMatrix(i,j) = SSD(A,B);
end
end
This just results in the first answer being repeated 631*1014 times, so I need a way to index A and B to get the appropriate answer for each (i,j) of SSDMatrix.
It seems you were needed to do something like this -
SSDMatrix = zeros(NumFeatures1,NumFeatures2);
for i = 1:631
for j = 1:1014
SSDMatrix(i,j) = sum( (A(:,i) - B(:,j)).^ 2 );
end
end
This, you can achieve with pdist2 as well that gets us the square root of summed squared distances. Now, please do note that pdist2 is part of the Statistics Toolbox. So, to get the desired output, you can do -
out = pdist2(A.',B.').^2;
Or with bsxfun -
out = squeeze(sum(bsxfun(#minus,A,permute(B,[1 3 2])).^2,1));

Bitwise commands such as Bitor with many inputs?

Matlab takes only two inputs with bitwise commands such as bitor. bitor(1,2) returns 3 and bitor(1,2,4) does not return 7 but:
ASSUMEDTYPE must be an integer type name.
Currently, I create for-loops to basically create a bitwise command to take as many inputs as needed. I feel the for-loops for this kind of thing is reinvention of the wheel.
Is there some easy way of creating the bitwise operations with many inputs?
Currently an example with some random numbers, must return 127
indices=[1,23,45,7,89,100];
indicesOR=0;
for term=1:length(indices)
indicesOR=bitor(indicesOR,indices(term));
end
If you don't mind getting strings involved (may be slow):
indicesOR = bin2dec(char(double(any(dec2bin(indices)-'0'))+'0'));
This uses dec2bin to convert to strings of '0' and '1'; converts to numbers 0 and 1 by subtracting '0'; applys an "or" operation column-wise using any; and then converts back.
For AND (instead of OR): replace any by all:
indicesAND = bin2dec(char(double(all(dec2bin(indices)-'0'))+'0'));
For XOR: use rem(sum(...),2):
indicesXOR = bin2dec(char(double(rem(sum(dec2bin(indices)-'0'),2))+'0'))
EDIT: I just found out about functions de2bi and bi2de (Communications Toolbox), which avoid using strings. However, they seem to be slower!
indicesOR = bi2de(double(any(de2bi(indices))));
indicesAND = bi2de(double(all(de2bi(indices))));
indicesXOR = bi2de(double(rem(sum((de2bi(indices))));
Another approach is to define a recursive function, exploiting the fact that AND, OR, XOR operations are (bit-wise) associative, that is, x OR y OR z equals (x OR y) OR z. The operation to be applied is passed as a function handle.
function r = bafun(v, f)
%BAFUN Binary Associative Function
% r = BAFUN(v,f)
% v is a vector with at least two elements
% f is a handle to a function that operates on two numbers
if numel(v) > 2
r = bafun([f(v(1), v(2)) v(3:end)], f);
else
r = f(v(1), v(2));
end
Example:
>> bafun([1,23,45,7,89,100], #bitor)
ans =
127