in clutrr/actors/ancestry.py [0:0]
def next_flip(self):
"""
Given an ancestry,
- maintain a set of nodes who have already been gender flipped
- sample one node to flip from the rest
- check if the node contains a SO relationship. if so, toggle both
- add the flipped nodes into the already flipped pile
- if no nodes are left, then return False. else return True
:return:
"""
candidates = list(set(self.family_data.keys()) - set(self.flipped))
if len(candidates) == 0:
# all candidates flipped already
# reset flip
self.flipped = []
else:
node = random.choice(candidates)
relations_with_node = [node_pair for node_pair in self.family.keys() if node_pair[0] == node]
SO_relation = [node_pair for node_pair in relations_with_node if self.family[node_pair]['family'] == 'SO']
assert len(SO_relation) <= 1
if len(SO_relation) == 1:
so_node = SO_relation[0][1]
# flip both
self.family_data[node].gender = self.toggle_gender(self.family_data[node])
self.family_data[so_node].gender = self.toggle_gender(self.family_data[so_node])
# exchange their names too
tmp_name = self.family_data[node].name
self.family_data[node].name = self.family_data[so_node].name
self.family_data[so_node].name = tmp_name
self.flipped.append(node)
self.flipped.append(so_node)
#print("flipping couples ...")
#print("Flipped {} to {}".format(node, self.family_data[node].gender))
#print("Flipped {} to {}".format(so_node, self.family_data[so_node].gender))
else:
# only childs, flip them
self.family_data[node].gender = self.toggle_gender(self.family_data[node])
# choose a new gender appropriate name
gender = self.family_data[node].gender
while name in self.taken_names:
name = names.get_first_name(gender=gender)
self.family_data[node].name = name
self.flipped.append(node)