@@ -1327,29 +1327,43 @@ def bfs():
1327
1327
u = queue .popleft ()
1328
1328
if dist [u ] < dist [None ]:
1329
1329
for v in graph .neighbors (u ):
1330
- if dist [pair_V [v .name ]] == float ('inf' ):
1331
- dist [pair_V [v .name ]] = dist [u ] + 1
1332
- queue .append (pair_V [v .name ])
1333
- return dist [None ] != float ('inf' )
1330
+ if v .name in pair_V :
1331
+ alt = pair_V [v .name ]
1332
+ if alt is None :
1333
+ dist [None ] = dist [u ] + 1
1334
+ queue .append (None )
1335
+ elif dist .get (alt , float ('inf' )) == float ('inf' ):
1336
+ dist [alt ] = dist [u ] + 1
1337
+ queue .append (alt )
1338
+ return dist .get (None , float ('inf' )) != float ('inf' )
1334
1339
1335
1340
def dfs (u ):
1336
- if u is not None :
1337
- for v in graph .neighbors (u ):
1338
- if dist [pair_V [v .name ]] == dist [u ] + 1 :
1339
- if dfs (pair_V [v .name ]):
1341
+ if u is None :
1342
+ return True
1343
+ for v in graph .neighbors (u ):
1344
+ if v .name in pair_V :
1345
+ alt = pair_V [v .name ]
1346
+ if alt is None :
1347
+ pair_V [v .name ] = u
1348
+ pair_U [u ] = v .name
1349
+ return True
1350
+ elif dist .get (alt , float ('inf' )) == dist .get (u , float ('inf' )) + 1 :
1351
+ if dfs (alt ):
1340
1352
pair_V [v .name ] = u
1341
1353
pair_U [u ] = v .name
1342
1354
return True
1343
- dist [u ] = float ('inf' )
1344
- return False
1345
- return True
1355
+ dist [u ] = float ('inf' )
1356
+ return False
1346
1357
1347
1358
matching = set ()
1348
1359
while bfs ():
1349
1360
for u in U :
1350
1361
if pair_U [u ] is None :
1351
- if dfs (u ):
1352
- matching .add ((u , pair_U [u ]))
1362
+ dfs (u )
1363
+
1364
+ for u in U :
1365
+ if pair_U [u ] is not None :
1366
+ matching .add ((u , pair_U [u ]))
1353
1367
1354
1368
return matching
1355
1369
@@ -1392,8 +1406,8 @@ def maximum_matching(graph: Graph, algorithm: str, **kwargs) -> set:
1392
1406
>>> graph.add_edge('v_1', 'v_2')
1393
1407
>>> graph.add_edge('v_2', 'v_3')
1394
1408
>>> graph.add_edge('v_4', 'v_1')
1395
- >>> maximum_matching(graph, 'hopcroft_karp')
1396
- >>> {('v_1 ', 'v_4 '), ('v_3 ', 'v_2 ')}
1409
+ >>> maximum_matching(graph, 'hopcroft_karp', make_undirected=True )
1410
+ >>> {('v_3 ', 'v_2 '), ('v_1 ', 'v_4 ')}
1397
1411
1398
1412
References
1399
1413
==========
@@ -1448,22 +1462,33 @@ def bfs():
1448
1462
u = queue .popleft ()
1449
1463
if dist [u ] < dist [None ]:
1450
1464
for v in graph .neighbors (u ):
1451
- if dist [pair_V [v .name ]] == float ('inf' ):
1452
- dist [pair_V [v .name ]] = dist [u ] + 1
1453
- queue .append (pair_V [v .name ])
1454
- return dist [None ] != float ('inf' )
1465
+ if v .name in pair_V :
1466
+ alt = pair_V [v .name ]
1467
+ if alt is None :
1468
+ dist [None ] = dist [u ] + 1
1469
+ queue .append (None )
1470
+ elif dist .get (alt , float ('inf' )) == float ('inf' ):
1471
+ dist [alt ] = dist [u ] + 1
1472
+ queue .append (alt )
1473
+ return dist .get (None , float ('inf' )) != float ('inf' )
1455
1474
1456
1475
def dfs (u ):
1457
- if u is not None :
1458
- for v in graph .neighbors (u ):
1459
- if dist [pair_V [v .name ]] == dist [u ] + 1 :
1460
- if dfs (pair_V [v .name ]):
1476
+ if u is None :
1477
+ return True
1478
+ for v in graph .neighbors (u ):
1479
+ if v .name in pair_V :
1480
+ alt = pair_V [v .name ]
1481
+ if alt is None :
1482
+ pair_V [v .name ] = u
1483
+ pair_U [u ] = v .name
1484
+ return True
1485
+ elif dist .get (alt , float ('inf' )) == dist .get (u , float ('inf' )) + 1 :
1486
+ if dfs (alt ):
1461
1487
pair_V [v .name ] = u
1462
1488
pair_U [u ] = v .name
1463
1489
return True
1464
- dist [u ] = float ('inf' )
1465
- return False
1466
- return True
1490
+ dist [u ] = float ('inf' )
1491
+ return False
1467
1492
1468
1493
matching = set ()
1469
1494
@@ -1474,7 +1499,7 @@ def dfs(u):
1474
1499
results = Executor .map (dfs , unmatched_nodes )
1475
1500
1476
1501
for u , success in zip (unmatched_nodes , results ):
1477
- if success :
1502
+ if success and pair_U [ u ] is not None :
1478
1503
matching .add ((u , pair_U [u ]))
1479
1504
1480
1505
return matching
@@ -1497,6 +1522,8 @@ def maximum_matching_parallel(graph: Graph, algorithm: str, num_threads: int, **
1497
1522
'hopcroft_karp' -> Hopcroft-Karp algorithm for Bipartite Graphs as given in [1].
1498
1523
num_threads: int
1499
1524
The maximum number of threads to be used.
1525
+ make_undirected: bool
1526
+ If False, the graph should be undirected or unwanted results may be obtained. The graph can be made undirected by setting this to true.
1500
1527
backend: pydatastructs.Backend
1501
1528
The backend to be used.
1502
1529
Optional, by default, the best available
@@ -1520,8 +1547,8 @@ def maximum_matching_parallel(graph: Graph, algorithm: str, num_threads: int, **
1520
1547
>>> graph.add_bidirectional_edge('v_1', 'v_2')
1521
1548
>>> graph.add_bidirectional_edge('v_2', 'v_3')
1522
1549
>>> graph.add_bidirectional_edge('v_4', 'v_1')
1523
- >>> maximum_matching_parallel(graph, 'hopcroft_karp', 1)
1524
- >>> {('v_1 ', 'v_4 '), ('v_3 ', 'v_2 ')}
1550
+ >>> maximum_matching_parallel(graph, 'hopcroft_karp', 1, make_undirected=True )
1551
+ >>> {('v_3 ', 'v_2 '), ('v_1 ', 'v_4 ')}
1525
1552
1526
1553
References
1527
1554
==========
@@ -1531,6 +1558,9 @@ def maximum_matching_parallel(graph: Graph, algorithm: str, num_threads: int, **
1531
1558
1532
1559
raise_if_backend_is_not_python (
1533
1560
maximum_matching_parallel , kwargs .get ('backend' , Backend .PYTHON ))
1561
+ make_undirected = kwargs .get ('make_undirected' , False )
1562
+ if make_undirected :
1563
+ graph = graph .to_undirected_adjacency_list ()
1534
1564
1535
1565
import pydatastructs .graphs .algorithms as algorithms
1536
1566
func = "_maximum_matching_" + algorithm + "_parallel"
0 commit comments