Linear combination of a string vector (w/functions) and number vector (coefficients) - matlab

I'm really new at matlab, and am trying to fit a line or curve to data points for homework (that part is actually done). Now, I want to take this a little further than the homework asked, I have constructed a function that takes in a text file with coordinates and any number of functions (1,x,x^2... e.g.) and determines the coefficients.
So in the end I'm left with two vectors: one with the coefficients: C = [a,b,c] and another one with functions: F = {'1','x','x^2'}, and I'd like to create a linear combination of them: l = a + b*x + c*x^2, to plot the curve on a graph, and for some reason I can't figure out how to get that to work. Is there something obvious I'm overlooking, or do I have to rethink this in some way?

a=1; b=2; c=3;
C=[a,b,c];
CS = cellfun(#num2str,num2cell(C),'uniformoutput',0)
M={'*','*','*'};
F={'1','x','x^2'};
P={' + ',' + ',''};
S=reshape([CS; M; F; P],1,[]);
cat(2,S{:})
Output:
ans =
1*1 + 2*x + 3*x^2
Are you sure you want to print 'a', 'b' and 'c' as chars?

Related

Using MATLAB plots to find linear equation constants

Finding m and c for an equation y = mx + c, with the help of math and plots.
y is data_model_1, x is time.
Avoid other MATLAB functions like fitlm as it defeats the purpose.
I am having trouble finding the constants m and c. I am trying to find both m and c by limiting them to a range (based on smart guess) and I need to deduce the m and c values based on the mean error range. The point where mean error range is closest to 0 should be my m and c values.
load(file)
figure
plot(time,data_model_1,'bo')
hold on
for a = 0.11:0.01:0.13
c = -13:0.1:-10
data_a = a * time + c ;
plot(time,data_a,'r');
end
figure
hold on
for a = 0.11:0.01:0.13
c = -13:0.1:-10
data_a = a * time + c ;
mean_range = mean(abs(data_a - data_model_1));
plot(a,mean_range,'b.')
end
A quick & dirty approach
You can quickly get m and c using fminsearch(). In the first example below, the error function is the sum of squared error (SSE). The second example uses the sum of absolute error. The key here is ensuring the error function is convex.
Note that c = Beta(1) and m = Beta(2).
Reproducible example (MATLAB code[1]):
% Generate some example data
N = 50;
X = 2 + 13*random(makedist('Beta',.7,.8),N,1);
Y = 5 + 1.5.*X + randn(N,1);
% Example 1
SSEh =#(Beta) sum((Y - (Beta(1) + (Beta(2).*X))).^2);
Beta0 = [0.5 0.5]; % Initial Guess
[Beta SSE] = fminsearch(SSEh,Beta0)
% Example 2
SAEh =#(Beta) sum(abs(Y-(Beta(1) + Beta(2).*X)));
[Beta SumAbsErr] = fminsearch(SAEh,Beta0)
This is a quick & dirty approach that can work for many applications.
#Wolfie's comment directs you to the analytical approach to solve a system of linear equations with the \ operator or mldivide(). This is the more correct approach (though it will get a similar answer). One caveat is this approach gets the SSE answer.
[1] Tested with MATLAB R2018a

Matlab AR digital fiter computation w/o loops

I'm given the a(k) matrix and e(n) and I need to compute y(n) from the following eq:
y(n) = sum(k = 1 to 10 )( a(k)*y(n-k) ) + e(n).
I have the a matrix(filter coefficients) and the e matrix (the residual), therefore there is only 1 unknown: y, which is built by the previous 10 samples of y.
An example to this equation:
say e(0) (my first residual sample) = 3
and y(-10) to y(-1) = 0
then y(0), my first sample in the signal y, would just be e(0) = 3:
y(0) = a(1)*y(-1) + a(2)*y(-2) + .... + a(10)*y(-10) + e(0) = e(0) = 3
and if e(1) = 4, and a(1) = 5, then
y(1) = a(1)*y(0) + a(2)*y(-1) + a(3)&y(-2) + ... + a(10)*y(-9) + e(1) = 19
The problem is
I don't know how to do this without loops because, say, y(n) needs y(n-1), so I need to immediately append y(n-1) into my matrix in order to get y(n).
If n (the number of samples) = say, 10,000,000, then using a loop is not ideal.
What I've done so far
I have not implemented anything. The only thing I've done for this particular problem is research on what kind of Matlab functions I could use.
What I need
A Matlab function that, given an equation and or input matrix, computes the next y(n) and automatically appends that to the input matrix, and then computes the next y(n+1), and automatically append that to the input matrix and so on.
If there is anything regarding my approach
That seems like it's on the wrong track, or my question isn't clear enough, of if there is no such matlab function that exists, then I apologize in advance. Thank you for your time.

Split Anonymous Function into Terms

I am wanting to take a matlab anonymous function of something like #(x) = x + x^2 and split it into a cell array so that
f{1} = #(x) x
f{2} = #(x) x^2
I want to be able to do this with some arbitrary function handle. The best that I have come up with so far is taking in #(x) = x + x^2 as a string and splitting it by the addition signs and appending #(x) to the beginning of this. However, I would like to be able to directly use a function handle as the function argument. It would also be nice as using other variables could lead to some difficulty in the string approach.
I am also considering just taking in a cell array of function handles as an argument, which would be more difficult for the user but easier in my code.
For some background, I'm wanting to do this for some least squares data fitting code that I am writing for a class. This code will be for taking in a model function as an argument and I need to evaluate each term separately for the least squares process. I'm not limiting these models to polynomials and even if a polynomial is the model, I want the option to leave out certain powers in the polynomial. If someone has a better suggestion for taking a model function, that would be great too.
UPDATE: Someone wanted to know what I meant by
I'm not limiting these models to polynomials and even if a polynomial
is the model, I want the option to leave out certain powers in the
polynomial.
For some clarification, I was saying that I didn't want to limit the models to
c0 + c1*x + ... + cn*x^n
in which case I could just take in n as a parameter and create terms from that similar to what happens in polyfit. For example, if I know that my input data fits an even or odd function, I may want one of the following models
c0 + c1*x^2 + c2*x^4 + ... + ck*x^(2k)
c1*x + c2*x^3 + ... + cm*x^(2m-1)
Where k is even and m is odd. Or possibly a model that isn't strictly a polynomial, but keeps the coefficients linear, such as
c0 + exp(x) * ( c1 + c2*x + ... cn*x^(n-1) )
This is an interesting problem. The string should not be split at + signs that are within a parenthesis group. For example, with
f = #(x) x + (x+1)*sqrt(x) + x^2 + exp(x+2);
the string should be split at the first, but not at the second + sign.
This can be accomplished as follows. To detect only + signs that are outside parentheses, add 1 for each opening parenthesis and subtract 1 for each closing parenthesis. Then the desired + signs are those with count 0.
I'm assuming the output should be a cell array of function handles. If it should be a cell array of strings just remove the last line.
F = functions(f);
str = F.function; %// get string from function handle
[pref, body] = regexp(str, '#\(.+?\)', 'match', 'split'); %// pref is the '#(...)' part
body = body{2}; %// body is the main part
ind = cumsum((body=='(')-(body==')'))==0 & body=='+'; %// indices for splitting
body(ind) = '?'; %// '?' will be used as split marker
ff = strcat(pref, strsplit(body, '?')); %// split, and then add prefix
ff = cellfun(#str2func, ff, 'uniformoutput', 0); %// convert strings to functions
Result in this example:
ff{1} =
#(x)x
ff{2} =
#(x)(x+1)*sqrt(x)
ff{3} =
#(x)x^2
ff{4} =
#(x)exp(x+2)

How can i create a multivariable function in matlab out of matrix data?

but i want to make a program in which i can generate a function of multiple variables that depend on the number of rows of a matrix.
for k = 1:sizel;
f(k)=(alpha(k,1)+(beta(k,1)*p(k))+(gamma(k,1)*p(k)^2));
end
cost=(sum(f))
this is for the purpose of optimization so i need that at the end the variables are declares as p(1),p(2),p(3)... these will be the input for my function.
Note: i dont want to assign values to the variables because this will be done be the optimization algorithm in the optimization toolbox.
here is the complete code
function cost = cost(p) ;
clc
clear
costfunctionconstantsmatrix;
sizel=size(CostFormulaconstants);
alpha=CostFormulaconstants(:,1);
beta=CostFormulaconstants(:,2);
gamma=CostFormulaconstants(:,3);
for k = 1:sizel;
f(k)=(alpha(k,1)+(beta(k,1)*p(k))+(gamma(k,1)*p(k)^2));
end
cost=(sum(f))
end
i used the symbolic approach and i got the correct answer for the cost indeed, i got something like this: (53*p(1))/10 + (11*p(2))/2 + (29*p(3))/5 + p(1)^2/250 + (3*p(2)^2)/500 + (9*p(3)^2)/1000 + 1100. But when i try to specify my function to be optimized in the optimization toolbox it tells me that the variables p are sym and cannot be converted to double. the trouble is how to convert this expression to double so that the optimization algorithm can input values for the variable p(1), p(2) and p(3)
Can you pass the matrix as an argument to the function?
function cost = fcn(my_mat)
[m,n] = size(my_mat);
f = zeros(m,1);
for k = 1:m % for example
f(k)=(alpha(k,1)+(beta(k,1)*p(k))+(gamma(k,1)*p(k)^2));
end
cost = sum(f);
end
Your problem is not entirely clear to me but I believe you wish to generate a series of functions in which the variables alpha, beta, gamma are constants with different values for each function, and the vector p is an argument.
What confuses me in your question is that you use the index k for both the constants and the arguments, which I think is not what you intended to write. Assuming I understand your goal, a solution may make use of function handles.
The notation f(k) = #(p) p(1)+p(2) for example, generates a function that adds p(1) and p(2). Abbreviating CostFormulaconstants to cf, the following would generate a series of functions, one for each row in cf.
for k = 1 : size(cf, 1)
f{k} = #(p) cf(k,1) + cf(k,2)*p(1) + cf(k,3)*p(2)^2;
end
You can supply individual function handles to callers from the optimization toolbox simply with f{3} for the third function, for example. A call to f{3} would look like
a = f{3}([3,4]);
If your functions are indeed all polynomials, polyval may be worth a look as well.
EDIT: After clarification, the problem seems a bit simpler, no need for function handles. Why not simply
function c = cost(p)
c = 0;
cf = [...]; % your coefficients here.
for k = 1 : size(cf, 1)
c = c + cf(k,1) + cf(k,2)*p(k) + cf(k,3)*p(k)^2;
end

Get function handle of fit function in matlab and assign fit parameters

I'm fitting custom functions to my data.
After obtaining the fit I would like to get something like a function handle of my fit function including the parameters set to the ones found by the fit.
I know I can get the model with
formula(fit)
and I can get the parameters with
coeffvalues(fit)
but is there any easy way to combine the two in one step?
This little loop will do the trick:
x = (1:100).'; %'
y = 1*x.^5 + 2*x.^4 + 3*x.^3 + 4*x.^2 + 5*x + 6;
fitobject = fit(x,y,'poly5');
cvalues = coeffvalues(fitobject);
cnames = coeffnames(fitobject);
output = formula(fitobject);
for ii=1:1:numel(cvalues)
cname = cnames{ii};
cvalue = num2str(cvalues(ii));
output = strrep(output, cname , cvalue);
end
output = 1*x^5 + 2*x^4 + 3*x^3 + 4*x^2 + 5*x + 6
The loop needs to be adapted to the number of coefficients of your fit.
Edit: two slight changes in order to fully answer the question.
fhandle = #(x) eval(output)
returns a function handle. Secondly output as given by your procedure doesn't work, as the power operation reads .^ instead of x, which can obviously be replaced by
strrep(output, '^', '.^');
You can use the Matlab curve fitting function, polyfit.
p = polyfit(x,y,n)
So, p contains the coefficients of the polynomial, x and y are the coordinates of the function you're trying to fit. n is the order of the polynomial. For example, n=1 is linear, n=2 is quadratic, etc. For more info, see this documentation centre link. The only issue is that you may not want a polynomial fit, in which case you'll have to use different method.
Oh, and you can use the calculated coefficients p to to re-evaluate the polynomial with:
f = polyval(p,x);
Here, f is the value of the polynomial with coefficients p evaluated at points x.