Search code examples
pythonlambdasympy

'Mul' object is not callable when iterating a function


I have this code, I am trying to get the fixed points from a function in each iteration from 1 to n:

import sympy as sp

def logistica():
    return lambda r,x : r * x * (1 - x)

def orbitas_periodicas(f,n):
    """
    Calcula las órbitas periódicas con periodo 'n' de una función f
    que debe ser polinomica.
    """
    lista_res = [] # Lista de listas que guarda los puntos fijos de cada fk con k = 1,2,3,...,n
    x = sp.Symbol("x")
    for i in range(1, n+1):
        print(f"Calculando órbitas periódicas de periodo {i}")


        # Calculamos las raices de: ecuacion(x) = f(x) - x = 0 
        ecuacion = sp.Eq(f(x) - x, 0)

        raices = sp.solve(ecuacion)
        derivada = sp.diff(f(x), x) # Derivada de f 
        derivada = sp.lambdify(x, derivada)
        aux = []
        for raiz in raices:
            print(raiz)

            if abs(derivada(raiz)) < 1:
                aux.append((raiz, "atractivo"))
            elif abs(derivada(raiz)) > 1:
                aux.append((raiz, "repulsivo"))

        lista_res.append(aux)

        f = f(f(x))
     
    return lista_res

The function orbitas_periodicas is called like this:

f =lambda x: logistica()(5,x)
print(orbitas_periodicas(f, 2))

Here is the traceback

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

.../hoja1.ipynb Cell 22 line 6
      1 c = 5
      3 f =lambda x: logistica()(c,x)
----> 6 print(orbitas_periodicas(f, 2))

.../hoja1.ipynb Cell 22 line 1
      9 print(f"Calculando órbitas periódicas de periodo {i}")
     12 # Calculamos las raices de: ecuacion(x) = f(x) - x = 0 
---> 13 ecuacion = sp.Eq(f(x) - x, 0)
     15 raices = sp.solve(ecuacion)
     16 derivada = sp.diff(f(x), x) # Derivada de f 

TypeError: 'Mul' object is not callable

I guess that when I am doing f = f(f(x)) I am transforming my function into a type which isnt valid, but I dont know which is exactly the error.


Solution

  • You are mixing up Python lambdas and sympy expressions in an unfortunate way. So f should always be a Python lambda to transform a sympy expression into another sympy expression. Add another variable f_x which is always a sympy expression (resulting form a call to f).

    Calling f(x) multiple times is not necessary by the way (if f doesn't change) because it will always return the same expression for the same expression in x.

    Then this looks like:

    def orbitas_periodicas(f,n):
        """
        Calcula las órbitas periódicas con periodo 'n' de una función f
        que debe ser polinomica.
        """
        lista_res = [] # Lista de listas que guarda los puntos fijos de cada fk con k = 1,2,3,...,n
        x = sp.Symbol("x")
        f_x = f(x)
        for i in range(1, n+1):
            print(f"Calculando órbitas periódicas de periodo {i}")
    
            # Calculamos las raices de: ecuacion(x) = f(x) - x = 0 
            ecuacion = sp.Eq(f_x - x, 0)
    
            raices = sp.solve(ecuacion)
            derivada = sp.diff(f_x, x) # Derivada de f 
            derivada = sp.lambdify(x, derivada)
            aux = []
            for raiz in raices:
                print(raiz)
    
                if abs(derivada(raiz)) < 1:
                    aux.append((raiz, "atractivo"))
                elif abs(derivada(raiz)) > 1:
                    aux.append((raiz, "repulsivo"))
    
            lista_res.append(aux)
    
            f_x = f(f_x)
         
        return lista_res