Skip to content

Commit

Permalink
Merge pull request #198 from LABSS/setup_siblings
Browse files Browse the repository at this point in the history
Added setup siblings
  • Loading branch information
ambitious-octopus authored Oct 2, 2020
2 parents bb684db + 4e082f6 commit ba0acc8
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 34 deletions.
3 changes: 1 addition & 2 deletions mesa/Person.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ def random_links(self, exclude_partner_net=False):
self.neighbors.get(net).add(self.m.rng.choice(Person.persons))
self.neighbors.get(net).discard(self)


@staticmethod
def NumberOfLinks():
return sum([
Expand Down Expand Up @@ -232,7 +231,7 @@ def enroll_to_school(self, level):
self.my_school = self.m.rng.choice(self.potential_school)
self.my_school.my_students.add(self)

def get_link_list(self, net_name):
def get_neighbor_list(self, net_name):
"""
Given the name of a network, this method returns a list of agents within the network.
If the network is empty, it returns an empty list.
Expand Down
76 changes: 47 additions & 29 deletions mesa/mesaPROTON_OC.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,34 +401,54 @@ def setup_persons_and_friendship(self):
# nx.draw(watts_strogatz, with_labels=True)
# plt.show()

def incestuos(self, ego, candidates):
all_potential_siblings = [ego] + candidates + list(ego.neighbors.get('sibling')) + [s for c in candidates for s
in
c.neighbors.get('sibling')]
return ego.neighbors.get("partner").pop() in all_potential_siblings
def list_contains_problems(self, ego, candidates):
"""
This procedure checks if there are any links between partners within the candidate pool.
Returns True if there are, None if there are not.
It is used during the setup_siblings procedure to avoid incestuous marriages.
:param ego: Person
:param candidates: list of Person objects
:return: bool, True if there are links between partners, None otherwise.
"""
all_potential_siblings = [ego] + ego.get_neighbor_list("sibling") + candidates + [sibling for candidate in candidates for sibling in candidate.neighbors.get('sibling')]
for sibling in all_potential_siblings:
if sibling.get_neighbor_list("partner") and sibling.get_neighbor_list("partner")[0] in all_potential_siblings:
return True

def setup_siblings(self):
for p in [p for p in self.schedule.agents if
p.neighbors.get('parent')]: # simulates people who left the original household.
num_siblings = self.rng.poisson(0.5) # 0.5 -> the number of links is N^3 agents, so let's keep this low
"""
Right now, during setup, links between agents are only those within households, between friends
and related to the school. At this stage of the standard setup, agents are linked through "siblings" links
outside the household. To simulate agents who have left the original household, agents who have
children are taken and "sibling" links are created taking care not to create incestuous relationships.
:return: None
"""
agent_left_household = [p for p in self.schedule.agents if p.neighbors.get('offspring')] # simulates people who left the original household.
for agent in agent_left_household:
num_siblings = self.rng.poisson(0.5)
# 0.5 -> the number of links is N^3 agents, so let's keep this low
# at this stage links with other persons are only relatives inside households and friends.
candidates = [c for c in self.schedule.agents if
c.neighbors.get('parent') and not p.isneighbor(c) and abs(p.age() - c.age()) < 5]
candidates = [c for c in self.schedule.agents if not p.isneighbor(c) and abs(p.age() - c.age()) < 5]
candidates = self.rng.choice(candidates, min(len(candidates), 5), False).tolist()
print("len cand:" + str(len(candidates)))
# remove couples from candidates and their neighborhoods
while len(candidates) > 0 and not self.incestuos(p, candidates):
# trouble should exist, or incestous would be false.
trouble = self.rng.choice(
[x for x in candidates if x.neighbors.get("partner").pop()], 1).tolist()
candidates = cadidates.remove(trouble)
targets = p + self.rng.choice(candidates,
min(len(candidates, num_siblings))
)
targets = targets + set([x.neighbors.get("siblings") for x in targets])
for x in targets:
x.addSiblingLinks(p)
candidates = [c for c in agent_left_household if c not in agent.neighbors.get("household") and abs(agent.age() - c.age()) < 5 and c != agent]
# remove couples from candidates and their neighborhoods (siblings)
if len(candidates) >= 50:
candidates = self.rng.choice(candidates, 50, replace=False).tolist()
while len(candidates) > 0 and self.list_contains_problems(agent, candidates):
# trouble should exist, or check-all-siblings would fail
potential_trouble = [x for x in candidates if agent.get_neighbor_list("partner")]
trouble = self.rng.choice(potential_trouble)
candidates.remove(trouble)
targets = [agent] + self.rng.choice(candidates, min(len(candidates),num_siblings)).tolist()
for sib in targets:
if sib in agent_left_household:
agent_left_household.remove(sib)
for target in targets:
target.addSiblingLinks(targets)
# this is a good place to remind that the number of links in the sibling link neighbors is not the "number of brothers and sisters"
# because, for example, 4 brothers = 6 links.
other_targets = targets + [s for c in targets for s in c.neighbors.get('sibling')]
for target in other_targets:
target.addSiblingLinks(other_targets)


def generate_households(self):
# this mostly follows the third algorithm from Gargiulo et al. 2010
Expand Down Expand Up @@ -672,6 +692,7 @@ def setup(self, n_agent):
if self.unemployment_multiplier != "base":
self.fix_unemployment(self.unemployment_multiplier)
self.generate_households()
self.setup_siblings()

def assign_jobs_and_wealth(self):
"""
Expand Down Expand Up @@ -735,7 +756,4 @@ def conclude_wedding(ego, partner):
print(m.total_num_links())
# m.setup_siblings()
print("num links:")
print(m.total_num_links())



print(m.total_num_links())
6 changes: 3 additions & 3 deletions mesa/testProton.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ def test_weddings():
m.wedding()
# print(Person.NumberOfLinks()-l)
for agent in m.schedule.agents:
if agent.get_link_list("partner"):
assert agent.get_link_list("partner")[0].get_link_list("partner")[0] == agent
assert m.number_weddings == len([x for x in m.schedule.agents if x.get_link_list("partner")]) / 2
if agent.get_neighbor_list("partner"):
assert agent.get_neighbor_list("partner")[0].get_neighbor_list("partner")[0] == agent
assert m.number_weddings == len([x for x in m.schedule.agents if x.get_neighbor_list("partner")]) / 2
assert m.number_weddings > 0
# coherent state of weddings

Expand Down

0 comments on commit ba0acc8

Please sign in to comment.