2016-12-26 5 views
0

Я хочу использовать OdeINT Python для интеграции нескольких наборов уравнений, которые генерируются циклом. Уравнения все связаны и поэтому должны быть интегрированы одновременно через один вызов odeINT. Проблема в том, что начальные условия («y0») должны быть списком списков или матрицей (а не просто списком). odeINT дает эту ошибку: «Начальное условие y0 должно быть одномерным». Мне интересно, как обойти это. Вот пример кода; Большое спасибо за любые идеи.Проблема с получением odeINT для принятия уравнений, сгенерированных циклом

class network: 
    def __init__(self): 
     self.i_range = 3 
     ## INITIAL CONDITIONS WILL BE A LIST OF LISTS. 
     ## THIS IS THE SOURCE OF odeINT's ERROR. 
     self.init = [[] for i in range(self.i_range)] 
     for i in range(0,self.i_range): 
      self.init[i].append(-50.+0.1*(random.random())) 
      self.init[i].append(1.+1.*(random.random())) 

     self.Tfinal = 10 # final time 
     self.dt = 1. # time step 

    def eqns(self, x, t): 
     a, b = x 
     dadt = zeros_like(a) 
     dbdt = zeros_like(b) 
     for i in range (0,i_range): 
      dadt[i] = np.cos(b[i]) 
      dbdt[i] = np.sin(a[i]) 
     return dadt, dbdt 

    def run(self): 
     self.times = sp.arange(0,self.Tfinal,self.dt) 
     self.sim = odeint(self.eqns,self.init,self.times) 

ответ

0

Применение

a,b = reshape(x,(2,-1)) 

разделить плоский вектор и

return reshape((dadt,dbdt), -1) 

рекомбинировать их в плоский массив. См https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html


Более конкретно, и играть с некоторыми из функциональных возможностей списка питона, в инициализации сделать

a = [ -50. + 0.1*random.random() for _ in range(self.i_range) ] 
b = [ 1. + 1.0*random.random() for _ in range(self.i_range) ] 
self.init = np.reshape((a,b), -1) 

и функция ода становится

def eqns(self, x, t): 
    a, b = np.reshape(x,(2,-1)) 
    dadt = [ np.cos(bb) for aa,bb in zip(a,b) ] 
    dbdt = [ np.sin(aa) for aa,bb in zip(a,b) ] 
    return np.reshape((dadt,dbdt), -1) 

Это должно быть достаточно чтобы получить некоторый результат. Возможно, вы захотите преобразовать self.sim в список пар списков, чтобы восстановить структуру проблемы, но там вам нужно работать, так как теперь есть 2 «больших» размера.

np.reshape(self.sim, (self.times.size,2,-1)) 

может работать в качестве первого шага ..

+0

спасибо за эту помощь. Я реализовал это в разделе eqns, но я не понимаю, как переформатировать исходные условия («self.init»). Как вы можете видеть в приведенном выше примере кода, у меня есть два отдельных местоположения для цикла через ИС (около вершины, в «я») и через переменные (ниже, в «eqns»). Должен ли я попытаться включить один цикл для обоих? – eve

+0

Я спрашиваю о объединении циклов, потому что: когда я петлю более одного раза, я получаю ошибку: «слишком много значений для распаковки». Это происходит потому, что, скажем, я повторяю дважды: сначала он видит 4 ИС, затем он видит, что «eqns» вызывает только 2 переменные - прежде чем он узнает, что они дважды проедут через них. – eve

+0

Является ли ваше намерение первым значением [i] и вторым b [i]? Затем запустите 'init' как' [[], []] 'как пару из двух списков и добавьте к первой и второй. Или используйте локальные переменные 'a0 = []; b0 = []; ', добавьте к ним и объедините их через' self.init = reshape ((a0, b0), -1) ', так что все сглаживание и структурирование происходят с одними и теми же методами. Вектор состояния для интеграции должен быть плоским списком или вектором во всех случаях, когда он передается интегратору. – LutzL