def transitive_closure(partitions=2):
"""Transitive closure.
:param partitions: Number of partitions.
:results: Transitive closure result.
"""
print("--- TRANSITIVE CLOSURE ---")
edges = _generate_graph()
start_time = time.time()
o_d = DDS().load(edges, partitions).collect(future_objects=True)
# Because join() joins on keys, the edges are stored in reversed order.
edges = DDS().load(o_d, -1).map(lambda x_y: (x_y[1], x_y[0]))
next_count = DDS().load(o_d, -1).count()
while True:
old_count = next_count
# Perform the join, obtaining an RDD of (y, (z, x)) pairs,
# then project the result to obtain the new (x, z) paths.
new_edges = (
DDS()
.load(o_d, -1)
.join(edges)
.map(lambda __a_b: (__a_b[1][1], __a_b[1][0]))
)
o_d = (
DDS()
.load(o_d, -1)
.union(new_edges)
.distinct()
.collect(future_objects=True)
)
next_count = DDS().load(o_d, -1).count()
if next_count == old_count:
break
print(f"- TC has {next_count} edges")
print(f"- Elapsed Time: {time.time() - start_time} (s)")
print("--------------------------")
return next_count == 20