Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added setup siblings #198

Merged
merged 16 commits into from
Oct 2, 2020
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion 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
74 changes: 46 additions & 28 deletions mesa/mesaPROTON_OC.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,33 +402,53 @@ def setup_persons_and_friendship(self):
# 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
"""
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_link_list("sibling") + candidates + [sibling for candidate in candidates for sibling in candidate.neighbors.get('sibling')]
for sibling in all_potential_siblings:
if sibling.get_link_list("partner") and sibling.get_link_list("partner")[0] in all_potential_siblings:
ambitious-octopus marked this conversation as resolved.
Show resolved Hide resolved
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.incestuos(agent, candidates):
ambitious-octopus marked this conversation as resolved.
Show resolved Hide resolved
# trouble should exist, or check-all-siblings would fail
potential_trouble = [x for x in candidates if agent.get_link_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 @@ -675,6 +695,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 @@ -738,7 +759,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())