I am trying to implement the following vector calculus equation in MATLAB.
Here n, u, v etc are 2D matrix of size 201 X 201 and others like mu and chi are respective functions. There are few doubts which comes to my mind now. gradient command produces both x-component and y-component. So how can I represent grad(n)? Can someone help me to realize this equation?
My attempt to code the first component alone in the equation is given below. The code is running inside a loop. I believe this nx+ny part in the code is wrong, but I saw such an attempt here in the example section "Part II: Divergence of a Vector Field".
[U,V] = meshgrid(1:201);
while t<T-dt
[nx,ny]=gradient(rho(:,:,1),dx,dy);
[ux,uy]=gradient(u(:,:,1),dx,dy);
a = divergence(U,V,mu*(nx+ny));
%b =divergence((U,V,chi*n(:,:,1)*(ux+uy));
n(:,:,2) = (dt)*(a) + n(:,:,1);
t=t+dt
u(:,:,1) = u(:,:,2);
n(:,:,1) = n(:,:,2);
rho(:,:,1) = rho(:,:,2);
end
Related
Background: I am working on a problem similar to the nonlinear logistic regression described in the link [1] (my problem is more complicated, but link [1] is enough for the next sections of this post). Comparing my results with those obtained in parallel with a R package, I got similar results for the coefficients, but (very approximately) an opposite logLikelihood.
Hypothesis: The logLikelihood given by fitnlm in Matlab is in fact the negative LogLikelihood. (Note that this impairs consequently the BIC and AIC computation by Matlab)
Reasonning: in [1], the same problem is solved through two different approaches. ML-approach/ By defining the negative LogLikelihood and making an optimization with fminsearch. GLS-approach/ By using fitnlm.
The negative LogLikelihood after the ML-approach is:380
The negative LogLikelihood after the GLS-approach is:-406
I imagine the second one should be at least multiplied by (-1)?
Questions: Did I miss something? Is the (-1) coefficient enough, or would this simple correction not be enough?
Self-contained code:
%copy-pasting code from [1]
myf = #(beta,x) beta(1)*x./(beta(2) + x);
mymodelfun = #(beta,x) 1./(1 + exp(-myf(beta,x)));
rng(300,'twister');
x = linspace(-1,1,200)';
beta = [10;2];
beta0=[3;3];
mu = mymodelfun(beta,x);
n = 50;
z = binornd(n,mu);
y = z./n;
%ML Approach
mynegloglik = #(beta) -sum(log(binopdf(z,n,mymodelfun(beta,x))));
opts = optimset('fminsearch');
opts.MaxFunEvals = Inf;
opts.MaxIter = 10000;
betaHatML = fminsearch(mynegloglik,beta0,opts)
neglogLH_MLApproach = mynegloglik(betaHatML);
%GLS Approach
wfun = #(xx) n./(xx.*(1-xx));
nlm = fitnlm(x,y,mymodelfun,beta0,'Weights',wfun)
neglogLH_GLSApproach = - nlm.LogLikelihood;
Source:
[1] https://uk.mathworks.com/help/stats/examples/nonlinear-logistic-regression.html
This answer (now) only details which code is used. Please see Tom Lane's answer below for a substantive answer.
Basically, fitnlm.m is a call to NonLinearModel.fit.
When opening NonLinearModel.m, one gets in line 1209:
model.LogLikelihood = getlogLikelihood(model);
getlogLikelihood is itself described between lines 1234-1251.
For instance:
function L = getlogLikelihood(model)
(...)
L = -(model.DFE + model.NumObservations*log(2*pi) + (...) )/2;
(...)
Please also not that this notably impacts ModelCriterion.AIC and ModelCriterion.BIC, as they are computed using model.LogLikelihood ("thinking" it is the logLikelihood).
To get the corresponding formula for BIC/AIC/..., type:
edit classreg.regr.modelutils.modelcriterion
this is Tom from MathWorks. Take another look at the formula quoted:
L = -(model.DFE + model.NumObservations*log(2*pi) + (...) )/2;
Remember the normal distribution has a factor (1/sqrt(2*pi)), so taking logs of that gives us -log(2*pi)/2. So the minus sign comes from that and it is part of the log likelihood. The property value is not the negative log likelihood.
One reason for the difference in the two log likelihood values is that the "ML approach" value is computing something based on the discrete probabilities from the binomial distribution. Those are all between 0 and 1, and they add up to 1. The "GLS approach" is computing something based on the probability density of the continuous normal distribution. In this example, the standard deviation of the residuals is about 0.0462. That leads to density values that are much higher than 1 at the peak. So the two things are not really comparable. You would need to convert the normal values to probabilities on the same discrete intervals that correspond to individual outcomes from the binomial distribution.
I am trying to implement Runge-Kutta 4 to solve a differential equation and need some insight.
The main problem that I'm having is that my error for these values is around 0.09, when it should be around 0.0001*10-4 , so there's something wrong with my implementation of rk4, but I have no idea where I'm making the error. If you could point me in the direction of where my implementation of runge-kutta is off, that would be great. (Note, we are able to compute the error because the solution is a circle, so I know that the end point should be the same as the initial condition, (1,0), and the error is the distance between the computed endpoint and (1,0). This assignment is for learning numerical methods.
I repeat: I AM NOT LOOKING FOR A SOLUTION, I am looking for someone to help point me in the direction of what's going wrong in my code, because I've been staring at this for god knows how long...
How the code works: between the function declaration and for loop is setting the initial values (again, p and q are irrelevant in this part of the problem), the for loop is iterating and solving the function numerically. I use runge kutta 4 as described on the wikipedia article.
The code I wrote is written is below and N=400 (400 steps), T=42 (terminal time of 4pi2), (x,y)=(1,0) (initial conditions), and gamma = 1 (gamma is a parameter in the equation), and (p,q) is irrelevant for the part about which I am asking. P1PC is the .m file that contains the differential equation, and is also below.
function rk(N,T,x,y,gamma,p,q)
timestep=T/N;
xy=zeros(N,4);
xy(1,:)=[x,y,p,q];
k=zeros(4,2);%k(:,1) is for x, k(:,2) is for y
for index=2:N
[k(1,1),k(1,2)]=P1PC(gamma,xy(index-1,1),xy(index-1,2));
[k(2,1),k(2,2)]=P1PC(gamma,xy(index-1,1)+0.5*k(1,1)*timestep,xy(index-1,2)+0.5*k(1,2)*timestep);
[k(3,1),k(3,2)]=P1PC(gamma,xy(index-1,1)+0.5*k(2,1)*timestep,xy(index-1,2)+0.5*k(2,2)*timestep);
[k(4,1),k(4,2)]=P1PC(gamma,xy(index-1,1)+k(3,1)*timestep,xy(index-1,2)+k(3,2)*timestep);
xy(index,1)=xy(index-1,1)+(timestep/6)*(k(1,1)+2*k(2,1)+2*k(3,1)+k(4,1));
xy(index,2)=xy(index-1,2)+(timestep/6)*(k(1,2)+2*k(2,2)+2*k(3,2)+k(4,2));
end
plot(xy(:,1),xy(:,2));
error=sqrt((1-xy(N,1))^2+(0-xy(N,2))^2)
xy(N,1)
xy(N,2)
end
Here is the matlab code for function I am solving (P1PC):
function [kx,ky]=P1PC(gamma,x,y)
r=x^2+y^2;
ky=(gamma*x)/(2*pi*r);
kx=(gamma*(-y))/(2*pi*r);
end
I see two issues. One is that the end time is only reached after taking N steps, and your code takes N-1 steps. Most importantly, your definition of error is wrong. You want to check if the radius is one and hence error=sqrt(x^2+y^2)-1
See the code below I used (a bit simplified) to test the algorithm
P1PC =#(gamma,x,y)[-gamma*y,gamma*x]/(2*pi*(x^2+y^2));
T = 42;
N = 400;
h=T/N;
time=0;
x0=1;
y0=0;
gamma=1;
xy = zeros(N+1,2);
xy(1,:) = [x0,y0];
for i=2:N+1
k1 = P1PC(gamma, xy(i-1,1),xy(i-1,2));
k2 = P1PC(gamma, xy(i-1,1)+(h/2)*k1(1), xy(i-1,2)+(h/2)*k1(2));
k3 = P1PC(gamma, xy(i-1,1)+(h/2)*k2(1), xy(i-1,2)+(h/2)*k2(2));
k4 = P1PC(gamma, xy(i-1,1)+(h)*k3(1), xy(i-1,2)+(h)*k3(2));
xy(i,:) = xy(i-1,:) + (h/6)*(k1+2*k2+2*k3+k4);
time = time + h;
end
plot(xy(:,1),xy(:,2));
disp(['time=',num2str(time)])
error=sqrt(xy(N+1,1)^2+xy(N+1,2)^2)-1;
disp(['error=',num2str(error)])
Produces the output
time=42
error=3.0267e-011
I'm trying to calculate the phase2 angle/value in the y2 equation of a signal given at a specific frequency if I know the other values. Is this possible? Example below: along with picture example:
y1=A1*cos*(2*pi*f1*t+phase1) we know A1,f1,t=1,phase1
y1=0.00720858*cos*(2*pi*6+6.33)
y2=A2*cos*(2*pi*f2*t+phase2) we know A2,f2,t=1, trying to find **phase2**
y2=.4*cos*(2*pi*6.4951+phase2)
y3=A3*cos*(2*pi*f3*t+phase3) we know A3,f3,t=1,phase3
y3=0.0135274*cos(2*pi*7+.786473)
I'm using maxima 13.04.2, octave 3.8.1.
I tried to solve the y2 equation for phase2 in maxima but it got rid of the cos function
kill(all);
A:A; phase:phase; solve(A*cos*(2*pi*t+phase)=0,phase);
the answer came back as phase=-2pi*t
Is this possible? or should I go about this another way?
Thanks
The weird result might stem from the fact that you multiply the cos function with what is supposed to be its argument (by the way, this is mathematically unsound). What you might want is to apply the cos function to the argument. To illustrate what I mean, compare:
A*cos*(2*pi*t+phase)
with:
A*cos(2*pi*t+phase)
On another hand, why not solve the equation pen-on-paper style?
y2 = A2×cos(2πf2t + φ2) ⇒
y2/A2 = cos(2πf2t + φ2) ⇒
arccos(y2/A2) = 2πf2t + φ2 ⇒
arccos(y2/A2) - 2πf2t = φ2
With the values that you provided:
A2 = 0.4, f2 = 6.4951, t = 1.
you can calculate the phase φ2 as function of your level y2 (left as exercise to you).
I’m currently a Physics student and for several weeks have been compiling data related to ‘Quantum Entanglement’. I’ve now got to a point where I have to plot my data (which should resemble a cos² graph - and does) to a sort of “best fit” cos² graph. The lab script says the following:
A more precise determination of the visibility V (this is basically how 'clean' the data is) follows from the best fit to the measured data using the function:
f(b) = A/2[1-Vsin(b-b(center)/P)]
Granted this probably doesn’t mean much out of context, but essentially A is the amplitude, b is an angle and P is the periodicity. Hence this is also a “wave” like the experimental data I have found.
From this I understand, as previously mentioned, I am making a “best fit” curve. However, I have been told that this isn’t possible with Excel and that the best approach is Matlab.
I know intermediate JavaScript but do not know Matlab and was hoping for some direction.
Is there a tutorial I can read for this? Is it possible for someone to go through it with me? I really have no idea what it entails, so any feed back would be greatly appreciated.
Thanks a lot!
Initial steps
I guess we should begin by getting a representation in Matlab of the function that you're trying to model. A direct translation of your formula looks like this:
function y = targetfunction(A,V,P,bc,b)
y = (A/2) * (1 - V * sin((b-bc) / P));
end
Getting hold of the data
My next step is going to be to generate some data to work with (you'll use your own data, naturally). So here's a function that generates some noisy data. Notice that I've supplied some values for the parameters.
function [y b] = generateData(npoints,noise)
A = 2;
V = 1;
P = 0.7;
bc = 0;
b = 2 * pi * rand(npoints,1);
y = targetfunction(A,V,P,bc,b) + noise * randn(npoints,1);
end
The function rand generates random points on the interval [0,1], and I multiplied those by 2*pi to get points randomly on the interval [0, 2*pi]. I then applied the target function at those points, and added a bit of noise (the function randn generates normally distributed random variables).
Fitting parameters
The most complicated function is the one that fits a model to your data. For this I use the function fminunc, which does unconstrained minimization. The routine looks like this:
function [A V P bc] = bestfit(y,b)
x0(1) = 1; %# A
x0(2) = 1; %# V
x0(3) = 0.5; %# P
x0(4) = 0; %# bc
f = #(x) norm(y - targetfunction(x(1),x(2),x(3),x(4),b));
x = fminunc(f,x0);
A = x(1);
V = x(2);
P = x(3);
bc = x(4);
end
Let's go through line by line. First, I define the function f that I want to minimize. This isn't too hard. To minimize a function in Matlab, it needs to take a single vector as a parameter. Therefore we have to pack our four parameters into a vector, which I do in the first four lines. I used values that are close, but not the same, as the ones that I used to generate the data.
Then I define the function I want to minimize. It takes a single argument x, which it unpacks and feeds to the targetfunction, along with the points b in our dataset. Hopefully these are close to y. We measure how far they are from y by subtracting from y and applying the function norm, which squares every component, adds them up and takes the square root (i.e. it computes the root mean square error).
Then I call fminunc with our function to be minimized, and the initial guess for the parameters. This uses an internal routine to find the closest match for each of the parameters, and returns them in the vector x.
Finally, I unpack the parameters from the vector x.
Putting it all together
We now have all the components we need, so we just want one final function to tie them together. Here it is:
function master
%# Generate some data (you should read in your own data here)
[f b] = generateData(1000,1);
%# Find the best fitting parameters
[A V P bc] = bestfit(f,b);
%# Print them to the screen
fprintf('A = %f\n',A)
fprintf('V = %f\n',V)
fprintf('P = %f\n',P)
fprintf('bc = %f\n',bc)
%# Make plots of the data and the function we have fitted
plot(b,f,'.');
hold on
plot(sort(b),targetfunction(A,V,P,bc,sort(b)),'r','LineWidth',2)
end
If I run this function, I see this being printed to the screen:
>> master
Local minimum found.
Optimization completed because the size of the gradient is less than
the default value of the function tolerance.
A = 1.991727
V = 0.979819
P = 0.695265
bc = 0.067431
And the following plot appears:
That fit looks good enough to me. Let me know if you have any questions about anything I've done here.
I am a bit surprised as you mention f(a) and your function does not contain an a, but in general, suppose you want to plot f(x) = cos(x)^2
First determine for which values of x you want to make a plot, for example
xmin = 0;
stepsize = 1/100;
xmax = 6.5;
x = xmin:stepsize:xmax;
y = cos(x).^2;
plot(x,y)
However, note that this approach works just as well in excel, you just have to do some work to get your x values and function in the right cells.
I am asked to write an fft mix radix in matlab, but before that I want to let to do a discrete Fourier transform in a straight forward way. So I decide to write the code according to the formula defined as defined in wikipedia.
[Sorry I'm not allowed to post images yet]
http://en.wikipedia.org/wiki/Discrete_Fourier_transform
So I wrote my code as follows:
%Brutal Force Descrete Fourier Trnasform
function [] = dft(X)
%Get the size of A
NN=size(X);
N=NN(2);
%====================
%Declaring an array to store the output variable
Y = zeros (1, N)
%=========================================
for k = 0 : (N-1)
st = 0; %the dummy in the summation is zero before we add
for n = 0 : (N-1)
t = X(n+1)*exp(-1i*2*pi*k*n/N);
st = st + t;
end
Y(k+1) = st;
end
Y
%=============================================
However, my code seems to be outputting a result different from the ones from this website:
http://www.random-science-tools.com/maths/FFT.htm
Can you please help me detect where exactly is the problem?
Thank you!
============
Never mind it seems that my code is correct....
By default the calculator in the web link applies a window function to the data before doing the FFT. Could that be the reason for the difference? You can turn windowing off from the drop down menu.
BTW there is an FFT function in Matlab