Search code examples
pythonoptimizationfunctionderivative

How to use a global variable (derivative expression) inside a function


This script works perfectly for what I want. It is a weight function that I want to minimize. I wrote inside a function and globally and I noticed that the global print(W) is my expression and the print(W) inside the function is the array of values to be plotted:

import numpy as np
from sympy import *
import matplotlib.pyplot as plt

#Weight function

tf = Symbol('tf')
l = 50/(0.54*tf) - tf
d = (tf*(2*l+2*(l-tf)/2))/(2*l*(l+tf)/2)
W = 15.7*tf-7.85*tf*d+7.85*d*50/(0.54*tf)
print(W)

def func(tf):
    l = 50/(0.54*tf) - tf
    d = (tf*(2*l+2*(l-tf)/2))/(2*l*(l+tf)/2)
    W = 15.7*tf-7.85*tf*d+7.85*d*50/(0.54*tf)
    print(W)
    return W

b = np.linspace(1, 10, 201)
plt.plot(b, func(b))
plt.xlabel("tf", fontsize=18)
plt.ylabel("Weight", fontsize=18)
plt.grid()
plt.show()

My problem happens now. I want the weight function derivative plotted as well. But I can't do it inside the function because it recognizes as a number (first element of the array). The first print gives me the expression I want to plot but I cannot send that expression inside the function. How can I call a global variable (derivative expression) to be used inside the function?

dW_dtf = W.diff(tf)
print(dW_dtf)

def funcd(tf):
    l = M/(a*tf) - tf
    tw = tf
    d = (tw*(2*l+2*(l-tw)/2))/(2*l*(l+tw)/2)
    W = 15.7*tf-7.85*tf*d+7.85*d*M/(a*tf)
    dW_dtf = W.diff(tf)
    return dW_dtf

AttributeError: 'numpy.ndarray' object has no attribute 'diff'

I'm open to other options to do what I want. I will be reading more about optimization algorithms using python because I will have to solve more difficult problems but I would like to make this kind of basic problems without using iterative methods. Thank you. Luis


Solution

  • In your code, you are essentially overriding your global definition. Right now, when you call func, you redefine W using whatever value you submitted as tf. In your case, an array. In that way, W is no longer a symbolic expression but plainly an array. What you want is something like this instead of func:

    def func(x):
        w_evaluator=lambdify(tf,W)
        return w_evaluator(x)
    

    And analogously:

    def funcd(x):
         dwdt_evaluator=lambdify(tf,W.diff(tf))
         return dwdt_evaluator(x)