## `solve` -- solve equations and inequalities

#### Introduction

`solve``(eq, x)` returns the set of all complex solutions of an equation or inequality `eq` with respect to `x`.

`solve``(system, vars)` solves a system of equations for the variables `vars`.

`solve``(eq, vars)` is equivalent to `solve``([eq], vars)`.

`solve``(system, x)` is equivalent to `solve``(system, [x])`.

`solve``(eq)` without second argument is equivalent to `solve``(eq, S)` where `S` is the set of all indeterminates in `eq`. The same holds for `solve``(system)`.

#### Call(s)

`solve(eq, x <, options>)`
`solve(eq, vars <, options>)`
`solve(eq <, options>)`
`solve(system, x <, options>)`
`solve(system, vars <, options>)`
`solve(system <, options>)`
`solve(ODE)`
`solve(REC)`

#### Parameters

`eq` | - | a single equation or an inequality of type `"_equal"`, `"_less"`, `"_leequal"`, or `"_unequal"`. Also an arithmetical expression is accepted and regarded as an equation with vanishing right hand side.
`x` | - | the indeterminate to solve for: an identifier or an indexed identifier
`vars` | - | a non-empty set or list of indeterminates to solve for
`system` | - | a set, list, array, or table of equations and/or arithmetical expressions. Expressions are regarded as equations with vanishing right hand side.
`ODE` | - | an ordinary differential equation: an object of type `ode`.
`REC` | - | a recurrence equation: an object of type `rec`.

#### Options

`MaxDegree =` n | - | do not use explicit formulas involving radicals to solve polynomial equations of degree larger than `n`. The default value of the positive integer `n` is 2.
`BackSubstitution =` b | - | do or do not perform back substitution when solving algebraic systems; `b` must be `TRUE` or `FALSE`. The default value is `TRUE`.
`Multiple` | - | returns the solution set as an object of type `Dom::Multiset`, indicating the multiplicity of polynomial roots. This option is only allowed for polynomial equations and polynomial expressions.
`PrincipalValue` | - | return only one solution as a set with one element
`Domain =` d | - | return the set of all solutions that are elements of `d`. `d` must represent a subset of the complex numbers (for example, the reals or the integers) or must be a domain over which polynomials can be factored, e.g., a finite field. In the latter case, this option is only allowed for polynomial equations. If this option is missing, all solutions in the set of complex numbers are returned.
`IgnoreSpecialCases` | - | If a case analysis becomes necessary, ignore all cases which suppose some parameter in the equation to be an element of a fixed finite set.

#### Returns

`solve``(eq, x)` returns an object that represents a mathematical set (see ``Details'') . A call to `solve` returns a set of lists if one of the arguments is a set or a list, or if the first argument is an array or a table, or if the second argument is missing. Each list consists of equations, where the left hand side contains a variable to be solved for. `solve` may also return an expression of the form `x in S`, where `x` is one of the variables to solve for, and `S` is some set.

### Overloadable:

`eq`

#### Side Effects

`solve` reacts to properties of identifiers.

#### Related Functions

`linsolve`, `numeric::linsolve`, `numeric::solve`, `RootOf`, `solvers`

#### Details

- The `solve` routine provides a unified interface to a variety of specialized solvers. See `?``solvers` for an overview.
- If no indeterminates are specified, the set of all indeterminates appearing in `eq` (or `system`, respectively) is used. Indeterminates are identifiers (except mathematical constants such as `PI`, `EULER` etc.) and indexed identifiers. Indeterminates that appear only inside function names or indices are discarded. Cf. example 6.
- If a list of indeterminates to solve for is specified, the components of the resulting solution vectors are sorted according to the specified ordering of the indeterminates. If indeterminates are specified by a set, some ordering of the indeterminates is chosen internally.
- The sets returned by `solve` can be of many different types (an overview is given in the ``Background'' section below). You can never foresee what type of set will be returned. However, they have a unified interface of functions that may be applied to all of them. These functions include the set-theoretic operations `intersect`, `union`, and `minus`. Cf. example 2. Further, pointwise defined arithmetical operations `+`, `*` etc. can be applied. The function `solvelib::getElement` serves for extracting elements. The function `solvelib::isFinite` tests whether the solution set returned by `solve` is finite.
- `solve``(eq, x)` returns only those solutions that are consistent with the properties of `x`. Cf. example 7. When solving a system of equations for several variables, the properties of the variables to solve for may, but need not be taken into account.
- Since `solve` may be overloaded, special domains for equations of special kinds can be written. The MuPAD library itself uses this feature in the case of differential equations (see `ode`) and recurrence equations (see `rec`). Thus, `solve` provides an interface for solving differential and recurrence equations. See the helppages of `ode` and `rec` for examples.
- The command `float(hold(solve)(equations, indeterminates <, options>))` yields a numerical solution. It is equivalent to the call `numeric::solve(equations, indeterminates <, options>)`. See the help page of `numeric::solve` for the available options. In particular, starting points and search ranges for the numerical search can be specified. Note that for non-polynomial equations, only a single numerical solution is searched for. Cf. example 10.

  In contrast to `solve`, `numeric::solve` does not react to properties of identifiers set via `assume`.

#### Option: Multiple

- With this option, `solve` returns a set of type `Dom::Multiset`.
- Trying to solve the zero polynomial with option Multiple causes an error since infinite multisets cannot be represented in MuPAD .
- If the solution is of type `RootOf`, this option is ignored.

#### Option: PrincipalValue

- With this option, only one solution is returned even if several solutions exist. If the equation does not have a solution, an empty set is returned.
- If no single element of the set of solutions can be found, the result is a symbolic call of `solve`. In particular, this is the case if the set of solutions is piecewise defined and no element is common to all cases.
- This option may also be used, when equations are to be solved for several variables. In this case, a set containing only one list (representing a solution vector) is returned.

#### Option: MaxDegree = `n`

- This option enables/disables the use of explicit formulas for the zeroes of polynomials; other methods such as factorization are always applied. For polynomial equations, the given maximal degree `n` refers to the factors of the polynmials and not to the input polynomial.
- For polynomials of degree larger than 4, no explicit formulas exist. It makes no difference whether MaxDegree is set to 4 or to a higher value.

#### Option: BackSubstitution = `b`

- An object of type `"RootOf"` is never substituted into a variable. Hence, even if BackSubstitution is set to `TRUE`, the solution for one variable may be the set of roots of a polynomial depending on another variable.

#### Option: Domain = `d`

- Equations and systems in more than one variable cannot be solved over domains.
- Two kinds of Domains `d` are possible: subsets of `C_` and domains where polynomials can be factored (for polynomial equations only).
- A subset of `C_` can be any kind of set returned by `solve` (see the ``Background'' section). Instead of `C_`, `R_`, `Q_`, and `Z_`, the corresponding domains of the domains package `Dom::Complex`, `Dom::Real`, `Dom::Rational`, and `Dom::Integer` may be used.

#### Option: IgnoreSpecialCases

- This option makes `solve` apply some kind of heuristics in order to reduce the number of branches in piecewise defined objects: all equalities are assumed to be `FALSE`, except those that the property mechanism can prove to be `TRUE`; for example, all denominators that are not provably zero are assumed to be nonzero. This option tends to decrease the number of piecewise defined objects in results considerably.

#### Example 1

Usually, a set of type `DOM_SET` is returned if an equation has a finite number of solutions:

    >> solve(x^4 - 5*x^2 + 6*x = 2, x)

                                  1/2         1/2
                             {1, 3    - 1, - 3    - 1}

#### Example 2

The solution set may also be an infinite discrete set:

    >> S := solve(sin(x*PI/7) = 0, x)

                               { 7*X4 |  X4 in Z_ }

To pick out the solutions in a certain finite interval, just intersect the solution set with the interval:

    >> S intersect Dom::Interval(-22, 22)

                           {-21, -14, -7, 0, 7, 14, 21}

    >> delete S:

#### Example 3

The solution set of an inequality is usually an interval or a union of intervals:

    >> solve(x^2 > 5, x)

                  ]5^(1/2), infinity[ union ]-infinity, -5^(1/2)[

#### Example 4

For all but two numbers x, their square does not equal 7:

    >> solve(x^2 <> 7, x)

                                         1/2     1/2
                              C_ minus {7   , - 7   }

#### Example 5

Piecewise defined objects occur if an equation contains symbolic parameters in addition to the variable to solve for. The well-known solution formula for the quadratic equation ax2+bx+c=0 is only valid for a<>0; otherwise the equation reduces to bx=-c, where again two cases b<>0 and b=0 must be treated separately. Finally, if b=0, the equation c=0 may be true -- then, every x is a solution -- or false -- then, no x is a solution.

    >> S := solve(a*x^2 + b*x + c, x)

                   /
                   |
                   |
                   |
          piecewise| C_ if a = 0 and b = 0 and c = 0,
                   \

             {} if a = 0 and b = 0 and c <> 0,

                                          {                   2 1/2
                                          {   b   (- 4 a c + b )
                                          { - - - -----------------
             {   c }                      {   2           2
             { - - } if a = 0 and b <> 0, { -----------------------,
             {   b }                      {            a

                               2 1/2 }           \
               b   (- 4 a c + b )    }           |
             - - + ----------------- }           |
               2           2         }           |
             ----------------------- } if a <> 0 |
                        a            }           /

You might want to make additional assumptions and re-evaluate the result:

    >> assume(a <> 0): S

                  {         2         1/2    2         1/2     }
                  {   b   (b  - 4 a c)     (b  - 4 a c)      b }
                  { - - - ---------------  --------------- - - }
                  {   2          2                2          2 }
                  { ---------------------, ------------------- }
                  {           a                     a          }

    >> delete S: unassume(a):

#### Example 6

If no indeterminates are specified, the set of all indeterminates in the equation is used:

    >> solve(x^2 = 3)

                                   1/2           1/2
                            {[x = 3   ], [x = - 3   ]}

Indeterminates are only searched for outside operators and indices. Hence, neither `f` nor `y` is an indeterminate of the following equation:

    >> solve(f(x[y]) = 7)

                           solve({f(x[y]) = 7}, [x[y]])

#### Example 7

If the unknown to solve carries a mathematical property, only the solutions compatible with that property are returned. In the following, `x` is assumed to be a positive number (implying that `x` is real):

    >> assume(x, Type::Positive): solve(x^4 = 1, x)

                                        {1}

Without a property, all complex solutions are returned:

    >> unassume(x): solve(x^4 = 1, x)

                                  {-1, 1, - I, I}

#### Example 8

Using the option Multiple, the multiplicity of zeroes of polynomials becomes visible. Below, we see that x=-1 is a double zero of x3+2x2+x, while x=0 has only multiplicity one:

    >> solve(x^3 + 2*x^2 + x, x, Multiple)

                                 {[0, 1], [-1, 2]}

#### Example 9

If BackSubstitution is set to `FALSE`, the solution for a variable `y` may contain another variable `x` to solve for, but only if `x` appears on the right of `y` in the list of indeterminates.

    >> solve({x^2 + y = 1, x - y = 2}, [y, x], BackSubstitution = FALSE)

          { --                    1/2       --
          { |                   13           |
          { |  y = x - 2, x = - ----- - 1/2  |,
          { --                    2         --

             --                  1/2       -- }
             |                 13           | }
             |  y = x - 2, x = ----- - 1/2  | }
             --                  2         -- }

    >> solve({x^2 + y = 1, x - y = 2}, {x, y})

          { --         1/2                1/2       --
          { |        13                 13           |
          { |  x = - ----- - 1/2, y = - ----- - 5/2  |,
          { --         2                  2         --

             --       1/2              1/2       -- }
             |      13               13           | }
             |  x = ----- - 1/2, y = ----- - 5/2  | }
             --       2                2         -- }

Although BackSubstitution is switched on in the following example, the solution for `y` still depends on `x` because variables are never substituted by objects of type `"RootOf"`.

    >> solve({x^2 + y = 1, x - y = 2}, [y, x], MaxDegree = 1)

                                                   2
                  {[y = x - 2, x = RootOf(X22 + X22  - 3, X22)]}

#### Example 10

MuPAD's solver does not find an exact symbolic solution of the following equation:

    >> solve(2^x = x^2, x)

                                      x    2
                               solve(2  - x  = 0, x)

Applying `float` invokes the numerical solver:

    >> float(%)

                                  {-0.7666646959}

Avoiding the overhead of the symbolic solver, the numerical solver is called directly via the following command:

    >> float(hold(solve)(2^x - x^2, x))

                                  {-0.7666646959}

When applied to a non-polynomial equation, the numerical solver returns at most one solution, even if there are more. Search ranges can be specified to find other solutions:

    >> float(hold(solve)(2^x - x^2, x = 0..3))

                                       {2.0}

As an alternative to `float(hold(solve)(...))`, the numerical solver `numeric::solve` can be called directly:

    >> numeric::solve(2^x - x^2, x = 3..6)

                                       {4.0}

For polynomial equations, the numerical solver returns all complex solutions:

    >> solve(x^4 + x^3 = 3*x, x)

                                          2      3
                      {0} union RootOf(X23  + X23  - 3, X23)

    >> float(%)

          {0.0} union {1.17455941, - 1.087279705 + 1.171312111 I,

             - 1.087279705 - 1.171312111 I}

    >> eval(%)

          {0.0, 1.17455941, - 1.087279705 + 1.171312111 I,

             - 1.087279705 - 1.171312111 I}

In general, we recommend not to use intermediate symbolic results if numerical approximations are desired. Note that symbolic preprocessing may be time consuming, and the numerical evaluation of symbolic results may be numerically unstable. A direct call to the numerical solver `numeric::solve` avoids such problems.

#### Background

- The following types of sets may be returned by `solve`:
  - finite sets (type `DOM_SET`);
  - symbolic calls to the function `solve`;
  - zero sets of polynomials (type `RootOf`). `solve` returns this type if it is not able or, by virtue of the option `MaxDegree`, not allowed to solve the equation explicitly in terms of radicals;
  - set-theoretic expressions (types `"_union"`, `"_intersect"`, and `"_minus"`);
  - symbolic calls of `solvelib::Union`. These represent unions over parametrized systems of sets;
  - the sets C, R, Q, and Z (type `solvelib::BasicSet`);
  - intervals (type `Dom::Interval`);
  - image sets of functions (type `Dom::ImageSet`);
  - piecewise defined objects, where every branch defines some set of one of the mentioned types (type `piecewise`).

#### Changes

- The syntax for solving over a domain (which used to be `solve``(eq, x = d)`) was changed to `solve``(eq, x, Domain = d)`.
- Further types of solution sets were implemented.
- `solve` now reacts to the properties both of variables to solve for and of free parameters.
- `solve` now performs a case analysis and returns objects of type `piecewise` where necessary.
- A new option `IgnoreSpecialCases` has been introduced.
- The default of MaxDegree was changed from 4 to 2.
- The default of BackSubstitution was changed from `FALSE` to `TRUE`.
- The numerical solvers called by `solve` were redesigned and improved.

Do you have questions or comments?
Copyright © SciFace Software GmbH & Co. KG 2000