Skip to content

Commit

Permalink
A few bugs removed, flood-driven spawning now with test case. #81
Browse files Browse the repository at this point in the history
  • Loading branch information
djgroen committed Aug 26, 2023
1 parent c7f146f commit 218eb88
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 14 deletions.
4 changes: 3 additions & 1 deletion flee/InputGeography.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,10 @@ def StoreInputGeographyInEcosystem(self, e):


@check_args_type
def UpdateLocationAttributes(self, e, attribute_name: str, time: int, Debug: bool = False) -> None:
def UpdateLocationAttributes(self, e, attribute_name: str, time: int) -> None:

attrlist = self.attributes[attribute_name]

for i in range(0, len(e.locations)):
loc_name = e.locations[i].name
if loc_name in attrlist:
Expand Down
21 changes: 15 additions & 6 deletions flee/SimulationSettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,17 +141,28 @@ def ReadFromYML(ymlfile: str):
else:
SimulationSettings.spawn_rules["displaced_per_conflict_day"] = int(fetchss(dpsc,"displaced_per_conflict_day", 500))


# Setting False by default.
SimulationSettings.move_rules["FloodRulesEnabled"] = False

if spawn_type == "flood":
dpsc = fetchss(dps,"flood_driven_spawning",None)
if dpsc is not None:
SimulationSettings.move_rules["FloodRulesEnabled"] = True

if SimulationSettings.spawn_rules["TakeFromPopulation"] is False:
print("ERROR in simulationsetting.yml: Flood rules are enabled but take_from_population in spawn_rules is set to False.", file=sys.stderr)
print("This is likely to lead to excessive production of agents in the simulation, so Flee does not support this at this stage.", file=sys.stderr)
sys.exit()

SimulationSettings.spawn_rules["flood_driven_spawning"] = True # Conflicts provide a direct push factor.

SimulationSettings.spawn_rules["flood_spawn_mode"] = fetchss(dpsc,"spawn_mode","constant") # constant, Poisson, pop_ratio
SimulationSettings.spawn_rules["flood_spawn_mode"] = fetchss(dpsc,"spawn_mode","pop_ratio") # constant, Poisson, pop_ratio

if SimulationSettings.spawn_rules["flood_spawn_mode"] == "pop_ratio":
SimulationSettings.spawn_rules["displaced_per_flood_day"] = float(fetchss(dpsc,"displaced_per_conflict_day", 0.01))
SimulationSettings.spawn_rules["displaced_per_flood_day"] = fetchss(dpsc,"displaced_per_flood_day", [0.0,0.1,0.2,0.5,0.9]) #expect an array.
else:
SimulationSettings.spawn_rules["displaced_per_flood_day"] = int(fetchss(dpsc,"displaced_per_conflict_day", 500))
SimulationSettings.spawn_rules["displaced_per_flood_day"] = fetchss(dpsc,"displaced_per_flood_day", [0,100,200,300,500])


SimulationSettings.spawn_rules["conflict_spawn_decay"] = fetchss(dps,"conflict_spawn_decay", None) # Expect an array or dict
Expand Down Expand Up @@ -247,10 +258,8 @@ def ReadFromYML(ymlfile: str):
SimulationSettings.move_rules["FloodLinkWeights"] = fetchss(dps,"flood_link_weights", None) # Expect an array or dict
print("Flood Link Weights set to:", SimulationSettings.spawn_rules["FloodLinkWeights"], file=sys.stderr)

# Add verification code.
#TODO: Add verification code.

else:
SimulationSettings.move_rules["FloodRulesEnabled"] = False

dpo = fetchss(dp, "optimisations", None)
SimulationSettings.optimisations["PopulationScaleDownFactor"] = int(fetchss(dpo,"hasten",1))
Expand Down
10 changes: 6 additions & 4 deletions flee/spawning.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,16 +174,18 @@ def spawn_daily_displaced(e, t, d, SumFromCamps=False):

num_spawned = 0

if e.locations[i].attributes["flood_level"] > 0:
print(e.locations[i].attributes)
flood_level = e.locations[i].attributes["flood_level"]
if flood_level > 0:
## BASE RATES
if SimulationSettings.spawn_rules["flood_spawn_mode"] == "constant":
num_spawned = int(SimulationSettings.spawn_rules["displaced_per_conflict_day"] * e.locations[i].conflict)
num_spawned = int(SimulationSettings.spawn_rules["displaced_per_conflict_day"][flood_level])

elif SimulationSettings.spawn_rules["flood_spawn_mode"] == "pop_ratio":
num_spawned = int(SimulationSettings.spawn_rules["displaced_per_conflict_day"] * e.locations[i].pop * e.locations[i].conflict)
num_spawned = int(SimulationSettings.spawn_rules["displaced_per_conflict_day"][flood_level] * e.locations[i].pop)

elif SimulationSettings.spawn_rules["flood_spawn_mode"].lower() == "poisson":
num_spawned = np.random.poisson(SimulationSettings.spawn_rules["displaced_per_conflict_day"] * e.locations[i].conflict)
num_spawned = np.random.poisson(int(SimulationSettings.spawn_rules["displaced_per_conflict_day"][flood_level]))

## Doing the actual spawning here.
for j in range(0, num_spawned):
Expand Down
3 changes: 0 additions & 3 deletions tests/test_conflict_driven_spawning.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@


def test_conflict_driven_spawning():
print("Testing basic data handling and simulation kernel.")

flee.SimulationSettings.ReadFromYML("empty.yml")

Expand Down Expand Up @@ -42,8 +41,6 @@ def test_conflict_driven_spawning():
# All agents should have reached l2, and be deactivated.
assert len(e.agents) == 1000

print("Test successful!")


if __name__ == "__main__":
test_conflict_driven_spawning()
49 changes: 49 additions & 0 deletions tests/test_flood_driven_spawning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from flee import flee, datamanager

"""
Testing flood drive spawning for DFlee.
"""


def test_flood_driven_spawning():

flee.SimulationSettings.ReadFromYML("empty.yml")

flee.SimulationSettings.move_rules["MaxMoveSpeed"] = 5000.0
flee.SimulationSettings.move_rules["MaxWalkSpeed"] = 5000.0
flee.SimulationSettings.move_rules["ForeignWeight"] = 0.0

#These values are normally specified in simsetting.yml
flee.SimulationSettings.spawn_rules["flood_driven_spawning"] = True
flee.SimulationSettings.spawn_rules["flood_spawn_mode"] = "constant"
flee.SimulationSettings.spawn_rules["displaced_per_conflict_day"] = [0,100,200,300,400]


end_time = 10
e = flee.Ecosystem()

l1 = e.addLocation(name="A", movechance=0.0, foreign=False, attributes={"flood_level": 1})
l2 = e.addLocation(name="B", movechance=0.0, foreign=True, attributes={"flood_level": 0})
l1.conflict = True

e.linkUp(endpoint1="A", endpoint2="B", distance=100.0)

for t in range(0, end_time):

new_refs,refugees_raw,refugee_debt = flee.spawning.spawn_daily_displaced(e,t,None)
print("new agents: {}".format(new_refs))

flee.spawning.refresh_spawn_weights(e)

# Propagate the model by one time step.
e.evolve()

assert t == 9

# All agents should be spawned in l1 and not be in l2.
assert len(e.agents) == 1000
assert l1.numAgents == 1000


if __name__ == "__main__":
test_conflict_driven_spawning()

0 comments on commit 218eb88

Please sign in to comment.