/// <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> public override void CreateFillin(SparseMatrix <T> matrix, MatrixElement <T> fillin) { matrix.ThrowIfNull(nameof(matrix)); fillin.ThrowIfNull(nameof(fillin)); // 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> /// Update the strategy after the pivot was moved. /// </summary> /// <param name="matrix">The matrix.</param> /// <param name="pivot">The pivot element.</param> /// <param name="eliminationStep">The elimination step.</param> public override void Update(SparseMatrix <T> matrix, MatrixElement <T> pivot, int eliminationStep) { 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 = 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 = 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> /// 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> /// <returns> /// True if the pivot can be used. /// </returns> public override bool IsValidPivot(MatrixElement <T> pivot) { pivot.ThrowIfNull(nameof(pivot)); // 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) { largest = Math.Max(largest, Magnitude(element.Value)); element = element.Below; } // Check the validity if (largest * RelativePivotThreshold < magnitude) { return(true); } return(false); }
/// <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> public override void MovePivot(SparseMatrix <T> matrix, SparseVector <T> rhs, MatrixElement <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 column = pivot.Column; // If the pivot is a singleton, then we just consumed it if (_markowitzProduct[pivot.Row] == 0 || _markowitzProduct[pivot.Column] == 0) { Singletons--; } // Exchange rows if (pivot.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 (column != eliminationStep) { // Swap column Markowitz numbers var tmp = _markowitzColumn[column]; _markowitzColumn[column] = _markowitzColumn[eliminationStep]; _markowitzColumn[eliminationStep] = tmp; // Update the Markowitz product oldProduct = _markowitzProduct[column]; _markowitzProduct[column] = _markowitzRow[column] * _markowitzColumn[column]; if (oldProduct == 0) { if (_markowitzProduct[column] != 0) { Singletons--; } } else { if (_markowitzProduct[column] == 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++; } } }