def Interpolacion_Lagrange(nombre):
    """Funcion que construira el Polinomio Interpolante de Lagrange"""
    # Primero llena una matriz con los datos contenidos en el documento de texto
    matDatos = LLenar_Matriz_Datos(nombre)

    # Manda a llamar a la funcion 'Opciones' para pedir al usuario que elija una opcion para usar la formula de lagrange, saber cuales son
    # los datos que el usuario desea elegir y para almacenar los indices de las filas de 'matDatos' que se van a usar en 'indicesDatos'
    indicesDatos = OpcionesLag(matDatos)

    # Revisa el contenido del primer elemento de 'indicesDatos' para saber que opcion eligio el usuario
    if indicesDatos[0] == 1 or indicesDatos[
            0] == 2:  # Construye el Polinomio Interpolante de Lagrange
        opcionAux = indicesDatos[0]
        # Elimina el primer elemento de 'indicesDatos'
        indicesDatos = indicesDatos[1:]
        # Ordena los indices de forma ascendente y elimina los valores duplicados
        indicesDatos = list(set(indicesDatos))

        # Crea la lista que contendra los polinomios de lagrange
        PolinomiosInterLag = list()

        # Declara las variables que contendran la expresiones que estaran en el numerador y en el denominador de cada polinomio de lagrange
        numerador = ""
        denominador = ""

        cont = 0
        # Bucle que construye el polinomio interpolante de lagrange
        for elemento in indicesDatos:
            # Bucle que construira el numerador
            for elemNum in indicesDatos:
                # Condicional que se saltara este paso en caso de que lleguemos al elemento que no ira en el numerdor
                if elemNum == elemento:
                    # Almacena en la variable 'elemFunAux' el indice del valor que estamos saltando para despues
                    # usarlo al multiplicar los polinomio interpolantes por el valor de la funcion en ese punto
                    elemFunAux = elemNum
                    continue
                else:
                    numerador += f"(x - {matDatos[elemNum, 0]})*"
            # Elimina el ultimo signo '*' de la cadena almacenada en la variable 'numerador'
            numerador = "(" + numerador[:(len(numerador) - 1)] + ")"

            # Bulce que construira el denominador
            for elemDen in indicesDatos:
                # Condicional que se saltara este paso en caso de que lleguemos al elemento que no ira en el numerdor
                if elemDen == elemento:
                    continue
                else:
                    denominador += f"({matDatos[elemento, 0]} - {matDatos[elemDen, 0]})*"
            # Elimina el ultimo signo '*' de la cadena almacenada en la variable 'denominador'
            denominador = "(" + denominador[:(len(denominador) - 1)] + ")"

            # Agrega a la lista de polinomio el polinomio que se forma con el numerador y el denominador de los bucles anteriores
            PolinomiosInterLag.append(f"{numerador} / {denominador}")

            numerador = ""
            denominador = ""

            # Multiplica el polinomio interpolante de lagrange por el valor de la funcion
            PolinomiosInterLag[
                cont] = "(" + f"({round(matDatos[elemFunAux, 1], 6)}) * " + f"({PolinomiosInterLag[cont]})" + ")"

            cont += 1

        # Declara variable que contendra el polinomio aplicando la formula de lagrange
        polinomio = ""

        # Bucle que convertira de formato 'srt' a formato de sagemath los polinomios obtenidos por los bucles anteriores y los sumara
        for pol in PolinomiosInterLag:
            polinomio += pol + "+"

        # Elimina el ultimo signo '+' de la cadena almacenada en la variable 'polinomio'
        polinomio = polinomio[:(len(polinomio) - 1)]

        if opcionAux == 1:  # Convierte la cadena de caracteres que contiene el polinomio en formato de sagemath
            polinomio = SR(polinomio)

            # Simplifica el polinomio resultante y lo imprime
            print(
                f"\n\nEl Polinomio Interpolante es: {polinomio.simplify_full()}\n"
            )

        else:  # Sustituye el punto que se quiere calcular por las 'x' que aparecen en la cadena de caracteres que contiene el polinomio
            x = float(input(
                "\nIngresa una abscisa: "))  # Pide al usuario una abscisa
            polinomio = polinomio.replace('x', str(x))
            polinomio = SR(polinomio)

            # Simplifica el resultado y lo imprime redondeandolo a 8 decimales
            print(
                f"\n\nEl valor de la funcion en el punto {x} es aproximadamente: {round(polinomio.simplify_full(), 8)}\n"
            )
Esempio n. 2
0
def Interpolacion_Diferencias_Divididas(nombre):
    """Funcion que construira el Polinomio Interpolante de Newton"""
    # Primero llena una matriz con los datos contenidos en el documento de texto
    matDatos = LLenar_Matriz_Datos(nombre)
    # Une la matriz 'matDatos' con otra matriz de ceros de orden n x n - 1, donde n es el numero de datos
    matDatos = np.copy(
        np.append(matDatos,
                  np.zeros((matDatos.shape[0], (matDatos.shape[0] - 1)),
                           dtype='f'),
                  axis=1))

    # Bucle que se repetira hasta calcular la ultima diferencia dividida posible
    # Este contador se utilizara para indexar los valores de las columnas de 'matDatos' [Burden p. 124]
    for cont1 in range(1, matDatos.shape[0]):
        #  Este contador se utilizara para indexar los valores de las filas de 'matDatos'
        cont2 = 0
        # Bucle que calcula los elementos de la tabla de diferencias divididas
        for elemRengl in range(cont1, matDatos.shape[0]):
            # La variable 'elemRengl' va a indexar la fila del valor de x que se va a usar en el minuendo (primer elemento de la resta)
            matDatos[cont2, (
                cont1 +
                1)] = (matDatos[(cont2 + 1), cont1] - matDatos[cont2, cont1]
                       ) / (matDatos[elemRengl, 0] - matDatos[cont2, 0])
            cont2 += 1

    np.set_printoptions(precision=6, suppress=True)

    # Imprime la matriz 'matDatos'
    print("\n" + "\n".join([
        ''.join(['{:12}'.format(round(val, 6)) for val in fila])
        for fila in matDatos
    ]) + "\n")

    # Pide al usuario el grado del polinomio
    while True:
        try:
            num = int(
                input(
                    "Ingrese el grado del polinomio que quiera usar para el calculo: "
                ))
            if num > 0 and num < (matDatos.shape[1] - 1):
                break
            print("Entrada invalida")
        except:
            print("Entrada invalida")

    # Crea la variable que contendra el polinomio en formato'str'
    polinomio = f"({round(matDatos[0, 1], 8)})+"  # Primero agrega el primer termino del polinomio (constante)
    # Lista que contendra los terminos lineales
    terLin = [f"(x - {round(matDatos[0, 0], 6)})"
              ]  # Almacena el primer termino lineal en la lista
    # Bucle que construye el polinomio usando como coeficientes los elementos de la primera fila de la matriz
    for coeficientes in range(1, num + 1):
        polinomio += f"({round(matDatos[0, (coeficientes + 1)], 8)}"
        # Bucle que agregara los terminos lineales al polinomio
        for terminosLineales in terLin:
            polinomio += f" * {terminosLineales}"
        polinomio += ")+"

        # Agrega un nuevo termino a la lista de terminos lineales
        terLin.append(f"(x - {round(matDatos[coeficientes, 0], 6)})")

    # Elimina el ultimo signo '+' que esta en la cadena que contiene el polinomio
    polinomio = polinomio[:(len(polinomio) - 1)]

    # Pide al usuario que elija una opcion
    opcion = OpcionesDifDiv()

    if opcion == 1:
        # Imprime el polinomio interpolante
        print(f"\n\nEl Polinomio Interpolante es: {polinomio}\n")

        while True:
            print("Desea simplificar? Si - 1, No - 2: ", end='')
            try:
                opcion = int(input())
                if opcion > 0 and opcion < 3:
                    print()
                    break
                print("Opcion invalida!!!")
            except:
                print("Opcion invalida!!!")

        # Si el usuario desea simplificar el polinomio lo convierte a formato sagemath y lo simplifica
        if opcion == 1:
            polinomio = SR(polinomio)

            # Simplifica el polinomio resultante y lo imprime
            print(
                f"\n\nEl Polinomio Interpolante es: {polinomio.simplify_full()}\n"
            )

    else:  # Sustituye el punto que se quiere calcular por las 'x' que aparecen en la cadena de caracteres que contiene el polinomio
        x = float(
            input("\nIngresa una abscisa: "))  # Pide al usuario una abscisa
        polinomio = polinomio.replace('x', str(x))
        polinomio = SR(polinomio)

        # Simplifica el resultado y lo imprime redondeandolo a 8 decimales
        print(
            f"\n\nEl valor de la funcion en el punto {x} es aproximadamente: {round(polinomio.simplify_full(), 8)}\n"
        )