- a part that shows how to generate equations as strings and store them in an array
- a part that shows how to solve equations in a loop using fsolve
- a part that generates a set of equations, writes a .m function file and solves the set of equations using fsolve
sprintf loop for writing equations
7 ビュー (過去 30 日間)
古いコメントを表示
i would like to get matlab to write equations automatically which i would like to use in fsolve.
the equations which i would like to print are in this form:
Dtau(i)+2*x(1)*l(i)*(s(i)^2*(cos(x(2))*cos(alpha_1(i))+sin(x(2))*sin(alpha_1(i)))
I've been told to use the command fprintf, and i've done this, which properly prints the equations in a txt file.
FID = fopen('equations list.txt','w');
for i=1:length(p)
% lenghts
l(i)=((q(i,1)-p(i,1))^2+(q(i,2)-p(i,2))^2)^0.5;
% angles
alpha_1(i)=atan((q(i,2)-p(i,2))/((q(i,1)-p(i,1))));;
% times
tau_f(i)=l(i)/(V1+V2);
tau_b(i)=l(i)/(V1-V2);
Dtau(i)=tau_f(i)-tau_b(i);
formatSpec = '%.10f+2*x(1)*%.10f*(%.10f)^2*(cos(x(2))*cos(%.10f)+sin(x(2))*sin(%.10f)) \n';
F(i)=fprintf(formatSpec,Dtau(i),l(i),s,alpha_1(i),alpha_1(i));
end
but then i cannot import with all the commands avaliable from matlab which i looked at for several days (for example sequential use of importdata(file), transpose, and cell2mat insert those brace indexing ' at the end and the beginning which gets the array unusable in fsolve).
so i've been thinking about using sprintf like this
F(i)=sprintf(formatSpec,Dtau(i),l(i),s,alpha_1(i),alpha_1(i));
directly in my code to create the matrix directly without printing in an external file but i get the error "Unable to perform assignment because the left and right sides have a different number of elements" .
So my question is: does anybody know a way to use sprintf in a for loop to write the equations in a matrix with including those parameters?
Any help would be greatly appreciated.
0 件のコメント
採用された回答
Karim
2022 年 12 月 24 日
編集済み: Karim
2022 年 12 月 24 日
There is no need for the sprintf function, you can store the equations direclty into an string array. See below for an example.
For the reader just passing by, this has become quit a long answer :), the answer is made up of 3 sections:
Hope it helps!
% create random data for p, q, V1, V2 and s to create the equations
p = rand(10,2);
q = rand(10,2);
V1 = rand;
V2 = rand;
s = rand;
% create an empty string array
F = strings(length(p),1);
for i = 1:length(p)
% lenghts
l(i)=((q(i,1)-p(i,1))^2+(q(i,2)-p(i,2))^2)^0.5;
% angles
alpha_1(i)=atan((q(i,2)-p(i,2))/((q(i,1)-p(i,1))));;
% times
tau_f(i)=l(i)/(V1+V2);
tau_b(i)=l(i)/(V1-V2);
Dtau(i)=tau_f(i)-tau_b(i);
% assume equation in the form:
% Dtau(i)+2*x(1)*l(i)*(s(i)^2*(cos(x(2))*cos(alpha_1(i))+sin(x(2))*sin(alpha_1(i)))
F(i,1) = num2str( Dtau(i) ) + "+2*x(1)*" + ...
num2str( l(i) ) + "*(" + ...
num2str( s ) + ")^2*(cos(x(2))*cos(" + ...
num2str( alpha_1(i) ) + ")+sin(x(2))*sin(" + ...
num2str( alpha_1(i) ) + "))";
end
% show the content of F
F
While the above generates the strings for the equations you asked, i'm not certain if this is the best way forward. I would modify the strings a bit so that you can make functions out of them. You can to this by inserting @(x) in front of the string, and then use the str2fun function to convert the equation into a function. Which you can call with solve or something else. See below:
% create an empty cell array to store the equations
F_eqn = cell(length(p),1);
for i = 1:length(p)
% lenghts
l(i)=((q(i,1)-p(i,1))^2+(q(i,2)-p(i,2))^2)^0.5;
% angles
alpha_1(i)=atan((q(i,2)-p(i,2))/((q(i,1)-p(i,1))));;
% times
tau_f(i)=l(i)/(V1+V2);
tau_b(i)=l(i)/(V1-V2);
Dtau(i)=tau_f(i)-tau_b(i);
% assume equation in the form:
% Dtau(i)+2*x(1)*l(i)*(s(i)^2*(cos(x(2))*cos(alpha_1(i))+sin(x(2))*sin(alpha_1(i)))
% first create the string
F_str = "@(x) " + ...
num2str( Dtau(i) ) + "+2*x(1)*" + ...
num2str( l(i) ) + "*(" + ...
num2str( s ) + ")^2*(cos(x(2))*cos(" + ...
num2str( alpha_1(i) ) + ")+sin(x(2))*sin(" + ...
num2str( alpha_1(i) ) + "))";
% convert the string into a function, and store it in the cell array
F_eqn{i,1} = str2func( F_str );
end
F_eqn
No you can evaluate any one of the functions, as example:
% create test input
x_test = rand(2,1);
% pick a function from the list
F_test = F_eqn{3};
% evaluate the function
my_sol = F_test(x_test)
EDIT: i also added some code to demonstrate how to solve the equations with fsolve. Note that there are several warnings. Recal that the equations are generated with random input data.
% intitialize an array for the solutions
x = zeros(length(F_eqn),2);
% loop over the problems
for i = 1:length(F_eqn)
% solving with fsolve
problem.objective = F_eqn{i};
problem.x0 = [0,0];
problem.solver = 'fsolve';
% set tolerances
problem.options = optimoptions('fsolve',...
'TolX',1e-16,...
'TolFun',1e-16,...
'MaxIter',1000,...
'MaxFunEvals',300,...
'StepTolerance',1e-10, ...
'FunctionTolerance',1e-16,...
'OptimalityTolerance',1e-16,...
'Algorithm','levenberg-marquardt');
% solving
x(i,:) = fsolve(problem);
end
% have a look at the solutions
x
EDIT 2: perhaps the easiest method to solve all equations, considering how you are generating the equations, is to write a .m file (i.e. a function file) and call this function afterwards in with fsolve:
% constants
k=1.4;
R_gas=287;
T_media_vera=550; %[K]
CL_VERA=(k*R_gas*T_media_vera)^0.5;
s=1/CL_VERA;
V_vera=40; %[m/s]
Beta_vero=pi/4; %[rad]
p = rand(6,2);
q = rand(6,2);
% writing equations in a txt file:
FID = fopen('MyFun.m','w');
% first wirte the starting line
fprintf(FID,'function F = MyFun(x)\n');
for i = 1:length(p)
% lengths
l(i)=((q(i,1)-p(i,1))^2+(q(i,2)-p(i,2))^2)^0.5;
% angles
alpha_1(i)=atan((q(i,2)-p(i,2))/((q(i,1)-p(i,1))));
%velocity
V_AB(i)=V_vera*(cos(alpha_1(i))*cos(Beta_vero)+(sin(alpha_1(i))*sin(Beta_vero)));
% times
tau_f(i)=l(i)/(CL_VERA+(V_AB(i)));
tau_b(i)=l(i)/(CL_VERA-(V_AB(i)));
Dtau(i)=tau_f(i)-tau_b(i);
% printing
formatSpec = 'F(%i) = %.10f+2*x(1)*%.10f*((%.10f)^2)*(cos(x(2))*cos(%.10f)+sin(x(2))*sin(%.10f)); \n';
fprintf(FID,formatSpec,i,Dtau(i),l(i),s,alpha_1(i),alpha_1(i));
end
% write the 'end' section of the function
fprintf(FID,'end\n');
% close the file
fclose(FID);
% import the file as a text file just to display the result
readlines('MyFun.m')
% defining problem
problem.objective = @MyFun; % here just link to the function file we created
problem.x0 = [0,0];
problem.solver = 'fsolve';
% setting tolerances
problem.options = optimoptions('fsolve','MaxIter', ...
4000,'MaxFunEvals',4000,'StepTolerance',1e-16, ...
'FunctionTolerance',1e-16,'OptimalityTolerance',1e-10,...
'Algorithm','levenberg-marquardt');
% solving
x = fsolve(problem);
% display the solution
x
2 件のコメント
Karim
2022 年 12 月 24 日
編集済み: Karim
2022 年 12 月 24 日
Please note that you make it very hard to interpret and help...
CL_VERA=(k*R_gas*T_media_vera)^0.5;
What are: k, R_gas and T_media_vera... are these scalars/vectors/matrices...
EDIT: i found your constants in one of your other questions... and added them below
% guessing some variables...
p = rand(6,2);
q = rand(6,2);
k = 1.4;
R_gas = 287;
T_media_vera = 550; %[K]
% inputs provided by the OP
T_media_vera=550; %[K]
CL_VERA=(k*R_gas*T_media_vera)^0.5;
s = 1/CL_VERA;
V_vera=40; %[m/s]
Beta_vero=pi/4; %[rad]
% writing equations
F_eqn = cell(length(p),1);
for i = 1:length(p)
% lenghts
l(i)=((q(i,1)-p(i,1))^2+(q(i,2)-p(i,2))^2)^0.5;
% angles
alpha_1(i)=atan((q(i,2)-p(i,2))/((q(i,1)-p(i,1))));;
%
V_AB(i)=V_vera*(cos(alpha_1(i))*cos(Beta_vero)+(sin(alpha_1(i))*sin(Beta_vero)));
% times
tau_f(i)=l(i)/(CL_VERA+V_AB(i));
tau_b(i)=l(i)/(CL_VERA-V_AB(i));
Dtau(i)=tau_f(i)-tau_b(i);
% assume equation in the form:
% Dtau(i)+2*x(1)*l(i)*(s(i)^2*(cos(x(2))*cos(alpha_1(i))+sin(x(2))*sin(alpha_1(i)))
% first create the string
F_str = "@(x) " + ...
num2str( Dtau(i) ) + "+2*x(1)*" + ...
num2str( l(i) ) + "*(" + ...
num2str( s ) + ")^2*(cos(x(2))*cos(" + ...
num2str( alpha_1(i) ) + ")+sin(x(2))*sin(" + ...
num2str( alpha_1(i) ) + "))";
% convert the string into a function, and store it in the cell array
F_eqn{i,1} = str2func( F_str );
end
% look at equations
F_eqn
% intitialize an array for the solutions
x = zeros(length(F_eqn),2);
% loop over the problems
for i = 1:length(F_eqn)
% solving with fsolve
problem.objective = F_eqn{i};
problem.x0 = [0,0];
problem.solver = 'fsolve';
% set tolerances
problem.options = optimoptions('fsolve',...
'TolX',1e-16,...
'TolFun',1e-16,...
'MaxIter',1000,...
'MaxFunEvals',300,...
'StepTolerance',1e-10, ...
'FunctionTolerance',1e-16,...
'OptimalityTolerance',1e-16);
% solving
x(i,:) = fsolve(problem);
end
% have a look at the solutions
x
その他の回答 (1 件)
Jan
2022 年 12 月 24 日
F{i} = sprintf(formatSpec,Dtau(i),l(i),s,alpha_1(i),alpha_1(i));
%^ ^ Curly braces for a cell string
0 件のコメント
参考
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!