【问题标题】:Python why does my variable leap_counter return the UnboundLocalError error message?Python为什么我的变量leap_counter返回UnboundLocalError错误信息?
【发布时间】:2020-05-31 17:19:07
【问题描述】:

我有以下功能来模拟生化系统随着时间的推移。代码背后的想法是对时间步进行采样,然后将它们添加到当前时间。

我有一个全局定义的开始时间:tao = 0.0

以及以下功能:

def gillespie_tau_leaping(propensity_calc, popul_num, popul_num_all, tao_all, rxn_vector, tao, epsi):
    t = simulation_timer()
    t.start()
    while tao < tmax:
        evaluate_propensity = propensity_calc(LHS, popul_num, stoch_rate)        
        a0 = (sum(propensity))  # a0 is a numpy.float64
        if a0 == 0.0: 
            break   
        if popul_num.any() < 0: # This isnt working
            print("Number of molecules {} is too small for reaction to fire".format(popul_num))
            break
        # code equation 26 here! 
        for x in range(len(popul_num)):
            # equation 22:
            expctd_net_change = a0*state_change_array[x]
            # equation 24:
            part_diff = derivative(evaluate_propensity, popul_num[x]) 
            # find the partial derivative of propensity with respect to popul_num (number of discrete molecules)
        # need to find a a way to SELECT delta_t before I can code it!
        # equation 26:
        t_step = epsi*a0 / sum(expctd_net_change*part_diff)
        delta_t = optimize.fmin(t_step, 0.00012) 
        print (delta_t)
        lam = (evaluate_propensity*delta_t) 
        rxn_vector = np.random.poisson(lam) # probability of a reaction firing in the given time period    
        if tao + delta_t > tmax:
            break    
        tao = tao + delta_t 
        leap_counter = tao / delta_t 
        if tao >= 2/a0:     # if tao is big enough
            for j in range(len(rxn_vector)):  
                state_change_lambda = np.squeeze(np.asarray(state_change_array[j])*rxn_vector[j])   
                #new_propensity = evaluate_propensity
                propensity_check = evaluate_propensity.copy()
                propensity_check[0] += state_change_lambda[0]
                propensity_check[1:] += state_change_lambda  
                for n in range(len(propensity_check)): 
                    if propensity_check[n] - evaluate_propensity[n] >= epsi*a0:   
                        print("The value of delta_t {} choosen is too large".format(delta_t))
                        break  
                    else:
                        popul_num = popul_num + state_change_lambda                  
                        popul_num_all.append(popul_num)
                        tao_all.append(tao) 
        else:
            t = np.random.exponential(1/a0)
            rxn_probability = evaluate_propensity / a0   
            num_rxn = np.arange(rxn_probability.size)       
            if tao + t > tmax:      
                tao = tmax
                break
            j = stats.rv_discrete(values=(num_rxn, rxn_probability)).rvs() 
            tao = tao + t
            popul_num = popul_num + np.squeeze(np.asarray(state_change_array[j]))  
            popul_num_all.append(popul_num)   
            tao_all.append(tao)
    print("tao:\n", tao)
    print("Molecule numbers:\n", popul_num)
    print("Number of leaps taken:\n", leap_counter)
    t.stop()
    return popul_num_all.append(popul_num), tao_all.append(tao)

print(gillespie_tau_leaping(propensity_calc, popul_num, popul_num_all, tao_all, rxn_vector, tao, epsi))

只有我得到错误:UnboundLocalError: local variable 'leap_counter' referenced before assignment 尝试打印或返回模拟期间所用的时间步数时,保存在变量 jump_counter 中,我不知道为什么。我试图稍微改变缩进,但这不起作用。发生了什么事,我该如何解决?

编辑:以下代码指定全局环境中 delta_t 的值。我试图在上面更新它,所以我在每次迭代中计算 delta_t 的值。但后来我遇到了跳跃计数器的问题。

def gillespie_tau_leaping(propensity_calc, popul_num, popul_num_all, tao_all, rxn_vector, tao, delta_t, epsi):
    t = simulation_timer()
    t.start()
    while tao < tmax:
        propensity = propensity_calc(LHS, popul_num, stoch_rate)       
        print("propensity:\n", type(propensity)) 
        a0 = (sum(propensity))
        if a0 == 0.0:
            break
        # if reaction cannot fire corresponding element in rxn_vector should be zero --> tau leaping method 
        if popul_num.any() < 0:
            print("Number of molecules {} is too small for reaction to fire".format(popul_num))
            break   
        lam = (propensity_calc(LHS, popul_num, stoch_rate)*delta_t)
        rxn_vector = np.random.poisson(lam)    
        if tao + delta_t > tmax:
            break
        tao += delta_t
        print("tao:\n", tao)
        print("Molecule numbers:\n", popul_num)
        # divide tao by delta_t to calculate number of leaps
        leap_counter = tao / delta_t   
        if tao >= 2/a0:     
            for j in range(len(rxn_vector)):
                state_change_lambda = np.squeeze(np.asarray(state_change_array[j])*rxn_vector[j]) 
                popul_num = popul_num + state_change_lambda
                new_propensity = propensity_calc(LHS, popul_num, stoch_rate)   
            for n in range(len(new_propensity)):
                propensity_check = propensity + state_change_lambda 
                if propensity_check[n] - new_propensity[n] >= epsi*a0:  
                    print("The value of delta_t {} choosen is too large".format(delta_t))
                    break
                else:
                    popul_num = popul_num + state_change_lambda     
                    popul_num_all.append(popul_num)   
                    tao_all.append(tao)
        else:
            next_t = np.random.exponential(1/a0)
            rxn_probability = propensity / a0   
            num_rxn = np.arange(rxn_probability.size)       
            if tao + next_t > tmax:      
                tao = tmax
                break
            j = stats.rv_discrete(values=(num_rxn, rxn_probability)).rvs()
            tao = tao + next_t
            popul_num = popul_num + np.squeeze(np.asarray(state_change_array[j]))   
    t.stop()
    return popul_num_all.append(popul_num), tao_all.append(tao), leap_counter

这段代码完全按照我的意愿工作,我无法理解的是第一个函数突然不了

干杯

【问题讨论】:

  • 请修正您的代码缩进。
  • leap_counter = tao / delta_t 之前的任何行都可能中止您的循环,如果您的循环甚至进入了?你确定tao &lt; tmax
  • 是 tmax = 5.0 和 tao = 到 0.0,都全局设置
  • 您没有考虑所有路径和错误情况。执行 0 次的 whilefor 怎么样?还是提前退出循环的中断?例如if popul_num.any() &lt; 0: break ... 然后你就不用处理了。
  • 请提供一个最小的、可重现的例子。有多个提前中断条件,我们不能排除您的函数被输入来触发这些条件。有关详细信息,请参阅How to Ask 页面。请注意,与描述相反,tao 是一个局部变量。您是否有理由尝试访问 leap_counter,即使它可能尚未设置?

标签: python scope variable-declaration


【解决方案1】:

leap_counter 仅在 while 循环内可见(因此可访问),尝试在循环外创建它(最好使用合理的默认值)。

【讨论】:

  • 不完全。它需要在while内计算,delta_t时间步可能在模拟过程中波动,因此在每次while循环迭代时计算。在计算之前将leap_counter移出循环引用delta_t
  • @Mike5298 - 该变量是否有合理的默认值?如果第一次调用函数时tao 大于tmax 怎么办?你没有提到哪一行有错误,是在print("Number of leaps taken:\n", leap_counter)吗?如果您正在记录变量,将其默认为None 是否有用?关键是,在 while 循环之外给这个变量一个默认值是有充分理由的。
  • @alagner - 我认为说“分配”而不是“声明”会更好 - 你不要在 python 中声明东西。
  • 第一次调用函数时 tao = 0.0 和 tmax = 20。抱歉,错误出现在打印行:'print("所采取的跳跃次数:\n",leap_counter)'
  • @tdelaney 对,我的措辞不准确,我修正了帖子,谢谢。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多