Pourquoi cette déclaration récursive est-elle fausse?
Question
Il s’agit d’une simulation bancaire prenant en compte 20 lignes de desserte différentes avec une seule file d’attente. Les clients arrivent selon un taux exponentiel et ils sont servis pendant une période qui suit une distribution de probabilité normale avec une moyenne de 40 et un écart type 20.
Les choses fonctionnaient bien jusqu'à ce que je décide d'exclure les valeurs négatives données par la distribution normale à l'aide de cette méthode:
def getNormal(self):
normal = normalvariate(40,20)
if (normal>=1):
return normal
else:
getNormal(self)
Est-ce que je bousille l'appel récursif? Je ne comprends pas pourquoi ça ne marcherait pas. J'ai changé la méthode getNormal () en:
def getNormal(self):
normal = normalvariate(40,20)
while (normal <=1):
normal = normalvariate (40,20)
return normal
Mais je suis curieux de savoir pourquoi la déclaration récursive précédente est interrompue.
Ceci est le code source complet, au cas où cela vous intéresserait.
""" bank21: One counter with impatient customers """
from SimPy.SimulationTrace import *
from random import *
## Model components ------------------------
class Source(Process):
""" Source generates customers randomly """
def generate(self,number):
for i in range(number):
c = Customer(name = "Customer%02d"%(i,))
activate(c,c.visit(tiempoDeUso=15.0))
validateTime=now()
if validateTime<=600:
interval = getLambda(self)
t = expovariate(interval)
yield hold,self,t #esta es la rata de generación
else:
detenerGeneracion=999
yield hold,self,detenerGeneracion
class Customer(Process):
""" Customer arrives, is served and leaves """
def visit(self,tiempoDeUso=0):
arrive = now() # arrival time
print "%8.3f %s: Here I am "%(now(),self.name)
yield (request,self,counter),(hold,self,maxWaitTime)
wait = now()-arrive # waiting time
if self.acquired(counter):
print "%8.3f %s: Waited %6.3f"%(now(),self.name,wait)
tiempoDeUso=getNormal(self)
yield hold,self,tiempoDeUso
yield release,self,counter
print "%8.3f %s: Completed"%(now(),self.name)
else:
print "%8.3f %s: Waited %6.3f. I am off"%(now(),self.name,wait)
## Experiment data -------------------------
maxTime = 60*10.5 # minutes
maxWaitTime = 12.0 # minutes. maximum time to wait
## Model ----------------------------------
def model():
global counter
#seed(98989)
counter = Resource(name="Las maquinas",capacity=20)
initialize()
source = Source('Source')
firstArrival= expovariate(20.0/60.0) #chequear el expovariate
activate(source,
source.generate(number=99999),at=firstArrival)
simulate(until=maxTime)
def getNormal(self):
normal = normalvariate(40,20)
if (normal>=1):
return normal
else:
getNormal(self)
def getLambda (self):
actualTime=now()
if (actualTime <=60):
return 20.0/60.0
if (actualTime>60)and (actualTime<=120):
return 25.0/60.0
if (actualTime>120)and (actualTime<=180):
return 40.0/60.0
if (actualTime>180)and (actualTime<=240):
return 30.0/60.0
if (actualTime>240)and (actualTime<=300):
return 35.0/60.0
if (actualTime>300)and (actualTime<=360):
return 42.0/60.0
if (actualTime>360)and (actualTime<=420):
return 50.0/60.0
if (actualTime>420)and (actualTime<=480):
return 55.0/60.0
if (actualTime>480)and (actualTime<=540):
return 45.0/60.0
if (actualTime>540)and (actualTime<=600):
return 10.0/60.0
## Experiment ----------------------------------
model()
La solution
Je pense que vous voulez
return getnormal(self)
au lieu de
getnormal(self)
Si la fonction se ferme sans toucher une instruction return, elle renvoie la valeur spéciale None, qui est un objet NoneType. C'est pourquoi Python se plaint d'un "NoneType". La fonction abs () veut un nombre et ne sait pas quoi faire avec un néant.
Vous pouvez également éviter la récursivité (et le coût de création d'un nouveau cadre de pile) en utilisant
def getNormal(self):
normal = 0
while normal < 1:
normal = normalvariate(40,20)
return normal
Autres conseils
Je ne suis pas tout à fait sûr, mais je pense que vous devez modifier votre méthode comme suit:
def getNormal(self):
normal = normalvariate(40,20)
if (normal>=1):
return normal
else:
return getNormal(self)
Vous devez avoir:
return getNormal(self)
au lieu de
getNormal(self)
Vraiment, il n'y a pas besoin de récursivité:
def getNormal(self):
normal = 0
while normal < 1:
normal = normalvariate(40,20)
return normal