1

I went through the other post on this same topic. UnboundLocalError: local variable … referenced before assignment

But in my case, I have never mentioned local variables in another part of the code. Pycharm is indicating the problem is following function specifically "shell_cost". Which Is a part of the module 'economic' I call in a separate script. It says

  column_investment_cost = 4.74 * (shell_cost + (stages - 2) * sieve_tray_cost)
UnboundLocalError: local variable 'shell_cost' referenced before assignment

The function is

def column(tray_area, height, stages):
    tray_diameter = (tray_area * 4 / 3.1415926)**0.5
    if tray_diameter <= 0.5:
        shell_cost = 15.401 * height**2 + 1588.5 * height + 1495.5
    elif tray_diameter <= 1:
        shell_cost = 13.929 * height ** 2 + 2028.4 * height + 1850.6
    elif tray_diameter <= 2:
        shell_cost = 3.011 * height ** 2 + 3139.4 * height + 7166.9
    elif tray_diameter <= 3:
        shell_cost = -23.555 * height ** 2 + 5119.4 * height + 10945
    elif tray_diameter <= 4:
        shell_cost = -4.9723 * height ** 2 + 5021.1 * height + 24285 #???
    # else:
    #     shell_cost = 'out of range'
    sieve_tray_cost = -32.7 * tray_diameter**3 + 234.91 * tray_diameter**2 - 66.321 * tray_diameter + 293.53
    column_investment_cost = 4.74 * (shell_cost + (stages - 2) * sieve_tray_cost)
    return  column_investment_cost

I am using an optimization tool Rbfopt, which calls another function name Optimization and optimization uses the 'economic' module to calculate objective function.

bb = rbfopt.RbfoptUserBlackBox(3, lower_bound, upper_bound, ['I', 'I', 'I'], optimization)
settings = rbfopt.RbfoptSettings(minlp_solver_path='C://Python_package//bonmin.exe', nlp_solver_path='C://Python_package//ipopt.exe', max_evaluations=2000)
alg = rbfopt.RbfoptAlgorithm(settings, bb)
val, x, itercount, evalcount, fast_evalcount = alg.optimize()
print(x)
     #update the bound based on the first optimization results
t1_stop = perf_counter()
print("Elapsed time:", t1_stop, t1_start)
print("Elapsed time during the whole program in seconds:", t1_stop - t1_start)

Total Error Massage

Traceback (most recent call last):
  File "C:/Users/XXX/Desktop/L/EOoptx.py", line 144, in <module>
    val, x, itercount, evalcount, fast_evalcount = alg.optimize()
  File "C:\Users\XXX\Anaconda3\envs\Rdsk\lib\site-packages\rbfopt\rbfopt_algorithm.py", line 803, in optimize
    self.optimize_serial(pause_after_iters)
  File "C:\Users\XXX\Anaconda3\envs\Rdsk\lib\site-packages\rbfopt\rbfopt_algorithm.py", line 1131, in optimize_serial
    self.fixed_vars])
  File "C:\Users\XXX\Anaconda3\envs\Rdsk\lib\site-packages\rbfopt\rbfopt_algorithm.py", line 2829, in objfun
    return data[0].evaluate(point)
  File "C:\Users\czm0131\Anaconda3\envs\Rdsk\lib\site-packages\rbfopt\rbfopt_user_black_box.py", line 152, in evaluate
    return self.obj_funct(x)
  File "C:/Users/XXX/Desktop/L/EOoptx.py", line 120, in optimization
    D2_column_cost = economic.column(Tray_area_D2, H_D2, C2_stages)
  File "C:\Users\XXX\Desktop\L\Economic.py", line 89, in column
    column_investment_cost = 4.74 * (shell_cost + (stages - 2) * sieve_tray_cost)
UnboundLocalError: local variable 'shell_cost' referenced before assignment

1 Answers1

1

Your tray_diameter value goes above 4, and thus shell_cost is never assigned. It does not exist.

A 'quick fix' would be to avoid calculating the column_investment_cost when tray_diameter is above 4 and return a None value instead. But you'd need to be able to handle that value where you try to call column():

def column(tray_area, height, stages):
    tray_diameter = (tray_area * 4 / 3.1415926)**0.5

    if tray_diameter > 4:
        return None

    if tray_diameter <= 0.5:
        shell_cost = 15.401 * height**2 + 1588.5 * height + 1495.5
    elif tray_diameter <= 1:
        shell_cost = 13.929 * height ** 2 + 2028.4 * height + 1850.6
    elif tray_diameter <= 2:
        shell_cost = 3.011 * height ** 2 + 3139.4 * height + 7166.9
    elif tray_diameter <= 3:
        shell_cost = -23.555 * height ** 2 + 5119.4 * height + 10945
    elif tray_diameter <= 4:
        shell_cost = -4.9723 * height ** 2 + 5021.1 * height + 24285 #???
    # else:
    #     shell_cost = 'out of range'
    sieve_tray_cost = -32.7 * tray_diameter**3 + 234.91 * tray_diameter**2 - 66.321 * tray_diameter + 293.53
    column_investment_cost = 4.74 * (shell_cost + (stages - 2) * sieve_tray_cost)
    return  column_investment_cost

You could also move the tray_diameter to its own function, and only calculate shell_cost and the rest if the conditions are met:

def calculate_tray_diameter(tray_area):
    tray_diameter = (tray_area * 4 / 3.1415926)**0.5
    return tray_diameter

def column(tray_diameter, height, stages)
    if tray_diameter <= 0.5:
        shell_cost = 15.401 * height**2 + 1588.5 * height + 1495.5
    elif tray_diameter <= 1:
        shell_cost = 13.929 * height ** 2 + 2028.4 * height + 1850.6
    elif tray_diameter <= 2:
        shell_cost = 3.011 * height ** 2 + 3139.4 * height + 7166.9
    elif tray_diameter <= 3:
        shell_cost = -23.555 * height ** 2 + 5119.4 * height + 10945
    else:
        shell_cost = -4.9723 * height ** 2 + 5021.1 * height + 24285 #???
    # else:
    #     shell_cost = 'out of range'
    sieve_tray_cost = -32.7 * tray_diameter**3 + 234.91 * tray_diameter**2 - 66.321 * tray_diameter + 293.53
    column_investment_cost = 4.74 * (shell_cost + (stages - 2) * sieve_tray_cost)
    return  column_investment_cost

tray_diameter = calculate_tray_diameter(some_value)
if tray_diameter > 4:
    print("Cannot calculate cost!")
else:
    column_investment_cost = column(tray_diameter, height_value, stages_value)
JiyuuSensei
  • 524
  • 5
  • 11