Documentation |
This topic shows you how to solve a system of equations symbolically using Symbolic Math Toolbox™. This toolbox offers both numeric and symbolic equation solvers. For a comparison of numeric and symbolic solvers, see Select a Numeric or Symbolic Solver.
Suppose you have the system
$$\begin{array}{c}{x}^{2}{y}^{2}=0\\ x-\frac{y}{2}=\alpha ,\end{array}$$
and you want to solve for x and y. First, create the necessary symbolic objects.
syms x y alpha
There are several ways to address the output of solve. One way is to use a two-output call.
[solx,soly] = solve(x^2*y^2 == 0, x-y/2 == alpha)
The call returns the following.
solx = 0 alpha soly = -2*alpha 0
Modify the first equation to x^{2}y^{2} = 1. The new system has more solutions.
[solx,soly] = solve(x^2*y^2 == 1, x-y/2 == alpha)
Four distinct solutions are produced.
solx = alpha/2 - (alpha^2 - 2)^(1/2)/2 alpha/2 - (alpha^2 + 2)^(1/2)/2 alpha/2 + (alpha^2 - 2)^(1/2)/2 alpha/2 + (alpha^2 + 2)^(1/2)/2 soly = - alpha - (alpha^2 - 2)^(1/2) - alpha - (alpha^2 + 2)^(1/2) (alpha^2 - 2)^(1/2) - alpha (alpha^2 + 2)^(1/2) - alpha
Since you did not specify the dependent variables, solve uses symvar to determine the variables.
This way of assigning output from solve is quite successful for "small" systems. For instance, if you have a 10-by-10 system of equations, typing the following is both awkward and time consuming.
[x1,x2,x3,x4,x5,x6,x7,x8,x9,x10] = solve(...)
To circumvent this difficulty, solve can return a structure whose fields are the solutions. For example, solve the system of equations u^2 - v^2 = a^2, u + v = 1, a^2 - 2*a = 3.
syms u v a S = solve(u^2 - v^2 == a^2, u + v == 1, a^2 - 2*a == 3)
The solver returns its results enclosed in this structure.
S = a: [2x1 sym] u: [2x1 sym] v: [2x1 sym]
The solutions for a reside in the "a-field" of S.
S.a
ans = -1 3
Similar comments apply to the solutions for u and v. The structure S can now be manipulated by the field and index to access a particular portion of the solution. For example, to examine the second solution, you can use the following statement to extract the second component of each field.
s2 = [S.a(2), S.u(2), S.v(2)]
s2 = [ 3, 5, -4]
The following statement creates the solution matrix M whose rows comprise the distinct solutions of the system.
M = [S.a, S.u, S.v]
M = [ -1, 1, 0] [ 3, 5, -4]
Clear solx and soly for further use.
clear solx soly
Linear systems of equations can also be solved using matrix division. For example, solve this system.
clear u v x y syms u v x y eqns = [x + 2*y == u, 4*x + 5*y == v]; S = solve(eqns); sol = [S.x; S.y] [A,b] = equationsToMatrix(eqns,x,y); z = A\b
sol = (2*v)/3 - (5*u)/3 (4*u)/3 - v/3 z = (2*v)/3 - (5*u)/3 (4*u)/3 - v/3
Thus,sol and z produce the same solution, although the results are assigned to different variables.
solve does not automatically return all solutions of an equation. To return all solutions along with the parameters in the solution and the conditions on the solution, set the ReturnConditions option to true.
Consider the following system of equations:
$$\begin{array}{l}\mathrm{sin}\left(x\right)\text{}+\mathrm{cos}\left(y\right)=\frac{4}{5}\\ \mathrm{sin}\left(x\right)\mathrm{cos}\left(y\right)=\frac{1}{10}\end{array}$$
Visualize the system of equations using ezplot. To set the x-axis and y-axis values in terms of pi, get the axes handles using axes in a. Create the symbolic array S of the values -2*pi to 2*pi at intervals of pi/2. To set the ticks to S, use the XTick and YTick properties of a. To set the labels for the x-and y-axes, convert S to character strings. Use arrayfun to apply char to every element of S to return T. Set the XTickLabel and YTickLabel properties of a to T.
syms x y eqn1 = sin(x)+cos(y) == 4/5; eqn2 = sin(x)*cos(y) == 1/10; a = axes; h = ezplot(eqn1); h.LineColor = 'blue'; hold on grid on g = ezplot(eqn2); g.LineColor = 'magenta'; L = sym(-2*pi:pi/2:2*pi); a.XTick = double(L); a.YTick = double(L); M = arrayfun(@char, L, 'UniformOutput', false); a.XTickLabel = M; a.YTickLabel = M; title('Plot of System of Equations') legend('sin(x)+cos(y) == 4/5','sin(x)*cos(y) == 1/10', 'Location', 'best')
The solutions lie at the intersection of the two plots. This shows the system has repeated, periodic solutions. To solve this system of equations for the full solution set, use solve and set the ReturnConditions option to true.
S = solve(eqn1, eqn2, 'ReturnConditions', true)
S = x: [2x1 sym] y: [2x1 sym] parameters: [1x2 sym] conditions: [2x1 sym]
solve returns a structure S with the fields S.x for the solution to x, S.y for the solution to y, S.parameters for the parameters in the solution, and S.conditions for the conditions on the solution. Elements of the same index in S.x, S.y, and S.conditions form a solution. Thus, S.x(1), S.y(1), and S.conditions(1) form one solution to the system of equations. The parameters in S.parameters can appear in all solutions.
Index into S to return the solutions, parameters, and conditions.
S.x S.y S.parameters S.conditions
ans = z z ans = z1 z1 ans = [ z, z1] ans = (in((z - asin(6^(1/2)/10 + 2/5))/(2*pi), 'integer') |... in((z - pi + asin(6^(1/2)/10 + 2/5))/(2*pi), 'integer')) &... (in((z1 - acos(2/5 - 6^(1/2)/10))/(2*pi), 'integer') |... in((z1 + acos(2/5 - 6^(1/2)/10))/(2*pi), 'integer')) (in((z - asin(2/5 - 6^(1/2)/10))/(2*pi), 'integer') |... in((z - pi + asin(2/5 - 6^(1/2)/10))/(2*pi), 'integer')) &... (in((z1 - acos(6^(1/2)/10 + 2/5))/(2*pi), 'integer') |... in((z1 + acos(6^(1/2)/10 + 2/5))/(2*pi), 'integer'))
To solve the system of equations under conditions, specify the conditions in the input to solve.
Solve the system of equations considered above for x and y in the interval -2*pi to 2*pi. Overlay the solutions on the plot using scatter.
Srange = solve(eqn1, eqn2, -2*pi<x, x<2*pi, -2*pi<y, y<2*pi, 'ReturnConditions', true);
scatter(Srange.x, Srange.y)
You can use the solutions, parameters, and conditions returned by solve to find solutions within an interval or under additional conditions. This section has the same goal as the previous section, to solve the system of equations within a search range, but with a different approach. Instead of placing conditions directly, it shows how to work with the parameters and conditions returned by solve.
For the full solution S of the system of equations, find values of x and y in the interval -2*pi to 2*pi by solving the solutions S.x and S.y for the parameters S.parameters within that interval under the condition S.conditions.
Before solving for x and y in the interval, assume the conditions in S.conditions using assume so that the solutions returned satisfy the condition. Assume the conditions for the first solution.
assume(S.conditions(1))
Solve the first solution of x for the parameter z.
solz(1,:) = solve(S.x(1)>-2*pi, S.x(1)<2*pi, S.parameters(1))
solz = [ asin(6^(1/2)/10 + 2/5), pi - asin(6^(1/2)/10 + 2/5),... asin(6^(1/2)/10 + 2/5) - 2*pi, - pi - asin(6^(1/2)/10 + 2/5)]
Similarly, solve the first solution to y for z1.
solz1(1,:) = solve(S.y(1)>-2*pi, S.y(1)<2*pi, S.parameters(2))
solz1 = [ acos(2/5 - 6^(1/2)/10), acos(2/5 - 6^(1/2)/10) - 2*pi,... -acos(2/5 - 6^(1/2)/10), 2*pi - acos(2/5 - 6^(1/2)/10)]
Clear the assumptions set by S.conditions(1) using sym. Call asumptions to check that the assumptions are cleared.
sym(S.parameters,'clear') assumptions
ans = [ z, z1] ans = Empty sym: 1-by-0
Assume the conditions for the second solution.
assume(S.conditions(2))
Solve the second solution to x and y for the parameters z and z1.
solz(2,:) = solve(S.x(2)>-2*pi, S.x(2)<2*pi, S.parameters(1)) solz1(2,:) = solve(S.y(2)>-2*pi, S.y(2)<2*pi, S.parameters(2))
solz = [ asin(6^(1/2)/10 + 2/5), pi - asin(6^(1/2)/10 + 2/5),... asin(6^(1/2)/10 + 2/5) - 2*pi, - pi - asin(6^(1/2)/10 + 2/5)] [ asin(2/5 - 6^(1/2)/10), pi - asin(2/5 - 6^(1/2)/10),... asin(2/5 - 6^(1/2)/10) - 2*pi, - pi - asin(2/5 - 6^(1/2)/10)] solz1 = [ acos(2/5 - 6^(1/2)/10), acos(2/5 - 6^(1/2)/10) - 2*pi,... -acos(2/5 - 6^(1/2)/10), 2*pi - acos(2/5 - 6^(1/2)/10)] [ acos(6^(1/2)/10 + 2/5), acos(6^(1/2)/10 + 2/5) - 2*pi,... -acos(6^(1/2)/10 + 2/5), 2*pi - acos(6^(1/2)/10 + 2/5)]
The first rows of solz and solz1 form the first solution to the system of equations, and the second rows form the second solution.
To find the values of x and y for these values of z and z1, use subs to substitute for z and z1 in S.x and S.y.
solx(1,:) = subs(S.x(1), S.parameters(1), solz(1,:)); solx(2,:) = subs(S.x(2), S.parameters(1), solz(2,:)) soly(1,:) = subs(S.y(1), S.parameters(2), solz1(1,:)); soly(2,:) = subs(S.y(2), S.parameters(2), solz1(2,:))
solx = [ asin(6^(1/2)/10 + 2/5), pi - asin(6^(1/2)/10 + 2/5),... asin(6^(1/2)/10 + 2/5) - 2*pi, - pi - asin(6^(1/2)/10 + 2/5)] [ asin(2/5 - 6^(1/2)/10), pi - asin(2/5 - 6^(1/2)/10),... asin(2/5 - 6^(1/2)/10) - 2*pi, - pi - asin(2/5 - 6^(1/2)/10)] soly = [ acos(2/5 - 6^(1/2)/10), acos(2/5 - 6^(1/2)/10) - 2*pi,... -acos(2/5 - 6^(1/2)/10), 2*pi - acos(2/5 - 6^(1/2)/10)] [ acos(6^(1/2)/10 + 2/5), acos(6^(1/2)/10 + 2/5) - 2*pi,... -acos(6^(1/2)/10 + 2/5), 2*pi - acos(6^(1/2)/10 + 2/5)]
Note that solx and soly are the two sets of solutions to x and to y. The full sets of solutions to the system of equations are the two sets of points formed by all possible combinations of the values in solx and soly.
Plot these two sets of points using scatter. Overlay them on the plot of the equations. As expected, the solutions appear at the intersection of the plots of the two equations.
for i = 1:length(solx(1,:)) for j = 1:length(soly(1,:)) scatter(solx(1,i), soly(1,j), 'black') scatter(solx(2,i), soly(2,j), 'black') end end
Symbolic calculations provide exact accuracy, while numeric calculations are approximations. Despite this loss of accuracy, you might need to convert symbolic results to numeric approximations for use in numeric calculations. For a high-accuracy conversion, use variable-precision arithmetic provided by the vpa function. For standard accuracy and better performance, convert to double precision using double.
Use vpa to convert the symbolic solutions solx and soly to numeric form.
vpa(solx) vpa(soly)
ans = [ 0.70095651347102524787213653614929, 2.4406361401187679905905068471302,... -5.5822287937085612290531502304097, -3.8425491670608184863347799194288] [ 0.15567910349205249963259154265761, 2.9859135500977407388300518406219,... -6.1275062036875339772926952239014, -3.2972717570818457380952349259371] ans = [ 1.4151172233028441195987301489821, -4.8680680838767423573265566175769,... -1.4151172233028441195987301489821, 4.8680680838767423573265566175769] [ 0.86983981332387137135918515549046, -5.4133454938557151055661016110685,... -0.86983981332387137135918515549046, 5.4133454938557151055661016110685]
If results look complicated, solve is stuck, or if you want to improve performance, see, Resolve Complicated Solutions or Stuck Solver.