@@ -274,6 +274,122 @@ def graph(point_count, edge_count, **kwargs):
274274 i += 1
275275 return graph
276276
277+ @staticmethod
278+ def DAG (point_count , edge_count , ** kwargs ):
279+ """DAG(point_count, edge_count, **kwargs) -> Graph
280+ Factory method. Return a graph with point_count vertexes and edge_count edges.
281+ int point_count -> the count of vertexes
282+ int edge_count -> the count of edges
283+ **kwargs(Keyword args):
284+ bool self_loop = False -> whether to allow self loops or not
285+ bool repeated_edges = True -> whether to allow repeated edges or not
286+ bool loop = False -> whether to allow loops or not
287+ (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)
288+ int weight_limit -> If you use a int for this arg, it means the max limit of the weight(included)
289+ int/float weight_gen()
290+ = lambda: random.randint(weight_limit[0], weight_limit[1])
291+ -> the generator of the weights. It should return the weight. The default way is to use the random.randint()
292+ """
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" )
295+
296+ self_loop = kwargs .get ("self_loop" , False ) # DAG default has no loop
297+ repeated_edges = kwargs .get ("repeated_edges" , True )
298+ loop = kwargs .get ("loop" , False )
299+ weight_limit = kwargs .get ("weight_limit" , (1 , 1 ))
300+ if not list_like (weight_limit ):
301+ weight_limit = (1 , weight_limit )
302+ weight_gen = kwargs .get (
303+ "weight_gen" , lambda : random .randint (
304+ weight_limit [0 ], weight_limit [1 ]))
305+
306+ used_edges = set ()
307+ edge_buf = list (Graph .tree (point_count , weight_limit = weight_gen ()).iterate_edges ())
308+ graph = Graph (point_count , directed = True )
309+
310+ for edge in edge_buf :
311+ if loop and random .randint (1 , 2 ) == 1 :
312+ edge .start , edge .end = edge .end , edge .start
313+ graph .add_edge (edge .start , edge .end , weight = edge .weight )
314+
315+ if not repeated_edges :
316+ used_edges .add ((edge .start , edge .end ))
317+
318+ i = point_count - 1
319+ while i < edge_count :
320+ u = random .randint (1 , point_count )
321+ v = random .randint (1 , point_count )
322+
323+ if not loop and u > v :
324+ u , v = v , u
325+
326+ if (not self_loop and u == v ) or (not repeated_edges and (u , v ) in used_edges ):
327+ # Then we generate a new pair of nodes
328+ continue
329+
330+ graph .add_edge (u , v , weight = weight_gen ())
331+
332+ if not repeated_edges :
333+ used_edges .add ((u , v ))
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 ))
388+
389+ i += 1
390+
391+ return graph
392+
277393 @staticmethod
278394 def hack_spfa (point_count , ** kwargs ):
279395 """hack_spfa(point_count, **kwargs) -> None
0 commit comments