Related
This question already has answers here:
MATLAB - Fit exponential curve WITHOUT toolbox
(2 answers)
Closed 7 years ago.
I have such x vectors and y vectors described in below :
x = [0 5 8 15 18 25 30 38 42 45 50];
y = [81.94 75.94 70.06 60.94 57.00 50.83 46.83 42.83 40.94 39.00 38.06];
with these values how can i find an coefficients of y = a*(b^x) ??
I've tried this code but it finds for y = a*e^(b*x)
clear, clc, close all, format compact, format long
% enter data
x = [0 5 8 15 18 25 30 38];
y = [81.94 75.94 70.06 60.94 57.00 50.83 46.83 42.83];
n = length(x);
y2 = log(y);
j = sum(x);
k = sum(y2);
l = sum(x.^2);
m = sum(y2.^2);
r2 = sum(x .* y2);
b = (n * r2 - k * j) / (n * l - j^2)
a = exp((k-b*j)/n)
y = a * exp(b * 35)
result_68 = log(68/a)/b
I know interpolation techniques but i couldn't implement it to my solutions...
Many thanks in advance!
Since y = a * b ^ x is the same as log(y) = log(a) + x log(b) you can do
>> y = y(:);
>> x = x(:);
>> logy = log(y);
>> beta = regress(logy, [ones(size(x)), x]);
>> loga = beta(1);
>> logb = beta(2);
>> a = exp(loga);
>> b = exp(logb);
so the values of a and b are
>> a, b
a =
78.8627588780382
b =
0.984328823937827
Plotting the fit
>> plot(x, y, '.', x, a * b .^ x, '-')
gives you this -
NB the regress function is from the statistics toolbox, but you can define a very simple version which does what you need
function beta = regress(y, x)
beta = (x' * x) \ (x' * y);
end
As an extension to the answer given by Chris Taylor, which provides the best linear fit in the logarithmic-transformed domain, you can find a better fit in the original domain by solving directly the non-linear problem with, for example, the Gauss-Newton algorithm
Using for example the solution given by Chris as a starting point:
x = [0 5 8 15 18 25 30 38 42 45 50];
y = [81.94 75.94 70.06 60.94 57.00 50.83 46.83 42.83 40.94 39.00 38.06];
regress = #(y, x) (x' * x) \ (x' * y);
y = y(:);
x = x(:);
logy = log(y);
beta = regress(logy, [ones(size(x)), x]);
loga = beta(1);
logb = beta(2);
a = exp(loga)
b = exp(logb)
error = sum((a*b.^x - y).^2)
Which gives:
>> a, b, error
a =
78.862758878038164
b =
0.984328823937827
error =
42.275290442577422
You can iterate a bit further to find a better solution
beta = [a; b];
iter = 20
for k = 1:iter
fi = beta(1)*beta(2).^x;
ri = y - fi;
J = [ beta(2).^x, beta(1)*beta(2).^(x-1).*x ]';
JJ = J * J';
Jr = J * ri;
delta = JJ \ Jr;
beta = beta + delta;
end
a = beta(1)
b = beta(2)
error = sum((a*b.^x - y).^2)
Giving:
>> a, b, error
a =
80.332725222265623
b =
0.983480686478288
error =
35.978195088265906
One more option is to use MATLAB's Curve Fitting Toolbox which lets you generate the fit interactively, and can also emit the MATLAB code needed to run the fit.
I'm trying to solve the following question :
maximize x^2-5x+y^2-3y
x+y <= 8
x<=2
x,y>= 0
By using Frank Wolf algorithm ( according to http://web.mit.edu/15.053/www/AMP-Chapter-13.pdf ).
But after running of the following program:
syms x y t;
f = x^2-5*x+y^2-3*y;
fdx = diff(f,1,x); % f'x
fdy = diff(f,1,y); % y'x
x0 = [0 0]; %initial point
A = [1 1;1 0]; %constrains matrix
b = [8;2];
lb = zeros(1,2);
eps = 0.00001;
i = 1;
X = [inf inf];
Z = zeros(2,200); %result for end points (x1,x2)
rr = zeros(1,200);
options = optimset('Display','none');
while( all(abs(X-x0)>[eps,eps]) && i < 200)
%f'x(x0)
c1 = subs(fdx,x,x0(1));
c1 = subs(c1,y,x0(2));
%f'y(x0)
c2 = subs(fdy,x,x0(1));
c2 = subs(c2,y,x0(2));
%optimization point of linear taylor function
ys = linprog((-[c1;c2]),A,b,[],[],lb,[],[],options);
%parametric representation of line
xt = (1-t)*x0(1)+t*ys(1,1);
yt = (1-t)*x0(2)+t*ys(2,1);
%f(x=xt,y=yt)
ft = subs(f,x,xt);
ft = subs(ft,y,yt);
%f't(x=xt,y=yt)
ftd = diff(ft,t,1);
%f't(x=xt,y=yt)=0 -> for max point
[t1] = solve(ftd); % (t==theta)
X = double(x0);%%%%%%%%%%%%%%%%%
% [ xt(t=t1) yt(t=t1)]
xnext(1) = subs(xt,t,t1) ;
xnext(2) = subs(yt,t,t1) ;
x0 = double(xnext);
Z(1,i) = x0(1);
Z(2,i) = x0(2);
i = i + 1;
end
x_point = Z(1,:);
y_point = Z(2,:);
% Draw result
scatter(x_point,y_point);
hold on;
% Print results
fprintf('The answer is:\n');
fprintf('x = %.3f \n',x0(1));
fprintf('y = %.3f \n',x0(2));
res = x0(1)^2 - 5*x0(1) + x0(2)^2 - 3*x0(2);
fprintf('f(x0) = %.3f\n',res);
I get the following result:
x = 3.020
y = 0.571
f(x0) = -7.367
And this no matter how many iterations I running this program (1,50 or 200).
Even if I choose a different starting point (For example, x0=(1,6) ), I get a negative answer to most.
I know that is an approximation, but the result should be positive (for x0 final, in this case).
My question is : what's wrong with my implementation?
Thanks in advance.
i changed a few things, it still doesn't look right but hopefully this is getting you in the right direction. It looks like the intial x0 points make a difference to how the algorithm converges.
Also make sure to check what i is after running the program, to determine if it ran to completion or exceeded the maximum iterations
lb = zeros(1,2);
ub = [2,8]; %if x+y<=8 and x,y>0 than both x,y < 8
eps = 0.00001;
i_max = 100;
i = 1;
X = [inf inf];
Z = zeros(2,i_max); %result for end points (x1,x2)
rr = zeros(1,200);
options = optimset('Display','none');
while( all(abs(X-x0)>[eps,eps]) && i < i_max)
%f'x(x0)
c1 = subs(fdx,x,x0(1));
c1 = subs(c1,y,x0(2));
%f'y(x0)
c2 = subs(fdy,x,x0(1));
c2 = subs(c2,y,x0(2));
%optimization point of linear taylor function
[ys, ~ , exit_flag] = linprog((-[c1;c2]),A,b,[],[],lb,ub,x0,options);
so here is the explanation of the changes
ub, uses our upper bound. After i added a ub, the result immediately changed
x0, start this iteration from the previous point
exit_flag this allows you to check exit_flag after execution (it always seems to be 1 indicating it solved the problem correctly)
I have a code in MATLAB which works with very small numbers, for example, I have values that are on the order of 10^{-25}, however when MATLAB does the calculations, the values themselves are rounded to 0. Note, I am not referring to format to display these extra decimals, but rather the number itself is changed to 0. I think the reason is because MATLAB, by default, uses up to 15 digits after the decimal point for its calculations. How can I change this so that numbers that are very very small are retained as they are in the calculations?
EDIT:
My code is the following:
clc;
clear;
format long;
% Import data
P = xlsread('Data.xlsx', 'P');
d = xlsread('Data.xlsx', 'd');
CM = xlsread('Data.xlsx', 'Cov');
Original_PD = P; %Store original PD
LM_rows = size(P,1)+1; %Expected LM rows
LM_columns = size(P,2); %Expected LM columns
LM_FINAL = zeros(LM_rows,LM_columns); %Dimensions of LM_FINAL
for ii = 1:size(P,2)
P = Original_PD(:,ii);
% c1, c2, ..., cn, c0, f
interval = cell(size(P,1)+2,1);
for i = 1:size(P,1)
interval{i,1} = NaN(size(P,1),2);
interval{i,1}(:,1) = -Inf;
interval{i,1}(:,2) = d;
interval{i,1}(i,1) = d(i,1);
interval{i,1}(i,2) = Inf;
end
interval{i+1,1} = [-Inf*ones(size(P,1),1) d];
interval{i+2,1} = [d Inf*ones(size(P,1),1)];
c = NaN(size(interval,1),1);
for i = 1:size(c,1)
c(i,1) = mvncdf(interval{i,1}(:,1),interval{i,1}(:,2),0,CM);
end
c0 = c(size(P,1)+1,1);
f = c(size(P,1)+2,1);
c = c(1:size(P,1),:);
b0 = exp(1);
b = exp(1)*P;
syms x;
eqn = f*x;
for i = 1:size(P,1)
eqn = eqn*(c0/c(i,1)*x + (b(i,1)-b0)/c(i,1));
end
eqn = c0*x^(size(P,1)+1) + eqn - b0*x^size(P,1);
x0 = solve(eqn);
x0 = double(x0);
for i = 1:size(x0)
id(i,1) = isreal(x0(i,1));
end
x0 = x0(id,:);
x0 = x0(x0 > 0,:);
clear x;
for i = 1:size(P,1)
x(i,:) = (b(i,1) - b0)./(c(i,1)*x0) + c0/c(i,1);
end
% x = [x0 x1 ... xn]
x = [x0'; x];
x = x(:,sum(x <= 0,1) == 0);
% lamda
lamda = -log(x);
LM_FINAL(:,ii) = lamda;
end
The problem is in this step:
for i = 1:size(P,1)
x(i,:) = (b(i,1) - b0)./(c(i,1)*x0) + c0/c(i,1);
end
where the "difference" gets very close to 0. How can I stop this rounding from occurring at this step?
For example, when i = 10, I have the following values:
b_10 = 0.006639735483297
b_0 = 2.71828182845904
c_10 = 0.000190641848119641
c_0 = 0.356210110252579
x_0 = 7.61247930625269
After doing the calculations we get: -1868.47805854794 + 1868.47805854794 which yields a difference of -2.27373675443232E-12, that gets rounded to 0 by MATLAB.
EDIT 2:
Here is my data file which is used for the code. After you run the code (should take about a minute and half to finish running), row 11 in the variable x shows 0 (even after double clicking to check it's real value), when it shouldn't.
The problem you're having is because the IEEE standard for floating points can't distinguish your numbers from zero because they don't utilize sufficient bits.
Have a look at John D'Errico's Big Decimal Class and Variable Precision Integer Arithmetic. Another option would be to use the Big Integer Class from Java but that might be more challenging if you are unfamiliar with using Java and othe rexternal libraries in MATLAB.
Can you give an example of the calculations in which you are using 1e-25 and getting zero? Here's what I get for a floating point called small_num and one of John's high-precision-floats called small_hpf when assigning them and multiplying by pi.
>> small_num = 1e-25
small_num =
1.0000e-25
>> small_hpf = hpf(1e-25)
small_hpf =
1.000000000000000038494869749191839081371989361591338301396127644e-25
>> small_num * pi
ans =
3.1416e-25
>> small_hpf * pi
ans =
3.141592653589793236933163473501228686498684350685747717239459106e-25
I have a formula here:
E = T*(1-W)*U + X*W*F + S*W*C*D
Lets say T, W,S,X and D are all constants, while U, F and C are variables and F and C are related to each other.
Now my aim is to find different values of E based on different combinations of U, F and C.
For example I have values for these variables:
U = 2.02, 1, 3, 4
F = 6, 4, 3.03
C = 0.5, 0.4, 0.3
Noting that F and C are related to each other e.g. when F=6 then C=0.5 or if F=4 then C=0.4 and so on.
Can anyone help me how to execute this on matlab so that matlab will calculate the value for E for all possible combinations of variables.
I found a relation
F = 10*(exp(C)-1.06);
from your data. I don't know if that is consistent with your expectations. Regardless, once you choose the range of C,F, and U and the size of the steps to sample the individual variables, you can compute the phase space of your function like this:
%%%% modify me %%%%
T = 1;
W = 1;
S = 1;
X = 1;
D = 1;
%%%%%%%%%%%%%
Nstep = 10;
U = [2.02, 1, 3 , 4];
F = [6, 4, 3.03];
C = [0.5, 0.4, 0.3];
Umin = min(U);
Umax = max(U);
Cmin = min(C);
Cmax = max(C);
Fmin = min(F);
Fmax = max(F);
Ustep = (Umax-Umin)/Nstep;
Fstep = (Fmax-Fmin)/Nstep;
Cstep = (Cmax-Cmin)/Nstep;
U = [Umin:Ustep:Umax];
C = [Cmin:Cstep:Cmax];
F = [Fmin:Fstep:Fmax];
[C,F,U] = MESHGRID(C,F,U);
E = T.*(1-W).*U + X.*W.*F + S.*W.*C.*D;
If the remaining variables T, W, S, X, D are not scalars you'll need to adjust the size of the arrays holding them.
I'm not sure if I understood correctly your question. If you just want to loop through 3 variables with known values, where two of them are correlated, you can use for example:
U = [2.02 1 3 4];
F = [6 4 3.03];
C = [0.5 0.4 0.3];
T = 1; W = 2; S = 3; X = 4; D = 5; %example values
for j=1:size(U,2)
for i=1:size(F,2)
E = T*(1-W)*U(j) + X*W*F(i) + S*W*C(i)*D; disp (E);
end
end
Otherwise, we need probably a bit more details about the relation between F and C.
I think you want to do this, it is not very optimized but should be easy to understand.
U = [2.02 1 3 4];
F = [6 4 3.03];
C = [0.5 0.4 0.3];
[W, T, D, X, S] = deal(1); %Assign dummy values for now
minLength = min(min(numel(U),numel(F)),numel(C)); %As U is not the same length as F and C here
E = zeros(minLength,1);
for k = 1:minLength
E(k) = T*(1-W)*U(k) + X*W*F(k) + S*W*C(k)*D;
end
You can now find the lowest value by doing:
find(E == min(E))
If I'm to integrate a function
y = -((F+h)M^3(cosh(h*M)+M*beta*sinh(h*M)))/(h*M*cosh(h*M)+(-1+h*M^2*beta)*sinh(h*M))- (alpha*(M^2*(F+h)*(-1+2*h^2*M^2+ cosh(2*h*M)-2*h*M*sinh(2*h*M)))/(8*(h*M*cosh(h*M)+(-1+h*M^2*beta)*sinh(h*M))^2));
with respect to x, where
phi = 0.6;
x = 0.5;
M = 2;
theta = -1:0.5:1.5;
F = theta - 1;
h = 1 + phi*cos(2*pi*x);
alpha = 0.2;beta = 0.0;
I have written an Mfile
function r = parameterIntegrate(F,h,M,beta,alpha,theta,phi)
% defining a nested function that uses one variable
phi = 0.6;
x = 0.5;
r = quad(#testf,0,1 + phi*cos(2*pi*x));
% simpson's rule from 0 to h
function y = testf(x)
h = 1 + phi*cos(2*pi*x);
theta = -1:0.5:1.5;
F = theta - 1;
M = 2;
beta = 0;
alpha = 0;
y = -((F+h)*M^3*(cosh(h*M)+M*beta*sinh(h*M)))/(h*M*cosh(h*M)+(-1+h*M^2*beta)*sinh(h*M))- (alpha*(M^2*(F+h)*(-1+2*h^2*M^2+ cosh(2*h*M)-2*h*M*sinh(2*h*M)))/(8*(h*M*cosh(h*M)+(-1+h*M^2*beta)*sinh(h*M))^2));
end
end
and called the function by
tol = [1e-5 1e-3];
q = quad(#parameterIntegrate, 0, h,tol)
or
q = quad(#parameterIntegrate, 0,1 + phi*cos(2*pi*0.5),tol)
its not working its giving me
Error using ==> plus
Matrix dimensions must agree.
What your error message means is that for some line of code, there are 2 matrices, but the dimensions don't match, so it can't add them. What I suggest you do to solve this is as follows:
Figure out exactly which line of code is causing the problem.
If the line has large numbers of variables, simplify them some.
Remember that if there are any matrixs at all, and you don't want to do matrix multiplication/division, use the .*, ./, and .^.
I suspect that if you change your multiplies/divides with step 3, your problem will go away.