- 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

4 views (last 30 days)

Show older comments

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 Comments

### Accepted Answer

Karim
on 24 Dec 2022

Edited: Karim
on 24 Dec 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:

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 Comments

Karim
on 24 Dec 2022

Edited: Karim
on 24 Dec 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

% 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

### More Answers (1)

Jan
on 24 Dec 2022

F{i} = sprintf(formatSpec,Dtau(i),l(i),s,alpha_1(i),alpha_1(i));

%^ ^ Curly braces for a cell string

##### 0 Comments

### See Also

### Community Treasure Hunt

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

Start Hunting!