使用NumPy数组和向量化,我试图创建一组n
个不同的个体,每个个体具有三个属性:alpha
,beta
和{{1 }}(phenotype
被计算为涉及phenotype
和alpha
的微分方程的稳态)。所以,我希望每个人都有自己的表型。
但是,我的代码为每个人产生相同的表型。此外,只有在beta
的{{1}}数组(这里是n
)中恰好有solve_ivp
个条目(这里是y0
)时,才会发生这种有害行为-否则会出现广播错误产生:
[0, 1]
代码如下:
ValueError: operands could not be broadcast together with shapes (2,) (3,)
相比之下,如果通过“简单”等式从import numpy as np
from scipy.integrate import solve_ivp
def create_population(n):
"""creates a population of n individuals"""
pop = np.zeros(n, dtype=[('alpha','<f8'),('beta','<f8'),('phenotype','<f8')])
pop['alpha'] = np.random.randn(n)
pop['beta'] = np.random.randn(n) + 5
def phenotype(n):
"""creates the phenotype"""
def pheno_ode(t_ode, y):
"""defines the ode for the phenotype"""
dydt = 0.123 - y + pop['alpha'] * (y ** pop['beta'] / (1 + y ** pop['beta']))
return dydt
t_end = 1e06
sol = solve_ivp(pheno_ode, [0, t_end], [0, 1], method='BDF')
return sol.y[0][-1] # last entry is assumed to be the steady state
pop['phenotype'] = phenotype(n)
return pop
popul = create_population(3)
print(popul)
和alpha
计算表型,则向量化可以正常工作:
beta
答案 0 :(得分:0)
我可以看到两个问题:
首先,您将ODE的初始条件设置为[0, 1]
。将solve_ivp
的向量解的大小设置为2,而不考虑n
的值。但是,数组pop['alpha']
和pop['beta']
的长度为n
,并且在脚本中,您将create_population
设置为3的情况下调用了n
。 dydt
的公式中的数组形状中:y
的长度为2,但是pop['alpha']
和pop['beta']
的长度为3。这会导致您看到错误。
您可以通过使用np.ones(n)
而不是[0, 1]
作为对solve_ivp
的调用的初始条件来解决此问题。
第二个问题是函数return sol.y[0][-1]
中的语句phenotype(n)
。 sol.y
的形状为(n, num_points)
,其中num_points
是solve_ivp
计算的点数。因此,sol.y[0]
只是解决方案的第一个组成部分,sol.y[0][-1]
是第一个组件的解决方案的最后一个值。这是一个标量,因此当执行pop['phenotype'] = phenotype(n)
时,您将为所有表型分配相同的值(第一个组件的稳态)。
return语句应为return sol.y[:, -1]
。返回结果数组的最后一个列(即所有稳态表型)。