private static void Initialize(MnMatrix graph, double[] verticesXLabel, double[] verticesYLabel) { _maximumEdge = 0; for (int i = 0; i < verticesXLabel.Length; i++) { double max = 0; for (int j = 0; j < verticesYLabel.Length; j++) { if (graph.At(i, j) > max) { max = graph.At(i, j); } } verticesXLabel[i] = max; if (max > _maximumEdge) { _maximumEdge = max; } } for (int j = 0; j < verticesYLabel.Length; j++) { verticesYLabel[j] = 0; } }
private static DenseMatrix CreateEqualityGraph(MnMatrix graph, double[] verticesXLabel, double[] verticesYLabel) { DenseMatrix subGraph = new DenseMatrix(verticesXLabel.Length, verticesYLabel.Length); for (int i = 0; i < verticesXLabel.Length; i++) { for (int j = 0; j < verticesYLabel.Length; j++) { if (Math.Abs(graph.At(i, j) - (verticesXLabel[i] + verticesYLabel[j])) < EPSILON) { subGraph.At(i, j, 1); } } } return(subGraph); }
/// <summary> /// Divides a scalar by each element of the matrix and stores the result in the result matrix. /// </summary> /// <param name="dividend">The scalar to add.</param> /// <param name="result">The matrix to store the result of the division.</param> protected override void DoDivideByThis(double dividend, Matrix <double> result) { if (result is DiagonalMatrix diagResult) { var resultData = diagResult._data; CommonParallel.For(0, _data.Length, 4096, (a, b) => { for (int i = a; i < b; i++) { resultData[i] = dividend / _data[i]; } }); return; } result.Clear(); for (int i = 0; i < _data.Length; i++) { result.At(i, i, dividend / _data[i]); } }
/// <summary> /// Multiplies this matrix with transpose of another matrix and places the results into the result matrix. /// </summary> /// <param name="other">The matrix to multiply with.</param> /// <param name="result">The result of the multiplication.</param> protected override void DoTransposeAndMultiply(Matrix <double> other, Matrix <double> result) { var diagonalOther = other as DiagonalMatrix; var diagonalResult = result as DiagonalMatrix; if (diagonalOther != null && diagonalResult != null) { var thisDataCopy = new double[diagonalResult._data.Length]; var otherDataCopy = new double[diagonalResult._data.Length]; Array.Copy(_data, thisDataCopy, (diagonalResult._data.Length > _data.Length) ? _data.Length : diagonalResult._data.Length); Array.Copy(diagonalOther._data, otherDataCopy, (diagonalResult._data.Length > diagonalOther._data.Length) ? diagonalOther._data.Length : diagonalResult._data.Length); Control.LinearAlgebraProvider.PointWiseMultiplyArrays(thisDataCopy, otherDataCopy, diagonalResult._data); return; } var denseOther = other.Storage as DenseColumnMajorMatrixStorage <double>; if (denseOther != null) { var dense = denseOther.Data; var diagonal = _data; var d = Math.Min(denseOther.ColumnCount, RowCount); if (d < RowCount) { result.ClearSubMatrix(denseOther.ColumnCount, RowCount - denseOther.ColumnCount, 0, denseOther.RowCount); } int index = 0; for (int j = 0; j < d; j++) { for (int i = 0; i < denseOther.RowCount; i++) { result.At(j, i, dense[index] * diagonal[j]); index++; } } return; } base.DoTransposeAndMultiply(other, result); }
/// <summary> /// Divides each element of the matrix by a scalar and places results into the result matrix. /// </summary> /// <param name="divisor">The scalar to divide the matrix with.</param> /// <param name="result">The matrix to store the result of the division.</param> protected override void DoDivide(double divisor, Matrix <double> result) { if (divisor == 1.0) { CopyTo(result); return; } var diagResult = result as DiagonalMatrix; if (diagResult != null) { Control.LinearAlgebraProvider.ScaleArray(1.0 / divisor, _data, diagResult._data); return; } result.Clear(); for (int i = 0; i < _data.Length; i++) { result.At(i, i, _data[i] / divisor); } }
/// <summary> /// Divides a scalar by each element of the matrix and stores the result in the result matrix. /// </summary> /// <param name="dividend">The scalar to add.</param> /// <param name="result">The matrix to store the result of the division.</param> protected override void DoDivideByThis(double dividend, Matrix <double> result) { var diagResult = result as DiagonalMatrix; if (diagResult != null) { var resultData = diagResult._data; for (int i = 0; i < _data.Length; i++) { resultData[i] = dividend / _data[i]; } return; } result.Clear(); for (int i = 0; i < _data.Length; i++) { result.At(i, i, dividend / _data[i]); } }
/// <summary> /// Divides each element of the matrix by a scalar and places results into the result matrix. /// </summary> /// <param name="divisor">The scalar to divide the matrix with.</param> /// <param name="result">The matrix to store the result of the division.</param> protected override void DoDivide(double divisor, Matrix <double> result) { if (divisor == 1.0) { CopyTo(result); return; } var diagResult = result as DiagonalMatrix; if (diagResult != null) { Map(x => x / divisor, result, divisor == 0.0 ? Zeros.Include : Zeros.AllowSkip); return; } result.Clear(); for (int i = 0; i < _data.Length; i++) { result.At(i, i, _data[i] / divisor); } }
/// <summary> /// Puts the lower triangle of this matrix into the result matrix. /// </summary> /// <param name="result">Where to store the lower triangle.</param> /// <exception cref="ArgumentNullException">If <paramref name="result"/> is <see langword="null" />.</exception> /// <exception cref="ArgumentException">If the result matrix's dimensions are not the same as this matrix.</exception> public override void LowerTriangle(Matrix <double> result) { if (result == null) { throw new ArgumentNullException("result"); } if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch <ArgumentException>(this, result, "result"); } if (ReferenceEquals(this, result)) { return; } result.Clear(); for (var i = 0; i < _data.Length; i++) { result.At(i, i, _data[i]); } }
/// <summary> /// Multiplies this matrix with another matrix and places the results into the result matrix. /// </summary> /// <param name="other">The matrix to multiply with.</param> /// <param name="result">The result of the multiplication.</param> protected override void DoMultiply(Matrix <double> other, Matrix <double> result) { var sparseOther = other as SparseMatrix; var sparseResult = result as SparseMatrix; if (sparseOther != null && sparseResult != null) { DoMultiplySparse(sparseOther, sparseResult); return; } var diagonalOther = other.Storage as DiagonalMatrixStorage <double>; if (diagonalOther != null && sparseResult != null) { var diagonal = diagonalOther.Data; if (other.ColumnCount == other.RowCount) { Storage.MapIndexedTo(result.Storage, (i, j, x) => x * diagonal[j], Zeros.AllowSkip, ExistingData.Clear); } else { result.Storage.Clear(); Storage.MapSubMatrixIndexedTo(result.Storage, (i, j, x) => x * diagonal[j], 0, 0, RowCount, 0, 0, ColumnCount, Zeros.AllowSkip, ExistingData.AssumeZeros); } return; } result.Clear(); var rowPointers = _storage.RowPointers; var columnIndices = _storage.ColumnIndices; var values = _storage.Values; var denseOther = other.Storage as DenseColumnMajorMatrixStorage <double>; if (denseOther != null) { // in this case we can directly address the underlying data-array for (var row = 0; row < RowCount; row++) { var startIndex = rowPointers[row]; var endIndex = rowPointers[row + 1]; if (startIndex == endIndex) { continue; } for (var column = 0; column < other.ColumnCount; column++) { var otherColumnStartPosition = column * other.RowCount; var sum = 0d; for (var index = startIndex; index < endIndex; index++) { sum += values[index] * denseOther.Data[otherColumnStartPosition + columnIndices[index]]; } result.At(row, column, sum); } } return; } var columnVector = new DenseVector(other.RowCount); for (var row = 0; row < RowCount; row++) { var startIndex = rowPointers[row]; var endIndex = rowPointers[row + 1]; if (startIndex == endIndex) { continue; } for (var column = 0; column < other.ColumnCount; column++) { // Multiply row of matrix A on column of matrix B other.Column(column, columnVector); var sum = 0d; for (var index = startIndex; index < endIndex; index++) { sum += values[index] * columnVector[columnIndices[index]]; } result.At(row, column, sum); } } }
public static void RunAlgorithm(MnMatrix graph, int[] copulationVerticesX, int[] copulationVerticesY) { double min = graph.ToColumnWiseArray().Min(); if (min < 0) { for (int i = 0; i < graph.ColumnCount; i++) { for (int j = 0; j < graph.RowCount; j++) { graph[j, i] = graph[j, i] - i + 1; } } } int limit = 0; if (copulationVerticesX.Length > copulationVerticesY.Length) { limit = copulationVerticesX.Length - copulationVerticesY.Length; } double[] verticesXLabel = new double[copulationVerticesX.Length]; double[] verticesYLabel = new double[copulationVerticesY.Length]; Initialize(graph, verticesXLabel, verticesYLabel); while (true) { for (int i = 0; i < copulationVerticesX.Length; i++) { copulationVerticesX[i] = -1; } for (int i = 0; i < copulationVerticesY.Length; i++) { copulationVerticesY[i] = -1; } DenseMatrix equalityGraph = CreateEqualityGraph(graph, verticesXLabel, verticesYLabel); int[,] vertices; HungarianAlgorithm.RunAlgorithm(equalityGraph, copulationVerticesX, copulationVerticesY, out vertices); if (CountCopulation(copulationVerticesX) == limit) { return; } //if (CountCopulation(copulationVerticesY) == 0) //{ // return; //} var F1UF2 = new List <int>(); var L2 = new List <int>(); var L1UL3 = new List <int>(); for (int i = 0; i < copulationVerticesX.Length; i++) { if (vertices[0, i] == 0) { F1UF2.Add(i); } } for (int i = 0; i < copulationVerticesY.Length; i++) { if (vertices[1, i] == 0) { L2.Add(i); } else { L1UL3.Add(i); } } double minDelta = _maximumEdge + 1; foreach (var i in F1UF2) { foreach (var j in L1UL3) { // if (graph[i, j] == -1) continue; double delta = verticesXLabel[i] + verticesYLabel[j] - graph.At(i, j); if (delta < minDelta) { minDelta = delta; } } } foreach (var i in F1UF2) { verticesXLabel[i] -= minDelta; } foreach (var i in L2) { verticesYLabel[i] += minDelta; } } }