1
0
mirror of https://github.com/gsi-upm/soil synced 2024-11-14 15:32:29 +00:00

Fix die bug

This commit is contained in:
J. Fernando Sánchez 2022-03-07 11:17:27 +01:00
parent 38f8a8d110
commit c02e6ea2e8
4 changed files with 31 additions and 6 deletions

View File

@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.20.1]
### Fixed
* Agents would run another step after dying.
## [0.20.0] ## [0.20.0]
### Added ### Added
* Integration with MESA * Integration with MESA

View File

@ -4,20 +4,34 @@ Example of a fully programmatic simulation, without definition files.
''' '''
from soil import Simulation, agents from soil import Simulation, agents
from soil.time import Delta from soil.time import Delta
from networkx import Graph
from random import expovariate from random import expovariate
import logging import logging
class MyAgent(agents.FSM): class MyAgent(agents.FSM):
'''
An agent that first does a ping
'''
defaults = {'pong_counts': 2}
@agents.default_state @agents.default_state
@agents.state @agents.state
def neutral(self): def ping(self):
self.info('I am running') self.info('Ping')
return self.pong, Delta(expovariate(1/16))
@agents.state
def pong(self):
self.info('Pong')
self.pong_counts -= 1
self.info(str(self.pong_counts))
if self.pong_counts < 1:
return self.die()
return None, Delta(expovariate(1/16)) return None, Delta(expovariate(1/16))
s = Simulation(name='Programmatic', s = Simulation(name='Programmatic',
network_agents=[{'agent_type': MyAgent, 'id': 0}], network_agents=[{'agent_type': MyAgent, 'id': 0}],
topology={'nodes': [{'id': 0}], 'links': []}, topology={'nodes': [{'id': 0}], 'links': []},

View File

@ -1 +1 @@
0.20.0 0.20.1

View File

@ -20,6 +20,10 @@ def as_node(agent):
IGNORED_FIELDS = ('model', 'logger') IGNORED_FIELDS = ('model', 'logger')
class DeadAgent(Exception):
pass
class BaseAgent(Agent): class BaseAgent(Agent):
""" """
A special Agent that keeps track of its state history. A special Agent that keeps track of its state history.
@ -129,13 +133,14 @@ class BaseAgent(Agent):
return None return None
def die(self, remove=False): def die(self, remove=False):
self.info(f'agent {self.unique_id} is dying')
self.alive = False self.alive = False
if remove: if remove:
self.remove_node(self.id) self.remove_node(self.id)
def step(self): def step(self):
if not self.alive: if not self.alive:
return time.When('inf') raise DeadAgent(self.unique_id)
return super().step() or time.Delta(self.interval) return super().step() or time.Delta(self.interval)
def log(self, message, *args, level=logging.INFO, **kwargs): def log(self, message, *args, level=logging.INFO, **kwargs):
@ -300,7 +305,10 @@ class FSM(NetworkAgent, metaclass=MetaFSM):
def step(self): def step(self):
self.debug(f'Agent {self.unique_id} @ state {self.state_id}') self.debug(f'Agent {self.unique_id} @ state {self.state_id}')
try:
interval = super().step() interval = super().step()
except DeadAgent:
return time.When('inf')
if 'id' not in self.state: if 'id' not in self.state:
# if 'id' in self.state: # if 'id' in self.state:
# self.set_state(self.state['id']) # self.set_state(self.state['id'])