in clutrr/relations/builder.py [0:0]
def add_facts_to_puzzle(self, puzzle):
"""
For a given puzzle, add different types of facts
- 1 : Provide supporting facts. After creating the essential fact graph, expand on any
k number of edges (randomly)
- 2: Irrelevant facts: after creating the relevant fact graph, expand on an edge,
but only provide dangling expansions
- 3: Disconnected facts: along with relevant facts, provide a tree which is completely
separate from the proof path
- 4: Random attributes: school, place of birth, etc.
If unable to add the required facts, return False
Else, return the puzzle
:return:
"""
if self.args.noise_support:
# Supporting facts
# A <-> B <-> C ==> A <-> D <-> C , A <-> D <-> B <-> C
story = puzzle.story
extra_story = []
for se in story:
e_pair = self.expand_new(se)
if e_pair:
if puzzle.target_edge not in e_pair and e_pair[0][1] not in set([p for e in puzzle.story for p in e]):
extra_story.append(tuple(e_pair))
if len(extra_story) == 0:
return False
else:
# choose a sample of 1 to k-1 edge pairs
num_edges = random.choice(range(1, (len(story) // 2) + 1))
extra_story = random.sample(extra_story, min(num_edges, len(extra_story)))
# untuple the extra stories
extra_story = [k for e in extra_story for k in e]
self._test_supporting(story, extra_story)
puzzle.add_fact(fact_type='supporting', fact=extra_story)
if self.args.noise_irrelevant:
# Irrelevant facts
# A <-> B <-> C ==> A <-> D <-> E
# Must have only one common node with the story
story = puzzle.story
num_edges = len(story)
sampled_edge = random.choice(story)
extra_story = []
for i in range(num_edges):
tmp = sampled_edge
seen_pairs = set()
pair = self.expand_new(sampled_edge)
if pair:
while len(extra_story) == 0 and (tuple(pair) not in seen_pairs):
seen_pairs.add(tuple(pair))
for e in pair:
if e != puzzle.target_edge and not self._subset(story, [e], k=2):
extra_story.append(e)
sampled_edge = e
break
if tmp == sampled_edge:
sampled_edge = random.choice(story)
if len(extra_story) == 0:
return False
else:
# add a length restriction so as to not create super long text
# length restriction should be k+1 than the current k
extra_story = random.sample(extra_story, min(len(extra_story), len(story) // 2))
self._test_irrelevant(story, extra_story)
puzzle.add_fact(fact_type='irrelevant', fact=extra_story)
if self.args.noise_disconnected:
# Disconnected facts
story = puzzle.story
nodes_story = set([y for x in list(story) for y in x])
nodes_not_in_story = set(self.anc.family_data.keys()) - nodes_story
possible_edges = [(x, y) for x, y in it.combinations(list(nodes_not_in_story), 2) if
(x, y) in self.anc.family]
num_edges = random.choice(range(1, (len(story) // 2) + 1))
possible_edges = random.sample(possible_edges, min(num_edges, len(possible_edges)))
if len(possible_edges) == 0:
return False
self._test_disconnected(story, possible_edges)
puzzle.add_fact(fact_type='disconnected', fact=possible_edges)
return puzzle