2016-12-26 2 views
0

Je souhaite utiliser l'odeINT de Python pour intégrer plusieurs jeux d'équations générés par une boucle. Les équations sont toutes couplées et doivent donc être intégrées simultanément, via un appel à odeINT. Le problème est que les conditions initiales ("y0") doivent être une liste de listes ou une matrice (plutôt qu'une simple liste). odeINT donne cette erreur: "La condition initiale y0 doit être unidimensionnelle". Je me demande comment contourner cela. Voici un exemple du code; merci beaucoup pour vos idées.Problème lors de l'obtention par odeINT des équations générées par une boucle

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) 

Répondre

0

utilisation

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

pour diviser le vecteur plat et

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

pour les recombiner en un réseau plat. Voir https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html


Plus concrètement, et jouer avec certaines des fonctionnalités de liste de python, dans l'initialisation ne

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) 

et la fonction ode devient

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) 

Cela devrait être suffisant pour obtenir un résultat. Vous voudrez peut-être transformer self.sim en une liste de paires de listes pour retrouver la structure du problème, mais là vous devez travailler, car il y a maintenant 2 "grandes" dimensions à fournir.

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

pourrait fonctionner comme une première étape ..

+0

Merci beaucoup pour cette aide. J'ai implémenté cela dans la section eqns, mais je ne comprends pas comment reformater les conditions initiales ("self.init"). Comme vous pouvez le voir dans l'exemple de code ci-dessus, j'ai deux emplacements séparés pour une boucle à travers les CI (près du haut, en "self") et à travers les variables (ci-dessous, dans "eqns"). Dois-je essayer d'incorporer une seule boucle pour les deux? – eve

+0

Je pose des questions sur la combinaison de boucles car: lorsque je boucle plus d'une fois, j'obtiens l'erreur: "trop ​​de valeurs à décompresser". C'est parce que, dis-je boucle deux fois: Il voit d'abord 4 circuits intégrés, puis il voit que "eqns" appelle seulement 2 variables - avant qu'il sache faire deux fois la boucle à travers eux. – eve

+0

Votre intention est-elle que la première valeur soit a [i] et la seconde b [i]? Puis lancez init comme '[[], []]' comme une paire de deux listes et ajoutez-les au premier et au second. Ou utilisez les variables locales 'a0 = []; b0 = []; ', ajoutez-y et combinez-les via' self.init = reshape ((a0, b0), -1) ', de sorte que tout aplatissement et structuration se fasse avec les mêmes méthodes. Le vecteur d'état pour l'intégration doit être une liste plate ou un vecteur dans tous les cas où il est transmis à l'intégrateur. – LutzL