void FillMaximalMatching(BipartiteGraphMatching <T> matching) { GetMaximalMatchingFSet fSet = new GetMaximalMatchingFSet(Data.VSize); do { fSet.Clear(); var freeUVertexList = Data.GetUVertexList().Where(x => !IsMatchedVertex(x)); foreach (var uVertex in freeUVertexList) { Color bfsColor = Color.CreateColor(); DoBFSearch(uVertex, (x, y) => IsMatchedEdge(x, y) ? Data.IsVVertex(x) : Data.IsUVertex(x) , (x, y) => Data.UpdateEdgeData(x, y, edgeData => edgeData.WithColor(bfsColor)) , x => { if (Data.IsVVertex(x) && !IsMatchedVertex(x)) { if (IsInFSet(x)) { fSet.UpdateItem(x.GetData <GetMaximalMatchingVertexInFSetData>().ItemIndex, new GetMaximalMatchingFSetItem(x, bfsColor)); } else { int itemIndex = fSet.AddItem(new GetMaximalMatchingFSetItem(x, bfsColor)); x.Data = new GetMaximalMatchingVertexInFSetData(itemIndex); } return(false); } return(true); }); } foreach (var fSetItem in fSet) { DoDFSearch(fSetItem.Vertex, (x, y) => Data.GetEdgeData(x, y).Color == fSetItem.BfsColor , (x, y) => { var uVertex = matching.Data.GetUVertex(Data.GetUVertex(x, y).Handle); var vVertex = matching.Data.GetVVertex(Data.GetVVertex(x, y).Handle); if (IsMatchedEdge(x, y)) { Data.GetEdgeData(x, y).WithData(null); matching.DeleteEdge(uVertex, vVertex); } else { Data.UpdateEdgeData(x, y, edgeData => edgeData.WithData(new GetMaximalMatchingMatchedData())); matching.CreateEdge(uVertex, vVertex); } }, x => { bool stopSearch = Data.IsUVertex(x) && !IsMatchedVertex(x); x.Data = new GetMaximalMatchingMatchedData(); return(stopSearch ? false : true); }); } }while(fSet.Size != 0); ClearData(true, true); }
BipartiteGraphMatching <T> GetMaximalMatchingCore() { BipartiteGraphMatching <T> matching = Clone <BipartiteGraphMatching <T> >(false); if (Size != 0) { FillMaximalMatching(matching); } return(matching); }
public BipartiteGraphMatching <T> GetAssignmentMatching() { if (Data.USize != Data.VSize || Properties.IsNegativeWeighted || !IsComplete()) { throw new InvalidOperationException(); } BipartiteGraphMatching <T> graph = Clone <BipartiteGraphMatching <T> >(false); Func <int, int, double, EdgeData, EdgeData> func1 = (row, column, minVal, x) => { var edgeData = x.WithWeight(x.Weight - minVal); if (MathUtils.AreEqual(edgeData.Weight, 0)) { graph.EnsureEdge(column, row, x.Weight); } return(edgeData); }; Func <int, int, double, EdgeData, EdgeData> func2 = (row, column, minVal, x) => { var edgeData = x.WithWeight(x.Weight + minVal); if (!MathUtils.AreEqual(edgeData.Weight, 0)) { graph.EnsureNoEdge(column, row); } return(edgeData); }; RectMatrix <EdgeData, Color> matrix = Data.Matrix.Clone(); int rowCount = matrix.Size.RowCount; for (int n = 0; n < rowCount; n++) { double minVal = matrix.GetRowItemList(n).Select(x => x.Weight).Min(); matrix.TranslateRow(n, func1, minVal); } if (graph.IsPerfect()) { return(graph); } int columnCount = matrix.Size.ColumnCount; for (int n = 0; n < columnCount; n++) { double minVal = matrix.GetColumnItemList(n).Select(x => x.Weight).Min(); matrix.TranslateColumn(n, func1, minVal); } if (graph.IsPerfect()) { return(graph); } while (true) { var matching = graph.GetMaximalMatchingCore(); if (matching.IsPerfect()) { return(CloneWithEdges(matching)); } Color color1 = Color.CreateColor(); matching.Data.GetVVertexList() .Where(x => x.Degree != 0) .ForEach(x => matrix.RowAttributes[x.Handle] = color1); Color color2 = Color.CreateColor(); matrix.TranslateRowAttributes((row, rowColor) => rowColor != color1, x => color2); matrix.ForEach((row, column, rowColor, columnColor, x) => rowColor == color2 && MathUtils.AreEqual(x.Weight, 0), (row, column, x) => { matrix.ColumnAttributes[column] = color2; for (int n = 0; n < matrix.Size.RowCount; n++) { if (matching.AreVerticesAdjacent(column, n)) { matrix.RowAttributes[n] = color2; } } }); Color color3 = Color.CreateColor(); matrix.TranslateColumnAttributes((column, columnColor) => columnColor == color2, x => color3); matrix.TranslateRowAttributes((row, rowColor) => rowColor != color2, x => color3); double minValue = matrix.GetItems((row, column, rowColor, columnColor, x) => rowColor != color3 && columnColor != color3).Select(x => x.Weight).Min(); matrix.Translate((row, column, rowColor, columnColor, x) => rowColor != color3 && columnColor != color3, func1, minValue); matrix.Translate((row, column, rowColor, columnColor, x) => rowColor == color3 && columnColor == color3, func2, minValue); } }