Sistemas de Ecuaciones No Lineales

En este capítulo se estudian algunos métodos para resolver sistemas de ecuaciones no lineales. Estos sistemas se caracterizan porque generalmente no tienen soluciones analíticas, siendo la única alternativa de solución la numérica.

Método Simplex

El método Simplex es un método de optimización, es decir un método que permite encontrar máximos y mínimos, pero, la solución de un sistema de ecuaciones, puede ser expresada como un problema de optimización, por lo que, estos métodos, permiten resolver sistemas de ecuaciones no lineales.

Para expresar un sistema de ecuaciones no lineales como un problema de optimización, se igualan todas las ecuaciones del sistema a cero, se calcula su sumatoria y se minimiza la misma. En el mínimo la sumatoria será igual a cero (o cercana a cero) y en consecuencia las ecuaciones del sistema serán también iguales a cero (o cercanas a cero). Cuando eso ocurre es porque se han encontrado las soluciones del sistema, es decir los valores que al ser reemplazados en las ecuaciones las igualan a cero (esto es los valores para los cuales se cumplen las igualdades del sistema).

En general, si la función a resolver, es:

\[ f(x_0, x_1, \cdots, x_{n-1}) = \alpha \]

Donde "n" es el número de incógnitas del sistema. La solución se encuentra cuando al reemplazar los valores de las variables (x0 a xn-1), la igualdad se cumple. Para convertir este problema, en un problema de optimización, simplemente se iguala la función a 0:

\[ g(x_0, x_1, \cdots, x_{n-1}) = f(x_0, x_1, \cdots, x_{n-1})-\alpha =0 \]

Sin embargo, para garantizar que se encuentre el mínimo, es necesario que la función devuelva sólo valores positivos, porque si se permiten valores negativos darían lugar a falsos mínimos (por ejemplo, cuando se suman dos valores iguales pero de distinto signo).

Para que los valores sean siempre positivos, simplemente se eleva al cuadrado ambos lados de la ecuación:

\[ \big(g(x_0, x_1, \cdots, x_{n-1})\big)^2 = \big(f(x_0, x_1, \cdots, x_{n-1})-\alpha \big)^2=0^2 \]

Cuando la función a optimizar se encuentra en esta forma, es decir cuando está igualada a cero y se puede garantizar que devuelve sólo valores positivos, se conoce como la función de error "e":

\[ e(x_0, x_1, \cdots, x_{n-1}) = \big(f(x_0, x_1, \cdots, x_{n-1})-\alpha \big)^2=0 \]

El método Simplex se aplica a este tipo de funciones y encuentra el mínimo mediante una serie de interpolaciones o extrapolaciones lineales multidimencionales, conocidas como proyecciones n-dimensionales.

En consecuencia, lo primero que se requiere en el método es la ecuación general para llevar a cabo dichas proyecciones.

Proyección lineal n-dimensional

En un sistema de ecuaciones, cada valor asumido constituye un vector, o, lo que es lo mismo un punto n-dimensional, con tantas dimensiones como incógnitas tiene el sistema.

Por simplicidad, la deducción de la ecuación para proyectar (extrapolar) un punto a través de otros dos, se la hace con puntos bidimensionales, sin embargo, las ecuaciones resultantes tienen carácter general.

Tomando en cuenta la siguiente figura:

Simplex proyección lineal n-dimensional

Donde se conocen los puntos P1 y P2 y se quiere calcular el punto P3, en base a la relación de distancias que existen entre los puntos P1, P2 y P1, P3, es decir en base al valor de:

\[ k = \dfrac{\overline{P_1P_3}}{\overline{P_1P_2}} \]

Por relación de triángulos, se cumple que:

\[ \begin{aligned} k &=\dfrac{x_3-x_1}{x_2-x_1}\\ x_3&=k\cdot x_2+(1-k)\cdot x_1\\[5mm] k &=\dfrac{y_3-y_1}{y_2-y_1}\\ y_3&=k\cdot y_2+(1-k)\cdot y_1 \end{aligned} \]

De donde se deduce que, para un punto "n" dimensional "Pi" cualquiera, se cumple:

\[ P_i = k\cdot P_{i-1}+(1-k)\cdot P_{i-2} \]

Plan inicial Simplex

Para comenzar el proceso, el método Simplex requiere un conjunto de "n+1" puntos iniciales, conocidos como plan inicial Simplex.

Por ejemplo, si el sistema tiene dos incógnitas (n=2), el método Simplex requiere 3 puntos (cada uno con 2 incógnitas), lo que implica asumir 6 valores. Si se tiene 5 incógnitas (n=5), el método Simplex requiere 6 puntos (cada uno con 5 incógnitas), lo que implica asumir 30 valores.

Para evitar la necesidad de asumir tantos valores, existen algunos procedimientos que permiten generar los "n" puntos a partir de uno.

Uno de dichos procedimientos es el siguiente: Sea P1 el punto asumido, entonces el segundo punto (P2) se genera multiplicando el primer elemento del punto P1 por 1.1, el tercer punto (P3) multiplicando el segundo elemento del punto P1 por 1.1, el cuarto punto (P4) multiplicando el tercer elemento del punto P1 por 1.1 y así sucesivamente, con lo que se generan los n+1 puntos.

Por ejemplo, si el sistema tiene 3 dimensiones (o variables) y el punto asumido es P0=(15,15,150), los otros puntos del plan Simplex se obtienen de la siguiente forma:

\[ \begin{aligned} P_1&= (15*1.1, 15, 150)=(16.5, 15, 150)\\ P_1&= (15, 15*1.1, 150)=(15, 16.5, 150)\\ P_1&= (15, 15, 150*1.1)=(16.5, 15, 165) \end{aligned} \]

Mayor y menor valor de la función de error

Con el plan inicial Simplex, se calculan los valores de la función de error para cada uno de los puntos, determinando cuál es el mayor de ellos "h" (highest) y el menor "s" (smallest).

Por ejemplo, si el problema tiene 2 incógnitas, los puntos del plan quedan identificados como se muestra en la siguiente figura:

Simplex mayor y menor puntos

Centroide

En el método Simplex, los nuevos puntos del plan se obtienen proyectando los puntos del plan actual a través de su promedio, sin incluir en el promedio el peor punto (el punto ph). Dicho promedio se denomina centroide y se calcula con la siguiente expresión:

\[ C = \dfrac{1}{n}\sum_{i=0}^n P_i \hspace{0.5cm} \begin{cases} i \ne h \end{cases} \]

Reflexión

Para reemplazar el peor punto del plan (ph), por uno mejor, se proyecta dicho punto (a través del centroide) al doble de su distancia con relación al centroide, como se muestra en la siguiente figura (caso bidimensional):

Simplex reflexión

De esa manera el nuevo punto es el reflejo del original, razón por la cual a esta proyección se conoce con el nombre de reflexión

Si se denomina a al término k de la ecuación de proyección n-dimensional (ecuación 5), la ecuación resultante (la ecuación de reflexión) toma la forma:

\[ P_r = a\cdot C +(1-a)\cdot P_h \]

En esta ecuación, el valor de "a" debería ser 2 (pues se proyecta al doble de la distancia original). En la práctica, sin embargo, se emplea un valor cercano a 2 (generalmente 1.95), porque un valor entero suele provocar problemas de convergencia.

Si se denomina er al valor de la función de error en el punto reflejado Pr, eh al valor de la función de error en el punto Ph y es al valor de la función de error en el punto Ps, al realizar la reflexión se pueden presentar los siguientes casos:

  1. Si er es menor a es, entonces la reflexión ha sido muy buena: el nuevo punto es más cercano a cero (el mínimo) que el mejor punto del plan actual (Ps), por lo tanto se prosigue en esa dirección con la expansión (que se explica más adelante).
  2. Si er es menor eh pero no mayor a es, entonces la reflexión ha sido buena: el nuevo punto es más cercano a cero que el peor punto del plan actual (Ph). En este caso se reemplaza el punto Ph por el punto reflejado Pr.
  3. Si er es mayor a eh, entonces la reflexión ha sido mala: el nuevo punto está más alejado de cero (del mínimo) que el peor punto del plan actual (Ph). En este caso se procede con la contracción (que se explica más adelante).

Expansión

Como se dijo, cuando la reflexión es muy buena (er<es), se procede con la expansión, que simplemente consiste en proyectar el punto Pr al doble de su distancia actual con relación al centroide, tal como se muestra en la siguiente figura (caso bidimensional):

Simplex expansión

Si se denomina b al término k de la ecuación de proyección n-dimensional (ecuación 5), la ecuación para la expansión toma la forma:

\[ P_x = b\cdot C +(1-b)\cdot P_r \]

Donde “b” debería ser 2 (se proyecta al doble de su distancia actual) sin embargo y al igual que en la reflexión, en la práctica se toma un valor cercano a 2 (generalmente 1.95).

Si se denomina ex al valor de la función de error en Px, entonces se pueden presentar los siguientes casos:

  1. Si ex es menor a er, la expansión ha sido buena, por tanto Px reemplaza a Ph.
  2. Si ex es mayor a er, la expansión no ha sido buena, entonces Pr reemplaza a Ph.

Contracción

Como se dijo, cuando la reflexión es mala, se procede en dirección contraria con la contracción, que consiste en recorrer el punto reflejado a la mitad de su distancia actual con relación al centroide, tal como se muestra en la siguiente figura (caso bidimensional):

Simplex contracción

Si se denomina d al término k, de la ecuación de proyección n-dimensional (ecuación 5), la ecuación de contracción, toma la forma:

\[ P_c = d\cdot C +(1-d)\cdot P_h \]

Donde “d” debería ser igual a 0.5 (se proyecta a la mitad de su distancia actual). En la práctica, se emplea un valor cercano a 0.5 (generalmente 0.45), para reducir los problemas de convergencia.

Si se denomina ec al valor de la función de error en el punto Pc, se pueden presentar los siguientes casos:

  1. Si ec es menor a eh, la contracción ha sido buena, entonces Pc reemplaza a Ph.
  2. Si ec es mayor a eh, la contracción ha sido mala, en ese caso se procede con el escalamiento (que se explica a continuación).

Escalamiento

En el escalamiento, que se lleva a cabo cuando la contracción es mala, se proyectan todos los puntos del plan Simplex, a través del mejor punto del plan actual (Ps), ya sea al doble de su distancia actual, o a la mitad de dicha distancia, tal como se muestra en la siguiente figura (para el caso bidimensional):

Simplex escalamiento

Donde P* son los nuevos puntos del plan. En este caso el valor del término k, de la ecuación de proyección n-dimensional (ecuación 5), puede ser 0.5 (en la práctica 0.45) cuando se proyecta a la mitad de la distancia actual o 2 (en la práctica 1.95) cuando se proyecta al doble de la distancia actual.

La ecuación de proyección, para el escalamiento, es:

\[ P_i^* = k\cdot P_s+(1-k)\cdot P_i \hspace{5mm} \begin{cases} i = 0 \rightarrow n\text{; }~~i\ne s \end{cases} \]

Como el escalamiento cambia todos los puntos del plan (con excepción de Ps), es necesario volver a calcular los valores de la función de error para todos los puntos del plan, excepto, por supuesto, para Ps.

Algoritmo

En el método Simplex, las operaciones de reflexión y las consiguientes operaciones de expansión, contracción y/o escalamiento se repiten hasta que se encuentra un valor de la función de error cercano a cero o hasta que los valores de Ps y Ph son iguales en un determinado número de dígitos.

Dado que la convergencia no está asegurada, se debe emplear también un contador de iteraciones, para terminar el proceso cuando se alcanza un límite establecido.

El algoritmo que automatiza la aplicación del método es el siguiente.

Simplex, algoritmo

En este algoritmo “planInicial”, "errores", "indice_s", "indice_h", "centroide", "reflexion", "expansion" y "contraccion", son funciones internas que llevan a cabo los procesos que sus nombres sugieren.

El código respectivo, ha sido añadido como un método dinámico de la clase Function, por lo que debe ser llamado desde la función que devuelve el vector con los restos de las ecuaciones del sistema:

El método devuelve un objeto con el vector (v) el cual contiene las soluciones del sistema y el valor de la función de error (e).

El valor de la función de error (e) permite determinar cuan cercano al mínimo es el punto encontrado, es decir cuan correctas son las soluciones obtenidas. Si es cero o cercano a cero, las soluciones son correctas, caso contrario el punto es un mínimo (una inflexión) pero no las soluciones del sistema.

Ejemplo

Encuentre las soluciones del siguiente sistema de ecuaciones no lineales con el método Simplex. Trabaje con una precisión/exactitud de 4 dígitos y redondee los resultados al cuarto dígitos después del punto.

\[ \begin{alignedat}{2} x^2+2y^2 &=& 22\\ -2x^2+xy-3y &=&-11 \end{alignedat} \]

Primero se igualan las ecuaciones del sistema a cero:

\[ \begin{alignedat}{2} x^2+2y^2-22 &=&~0\\ -2x^2+xy-3y+11 &=&~0 \end{alignedat} \]

Se programan estas ecuaciones en una función que devuelve el vector con los restos de las ecuaciones:

var f = ([x, y]) =>{
  const e1 = Math.sqr(x)+2*Math.sqr(y)-22;
  const e2 = -2*Math.sqr(x)+x*y-3*y+11;
  return [e1, e2];
};

Sin embargo, dado que es un sólo resultado (un vector) es más sencillo calcular los valores de las ecuaciones directamente en el vector resultante:

var f = ([x, y]) =>[
  Math.sqr(x)+2*Math.sqr(y)-22,
  -2*Math.sqr(x)+x*y-3*y+11
];

Observe que, en este caso, las ecuaciones se separan con comas (no puntos y comas) porque son los elementos de un vector.

Una vez programadas las ecuaciones, se resuelve el sistema de ecuaciones con el método Simplex, asumiendo para ello un vector con los valores iniciales (en este ejemplo x=1, y=2) y mandando el error permitido (en este ejemplo 4):

var r = f.simplex({vi:[1, 2], err:4}); r

En este caso, las soluciones (el vector "v") son correctas, porque el error "e", es cercano a 0 (tiene 8 ceros después del punto). Las soluciones y el valor de la función de error, mostradas en forma de vector (array) y redondeados al cuarto dígito después del punto (como requiere el enunciado), son:

[r.v, r.e].round(4)

Alternativamente, en lugar de recibir el objeto resultante en una variable (como se ha hecho previamente), los resultados pueden ser recibidos directamente en variables:

var {v, e} = f.simplex({vi:[1, 2], err:4});
[v,e].round(4)

Si no se requiere el valor de la función de error (e), porque, por la naturaleza del problema se sabe que las soluciones son correctas, se puede recibir sólo el vector de soluciones:

var {v} = f.simplex({vi:[1, 2], err:4});
v.round(4)

O, si se quieren mostrar directamente los resultados, sin guardarlos en una variable (que es lo más práctico cuando sólo se resuelve un sistema de ecuaciones), se accede al campo "v", directamente desde la solución devuelta por "simplex":

f.simplex({vi:[1, 2], err:4}).v.round(4)

Por supuesto, es posible guardar las soluciones (o el valor de la función de error) en variables con otros nombres, por ejemplo, en las siguientes instrucciones se muestra dos formas para guardar el vector de resultados en la variable "z":

var {v: z} = f.simplex({vi:[1, 2], err:4}); z.round(4)
var z = f.simplex({vi:[1,2], err:4}).v.round(4); z

Finalmente, es posible obtener las soluciones (y/o el valor de la función de error) directamente, sin guardar ni la función con el sistema de ecuaciones, ni los resultados (empleando una función inmediatamente invocada, una IIFE), como se muestra en la siguiente instrucción:

(([x, y]) =>[
Math.sqr(x)+2*Math.sqr(y)-22,
-2*Math.sqr(x)+x*y-3*y+11
]).simplex({vi:[1, 2], err:4}).v.round(4)

Gráficamente, cuando se trabaja con un sistema de dos ecuaciones no lineales, cada función representa una superficie (no una curva), por lo tanto, no se tienen uno o más puntos de intersección (una o más soluciones), sino una o más curvas de solución (una o más funciones de solución), por esa razón, en la solución de un sistema de ecuaciones no lineales, es mucho más probable encontrar soluciones diferentes al emplear valores iniciales diferentes.

En sistemas con dos ecuaciones no lineales, como en este ejemplo, es posible dibujar la gráfica de las dos funciones para apreciar visualmente la curva de las soluciones (la intersección de las dos superficies). En la calculadora JavaScript, para elaborar gráficas tridimensionales, que son las gráficas resultantes de dibujar funciones con dos variables, se hace uso de la librería Plotly. Esta librería permite dibujar diez tipos de gráficas tridimensionales y más de 30 gráficas bidimensionales.

Los más de 40 tipos de gráficas disponibles en Plotly pueden ser dibujados en la calculadora empleando la función plotly, la cual recibe los mismos parámetros que el método Plotly.newPlot, con excepción del primer parámetro: el elemento donde se dibuja la gráfica, que no es necesario en la calculadora, porque la gráfica se dibuja en la celda de resultados.

Así, en las siguientes instrucciones, se han copiado los datos del ejemplo disponible en el sitio de la librería (Plotly 3D Mesh), para dibujar un cubo empleando una gráfica de tipo mesh3d:

var intensity = [0, 0.14285714285714285, 0.2857142857142857, 0.42857142857142855, 0.5714285714285714, 0.7142857142857143, 0.8571428571428571, 1];

var data = [{
type: "mesh3d",
x: [0, 0, 1, 1, 0, 0, 1, 1],
y: [0, 1, 1, 0, 0, 1, 1, 0],
z: [0, 0, 0, 0, 1, 1, 1, 1],
i: [7, 0, 0, 0, 4, 4, 6, 6, 4, 0, 3, 2],
j: [3, 4, 1, 2, 5, 6, 5, 2, 0, 1, 6, 3],
k: [0, 7, 2, 3, 6, 7, 1, 1, 5, 5, 7, 6],
intensity: intensity,
colorscale: [
[0, 'rgb(255, 0, 255)'],
[0.5, 'rgb(0, 255, 0)'],
[1, 'rgb(0, 0, 255)']
]
}
];

plotly(data)

En función al dispositivo empleado, Plotly puede demorar unos cuantos segundos en dibujar la gráfica (sobre todo la primera vez que se llama a la función).

Como se puede comprobar, la gráfica puede ser ampliada o reducida con la rueda del mouse, rotada alrededor del eje z Rotar alrededor del eje z, rotada libremente Rotar libremente, movida Mover la gráfica, ampliada o reducida arrastrando el puntero del mouse Ampliar/reducir, vuelta a la posición inicial Posición inicial, guardada en un archivo Guardar imagen, se pueden ocultar o mostrar los valores de los puntos Mostrar/ocultar puntos y, en animaciones, volver a la última posición guardada Posición anterior.

Para el caso específico de las gráficas de superficie, dibujadas a partir de funciones bidimensionales, para facilitar el proceso, se ha creado la función surfacePlot, que recibe la función o funciones a dibujar: fun, valor por defecto: (x,y)=>x**2+y**2, en caso de dos o más funciones se debe mandar un array con las funciones a dibujar. Los límites del eje "x": xmin y xmax, valores por defecto -5 y 5 y el incremento de los valores de "x": dx, valor por defecto 0.5. Igualmente, recibe los límites e incremento de "y": ymin, ymax y dy, valores por defecto -5, 5 y 0.5.

Además, puede recibir todos los parámetros que son válidos en las gráficas de tipo surface.

Así, las dos ecuaciones del sistema, pueden ser dibujadas con la siguiente instrucción:

surfacePlot({fun:[(x,y)=>Math.sqr(x)+2*Math.sqr(y)-22, (x,y)=>-2*Math.sqr(x)+x*y-3*y+11], ymin:-6, ymax:5})

En esta gráfica, las soluciones se encuentran en la curva (de forma circular) que se crea en la intersección de las dos superficies. Todos los valores de esa curva son las soluciones del sistema de ecuaciones no lineales.

En la solución de sistemas de ecuaciones no lineales, los métodos gráficos son de utilidad limitada, básicamente ayudan a tener una idea del lugar y forma de la curva de solución. En sistemas con 3 o más ecuaciones no lineales, no es posible emplear método gráficos.


Método del descenso acelerado

Al igual que en Simplex, en el método del descenso acelerado se trabaja con la función de error, ecuación (3):

\[ e(x_0, x_1, \cdots, x_{n-1}) = \big(f(x_0, x_1, \cdots, x_{n-1})-\alpha \big)^2=0 \]

Pero, la dirección a seguir, se determina mediante la gradiente de la función de error, que viene definida por la siguiente expresión:

\[ \overrightarrow{~z~} = \nabla \text{fe}(\overrightarrow{~x~}) = \begin{bmatrix} \dfrac{\partial{\text{fe}(\overrightarrow{~x~})}}{\partial{x_0}}\\[4mm] \dfrac{\partial{\text{fe}(\overrightarrow{~x~})}}{\partial{x_1}}\\[5mm] \vdots\\[3mm] \dfrac{\partial{\text{fe}(\overrightarrow{~x~})}}{\partial{x_{n-1}}} \end{bmatrix} \]

Para acercarse al mínimo, se resta, a los valores iniciales asumidos, el gradiente de la función multiplicado por un factor α:

\[ \overrightarrow{x_n}=\overrightarrow{x}-\alpha \cdot \overrightarrow{z} \]

La forma en la que se calcula este factor (α) es lo que da lugar a las diferentes variantes del método.

De dichas variantes, en la asignatura se toma aquella donde el valor de α se calcula normalizando los valores del vector z (para que su suma sea 1) y probando luego valores de α que comienzan en 1 y que en cada iteración disminuyen a la mitad de su valor anterior, hasta que la función de error es menor al valor obtenido con el vector asumido.

Posteriormente, se comprueba si es posible o no, mejorar este valor mediante una extrapolación y de ser así se emplea el valor extrapolado.

Para el cálculo del gradiente, el principal problema radica en el cálculo de las derivadas. La deducción de las fórmulas analíticas, para cada problema, no es una alternativa práctica, por lo que dicho cálculo debe ser numérico

En este capítulo se empleará la fórmula de diferencia central de segundo orden, adaptada para el cálculo de derivadas parciales:

\[ \dfrac{\partial{\text{fe}(\overrightarrow{x})}}{\partial{x_i}}= \dfrac{\text{fe}(x_0, \cdots, x_i+h,\cdots, x_{n-1})- \text{fe}(x_0,\cdots,x_{i-h},\cdots,x_{n-1})} {2h} \]

Donde el valor de “h” se calcula con:

\[ h = x_i \cdot 10^{-6} \]

El proceso comienza calculando el valor de la función de error con los valores asumidos (vector x):

\[ \text{fe}_1 = \text{fe}(\overrightarrow{x}) \]

Para determinar la dirección a seguir se calcula el valor absoluto del gradiente (\(|\overrightarrow{z}|\)):

\[ z_0 = |\overrightarrow{z}| \]

Si este valor es cero, el proceso concluye, siendo las soluciones los valores del vector x, caso contrario, se normalizan los valores de z:

\[ \overrightarrow{z} = \dfrac{\overrightarrow{z}}{z_0} \]

Entonces se fija el valor de α (a3) en 1 y con el mismo se calcula el nuevo vector de prueba y los respectivos valores de la función de error:

\[ \begin{aligned} \overrightarrow{x_3} &= \overrightarrow{x}-a_3\overrightarrow{z}\\ \text{fe}_{3}&=\text{fe}(\overrightarrow{x_3}) \end{aligned} \]

Si fe3 no es menor a fe1, a3 se divide entre dos y el proceso se repite hasta que fe3 sea menor a fe1 o hasta que a3 sea menor al error permitido, en cuyo caso el proceso concluye, siendo las soluciones los valores actuales de x.

Una vez que fe3 es menor a fe1, se calcula un nuevo valor de α extrapolado a0 y para ello se calculan previamente los siguientes parámetros:

\[ \begin{aligned} a_2 &= \dfrac{a_3}{2}\\ \overrightarrow{x_2}&=\overrightarrow{x}-a_2\overrightarrow{z}\\ \text{fe}_2 &= \text{fe}(\overrightarrow{x_2}) \end{aligned} \]
\[ h_1 = \dfrac{\text{fe}_2-\text{fe}_0}{a_2} \]
\[ h_2 = \dfrac{\text{fe}_3-\text{fe}_2}{a_3-a_2} \]
\[ h_2 = \dfrac{\text{fe}_3-\text{fe}_2}{a_3-a_2} \]
\[ h_3 = \dfrac{h_2-h_1}{a_3} \]

Con los cuales se calcula a0:

\[ a_0 = 0.5\left({a_2-\dfrac{h_1}{h_3}}\right) \]

Con este nuevo valor de α (a0) se calcula un nuevo valor de prueba y el correspondiente valor de la función de error:

\[ \begin{aligned} \overrightarrow{x_0}&=\overrightarrow{x}-a_0\overrightarrow{z}\\ \text{fe}_0 &=\text{fe}(\overrightarrow{x_0}) \end{aligned} \]

Si fe0 es menor a fe3, los nuevos valores de prueba son los valores del vector x0, caso contrario los nuevos valores de prueba son los valores del vector x3.

Algoritmo

El algoritmo del método, que sigue el procedimiento descrito en el anterior acápite, es el siguiente:

Descenso acelerado, algoritmo

Donde los vectores, se escriben en color celeste, para diferenciarlos de los valores escalares.

El código respectivo, ha sido añadido como un método dinámico de la clase Function y al igual que el método Simplex, debe ser llamado desde la función que devuelve los restos del sistema de ecuaciones y devuelve (igualmente) el vector con las soluciones del sistema (v) y el valor de la función de error (e).

Ejemplo

Resuelva el sistema de ecuaciones del ejemplo 1 (ecuación 11) empleando el método del Descenso Acelerado con un error permitido de 6 dígitos, redondeando el resultado al cuarto dígito después del punto.

\[ \begin{alignedat}{2} x^2+2y^2 &=& 22\\ -2x^2+xy-3y &=&-11 \end{alignedat} \]

El problema se resuelve de manera similar al mencionado ejemplo, sólo que ahora se llama al método del Descenso Acelerado, en lugar del método Simplex:

var f = ([x, y]) =>[
Math.sqr(x)+2*Math.sqr(y)-22,
-2*Math.sqr(x)+x*y-3*y+11
];
f.descensoa({vi:[1, 2], err:4}).v.round(4)

Si no se logra convergencia (con este o con cualquiera de los métodos) se puede incrementar el límite de iteraciones, para verificar si, con un mayor número de iteraciones, se logra convergencia.

Así, asumiendo que con valores iniciales iguales a -3 y -1, no se logra convergencia, se puede incrementar el límite de iteraciones, por ejemplo a 5000, para verificar si, con ese número de iteraciones, se logra convergencia:

f.descensoa({vi:[-3, -1], err:4, li:5000}).v.round(4)

Método de Newton (Gradiente)

El método de Newton para sistemas de ecuaciones no lineales, conocido también como el método de la Gradiente, requiere, casi siempre, menos iteraciones que los dos métodos anteriores. En contrapartida sólo logra convergencia si los valores iniciales son cercanos a las soluciones, por esta razón, con frecuencia, los valores iniciales se encuentran con un método más estable (como el método Simplex) y las soluciones más exactas con el método de Newton.

En este método se expanden las ecuaciones del sistema empleando series de Taylor. Por ejemplo, para un sistema de 3 ecuaciones con 3 incógnitas:

\[ \begin{aligned} f_0(x_0, x_1, x_2)&= 0\\ f_1(x_0, x_1, x_2)&= 0\\ f_2(x_0, x_1, x_2)&= 0 \end{aligned} \]

La expansión de este sistema, en series de Taylor, es:

\[ \begin{aligned} f_0(x_0+\Delta x_0, x_1+\Delta x_1, x_2+\Delta x_2)&= f_0+\dfrac{\partial f_0}{\partial x_0}\Delta x_0+ \dfrac{\partial f_0}{\partial x_1}\Delta x_1+ \dfrac{\partial f_0}{\partial x_2}\Delta x_2+\cdots +\infty = 0\\ f_1(x_0+\Delta x_0, x_1+\Delta x_1, x_2+\Delta x_2)&= f_1+\dfrac{\partial f_1}{\partial x_0}\Delta x_0+ \dfrac{\partial f_1}{\partial x_1}\Delta x_1+ \dfrac{\partial f_1}{\partial x_2}\Delta x_2+\cdots +\infty = 0\\ f_2(x_0+\Delta x_0, x_1+\Delta x_1, x_2+\Delta x_2)&= f_2+\dfrac{\partial f_2}{\partial x_0}\Delta x_0+ \dfrac{\partial f_2}{\partial x_1}\Delta x_1+ \dfrac{\partial f_2}{\partial x_2}\Delta x_2+\cdots +\infty = 0 \end{aligned} \]

Donde Δx0, Δx1 y Δx2 son los valores que deberían añadirse a los valores asumidos (x0, x1 y x2) para que las funciones (f0, f1 y f2) sean iguales a cero. En otras palabras, si fuera posible calcular los valores de Δx0, Δx1 y Δx2, las soluciones del sistema serían x0=x0+Δx0, x1=x1+Δx1 y x2=x2+Δx2.

Por supuesto, al tratarse de series infinitas, no es posible en la práctica calcular dichos valores, sin embargo, es posible obtener un valor aproximado tomando en cuenta sólo los términos de primer orden:

\[ \begin{aligned} f_0(x_0+\Delta x_0, x_1+\Delta x_1, x_2+\Delta x_2)&{\approx} f_0+\dfrac{\partial f_0}{\partial x_0}\Delta x_0+ \dfrac{\partial f_0}{\partial x_1}\Delta x_1+ \dfrac{\partial f_0}{\partial x_2}\Delta x_2= 0\\ f_1(x_0+\Delta x_0, x_1+\Delta x_1, x_2+\Delta x_2)&{\approx} f_1+\dfrac{\partial f_1}{\partial x_0}\Delta x_0+ \dfrac{\partial f_1}{\partial x_1}\Delta x_1+ \dfrac{\partial f_1}{\partial x_2}\Delta x_2= 0\\ f_2(x_0+\Delta x_0, x_1+\Delta x_1, x_2+\Delta x_2)&{\approx} f_2+\dfrac{\partial f_2}{\partial x_0}\Delta x_0+ \dfrac{\partial f_2}{\partial x_1}\Delta x_1+ \dfrac{\partial f_2}{\partial x_2}\Delta x_2= 0 \end{aligned} \]

Que, al ser un sistema de ecuaciones lineales, puede ser resuelto, obteniéndose así los valores de: Δx0, Δx1 y Δx2, pero como son sólo valores aproximados el proceso de cálculo es iterativo: comenzando con los valores asumidos x0 a x2, se calculan los valores de Δx0, Δx1 y Δx2, con los que se calculan nuevos valores de prueba: x0=x0+Δx0, x1=x1+Δx1, x2=x2+Δx2. Entonces el proceso se repite, empleando en cada repetición los nuevos valores calculados, hasta que los valores de Δxi son cero o cercanos a cero (exactitud), o hasta que los valores de prueba, de dos iteraciones sucesivas, son iguales en un determinado número de dígitos (precisión).

Las derivadas parciales se calculan igual que en el método del descenso acelerado, es decir empleando la ecuación (14).

Algoritmo

El algoritmo que automatiza el proceso descrito en el anterior acápite, es el siguiente:

Newton para sistemas no lineales, algoritmo

El código respectivo, ha sido añadido como un método dinámico de la clase Function, por lo que debe ser llamado desde la función que devuelve el vector con los restos de las ecuaciones del sistema y se emplea igual que los dos métodos anteriores.

Ejemplo

Resuelva el sistema de ecuaciones del ejemplo 1 (ecuación 11) con el método de Newton con un error permitido de 6 dígitos, redondeando los resultados al sexto dígito después del punto.

\[ \begin{alignedat}{2} x^2+2y^2 &=& 22\\ -2x^2+xy-3y &=&-11 \end{alignedat} \]

La solución es similar a la de los otros métodos, excepto que ahora se llama al método de Newton:

var f = ([x, y]) =>[
Math.sqr(x)+2*Math.sqr(y)-22,
-2*Math.sqr(x)+x*y-3*y+11
];
f.newtonnl({vi:[1,2], err:6}).v.round(6)

Ecuaciones no lineales en Octave

Para resolver un sistemas de ecuaciones no lineales en Octave (y MatLab), se emplea la función fsolve, la cual recibe una función, que devuelve un vector con los valores de cada una de las ecuaciones del sistema igualadas a cero y un vector con los valores inicialmente asumidos para las soluciones.

La función que se manda a fsolve, debe recibir un vector, con un número de elementos, igual al número de ecuaciones del sistema. Cada uno de dichos elementos, corresponde a cada una de la variables del sistema.

Así, para resolver el siguiente sistema de ecuaciones lineales (ecuación 11):

\[ \begin{alignedat}{2} x^2+2y^2 &=& 22\\ -2x^2+xy-3y &=&-11 \end{alignedat} \]

Se escribe, en myCompiler:

format shortG; function res = f2(v) [x, y] = num2cell(v){:}; res = [x^2+2*y^2-22, -2*x^2+x*y-3*y+11]; end fsolve(@f2,[1.1,1.2]) % Resultados obtenidos: 2.0000 3.0000

En este ejemplo, en "v", se recibe el vector con los valores de las dos varíables (x, y) del sistema. Por claridad y para reducir la probabilidad de error, esos valores se guardan en las variables locales "x" y "y". Con esas variables se calculan (en un vector) los resultados de las dos ecuaciones del sistema. Los valores inicialmente asumidos, para "x" y "y", son 1.1 y 1.2.

Ecuaciones no lineales en Python

Para resolver un sistemas de ecuaciones no lineales en Python, se emplea, igualmente, la función fsolve, de la sublibrería optimize, de la librería scipy. Al igual que en JavaScript, Octave y MatLab, fsolve, recibe una función que, devuelve un vector, con los valores de cada una de las ecuaciones del sistema igualadas a cero.

La función que se manda a fsolve, debe recibir un vector con un número de elementos, igual al número de ecuaciones del sistema. Cada uno de dichos elementos corresponde a cada una de la variables del sistema.

Así, para resolver el siguiente sistema de ecuaciones lineales (ecuación 11):

\[ \begin{alignedat}{2} x^2+2y^2 &=& 22\\ -2x^2+xy-3y &=&-11 \end{alignedat} \]

Se escribe, en myCompiler:

from scipy.optimize import fsolve import numpy as np np.set_printoptions(suppress=True) def f(v): [x, y] = v return [x**2+2*y**2-22, -2*x**2+x*y-3*y+11] r = fsolve(f, [1.1, 1.2]) print(r.round(5)) % Resultados obtenidos: [2. 3.]

Que son los mismos resultados obtenidos con las otras aplicaciones (redondeados al quinto dígito después del punto). En este ejemplo se importa la librería numpy (como "np"), para suprimir la impresión de resultados en notación científica, con la función set_printoptions, mandando el parámetro suppress con un valor igual a True, porque, por defecto, los resultados que son arrays numpy, se muestran en notación científica.

Al igual que en Octave y Javascript, los valores del vector se asignan a variables locales, con los mismos nombres que en las ecuaciones, para poder escribir más fácilmente las ecuaciones y reducir así la probabilidad de cometer errores.