mirror of
https://github.com/gsi-upm/soil
synced 2025-08-23 19:52:19 +00:00
1.0pre4
This commit is contained in:
@@ -17,7 +17,7 @@ class TestAgents(TestCase):
|
||||
"""The last step of a dead agent should return time.INFINITY"""
|
||||
d = Dead(unique_id=0, model=environment.Environment())
|
||||
ret = d.step()
|
||||
assert ret == stime.NEVER
|
||||
assert ret == stime.INFINITY
|
||||
|
||||
def test_die_raises_exception(self):
|
||||
"""A dead agent should raise an exception if it is stepped after death"""
|
||||
@@ -52,23 +52,25 @@ class TestAgents(TestCase):
|
||||
|
||||
def test_state_decorator(self):
|
||||
class MyAgent(agents.FSM):
|
||||
run = 0
|
||||
times_run = 0
|
||||
|
||||
@agents.state("original", default=True)
|
||||
def root(self):
|
||||
self.run += 1
|
||||
return self.other
|
||||
|
||||
@agents.state
|
||||
def other(self):
|
||||
self.run += 1
|
||||
self.times_run += 1
|
||||
|
||||
e = environment.Environment()
|
||||
a = e.add_agent(MyAgent)
|
||||
e.step()
|
||||
assert a.run == 1
|
||||
assert a.times_run == 0
|
||||
a.step()
|
||||
print("DONE")
|
||||
assert a.times_run == 1
|
||||
assert a.state_id == MyAgent.other.id
|
||||
a.step()
|
||||
assert a.times_run == 2
|
||||
|
||||
def test_broadcast(self):
|
||||
"""
|
||||
@@ -86,7 +88,7 @@ class TestAgents(TestCase):
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
while True:
|
||||
self.check_messages()
|
||||
self.process_messages()
|
||||
yield
|
||||
|
||||
def on_receive(self, msg, sender=None):
|
||||
@@ -132,14 +134,14 @@ class TestAgents(TestCase):
|
||||
while True:
|
||||
if pongs or not pings: # First agent, or anyone after that
|
||||
pings.append(self.now)
|
||||
response = yield target.ask("PING")
|
||||
response = yield from target.ask("PING")
|
||||
responses.append(response)
|
||||
else:
|
||||
print("NOT sending ping")
|
||||
print("Checking msgs")
|
||||
# Do not block if we have already received a PING
|
||||
if not self.check_messages():
|
||||
yield self.received()
|
||||
if not self.process_messages():
|
||||
yield from self.received()
|
||||
print("done")
|
||||
|
||||
def on_receive(self, msg, sender=None):
|
||||
@@ -174,4 +176,200 @@ class TestAgents(TestCase):
|
||||
assert len(ev) == 1
|
||||
assert ev[0].unique_id == 1
|
||||
null = list(e.agents(unique_ids=[0, 1], agent_class=agents.NetworkAgent))
|
||||
assert not null
|
||||
assert not null
|
||||
|
||||
def test_agent_return(self):
|
||||
'''
|
||||
An agent should be able to cycle through different states and control when it
|
||||
should be awaken.
|
||||
'''
|
||||
class TestAgent(agents.Agent):
|
||||
@agents.state(default=True)
|
||||
def one(self):
|
||||
return self.two
|
||||
|
||||
@agents.state
|
||||
def two(self):
|
||||
return self.three.at(10)
|
||||
|
||||
@agents.state
|
||||
def three(self):
|
||||
return self.four.delay(1)
|
||||
|
||||
@agents.state
|
||||
def four(self):
|
||||
yield self.delay(2)
|
||||
return self.five.delay(3)
|
||||
|
||||
@agents.state
|
||||
def five(self):
|
||||
return self.delay(1)
|
||||
|
||||
model = environment.Environment()
|
||||
a = model.add_agent(TestAgent)
|
||||
assert a.state_id == TestAgent.one.id
|
||||
assert a.now == 0
|
||||
model.step()
|
||||
assert a.state_id == TestAgent.two.id
|
||||
assert a.now == 1
|
||||
model.step()
|
||||
assert a.state_id == TestAgent.three.id
|
||||
assert a.now == 10
|
||||
model.step()
|
||||
assert a.state_id == TestAgent.four.id
|
||||
assert a.now == 11
|
||||
model.step()
|
||||
assert a.state_id == TestAgent.four.id
|
||||
assert a.now == 13
|
||||
model.step()
|
||||
assert a.state_id == TestAgent.five.id
|
||||
assert a.now == 16
|
||||
model.step()
|
||||
assert a.state_id == TestAgent.five.id
|
||||
assert a.now == 17
|
||||
|
||||
def test_agent_async(self):
|
||||
'''
|
||||
Async functions should also be valid states.
|
||||
'''
|
||||
|
||||
class TestAgent(agents.Agent):
|
||||
@agents.state(default=True)
|
||||
def one(self):
|
||||
return self.two
|
||||
|
||||
@agents.state
|
||||
def two(self):
|
||||
return self.three.at(10)
|
||||
|
||||
@agents.state
|
||||
def three(self):
|
||||
return self.four.delay(1)
|
||||
|
||||
@agents.state
|
||||
async def four(self):
|
||||
await self.delay(2)
|
||||
return self.five.delay(3)
|
||||
|
||||
@agents.state
|
||||
def five(self):
|
||||
return self.delay(1)
|
||||
|
||||
model = environment.Environment()
|
||||
a = model.add_agent(TestAgent)
|
||||
assert a.now == 0
|
||||
assert a.state_id == TestAgent.one.id
|
||||
model.step()
|
||||
assert a.now == 1
|
||||
assert a.state_id == TestAgent.two.id
|
||||
model.step()
|
||||
assert a.now == 10
|
||||
assert a.state_id == TestAgent.three.id
|
||||
model.step()
|
||||
assert a.state_id == TestAgent.four.id
|
||||
assert a.now == 11
|
||||
model.step()
|
||||
assert a.state_id == TestAgent.four.id
|
||||
assert a.now == 13
|
||||
model.step()
|
||||
assert a.state_id == TestAgent.five.id
|
||||
assert a.now == 16
|
||||
model.step()
|
||||
assert a.state_id == TestAgent.five.id
|
||||
assert a.now == 17
|
||||
|
||||
def test_agent_return_step(self):
|
||||
'''
|
||||
The same result as the previous test should be achievable by manually
|
||||
handling the agent state.
|
||||
'''
|
||||
class TestAgent(agents.Agent):
|
||||
my_state = 1
|
||||
my_count = 0
|
||||
|
||||
def step(self):
|
||||
if self.my_state == 1:
|
||||
self.my_state = 2
|
||||
return None
|
||||
elif self.my_state == 2:
|
||||
self.my_state = 3
|
||||
return self.at(10)
|
||||
elif self.my_state == 3:
|
||||
self.my_state = 4
|
||||
self.my_count = 0
|
||||
return self.delay(1)
|
||||
elif self.my_state == 4:
|
||||
self.my_count += 1
|
||||
if self.my_count == 1:
|
||||
return self.delay(2)
|
||||
self.my_state = 5
|
||||
return self.delay(3)
|
||||
elif self.my_state == 5:
|
||||
return self.delay(1)
|
||||
|
||||
model = environment.Environment()
|
||||
a = model.add_agent(TestAgent)
|
||||
assert a.my_state == 1
|
||||
assert a.now == 0
|
||||
model.step()
|
||||
assert a.now == 1
|
||||
assert a.my_state == 2
|
||||
model.step()
|
||||
assert a.now == 10
|
||||
assert a.my_state == 3
|
||||
model.step()
|
||||
assert a.now == 11
|
||||
assert a.my_state == 4
|
||||
model.step()
|
||||
assert a.now == 13
|
||||
assert a.my_state == 4
|
||||
model.step()
|
||||
assert a.now == 16
|
||||
assert a.my_state == 5
|
||||
model.step()
|
||||
assert a.now == 17
|
||||
assert a.my_state == 5
|
||||
|
||||
def test_agent_return_step_async(self):
|
||||
'''
|
||||
The same result as the previous test should be achievable by manually
|
||||
handling the agent state.
|
||||
'''
|
||||
class TestAgent(agents.Agent):
|
||||
my_state = 1
|
||||
|
||||
async def step(self):
|
||||
self.my_state = 2
|
||||
await self.delay()
|
||||
self.my_state = 3
|
||||
await self.at(10)
|
||||
self.my_state = 4
|
||||
await self.delay(1)
|
||||
await self.delay(2)
|
||||
self.my_state = 5
|
||||
await self.delay(3)
|
||||
while True:
|
||||
await self.delay(1)
|
||||
|
||||
model = environment.Environment()
|
||||
a = model.add_agent(TestAgent)
|
||||
assert a.my_state == 1
|
||||
assert a.now == 0
|
||||
model.step()
|
||||
assert a.now == 1
|
||||
assert a.my_state == 2
|
||||
model.step()
|
||||
assert a.now == 10
|
||||
assert a.my_state == 3
|
||||
model.step()
|
||||
assert a.now == 11
|
||||
assert a.my_state == 4
|
||||
model.step()
|
||||
assert a.now == 13
|
||||
assert a.my_state == 4
|
||||
model.step()
|
||||
assert a.now == 16
|
||||
assert a.my_state == 5
|
||||
model.step()
|
||||
assert a.now == 17
|
||||
assert a.my_state == 5
|
@@ -29,15 +29,12 @@ class TestConfig(TestCase):
|
||||
def test_torvalds_config(self):
|
||||
sim = simulation.from_config(os.path.join(ROOT, "test_config.yml"))
|
||||
MAX_STEPS = 10
|
||||
INTERVAL = 2
|
||||
assert sim.interval == INTERVAL
|
||||
assert sim.max_steps == MAX_STEPS
|
||||
envs = sim.run()
|
||||
assert len(envs) == 1
|
||||
env = envs[0]
|
||||
assert env.interval == 2
|
||||
assert env.count_agents() == 3
|
||||
assert env.now == INTERVAL * MAX_STEPS
|
||||
assert env.now == MAX_STEPS
|
||||
|
||||
|
||||
def make_example_test(path, cfg):
|
||||
|
@@ -1,5 +1,4 @@
|
||||
---
|
||||
source_file: "../examples/torvalds_sim.py"
|
||||
model: "TorvaldsEnv"
|
||||
max_steps: 10
|
||||
interval: 2
|
||||
max_steps: 10
|
@@ -88,7 +88,7 @@ class Exporters(TestCase):
|
||||
parameters=dict(
|
||||
network_generator="complete_graph",
|
||||
network_params={"n": n_nodes},
|
||||
agent_class="CounterModel",
|
||||
agent_class=agents.CounterModel,
|
||||
agent_reporters={"times": "times"},
|
||||
),
|
||||
max_time=max_time,
|
||||
|
@@ -7,8 +7,6 @@ from functools import partial
|
||||
|
||||
from os.path import join
|
||||
from soil import simulation, Environment, agents, network, serialization, utils, config, from_file
|
||||
from soil.time import Delta
|
||||
|
||||
from mesa import Agent as MesaAgent
|
||||
|
||||
ROOT = os.path.abspath(os.path.dirname(__file__))
|
||||
@@ -114,7 +112,6 @@ class TestMain(TestCase):
|
||||
def test_serialize_class(self):
|
||||
ser, name = serialization.serialize(agents.BaseAgent, known_modules=[])
|
||||
assert name == "soil.agents.BaseAgent"
|
||||
assert ser == agents.BaseAgent
|
||||
|
||||
ser, name = serialization.serialize(
|
||||
agents.BaseAgent,
|
||||
@@ -123,11 +120,9 @@ class TestMain(TestCase):
|
||||
],
|
||||
)
|
||||
assert name == "BaseAgent"
|
||||
assert ser == agents.BaseAgent
|
||||
|
||||
ser, name = serialization.serialize(CustomAgent)
|
||||
assert name == "test_main.CustomAgent"
|
||||
assert ser == CustomAgent
|
||||
pickle.dumps(ser)
|
||||
|
||||
def test_serialize_builtin_types(self):
|
||||
@@ -168,7 +163,6 @@ class TestMain(TestCase):
|
||||
|
||||
def test_fsm(self):
|
||||
"""Basic state change"""
|
||||
|
||||
class ToggleAgent(agents.FSM):
|
||||
@agents.default_state
|
||||
@agents.state
|
||||
@@ -193,7 +187,7 @@ class TestMain(TestCase):
|
||||
@agents.default_state
|
||||
@agents.state
|
||||
def ping(self):
|
||||
return self.pong, 2
|
||||
return self.pong.delay(2)
|
||||
|
||||
@agents.state
|
||||
def pong(self):
|
||||
@@ -203,7 +197,7 @@ class TestMain(TestCase):
|
||||
when = a.step()
|
||||
assert when == 2
|
||||
when = a.step()
|
||||
assert when == Delta(a.interval)
|
||||
assert when == None
|
||||
|
||||
def test_load_sim(self):
|
||||
"""Make sure at least one of the examples can be loaded"""
|
||||
@@ -232,4 +226,4 @@ class TestMain(TestCase):
|
||||
assert len(configs) == len(a) * len(b)
|
||||
for i in a:
|
||||
for j in b:
|
||||
assert {"a": i, "b": j} in configs
|
||||
assert {"a": i, "b": j} in configs
|
||||
|
@@ -4,26 +4,6 @@ from soil import time, agents, environment
|
||||
|
||||
|
||||
class TestMain(TestCase):
|
||||
def test_cond(self):
|
||||
"""
|
||||
A condition should match a When if the concition is True
|
||||
"""
|
||||
|
||||
t = time.Cond(lambda t: True)
|
||||
f = time.Cond(lambda t: False)
|
||||
for i in range(10):
|
||||
w = time.When(i)
|
||||
assert w == t
|
||||
assert w is not f
|
||||
|
||||
def test_cond(self):
|
||||
"""
|
||||
Comparing a Cond to a Delta should always return False
|
||||
"""
|
||||
|
||||
c = time.Cond(lambda t: False)
|
||||
d = time.Delta(1)
|
||||
assert c is not d
|
||||
|
||||
def test_cond_env(self):
|
||||
""" """
|
||||
@@ -36,11 +16,12 @@ class TestMain(TestCase):
|
||||
|
||||
class CondAgent(agents.BaseAgent):
|
||||
def step(self):
|
||||
nonlocal done
|
||||
nonlocal done, times_started, times_asleep, times_awakened
|
||||
times_started.append(self.now)
|
||||
while True:
|
||||
times_asleep.append(self.now)
|
||||
yield time.Cond(lambda agent: agent.now >= 10, delta=2)
|
||||
while self.now < 10:
|
||||
yield self.delay(2)
|
||||
times_awakened.append(self.now)
|
||||
if self.now >= 10:
|
||||
break
|
||||
@@ -57,7 +38,6 @@ class TestMain(TestCase):
|
||||
assert times_started == [0]
|
||||
assert times_awakened == [10]
|
||||
assert done == [10]
|
||||
# The first time will produce the Cond.
|
||||
assert env.schedule.steps == 6
|
||||
assert len(times) == 6
|
||||
|
||||
@@ -65,11 +45,10 @@ class TestMain(TestCase):
|
||||
times.append(env.now)
|
||||
env.step()
|
||||
|
||||
assert times == [0, 2, 4, 6, 8, 10, 11]
|
||||
assert times == [0, 2, 4, 6, 8, 10, 11, 12]
|
||||
assert env.schedule.time == 13
|
||||
assert times_started == [0, 11]
|
||||
assert times_awakened == [10]
|
||||
assert done == [10]
|
||||
# Once more to yield the cond, another one to continue
|
||||
assert env.schedule.steps == 7
|
||||
assert len(times) == 7
|
||||
assert times_started == [0, 11, 12]
|
||||
assert times_awakened == [10, 11, 12]
|
||||
assert done == [10, 11, 12]
|
||||
assert env.schedule.steps == 8
|
||||
assert len(times) == 8
|
||||
|
Reference in New Issue
Block a user