diff --git a/pyproject.toml b/pyproject.toml index 9a56a416..ca9374fe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "titan-model" -version = "3.2.1" +version = "3.3.0" description = "TITAN Agent Based Model" license = "GPL-3.0-only" authors = ["Sam Bessey ", "Mary McGrath "] @@ -12,11 +12,11 @@ classifiers = ["Operating System :: OS Independent"] packages = [{ include = "titan" }] [tool.poetry.dependencies] -python = "^3.8" +python = "^3.6" paraml= "^0.1" networkx = "^2.4" nanoid = "^2.0" -numpy = "^1.23" +numpy = "^1.18" black = {version = "^23.1.0", optional = true} flake8 = {version = "^3.8", optional = true} mypy = {version = "^1.0.0", optional = true} diff --git a/tests/integration_test.py b/tests/integration_test.py index eb37b43f..16c1855a 100644 --- a/tests/integration_test.py +++ b/tests/integration_test.py @@ -411,6 +411,39 @@ def test_static_network(make_model_integration, tmpdir): assert rel in curr_rel_ids +@pytest.mark.integration_deterministic +def test_dissolution(params_integration, tmpdir): + model = TITAN(params_integration) + inj_r = 0 + for rel in model.pop.relationships: + inj_r += 1 + assert inj_r > 0 + model.time = 1 + + model.params.partnership.dissolve.time = 1 + model.params.partnership.dissolve.enabled = True + + model.params.demographics.white.sex_type.MSM.drug_type.Inj.num_partners = ( + model.params.demographics.black.sex_type.MSM.drug_type.Inj.num_partners + ) + for agent in model.pop.all_agents: + agent.mean_num_partners["Inj"] = -1 + agent.mean_num_partners["Sex"] = -1 + agent.mean_num_partners["SexInj"] = -1 + agent.mean_num_partners["Social"] = -1 + model.pop.update_partner_targets() + + model.step(tmpdir) + + for rel in model.pop.relationships: + if rel.bond_type == "Inj": + print(rel.agent1.mean_num_partners) + print(rel.agent2.mean_num_partners) + print(rel.agent1.race, rel.agent1.sex_type, rel.agent1.drug_type) + print(rel.agent2.race, rel.agent2.sex_type, rel.agent2.drug_type) + assert rel.bond_type != "Inj" + + @pytest.mark.integration_deterministic def test_incar(params_integration, tmpdir): # turn on incar - initi is set to 0, so for these purposes, just run time diff --git a/tests/model_test.py b/tests/model_test.py index febfcd9a..874eedd1 100644 --- a/tests/model_test.py +++ b/tests/model_test.py @@ -30,7 +30,7 @@ def test_model_init(params): @pytest.mark.unit -def test_update_all_agents(make_model, make_agent): +def test_update_all_agents(make_model, make_agent, make_relationship): # make agent 0 model = make_model() assert model.params.agent_zero.interaction_type == "injection" @@ -57,6 +57,23 @@ def test_update_all_agents(make_model, make_agent): assert "No agent zero!" in str(excinfo) + # check that model dissolves relationships + model.params.features.agent_zero = False + model.params.partnership.dissolve.enabled = True + model.params.partnership.dissolve.time = 1 + model.time = 1 + a = make_agent() + p = make_agent() + r = make_relationship(a, p) + model.pop.add_relationship(r) + a.target_partners["Sex"] = 0 + a.target_partners["SexInj"] = 0 + a.target_partners["Inj"] = 0 + + assert a.has_partners() is True + model.update_all_agents() + assert a.has_partners() is False + @pytest.mark.unit def test_death_none(make_model): diff --git a/titan/model.py b/titan/model.py index e70ad942..5c8f9748 100644 --- a/titan/model.py +++ b/titan/model.py @@ -235,7 +235,13 @@ def update_all_agents(self): # If static network, ignore relationship progression if not self.params.features.static_network: for rel in copy(self.pop.relationships): - if rel.progress(): + if ( + self.params.partnership.dissolve.enabled + and self.time == self.params.partnership.dissolve.time + ): + rel.progress(force=True) + self.pop.remove_relationship(rel) + elif rel.progress(): self.pop.remove_relationship(rel) if self.params.features.exit_enter: diff --git a/titan/params/partnership.yml b/titan/params/partnership.yml index 114ead1d..fddfa759 100644 --- a/titan/params/partnership.yml +++ b/titan/params/partnership.yml @@ -258,3 +258,10 @@ partnership: description: Probability that for a given partnering attempt, the agent tries to partner with only other agents in their component. Otherwise, the agent tries to partner with agents from any component. Network must be enabled. min: 0 max: 1 + dissolve: + time: + type: int + default: -9999 + enabled: + type: bool + default: false