How can I write a mathematical function in Matlab?
21 次查看(过去 30 天)
显示 更早的评论
ND
2015-6-25
Can I build an equation which have different components?
variables written in cell array(1x3) such as 'X1' 'X2' 'X3'
exponents written in matrix (3x3 double) e.g [0 .5 -.5; .5 -.5 0; 1 0 .5]
Parameters written in matrix(3x1) e.g [.55;.25;.6893]
can I get equation like
F= .55*X2^.5*X3^-.5+ .25*X1^.5*X2^-.5+.6893*X1^1*X3^.5
Many thanks
采纳的回答
Walter Roberson
2015-6-25
MATLAB is a general purpose programming language. You can build up any string you want.
subf = sprintf('*X%d^e%d', [1:3; 1:3]);
formula = ['a1' subf '+a2' subf '+a3' subf];
What you should try to avoid is executing such strings. Dynamic generation of code is error prone.
32 个评论
Image Analyst
2015-6-26
What is e1, e2, and e3? Also, you're going to have to add braces after the X's because the X's were decided to be put (perhaps unwisely ) into a cell array.
ND
2015-6-26
I need to have this function
F= .55*X2^.5*X3^-.5+ .25*X1^.5*X2^-.5+.6893*X1^1*X3^.5
e1,e2,... mean the exponents written in matrix [[0 .5 -.5; .5 -.5 0; 1 0 .5]
Steven Lord
2015-6-26
What are you planning to DO with this function?
Are you planning to evaluate it? [If so, please DON'T DO THIS. Walter is correct that it can be problematic.]
Are you planning to display it? If so, expand Walter's solution.
s = 'X^3';
a = pi;
term = sprintf('%1.4f*%s', a, s)
ND
2015-6-26
Actually, i need to build up the equation. I have the variables and exponents and parameters. but those are changeable every run I will have different length of matrices so it should be done in a for loop.
Walter Roberson
2015-6-26
What are you going to do with the equation once it is built?
If your need is to display the formula in a table or publication then the method of proceeding would be different than if you are needing to (for example) use the generated formula as an objective function.
Walter Roberson
2015-6-26
Building up the equation symbolically is different than building it up in a string. When doing it symbolically you can create the template and then subs() the values and variable names in to make it more specific. Or better yet, don't substitute the values in, build it up symbolically as pure variables and calculate the jacobians or differentiate it as pure variables, which is something you could do once on the template and then afterwards substitute in specific values if you ever need to evaluate it.
syms A E V
form = feval(symengine, 'k->sum(A[k]*(product(V[n]^E[k, n], n = 1 .. p))/V[k]^E[k, k], k = 1 .. p)');
syms X1 X2 X3
X = [X1, X2, X3];
form3 = subs(form(length(X)), V, X); %one specific case for 3
syms X4 X5 X21
X2 = [X2, X4, X5, X21];
form3b = subs(form(length(X2)), V, X2); %another one in different variables
and you can then do things like diff(form3, X1) and otherwise manipulate it without substituting in the actual values. When it becomes time to put in actual values,
expr = subs(form3, {A, E}, {a, e});
exprb = subs(form3b, {A, E}, {a2, e2});
ND
2015-6-26
编辑:ND
2015-6-26
This is not what I am looking for,it seems to be more difficult than expected, As it is an automation process, so I should use for loop to build up an equation because I do not know the length of matrix for next run (at each run I will get another equation).
the basic form of the equation is
a1*X1^e11 *X2^e12 ...+ a2 X1^e21*X2^e22 +....
a1, a2 = parameters X1,X2 = variables e11,e12 ,...= exponent(power)
Image Analyst
2015-6-26
Why are you saying that X is a cell array when you made it like this:
syms X1 X2 X3
X = [X1, X2, X3];
You did not use the cell() function or use braces, so how is X a cell array. Please read this: http://matlab.wikia.com/wiki/FAQ#What_is_a_cell_array.3F And anyway, what is a typical value for X? Are all the X's different sizes? Why can't the X simply be regular, normal numerical arrays? Why do they have to be symbolic or cells?
e is this:
[0.0 5.0 -0.5;
0.5 -0.5 0.0;
1.0 0.0 0.5]
What is the order for e1 through e6? Are you going down columns, or across rows? Why not just call the whole thing e and refer to the values as e(2,3) or e(3,1) or whatever - use the actual row and column numbers instead of extracting them into separate variables like e23 and e31?
And what are the a's? how many of them are there? Where do they come from? Are they really elements of an "a" array like the e's are but you just extracted them (for some reason) into single variables?
ND
2015-6-26
编辑:ND
2015-6-26
sorry, I explained everything above
variables written in cell array(1x3) such as 'X1' 'X2' 'X3'
exponents written in matrix (3x3 double) e.g [0 .5 -.5; .5 -.5 0; 1 0 .5]
0 0.5000 -0.5000
0.5000 -0.5000 0
1.0000 0 0.5000
Parameters written in matrix(3x1) e.g [.55;.25;.6893]
X1,X2 variables like stress , speed ,pressure any variable stored in a cell array
so, in the first term of equation X1 ^0 , and X2^.5 , X3^-.5 and so on
a represents the parameter
in each term of equation there is specific a such as a1 in first , a2 in the second ... so on
Image Analyst
2015-6-26
OK, I'm about to give up. I don't think you know enough about MATLAB yet to answer questions. If X is a cell array, with 3 cells, and the first cell contains the string 'X1', then how can you raise a string to a numerical power? You can only raise numbers to a power. It does not make sense to raise a string to a power, like 'Hello world' ^0.5 or 'X1' ^1.5. X1 as a string would be the ASCII value of 88 for the X followed by an ASCII value of 49 for the 1, but 'X1' is a string, not a number, and you can't, or shouldn't raise a string to a power.
Image Analyst
2015-6-27
Not if X1 is a string. If X1 is numbers rather than a string , please give an actual value for X1 so we can see what it is.
ND
2015-6-27
simply if I have variable like X1= 0,2,3,4,5 and X2= 0,4,9,16,25
So the equation is X2=X1^2
How can build up like this simple equation ?
Walter Roberson
2015-6-27
syms A E V
form = evalin(symengine, 'p->sum(A[k]*(product(V[n]^E[k, n], n = 1 .. p))/V[k]^E[k, k], k = 1 .. p)');
X = {'X1', 'X2', 'X3'};
Xs = cellfun(@sym, X);
formX = subs(form(length(X)), V, Xs);
and you can differentiate this and take jacobians to your heart's content. (Hearts' content if you have multiple hearts.) For example,
diff(formX, Xs(2))
When you want to specialize it with particular numbers,
specialized = subs(formX, {A, E}, {a, e});
and you can compute with that result. You can also
fstring = char(specialized);
and that will give you a string containing what you have been asking for (but which is not what you actually need except for display purposes.)
If you wanted to create a MATLAB anonymous objective function for fitting purposes then you could do
ffun = matlabFunction(specialized, 'Vars', Xs);
I do not much concerned that the symbolic mechanism is "more difficult than you expected".
form = evalin(symengine, 'p->sum(A[k]*(product(V[n]^E[k, n], n = 1 .. p))/V[k]^E[k, k], k = 1 .. p)');
is pretty simple and returns a symbolic function that generates the formula for any number of variables. You wanted a sum of products of indexed variables and this expresses a sum of products of indexed variables very compactly. You wanted differentiation and this allows you true differentiation, not trying to fake it by taking numeric differentiation or by doing textual processing on strings to implement the chain rule mechanically.
ND
2015-6-27
Thank you Walter for your answer,
But I do not know why you used syms ? I have already these variables.
A = parameter, V = variable, E= exponent ? what does the second term in the form ?
/V[k]^E[k, k], k = 1 .. p)');
Walter Roberson
2015-6-28
"syms" is for creating symbolic formula. The evalin() creates a symbolic function. When the symbolic function is executed being passed the number of variables involved, called p in the function, the execution of the function creates a template for the desired formula. In the template, the location for the parameter is named A, the location of the variable name is named V, and the location of the exponent is named E. You can substitute particular variable names or particular parameter arrays or exponent arrays into the template by using subs() in the way I show. And when you have the template for a particular number of variables you can substitute different names or values into the template without having to recreate the template.
The expression the symbolic function would create when passed the integer 3 would be
A[1]*V[2]^E[1,2]*V[3]^E[1,3] + A[2]*V[1]^E[2,1]*V[3]^E[2,3] + A[3]*V[1]^E[3,1]*V[2]^E[3,2]
This is the pattern that has to be followed for 3 variables. If you subs() in [X1, X2, X3] for V then the specialized version would become
A[1]*X2^E[1,2]*X3^E[1,3] + A[2]*X1^E[2,1]*X3^E[2,3] + A[3]*X1^E[3,1]*X2^E[3,2]
and if you subs() in [X9, X3, X17] for V then the specialized version for that would become
A[1]*X3^E[1,2]*X17^E[1,3] + A[2]*X9^E[2,1]*X17^E[2,3] + A[3]*X9^E[3,1]*X3^E[3,2]
It is not necessary to recompute what the form of the expression is; it is only necessary to substitute in different names.
Keep in mind that what is being created here is symbolic formula. When you specialize the formula by subs() in the array values you give in your example, and the formula
.55*X2^(.5)*X3^(-.5)+.25*X1^(.5)*X2^(-.5)+.6893*X1^(1)*X3^(.5)
gets created, this is in symbolic form and it is not going to try to immediate execute it based upon whatever value is in the workspace for X1, X2, X3. Requesting that it be executed for particular X1, X2, X3 would be an additional step. The matlabFunction() call that I showed would translate the above symbolic formula into an anonymous MATLAB function
@(X1, X2, X3) .55.*X2.^.5.*X3.^-.5+.25.*X1.^.5.*X2.^-.5+.6893.*X1.^1.*X3.^.5
all ready to be called with specific numeric values at the MATLAB level.
With regards to the /V[k]^E[k, k] part of the formula:
the first term of your sum involves X2, X3 but not X1, the second term involves X1, X3 but not X2, the third term involves X1, X2 but not X3. There are two ways of handling that: one can directly generate "product of all of the variables but leave out the K'th variable"; or one can generate "product of all of the variable and divide that by the K'th variable to get the same result as if the K'th had been left out". It happens that generating all of the product of all of the variables but leaving a particular one out involves more complicated code than multiplying all of the entries together and then dividing by the one that is not wanted. An analogy would be "Calculate the sum of the first N integers but leave out the number M": you can calculate that as
sum(1:M-1)+sum(M+1:N)
or you can calculate it as
sum(setdiff(1:N),M)
or you can calculate it as
sum(1:N)-M
You can see that removing the effect of the M makes for much simpler code than if you had to avoid adding in the value for M.
Notice the whole bit is being evaluated in the symbolic engine. In MATLAB if you want to take the product of values, you have to calculate the values first and then use prod() on them to multiply the terms together. In the symbolic engine you can instead say product(expression,range_of_values) like product((a[k]-1)^2,k=1..3) meaning product([(a[1]-1)^2, (a[2]-1)^2, (a[3]-1)^2]) meaning (a[1]-1)^2*(a[2]-1)^2*(a[3]-1)^2 . This is more compact and intuitive than the way you would have to do it in MATLAB itself, prod(arrayfun(@(V) (V-1)^2, a))
Likewise the symbolic engine supports sum(expression,range_of_values) indicating summation over the values indicated.
The symbolic expression I created is a summation (sum()) of terms of an expression, where the expression is a[k] times the product of terms of an expression involving one variable and one exponent. This is like a nested for loop.
Walter Roberson
2015-6-28
A point that I think needs to be made:
You cannot use MATLAB to generate MATLAB code directly.
If you have the symbolic toolbox, you can use MATLAB to generate symbolic formula which can be mathematically manipulated with mathematical reasoning, with the tool knowing for example that diff(x^n,x) is n*x^(n-1), or knowing that cos(theta)^2+sin(theta)^2 = 1 . That tool allows substitutions of values for expressions and subexpressions and the substitutions can be numeric or symbolic expressions. Considerable mathematical reasoning power is available through the symbolic toolbox. The symbolic toolbox includes a routine named matlabFunction() which can convert symbolic formulae into MATLAB anonymous functions.
If you do not have the symbolic toolbox or choose not to use it, then you can generate strings in MATLAB code format. If the string is a single expression, you can use str2fun() to have MATLAB parse the string and convert it to the anonymous function represented by the content of the string. If you choose not to do that or the string represents a command, then you can write the string to a file and then ask MATLAB to execute the file. Or you can use eval() on the string.
Converting a string to an anonymous function using str2fun(), and even more so using eval(), have some hidden risks that can make it easy to destroy the state of your program or even delete files on your system. The risks are notably lower when you use symbolic formula instead of str2fun() or eval(). Using eval() is quite likely to cause difficult to track down trouble; str2fun() and symbolic formula are a lot less likely to lead to the same scenarios.
You need to differentiate between something that is data that might happen to have an interesting form, compared to something is a command. At the MATLAB command prompt, typing in
quit
is going to leave MATLAB. But you can have a string
F = 'tiuq'
which is data and when you use
fliplr(F)
then the result is the string 'quit' but it is still data. Data can be manipulated.
If you have
F2 = str2fun(['@() ', fliplr(F)])
then F2 is still data, but it is data that has been parsed and is ready to be executed. If you now invoke
F2()
then you putting what was formerly data into execution and your MATLAB session is going to execute.
Now imagine what would happen in the code you are thinking of if someone were to say that the variable names to use for this call of the routine should be 'X1, 'X2', and 'quit()' . You "somehow" create
.55*X2^.5*quit()^-.5+.25*X1^.5*X2^-.5+.6893*X1^1*quit()^.5
and then what happens? As long as what you are creating is data then nothing special happens, and if what you are creating is a symbolic formula then you can continue to work with it including differentiation and jacobians because the symbolic engine will treat "quit" as just another variable name. But if you eval() the data at the MATLAB level then you are in trouble.
This is why it is crucial that you understand the difference between code and data, and so understand why I created the formula as data that can then be manipulated in useful ways.
ND
2015-6-28
编辑:ND
2015-6-29
Sorry, I think there is something misunderstand, that I have the general form of the equation, so why all of these complicated stuff to build up an equation ?
Function = a(1) * X1^e(1,1) * X2^e(1,2) * X3^e(1,3) +
a(2) * X1^e(2,1) * X2^e(2,2) * X3^e(2,3) +
a(3) * X1^e(3,1) * X2^e(3,2) * X3^e(3,3)
If you apply with this you well get this function
F= .55*X2^.5*X3^-.5+ .25*X1^.5*X2^-.5+.6893*X1^1*X3^.5
When I apply with the components which are stored in workspace (variables,exponents, parameters) so when e(1,1) = 0 (X1^0 =1) will cancel the variable from the equation and so on.
So the number of variables are constant and the changes are just with exponents and parameters. therefore, I will get different model at each run but in the same form. Is that possible ?
Many thanks
Walter Roberson
2015-6-29
I had no reason at all to expect that the number of variables was fixed. If the number of variables was fixed then there would be no point in generating the formula for the purposes of taking the jacobian or differentiating, because those could be done ahead of time and the numbers substituted in afterwards.
It appears that I was mistaken about only two of the three variables being used; I had not noticed that you had exponents of 0: you had bothered to write in an exponent of 1 but not an exponent of 0. The adjustment would make my symbolic function even simpler.
Anyhow, you still need to decide what form you want the result in. Do you want the result as a string? As a symbolic expression? As an anonymous function? Do you want to be passing in values for everything including values for the variables and have just a pure numeric output? (If so then the names of the variables are irrelevant.) If your answer is "string" then be advised that you cannot differentiate a string or form its jacobian. If your answer is "anonymous function" then be advised that differentiating an anonymous function or forming its jacobian would have to be done as numeric approximation, which would be an inefficient thing to do when you could so easily do an exact differentiation if you worked with a symbolic expression.
ND
2015-6-29
编辑:ND
2015-6-29
I need it as a symbolic expression and then by using function (jacobian) in matlab I can get it then passing it to another software which does the calculation so if I have like this equation :
F= .55*X2^.5*X3^-.5+ .25*X1^.5*X2^-.5+.6893*X1^1*X3^.5
It would be easy to get jacobian for it
But remember I will have known number of variables but the parameters and exponents would vary at each run. I mean for first run I will have matrix of exponent [3x2] and next run [3x3] and so on and for parameter the same thing
Walter Roberson
2015-6-29
Would there be a difference between a 3 x 2 exponent and a 3 x 2 padded with 0s to form 3 x 3? Since an exponent of 0 would cause that portion to simplify to 1 ? (This returns to the point that sometimes it is easier to fill out a pattern in full rather than to only generate a partial pattern.)
Is the number of rows in the exponent always the same as the number of elements in the "a" matrix?
Is the number of elements in the "a" matrix always 3? Because so far the number of elements in the "a" matrix determines the number of terms in the summation, so if that number is going to vary then we do need a generating routine.
ND
2015-6-29
编辑:ND
2015-6-29
I think we need to generate it to full and with zero will cancel that variable. the number of rows of exponent is vary but the coloumns are the same as number of variable. and the number of elements of 'a' matrix (parameters) is vary as sometime I have model with two term , three term ,etc
all elements (variables, parameters,exponents) are stored in the workspace
Walter Roberson
2015-6-29
function form = generateFormula(X, a, e)
form = 0;
Xs = cellfun(@sym, X);
for k = 1 : length(a)
form = form + a(k) * Xs(1)^e(k,1) * Xs(2)^e(k,2) * Xs(3)^e(k,3);
end
end
To me this is worse code than before, but it is what you expect, and if you won't use the better code then you must use the worse code.
ND
2015-6-29
I cannot use the first code as the variables are constant.
now how can I define the exponents, parameters inside the loop? As they are stored in cell array ? At each run I have set of models and I need to choose the best one and work with it choosing the best on depending on the CoD like rsquare
Then I should implement your code with best model please see the attached files to have clear picture.
many thanks
Walter Roberson
2015-6-29
To use this code:
call it with the first parameter being a cell array of strings that represent the variable names. The cell array must be exactly 3 elements long, and every entry in it must be a string that represents a variable. Do not pass in the cell array that is in your variables.png which has empty elements in locations 4, 5, and 6. You were insistent that there were exactly 3 variables, so this code will error if there are not exactly 3 variables.
For the second parameter, pass in the vector of numeric "a" values that you want to use. It does not matter whether you pass them as a row or column vector. The code will assume that the length of "a" is the same as the number of rows to use out of the exponent matrix.
For the third parameter, pass in the array of numeric "e" values that you want to use. The array must have exactly 3 columns (columns can contain 0's), and there must be as many rows in the array as there are elements in the vector "a" that you pass in.
The result of the function is a symbolic expression in variable names that match the strings you passed in as the cell array of strings.
If you have a number of different models to experiment with, then call this routine a number of times in a loop, passing in specific numeric arrays.
For example:
%prepare data
cell_of_cell_of_vars = {{'X1' 'X2' 'X3'},{'X17' 'X2' 'X9'}, {'X1' 'X2' 'X3'}, {'X2' 'X9' 'X3'});
for K = 1 : length(cell_of_cell_of_vars)
numterms = randi(8);
cell_of_a_vectors = rand(numterms,1);
cell_of_e_arrays = rand(numterms,3);
end
%generate expressions
for K = 1 : length(cell_of_cell_of_vars)
this_vars = cell_of_cell_of_vars{K};
this_a = cell_of_a_vectors{K};
this_e = cell_of_e_arrays{K};
formulae(K) = generateFormula(this_vars, this_a, this_e);
displayableform{K} = char(formulae(K));
formj{K} = jacobian([formulae(K)], this_vars);
end
Now formulae would be a vector of 4 symbolic expressions, and formj would be a cell array of their jacobians with respect to all of the variables. displayableform would be a cell array of strings containing the printable versions of the formula.
ND
2015-6-29
编辑:ND
2015-6-29
Unfortunately, I can not understand this code what do X17,X9,.. mean? I am really confused I have just three variables need to build the equation .( X1, X2) Like x,y For example: this is with two variables
variables X1, X2 0 0 0 0
exponent =[0 1 0 0 0 0 ; .5 0 0 0 0 0]
parameter = [105 ; 195 ; 0 ]
F = 105* X1^0 * X2^1 + 195 X1^.5 X2^0
x^0 =1 ,
F = 105 * X2 ^1 +195 * X1 ^.5 +0
Walter Roberson
2015-6-29
You have been writing
variables written in cell array(1x3) such as 'X1' 'X2' 'X3'
Not that the variables are those three, but rather that those are examples of what the variable names can be. You have always specified that the names of the variables are given by a cell array. That means that the names of the variables have been data, not fixed!
Here:
function form = generateFormula(a, e)
syms X1 X2 X3
form = 0;
for k = 1 : length(a)
form = form + a(k) * X1^e(k,1) * X2^e(k,2) * X3^e(k,3);
end
end
and the test code:
%prepare data
numtests = 4;
for K = 1 : numtests
numterms = randi(8);
cell_of_a_vectors = randn(numterms,1);
cell_of_e_arrays = randn(numterms,3);
end
%generate expressions
for K = 1 : numtests
this_a = cell_of_a_vectors{K};
this_e = cell_of_e_arrays{K};
formulae(K) = generateFormula(this_a, this_e);
displayableform{K} = char(formulae(K));
formj{K} = jacobian([formulae(K)], symvar(formulae(K)));
end
ND
2015-6-30
编辑:ND
2015-6-30
Please in this code how can I define (a,e) , I have them in workspace and they have not been defined in the code??
Why you use syms? If we build the model as a string then getting jacobian would be easy in matlab using function (jacobian) after syms ..variables X1,X2..
Such as this:
syms x y z
jacobian(2*x + 3*y + 4*z, [x, y, z])
Walter Roberson
2015-6-30
function form = generateFormula(a, e)
form = '';
for k = 1 : length(a)
thispart = sprintf('%g*X1^%g*X2^%g*X3^%g+', a(k), e(k,1), e(k,2), e(k,3));
form = [form thispart];
end
form(end) = []; %remove extra '+'
end
and the test code
%generate expression
%Use the "a" and "e" that are in your workspace!
formula = generateFormula(a, e) %it returns a string now!
I am done. I am not going to answer any more questions on this topic. Do not email me about it.
You now have the code to create the string that you wanted, and what you do with it is your problem.
ND
2015-7-1
Many thanks Walter for all help and I am very sorry for that you are right I should use the code that result symbolic expression . Please delete the last your comment
Many thanks
更多回答(1 个)
Thorsten
2015-6-29
编辑:Thorsten
2015-6-29
If X take some values and you make sure that the e and p parameters are in the order of pairs, e.g., for N = 3
1 2
1 3
2 3
You can use the following code:
e = [0.5 -.5; 0.5 -0.5; 1 0.5];
p = [.55 0.25 0.6893];
X = [345 3 27]; % array of number
% code below should work for arbitrary number N of X values,
% as long as e is N x 2 and p is 1 x N:
N = numel(p);
pairs = nchoosek(1:N, 2);
F = 0;
for i=1:N
F = p(i)*X(pairs(i,1))^e(i,1)*X(pairs(i,2))^e(i,2);
end
3 个评论
Thorsten
2015-6-29
Ok, then it is straightforward
F = p(1)*X(2)^e(1,1)*X(3)^e(1,2) + ... p(2)*X(1)^e(2,1)*X(3)^e(2,2) + ... p(3)*X(2)^e(3,1)*X(3)^e(3,2);
Walter Roberson
2015-6-29
The variables are strings, Thorsten, and the number of terms (the p values) is variable.
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!发生错误
由于页面发生更改,无法完成操作。请重新加载页面以查看其更新后的状态。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
亚太
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)