surface(2d) fit in MATLAB with anonymous function - matlab

I want to use fit in MATLAB for two dimensions.
I defined function separately and then called it with fittype
x has two columns!
f=fittype('#(x)myfun(beta1, beta2,beta3, x)')
and then customize in options my start point and algorithm.
then use [results, goodness]=fit(x, zdata,f, options), but I have a error
??? Too many inputs to FITTYPE function.
Error in ==> fit at 443
errstr = handleerr( errid, errmsg, suppresserr );
I also tried with [results, goodness]=fit([x(:,1), x(:,2)], zdata,f, options),
and still have the same problem.
I used fit -all
XDATA must be a matrix with one to two columns.
Error in ==> fit at 115
errstr = handleerr('curvefit:fit:xDataMustBeColumnVector', ...
for me sounds meaningles , since I have my x in two columns!!!!
and then which fit -all
/Applications/matlab/MATLAB_R2010a.app/toolbox/curvefit/curvefit/fit.m
/Applications/matlab/MATLAB_R2010a.app/toolbox/stats/#ProbDistUnivParam/fit.m % ProbDistUnivParam method
/Applications/matlab/MATLAB_R2010a.app/toolbox/stats/#NaiveBayes/fit.m % NaiveBayes method
/Applications/matlab/MATLAB_R2010a.app/toolbox/stats/#gmdistribution/fit.m % gmdistribution method
could you please help me to use fit and fittype to fit my 2 dimension data?
{please don't introduce me meshgrid and other commands.}

You need to add the parameter 'numindep' = 2 which indicates that your fit is for a surface (i.e has two independent variables).
Here's an example using your function with the Franke data using a string:
load franke
ft = fittype('myfun(beta1, beta2, beta3, [x, y])', 'numindep', 2)
[results, goodness] = fit([x, y], z, ft)
Here's an example using your function with the Franke data using an anonymous function:
load franke
ft = fittype(#(beta1,beta2,beta3, x, y)myfun(beta1, beta2,beta3, [x, y]), 'numindep', 2)
[results, goodness] = fit([x, y], z, ft)

Related

How can vector elements with indexing be used in a MATLAB symbolic expression?

I would like to create a MATLAB function with vector inputs. The problem is that the inputs of a function created by matlabFunction() has only scalar inputs.
x = sym('x',[2 1]);
y = sym('y',[2 1]);
f=x(1)+x(2)+y(1)+y(2);
matlabFunction(f,'file','testFunction.m');
matlabFunction(f,'file','testFunction.m','vars',[x,y]); % tried with different options but doesn't work
This is the result (with x1,x2,y1,y2 inputs instead of x,y):
function f = testFunction(x1,x2,y1,y2)
%TESTFUNCTION
% F = TESTFUNCTION(X1,X2,Y1,Y2)
% This function was generated by the Symbolic Math Toolbox version 8.2.
% 10-Apr-2019 21:28:40
f = x1+x2+y1+y2;
Is there a solution to this problem within MATLAB? Or do I need to write a program opening the file as txt and replacing the words...
Update: I managed to solve the problem. For me, the best solution is the odeToVectorField() function.
Manually it is more difficult to give vector inputs to a function created by matlabFunction(). One way is the following:
syms y;
f=str2sym('y(1)+y(2)');
matlabFunction(f,'File','fFunction','Vars',y);
With this method, you need to manipulate the equation as a string (which is possible but not practical...), then re-convert it to symbolic expression.
If you check the result of f=x(1)+x(2)+y(1)+y(2) you will see that it is also scalar. Do simple test:
x = sym('x',[2 1]);
y = sym('y',[2 1]);
f=x(1)+x(2)+y(1)+y(2);
disp(f)
The results is x1 + x2 + y1 + y2. So there's nothing wrong with your matlabFunction expression, it just save what you give. If you need it to be stored in the form x(1)+x(2)+y(1)+y(2) you need to rewrite your f expression so it will be stored in vector form, until passing it to matlabFunction. Or alternatively you can create your file structure manualy using fprintf, look docs.

Passing parameters from workspace to fit function in MATLAB

This is the first time I'm trying to use the fittype function to fit a custom curve (Birch-Murnaghan EOS). This is what I've done so far:
BM = fittype((3*B0/2*((V0/V).^(7/3)-(V0/V).^(5/3))*(1+(3/4)*(B1-4)*((V0/V).^(2/3)-1))), 'coefficients',{'B0', 'B1'}, 'independent', {'V'});
Pres = fit(V,p,BM);
V0 is a constant that I've defined earlier. Data values for pressure(dependent variable), and V(independent variable), have also been defined.
I wish to obtain the values of B0 and B1 through the fitting.
However, I get an error in the fittype function:
Undefined function or variable 'B0'.
However, that is the coefficient I wish to determine from the fitting. Am I using fittype incorrectly?
You are encountering two problems here.
Firstly, there a number of element-wise multiplications and divisions you need to change (similarly to the way you are using .^).
Secondly, according to the MATLAB documentation here anonymous functions are used (search for 'Create a fit type using an anonymous function' in the documentation) if you want to pass parameters from the workspace.
Try like this:
V = rand(10, 1);
p = rand(10, 1);
V0 = 1;
BM = fittype(#(B0, B1, V) (3*B0/2*((V0./V).^(7/3)-(V0./V).^(5/3)).*(1+(3/4).*(B1-4).*((V0./V).^(2/3)-1))), 'independent', {'V'});
fo = fitoptions( 'Method','NonlinearLeastSquares', 'StartPoint',[1 1]);
Pres = fit(V,p,BM, fo);
Note: Without specifying a start point for the parameters to be fit you get a warning because MATLAB chooses the start points randomly.
You can access your parameters using dot notation Pres.B0 or Pres.B1.

Matlab fit function error : Function value and YDATA sizes are not equal

I'm trying to use the fit function to estimate a 4 parameters model(P B A R) and meet the error following message and I dont know what does it mean.
Error using fit>iFit (line 367)
Function value and YDATA sizes are not equal.
Error in fit (line 108)
[fitobj, goodness, output, convmsg] = iFit( xdatain, ydatain, fittypeobj, ...
The basic function is
function c1 = c1(x,T,P,B,A,R)
if T == 0
c1=0;
else
G = #(t) 0.5*erfc((P./(4*B*R*t)).^0.5.*(B*R*x-t))...
-1/2*(1+P*x+P*t/(B*R))*exp(P*x).*erfc((P./(4*B*R*t)).^0.5.*(B*R*x+t))...
+(P*t/(pi*B*R)).^0.5.*exp(-P*(B*R*x-t).^2./(4*B*R*t)); %first term in the solution
u = #(t) A*t/(B*R);%.
v = #(t) A*(T-t)/(1-B)/R; %.
e = #(t) 2*(u(t.*v(t))).^0.5; %.
H1 = #(t) exp(-u(t)-v(t)).*(besseli(0,e(t))/B+besseli(1,e(t)).*((u(t)./v(t)).^0.5)/(1-B));
GH = #(t) G(t).*H1(t);
c1 = G(T).*exp(-A*T/(B*R))+A/R*integral(GH,0,T); %int((g*H1),0,T);
end
and another function that based on the foregoing function c1 is
function cm = cm(x,time,P,B,A,R,T1)
for i=1:length(time);
if time(i)<T1
cm(i)=c1(x,time(i),P,B,A,R);
else
cm(i)=c1(x,time(i),P,B,A,R)-c1(x,time(i)-T1,P,B,A,R);
end
end
This function mainly divide the data into two parts for different calculation.
I tried to give a reasonable arbitrary four parameters to run cm to obtain a set of time-c data, use the following code
x=2;
time=0.1:0.1:10;
T1=2;
c=cm(x,time,0.8,0.8,0.8,0.8,T1);
and it works well
after that I tried to use fit function to fit the set of data to obtain the four parameters, using the following code
ft = fittype('cm(x,time,P,B,A,R,T1)','independent','time','problem','x'); % independent variable is time, fixed parameter x
>> [f, gof] = fit( time', c', ft, 'Lower', [0, 0, 0, 1,2], 'Upper', [1, 1, 1, 1,2],'problem',x);
thats when I met the error
Error using fit>iFit (line 367)
Function value and YDATA sizes are not equal.
I checked the input time-c data that obtained from function cm, they have the same size, so I don'k see anything wrong with the input data. I suspect it is the problem with the function that fit function does not work.
Can anyone help me with this problem? Besides, what does it mean by YDATA?
Thank you in advance !

How to use multiple parameters with fittype in Matlab

I have a 1000x2 data file that I'm using for this problem.
I am supposed to fit the data with Acos(wt + phi). t is time, which is the first column in the data file, i.e. the independent variable. I need to find the fit parameters (A, f, and phi) and their uncertainties.
My code is as follows:
%load initial data file
data = load('hw_fit_cos_problem.dat');
t = data(:,1); %1st column is t (time)
x = t;
y = data(:,2); %2nd column is y (signal strength)
%define fitting function
f = fittype('A*cos(w*x + p)','coefficients','A','problem',{'w','p'});
% check fit parameters
coeffs = coeffnames(f);
%fit data
[A] = fit(x,y,f)
disp('confidence interval/errorbars');
ci = confint(A)
which yields 4 different error messages that I don't understand.
Error Messages:
Error using fit>iAssertNumProblemParameters (line 1113)
Missing problem parameters. Specify the values as a cell array with one element for each problem parameter
in the fittype.
Error in fit>iFit (line 198)
iAssertNumProblemParameters( probparams, probnames( model ) );
Error in fit (line 109)
[fitobj, goodness, output, convmsg] = iFit( xdatain, ydatain, fittypeobj, ...
Error in problem2 (line 14)
[A] = fit(x,y,f)
The line of code
f = fittype('A*cos(w*x + p)','coefficients','A','problem',{'w','p'});
specifies A as a "coefficient" in the model, and the values w and p as "problem" parameters.
Thus, the fitting toolbox expects that you will provide some more information about w and p, and then it will vary A. When no further information about w and p was provided to the fitting tool, that resulted in an error.
I am not sure of the goal of this project, or why w and p were designated as problem parameters. However, one simple solution is to allow the toolbox to treat A, w, and p as "coefficients", as follows:
f = fittype('A*cos(w*x + p)','coefficients', {'A', 'w', 'p'});
In this case, the code will not throw an error, and will return 95% confidence intervals on A, w, and p.
I hope that helps.
The straightforward answer to your question is that the error "Missing problem parameters" is generated because you have identified w and p as problem-specific fixed parameters,
but you have not told the fit function what these fixed values are.
You can do this by changing the line
[A] = fit(x,y,f)
to
[A]=fit(x,y,f,'problem',{100,0.1})
which supplies the values w=100 and p=0.1 in the fit. This should resolve the errors you specified (all 4 error messages result from this error)
In general specifying some of the quantities in your fit equation as problem-specific fixed parameters might be a valid thing to do - for example if you have determined them independently and have good reason to believe the values you obtained to be reliable. In this case, you might know the frequency w in this way, but you most probably won't know the phase p, so that should be a fit coefficient.
Hope that helps.

MATLAB Function (Solving an Error)

I have one file with the following code:
function fx=ff(x)
fx=x;
I have another file with the following code:
function g = LaplaceTransform(s,N)
g = ff(x)*exp(-s*x);
a=0;
b=1;
If=0;
h=(b-a)/N;
If=If+g(a)*h/2+g(b)*h/2;
for i=1:(N-1)
If=If+g(a+h*i)*h;
end;
If
Whenever I run the second file, I get the following error:
Undefined function or variable 'x'.
What I am trying to do is integrate the function g between 0 and 1 using trapezoidal approximations. However, I am unsure how to deal with x and that is clearly causing problems as can be seen with the error.
Any help would be great. Thanks.
Looks like what you're trying to do is create a function in the variable g. That is, you want the first line to mean,
"Let g(x) be a function that is calculated like this: ff(x)*exp(-s*x)",
rather than
"calculate the value of ff(x)*exp(-s*x) and put the result in g".
Solution
You can create a subfunction for this
function result = g(x)
result = ff(x) * exp(-s * x);
end
Or you can create an anonymous function
g = #(x) ff(x) * exp(-s * x);
Then you can use g(a), g(b), etc to calculate what you want.
You can also use the TRAPZ function to perform trapezoidal numerical integration. Here is an example:
%# parameters
a = 0; b = 1;
N = 100; s = 1;
f = #(x) x;
%# integration
X = linspace(a,b,N);
Y = f(X).*exp(-s*X);
If = trapz(X,Y) %# value returned: 0.26423
%# plot
area(X,Y, 'FaceColor',[.5 .8 .9], 'EdgeColor','b', 'LineWidth',2)
grid on, set(gca, 'Layer','top', 'XLim',[a-0.5 b+0.5])
title('$\int_0^1 f(x) e^{-sx} \,dx$', 'Interpreter','latex', 'FontSize',14)
The error message here is about as self-explanatory as it gets. You aren't defining a variable called x, so when you reference it on the first line of your function, MATLAB doesn't know what to use. You need to either define it in the function before referencing it, pass it into the function, or define it somewhere further up the stack so that it will be accessible when you call LaplaceTransform.
Since you're trying to numerically integrate with respect to x, I'm guessing you want x to take on values evenly spaced on your domain [0,1]. You could accomplish this using e.g.
x = linspace(a,b,N);
EDIT: There are a couple of other problems here: first, when you define g, you need to use .* instead of * to multiply the elements in the arrays (by default MATLAB interprets multiplication as matrix multiplication). Second, your calls g(a) and g(b) are treating g as a function instead of as an array of function values. This is something that takes some getting used to in MATLAB; instead of g(a), you really want the first element of the vector g, which is given by g(1). Similarly, instead of g(b), you want the last element of g, which is given by g(length(g)) or g(end). If this doesn't make sense, I'd suggest looking at a basic MATLAB tutorial to get a handle on how vectors and functions are used.