I'm trying to write the code for quadrature phase-shift keying (QPSK) with zeroforcing when N=2, and I got an error.
Here is the code:
Modulation = 'QPSK'
Decode_Method = 'ZeroForcing'
switch Modulation
case {'QPSK'}
Symbols = [ 1+j 1-j -1+j -1-j ]';
end
Symbols = Symbols.';
nSymbols = length(Symbols);
SNR_Array = [0.3 0.7 1.2 2.5 5 6.2 10 15.4 22 45 75.7 100.0];
nSNR = length(SNR_Array);
Ntest = 20;
N = 2;
for iSNR = 1 : nSNR
SNR = SNR_Array(iSNR);
Nerror = 0;
for i = 1:Ntest
H = randn(N,N) + j*randn(N,N);
X = Symbols( ceil( nSymbols*rand(N,1) ) )';
Noise = (randn(N,1) + j*randn(N,1))/sqrt(2)/sqrt(SNR);
Y = H*X + Noise;
switch Decode_Method
case {'ZeroForcing'}
X_Decode = Zero_Forcing(Y,H,Symbols);
end
end
Nerror = Nerror + length( find( X ~= X_Decode) );
end
Symbol_Error_Rate(iSNR) = Nerror/Ntest/N;
figure(1)
loglog(SNR_Array, Symbol_Error_Rate,'b')
hold on
xlabel('SNR')
ylabel('Symbol Error Ratio')
title('Symbol Error Ratio for NxN MIMO System')
And the error is:
??? Undefined function or method 'Zero_Forcing' for input arguments of type 'double'.
Error in ==> Untitled2 at 33
X_Decode = Zero_Forcing(Y,H,Symbols);
How can I fix this error?
The error indicates that MATLAB cannot find the function Zero_Forcing. If you have a function of that name, you should make sure it's on the MATLAB path, that is, a directory MATLAB knows about. Otherwise, you should write the function. It seems rather important.
Also, you may want to not call your function 'Untitled2', but give it a more meaningful name.
Related
I am having difficulty in finding roots of a nonlinear equation. I have tried Matlab and Maple both, and both give me the same error which is
Error, (in RootFinding:-NextZero) can only handle isolated zeros
The equation goes like
-100 + 0.1335600000e-5*H + (1/20)*H*arcsinh(2003.40/H)
The variable is H in the equation.
How do I find the roots (or the approximate roots) of this equation?
Matlab Code:
The function file:
function hor_force = horizontal(XY, XZ, Lo, EAo, qc, VA)
syms H
equation = (-1*ZZ) + (H/qc)*(cosh((qc/H)*(XZ- XB))) - H/qc + ZB;
hor_force = `solve(equation);`
The main file:
EAo = 7.5*10^7;
Lo = 100.17;
VA = 2002;
XY = 0;
ZY = 0;
XB = 50;
ZB = -2;
XZ = 100;
ZZ = 0;
ql = 40;
Error which Matlab shows:
Error using sym/solve (line 22)
Error using maplemex
Error, (in RootFinding:-NextZero) can only handle isolated zeros
Error in horizontal (line 8)
hor_force = solve(equation);
Error in main (line 34)
h = horizontal(XY, XZ, Lo, EAo, ql, VA)
http://postimg.org/image/gm93z3b7z/
You don't need the symbolic toolbox for this:
First, create an anonymous function that can take vectors at input (use .* and ./:
equation = #(H) ((-1*ZZ) + (H./qc).*(cosh((qc./H).*(XZ- XB))) - H./qc + ZB);
Second, create a vector that you afterwards insert into the equation to find approximately when the sign of the function changes. In the end, use fzero with x0 as the second input parameter.
H = linspace(1,1e6,1e4);
x0 = H(find(diff(sign(equation(H))))); %// Approximation of when the line crosses zero
x = fzero(equation, x0) %// Use fzero to find the crossing point, using the initial guess x0
x =
2.5013e+04
equation(x)
ans =
0
To verify:
You might want to check out this question for more information about how to find roots of non-polynomials.
In Maple, using the expression from your question,
restart:
ee := -100 + 0.1335600000e-5*H + (1/20)*H*arcsinh(2003.40/H):
Student:-Calculus1:-Roots(ee, -1e6..1e6);
[ 5 ]
[-1.240222868 10 , -21763.54830, 18502.23816]
#plot(ee, H=-1e6..1e6, view=-1..1);
In Matlab I want to create the partial derivative of a cost function called J(theta_0, theta_1) (in order to do the calculations necessary to do gradient descent).
The function J(theta_0, theta_1) is defined as:
Lets say h_theta(x) = theta_1 + theta_2*x. Also: alpha is fixed, the starting values of theta_1 and theta_2 are given. Let's say in this example: alpha = 0.1 theta_1 = 0, theta_2 = 1. Also I have all the values for x and y in two different vectors.
VectorOfX =
5
5
6
VectorOfX =
6
6
10
Steps I took to try to solve this in Matlab: I have no clue how to solve this problem in matlab. So I started off with trying to define a function in Matlab and tried this:
theta_1 = 0
theta_2 = 1
syms x;
h_theta(x) = theta_1 + t2*x;
This worked, but is not what I really wanted. I wanted to get x^(i), which is in a vector. The next thing I tried was:
theta_1 = 0
theta_2 = 1
syms x;
h_theta(x) = theta_1 + t2*vectorOfX(1);
This gives the following error:
Error using sym/subsindex (line 672)
Invalid indexing or function definition. When defining a
function, ensure that the body of the function is a SYM
object. When indexing, the input must be numeric, logical or
':'.
Error in prog1>gradientDescent (line 46)
h_theta(x) = theta_1 + theta_2*vectorOfX(x);
I looked up this error and don't know how to solve it for this particular example. I have the feeling that I make matlab work against me instead of using it in my favor.
When I have to perform symbolic computations I prefer to use Mathematica. In that environment this is the code to get the partial derivatives you are looking for.
J[th1_, th2_, m_] := Sum[(th1 + th2*Subscript[x, i] - Subscript[y, i])^2, {i, 1, m}]/(2*m)
D[J[th1, th2, m], th1]
D[J[th1, th2, m], th2]
and gives
Coming back to MATLAB we can solve this problem with the following code
%// Constants.
alpha = 0.1;
theta_1 = 0;
theta_2 = 1;
X = [5 ; 5 ; 6];
Y = [6 ; 6 ; 10];
%// Number of points.
m = length(X);
%// Partial derivatives.
Dtheta1 = #(theta_1, theta_2) sum(2*(theta_1+theta_2*X-Y))/2/m;
Dtheta2 = #(theta_1, theta_2) sum(2*X.*(theta_1+theta_2*X-Y))/2/m;
%// Loop initialization.
toll = 1e-5;
maxIter = 100;
it = 0;
err = 1;
theta_1_Last = theta_1;
theta_2_Last = theta_2;
%// Iterations.
while err>toll && it<maxIter
theta_1 = theta_1 - alpha*Dtheta1(theta_1, theta_2);
theta_2 = theta_2 - alpha*Dtheta2(theta_1, theta_2);
it = it + 1;
err = norm([theta_1-theta_1_Last ; theta_2-theta_2_Last]);
theta_1_Last = theta_1;
theta_2_Last = theta_2;
end
Unfortunately for this case the iterations does not converge.
MATLAB is not very flexible for symbolic computations, however a way to get those partial derivatives is the following
m = 10;
syms th1 th2
x = sym('x', [m 1]);
y = sym('y', [m 1]);
J = #(th1, th2) sum((th1+th2.*x-y).^2)/2/m;
diff(J, th1)
diff(J, th2)
%%PMOS
Cox = 10;
Co = .25;
Cjo = .6 ;
mj = .3 ;
phi_b = 1;
Cjswo = 0.066;
mjsw = 0.1 ;
phi_bsw = .5 ;
Ls = 240000 ;
W = 20 ;
Vd = 0:0.1:1 ;
%%%%%
**Cj = Cjo/((1-(Vd/phi_b))).^mj;**
Cjsw = Cjswo/((1-(Vd/phi_bsw))).^mjsw;
%%%%%%%%%%%%
Cdiff_PMOS = Cj*Ls*W + Cjsw*(2*Ls + W);
plot(Vd,Cdiff_PMOS);
The error it shows is
Error using /
Matrix dimensions must agree.
Error in P4_ee115_hw1 (line 14)
Cj = Cjo/((1-(Vd/phi_b))).^mj;
Any tips on how to fix it will be really apprecitated. Thanks .
If you put a ./ on the line for Cj and Cjsw this will work. So:
Cj = Cjo./((1-(Vd/phi_b))).^mj;
Cjsw = Cjswo./((1-(Vd/phi_bsw))).^mjsw;
You are getting this error because you are trying to divide a scalar by a vector and Matlab is picky about this. What you want is to do this element wise which is what the ./ will do and will remedy your code.
I want to solve equations in matlab, eg.
100+a/2=173*cos(b)
sqrt(3)*a/2=173*sin(b)
and the code would be:
[a,b]=solve('100+a/2=173*cos(b)','sqrt(3)*a/2=173*sin(b)','a','b')
However, if I want to take 100 as a variable, like
for k=1:100
[a,b]=solve('k+a/2=173*cos(b)','sqrt(3)*a/2=173*sin(b)','a','b')
end
There would be an error, how to make it?
degree=140/1000000;
p=42164000;
a=6378136.5;
b=6356751.8;
x_1=0;
y_1=p;
z_1=0;
for i=451:550
for j=451:550
alpha=(1145-i)*degree;
beta=(1145-j)*degree;
x_2=p/cos(alpha)*tan(beta);
y_2=0;
z_2=p*tan(alpha);
syms x y z x_1 x_2 y_1 y_2 z_1 z_2 a b
eq = [(x-x_1)*(y2-y_1)-(x_2-x_1)*(y-y_1),(x-x_1)*(z_2-z_1)-(x_2-x_1)*(z-z_1), b^2*(x^2+y^2)+a^2*(y^2)-a^2*b^2 ];
sol = solve(eq(1),x,eq(2),y, eq(3),z);
sol.x
sol.y
sol.z
end
end
I got the expression value, how do I get the numeric value of x,y,z?
[['x(1)=';'x(2)='],num2str(double(sol.x))]
not work ,shows
??? Error using ==> mupadmex
Error in MuPAD command: DOUBLE cannot convert the input expression into a double array.
If the input expression contains a symbolic variable, use the VPA function instead.
Error in ==> sym.sym>sym.double at 927
Xstr = mupadmex('mllib::double', S.s, 0);
Error in ==> f2 at 38
[['x(1)=';'x(2)='],num2str(double(sol.x))]
If you have access to the Symbolic Toolkit then you do the following:
syms a b k
eq = [k+a/2-173*cos(b), sqrt(3)*a/2-173*sin(b)];
sol = solve(eq(1),a,eq(2),b);
sol.a = simplify(sol.a);
sol.b = simplify(sol.b);
% There are two solutions for 'a' and 'b'
% check residuals for example k=20
subs(subs(eq,{a,b},{sol.a(1),sol.b(1)}),k,20)
% ans = 0.2e-13
subs(subs(eq,{a,b},{sol.a(2),sol.b(2)}),k,20)
% ans = 0.2e-13
Edit 1
Based on new code by OP the matlab script to solve this is:
clear all
clc
syms alpha beta
degree=140/1000000;
p=42164000;
a=6378136.5;
b=6356751.8;
x_1=0;
y_1=p;
z_1=0;
x_2 = p/cos(alpha)*tan(beta);
y_2 = 0;
z_2 = p*tan(alpha);
syms x y z
eq = [(x-x_1)*(y_2-y_1)-(x_2-x_1)*(y-y_1);...
(x-x_1)*(z_2-z_1)-(x_2-x_1)*(z-z_1); ...
b^2*(x^2+y^2)+a^2*(y^2)-a^2*b^2 ];
sol = solve(eq(1),x,eq(2),y,eq(3),z);
sol.x = simplify(sol.x);
sol.y = simplify(sol.y);
sol.z = simplify(sol.z);
pt_1 = [sol.x(1);sol.y(1);sol.z(1)] % First Solution Point
pt_2 = [sol.x(2);sol.y(2);sol.z(2)] % Second Solution Point
x = zeros(100,100);
y = zeros(100,100);
z = zeros(100,100);
for i=451:550
disp(['i=',num2str(i)])
for j=451:550
res = double(subs(pt_1,{alpha,beta},{(1145-i)*degree,(1145-j)*degree}));
x(i-450, j-450) = res(1);
y(i-450, j-450) = res(2);
z(i-450, j-450) = res(3);
end
end
disp('x=');
disp(x);
disp('y=');
disp(x);
disp('z=');
disp(x);
I would try
for i=1:100
k=num2str(i)
[a,b]=solve('100+a/2=173*cos(b)','sqrt(3)*a/2=173*sin(b)','a','b')
end
and then solve the equation
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.