matlab: apply an operand on an array by a condition - matlab

I have an array like this:
>> a = [2,34,5,6,7,0,1,10]
now I want to reverse each element of this array.
By using 1 ./ a the result is:
ans =
0.5000 0.0294 0.2000 0.1667 0.1429 Inf 1.0000 0.1000
The Inf is not good for me, the answer should be
ans =
0.5000 0.0294 0.2000 0.1667 0.1429 0 1.0000 0.1000
I want to apply this on elements that are not zero!
How can I do that?

You could also reset the Inf value to zero afterwards:
>> b=1./a
b =
0.5000 0.0294 0.2000 0.1667 0.1429 Inf 1.0000 0.1000
>> b(isinf(b)) = 0
b =
0.5000 0.0294 0.2000 0.1667 0.1429 0 1.0000 0.1000

You can do it conditionally:
nz = a ~= 0; %// select using logical indexing
a(nz) = 1./a(nz);

A slightly more general approach than m.s.'s is to check for finite elements in the output using isfinite:
b = 1./a;
b( ~isfinite(b) ) = 0;
isfinite covers both inf values as well as NaN values, so if the element-wise function you are applying might generate both types of non-numeric values, isfinite handles them simultaneously for you.

Related

Solve System of Linear Equations in MatLab with Matrix of Arbitrary Size for Finite Difference Calculation

I am trying to write a script in MatLab R2016a that can solve a system of linear equations that can have different sizes depending on the values of p and Q.
I have the following equations that I am trying to solve, where h=[-p:1:p]*dx. Obviously, there is some index m where h=0, but that shouldn't be a problem.
I'm trying to write a function where I can input p and Q and build the matrix and then just solve it to get the coefficients. Is there a way to build a matrix using the variables p, Q, and h instead of using different integer values for each individual case?
I would use bsxfun(in recent matlab versions this function may be implented to the interpreter, I don't know for sure):
p = 4;
Q = 8;
dx = 1;
h = -p:p*dx
Qvector = [Q,1:Q-1]'
Matrix = bsxfun(#(Qvector, h)h.^(Qvector)./factorial(Qvector), Qvector, h)
Output:
h =
-4 -3 -2 -1 0 1 2 3 4
Qvector =
8
1
2
3
4
5
6
7
Matrix =
1.6254 0.1627 0.0063 0.0000 0 0.0000 0.0063 0.1627 1.6254
-4.0000 -3.0000 -2.0000 -1.0000 0 1.0000 2.0000 3.0000 4.0000
8.0000 4.5000 2.0000 0.5000 0 0.5000 2.0000 4.5000 8.0000
-10.6667 -4.5000 -1.3333 -0.1667 0 0.1667 1.3333 4.5000 10.6667
10.6667 3.3750 0.6667 0.0417 0 0.0417 0.6667 3.3750 10.6667
-8.5333 -2.0250 -0.2667 -0.0083 0 0.0083 0.2667 2.0250 8.5333
5.6889 1.0125 0.0889 0.0014 0 0.0014 0.0889 1.0125 5.6889
-3.2508 -0.4339 -0.0254 -0.0002 0 0.0002 0.0254 0.4339 3.2508

Matlab: Removing duplicate interactions [duplicate]

This question already has answers here:
How can I find unique rows in a matrix, with no element order within each row?
(4 answers)
Closed 7 years ago.
I have a Protein-Protein interaction data of homo sapiens. The size of the matrix is <4850628x3>. The first two columns are proteins and the third is its confident score. The problem is half the rows are duplicate pairs
if protein A interacts with B, C, D. it is mentioned as
A B 0.8
A C 0.5
A D 0.6
B A 0.8
C A 0.5
D A 0.6
If you observe the confident score of A interacting with B and B interacting with A is 0.8
If I have a matrix of <4850628x3> half the rows are duplicate pairs. If I choose Unique(1,:) I might loose some data.
But I want <2425314x3> i.e without duplicate pairs. How can I do it efficiently?
Thanks
Naresh
Supposing that in your matrix you store each protein with a unique id.
(Eg: A=1, B=2, C=3...) your example matrix will be:
M =
1.0000 2.0000 0.8000
1.0000 3.0000 0.5000
1.0000 4.0000 0.6000
2.0000 1.0000 0.8000
3.0000 1.0000 0.5000
4.0000 1.0000 0.6000
You must first sort the two first columns row-wise so you will always have the protein pairs in the same order:
M2 = sort(M(:,1:2),2)
M2 =
1 2
1 3
1 4
1 2
1 3
1 4
Then use unique with the second parameter rows and keep the indexes of unique pairs:
[~, idx] = unique(M2, 'rows')
idx =
1
2
3
Finally filter your initial matrix to keep unly the unique pairs.
R = M(idx,:)
R =
1.0000 2.0000 0.8000
1.0000 3.0000 0.5000
1.0000 4.0000 0.6000
Et voilĂ !

MATLAB code for Hamacher sum

The hamacher sum is :
I wrote the following MATLAB code for the above function
function f=hamachersum(x,y)
f = zeros(numel(x),1);
for j=1:numel(x)
if x(j)==1 && y(j)==1
f(j,1)=1;
else
f(j,1)=(x(j)+y(j)-2*(x(j)*y(j)))/(1-(x(j)*y(j)));
end
end
end
Then I want to test t3=hamachersum(t1,t2)
My input values t1, t2 are
t1
t1 =
1.0000
0
1.0000
1.0000
1.0000
1.0000
NaN
0.8167
1.0000
1.0000
1.0000
0.4667
NaN
1.0000
1.0000
1.0000
NaN
NaN
1.0000
1.0000
1.0000
NaN
0.0250
1.0000
t2
t2 =
1.0000
0.5524
1.0000
1.0000
1.0000
1.0000
NaN
0
1.0000
1.0000
1.0000
1.0000
NaN
1.0000
1.0000
1.0000
NaN
NaN
0.6032
1.0000
1.0000
NaN
0.9973
0.7260
The result is
t3 =
1.2000
0.5524
1.0000
1.0000
1.0000
1.0000
NaN
0.8167
2.0000
2.0000
1.0000
1.0000
NaN
0.6667
1.0000
1.0769
NaN
NaN
1.0000
1.0000
1.0000
NaN
0.9973
1.0000
Why do I get values above 1. As this is a fuzzy operator it can't have values above 1.
Is there something wrong in my code?
I am probably answering this against my better judgement.
Caveat: I am not familiar with the Hamacher sum so my approach to answering this is strictly based on the equation in your question.
Is there something wrong in my code?
Your code produces 1.0 when I run it on MATLAB R2014a for inputs of 1.0 and 1.0, I'm presuming that is correct as you have an explicit condition for it. I cant produce the results you are are seeing in your question.
However, I felt compelled to provide a more efficient implementation of the equation
function h = hamachersum(mu_a, mu_b)
h = (mu_a + mu_b - (2 .* mu_a .* mu_b)) ./ (1 - mu_a .* mu_b);
% h(isnan(h)) = 1.0; % Included this line to show you how to remove NaN
end
Note: I've included % h(isnan(h)) = 1.0; to show you how to handle cases when mu_a and mu_b are both 1.0 as you have explicitly handled this in your question (rather poorly might I add).
Comparing floating point numbers is not reliable even in MATLAB and could be part of the reason why you are receiving the results you are. A better way to check what the value of a floating point number is would be to use
if (x - 1.0 > 1e-15)
fprintf(1, "x == 1.0");
else
fprintf(1, "x ~= 1.0");
end
If x is equal to 1.0 down to machine precision this expression will be true otherwise it will be false.

matlab equality check going wrong. decides true on an arbitrary moment

THE CODE:
function[E] = eig_noshift(A)
A_k = A;
for(i=0:inf)
[Qk,Rk] = qr(A_k);
A_k1 = Rk*Qk;
diag(A_k1)
diag(A_k)
isequal(diag(A_k1),diag(A_k))
if(isequal(diag(A_k1),diag(A_k)))
break
end
A_k = A_k1;
end
E = diag(A_k);
I'm creating a matlab method that calculates a matrix' eigenvalues with the QR-algorithm. (which works) i'm trying to break the for loop if the next matrix diagonal is equal to the current diagonal (algorithm has converged)
When executing the algorithm I get following output:
>> eig_noshift(A0)
Warning: FOR loop index is too large. Truncating to 281474976710655.
> In eig_noshift at 3
ans =
4.8419
1.2591
-0.0011
ans =
-22.2000
-14.6000
42.9000
ans =
0
ans =
4.9434
1.0611
0.0954
ans =
4.8419
1.2591
-0.0011
ans =
0
ans =
4.9881
1.0123
0.0996
ans =
4.9434
1.0611
0.0954
ans =
0
ans =
4.9976
1.0024
0.1000
ans =
4.9881
1.0123
0.0996
ans =
0
ans =
4.9995
1.0005
0.1000
ans =
4.9976
1.0024
0.1000
ans =
0
ans =
4.9999
1.0001
0.1000
ans =
4.9995
1.0005
0.1000
ans =
0
ans =
5.0000
1.0000
0.1000
ans =
4.9999
1.0001
0.1000
ans =
0
ans =
5.0000
1.0000
0.1000
ans =
5.0000
1.0000
0.1000
ans =
0
ans =
5.0000
1.0000
0.1000
ans =
5.0000
1.0000
0.1000
ans =
0
--- a few dozen more iterations that are the same ---
ans =
5.0000
1.0000
0.1000
ans =
5.0000
1.0000
0.1000
ans =
0
ans =
5.0000
1.0000
0.1000
ans =
5.0000
1.0000
0.1000
ans =
1
The 0/1 values are as you can see the truth value of checking the equality between the previous 2 vectors outputted. As you can see, the algo should have converged/stopped a long while ago, but didn't until some arbetrary moment. What am I doing wrong?
SOLUTION:
ofcourse I forgot to put matlab in format long and didn't think about it straight on. (I don't use matlab all that often) anyway the solution I have is adding a precision boundary to the method, resulting in following code:
function[E] = eig_noshift(A, prec)
A_k = A;
v_prec = [prec;prec;prec];
for(i=0:inf)
[Qk,Rk] = qr(A_k);
A_k1 = Rk*Qk;
if(diag(A_k1) - diag(A_k) < v_prec)
break
end
A_k = A_k1;
end
E = diag(A_k);
Method stops when asked precision has been reached. cheers!
The output does not include all digits. Print the difference instead: diag(A_k1)-diag(A_k)

Blockdiagonal variation grid

I have the feeling I am missing something intuitive in my solution for generating a partially varied block-diagonal grid. In any case, I would like to get rid of the loop in my function (for the sake of challenge...)
Given tuples of parameters, number of intervals and percentage variation:
params = [100 0.5 1
24 1 0.9];
nint = 1;
perc = 0.1;
The desired output should be:
pspacegrid(params,perc,nint)
ans =
90.0000 0.5000 1.0000
100.0000 0.5000 1.0000
110.0000 0.5000 1.0000
100.0000 0.4500 1.0000
100.0000 0.5000 1.0000
100.0000 0.5500 1.0000
100.0000 0.5000 0.9000
100.0000 0.5000 1.0000
100.0000 0.5000 1.1000
21.6000 1.0000 0.9000
24.0000 1.0000 0.9000
26.4000 1.0000 0.9000
24.0000 0.9000 0.9000
24.0000 1.0000 0.9000
24.0000 1.1000 0.9000
24.0000 1.0000 0.8100
24.0000 1.0000 0.9000
24.0000 1.0000 0.9900
where you can see that the variation occurs at the values expressed by this mask:
mask =
1 0 0
1 0 0
1 0 0
0 1 0
0 1 0
0 1 0
0 0 1
0 0 1
0 0 1
1 0 0
1 0 0
1 0 0
0 1 0
0 1 0
0 1 0
0 0 1
0 0 1
0 0 1
The function pspacegrid() is:
function out = pspacegrid(params, perc, nint)
% PSPACEGRID Generates a parameter space grid for sensitivity analysis
% Size and number of variation steps
sz = size(params);
nsteps = nint*2+1;
% Preallocate output
out = reshape(permute(repmat(params,[1,1,nsteps*sz(2)]),[3,1,2]),[],sz(2));
% Mask to index positions where to place interpolated
[tmp{1:sz(2)}] = deal(true(nsteps,1));
mask = repmat(logical(blkdiag(tmp{:})),sz(1),1);
zi = cell(sz(1),1);
% LOOP per each parameter tuple
for r = 1:sz(1)
% Columns, rows, rows to interpolate and lower/upper parameter values
x = 1:sz(2);
y = [1; nint*2+1];
yi = (1:nint*2+1)';
z = [params(r,:)*(1-perc); params(r,:)*(1+perc)];
% Interpolated parameters
zi{r} = interp2(x,y,z, x, yi);
end
out(mask) = cat(1,zi{:});
I think I got it, building off your pre-loop code:
params = [100 0.5 1
24 1 0.9];
nint = 1;
perc = 0.1;
sz = size(params);
nsteps = nint*2+1;
% Preallocate output
out = reshape(permute(repmat(params,[1,1,nsteps*sz(2)]),[3,1,2]),[],sz(2));
%Map of the percentage moves
[tmp{1:sz(2)}] = deal(linspace(-perc,perc,nint*2+1)');
mask = repmat(blkdiag(tmp{:}),sz(1),1) + 1; %Add one so we can just multiply at the end
mask.*out
So instead of making your mask replicate the ones I made it replicate the percentage moves each element makes which is a repeating pattern, the basic element is made like this:
linspace(-perc,perc,nint*2+1)'
Then it's as simple as adding 1 to the whole thing and multiplying by your out matrix
I tested it as follows:
me = mask.*out;
you = pspacegrid(params, perc, nint);
check = me - you < 0.0001;
mean(check(:))
Seemed to work when I fiddled with the inputs. However I did get an error with your function, I had to change true(...) to ones(...). This might be because I'm running it online which probably uses Octave rather than Matlab.