/// <summary> /// Notifies the strategy that a fill-in has been created /// </summary> /// <param name="matrix">The matrix.</param> /// <param name="fillin">The fill-in.</param> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="matrix"/> or <paramref name="fillin"/> is <c>null</c>. /// </exception> public void CreateFillin(ISparseMatrix <T> matrix, ISparseMatrixElement <T> fillin) { matrix.ThrowIfNull(nameof(matrix)); fillin.ThrowIfNull(nameof(fillin)); if (_markowitzProduct == null) { return; } // Update the markowitz row count int index = fillin.Row; _markowitzRow[index]++; _markowitzProduct[index] = Math.Min(_markowitzRow[index] * _markowitzColumn[index], _maxMarkowitzCount); if (_markowitzRow[index] == 1 && _markowitzColumn[index] != 0) { Singletons--; } // Update the markowitz column count index = fillin.Column; _markowitzColumn[index]++; _markowitzProduct[index] = Math.Min(_markowitzRow[index] * _markowitzColumn[index], _maxMarkowitzCount); if (_markowitzRow[index] != 0 && _markowitzColumn[index] == 1) { Singletons--; } }
/// <summary> /// This method will check whether or not a pivot element is valid or not. /// It checks for the submatrix right/below of the pivot. /// </summary> /// <param name="pivot">The pivot candidate.</param> /// <param name="max">The maximum index that a pivot can have.</param> /// <returns> /// True if the pivot can be used. /// </returns> /// <exception cref="ArgumentNullException">Thrown if <paramref name="pivot"/> is <c>null</c>.</exception> public bool IsValidPivot(ISparseMatrixElement <T> pivot, int max) { pivot.ThrowIfNull(nameof(pivot)); if (pivot.Row > max || pivot.Column > max) { return(false); } // Get the magnitude of the current pivot var magnitude = Magnitude(pivot.Value); // Search for the largest element below the pivot var element = pivot.Below; var largest = 0.0; while (element != null && element.Row <= max) { largest = Math.Max(largest, Magnitude(element.Value)); element = element.Below; } // Check the validity if (largest * RelativePivotThreshold < magnitude) { return(true); } return(false); }
/// <summary> /// Moves a chosen pivot to the diagonal. /// </summary> /// <param name="pivot">The pivot element.</param> /// <param name="step">The current step of factoring.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="pivot"/> is <c>null</c>.</exception> protected void MovePivot(ISparseMatrixElement <T> pivot, int step) { pivot.ThrowIfNull(nameof(pivot)); Parameters.MovePivot(Matrix, Vector, pivot, step); // Move the pivot in the matrix SwapRows(pivot.Row, step); SwapColumns(pivot.Column, step); // Update the pivoting strategy Parameters.Update(Matrix, pivot, Size - PivotSearchReduction); }
/// <summary> /// Update the strategy after the pivot was moved. /// </summary> /// <param name="matrix">The matrix.</param> /// <param name="pivot">The pivot element.</param> /// <param name="limit">The maximum row/column for pivots.</param> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="matrix"/> or <paramref name="pivot"/> is <c>null</c>. /// </exception> public void Update(ISparseMatrix <T> matrix, ISparseMatrixElement <T> pivot, int limit) { matrix.ThrowIfNull(nameof(matrix)); pivot.ThrowIfNull(nameof(pivot)); // If we haven't setup, just skip if (_markowitzProduct == null) { return; } // Go through all elements below the pivot. If they exist, then we can subtract 1 from the Markowitz row vector! for (var column = pivot.Below; column != null && column.Row <= limit; column = column.Below) { var row = column.Row; // Update the Markowitz product _markowitzProduct[row] -= _markowitzColumn[row]; --_markowitzRow[row]; // If we reached 0, then the row just turned to a singleton row if (_markowitzRow[row] == 0) { Singletons++; } } // go through all elements right of the pivot. For every element, we can subtract 1 from the Markowitz column vector! for (var row = pivot.Right; row != null && row.Column <= limit; row = row.Right) { var column = row.Column; // Update the Markowitz product _markowitzProduct[column] -= _markowitzRow[column]; --_markowitzColumn[column]; // If we reached 0, then the column just turned to a singleton column // This only adds a singleton if the row wasn't detected as a singleton row first if (_markowitzColumn[column] == 0 && _markowitzRow[column] != 0) { Singletons++; } } }
/// <summary> /// Move the pivot to the diagonal for this elimination step. /// </summary> /// <param name="matrix">The matrix.</param> /// <param name="rhs">The right-hand side vector.</param> /// <param name="pivot">The pivot element.</param> /// <param name="eliminationStep">The elimination step.</param> /// <remarks> /// This is done by swapping the rows and columns of the diagonal and that of the pivot. /// </remarks> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="matrix"/>, <paramref name="rhs"/> or <paramref name="pivot"/> is <c>null</c>. /// </exception> public void MovePivot(ISparseMatrix <T> matrix, ISparseVector <T> rhs, ISparseMatrixElement <T> pivot, int eliminationStep) { matrix.ThrowIfNull(nameof(matrix)); rhs.ThrowIfNull(nameof(rhs)); pivot.ThrowIfNull(nameof(pivot)); // If we haven't setup, just skip if (_markowitzProduct == null) { return; } int oldProduct; var row = pivot.Row; var col = pivot.Column; // If the pivot is a singleton, then we just consumed it if (_markowitzProduct[row] == 0 || _markowitzProduct[col] == 0) { Singletons--; } // Exchange rows if (row != eliminationStep) { // Swap row Markowitz numbers var tmp = _markowitzRow[row]; _markowitzRow[row] = _markowitzRow[eliminationStep]; _markowitzRow[eliminationStep] = tmp; // Update the Markowitz product oldProduct = _markowitzProduct[row]; _markowitzProduct[row] = _markowitzRow[row] * _markowitzColumn[row]; if (oldProduct == 0) { if (_markowitzProduct[row] != 0) { Singletons--; } } else { if (_markowitzProduct[row] == 0) { Singletons++; } } } // Exchange columns if (col != eliminationStep) { // Swap column Markowitz numbers var tmp = _markowitzColumn[col]; _markowitzColumn[col] = _markowitzColumn[eliminationStep]; _markowitzColumn[eliminationStep] = tmp; // Update the Markowitz product oldProduct = _markowitzProduct[col]; _markowitzProduct[col] = _markowitzRow[col] * _markowitzColumn[col]; if (oldProduct == 0) { if (_markowitzProduct[col] != 0) { Singletons--; } } else { if (_markowitzProduct[col] == 0) { Singletons++; } } } // Also update the moved pivot oldProduct = _markowitzProduct[eliminationStep]; _markowitzProduct[eliminationStep] = _markowitzRow[eliminationStep] * _markowitzColumn[eliminationStep]; if (oldProduct == 0) { if (_markowitzProduct[eliminationStep] != 0) { Singletons--; } } else { if (_markowitzProduct[eliminationStep] == 0) { Singletons++; } } }