Documentation |
On this page… |
---|
Solve Polynomial Equations and Systems |
There are two methods to get numeric approximations of the solutions:
Solve equations symbolically and approximate the obtained symbolic results numerically. Using this method, you get numeric approximations of all the solutions found by the symbolic solver. If the symbolic solver fails to find any solutions, MuPAD^{®} calls the numeric solver directly. For nonpolynomial equations, the numeric solver returns only one solution. Using the symbolic solver and post-processing its results method requires more time than a purely numeric solver and can significantly decrease performance.
Solve equations using numeric methods from the beginning. This method is faster, but for nonpolynomial equations the numeric solver returns only the first solution it finds. You can use the AllRealRoots option to make the solver look for other real roots. Even with this option, the solution set can be incomplete. Using AllRealRoots can significantly decrease performance.
When you solve an equation symbolically, the solver does not always return results in an explicit form. For example, the solver can represent solutions using RootOf:
solve(x^3 + x + 1, x)
If you have a symbolic solution that you want to approximate numerically, use the float command:
float(%)
Use float to approximate the solutions of the symbolic system:
float(solve([x^3 + x^2 + 2*x = y, y^2 = x^2], [x, y]))
Approximating symbolic solutions numerically, you get the complete set of solutions. For example, solve the following equation symbolically:
S := solve(sin(x^2) = 1/2, x)
Suppose, you want to get numeric results instead of expressions containing PI. The float command returns the infinite solution set:
float(S)
To avoid getting symbolic solutions and to proceed with numeric methods, use the numeric::solve command. If an equation is not polynomial, the numeric solver returns only one solution:
numeric::solve(sin(x^2) = 1/2, x)
For polynomial equations, the numeric solver returns all solutions:
numeric::solve(4*x^4 + 3*x^3 + 2*x^2 + x + 5 = 0, x)
When called with the option AllRealRoots, the solver omits all complex roots. For example, when you symbolically solve the polynomial equation and approximate the solutions, you get all solutions:
numeric::solve(4*x^4 + 3*x^3 + 2*x^2 + x -1 = 0, x)
To limit the solution set to the real solutions only, use the option AllRealRoots:
numeric::solve(4*x^4 + 3*x^3 + 2*x^2 + x - 1 = 0, x, AllRealRoots)
Using numeric::solve, you also can solve a system of polynomial equations:
numeric::solve([x^3 + 2*x = y, y^2 = x], [x, y])
To solve linear systems numerically, use the numeric::linsolve command. For example, solve the following system symbolically and numerically:
linsolve([x = y - 1, x + y = 5/2], [x, y]); numeric::linsolve([x = y - 1, x + y = 5/2], [x, y])
For nonpolynomial equations, there is no general method of finding all the solutions numerically. When you solve a nonpolynomial equation or a system numerically, and the solutions exist, the solver returns only one solution:
numeric::solve(sin(1/x) = x, x)
This equation obviously has more than one solution:
plot(sin(1/x), x, x = -1..1)
To get more real solutions of a single equation containing one variable, call the numeric solver with the option AllRealRoots. The AllRealRoots option does not guarantee that the solver finds all existing real roots. For example, the option helps to find additional solutions for the equation:
numeric::solve(sin(1/x) = x, x, AllRealRoots)
Warning: Problem in isolating search intervals. Some roots might be lost. [numeric::allRealRoots]
For a system of nonpolynomial equation, the solver also returns only one solution. Plotting the equations, you see that the system has more than one solution:
numeric::solve([sin(x) = y^2 - 1, cos(x) = y], [x, y]); plot(sin(x) = y^2 - 1, cos(x) = y)
The AllRealRoots option does not work for systems:
numeric::solve([sin(x) = y^2 - 1, cos(x) = y], [x, y], AllRealRoots)
Error: Only one equation is allowed with the 'AllRealRoots' option. [numeric::solve]
To find numerical approximations of other solutions, specify intervals that contain the solutions. You can use the command numeric::solve that internally calls numeric::fsolve. However, to speed up your calculations, call numeric::fsolve directly. Note that numeric::solve returns a set of solutions, and numeric::fsolve returns a list:
numeric::solve([sin(x) = y^2 - 1, cos(x) = y], [x = 2.5..3.5, y = -1.5..-0.5]); numeric::fsolve([sin(x) = y^2 - 1, cos(x) = y], [x = 4..5, y = -0.2..0.2])
The MultiSolutions option also serves to find more than one numeric approximation. Without this option, the numeric solver looks for a solution inside the specified interval and disregards any solutions it finds outside of the interval. When the solver finds the first solution inside the interval, it stops and does not look for other solutions. If you use MultiSolutions, the solver returns the solutions found outside of a specified interval.
Note: If you use the option MultiSolutions and do not specify any interval, the numeric solver returns only the first solution it finds. |
With the MultiSolutions option, the solver also stops after it finds the first solution inside the specified interval. For example, find several numeric approximations for the following system:
eqs := [x*sin(10*x) = y^3, y^2 = exp(-2*x/3)]: plot(x*sin(10*x) = y^3, y^2 = exp(-2*x/3))
Specify the interval where you want to search for the solutions. For example, consider the interval x = 0..1 that contains two solutions:
plot(x*sin(10*x) = y^3, y^2 = exp(-2*x/3), x = 0..1, y = 0..1)
Call the numeric::solve or numeric::fsolve command with the MultiSolutions option. Both solvers return one solution that belongs to the specified interval and one solution outside of the interval:
numeric::fsolve(eqs, [x = 0..1, y = 0..1], MultiSolutions); numeric::solve(eqs, [x = 0..1, y = 0..1], MultiSolutions)
Specifying the interval that does not contain any solutions can help you find more approximations. In this case, the solver cannot find the solution inside the interval and continues searching. Before the solver quits, it can find many solutions outside the specified interval:
numeric::fsolve(eqs, [x = -10..0, y = 0..1], MultiSolutions)
If you know an interval containing the solutions of a polynomial equation, you can significantly speed up numeric approximations. To find one solution inside a specified interval, use the numeric::realroot command. The command returns real solutions and omits the complex ones:
numeric::realroot(1/4*x^4 + x^3 + x + 1 = 0, x = -5..0)
You also can specify an interval and search for all subintervals that can contain real roots. The numeric::realroots command returns a complete list of such subintervals:
numeric::realroots(1/4*x^4 + x^3 + x + 1 = 0, x = -5..0)
If the equation you solve is polynomial, each subinterval contains exactly one root. For nonpolynomial equations, numeric::realroots can return subintervals that do not contain any roots. numeric::realroots guarantees that the search interval does not contain any real roots outside the returned subintervals.
There is no general way to solve an arbitrary second- or higher-order ordinary differential equation (ODE). Often, such an equation does not have a symbolic solution. In some cases, the solution exists, but it can be presented only by special functions. For example, the solution of the following second-order ODE includes the error function erf:
o:=ode({y''(t) = t*y'(t), y(0) = 0, y'(0) = 1/3}, y(t)): ode::solve(o)
Suppose, you do not need an exact symbolic solution, but you want to approximate the solution for several values of the parameter t. For numeric approximations of the solutions of ODEs, MuPAD provides two functions:
numeric::odesolve returns a numeric approximation of the solution at a particular point.
numeric::odesolve2 returns a function representing a numeric approximation of the solution.
Both functions accept either a first-order ODE or a system of first-order ODEs. To solve a higher-order equation, convert it to a system of the first-order equations. For example, represent the second-order ODE you solved symbolically as a system of two first-order equations: . The solution vector for this system is Y = [y, z].
The function numeric::odesolve requires the system of first-order ODEs (dynamic system) to be represented by a procedure:
f := proc(t, Y) begin [Y[2], t*Y[2]] end_proc
The second parameter of numeric::odesolve is the range over which you want to solve an ODE. The third parameter is a list of initial conditions ( ). Approximate the solutions y(t) for t = 1, t = 3, and :
numeric::odesolve(f, 0..1, [0, 1/3]); numeric::odesolve(f, 0..3, [0, 1/3]); numeric::odesolve(f, 0..1/127, [0, 1/3])
MuPAD also offers an alternate way to generate parameters for the ODE numeric solvers:
Define your initial value problem as a list or a set:
IVP := {y''(t) = t*y'(t), y(0) = 0, y'(0) = 1/3}:
Define a set of fields over which you want to get a solution:
fields := [y(t), y'(t)]:
Convert the initial value problem and the fields into a procedure acceptable by numeric::odesolve. The function numeric::ode2vectorfield generates the required procedure:
[ODE, t0, Y0] := [numeric::ode2vectorfield(IVP, fields)]
Now call numeric::odesolve to approximate the solution at particular values of t:
numeric::odesolve(ODE, t0..1, Y0)
The function numeric::odesolve2 also requires the system of first-order ODEs (dynamic system) to be represented by a procedure. To generate parameters for numeric::odesolve2, use the following steps:
Define your initial value problem as a list or a set:
IVP := {y''(t) = t*y'(t), y(0) = 0, y'(0) = 1/3}:
Define a set of fields over which you want to get a solution:
fields := [y(t), y'(t)]:
Convert the initial value problem and the fields into a procedure acceptable by numeric::odesolve2. The function numeric::ode2vectorfield generates the required procedure:
ODE := numeric::ode2vectorfield(IVP, fields)
Now call numeric::odesolve2 to approximate the solution:
numApprox := numeric::odesolve2(ODE)
Using the function generated by numeric::odesolve2, find the numeric approximation at any point. For example, find the numeric solutions for the values t = 1, t = 3, and . You get the same results as with numeric::odesolve, but the syntax is shorter:
numApprox(1); numApprox(3); numApprox(1/127)
Plot the numeric solution using the function generated by numeric::odesolve2. The function numApprox returns a list [y(t), y'(t)]. When plotting the solution y(t), use brackets to extract the first entry of the solution list:
plotfunc2d(numApprox(t)[1], t = 0..3)
Use numeric::odesolve2 to find numeric approximations for the following system of ODEs:
IVP := {x'(t) = -y(t) + x(t)^2, y'(t) = 10*x(t) - y(t)^2, x(0) = 1, y(0) = 1}: fields := [x(t), y(t)]: ODE := numeric::ode2vectorfield(IVP, fields): numApprox := numeric::odesolve2(ODE)
Plot the numeric solutions for x(t) and y(t) in one graph:
plotfunc2d(numApprox(t)[1], numApprox(t)[2], t = 0..20)
Use the plot::Curve2d plotting function to generate a parametric plot of the numeric solution:
curve := plot::Curve2d([numApprox(t)[1], numApprox(t)[2]], t = 0..20): plot(curve)
Alternatively, use plot::Ode2d or plot::Ode3d.