I am working on something similar to the following example:
I want to compute <x(t)> that is the average of a function x(t) over number of simulations. To do this, I generate the following code:
sim=50;% number of simulations
t=linspace(0,1);% time interval
a_range=[1,2,3];% different values for the parameter a
b_range=[0,0.5,1];% different values for the parameter b
z=zeros(1,sim);
theta=zeros(1,sim);
for nplot=1:3
a=a_range(nplot);
b=b_range(nplot);
average_x=zeros(nplot,sim);
for i=1:sim
z(i)=rand(1);% random number for every simulation
theta(i)=pi*rand(1);% random number for every simulation
x=z(i)*t.^2+a*sin(theta(i))+b.*tan(theta(i));% the function
end
average_x(nplot,sim)=mean(x);% average over the number of simulations
end
fname=['xsin.mat'];
save(fname)
The time is a vector 1 by 100 and x is a vector 1 by 100, and average_x is 1 by 50. What I am looking for is to write a script to load the file and plot the average against time for different parameters a and b. So I want to write a code to generate three figures such that in figure 1 I will plot the average
plot(t,average_x)
for a=1 and b=0.
Then in figure 2 I will plot the average again but for a=2 and b=0.5 and so on. The problem is the dimension of time t and the average are not the same. How can I fix this problem and generate three distinct figures.
If I got your intention correctly, this is what you look for:
sim = 50;% number of simulations
t = linspace(0,1);% time interval
a_range = [1,2,3];% different values for the parameter a
b_range = [0,0.5,1];% different values for the parameter b
% NO NEED TO GENERATE THE RANDOM NUMBERS ONE BY ONE:
theta = pi*rand(sim,1);% random number for every simulation
z = rand(sim,1); % random number for every simulation
% YOU SOULD INITIALIZE ALL YOUR VARIABLES OUTSIDE THE LOOPS:
x = zeros(sim,numel(t));
average_x = zeros(3,numel(t));% the mean accross simulations
% for average accros time use:
% average_x = zeros(3,sim);
for nplot=1:3
a = a_range(nplot);
b = b_range(nplot);
for i=1:sim
x(i,:) = z(i)*t.^2+a*sin(theta(i))+b.*tan(theta(i));% the function
end
average_x(nplot,:) = mean(x); % average over the number of simulations
% average_x(nplot,:) = mean(x,2); % average accross time
end
% save the relevant variables:
save('results.mat','average_x','t')
In another file you can write:
load('results.mat')
for k = 1:size(average_x,1)
figure(k)
plot(t,average_x(k,:))
title(['Parameter set ' num2str(k)])
xlabel('Time')
ylabel('mean x')
end
This is the plot in one figure (if you want then average over simulations):
BTW, if you want to make your code more compact and fast, you can vectorize it, mainly using bsxfun. Here is a demonstration with your code:
% assuming all parameters are defined as above:
zt = bsxfun(#times,z,t.^2); % first part of the function 'z(i)*t.^2'
% second part of the function 'a*sin(theta(i)) + b.*tan(theta(i))':
ab = bsxfun(#times,a_range,sin(theta)) + bsxfun(#times,b_range,tan(theta));
% convert the second part to the right dimensions and size:
ab = repmat(reshape(ab,[],1,3),1,numel(t),1);
x = bsxfun(#plus,zt,ab); % the function
average_x = squeeze(mean(x)); % take the mean by simulation
plot(t,average_x) % plot it all at once, as in the figure above
xlabel('Time')
ylabel('mean x')
Related
I need to plot population growth model with different values of b
where b>d
and b=d
using for loops. Both results should be visible on the same graph with different colors.
Here is my function and intial value, but I am not getting how to get the plot .
[T,Y]=ode45(H,[0:1:time],[N0]);
Intitial value
b= 0.1 0.001
d=0.001
N0=400````
I need two line for each b on the same plot.
```***
Intitial value
b= 0.1 0.001;
d=0.001;
N0=400;
H=#(t,N)[b*N-d*N];
[T,Y]=ode45(H,[0:1:time],[N0]);
plot(T,Y)
***```
First, you need to put the code in a proper format, now you copied the initial value block twice (I guess you had some issue putting the code format. I hope you can focus on that when asking new questions.
The current code gives an error on the definition of b as you did not define it as a vector. To have two lines, it is best to store the output Y as a matrix of two columns (each column being one vector). MATLAB then outputs each column as a line in the plot.
The following code solves your issue:
% Initial value
b = [0.1, 0.001];
d = 0.001;
N0= 400;
simTime = 0:1:300;
% Preallocate output for the loop
Y = zeros(length(simTime), length(b));
% Run for loop
for i = 1:length(b)
b_i = b(i);
H=#(t,N)[b_i*N-d*N];
[T,y]=ode45(H, simTime, [N0]);
Y(:,i) = y;
end
% Plot output
plot(T,Y)
I have data (y) measured in over 4 time points (t), for three concentrations (c).
So data will be like:
Under c1: y11,y12,y13,y14 (measured at the 4 time points)
Under c2:y21,y12,y23,y24
under c3: y31,y32,y33,y34
What I am trying to do is to estimate two parameters c and d by fitting simultaneously to all these data measures at diffferent concnetrations.
However, some of these values are NaNs. So, for example,
Under c2:y21,y12,NaN,NaN
under c3: y31,y32,y33,NaN
here is the Matlab code that I have written.
%C contains the different concentration values (c1,c2,c3)
[fittedVals,errorVals]=lsqcurvefit(#(xEstimate,thours)model(xEstimate,t,C),initial,t,y,lb,ub);
function output= model(xEstimate,t,C)
intVals=repmat(10^5,3,1);%initial value of the ODE system
[~,values] = ode45(#(t,y)Equations(t,y,C),t,intVals);
function s=Equations(~,y,para)
a=0.25;
b=-0.1;
k=xEstimate(1);
d=xEstimate(2);
concentration=para;%different concentrations
s=zeros(3,1);
s(1)=a*y(1)-y(1)*(((a-b)*(concentration(1)/k).^d)/((concentration(1)/k).^d-(b/(a))));
s(2)=a*y(2)-y(2)*(((a-b)*(concentration(2)/k).^d)/((concentration(2)/k).^d-(b/(a))));
s(3)=a*y(3)-y(3)*(((a-b)*(concentration(3)/k).^d)/((concentration(3)/k).^d-(b/(a))));
end
output=values;
end
This code works when data is not NaN but, with missing data, it gives an error as:
Objective function is returning undefined values at initial point.
lsqcurvefit cannot continue.
What can I do here to solve this problem? Should I input time and y data as cell arrays?
If so I don't quite understand how to change the code to work with cell arrays.
Any help is appreciated.
What you can do, is use lsqnonlin instead of lsqcurvefit. This allows you to have more flexibility in the error vector you want to minimize.
You can determine the error for each measurement per concentration, and then combine these to a large error vector which you want to minimize. A simple example is e.g. a model of a sine, with varying amplitude, frequency and phase. Say we know the phase, and want to find the amplitude and frequency.
The model is:
function y = model(t, A, w, phi)
y = A.*sin(w.*t+phi);
end
The error function for the fitting process takes the measured data, and known parameters. Determine the y_estimated for a certain parameter set (given by lsqnonlin), and determine the error with the measured values y_meas. Do this for all the different concentrations, and combine in one error vector. Since some values in y_meas are NaN, and you want to omit them, remove them from the error vector.
function err = errorFun(params, y_meas, t, phi)
% get w and phi from params
A = params(1:3);
w = params(4:6);
% simulate model with params to estimate
yest = model(t, A, w, phi);
% determine error vector
err = y_meas-yest;
err = err(:); % make one vector
err(isnan(err)) = []; % remove NaNs
end
Example:
t = 0:0.5:4*pi;
A = rand(3,1);
w = rand(3,1);
phi = rand(3,1);
y_true = A.*sin(w.*t+phi); % three sinusoids
% measured data
y_meas = y_true;
y_meas(randi([1 numel(y_meas)], 10,1)) = NaN; % set some values to NaN
% optimize
% p = [A;w];
p0 = [A;w;]+0.1; % small deviation from initial parameters, for the example
[p_estimated,a] = lsqnonlin(#(p) errorFun(p,y_meas,t,phi), p0);
A_est = p_estimated(1:3);
w_est = p_estimated(4:6);
disp([A A_est w w_est])
I want to determine how well the estimated model fits to the future new data. To do this, prediction error plot is often used. Basically, I want to compare the measured output and the model output. I am using the Least Mean Square algorithm as the equalization technique. Can somebody please help what is the proper way to plot the comparison between the model and the measured data? If the estimates are close to true, then the curves should be very close to each other. Below is the code. u is the input to the equalizer, x is the noisy received signal, y is the output of the equalizer, w is the equalizer weights. Should the graph be plotted using x and y*w? But x is noisy. I am confused since the measured output x is noisy and the model output y*w is noise-free.
%% Channel and noise level
h = [0.9 0.3 -0.1]; % Channel
SNRr = 10; % Noise Level
%% Input/Output data
N = 1000; % Number of samples
Bits = 2; % Number of bits for modulation (2-bit for Binary modulation)
data = randi([0 1],1,N); % Random signal
d = real(pskmod(data,Bits)); % BPSK Modulated signal (desired/output)
r = filter(h,1,d); % Signal after passing through channel
x = awgn(r, SNRr); % Noisy Signal after channel (given/input)
%% LMS parameters
epoch = 10; % Number of epochs (training repetation)
eta = 1e-3; % Learning rate / step size
order=10; % Order of the equalizer
U = zeros(1,order); % Input frame
W = zeros(1,order); % Initial Weigths
%% Algorithm
for k = 1 : epoch
for n = 1 : N
U(1,2:end) = U(1,1:end-1); % Sliding window
U(1,1) = x(n); % Present Input
y = (W)*U'; % Calculating output of LMS
e = d(n) - y; % Instantaneous error
W = W + eta * e * U ; % Weight update rule of LMS
J(k,n) = e * e'; % Instantaneous square error
end
end
Lets start step by step:
First of all when using some fitting method it is a good practice to use RMS error . To get this we have to find error between input and output. As I understood x is an input for our model and y is an output. Furthermore you already calculated error between them. But you used it in loop without saving. Lets modify your code:
%% Algorithm
for k = 1 : epoch
for n = 1 : N
U(1,2:end) = U(1,1:end-1); % Sliding window
U(1,1) = x(n); % Present Input
y(n) = (W)*U'; % Calculating output of LMS
e(n) = x(n) - y(n); % Instantaneous error
W = W + eta * e(n) * U ; % Weight update rule of LMS
J(k,n) = e(n) * (e(n))'; % Instantaneous square error
end
end
Now e consists of errors at the last epoch. So we can use something like this:
rms(e)
Also I'd like to compare results using mean error and standard deviation:
mean(e)
std(e)
And some visualization:
histogram(e)
Second moment: we can't use compare function just for vectors! You can use it for dynamic system models. For it you have to made some workaround about using this method as dynamic model. But we can use some functions as goodnessOfFit for example. If you want something like error at each step that consider all previous points of data then make some math workaround - calculate it at each point using [1:currentNumber].
About using LMS method. There are built-in function calculating LMS. Lets try to use it for your data sets:
alg = lms(0.001);
eqobj = lineareq(10,alg);
y1 = equalize(eqobj,x);
And lets see at the result:
plot(x)
hold on
plot(y1)
There are a lot of examples of such implementation of this function: look here for example.
I hope this was helpful for you!
Comparison of the model output vs observed data is known as residual.
The difference between the observed value of the dependent variable
(y) and the predicted value (ŷ) is called the residual (e). Each data
point has one residual.
Residual = Observed value - Predicted value
e = y - ŷ
Both the sum and the mean of the residuals are equal to zero. That is,
Σ e = 0 and e = 0.
A residual plot is a graph that shows the residuals on the vertical
axis and the independent variable on the horizontal axis. If the
points in a residual plot are randomly dispersed around the horizontal
axis, a linear regression model is appropriate for the data;
otherwise, a non-linear model is more appropriate.
Here is an example of residual plots from a model of mine. On the vertical axis is the difference between the output of the model and the measured value. On the horizontal axis is one of the independent variables used in the model.
We can see that most of the residuals are within 0.2 units which happens to be my tolerance for this model. I can therefore make a conclusion as to the worth of the model.
See here for a similar question.
Regarding you question about the lack of noise in your models output. We are creating a linear model. There's the clue.
Maybe this is a silly question but here we go:
I have two input matrices of 5X6 in a two for loop where I have a simulation in simulink that has to be run for each combination in order to get two resulting matrices but with the size of 6x6 having issues at then end to get my contour plots since the size are different. I have tried with size(max()), length, numel and the results are different from each, but always the size are different. I am not sure what am I doing wrong. Any help would be appreciated.
The code looks like this so far (battery_bankmatrix_test1 and power_peak_PVmatrix_1test are my input matrices of 5x6 and results_waterproduction and results_energyconsumption are the resulting matrices of 6x6)
for i_Batterycapacity = 1:length(battery_bankmatrix_test1)
for i_PVarray = 1:length(power_peak_PVmatrix_1test)
parameter.battery.cap = battery_bankmatrix_test1(i_Batterycapacity);
parameter.pv.power = power_peak_PVmatrix_1test(i_PVarray); %Watt peak, used to run the simulation
% Calculate solar radiation on surface and run Simulink simulation
% load PV data
%load PV data
% load('PV Data/PV U-V Map SolarWorld 150Wp Poly - 4 Parameter Model based on Carrero et al 2010.mat');
PVmodule_data = 'PV U-V Map SolarWorld 150Wp Poly - 4 Parameter Model based on Carrero et al 2010.mat';
load([cd '\PV Data\' PVmodule_data]);
% Calculate solar radiation on surface and run Simulink simulation
run('Revived_SIM_Manual.p');
sim('B_Simulink_Sim_Revived_V2_July2017');
% % saveas(ho,sprintf('FIG%d.png')); % will create FIG1, FIG2,...
%
results_waterproduction(i_PVarray,i_Batterycapacity) = water_production(8760)
results_energyconsumption(i_PVarray,i_Batterycapacity) = consumption(8760)
end
end
It's normal that the results aren't the same because numel return the number of element 5x6 = 30, the function length returns the maximum of lines or columns, here it returns 6 (because your matrix is 5x6, but if it was 6x11, length will return 11) and the last one is size(max()) it returns 1 because the maximum is only one element but if you try max(size()) instead it will return 6.
i have variable x that undergoes a random walk according to the following rules:
x(t+1)=x(t)-1; probability p=0.3
x(t+1)=x(t)-2; probability q=0.2
x(t+1)=x(t)+1; probability p=0.5
a) i have to create this variable initialized at zero and write a for loop for 100 steps and that runs 10000 times storing each final value in xfinal
b) i have to plot a probability distribution of xfinal (a histogram) choosing a bin size and normalization!!* i have to report the mean and variance of xfinal
c) i have to recreate the distribution by application of the central limit theorem and plot the probability distribution on the same plot!
help would be appreciated in telling me how to choose the bin size and normalize the histogram and how to attempt part c)
your help is much appreciated!!
p=0.3;
q=0.2;
s=0.5;
numberOfSteps = 100;
maxCount = 10000;
for count=1:maxCount
x=0;
for i = 1:numberOfSteps
random = rand(1, 1);
if random <=p
x=x-1;
elseif random<=(p+q)
x=x-2;
else
x=x+1;
end
end
xfinal(count) = x;
end
[f,x]=hist(xfinal,30);
figure(1)
bar(x,f/sum(f));
xlabel('xfinal')
ylabel('frequency')
mean = mean(xfinal)
variance = var(xfinal)
For the first question, check the help for hist on mathworks homepage
[nelements,centers] = hist(data,nbins);
You do not select the bin size, but the number of bins. nelements gives the elements per bin and center is all the bin centers. So to say, it would be the same to call
hist(data,nbins);
as
[nelements,centers] = hist(data,nbins);
plot(centers,nelements);
except that the representation is different (line or pile). To normalize, simply divide nelements with sum(nelements)
For c, here i.i.d. variables it actually is a difference if the variables are real or complex. However for real variables the central limit theorem in short tells you that for a large number of samples the distribution will limit the normal distribution. So if the samples are real, you simply asssumes a normal distribution, calculates the mean and variance and plots this as a normal distribution. If the variables are complex, then each of the variables will be normally distributed which means that you will have a rayleigh distribution instead.
Mathworks is deprecating hist that is being replaced with histogram.
more details in this link
You are not applying the PDF function as expected, the expression Y doesn't work
For instance Y does not have the right X-axis start stop points. And you are using x as input to Y while x already used as pivot inside the double for loop.
When I ran your code Y generates a single value, it is not a vector but just a scalar.
This
bar(x,f/sum(f));
bringing down all input values with sum(f) division? no need.
On attempting to overlap the ideal probability density function, often one has to do additional scaling, to have both real and ideal visually overlapped.
MATLAB can do the scaling for us, and no need to modify input data /sum(f).
With a dual plot using yyaxis
You also mixed variance and standard deviation.
Instead try something like this
y2=1 / sqrt(2*pi*var1)*exp(-(x2-m1).^2 / (2*var1))
ok, the following solves your question(s)
codehere
clear all;
close all;
clc
p=0.3; % thresholds
q=0.2;
s=0.5;
n_step=100;
max_cnt=10000;
n_bin=30; % histogram amount bins
xf=zeros(1,max_cnt);
for cnt=1:max_cnt % runs loop
x=0;
for i = 1:n_step % steps loop
t_rand1 = rand(1, 1);
if t_rand1 <=p
x=x-1;
elseif t_rand1<=(p+q)
x=x-2;
else
x=x+1;
end
end
xf(cnt) = x;
end
% [f,x]=hist(xf,n_bin);
hf1=figure(1)
ax1=gca
yyaxis left
hp1=histogram(xf,n_bin);
% bar(x,f/sum(f));
grid on
xlabel('xf')
ylabel('frequency')
m1 = mean(xf)
var1 = var(xf)
s1=var1^.5 % sigma
%applying central limit theorem %finding the mean
n_x2=1e3 % just enough points
min_x2=min(hp1.BinEdges)
max_x2=max(hp1.BinEdges)
% quite same as
min_x2=hp1.BinLimits(1)
max_x2=hp1.BinLimits(2)
x2=linspace(min_x2,max_x2,n_x2)
y2=1/sqrt(2*pi*var1)*exp(-(x2-m1).^2/(2*var1));
% hold(ax1,'on')
yyaxis right
plot(ax1,x2,y2,'r','LineWidth',2)
.
.
.
note I have not used these lines
% Xp=-1; Xq=-2; Xs=1; mu=Xp.*p+Xq.*q+Xs.*s;
% muN=n_step.*mu;
%
% sigma=(Xp).^2.*p+(Xq).^2.*q+(Xs).^2.s; % variance
% sigmaN=n_step.(sigma-(mu).^2);
People ususally call sigma to variance^.5
This supplied script is a good start point to now take it to wherever you need it to go.