Solve function for real part = 0 instead of imaginary in MATLAB - matlab

I have a function which outputs a vector of complex eigenvalues. It takes a single argument, rho. I need to find a rho for which the complex eigenvalues lie on the imaginary axis. In other words, the real parts have to be 0.
When I run fzero() it throws the following error
Operands to the || and && operators must be convertible to logical scalar values.
Whereas fsolve() simply solves for the imaginary part = 0, which is exactly the oposite of what I want.
This is the function I wrote
function lambda = eigLorenz(rho)
beta = 8/3;
sigma = 10;
eta = sqrt(beta*(rho-1));
A = [ -beta 0 eta;0 -sigma sigma;-eta rho -1];
y = [rho-1; eta; eta];
% Calculate eigenvalues of jacobian
J = A + [0 y(3) 0; 0 0 0; 0 -y(1) 0]
lambda = eig(J)
It outputs 3 eigenvalues, 2 complex conjugates and 1 real eigenvalue (with complex part = 0).
I need to find rho for which the complex eigenvalues lie on the imaginary axis so that the real parts are 0.

Two problems:
fzero is only suited for scalar-valued functions (f: ℝ → ℝ)
complex numbers are single numbers, treated as signle entities by almost all functions. You'll have to force MATLAB to split up the complex number into its imaginary and real parts
So, one possible workaround is to take the real part of the first complex eigenvalue:
function [output, lambda] = eigLorenz(rho)
% Constants
beta = 8/3;
sigma = 10;
eta = sqrt(beta*(rho-1));
A = [-beta 0 eta
0 -sigma sigma
-eta rho -1];
y = [rho-1
eta
eta];
% Calculate eigenvalues of jacobian
J = A + [0 y(3) 0
0 0 0
0 -y(1) 0];
lambda = eig(J);
% Make it all work for all rho with FZERO(). Check whether:
% - the complex eigenvalues are indeed each other's conjugates
% - there are exactly 2 eigenvalues with nonzero imaginary part
complex = lambda(imag(lambda) ~= 0);
if numel(complex) == 2 && ...
( abs(complex(1) - conj(complex(2))) < sqrt(eps) )
output = real(complex(1));
else
% Help FZERO() get out of this hopeless valley
output = -norm(lambda);
end
end
Call like this:
rho = fzero(#eigLorenz, 0);
[~, lambda] = eigLorenz(rho);

Related

Matlab linear correlation matrix in copularnd (copula random number) function

Consider we have 4 vectors, V1,V2,nf1 and nf2. We need to generate n=8736 random numbers that each pair of (V1,V2) , (V1,nf1), (V2,nf2) and (nf1,nf2) to be correlate as follow:
Rvv=0.6 for (V1,V2)
Rvn=0.5 for (V1,nf1) and (V2,nf2)
Rnn=0 for (nf1,nf2)
(It's not important what correlation of (V1,nf2) and (V2, nf1) is). Now we use copula to generate correlated random numbers in MATLAB:
Rvv=0.6;
Rvn=0.5;
Rnn=0;
n = 8736;
%V1 V2 nf1 nf2
Rho = [1 Rvv Rvn 0 ; %V1
Rvv 1 0 Rvn; %V2
Rvn 0 1 Rnn; %nf1
0 Rvn Rnn 1 ]; %nf2
Random_no = copularnd('Gaussian',Rho,n);
It's all OK when Rvv is 0.6, and Random_no will be a 8736 by 4 matrix, that each pair of columns are correlated as we specified by Rho Matrix. BUT when Rvv=0.9, MATLAB returns error as follow:
Error using mvnrnd
SIGMA must be a symmetric positive semi-definite matrix.
Error in copularnd
u = normcdf(mvnrnd(zeros(1,d),Rho,n));
I can't understand what the problem is and how can I really generate correlated random numbers using copula. I'll really appreciate if anyone can help me through this problem.
I can't answer about theory, but got this in code of copularnd:
case 'gaussian'
Rho = varargin{1};
n = varargin{2};
d = size(Rho,1);
if isscalar(Rho)
if ~(-1 < Rho && Rho < 1)
error(message('stats:copularnd:BadScalarCorrelation'));
end
Rho = [1 Rho; Rho 1];
d = 2;
elseif any(diag(Rho) ~= 1)
error(message('stats:copularnd:BadCorrelationMatrix'));
end
% MVNRND will check that Rho is square, symmetric, and positive semi-definite.
u = normcdf(mvnrnd(zeros(1,d),Rho,n));
Because of there no any information about it in help, I think it must be clearly for people who knows what copula is :) but is not for me
There are a lot of ways to generate positive semi-definite matrices: http://www.mathworks.com/matlabcentral/newsreader/view_thread/163489

Matlab: converting symbolic to function handle, values returned not double

I have some obscurely long symbolic expression of 3 variables (g_eq), which i would like to minimize with some constraints. I am trying to do so by converting it to a function handle and using fmicon:
cfun = matlabFunction(g_eq,'vars',[kappa;theta;sigma]);
A = [-1 0 0; 0 -1 0; 0 0 -1];
b = [0; 0; 0];
[x,fval] = fmincon(#(kappa, theta, sigma) cfun, x0, A, b)
Which Matlab doesn't like:
FMINCON requires all values returned by user functions to be of
data type double.
I would suspect, that the problem is with cfun, as it is full of numbers with symbolic precision, can I somehow convert it, so that they're double? Or better (computation time wise) while creating my objective function (cfun) (complicated process of some transformation of data and a parametric model), can I use symbols or some other "proxy for the variables" with double for the numeric part of the expressions?
Thanks,
J.
Edit - MCVE:
My aim is to find parameters of a model by minimizing a difference between the model implied and data implied laplace transforms over some weighted regions. Here I provide the problem over one small region without use of weights over the regions and some further simplifications. In part 0, I provide the code for functions of the transformation, in part II I make the parametric transformation, while in III the data transformation and attempt to minimize it in IV.
%% 0. Functions used
%% 0.1 L_V1 - transform of parametric
function lv = L_V1(u,sigma,kappa,theta)
lv = (1/(1+u.*sigma^2/(2*kappa))).^(2*kappa*theta/sigma^2);
end
%% 0.2 LV_2 - transform of data
function lv = L_hat1(u,D,n,T)
A_u = cos(sqrt(2 .*u) *sqrt(n) .*D);
Z_u = 1/n * sum(A_u);
lv = 1/T * sum(Z_u);
end
%% I. Pre-estimation
ulng1=100; %select number of points on the evaluated interval
u1 = linspace(.8, 1.6,ulng1); % create region of interest
%% II. Parametric part
par_mat1 = sym(zeros(ulng1,1)); % create interval for parametric
syms sigma kappa theta LV_par1;
for i = 1:ulng1
par_mat1(i) = L_V1(u1(i),sigma,kappa,theta); %transformations of parametric
end
LV_par1 = sum(par_mat1); %sum of parametric over the region
%% III. Data part
n = 100; %choose number of days
T = 20; %choose number of obs over a day
D = rand([n-1, T]); %vector of observations, here just random numbers
for i = 1:ulng1
hat_mat1(i) = L_hat1(u1(i),D,n,T); %transformations of data
end
hat_1 = sum(hat_mat1); %sum of transforms over the region
%% IV. Minimize
W = 1; %weighting matrix, here just one region, hence 1
MC = hat_1 - LV_par1 ; %moment condition
g_eq = (MC) * (W) *(MC.'); %objective function (symbolic)
cfun = matlabFunction(g_eq,'vars',[kappa;theta;sigma]); %create a function handle from the symbolic
x0 = [.5; 1; .5];
A = [-1 0 0; 0 -1 0; 0 0 -1]; %constrains
b = [0; 0; 0]; %constrains
[x,fval] = fmincon(#(kappa, theta, sigma) cfun, x0, A, b) %minimize
The optimization parameters are always passed as vector.
[x,fval] = fmincon(#(x) cfun(x(1),x(2),x(3)), x0, A, b)

the entries of vector x is not sequential in Chebyshev polynomial in matlab

here is the question:
The degree-n Chebyshev polynomial is defined by Tn(x) = cos[n*arcos(x)] x is between -1 to 1
these polynomials satisfy T0(x)=1, T1(x)=x, and the recursion relation T(n+1)(x) = 2*x*Tn(x)-T(n-1)(x), n is larger and equal to 1.
Write a function that evaluates all the Chebyshev polynomials of degree less than or equal to N at all the points in the vector x.
here is what I did:
c = length(x);
x = x';
T = ones(c,N);
T(:,1) = 1;
T(:,2) = x;
for n = 2:N
T(:,n+1) = 2*x.*T(:,n)-T(:,n-1);
end
I run into problem with entries of x are not sequential between -1 to 1. like x = [-1 0.5 0.2 0.3 1]. The graph of that is weird. I am not sure if I did this right.
Try this as your first line of code:
x = sort(x);
That will put the elements of x in ascending order for you.

How to solve a system of equations involving a tridiagonal matrix? MATLAB

I'm not sure if this typical behaviour or not but I am solving a finite-difference problem using the backward differencing method.
I populated a sparse matrix with the appropriate diagonal terms (along the central diagonal and one above and below it) and I attempted to solve the problem using MATLAB's built-in method (B=A\x) and it seems MATLAB just gets it wrong.
Furthermore, if use inv() and use the inverse of the tridiagonal matrix I get the correct solution.
Why does this behave like this?
Additional info:
http://pastebin.com/AbuEW6CR (Values are tabbed so its easier read)
Stiffness matrix K:
1 0 0 0
-0.009 1.018 -0.009 0
0 -0.009 1.018 -0.009
0 0 0 1
Values for d:
0
15.55
15.55
86.73
Built-in output:
-1.78595556155136e-05
0.00196073713853244
0.00196073713853244
0.0108149483252210
Output using inv(K):
0
15.42
16.19
86.73
Manual output:
0
15.28
16.18
85.16
Code
nx = 21; %number of spatial steps
nt = 501; %number of time steps (varies between 501 and 4001)
p = alpha * dt / dx^2; %arbitrary constant
a = [0 -p*ones(1,nx-2) 0]'; %diagonal below central diagonal
b = (1+2*p)*ones(nx,1); %central diagonal
c = [1 -p*ones(1,nx-2) 1]'; %diagonal above central diagonal
d = zeros(nx, 1); %rhs values
% Variables a,b,c,d are used for the manual tridiagonal method for
% comparison with MATLAB's built-in functions. The variables represent
% diagonals and the rhs of the matrix
% The equation is K*U(n+1)=U(N)
U = zeros(nx,nt);
% Setting initial conditions
U(:,[1 2]) = (60-32)*5/9;
K = sparse(nx,nx);
% Indices of the sparse matrix which correspond to the diagonal
diagonal = 1:nx+1:nx*nx;
% Populating diagonals
K(diagonal) =1+2*p;
K(diagonal(2:end)-1) =-p;
K(diagonal(1:end-1)+1) =-p;
% Applying dirichlet condition at final spatial step, the temperature is
% derived from a table for predefined values during the calculation
K(end,end-1:end)=[0 1];
% Applying boundary conditions at first spatial step
K(1,1:2) = [1 0];
% Populating rhs values and applying boundary conditions, d=U(n)
d(ivec) = U(ivec,n);
d(nx) = R; %From table
d(1) = 0;
U(:,n+1) = tdm(a,b,c,d); % Manual solver, gives correct answer
U(:,n+1) = d\K; % Built-in solver, gives wrong answer
The following line:
U(:,n+1) = d\K;
should have been
U(:,n+1) = K\d;
By mistake I had them the wrong way round and didn't notice it, it obviously changes the mathematical expression and hence the wrong answers.

Matlab: how to write a vector of a few points as a continuous function?

I have two vectors:
x = [0; 1; 2]
y = [2.0000; 0; -14.7781]
If I will plot x and y I will see three points on the xy-plane. But I want to connect those three points and get them as a continuous function:
y = f(x),
y(0) = 2;
y(1) = 0;
y(2) = -14.7781;
y(0.5) = value between 2 and 0.
For example y can be treated as a ZOH (zero order held) continuous signal.
I saw that MATLAB has a function called d2c, which converts a model from discrete to continuous time. But have no idea how to link it with the vector I have already. How to do
this with MATLAB?
OK, your latest edit improves the situation a lot.
However, you still do not demarcate the problem sufficiently.
ZOH would be as simple as
>> x = [0; 1; 2];
>> y = [2.0000; 0; -14.7781];
>> f = #(new_x) y(find(x <= new_x, 1, 'last'));
>> f(0.5)
ans =
2
However, this is not what I think you mean, as the y(0.5) = value between 2 and 0 part of your question indicates.
Perhaps you want a linearly interpolated value:
>> f = #(new_x) interp1(x,y, new_x);
>> f(0.5)
ans =
1
Or a cubic splines interpolation:
>> f = #(new_x) interp1(x,y, new_x, 'spline');
>> f(0.5)
ans =
2.5973
What I'm asking is: what model best describes your signal when the sample time would decrease to infinitesmal values?
An nth degree polynomial can have at most n-1 turning points. Thus, we can do a polynomial regression:
% Input data
yy = [2.0000; 0; -14.7781];
% Parameters
n = length(yy)-1;
x = (0:1:n).';
% Regression
p = polyfit(x,yy,n);
% Plot
f = polyval(p,x);
figure
plot(x,yy,'o',x,f,'-')