Custom correlation function in matlab - matlab

I am trying to create a custom function for pearson's correlation coefficient with this code in matlab 2010
function [p] = customcorr(o)
x := a
y := b
x_mean := mean(a)
y_mean := mean(b)
x_std := std(a)
y_std := std(b)
n := length(o)
r := (1/(n-1))*((x-x_mean)*(y-y_mean))/(x_std*y_std)
end
But i get an error when trying to execute it
Error in ==> customcorr at 2
x := a
Anybody might know what the problem is? Thank you

First, check the correct MATLAB syntax: a "normal" assignment is done by =, not by :=.
Second, you use a and b but these are not defined as parameters of the function. Replace the function head by function p = customcorr(a,b).
Third, I am not really sure what o should be, I assume it can be replaced by length(a) or length(b).
The estimator for an unbiased correlation coefficient is given by
(from wikipedia)
Thus you need to sum all the (a-a_mean).*(b-b_mean) up with sum. Note that it is required to write .* to get the element-wise multiplication. That way you subtract the mean from each element of the vectors, then multiply the corresponding a's and b's and sum up the results of these multiplications.
Together this is
function p = customcorr(a,b)
a_mean = mean(a);
b_mean = mean(b);
a_std = std(a);
b_std = std(b);
n = length(a);
p = (1/(n-1)) * sum((a-a_mean).*(b-b_mean)) / (a_std*b_std);
end
What MATLAB does in their corr function (besides many other interesting things) is, they check the number of arguments (nargin variable) to see if a and b were supplied or not. You can do that by adding the following code to the function (at the beginning)
if nargin < 2
b = a;
end

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.

how to solve a matrix equation in maple

I have a program that does some work to get a matrix w, which is 3(n+1) by 3(n+1). I have a vector fbar that is 3(n+1) by 1. I want to get the matrix that, when w is multiplied by it, gives fbar.
In mathematical notation, w * A = fbar. I have w and fbar, and I want A.
I tried to solve it with this command:
fsolve({seq(multiply(w, A)[i, 1] = fbar[i, 1], i = 1 .. 3*(n+1))})
but I don't understand the response Maple gave:
fsolve({2.025881905 A1[2,1]+7.814009150 A1[3,1]+...
-7.071067816 10^(-13) A1[3,1]-0.0004999999990
A1[4,1]-0.0007071067294 A1[5,1]-0.0004999999990 A1[6,1])
A3[6,1]=0},{A1[1,1],A1[2,1],A1[3,1],A1[4,1],A1[5,1],A1[6,1],A\
2[1,1],A2[2,1],A2[3,1],A2[4,1],A2[5,1],A2[6,1],A3[1,1],A3[2,1]\
,A3[3,1],A3[4,1],A3[5,1],A3[6,1]})
What does this mean, and how can I get a more meaningful answer?
You can do this directly with the LinearSolve functional from the LinearAlgebra package if w and fbar are defined as a matrix and vector respectively. The below code makes a reproducible example. Note that the solution of LinearSolve should be equal to x.
w := Matrix(<<1,2,3>|<4,5,6>|<7,8,10>>);
LinearAlgebra[ReducedRowEchelonForm](%); ## Full rank => 1 solution)
x := <1,2,3>;
fbar := w.x;
## Solve the equation w.x = fbar
LinearAlgebra[LinearSolve](w,fbar);

MATLAB function handles and parameters

When I type help gmres in MATLAB I get the following example:
n = 21; A = gallery('wilk',n); b = sum(A,2);
tol = 1e-12; maxit = 15;
x1 = gmres(#(x)afun(x,n),b,10,tol,maxit,#(x)mfun(x,n));
where the two functions are:
function y = afun(x,n)
y = [0; x(1:n-1)] + [((n-1)/2:-1:0)'; (1:(n-1)/2)'].*x+[x(2:n); 0];
end
and
function y = mfun(r,n)
y = r ./ [((n-1)/2:-1:1)'; 1; (1:(n-1)/2)'];
end
I tested it and it works great. My question is in both those functions what is the value for x since we never give it one?
Also shouldn't the call to gmres be written like this: (y in the #handle)
x1 = gmres(#(y)afun(x,n),b,10,tol,maxit,#(y)mfun(x,n));
Function handles are one way to parametrize functions in MATLAB. From the documentation page, we find the following example:
b = 2;
c = 3.5;
cubicpoly = #(x) x^3 + b*x + c;
x = fzero(cubicpoly,0)
which results in:
x =
-1.0945
So what's happening here? fzero is a so-called function function, that takes function handles as inputs, and performs operations on them -- in this case, finds the root of the given function. Practically, this means that fzero decides which values for the input argument x to cubicpoly to try in order to find the root. This means the user just provides a function - no need to give the inputs - and fzero will query the function with different values for x to eventually find the root.
The function you ask about, gmres, operates in a similar manner. What this means is that you merely need to provide a function that takes an appropriate number of input arguments, and gmres will take care of calling it with appropriate inputs to produce its output.
Finally, let's consider your suggestion of calling gmres as follows:
x1 = gmres(#(y)afun(x,n),b,10,tol,maxit,#(y)mfun(x,n));
This might work, or then again it might not -- it depends whether you have a variable called x in the workspace of the function eventually calling either afun or mfun. Notice that now the function handles take one input, y, but its value is nowhere used in the expression of the function defined. This means it will not have any effect on the output.
Consider the following example to illustrate what happens:
f = #(y)2*x+1; % define a function handle
f(1) % error! Undefined function or variable 'x'!
% the following this works, and g will now use x from the workspace
x = 42;
g = #(y)2*x+1; % define a function handle that knows about x
g(1)
g(2)
g(3) % ...but the result will be independent of y as it's not used.

MuPAD evaluation of local variables, Sum of row of array

I have discovered a strange behavior in MuPAD version 5.7.0 (MATLAB R2011b), and I would like to know whether this is a bug, and if not so, what I am doing wrong. Ideally, I would also like to know why MuPAD does what it does.
Consider the array C of size 3x3, the elements of which have some example values. I would like to regard this array as an array of arrays and thus use cascaded indexing.
The problem apparently arises when both indices are local variables of different nested scopes, namely when the first index's scope is wider than the second index's one. There is no problem if the first index is a constant.
When I enter:
reset();
C := [[a,b,c],[d,e,f],[g,h,i]];
sum((C[3])[t], t = 1..3);
S := j -> sum((C[j])[t], t = 1..3);
S(3);
I get the following result:
I would expect lines 3 and 5 in the code (2 and 4 in the output) to yield the same result: g+h+i. Instead, line 5 produces a+e+i, which seems to be the diagonal of C.
When I do the same with product instead of sum, the result is even stranger, but might reveal more about the "error's" source, particularly DOM_VAR(0,2):
reset();
C := [[a,b,c],[d,e,f],[g,h,i]];
product((C[3])[t], t = 1..3);
eval(product((C[3])[t], t = 1..3));
S := j -> product((C[j])[t], t = 1..3);
S(3);
eval(S(3));
I get:
I might be on the wrong track here, but I suspect that a closure is created that tried to save the surrounding scope's local variables, which are undetermined at the time of the closure's creation. Also, substitutions seem to stop at some point, which is overridden by eval().
Practical Problem
The practical problem I am trying to solve is the following:
reset();
aVec := Symbol::accentUnderBar(Symbol::alpha)
Problem: Calculate multinomials of the form
hold(sum(x(i), i=i_0..i_k)^n)
On Wikipedia, the following form is defined:
sumf := freeze(sum):
hold(sum(x[i], i=1..m)^n)=sumf(binomial(n,aVec)*product(x[t]^aVec[t], t = 1..m), abs(aVec)=n);
In order to implement this, we need to define the set of vectors alpha, the sum of which equals m.
These correspond to the set of possible compositions of n with length m and possible zero elements:
C := (n,m) -> combinat::compositions(n, MinPart = 0, Length = m)
For example, the sum
n := 3:
m := 3:
sumf(x[i], i=1..m)^n = sum(x[i], i=1..m)^n;
would call for these combinations of powers, each of which is one vector alpha:
A := C(n,m)
Additionally, we need the multinomial coefficients.
Each such coefficient depends on vector alpha and the power n:
multinomial := (n, aVec) -> fact(n) / product(fact(aVec[k]), k = 1..nops(aVec))
For example, the number of times that the second composition appears, is:
multinomial(n, A[2])
Summation over all compositions yields:
sum(multinomial(n,A[i])*product(x[t]^A[i][t], t = 1..m), i = 1..nops(A))
The powers are correct, but the coefficients are not. This seems related to the boiled-down abstract problem stated first in this question.
The expression [[a,b,c],[d,e,f],[g,h,i]] is not an array in MuPAD. It is a "list of lists." I'm guessing that's not what you're after. Lists are commonly used to initialize arrays and matrices and other objects (more here). For these examples, either arrays or matrices will work, but note that these two data types have different advantages.
Using array:
reset();
C := array([[a,b,c],[d,e,f],[g,h,i]]);
sum(C[3, t],t=1..3);
S := j -> sum(C[j, t], t = 1..3);
S(3);
which returns
Note the different way row/column indexing is represented relative to that in your question. Similarly, modifying your other example
reset();
C := matrix([[a,b,c],[d,e,f],[g,h,i]]);
product(C[3, t], t = 1..3);
S := j -> product(C[j, t], t = 1..3);
S(3);
results in
If you do happen to want to use lists for this, you can do so like this
reset();
C := [[a,b,c],[d,e,f],[g,h,i]];
_plus(op(C[3]));
S := j -> _plus(op(C[j]));
S(3);
which returns
The _plus is the functional form of + and op extracts each element from the list. There are other ways to do this, but this is one of the simplest.
I am posting this answer only to provide a working example of the practical problem from the question. horchler provided the decisive solution by proposing to use a matrix instead of a list of lists.
Basically, this is a modified transscript of the practical problem.
Practical Solution
The practical problem I am trying to solve is the following:
reset();
aVec := Symbol::accentUnderBar(Symbol::alpha)
Problem: Calculate multinomials of the form
hold(sum(x(i), i=i_0..i_k)^n)
On Wikipedia, the following form is defined:
sumf := freeze(sum):
hold(sum(x[i], i=1..m)^n)=sumf(binomial(n,aVec)*product(x[t]^aVec[t], t = 1..m), abs(aVec)=n);
In order to implement this, we need to define the set of vectors alpha, the sum of which equals m.
These correspond to the set of possible compositions of n with length m and possible zero elements:
C := (n,m) -> combinat::compositions(n, MinPart = 0, Length = m)
For example, the sum
n := 3:
m := 3:
sumf(x[i], i=1..m)^n = sum(x[i], i=1..m)^n;
would call for these combinations of powers, each of which is one vector alpha:
A := matrix(nops(C(n,m)),m,C(n,m));
Additionally, we need the multinomial coefficients.
Each such coefficient depends on vector alpha and the power n:
multinomial := (n, aVec) -> fact(n) / product(fact(aVec[k]), k = 1..nops(aVec))
For example, the number of times that the second composition appears, is:
multinomial(n,A[2,1..m])
Summation over all compositions yields:
sum(multinomial(n,A[i,1..m])*product(x[t]^A[i,t], t = 1..m), i = 1..nops(C(n,m)));
Finally, prove that the result transforms back:
simplify(%)

Please Help: In an assignment A(I) = B, the number of elements in B and I must be the same. MATLAB

I was asked in an assignment to use Euler's method to determine the values of t and y from t=0:1000. I have all the basic code and parameters down but when i put my Euler's equation in I get the error code
In an assignment A(I) = B, the number of
elements in B and I must be the same.
Error in Project1 (line 24)
Ay(i+1) = Ay(i) + (dAy)*x;
How could I change these variables between vectors and scalars to allow the equation to run? My full code can be found below:
dt=x;
Ay=zeros(1,1001);
Ay0=1250;
Ay(1) = Ay0;
t=0;
y=0;
t=0:dt:1000;
for i=1:1000
if y > 10
Qout=3*(y-10).^1.5;
else
Qout=0;
end
Qin=1350*sin(t).^2;
dAy=Qin-Qout;
Ay(i+1) = Ay(i) + dAy*dt;
end
plot(t,y);
The issue is that your variable "Qin" is not a number it is a vector containing sin values of the whole vector t. Similarly your "dAy" is also a vector. Hence it cannot be stored in a variable Ay.
if your dt =x = 1, just replace sin(t) with sin(i) i.e.
replace
Qin=1350*sin(t).^2;
by
Qin=1350*sin(i).^2;
The problem lies in the line of your code:
Ay(i+1) = Ay(i) + dAy*dt;
dAy*dt returns a vector.
When you add it to Ay(i) you still end up with a vector.
Ay(i+1) is a SINGLE element within a vector.
You Cannot assign a vector quantity to an element within a vector.