package optimizacion;
import operaciones.Matriz;

/**
 * <p>Title: Ceros de una funcion</p>
 * <p>Description: Calcula los zeros de una funcion utilizando algunos de los
 * metodos mas conocidos</p>
 * <p>Copyright: Copyright (c) 2005</p>
 * <p>Company: UMSNH</p>
 * @author Dr. Felix Calderon Solorio
 * @version 1.0
 */

public class zeros {
     private double T=1e-3;

     /**
      * M�teodo de Biseccines. Calcula la soluci�n haciendo divisiones sucesivas
      * hasta llegar a una tolerancia. La funci�n debe tener un zero en el
      * intervalo [a, b]
      * @param a double l�mite inferior
      * @param b double l�mite superior
      */

     public void biseccion(double a, double b){
         double c;
         int i = 1;

         do {
             c = (a + b) / 2.0;
             System.out.println("iter: " + i + " a: " + a + " c: " + c + " b: " + b +
                                " f(a): " + funcion(a) + " f(c): " + funcion(c) +
                                " f(b): " + funcion(b));
             if ((funcion(a) * funcion(c)) < 0)
                 b = c;
             else
             if ((funcion(c) * funcion(b)) < 0)
                 a = c;

             i++;
         } while (Math.abs(funcion(c)) > T);
     }

     /**
      * M�teodo de Regula Falsi. Calcula la soluci�n haciendo una aproximaci�n
      * lineal en el [a, b] en donde existe un zero
      * @param a double l�mite inferior
      * @param b double l�mite superior
      */

     public void Regla_falsa(double a, double b){
         double c, tope;
         int i = 1;

         do {
             c = a + ((a - b) * funcion(a)) / (funcion(b) - funcion(a));
             System.out.println("iter: " + i + " a: " + a + " c: " + c + " b: " +
                                b + " f(a): " + funcion(a) + " f(c): " +
                                funcion(c) + " f(b): " + funcion(b));
             if ((funcion(a) * funcion(c)) < 0)
                 b = c;
             else
             if ((funcion(c) * funcion(b)) < 0)
                 a = c;
             i++;
         } while (Math.abs(funcion(c)) > T);
     }

     /**
      * M�todo de Newton Raphson. Calcula el zero de la funci�n dado una aproximaci�n
      * inicial al valor. Este m�todo trabaja solo en una dimensi�n
      * @param x0 double
      */

     public void Newton_Raphson(double x0){
         int i = 1;
         double x;

         do {
             x = (x0 - (funcion(x0) / derivada(x0)));
             System.out.println("iter: " + i + " x0: " + x0 + " x: " + x +
                                " f(x0): " + funcion(x0) + " f(x): " + funcion(x));
             x0 = x;
             i++;
         } while (Math.abs(funcion(x0)) > T);
     }

     /**
      * M�todo de Newton Raphson. Calcula el zero de la funci�n dado una aproximaci�n
      * inicial al valor.
      * @param r Matriz
      * @return Matriz
      */

     public Matriz Newton_Raphson(Matriz r) {
       int k = 0;
       double tol;

       do {
           System.out.println("iteracion " + k );
           r.imprime();
           r = r.menos(funcion(r).entre(J(r)));
           k++;
           tol = (funcion(r).T()).por(funcion(r)).obten(0,0);
           System.out.println("Tol = " + tol);
       } while ( Math.abs(tol) > T);
       return r;
     }

     /**
      * M�todo de secante en n-dimensiones
      * @param x Matriz valor incial
      * @return Matriz
      */

     public Matriz Secante(Matriz x) {
         int k = 0;
         double tol, ss;
         Matriz A = J(x);
         Matriz s = null, y = null, g1 = null, g0 = funcion(x);
         Matriz aux = null;

         do {
             System.out.println("iteracion " + k);
             x.imprime();
             s = (g0.entre(A)).por( -1);
             x = x.mas(s);
             g1 = funcion(x);
             y = g1.menos(g0);

             ss = 1.0 / (s.T().por(s)).obten(0, 0);

             aux = (y.menos(A.por(s))).por(s.T());

             A = A.mas(aux.por(ss));
             k++;
             tol = (g1.T()).por(g1).obten(0, 0);
             g0 = Matriz.igual_a(g1);
             System.out.println("Tol = " + tol);
         } while (Math.abs(tol) > T);
         System.out.println("La solucion en " + k + " iteraciones es x* = ");
         x.imprime();
         return x;
     }

     /**
      * M�todo de Secante unidimensional. Calcula el zero de una funci�n en el
      * intervalo [x0, x1]
      * @param x0 double l�mite inferior del intervalo
      * @param x1 double l�mite superior del intervalo
      * @return double
      */

     public double secante(double x0, double x1){
         int i = 1;
         double m;

         while (Math.abs(funcion(x1)) > T) {
             System.out.println("iter: " + i + " x0: " + x0 + " x1: " + x1 +
                                " f(x0): " + funcion(x0) + " f(x1): " + funcion(x1));
             m = (funcion(x1) - funcion(x0)) / (x1 - x0);
             x0 = x1;
             x1 = x1 - funcion(x1) / m;
             i++;
         }
         System.out.println("iter: " + i + " x0: " + x0 + " x1: " + x1 + " f(x0): " +
                            funcion(x0) + " f(x1): " + funcion(x1));
         return x1;
     }

     /**
      * M�todo de Newton Raphson Modificado. Calcula los zeros de una funci�n
      * en una dimensi�n la cual tiene raices multiples
      * @param x0 double
      * @return double
      */

     public double Newton_Raphson_Modificado(double x0){
         int i = 0;
         while (Math.abs(funcion(x0)) > T) {
             System.out.println("Iter: " + i + " x: " + x0 + " f(x0): " +
                                funcion(x0));
             x0 = x0 -
                  (funcion(x0) * derivada(x0)) /
                  (derivada(x0) * derivada(x0) - funcion(x0) * dderivada(x0));
             i++;
         }
         System.out.println("Iter: " + i + " x: " + x0 + " f(x0): " +
                            funcion(x0));
         return x0;
     }

     /**
      * Funci�n objetivo generica en una dimensi�n
      * @param x0 double punto de evaluaci�n
      * @return double
      */

     public double funcion(double x0){
         return 0;
     }

     /**
      * Primer derivada de la funci�n objetivo unidemensional
      * @param x double
      * @return double
      */

     public double derivada(double x){
         return 0;
     }

     /**
      * Segunda derivada de la funci�n objetivo unidemensional
      * @param x double
      * @return double
      */

     public double dderivada(double x){
         return 0;
     }

     /**
      * Funci�n objetivo gen�rica en n-dimensiones
      * @param r Matriz
      * @return Matriz
      */

     public Matriz funcion(Matriz r){
       return null;
     }

     /**
      * Matriz Jacobiana de primeras derivadas de la funci�n objetivo en
      * n-dimensiones.
      * @param r Matriz
      * @return Matriz
      */

     public Matriz J(Matriz r){
       return null;
     }
}

