Main Content

This example shows how to attempt to solve a nonlinear system of equations with constraints by using the problem-based approach.

When your problem has only bound constraints, the process for solving the problem is straightforward. For example, to find the solution with positive components to the system of equations

$$\begin{array}{l}\left({\mathit{x}}_{1}+1\right)\left(10-{\mathit{x}}_{1}\right)\frac{1+{\mathit{x}}_{2}^{2}}{1+{\mathit{x}}_{2}^{2}+{\mathit{x}}_{2}}=0\\ \left({\mathit{x}}_{2}+2\right)\left(20-{\mathit{x}}_{2}\right)\frac{1+{\mathit{x}}_{1}^{2}}{1+{\mathit{x}}_{1}^{2}+{\mathit{x}}_{1}}=0,\end{array}$$

simply create optimization variables with lower bounds of 0. (These equations have four solutions: where $${x}_{1}=-1$$ or $${x}_{1}=10$$, and where $${x}_{2}=-2$$ or $${x}_{2}=20$$.)

x = optimvar('x',2,"LowerBound",0); expr1 = (x(1) + 1)*(10 - x(1))*((1 + x(2)^2))/(1 + x(2)^2 + x(2)); expr2 = (x(2) + 2)*(20 - x(2))*((1 + x(1)^2))/(1 + x(1)^2 + x(1)); eqn1 = expr1 == 0; eqn2 = expr2 == 0; prob = eqnproblem; prob.Equations.eqn1 = eqn1; prob.Equations.eqn2 = eqn2; x0.x = [15,15]; [sol,fval,exitflag] = solve(prob,x0)

Equation problem has bound constraints. Reformulating as a least squares problem. Solving problem using lsqnonlin. Equation solved. lsqnonlin 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.

`sol = `*struct with fields:*
x: [2x1 double]

`fval = `*struct with fields:*
eqn1: 0
eqn2: 0

exitflag = EquationSolved

View the solution.

sol.x

`ans = `*2×1*
10
20

When your problem has general constraints, formulate the problem as an optimization problem, not an equation problem. Set the equations as equality constraints. For example, to solve the preceding equations subject to the nonlinear inequality constraint $$\Vert x{\Vert}^{2}\le 10$$, remove the bounds on `x`

and formulate the problem as an optimization problem with no objective function.

x.LowerBound = []; circlecons = x(1)^2 + x(2)^2 <= 10; prob2 = optimproblem; prob2.Constraints.circlecons = circlecons; prob2.Constraints.eqn1 = eqn1; prob2.Constraints.eqn2 = eqn2; [sol2,fval2,exitflag2] = solve(prob2,x0)

Solving problem using fmincon. Local minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the value of the optimality tolerance, and constraints are satisfied to within the value of the constraint tolerance.

`sol2 = `*struct with fields:*
x: [2x1 double]

fval2 = 0

exitflag2 = OptimalSolution

View the solution.

sol2.x

`ans = `*2×1*
-1.0000
-2.0000

You can also formulate the problem by setting the objective function as a sum of squares, and the general constraints as a constraint. This alternative formulation gives a mathematically equivalent problem, but can result in a different solution because the change in formulation leads the solver to different iterations.

prob3 = optimproblem; prob3.Objective = expr1^2 + expr2^2; prob3.Constraints.circlecons = circlecons; [sol3,fval3,exitflag3] = solve(prob3,x0)

Solving problem using fmincon. Local minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the value of the optimality tolerance, and constraints are satisfied to within the value of the constraint tolerance.

`sol3 = `*struct with fields:*
x: [2x1 double]

fval3 = 8.0569e-16

exitflag3 = OptimalSolution

View the solution.

sol3.x

`ans = `*2×1*
-1.0000
-2.0000

In this case, the least squares objective leads to the same solution as the previous formulation, which uses only constraints.

Generally, `solve`

attempts to solve a nonlinear system of equations by minimizing the sum of squares of the equation components. In other words, if `LHS(i)`

is the left-side expression for equation `i`

, and `RHS(i)`

is the right-side expression, then `solve`

attempts to minimize `sum((LHS `

–` RHS).^2)`

.

In contrast, when attempting to satisfy nonlinear constraint expressions, `solve`

generally uses `fmincon`

, and tries to satisfy the constraints by using different strategies.

In both cases, the solver can fail to solve the equations. For strategies you can use to attempt to find a solution when the solver fails, see fsolve Could Not Solve Equation.