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);
            }
        }
 protected virtual void Assign(RectMatrix <T> clone)
 {
     clone.EnsureSize(Size.RowCount, Size.ColumnCount);
     Array.Copy(this.data, clone.data, this.data.Length);
 }