Browse Source

Started implementing LU decomposition.

la-knuth
Jurgen Van Gael 17 years ago
parent
commit
e946954ec4
  1. 13
      src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebraProviderOfT.cs
  2. 11
      src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs
  3. 15
      src/Numerics/Algorithms/LinearAlgebra/NativeAlgebraProvider.include
  4. 26
      src/Numerics/LinearAlgebra/Double/Factorization/Cholesky.cs
  5. 36
      src/Numerics/LinearAlgebra/Double/Factorization/DenseCholesky.cs
  6. 179
      src/Numerics/LinearAlgebra/Double/Factorization/DenseLU.cs
  7. 171
      src/Numerics/LinearAlgebra/Double/Factorization/LU.cs
  8. 103
      src/Numerics/LinearAlgebra/Double/Matrix.cs
  9. 2
      src/Numerics/Numerics.csproj

13
src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebraProviderOfT.cs

@ -210,14 +210,15 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
int aRows, int aColumns, T[] b, int bRows, int bColumns, T beta, T[] c);
/// <summary>
/// Computes the LU factorization of A.
/// Computes the LUP factorization of A. P*A = L*U.
/// </summary>
/// <param name="a">An m by n matrix. The matrix is overwritten with the
/// the LU factorization On exit.</param>
/// <param name="ipiv">On exit, it contains the pivot indices. The size
/// of the array must be min(m,n).</param>
/// <param name="a">An <paramref name="aOrder"/> by <paramref name="aOrder"/> matrix. The matrix is overwritten with the
/// the LU factorization on exit. The lower triangular factor L is stored in under the diagonal of <paramref name="A"/> (the diagonal is always 1.0
/// for the L factor). The upper triangular factor U is stored on and above the diagonal of <paramref name="A"/>.</param>
/// <param name="aOrder">The order of the square matrix <paramref name="A"/>.</param>
/// <param name="ipiv">On exit, it contains the pivot indices. The size of the array must be <paramref name="aOrder"/>.</param>
/// <remarks>This is equivalent to the GETRF LAPACK routine.</remarks>
void LUFactor(T[] a, int[] ipiv);
void LUFactor(T[] a, int aOrder, int[] ipiv);
/// <summary>
/// Computes the inverse of matrix using LU factorization.

11
src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs

@ -688,7 +688,16 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
}
}
public void LUFactor(double[] a, int[] ipiv)
/// <summary>
/// Computes the LUP factorization of A. P*A = L*U.
/// </summary>
/// <param name="a">An <paramref name="aOrder"/> by <paramref name="aOrder"/> matrix. The matrix is overwritten with the
/// the LU factorization on exit. The lower triangular factor L is stored in under the diagonal of <paramref name="A"/> (the diagonal is always 1.0
/// for the L factor). The upper triangular factor U is stored on and above the diagonal of <paramref name="A"/>.</param>
/// <param name="aOrder">The order of the square matrix <paramref name="A"/>.</param>
/// <param name="ipiv">On exit, it contains the pivot indices. The size of the array must be <paramref name="aOrder"/>.</param>
/// <remarks>This is equivalent to the GETRF LAPACK routine.</remarks>
public void LUFactor(double[] a, int aOrder, int[] ipiv)
{
throw new NotImplementedException();
}

15
src/Numerics/Algorithms/LinearAlgebra/NativeAlgebraProvider.include

@ -333,16 +333,17 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.<#=library#>
SafeNativeMethods.d_matrix_multiply(transposeA, transposeB, m, n, k, alpha, a, b, beta, c);
}
/// <summary>
/// Computes the LU factorization of A.
/// Computes the LUP factorization of A. P*A = L*U.
/// </summary>
/// <param name="a">An m by n matrix. The matrix is overwritten with the
/// the LU factorization On exit.</param>
/// <param name="ipiv">On exit, it contains the pivot indices. The size
/// of the array must be min(m,n).</param>
/// <param name="a">An <paramref name="aOrder"/> by <paramref name="aOrder"/> matrix. The matrix is overwritten with the
/// the LU factorization on exit. The lower triangular factor L is stored in under the diagonal of <paramref name="A"/> (the diagonal is always 1.0
/// for the L factor). The upper triangular factor U is stored on and above the diagonal of <paramref name="A"/>.</param>
/// <param name="aOrder">The order of the square matrix <paramref name="A"/>.</param>
/// <param name="ipiv">On exit, it contains the pivot indices. The size of the array must be <paramref name="aOrder"/>.</param>
/// <remarks>This is equivalent to the GETRF LAPACK routine.</remarks>
public void LUFactor(double[] a, int[] ipiv)
public void LUFactor(double[] a, int aOrder, int[] ipiv)
{
throw new NotImplementedException();
}

26
src/Numerics/LinearAlgebra/Double/Factorization/Cholesky.cs

@ -110,7 +110,18 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// </summary>
/// <param name="input">The right hand side <see cref="Matrix"/>, <b>B</b>.</param>
/// <returns>The left hand side <see cref="Matrix"/>, <b>X</b>.</returns>
public abstract Matrix Solve(Matrix input);
public virtual Matrix Solve(Matrix input)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
var X = input.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(input, X);
return X;
}
/// <summary>
/// Solves a system of linear equations, <b>AX = B</b>, with A Cholesky factorized.
@ -124,7 +135,18 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// </summary>
/// <param name="input">The right hand side vector, <b>b</b>.</param>
/// <returns>The left hand side <see cref="Vector"/>, <b>x</b>.</returns>
public abstract Vector Solve(Vector input);
public virtual Vector Solve(Vector input)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
var x = input.CreateVector(input.Count);
Solve(input, x);
return x;
}
/// <summary>
/// Solves a system of linear equations, <b>Ax = b</b>, with A Cholesky factorized.

36
src/Numerics/LinearAlgebra/Double/Factorization/DenseCholesky.cs

@ -70,24 +70,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
mFactor = factor;
}
/// <summary>
/// Solves a system of linear equations, <b>AX = B</b>, with A Cholesky factorized.
/// </summary>
/// <param name="input">The right hand side <see cref="Matrix"/>, <b>B</b>.</param>
/// <returns>The left hand side <see cref="Matrix"/>, <b>X</b>.</returns>
public override Matrix Solve(Matrix input)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
var X = new DenseMatrix(input.RowCount, input.ColumnCount);
Solve(input, X);
return X;
}
/// <summary>
/// Solves a system of linear equations, <b>AX = B</b>, with A Cholesky factorized.
/// </summary>
@ -142,24 +124,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Data, dfactor.RowCount, dresult.Data, dresult.RowCount, dresult.ColumnCount);
}
/// <summary>
/// Solves a system of linear equations, <b>Ax = b</b>, with A Cholesky factorized.
/// </summary>
/// <param name="input">The right hand side vector, <b>b</b>.</param>
/// <returns>The left hand side <see cref="DenseVector"/>, <b>x</b>.</returns>
public override Vector Solve(Vector input)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
var x = new DenseVector(input.Count);
Solve(input, x);
return x;
}
/// <summary>
/// Solves a system of linear equations, <b>Ax = b</b>, with A Cholesky factorized.
/// </summary>

179
src/Numerics/LinearAlgebra/Double/Factorization/DenseLU.cs

@ -0,0 +1,179 @@
// <copyright file="DenseLU.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
using System;
using Properties;
/// <summary>
/// <para>A class which encapsulates the functionality of an LU factorization.</para>
/// <para>For a matrix A, the LU factorization is a pair of lower triangular matrix L and
/// upper triangular matrix U so that A = L*U.</para>
/// </summary>
/// <remarks>
/// The computation of the LU factorization is done at construction time.
/// </remarks>
public class DenseLU : LU
{
/// <summary>
/// Initializes a new instance of the <see cref="DenseLU"/> class. This object will compute the
/// LU factorization when the constructor is called and cache it's factorization.
/// </summary>
/// <param name="matrix">The matrix to factor.</param>
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <b>null</b>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not a square matrix.</exception>
public DenseLU(DenseMatrix matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount != matrix.ColumnCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSquare);
}
// Create an array for the pivot indices.
mPivots = new int[matrix.RowCount];
// Create a new matrix for the LU factors, then perform factorization (while overwriting).
var factors = (DenseMatrix)matrix.Clone();
Control.LinearAlgebraProvider.LUFactor(factors.Data, factors.RowCount, mPivots);
mFactors = factors;
}
/// <summary>
/// Solves a system of linear equations, <b>AX = B</b>, with A LU factorized.
/// </summary>
/// <param name="input">The right hand side <see cref="Matrix"/>, <b>B</b>.</param>
/// <param name="result">The left hand side <see cref="Matrix"/>, <b>X</b>.</param>
public override void Solve(Matrix input, Matrix result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (result.RowCount != input.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
}
if (result.ColumnCount != input.ColumnCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
}
if (input.RowCount != mFactors.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
var dinput = input as DenseMatrix;
if (dinput == null)
{
throw new NotImplementedException("Can only do LU factorization for dense matrices at the moment.");
}
var dresult = result as DenseMatrix;
if (dresult == null)
{
throw new NotImplementedException("Can only do LU factorization for dense matrices at the moment.");
}
// Copy the contents of input to result.
Buffer.BlockCopy(dinput.Data, 0, dresult.Data, 0, dinput.Data.Length * Constants.SizeOfDouble);
// LU solve by overwriting result.
var dfactors = mFactors as DenseMatrix;
throw new NotImplementedException();
//Control.LinearAlgebraProvider.LUSolveFactored(dfactors.Data, dfactors.RowCount, dresult.Data, dresult.RowCount, dresult.ColumnCount);
}
/// <summary>
/// Solves a system of linear equations, <b>Ax = b</b>, with A LU factorized.
/// </summary>
/// <param name="input">The right hand side vector, <b>b</b>.</param>
/// <param name="result">The left hand side <see cref="Matrix"/>, <b>x</b>.</param>
public override void Solve(Vector input, Vector result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (input.Count != result.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
}
if (input.Count != mFactors.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions);
}
var dinput = input as DenseVector;
if (dinput == null)
{
throw new NotImplementedException("Can only do LU factorization for dense vectors at the moment.");
}
var dresult = result as DenseVector;
if (dresult == null)
{
throw new NotImplementedException("Can only do LU factorization for dense vectors at the moment.");
}
// Copy the contents of input to result.
Buffer.BlockCopy(dinput.Data, 0, dresult.Data, 0, dinput.Data.Length * Constants.SizeOfDouble);
// LU solve by overwriting result.
var dfactors = mFactors as DenseMatrix;
throw new NotImplementedException();
//Control.LinearAlgebraProvider.LUSolveFactored(dfactors.Data, dfactors.RowCount, dresult.Data, dresult.Count, 1);
}
}
}

171
src/Numerics/LinearAlgebra/Double/Factorization/LU.cs

@ -0,0 +1,171 @@
// <copyright file="LU.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
using System;
using Properties;
/// <summary>
/// <para>A class which encapsulates the functionality of an LU factorization.</para>
/// <para>For a matrix A, the LU factorization is a pair of lower triangular matrix L and
/// upper triangular matrix U so that A = L*U.</para>
/// <para>In the Math.Net implementation we also store a set of pivot elements for increased
/// numerical stability. The pivot elements encode a permutation matrix P such that P*A = L*U.</para>
/// </summary>
/// <remarks>
/// The computation of the LU factorization is done at construction time.
/// </remarks>
public abstract class LU
{
/// <summary>
/// Stores both the L and U factors in the same matrix..
/// </summary>
protected Matrix mFactors;
/// <summary>
/// Stores the pivot indices of the LU factorization.
/// </summary>
protected int[] mPivots;
/// <summary>
/// Internal method which routes the call to perform the LU factorization to the appropriate class.
/// </summary>
/// <param name="matrix">The matrix to factor.</param>
/// <returns>An LU factorization object.</returns>
internal static LU Create(Matrix matrix)
{
var dense = matrix as DenseMatrix;
if (dense != null)
{
return new DenseLU(dense);
}
throw new NotImplementedException();
}
/// <summary>
/// Returns the lower triangular factor.
/// </summary>
public virtual Matrix L
{
get
{
Matrix result = mFactors.GetLowerTriangle();
for (int i = 0; i < result.RowCount; i++)
{
result.At(i, i, 1);
}
return result;
}
}
/// <summary>
/// Returns the upper triangular factor.
/// </summary>
public virtual Matrix U
{
get { return mFactors.GetUpperTriangle(); }
}
/// <summary>
/// The determinant of the matrix for which the LU factorization was computed.
/// </summary>
public virtual double Determinant
{
get
{
double det = 1.0;
for (int j = 0; j < mFactors.RowCount; j++)
{
if (mPivots[j] != j)
{
det = -det * mFactors.At(j, j);
}
else
{
det *= mFactors.At(j, j);
}
}
return det;
}
}
/// <summary>
/// Solves a system of linear equations, <b>AX = B</b>, with A LU factorized.
/// </summary>
/// <param name="input">The right hand side <see cref="Matrix"/>, <b>B</b>.</param>
/// <returns>The left hand side <see cref="Matrix"/>, <b>X</b>.</returns>
public virtual Matrix Solve(Matrix input)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
var X = input.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(input, X);
return X;
}
/// <summary>
/// Solves a system of linear equations, <b>AX = B</b>, with A LU factorized.
/// </summary>
/// <param name="input">The right hand side <see cref="Matrix"/>, <b>B</b>.</param>
/// <param name="result">The left hand side <see cref="Matrix"/>, <b>X</b>.</param>
public abstract void Solve(Matrix input, Matrix result);
/// <summary>
/// Solves a system of linear equations, <b>Ax = b</b>, with A LU factorized.
/// </summary>
/// <param name="input">The right hand side vector, <b>b</b>.</param>
/// <returns>The left hand side <see cref="Vector"/>, <b>x</b>.</returns>
public virtual Vector Solve(Vector input)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
var x = input.CreateVector(input.Count);
Solve(input, x);
return x;
}
/// <summary>
/// Solves a system of linear equations, <b>Ax = b</b>, with A LU factorized.
/// </summary>
/// <param name="input">The right hand side vector, <b>b</b>.</param>
/// <param name="result">The left hand side <see cref="Matrix"/>, <b>x</b>.</param>
public abstract void Solve(Vector input, Vector result);
}
}

103
src/Numerics/LinearAlgebra/Double/Matrix.cs

@ -33,6 +33,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
using System;
using System.Text;
using Properties;
using MathNet.Numerics.Threading;
/// <summary>
/// Defines the base class for <c>Matrix</c> classes.
@ -456,6 +457,108 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
}
/// <summary>
/// Returns a new matrix containing the lower triangle of this matrix.
/// </summary>
/// <returns>The lower triangle of this matrix.</returns>
public virtual Matrix GetLowerTriangle()
{
Matrix ret = CreateMatrix(RowCount, ColumnCount);
CommonParallel.For(0, ColumnCount, j =>
{
for (int i = j; i < RowCount; i++)
{
ret.At(i, j, At(i, j));
}
});
return ret;
}
/// <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 virtual void GetLowerTriangle(Matrix result)
{
if (result == null)
{
throw new ArgumentNullException("result");
}
if (result.RowCount != RowCount || result.ColumnCount != ColumnCount)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions, "result");
}
CommonParallel.For(0, ColumnCount, j =>
{
for (int i = 0; i < RowCount; i++)
{
if (i >= j)
{
result.At(i, j, At(i, j));
}
else
{
result.At(i, j, 0);
}
}
});
}
/// <summary>
/// Returns a new matrix containing the upper triangle of this matrix.
/// </summary>
/// <returns>The upper triangle of this matrix.</returns>
public virtual Matrix GetUpperTriangle()
{
Matrix ret = CreateMatrix(RowCount, ColumnCount);
CommonParallel.For(0, ColumnCount, j =>
{
for (int i = 0; i <= j; i++)
{
ret.At(i, j, At(i, j));
}
});
return ret;
}
/// <summary>
/// Puts the upper 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 virtual void GetUpperTriangle(Matrix result)
{
if (result == null)
{
throw new ArgumentNullException("result");
}
if (result.RowCount != RowCount || result.ColumnCount != ColumnCount)
{
throw new ArgumentException(Resources.ArgumentMatrixDimensions, "result");
}
CommonParallel.For(0, ColumnCount, j =>
{
for (int i = 0; i < RowCount; i++)
{
if (i <= j)
{
result.At(i, j, At(i, j));
}
else
{
result.At(i, j, 0);
}
}
});
}
#region Implemented Interfaces
#if !SILVERLIGHT

2
src/Numerics/Numerics.csproj

@ -145,6 +145,8 @@
<Compile Include="Interpolation\Interpolate.cs" />
<Compile Include="Interpolation\SplineBoundaryCondition.cs" />
<Compile Include="LinearAlgebra\Double\Factorization\Cholesky.cs" />
<Compile Include="LinearAlgebra\Double\Factorization\DenseLU.cs" />
<Compile Include="LinearAlgebra\Double\Factorization\LU.cs" />
<Compile Include="LinearAlgebra\Double\Factorization\ExtensionMethods.cs" />
<Compile Include="LinearAlgebra\Double\Factorization\DenseCholesky.cs" />
<Compile Include="LinearAlgebra\Double\Matrix.Arithmetic.cs" />

Loading…
Cancel
Save