sprintf loop for writing equations

7 vues (au cours des 30 derniers jours)
anto
anto le 24 Déc 2022
Modifié(e) : Karim le 24 Déc 2022
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.

Réponse acceptée

Karim
Karim le 24 Déc 2022
Modifié(e) : Karim le 24 Déc 2022
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:
  1. a part that shows how to generate equations as strings and store them in an array
  2. a part that shows how to solve equations in a loop using fsolve
  3. a part that generates a set of equations, writes a .m function file and solves the set of equations using fsolve
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
F = 10×1 string array
"-2.984+2*x(1)*0.61576*(0.37184)^2*(cos(x(2))*cos(1.3829)+sin(x(2))*sin(1.3829))" "-4.2453+2*x(1)*0.87604*(0.37184)^2*(cos(x(2))*cos(1.0114)+sin(x(2))*sin(1.0114))" "-1.3785+2*x(1)*0.28447*(0.37184)^2*(cos(x(2))*cos(0.0078137)+sin(x(2))*sin(0.0078137))" "-1.3535+2*x(1)*0.27931*(0.37184)^2*(cos(x(2))*cos(0.38969)+sin(x(2))*sin(0.38969))" "-1.8807+2*x(1)*0.38809*(0.37184)^2*(cos(x(2))*cos(-0.91443)+sin(x(2))*sin(-0.91443))" "-1.1394+2*x(1)*0.23512*(0.37184)^2*(cos(x(2))*cos(-1.5697)+sin(x(2))*sin(-1.5697))" "-3.2934+2*x(1)*0.67962*(0.37184)^2*(cos(x(2))*cos(0.93812)+sin(x(2))*sin(0.93812))" "-2.2544+2*x(1)*0.4652*(0.37184)^2*(cos(x(2))*cos(-1.0979)+sin(x(2))*sin(-1.0979))" "-2.3893+2*x(1)*0.49305*(0.37184)^2*(cos(x(2))*cos(-0.078948)+sin(x(2))*sin(-0.078948))" "-0.96395+2*x(1)*0.19892*(0.37184)^2*(cos(x(2))*cos(-1.1029)+sin(x(2))*sin(-1.1029))"
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
F_eqn = 10×1 cell array
{ @(x)-2.984+2*x(1)*0.61576*(0.37184)^2*(cos(x(2))*cos(1.3829)+sin(x(2))*sin(1.3829))} { @(x)-4.2453+2*x(1)*0.87604*(0.37184)^2*(cos(x(2))*cos(1.0114)+sin(x(2))*sin(1.0114))} {@(x)-1.3785+2*x(1)*0.28447*(0.37184)^2*(cos(x(2))*cos(0.0078137)+sin(x(2))*sin(0.0078137))} { @(x)-1.3535+2*x(1)*0.27931*(0.37184)^2*(cos(x(2))*cos(0.38969)+sin(x(2))*sin(0.38969))} { @(x)-1.8807+2*x(1)*0.38809*(0.37184)^2*(cos(x(2))*cos(-0.91443)+sin(x(2))*sin(-0.91443))} { @(x)-1.1394+2*x(1)*0.23512*(0.37184)^2*(cos(x(2))*cos(-1.5697)+sin(x(2))*sin(-1.5697))} { @(x)-3.2934+2*x(1)*0.67962*(0.37184)^2*(cos(x(2))*cos(0.93812)+sin(x(2))*sin(0.93812))} { @(x)-2.2544+2*x(1)*0.4652*(0.37184)^2*(cos(x(2))*cos(-1.0979)+sin(x(2))*sin(-1.0979))} {@(x)-2.3893+2*x(1)*0.49305*(0.37184)^2*(cos(x(2))*cos(-0.078948)+sin(x(2))*sin(-0.078948))} { @(x)-0.96395+2*x(1)*0.19892*(0.37184)^2*(cos(x(2))*cos(-1.1029)+sin(x(2))*sin(-1.1029))}
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)
my_sol = -1.3312
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
Equation solved. fsolve completed because the vector of function values is near zero as measured by the value of the function tolerance, and the problem appears regular as measured by the gradient. Equation solved, solver stalled. fsolve stopped because the relative size of the current step is less than the value of the step size tolerance and the vector of function values is near zero as measured by the value of the function tolerance. Equation solved, solver stalled. fsolve stopped because the relative size of the current step is less than the value of the step size tolerance and the vector of function values is near zero as measured by the value of the function tolerance. Equation solved, solver stalled. fsolve stopped because the relative size of the current step is less than the value of the step size tolerance and the vector of function values is near zero as measured by the value of the function tolerance. Equation solved, solver stalled. fsolve stopped because the relative size of the current step is less than the value of the step size tolerance and the vector of function values is near zero as measured by the value of the function tolerance. Equation solved, solver stalled. fsolve stopped because the relative size of the current step is less than the value of the step size tolerance and the vector of function values is near zero as measured by the value of the function tolerance. Equation solved, solver stalled. fsolve stopped because the relative size of the current step is less than the value of the step size tolerance and the vector of function values is near zero as measured by the value of the function tolerance. Equation solved. fsolve completed because the vector of function values is near zero as measured by the value of the function tolerance, and the problem appears regular as measured by the gradient. Equation solved. fsolve completed because the vector of function values is near zero as measured by the value of the function tolerance, and the problem appears regular as measured by the gradient. Equation solved, solver stalled. fsolve stopped because the relative size of the current step is less than the value of the step size tolerance and the vector of function values is near zero as measured by the value of the function tolerance.
% have a look at the solutions
x
x = 10×2
17.5260 1.3959 20.5908 0.4586 17.5238 0.0098 17.5239 0.3926 17.5246 -0.9101 17.7378 -1.7250 17.5272 0.9194 17.5296 -1.1218 17.5244 -0.0838 17.5282 -13.6474
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')
ans = 9×1 string array
"function F = MyFun(x)" "F(1) = 0.0001355713+2*x(1)*0.6289681511*((0.0021272263)^2)*(cos(x(2))*cos(-1.4212924022)+sin(x(2))*sin(-1.4212924022)); " "F(2) = -0.0002454104+2*x(1)*0.6859337445*((0.0021272263)^2)*(cos(x(2))*cos(0.9784759962)+sin(x(2))*sin(0.9784759962)); " "F(3) = -0.0000153713+2*x(1)*0.7937716818*((0.0021272263)^2)*(cos(x(2))*cos(-0.7318806436)+sin(x(2))*sin(-0.7318806436)); " "F(4) = -0.0001721548+2*x(1)*0.6096992363*((0.0021272263)^2)*(cos(x(2))*cos(0.1038194500)+sin(x(2))*sin(0.1038194500)); " "F(5) = -0.0000285549+2*x(1)*0.0901234429*((0.0021272263)^2)*(cos(x(2))*cos(0.2706851873)+sin(x(2))*sin(0.2706851873)); " "F(6) = -0.0000206362+2*x(1)*0.1328397671*((0.0021272263)^2)*(cos(x(2))*cos(-0.3425049394)+sin(x(2))*sin(-0.3425049394)); " "end" ""
% 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);
Equation solved, solver stalled. fsolve stopped because the relative size of the current step is less than the value of the step size tolerance and the vector of function values is near zero as measured by the value of the function tolerance.
% display the solution
x
x = 1×2
40.2203 7.0686
  2 commentaires
anto
anto le 24 Déc 2022
Thanks for your answer, it works. But it's strange because the code in this way works, but if i add "V_AB(i)" in the definition of Dtau(i) it gives the error:
Error using inlineeval
Error in inline expression ==>
-0--0-0+00+0.2..2.0*00*00x00x00(00(02122125)55)56*77*69088091.44.1+7++7+202202*7**7*x1xx1x(1((1(1*11*1)())()*0**0*1.00.1*0..0*(0770(020020.1771.02112007117022**221)(()12^00^272..272*00*2)(00()^c22c^2o11o2*s22s*((77((cx22xco())(os2^^2s()22)(x)**)x(*((*(2cccc2)oooo))ssss)*((((*c-xx-co0((0os.22.s(7))7(18))80.5**5)54cc4+7)oo)s0+ss+i8s((sn)i00i(+n..nxs(77((ix88x2n(55()(2442)x))))*()++)s2*ss*i)siisn)inni(*n((n0s(xx()i-((-)n0220
(.)). 17))7 .8**8 55ss5 74ii4 0)nn) 8)(() ) 00 ) .. 77 88 55 44 )) ))
Invalid use of operator.
the code is equal to yours but i only added V_AB(i)
T_media_vera=550; %[K]
CL_VERA=(k*R_gas*T_media_vera)^0.5;
Unrecognized function or variable 'k'.
%definining constants
s=1/CL_VERA;
V_vera=40; %[m/s]
Beta_vero=pi/4; %[rad]
%writing equations
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))));;
%
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)))
F(i) = 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
%converting for fsolve
F_mat=str2mat(F)
%solving with fsolve
problem.objective = F_mat;
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 = fsolve(problem)
Do you know why?
Karim
Karim le 24 Déc 2022
Modifié(e) : Karim le 24 Déc 2022
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
F_eqn = 6×1 cell array
{ @(x)0.00011633+2*x(1)*0.87482*(0.0021272)^2*(cos(x(2))*cos(-1.1611)+sin(x(2))*sin(-1.1611))} {@(x)-9.5032e-06+2*x(1)*0.093632*(0.0021272)^2*(cos(x(2))*cos(-0.50139)+sin(x(2))*sin(-0.50139))} { @(x)-0.0001617+2*x(1)*0.60075*(0.0021272)^2*(cos(x(2))*cos(1.5223)+sin(x(2))*sin(1.5223))} { @(x)-0.00014033+2*x(1)*0.44659*(0.0021272)^2*(cos(x(2))*cos(1.3143)+sin(x(2))*sin(1.3143))} { @(x)-0.00034351+2*x(1)*0.94886*(0.0021272)^2*(cos(x(2))*cos(0.66616)+sin(x(2))*sin(0.66616))} { @(x)3.7641e-05+2*x(1)*0.44527*(0.0021272)^2*(cos(x(2))*cos(-1.021)+sin(x(2))*sin(-1.021))}
% 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
Warning: Trust-region-dogleg algorithm of FSOLVE cannot handle non-square systems; using Levenberg-Marquardt algorithm instead.
Equation solved. fsolve completed because the vector of function values is near zero as measured by the value of the function tolerance, and the problem appears regular as measured by the gradient.
Warning: Trust-region-dogleg algorithm of FSOLVE cannot handle non-square systems; using Levenberg-Marquardt algorithm instead.
Equation solved. fsolve completed because the vector of function values is near zero as measured by the value of the function tolerance, and the problem appears regular as measured by the gradient.
Warning: Trust-region-dogleg algorithm of FSOLVE cannot handle non-square systems; using Levenberg-Marquardt algorithm instead.
Solver stopped prematurely. fsolve stopped because it exceeded the function evaluation limit, options.MaxFunctionEvaluations = 3.000000e+02.
Warning: Trust-region-dogleg algorithm of FSOLVE cannot handle non-square systems; using Levenberg-Marquardt algorithm instead.
Solver stopped prematurely. fsolve stopped because it exceeded the function evaluation limit, options.MaxFunctionEvaluations = 3.000000e+02.
Warning: Trust-region-dogleg algorithm of FSOLVE cannot handle non-square systems; using Levenberg-Marquardt algorithm instead.
Solver stopped prematurely. fsolve stopped because it exceeded the function evaluation limit, options.MaxFunctionEvaluations = 3.000000e+02.
Warning: Trust-region-dogleg algorithm of FSOLVE cannot handle non-square systems; using Levenberg-Marquardt algorithm instead.
Equation solved. fsolve completed because the vector of function values is near zero as measured by the value of the function tolerance, and the problem appears regular as measured by the gradient.
% have a look at the solutions
x
x = 6×2
-14.6936 -1.1596 11.2150 -0.4987 20.7481 1.5397 23.5239 13.8528 21.0971 7.0352 -9.3463 -0.9873

Connectez-vous pour commenter.

Plus de réponses (1)

Jan
Jan le 24 Déc 2022
F{i} = sprintf(formatSpec,Dtau(i),l(i),s,alpha_1(i),alpha_1(i));
%^ ^ Curly braces for a cell string

Catégories

En savoir plus sur Mathematics dans Help Center et File Exchange

Produits


Version

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by