Matrix Multiplication Error: Matrix dimensions must agree - matlab

I have this code:
function main()
a = 1.0e+04 * [0.005055052938847,0.010897917816899,0.022355965424711,0.043081981439108,0.077074049394439,0.127074049394439,0.193081981439108,0.272355965424711,0.360897917816899,0.455055052938847,0.552256864601221,0.650978664311931,0.750415022011379,0.850172973479352,0.950071110045004,1.050028912038499,1.150011648830086]
B = 1.0e+04 * [1.215101736363023,0.697166188613023,0.400000000000000,0.229500515964941,0.131676217070435,0.075549399394941,0.043346565354951,0.024870147785673,0.014269279372341,0.008187017446000,0.004697311820178,0.002695088715947,0.001546310627203,0.000887197716963,0.000509030834515,0.000292057097908,0.000167568136653
m = timeloop(a,B);
end
function m = timeloop(a,B)
st = zeros(49,4);
t = 0:0.001:0.05;
for i = (1:49)
st(i+1,1:4) = next_state(st(i,1:4),a,B,1e-4);
end
m = mean(prod(state,2))
end
function next_state = next_state(state,alpha,beta,dt)
nch = size(state,2);
p01 = rand(1,nch);
alphadt = repmat(alpha,1,nch)*dt;
betadt = repmat(beta,1,nch)*dt;
next_state1 = (p01<alphadt) .* (state==0);
next_state0 = (p01<betadt) .* (state==1);
next_state = state + next_state1 - next_state0;
end
but it gives me the following error:
Matrix dimensions must agree.
Error in q3>next_state (line 59)
next_state1 = (p01<alphadt) .* (state==0);
Error in q3>timeloop (line 49)
st(i+1,1:4) = next_state(st(i,1:4),a,B,1e-4);
Error in q3 (line 4)
m = timeloop(a,B);
Error in run (line 86)
evalin('caller', [script ';']);
I've tried changing the multiplication to just * with no improvement. What I've looked up online hasn't seemed to be able to help me. I don't understand MATLAB very well so you will have to be very specific in your explanation.

If you debugged your code you would quickly realise the issue.
alpha in next_state is the same as a in main, meaning it is of size 1x3.
You then create alphadt using repmat(alpha,1,4), so it is of size 1x12.
Then you try and do the following
(p01<alphadt) .* (state==0)
% 1x12 .* 1x3
As the error clearly states, your matrix dimensions don't agree.
Because you haven't given any context for what you're trying to achieve, it's not obvious what the solution should be. Perhaps you want to also use repmat on state, or loop over single values from a.

Related

iterating matlab symbolic solve function

I am trying to solve the equation below for array d. I have used the snippet below:
channel_size = 9e-3;
d = [11e-3, 12e-3];
sigma = 0.49;
ee = 727/9806.65;
alpha = d-channel_size;
sym('p',[1 2])
for i = 1:2
eqn = alpha == (4.3^(1/7))*(p^(3/11))*(((1-(sigma^2))/ee)^(7/5))/(d.^(1/6))
S = solve(eqn, p)*0.015;
vpa(S/13e-12)
end
In fact, I should get two number corresponding to d(1) and d(2), but it does not work and this error appears:
Error using mupadmex
Error in MuPAD command: Operands are invalid. [linalg::matlinsolve]
Error in sym/privBinaryOp (line 1693)
Csym = mupadmex(op,args{1}.s, args{2}.s, varargin{:});
Error in sym/mrdivide (line 232)
X = privBinaryOp(A, B, 'symobj::mrdivide');
Declaring (d.^(1/6)) is wrong and instead (d(i)^(1/6)) should be used. In addition, as alpha = d-channel_size, in the equation, I should also declare alpha(i) instead of simple alpha.

MATLAB strange error Gamma function numerical integration

i try to run the following in order to integrate numerically:
nu = 8;
psi=-0.2;
lambda = 1;
git = #(u) tpdf((0 - lambda * skewtdis_inverse(u, nu, psi)), nu);
g(t,i) = integral(git,1e-10,1-1e-10,'AbsTol',1e-16);
where tpdf is a matlab function and skewtdis:inverse looks like this:
function inv = skewtdis_inverse(u, nu, lambda)
% PURPOSE: returns the inverse cdf at u of Hansen's (1994) 'skewed t' distribution
c = gamma((nu+1)/2)/(sqrt(pi*(nu-2))*gamma(nu/2));
a = 4*lambda*c*((nu-2)/(nu-1));
b = sqrt(1 + 3*lambda^2 - a^2);
if (u<(1-lambda)/2);
inv = (1-lambda)/b*sqrt((nu-2)./nu)*tinv(u/(1-lambda),nu)-a/b;
elseif (u>=(1-lambda)/2);
inv = (1+lambda)/b*sqrt((nu-2)./nu).*tinv(0.5+1/(1+lambda)*(u-(1-lambda)/2),nu)-a/b;
end
What i get out is:
Error in skewtdis_inverse (line 6)
c = gamma((nu+1)/2)/(sqrt(pi*(nu-2))*gamma(nu/2));
Output argument "inv" (and maybe others) not assigned during call to "F:\Xyz\skewtdis_inverse.m>skewtdis_inverse".
Error in #(u)tpdf((0-lambda*skewtdis_inverse(u,nu,psi)),nu)
Error in integralCalc/iterateScalarValued (line 314)
fx = FUN(t);
Error in integralCalc/vadapt (line 133)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 76)
[q,errbnd] = vadapt(#AtoBInvTransform,interval);
Error in integral (line 89)
Q = integralCalc(fun,a,b,opstruct);
If i , however call the function in thr handle directly there are no Problems:
tpdf((0 - lambda * skewtdis_inverse(1e-10, nu, psi)), nu)
ans =
1.4092e-11
tpdf((0 - lambda * skewtdis_inverse(1-1e-10, nu, psi)), nu)
ans =
7.0108e-10
Your effort is highly appreciated!
By default, integral expects the function handle to take a vector input.
In your code, the if-statement creates a complication since the condition will evaluate to true only if all elements of u satisfy it.
So, if u is a vector that has elements both greater than and less than (1-lambda)/2, inv will never be assigned.
There are two options:
Put the if-statement in a for-loop and iterate over all of the elements of u.
Use logical indexes for the assignment.
The second option is faster for large element count and, in my opinion, cleaner:
inv = u; % Allocation
IsBelow = u < (1-lambda)/2; % Below the threshold
IsAbove = ~IsBelow ; % Above the threshold
inv(IsBelow) = (1-lambda)/b*sqrt((nu-2)./nu)*tinv(u(IsBelow)/(1-lambda),nu)-a/b;
inv(IsAbove) = (1+lambda)/b*sqrt((nu-2)./nu)*tinv(0.5+1/(1+lambda)*(u(IsAbove)-(1-lambda)/2),nu)-a/b;

Create flexible function handle

I am using numerical integration in MATLAB, with one varibale to integrate over but the function also contains a variable number of terms depending on the dimension of my data. Right now this looks like the following for the 2-dimensional case:
for t = 1:T
fxt = #(u) exp(-0.5*(x(t,1)-theta*norminv(u,0,1)).^2) .* ...
exp(-0.5*(x(t,2) -theta*norminv(u,0,1)).^2);
f(t) = integral(fxt,1e-4,1-1e-4,'AbsTol',1e-3);
end
I would like to have this function flexible in the sense that there could be any number of data points in, each in the following term:
exp(-0.5*(x(t,i) -theta*norminv(u,0,1)).^2);
I hope this is understandable.
If x and u have a valid dimension match (vector-vector or array-scalar) for the subtraction, you can put the whole matrix x into the handle and pass it to the integral function using the name-parameter pair ('ArrayValued',true):
fxt = #(u) exp(-0.5*(x - theta*norminv(u,0,1)).^2) .* ...
exp(-0.5*(x - theta*norminv(u,0,1)).^2);
f = integral(fxt,1e-4,1-1e-4,'AbsTol',1e-3,'ArrayValued',true);
[Documentation]
You may need a loop if integral ever passes a vector u into the handle.
But in looking at how the integral function is written, the integration nodes are entered as scalars for array-valued functions, so the loop shouldn't be necessary unless some weird dimension-mismatch error is thrown.
Array-Valued Output
In response to the comments below, you could try this function handle:
fx = #(u,t,k) prod(exp(-0.5*(x(t,1:k)-theta*norminv(u,0,1)).^2),2);
Then your current loop would look like
fx = #(u,t,k) prod(exp(-0.5*(x(t,1:k)-theta*norminv(u,0,1)).^2),2);
k = 2;
for t = 1:T
f(t) = integral(#(u)fx(u,t,k),1e-4,1-1e-4,'AbsTol',1e-3,'ArrayValued',true);
end
The ArrayValued flag is needed since x and u will have a dimension mismatch.
In this form, another loop would be needed to sweep through the k indexes.
However, we can improve this function by skipping the loop altogether since each iterate of the loop is independent by using the ArrayValued mode:
fx = #(u,k) prod(exp(-0.5*(x(:,1:k)-theta*norminv(u,0,1)).^2),2);
k = 2;
f = integral(#(u)fx(u,k),1e-4,1-1e-4,'AbsTol',1e-3,'ArrayValued',true);
Vector-Valued Output
If ArrayValued is not desired, which may be the case if the integration requires a lot of subdivisions and a vector-valued u is preferable, you can also try a recursive version of the handle using cell arrays:
% x has size [T,K]
fx = cell(K,1);
fx{1} = #(u,t) exp(-0.5*(x(t,1) - theta*norminv(u,0,1)).^2);
for k = 2:K
fx{k} = #(u,t) fx{k-1}(u,t).*exp(-0.5*(x(t,k) - theta*norminv(u,0,1)).^2);
end
f(T) = 0;
k = 2;
for t = 1:T
f(t) = integral(#(u)fx{k}(u,t),1e-4,1-1e-4,'AbsTol',1e-3);
end
ThanksTroy but now I run into the follwing:
x = [0.3,0.8;1.5,-0.7];
T = size(x,1);
k = size(x,2);
theta= 1;
fx = #(u,t,k) prod(exp(-0.5*(x(t,1:k) - theta*norminv(u,0,1))^2));
for t = 1,T
f(t) = integral(#(u)fx(u,t,k),1e-4,1-1e-4,'AbsTol',1e-3);
end
Error using -
Matrix dimensions must agree.
Error in #(u,t,k)prod(exp(-0.5*(x(t,1:k)-theta*norminv(u,0,1))^2))
Error in #(u)fx(u,t,k)
Error in integralCalc/iterateScalarValued (line 314)
fx = FUN(t);
Error in integralCalc/vadapt (line 133)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 76)
[q,errbnd] = vadapt(#AtoBInvTransform,interval);
Error in integral (line 89)
Q = integralCalc(fun,a,b,opstruct);

Cubic spline interpolation of function

I am trying to interpolate the following function using the MATLAB function spline,
at equidistant points xi = i./n, i = 0,1,...,n, and for n = 2^j, j = 4,5,...,14.
For each calculation, I record the maximum error at the points x = 0:0.001:1 and plot these errors against n using a loglog plot.
Below is the code,
index=1
for j = 4:1:14;
n = 2^j;
i = 0:1:n;
xi = i./n;
yi = ((exp(3*xi))*sin(200.*(xi.^2))) ./(1+20.*(xi.^2));
x = 0:.001:1;
ye = ((exp(3*x))*sin(200*x.^2)) ./(1+20*x.^2);
yp = spline(x,xi,yi);
err = ye - yp;
merr(index) = max(err);
index = index+1;
end
n1 = 10:10:170;
loglog(n1, merr,'.')
xlabel('n');
ylabel('errors');
title('Cubic Splines');
but when I run the code, I got the following error:
Error using * Inner matrix dimensions must agree.
Error in (line 9) yi = ((exp(3*xi))sin(200.(xi.^2)))
./(1+20.*(xi.^2));
I'm just starting learning MatLab, can anyone help?
You want element-wise multiplication (.*) for the following part of code:
yi = ((exp(3*xi))*sin(200.*(xi.^2))) ./(1+20.*(xi.^2));
should be
yi = ((exp(3*xi)).*sin(200.*(xi.^2))) ./(1+20.*(xi.^2));
The same issue is present for the computation of ye.
When you use mtimes (*), MATLAB tries to do matrix multiplication, which in your case (1-by-n times 1-by-n) is invalid.
Then you will run into a problem with your spline command. Change it to yp = spline(xi,yi,x); so that the values at which you want to interploate (x) are the last argument.

fminsearch on a function internally using matrices

I'm having trouble minimizing a rather complicated function:
% Current densities - psi is a 4x1 fourvector
j0 = #(psi) psi' * psi;
% Solutions
chi1 = #(n_,r_,kt_,theta_) ...
1/sqrt(2) * ...
[ exp(1i*n_*theta_) .* besselj(n_,kt_*r_); ...
exp(1i*(n_+1)*theta_) .* besselj(n_+1,kt_*r_) ];
chi2 = #(n_,r_,kt_,theta_) ...
1/sqrt(2) * ...
[ exp(1i*n_*theta_) .* besselj(n_,kt_*r_); ...
-exp(1i*(n_+1)*theta_) .* besselj(n_+1,kt_*r_) ];
uplus = #(n_,E_,m_,r_,kz_,kt_,theta_) ...
sqrt((E_+m_)/(4*m_)) * ...
[ chi1(n_,r_,kt_,theta_); ...
(kz_-1i*kt_)/(E_+m_) * chi2(n_,r_,kt_,theta_) ];
Here: n,E,m,kz,theta are all constants for any purpose. I need to fit j0 to a step function (1 for r=1...10), and the model function being the four-vector psi, consisting of summing uplus over kt=zeros of besselj(n,kt/10*r), so that besselj(0,kt*10) is zero. The problem is that fminsearch doesn't like my complicated setup:
uplus_reduced = #(r_,kt_) uplus(0,E,m,r_,kz,kt_,0);
error_function = #(r_,coeffs_) error_j0_stepfunction(r_,coeffs_,...
uplus_reduced);
coeffs(1,:) = fminsearch( #(r) error_function(r',coeffs(:,1)), r);
where error_j0_stepfunction is this:
function error = error_j0_stepfunction(r,coeffs,basisspinor)
% Zeros of BesselJ
Nzeros = 100;
lambda = [ besselzero(0,Nzeros,1)';
besselzero(1,Nzeros,1)';
besselzero(2,Nzeros,1)' ];
% calculate psi= sum over zeros
psi = zeros(4,length(r));
for k=1:length(coeffs)
size_psi = size(psi(:,:) )
size_coeffs = size(coeffs(k))
size_basisspinor = size( basisspinor(r(:)', lambda(1,k)/10))
psi(:,:) = psi(:,:) + coeffs(k) * ...
basisspinor(r(:), lambda(1,k)/10);
end;
% calculate density (j0)
density = zeros(1,length(r));
for k=1:length(r)
density(k) = j0(psi(:,k));
end;
% calculate square error
error = sum((1-density(:)).^2);
end
I hope I have been clear enough, and at the same time concise so this can be answered. Thanks for any help!
EDIT: The error I get is this (with output making it nonsensical to me):
size_psi = 4 1000
size_coeffs = 1 1
size_basisspinor = 4 1000
Error using +
Matrix dimensions must agree.
Error in error_j0_stepfunction (line 15)
psi(:,:) = psi(:,:) + coeffs(k) * ...
Error in #(r_,coeffs_)error_j0_stepfunction(r_,coeffs_,uplus_reduced)
Error in #(r)error_function(r',coeffs(:,1))
Error in fminsearch (line 191)
fv(:,1) = funfcn(x,varargin{:});
Error in dirac_stepfunction (line 17)
coeffs(1,:) = fminsearch( #(r) error_function(r',coeffs(:,1)), r);
Error in dirac (line 7)
dirac_stepfunction;
It should make enough sense to anyone reading the error and code above. coeffs is a 20x3 matrix, r is a 1x1000 (or 1000x1)
Your call to basisspinor in the size-statement has r(:)' as first argument, while the second call to basisspinor has just r(:). I guess the first version was also intended for the second call.