예제 #1
0
        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;
            }
        }
예제 #2
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);
        }
예제 #3
0
        /// <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]);
            }
        }
예제 #4
0
        /// <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);
        }
예제 #5
0
        /// <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);
            }
        }
예제 #6
0
        /// <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]);
            }
        }
예제 #7
0
        /// <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);
                }
            }
        }
예제 #10
0
        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;
                }
            }
        }