mirror of
https://github.com/gsi-upm/soil
synced 2025-08-23 19:52:19 +00:00
1.0pre4
This commit is contained in:
1
examples/README.md
Normal file
1
examples/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Some of these examples are close to real life simulations, whereas some others are only a demonstration of Soil's capatibilities.
|
@@ -86,7 +86,7 @@ class Driver(Evented, FSM):
|
||||
earnings = 0
|
||||
|
||||
def on_receive(self, msg, sender):
|
||||
"""This is not a state. It will run (and block) every time check_messages is invoked"""
|
||||
"""This is not a state. It will run (and block) every time process_messages is invoked"""
|
||||
if self.journey is None and isinstance(msg, Journey) and msg.driver is None:
|
||||
msg.driver = self
|
||||
self.journey = msg
|
||||
@@ -95,15 +95,14 @@ class Driver(Evented, FSM):
|
||||
"""If there are no more passengers, stop forever"""
|
||||
c = self.count_agents(agent_class=Passenger)
|
||||
self.debug(f"Passengers left {c}")
|
||||
if not c:
|
||||
self.die("No more passengers")
|
||||
return c
|
||||
|
||||
@default_state
|
||||
@state
|
||||
def wandering(self):
|
||||
@state(default=True)
|
||||
async def wandering(self):
|
||||
"""Move around the city until a journey is accepted"""
|
||||
target = None
|
||||
self.check_passengers()
|
||||
if not self.check_passengers():
|
||||
return self.die("No passengers left")
|
||||
self.journey = None
|
||||
while self.journey is None: # No potential journeys detected (see on_receive)
|
||||
if target is None or not self.move_towards(target):
|
||||
@@ -111,14 +110,15 @@ class Driver(Evented, FSM):
|
||||
self.model.grid.get_neighborhood(self.pos, moore=False)
|
||||
)
|
||||
|
||||
self.check_passengers()
|
||||
if not self.check_passengers():
|
||||
return self.die("No passengers left")
|
||||
# This will call on_receive behind the scenes, and the agent's status will be updated
|
||||
self.check_messages()
|
||||
yield Delta(30) # Wait at least 30 seconds before checking again
|
||||
self.process_messages()
|
||||
await self.delay(30) # Wait at least 30 seconds before checking again
|
||||
|
||||
try:
|
||||
# Re-send the journey to the passenger, to confirm that we have been selected
|
||||
self.journey = yield self.journey.passenger.ask(self.journey, timeout=60)
|
||||
self.journey = await self.journey.passenger.ask(self.journey, timeout=60, delay=5)
|
||||
except events.TimedOut:
|
||||
# No journey has been accepted. Try again
|
||||
self.journey = None
|
||||
@@ -127,18 +127,19 @@ class Driver(Evented, FSM):
|
||||
return self.driving
|
||||
|
||||
@state
|
||||
def driving(self):
|
||||
async def driving(self):
|
||||
"""The journey has been accepted. Pick them up and take them to their destination"""
|
||||
self.info(f"Driving towards Passenger {self.journey.passenger.unique_id}")
|
||||
while self.move_towards(self.journey.origin):
|
||||
yield
|
||||
await self.delay()
|
||||
self.info(f"Driving {self.journey.passenger.unique_id} from {self.journey.origin} to {self.journey.destination}")
|
||||
while self.move_towards(self.journey.destination, with_passenger=True):
|
||||
yield
|
||||
await self.delay()
|
||||
self.info("Arrived at destination")
|
||||
self.earnings += self.journey.tip
|
||||
self.model.total_earnings += self.journey.tip
|
||||
self.check_passengers()
|
||||
if not self.check_passengers():
|
||||
return self.die("No passengers left")
|
||||
return self.wandering
|
||||
|
||||
def move_towards(self, target, with_passenger=False):
|
||||
@@ -167,7 +168,7 @@ class Passenger(Evented, FSM):
|
||||
pos = None
|
||||
|
||||
def on_receive(self, msg, sender):
|
||||
"""This is not a state. It will be run synchronously every time `check_messages` is run"""
|
||||
"""This is not a state. It will be run synchronously every time `process_messages` is run"""
|
||||
|
||||
if isinstance(msg, Journey):
|
||||
self.journey = msg
|
||||
@@ -175,7 +176,7 @@ class Passenger(Evented, FSM):
|
||||
|
||||
@default_state
|
||||
@state
|
||||
def asking(self):
|
||||
async def asking(self):
|
||||
destination = (
|
||||
self.random.randint(0, self.model.grid.height-1),
|
||||
self.random.randint(0, self.model.grid.width-1),
|
||||
@@ -195,9 +196,9 @@ class Passenger(Evented, FSM):
|
||||
while not self.journey:
|
||||
self.debug(f"Waiting for responses at: { self.pos }")
|
||||
try:
|
||||
# This will call check_messages behind the scenes, and the agent's status will be updated
|
||||
# This will call process_messages behind the scenes, and the agent's status will be updated
|
||||
# If you want to avoid that, you can call it with: check=False
|
||||
yield self.received(expiration=expiration)
|
||||
await self.received(expiration=expiration, delay=10)
|
||||
except events.TimedOut:
|
||||
self.info(f"Still no response. Waiting at: { self.pos }")
|
||||
self.model.broadcast(
|
||||
@@ -208,13 +209,13 @@ class Passenger(Evented, FSM):
|
||||
return self.driving_home
|
||||
|
||||
@state
|
||||
def driving_home(self):
|
||||
async def driving_home(self):
|
||||
while (
|
||||
self.pos[0] != self.journey.destination[0]
|
||||
or self.pos[1] != self.journey.destination[1]
|
||||
):
|
||||
try:
|
||||
yield self.received(timeout=60)
|
||||
await self.received(timeout=60)
|
||||
except events.TimedOut:
|
||||
pass
|
||||
|
||||
@@ -228,4 +229,4 @@ simulation = Simulation(name="RideHailing",
|
||||
parameters=dict(n_passengers=2))
|
||||
|
||||
if __name__ == "__main__":
|
||||
easy(simulation)
|
||||
easy(simulation)
|
@@ -33,7 +33,7 @@ class GeneratorEnv(Environment):
|
||||
self.add_agents(CounterModel)
|
||||
|
||||
|
||||
sim = Simulation(model=GeneratorEnv, max_steps=10, interval=1)
|
||||
sim = Simulation(model=GeneratorEnv, max_steps=10)
|
||||
|
||||
if __name__ == '__main__':
|
||||
sim.run(dump=False)
|
0
examples/custom_timeouts/custom_timeouts.py
Normal file
0
examples/custom_timeouts/custom_timeouts.py
Normal file
@@ -1,5 +1,4 @@
|
||||
from soil.agents import FSM, state, default_state
|
||||
from soil.time import Delta
|
||||
|
||||
|
||||
class Fibonacci(FSM):
|
||||
@@ -11,17 +10,17 @@ class Fibonacci(FSM):
|
||||
def counting(self):
|
||||
self.log("Stopping at {}".format(self.now))
|
||||
prev, self["prev"] = self["prev"], max([self.now, self["prev"]])
|
||||
return None, Delta(prev)
|
||||
return self.delay(prev)
|
||||
|
||||
|
||||
|
||||
class Odds(FSM):
|
||||
"""Agent that only executes in odd t_steps"""
|
||||
|
||||
@default_state
|
||||
@state
|
||||
@state(default=True)
|
||||
def odds(self):
|
||||
self.log("Stopping at {}".format(self.now))
|
||||
return None, Delta(1 + self.now % 2)
|
||||
return self.delay(1 + (self.now % 2))
|
||||
|
||||
|
||||
from soil import Environment, Simulation
|
||||
@@ -35,7 +34,7 @@ class TimeoutsEnv(Environment):
|
||||
self.add_agent(agent_class=Odds, node_id=1)
|
||||
|
||||
|
||||
sim = Simulation(model=TimeoutsEnv, max_steps=10, interval=1)
|
||||
sim = Simulation(model=TimeoutsEnv, max_steps=10)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sim.run(dump=False)
|
||||
sim.run(dump=False)
|
||||
|
@@ -1,7 +1,7 @@
|
||||
from soil import Simulation
|
||||
from social_wealth import MoneyEnv, graph_generator
|
||||
|
||||
sim = Simulation(name="mesa_sim", dump=False, max_steps=10, interval=2, model=MoneyEnv, parameters=dict(generator=graph_generator, N=10, width=50, height=50))
|
||||
sim = Simulation(name="mesa_sim", dump=False, max_steps=10, model=MoneyEnv, parameters=dict(generator=graph_generator, N=10, width=50, height=50))
|
||||
|
||||
if __name__ == "__main__":
|
||||
sim.run()
|
||||
|
@@ -1,5 +1,4 @@
|
||||
from soil import FSM, state, default_state, BaseAgent, NetworkAgent, Environment, Simulation
|
||||
from soil.time import Delta
|
||||
from enum import Enum
|
||||
from collections import Counter
|
||||
import logging
|
||||
@@ -35,7 +34,7 @@ class Rabbit(FSM, NetworkAgent):
|
||||
self.info("I am a newborn.")
|
||||
self.birth = self.now
|
||||
self.offspring = 0
|
||||
return self.youngling, Delta(self.sexual_maturity - self.age)
|
||||
return self.youngling.delay(self.sexual_maturity - self.age)
|
||||
|
||||
@state
|
||||
def youngling(self):
|
||||
|
@@ -1,9 +1,7 @@
|
||||
"""
|
||||
Example of setting a
|
||||
Example of a fully programmatic simulation, without definition files.
|
||||
"""
|
||||
from soil import Simulation, agents, Environment
|
||||
from soil.time import Delta
|
||||
|
||||
|
||||
class MyAgent(agents.FSM):
|
||||
@@ -11,22 +9,22 @@ class MyAgent(agents.FSM):
|
||||
An agent that first does a ping
|
||||
"""
|
||||
|
||||
defaults = {"pong_counts": 2}
|
||||
max_pongs = 2
|
||||
|
||||
@agents.default_state
|
||||
@agents.state
|
||||
def ping(self):
|
||||
self.info("Ping")
|
||||
return self.pong, Delta(self.random.expovariate(1 / 16))
|
||||
return self.pong.delay(self.random.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:
|
||||
self.max_pongs -= 1
|
||||
self.info(str(self.max_pongs), "pongs remaining")
|
||||
if self.max_pongs < 1:
|
||||
return self.die()
|
||||
return None, Delta(self.random.expovariate(1 / 16))
|
||||
return self.delay(self.random.expovariate(1 / 16))
|
||||
|
||||
|
||||
class RandomEnv(Environment):
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import networkx as nx
|
||||
from soil.agents import Geo, NetworkAgent, FSM, custom, state, default_state
|
||||
from soil.agents import NetworkAgent, FSM, custom, state, default_state
|
||||
from soil.agents.geo import Geo
|
||||
from soil import Environment, Simulation
|
||||
from soil.parameters import *
|
||||
from soil.utils import int_seed
|
||||
@@ -39,8 +40,8 @@ class TerroristEnvironment(Environment):
|
||||
HavenModel
|
||||
], [self.ratio_civil, self.ratio_leader, self.ratio_training, self.ratio_haven])
|
||||
|
||||
def generator(self, *args, **kwargs):
|
||||
return nx.random_geometric_graph(*args, **kwargs, seed=int_seed(self._seed))
|
||||
def generator(self, *args, seed=None, **kwargs):
|
||||
return nx.random_geometric_graph(*args, **kwargs, seed=seed or int_seed(self._seed))
|
||||
|
||||
class TerroristSpreadModel(FSM, Geo):
|
||||
"""
|
||||
|
@@ -21,5 +21,4 @@ class TorvaldsEnv(Environment):
|
||||
|
||||
sim = Simulation(name='torvalds_example',
|
||||
max_steps=10,
|
||||
interval=2,
|
||||
model=TorvaldsEnv)
|
Reference in New Issue
Block a user