/// <summary> /// Approximates the solution to the matrix equation <b>Ax = b</b>. /// </summary> /// <param name="rhs">The right hand side vector.</param> /// <param name="lhs">The left hand side vector. Also known as the result vector.</param> public void Approximate(Vector rhs, Vector lhs) { if (rhs == null) { throw new ArgumentNullException("rhs"); } if (lhs == null) { throw new ArgumentNullException("lhs"); } if (_upper == null) { throw new ArgumentException(Resources.ArgumentMatrixDoesNotExist); } if ((lhs.Count != rhs.Count) || (lhs.Count != _upper.RowCount)) { throw new ArgumentException(Resources.ArgumentVectorsSameLength, "rhs"); } // Solve equation here // Pivot(vector, result); // Solve L*Y = B(piv,:) Vector rowValues = new DenseVector(_lower.RowCount); for (var i = 0; i < _lower.RowCount; i++) { _lower.Row(i, rowValues); var sum = Complex.Zero; for (var j = 0; j < i; j++) { sum += rowValues[j] * lhs[j]; } lhs[i] = rhs[i] - sum; } // Solve U*X = Y; for (var i = _upper.RowCount - 1; i > -1; i--) { _upper.Row(i, rowValues); var sum = Complex.Zero; for (var j = _upper.RowCount - 1; j > i; j--) { sum += rowValues[j] * lhs[j]; } lhs[i] = 1 / rowValues[i] * (lhs[i] - sum); } // We have a column pivot so we only need to pivot the // end result not the incoming right hand side vector var temp = (Vector)lhs.Clone(); Pivot(temp, lhs); }
/// <summary> /// Solves a system of linear equations, <b>Ax = b</b>, with A QR factorized. /// </summary> /// <param name="input">The right hand side vector, <b>b</b>.</param> /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param> public override void Solve(Vector<Complex> input, Vector<Complex> result) { // Ax=b where A is an m x n matrix // Check that b is a column vector with m entries if (FullR.RowCount != input.Count) { throw new ArgumentException(Resources.ArgumentVectorsSameLength); } // Check that x is a column vector with n entries if (FullR.ColumnCount != result.Count) { throw Matrix.DimensionsDontMatch<ArgumentException>(FullR, result); } var inputCopy = input.Clone(); // Compute Y = transpose(Q)*B var column = new Complex[FullR.RowCount]; for (var k = 0; k < FullR.RowCount; k++) { column[k] = inputCopy[k]; } for (var i = 0; i < FullR.RowCount; i++) { var s = Complex.Zero; for (var k = 0; k < FullR.RowCount; k++) { s += Q.At(k, i).Conjugate()*column[k]; } inputCopy[i] = s; } // Solve R*X = Y; for (var k = FullR.ColumnCount - 1; k >= 0; k--) { inputCopy[k] /= FullR.At(k, k); for (var i = 0; i < k; i++) { inputCopy[i] -= inputCopy[k]*FullR.At(i, k); } } for (var i = 0; i < FullR.ColumnCount; i++) { result[i] = inputCopy[i]; } }