I am trying to use SciPy's minimize function to maximize the results of my function f
. However, every time I run the script, I get the following error message.
Exception has occurred: TypeError
'float' object is not iterable
File "C:\Users\DonzaJ\OneDrive - LiRo Group\Desktop\Personal Files\Python Code\Fence Angle Optimizer.py", line 24, in <module>
theta_final = spo.minimize(f, theta, method = 'SLSQP', options ={'disp':True}, bounds = bdns)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'float' object is not iterable
Here is the script that I have set up so far.
import scipy.optimize as spo
import math as m
import numpy as np
# Define Constants
fenceLength = 7.5 #ft
pointLoad = 500 #lbs
ex2 = 2 #in
ey2 = 4 #in
# Define Initial Variables
theta = np.ndarray(45.0) #degrees
# Define bounds for theta
bdns = (0.0, 90.0)
def f(X, *args):
ex1 = (fenceLength/2)*m.cos(m.radians(theta))
ey1 = (fenceLength/2)*m.sin(m.radians(theta))
Y = m.sqrt(((pointLoad*(ey1+ey2))**2 + (pointLoad*(ex1+ex2))**2)) * -1
return Y
# Call minimizer
theta_final = spo.minimize(f, theta, method = 'SLSQP', options ={'disp':True}, bounds = bdns)
Can anyone explain to me how I can fix this and what I am doing wrong?
You have a couple of things wrong with your code.
np.ndarray(45.0)
does not make a numpy array, you need to do something like np.array([45.0])
. But, considering you only have one variable, you can just set theta0 = 45.0
.bnds = [(0.0, 90.0)]
.f
function needs to use the variable you are passing it, otherwise the optimizer will see no change in the results and assume it is already at a minimum. In other words, you should have ex1 = (fenceLength/2)*m.cos(m.radians(X))
.theta_final
will not take the optimal value but will be an OptimizerResult
, which you need to get the value from.Below is the updated code that removes the numpy import, since it is unnecessary, makes the necessary changes outlined above, and updates some of the notation to be more standard.
from scipy.optimize import minimize
import math
# Define Constants
fenceLength = 7.5 #ft
pointLoad = 500 #lbs
ex2 = 2 #in
ey2 = 4 #in
# Define Initial Variables
theta0 = 45.0 #degrees
# Define bounds for theta
bdns = [(0.0, 90.0)]
def f(X, *args):
ex1 = (fenceLength/2)*math.cos(math.radians(X))
ey1 = (fenceLength/2)*math.sin(math.radians(X))
Y = -math.sqrt(((pointLoad*(ey1+ey2))**2 + (pointLoad*(ex1+ex2))**2))
return Y
# Call minimizer
res = minimize(f, theta0, method = "SLSQP", options={"disp":True}, bounds=bdns)
theta = res.x[0]
print(f"{theta = } deg")
Output:
Optimization terminated successfully (Exit mode 0)
Current function value: -4111.067977477818
Iterations: 4
Function evaluations: 8
Gradient evaluations: 4
theta = 63.43457272808145 deg