Skip to content

Commit 7cd09a5

Browse files
authored
Complete DAG generater
1 parent 46a829d commit 7cd09a5

File tree

1 file changed

+66
-13
lines changed

1 file changed

+66
-13
lines changed

cyaron/graph.py

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -281,21 +281,21 @@ def DAG(point_count, edge_count, **kwargs):
281281
int point_count -> the count of vertexes
282282
int edge_count -> the count of edges
283283
**kwargs(Keyword args):
284-
bool self_loop = True -> whether to allow self loops or not
284+
bool self_loop = False -> whether to allow self loops or not
285285
bool repeated_edges = True -> whether to allow repeated edges or not
286-
bool directed = False -> whether the chain is directed(true:directed,false:not directed)
286+
bool loop = False -> whether to allow loops or not
287287
(int,int) weight_limit = (1,1) -> the limit of weight. index 0 is the min limit, and index 1 is the max limit(both included)
288288
int weight_limit -> If you use a int for this arg, it means the max limit of the weight(included)
289289
int/float weight_gen()
290290
= lambda: random.randint(weight_limit[0], weight_limit[1])
291291
-> the generator of the weights. It should return the weight. The default way is to use the random.randint()
292292
"""
293-
if point_count > edge_count - 1:
294-
raise Exception("the number of edges of DAG must more than the number of nodes + 1")
293+
if edge_count < point_count - 1:
294+
raise Exception("the number of edges of connected graph must more than the number of nodes - 1")
295295

296-
directed = kwargs.get("directed", False)
297-
self_loop = kwargs.get("self_loop", True)
296+
self_loop = kwargs.get("self_loop", False) # DAG default has no loop
298297
repeated_edges = kwargs.get("repeated_edges", True)
298+
loop = kwargs.get("loop", False)
299299
weight_limit = kwargs.get("weight_limit", (1, 1))
300300
if not list_like(weight_limit):
301301
weight_limit = (1, weight_limit)
@@ -304,24 +304,25 @@ def DAG(point_count, edge_count, **kwargs):
304304
weight_limit[0], weight_limit[1]))
305305

306306
used_edges = set()
307-
edge_buf = [edge for edge in Graph.tree(point_count, weight_limit=weight_limit).iterate_edges()]
308-
graph = Graph(point_count, directed)
307+
edge_buf = list(Graph.tree(point_count, weight_limit=weight_gen()).iterate_edges())
308+
graph = Graph(point_count, directed=True)
309309

310310
for edge in edge_buf:
311-
if random.randint(1, 2) == 1 and directed:
311+
if loop and random.randint(1, 2) == 1:
312312
edge.start, edge.end = edge.end, edge.start
313313
graph.add_edge(edge.start, edge.end, weight=edge.weight)
314314

315315
if not repeated_edges:
316316
used_edges.add((edge.start, edge.end))
317-
if not directed:
318-
used_edges.add((edge.end, edge.start))
319317

320318
i = point_count - 1
321319
while i < edge_count:
322320
u = random.randint(1, point_count)
323321
v = random.randint(1, point_count)
324322

323+
if not loop and u > v:
324+
u, v = v, u
325+
325326
if (not self_loop and u == v) or (not repeated_edges and (u, v) in used_edges):
326327
# Then we generate a new pair of nodes
327328
continue
@@ -330,8 +331,60 @@ def DAG(point_count, edge_count, **kwargs):
330331

331332
if not repeated_edges:
332333
used_edges.add((u, v))
333-
if not directed:
334-
used_edges.add((v, u))
334+
335+
i += 1
336+
337+
return graph
338+
339+
@staticmethod
340+
def UDAG(point_count, edge_count, **kwargs):
341+
"""UDAG(point_count, edge_count, **kwargs) -> Graph
342+
Factory method. Return a graph with point_count vertexes and edge_count edges.
343+
int point_count -> the count of vertexes
344+
int edge_count -> the count of edges
345+
**kwargs(Keyword args):
346+
bool self_loop = True -> whether to allow self loops or not
347+
bool repeated_edges = True -> whether to allow repeated edges or not
348+
(int,int) weight_limit = (1,1) -> the limit of weight. index 0 is the min limit, and index 1 is the max limit(both included)
349+
int weight_limit -> If you use a int for this arg, it means the max limit of the weight(included)
350+
int/float weight_gen()
351+
= lambda: random.randint(weight_limit[0], weight_limit[1])
352+
-> the generator of the weights. It should return the weight. The default way is to use the random.randint()
353+
"""
354+
if edge_count < point_count - 1:
355+
raise Exception("the number of edges of connected graph must more than the number of nodes - 1")
356+
357+
self_loop = kwargs.get("self_loop", True)
358+
repeated_edges = kwargs.get("repeated_edges", True)
359+
weight_limit = kwargs.get("weight_limit", (1, 1))
360+
if not list_like(weight_limit):
361+
weight_limit = (1, weight_limit)
362+
weight_gen = kwargs.get(
363+
"weight_gen", lambda: random.randint(
364+
weight_limit[0], weight_limit[1]))
365+
366+
used_edges = set()
367+
graph = Graph.tree(point_count, weight_limit=weight_gen(), directed=False)
368+
369+
for edge in graph.iterate_edges():
370+
if not repeated_edges:
371+
used_edges.add((edge.start, edge.end))
372+
used_edges.add((edge.end, edge.start))
373+
374+
i = point_count - 1
375+
while i < edge_count:
376+
u = random.randint(1, point_count)
377+
v = random.randint(1, point_count)
378+
379+
if (not self_loop and u == v) or (not repeated_edges and (u, v) in used_edges):
380+
# Then we generate a new pair of nodes
381+
continue
382+
383+
graph.add_edge(u, v, weight=weight_gen())
384+
385+
if not repeated_edges:
386+
used_edges.add((u, v))
387+
used_edges.add((v, u))
335388

336389
i += 1
337390

0 commit comments

Comments
 (0)