Browse Source

More value tuples

pull/769/head
Christoph Ruegg 5 years ago
parent
commit
834a2d6425
  1. 3
      .paket/Paket.Restore.targets
  2. 8
      src/Data.Text/MatrixMarketReader.cs
  3. 8
      src/FSharp/LinearAlgebra.Matrix.fs
  4. 4
      src/FSharp/LinearAlgebra.Vector.fs
  5. 10
      src/Numerics.Tests/GenerateTests.cs
  6. 41
      src/Numerics/Generate.cs
  7. 44
      src/Numerics/LinearAlgebra/Builder.cs
  8. 11
      src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs
  9. 11
      src/Numerics/LinearAlgebra/Complex/DenseVector.cs
  10. 11
      src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs
  11. 11
      src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs
  12. 11
      src/Numerics/LinearAlgebra/Complex/SparseVector.cs
  13. 11
      src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs
  14. 11
      src/Numerics/LinearAlgebra/Complex32/DenseVector.cs
  15. 11
      src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs
  16. 11
      src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs
  17. 11
      src/Numerics/LinearAlgebra/Complex32/SparseVector.cs
  18. 24
      src/Numerics/LinearAlgebra/CreateMatrix.cs
  19. 24
      src/Numerics/LinearAlgebra/CreateVector.cs
  20. 11
      src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
  21. 11
      src/Numerics/LinearAlgebra/Double/DenseVector.cs
  22. 11
      src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs
  23. 11
      src/Numerics/LinearAlgebra/Double/SparseMatrix.cs
  24. 11
      src/Numerics/LinearAlgebra/Double/SparseVector.cs
  25. 20
      src/Numerics/LinearAlgebra/Matrix.cs
  26. 11
      src/Numerics/LinearAlgebra/Single/DenseMatrix.cs
  27. 11
      src/Numerics/LinearAlgebra/Single/DenseVector.cs
  28. 11
      src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs
  29. 11
      src/Numerics/LinearAlgebra/Single/SparseMatrix.cs
  30. 11
      src/Numerics/LinearAlgebra/Single/SparseVector.cs
  31. 28
      src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs
  32. 27
      src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs
  33. 29
      src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs
  34. 8
      src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs
  35. 58
      src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs
  36. 48
      src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs
  37. 8
      src/Numerics/LinearAlgebra/Storage/VectorStorage.cs
  38. 4
      src/Numerics/LinearAlgebra/Vector.cs
  39. 51
      src/Numerics/LinearRegression/MultipleRegression.cs
  40. 16
      src/Numerics/LinearRegression/SimpleRegression.cs
  41. 34
      src/Numerics/LinearRegression/Util.cs
  42. 24
      src/Numerics/LinearRegression/WeightedRegression.cs
  43. 8
      src/Numerics/Optimization/LevenbergMarquardtMinimizer.cs
  44. 4
      src/Numerics/Optimization/NonlinearMinimizerBase.cs
  45. 8
      src/Numerics/Optimization/TrustRegion/TrustRegionMinimizerBase.cs

3
.paket/Paket.Restore.targets

@ -359,7 +359,8 @@
NuspecProperties="$(NuspecProperties)" NuspecProperties="$(NuspecProperties)"
PackageLicenseFile="$(PackageLicenseFile)" PackageLicenseFile="$(PackageLicenseFile)"
PackageLicenseExpression="$(PackageLicenseExpression)" PackageLicenseExpression="$(PackageLicenseExpression)"
PackageLicenseExpressionVersion="$(PackageLicenseExpressionVersion)" /> PackageLicenseExpressionVersion="$(PackageLicenseExpressionVersion)"
NoDefaultExcludes="$(NoDefaultExcludes)" />
<PackTask Condition="$(UseMSBuild15_9_Pack)" <PackTask Condition="$(UseMSBuild15_9_Pack)"
PackItem="$(PackProjectInputFile)" PackItem="$(PackProjectInputFile)"

8
src/Data.Text/MatrixMarketReader.cs

@ -133,7 +133,7 @@ namespace MathNet.Numerics.Data.Text
if (sparse) if (sparse)
{ {
var indexed = ReadTokenLines(reader).Select(tokens => new Tuple<int, int, T>(int.Parse(tokens[0]) - 1, int.Parse(tokens[1]) - 1, parse(2, tokens))); var indexed = ReadTokenLines(reader).Select(tokens => (int.Parse(tokens[0]) - 1, int.Parse(tokens[1]) - 1, parse(2, tokens)));
return Matrix<T>.Build.SparseOfIndexed(rows, cols, symmetry == MatrixMarketSymmetry.General ? indexed : ExpandSparse(symmetry, indexed)); return Matrix<T>.Build.SparseOfIndexed(rows, cols, symmetry == MatrixMarketSymmetry.General ? indexed : ExpandSparse(symmetry, indexed));
} }
@ -207,7 +207,7 @@ namespace MathNet.Numerics.Data.Text
if (sparse) if (sparse)
{ {
var indexedSeq = ReadTokenLines(reader).Select(tokens => new Tuple<int, T>(int.Parse(tokens[0]) - 1, parse(1, tokens))); var indexedSeq = ReadTokenLines(reader).Select(tokens => (int.Parse(tokens[0]) - 1, parse(1, tokens)));
return Vector<T>.Build.SparseOfIndexed(length, indexedSeq); return Vector<T>.Build.SparseOfIndexed(length, indexedSeq);
} }
@ -326,7 +326,7 @@ namespace MathNet.Numerics.Data.Text
} }
} }
static IEnumerable<Tuple<int, int, T>> ExpandSparse<T>(MatrixMarketSymmetry symmetry, IEnumerable<Tuple<int, int, T>> indexedValues) static IEnumerable<(int, int, T)> ExpandSparse<T>(MatrixMarketSymmetry symmetry, IEnumerable<(int, int, T)> indexedValues)
{ {
var map = CreateSymmetryMap<T>(symmetry); var map = CreateSymmetryMap<T>(symmetry);
foreach (var x in indexedValues) foreach (var x in indexedValues)
@ -334,7 +334,7 @@ namespace MathNet.Numerics.Data.Text
yield return x; yield return x;
if (x.Item1 != x.Item2) if (x.Item1 != x.Item2)
{ {
yield return new Tuple<int, int, T>(x.Item2, x.Item1, map(x.Item3)); yield return (x.Item2, x.Item1, map(x.Item3));
} }
} }
} }

8
src/FSharp/LinearAlgebra.Matrix.fs

@ -52,25 +52,25 @@ module Matrix =
let inline toSeq (m: #Matrix<_>) = m.Enumerate(Zeros.Include) let inline toSeq (m: #Matrix<_>) = m.Enumerate(Zeros.Include)
/// Transform a matrix into an indexed sequence. /// Transform a matrix into an indexed sequence.
let inline toSeqi (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.Include) let inline toSeqi (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.Include) |> Seq.map (fun t -> t.ToTuple())
/// Transform a matrix into a sequence where zero-values are skipped. Skipping zeros is efficient on sparse data. /// Transform a matrix into a sequence where zero-values are skipped. Skipping zeros is efficient on sparse data.
let inline toSeqSkipZeros (m: #Matrix<_>) = m.Enumerate(Zeros.AllowSkip) let inline toSeqSkipZeros (m: #Matrix<_>) = m.Enumerate(Zeros.AllowSkip)
/// Transform a matrix into an indexed sequence where zero-values are skipped. Skipping zeros is efficient on sparse data. /// Transform a matrix into an indexed sequence where zero-values are skipped. Skipping zeros is efficient on sparse data.
let inline toSeqiSkipZeros (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.AllowSkip) let inline toSeqiSkipZeros (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.AllowSkip) |> Seq.map (fun t -> t.ToTuple())
/// Transform a matrix into a column sequence. /// Transform a matrix into a column sequence.
let inline toColSeq (m: #Matrix<_>) = m.EnumerateColumns() let inline toColSeq (m: #Matrix<_>) = m.EnumerateColumns()
/// Transform a matrix into an indexed column sequence. /// Transform a matrix into an indexed column sequence.
let inline toColSeqi (m: #Matrix<_>) = m.EnumerateColumnsIndexed() let inline toColSeqi (m: #Matrix<_>) = m.EnumerateColumnsIndexed() |> Seq.map (fun t -> t.ToTuple())
/// Transform a matrix into a row sequence. /// Transform a matrix into a row sequence.
let inline toRowSeq (m: #Matrix<_>) = m.EnumerateRows() let inline toRowSeq (m: #Matrix<_>) = m.EnumerateRows()
/// Transform a matrix into an indexed row sequence. /// Transform a matrix into an indexed row sequence.
let inline toRowSeqi (m: #Matrix<_>) = m.EnumerateRowsIndexed() let inline toRowSeqi (m: #Matrix<_>) = m.EnumerateRowsIndexed() |> Seq.map (fun t -> t.ToTuple())
/// Applies a function to all elements of the matrix. /// Applies a function to all elements of the matrix.

4
src/FSharp/LinearAlgebra.Vector.fs

@ -49,13 +49,13 @@ module Vector =
let inline toSeq (v: #Vector<_>) = v.Enumerate(Zeros.Include) let inline toSeq (v: #Vector<_>) = v.Enumerate(Zeros.Include)
/// Transform a vector into an indexed sequence. /// Transform a vector into an indexed sequence.
let inline toSeqi (v: #Vector<_>) = v.EnumerateIndexed(Zeros.Include) let inline toSeqi (v: #Vector<_>) = v.EnumerateIndexed(Zeros.Include) |> Seq.map (fun t -> t.ToTuple())
/// Transform a vector into a sequence where zero-values are skipped. Skipping zeros is efficient on sparse data. /// Transform a vector into a sequence where zero-values are skipped. Skipping zeros is efficient on sparse data.
let inline toSeqSkipZeros (v: #Vector<_>) = v.Enumerate(Zeros.AllowSkip) let inline toSeqSkipZeros (v: #Vector<_>) = v.Enumerate(Zeros.AllowSkip)
/// Transform a vector into an indexed sequence where zero-values are skipped. Skipping zeros is efficient on sparse data. /// Transform a vector into an indexed sequence where zero-values are skipped. Skipping zeros is efficient on sparse data.
let inline toSeqiSkipZeros (v: #Vector<_>) = v.EnumerateIndexed(Zeros.AllowSkip) let inline toSeqiSkipZeros (v: #Vector<_>) = v.EnumerateIndexed(Zeros.AllowSkip) |> Seq.map (fun t -> t.ToTuple())
/// Applies a function to all elements of the vector. /// Applies a function to all elements of the vector.

10
src/Numerics.Tests/GenerateTests.cs

@ -222,8 +222,8 @@ namespace MathNet.Numerics.UnitTests
public void UnfoldConsistentWithSequence() public void UnfoldConsistentWithSequence()
{ {
Assert.That( Assert.That(
Generate.UnfoldSequence((s => new Tuple<int, int>(s + 1, s + 1)), 0).Take(250).ToArray(), Generate.UnfoldSequence((s => (s + 1, s + 1)), 0).Take(250).ToArray(),
Is.EqualTo(Generate.Unfold(250, (s => new Tuple<int, int>(s + 1, s + 1)), 0)).AsCollection); Is.EqualTo(Generate.Unfold(250, (s => (s + 1, s + 1)), 0)).AsCollection);
} }
[Test] [Test]
@ -239,11 +239,11 @@ namespace MathNet.Numerics.UnitTests
{ {
Assert.That( Assert.That(
Generate.FibonacciSequence().Take(250).ToArray(), Generate.FibonacciSequence().Take(250).ToArray(),
Is.EqualTo(new[] { BigInteger.Zero, BigInteger.One }.Concat(Generate.Unfold(248, (s => Is.EqualTo(new[] { BigInteger.Zero, BigInteger.One }.Concat(Generate.Unfold(248, s =>
{ {
var z = s.Item1 + s.Item2; var z = s.Item1 + s.Item2;
return new Tuple<BigInteger, Tuple<BigInteger, BigInteger>>(z, new Tuple<BigInteger, BigInteger>(s.Item2, z)); return (z, (s.Item2, z));
}), new Tuple<BigInteger, BigInteger>(BigInteger.Zero, BigInteger.One)))).AsCollection); }, (BigInteger.Zero, BigInteger.One)))).AsCollection);
} }
} }
} }

41
src/Numerics/Generate.cs

@ -774,9 +774,25 @@ namespace MathNet.Numerics
var data = new T[length]; var data = new T[length];
for (int i = 0; i < data.Length; i++) for (int i = 0; i < data.Length; i++)
{ {
Tuple<T, TState> next = f(state); (data[i], state) = f(state);
data[i] = next.Item1; }
state = next.Item2; return data;
}
/// <summary>
/// Generate samples generated by the given computation.
/// </summary>
public static T[] Unfold<T, TState>(int length, Func<TState, (T, TState)> f, TState state)
{
if (length < 0)
{
throw new ArgumentOutOfRangeException(nameof(length));
}
var data = new T[length];
for (int i = 0; i < data.Length; i++)
{
(data[i], state) = f(state);
} }
return data; return data;
} }
@ -788,9 +804,22 @@ namespace MathNet.Numerics
{ {
while (true) while (true)
{ {
Tuple<T, TState> next = f(state); var (item, nextState) = f(state);
state = next.Item2; state = nextState;
yield return next.Item1; yield return item;
}
}
/// <summary>
/// Generate an infinite sequence generated by the given computation.
/// </summary>
public static IEnumerable<T> UnfoldSequence<T, TState>(Func<TState, (T, TState)> f, TState state)
{
while (true)
{
var (item, nextState) = f(state);
state = nextState;
yield return item;
} }
} }

44
src/Numerics/LinearAlgebra/Builder.cs

@ -565,6 +565,17 @@ namespace MathNet.Numerics.LinearAlgebra
return Dense(DenseColumnMajorMatrixStorage<T>.OfIndexedEnumerable(rows, columns, enumerable)); return Dense(DenseColumnMajorMatrixStorage<T>.OfIndexedEnumerable(rows, columns, enumerable));
} }
/// <summary>
/// Create a new dense matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public Matrix<T> DenseOfIndexed(int rows, int columns, IEnumerable<(int, int, T)> enumerable)
{
return Dense(DenseColumnMajorMatrixStorage<T>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary> /// <summary>
/// Create a new dense matrix as a copy of the given enumerable. /// Create a new dense matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in column-major order (column by column). /// The enumerable is assumed to be in column-major order (column by column).
@ -911,6 +922,17 @@ namespace MathNet.Numerics.LinearAlgebra
return Sparse(SparseCompressedRowMatrixStorage<T>.OfIndexedEnumerable(rows, columns, enumerable)); return Sparse(SparseCompressedRowMatrixStorage<T>.OfIndexedEnumerable(rows, columns, enumerable));
} }
/// <summary>
/// Create a new sparse matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public Matrix<T> SparseOfIndexed(int rows, int columns, IEnumerable<(int, int, T)> enumerable)
{
return Sparse(SparseCompressedRowMatrixStorage<T>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary> /// <summary>
/// Create a new sparse matrix as a copy of the given enumerable. /// Create a new sparse matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in row-major order (row by row). /// The enumerable is assumed to be in row-major order (row by row).
@ -1537,6 +1559,17 @@ namespace MathNet.Numerics.LinearAlgebra
return Dense(DenseVectorStorage<T>.OfIndexedEnumerable(length, enumerable)); return Dense(DenseVectorStorage<T>.OfIndexedEnumerable(length, enumerable));
} }
/// <summary>
/// Create a new dense vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public Vector<T> DenseOfIndexed(int length, IEnumerable<(int, T)> enumerable)
{
return Dense(DenseVectorStorage<T>.OfIndexedEnumerable(length, enumerable));
}
/// <summary> /// <summary>
/// Create a new sparse vector straight from an initialized vector storage instance. /// Create a new sparse vector straight from an initialized vector storage instance.
/// The storage is used directly without copying. /// The storage is used directly without copying.
@ -1611,6 +1644,17 @@ namespace MathNet.Numerics.LinearAlgebra
{ {
return Sparse(SparseVectorStorage<T>.OfIndexedEnumerable(length, enumerable)); return Sparse(SparseVectorStorage<T>.OfIndexedEnumerable(length, enumerable));
} }
/// <summary>
/// Create a new sparse vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public Vector<T> SparseOfIndexed(int length, IEnumerable<(int, T)> enumerable)
{
return Sparse(SparseVectorStorage<T>.OfIndexedEnumerable(length, enumerable));
}
} }
internal static class BuilderInstance<T> where T : struct, IEquatable<T>, IFormattable internal static class BuilderInstance<T> where T : struct, IEquatable<T>, IFormattable

11
src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs

@ -145,6 +145,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return new DenseMatrix(DenseColumnMajorMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, enumerable)); return new DenseMatrix(DenseColumnMajorMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, enumerable));
} }
/// <summary>
/// Create a new dense matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DenseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, Complex)> enumerable)
{
return new DenseMatrix(DenseColumnMajorMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary> /// <summary>
/// Create a new dense matrix as a copy of the given enumerable. /// Create a new dense matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in column-major order (column by column). /// The enumerable is assumed to be in column-major order (column by column).

11
src/Numerics/LinearAlgebra/Complex/DenseVector.cs

@ -131,6 +131,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return new DenseVector(DenseVectorStorage<Complex>.OfIndexedEnumerable(length, enumerable)); return new DenseVector(DenseVectorStorage<Complex>.OfIndexedEnumerable(length, enumerable));
} }
/// <summary>
/// Create a new dense vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static DenseVector OfIndexedEnumerable(int length, IEnumerable<(int, Complex)> enumerable)
{
return new DenseVector(DenseVectorStorage<Complex>.OfIndexedEnumerable(length, enumerable));
}
/// <summary> /// <summary>
/// Create a new dense vector and initialize each value using the provided value. /// Create a new dense vector and initialize each value using the provided value.
/// </summary> /// </summary>

11
src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs

@ -148,6 +148,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return new DiagonalMatrix(DiagonalMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, diagonal)); return new DiagonalMatrix(DiagonalMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, diagonal));
} }
/// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DiagonalMatrix OfIndexedDiagonal(int rows, int columns, IEnumerable<(int, Complex)> diagonal)
{
return new DiagonalMatrix(DiagonalMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, diagonal));
}
/// <summary> /// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided enumerable. /// Create a new diagonal matrix and initialize each diagonal value from the provided enumerable.
/// This new matrix will be independent from the enumerable. /// This new matrix will be independent from the enumerable.

11
src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs

@ -118,6 +118,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return new SparseMatrix(SparseCompressedRowMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, enumerable)); return new SparseMatrix(SparseCompressedRowMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, enumerable));
} }
/// <summary>
/// Create a new sparse matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static SparseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, Complex)> enumerable)
{
return new SparseMatrix(SparseCompressedRowMatrixStorage<Complex>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary> /// <summary>
/// Create a new sparse matrix as a copy of the given enumerable. /// Create a new sparse matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in row-major order (row by row). /// The enumerable is assumed to be in row-major order (row by row).

11
src/Numerics/LinearAlgebra/Complex/SparseVector.cs

@ -107,6 +107,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return new SparseVector(SparseVectorStorage<Complex>.OfIndexedEnumerable(length, enumerable)); return new SparseVector(SparseVectorStorage<Complex>.OfIndexedEnumerable(length, enumerable));
} }
/// <summary>
/// Create a new sparse vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static SparseVector OfIndexedEnumerable(int length, IEnumerable<(int, Complex)> enumerable)
{
return new SparseVector(SparseVectorStorage<Complex>.OfIndexedEnumerable(length, enumerable));
}
/// <summary> /// <summary>
/// Create a new sparse vector and initialize each value using the provided value. /// Create a new sparse vector and initialize each value using the provided value.
/// </summary> /// </summary>

11
src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs

@ -145,6 +145,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return new DenseMatrix(DenseColumnMajorMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, enumerable)); return new DenseMatrix(DenseColumnMajorMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, enumerable));
} }
/// <summary>
/// Create a new dense matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DenseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, Complex32)> enumerable)
{
return new DenseMatrix(DenseColumnMajorMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary> /// <summary>
/// Create a new dense matrix as a copy of the given enumerable. /// Create a new dense matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in column-major order (column by column). /// The enumerable is assumed to be in column-major order (column by column).

11
src/Numerics/LinearAlgebra/Complex32/DenseVector.cs

@ -131,6 +131,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return new DenseVector(DenseVectorStorage<Complex32>.OfIndexedEnumerable(length, enumerable)); return new DenseVector(DenseVectorStorage<Complex32>.OfIndexedEnumerable(length, enumerable));
} }
/// <summary>
/// Create a new dense vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static DenseVector OfIndexedEnumerable(int length, IEnumerable<(int, Complex32)> enumerable)
{
return new DenseVector(DenseVectorStorage<Complex32>.OfIndexedEnumerable(length, enumerable));
}
/// <summary> /// <summary>
/// Create a new dense vector and initialize each value using the provided value. /// Create a new dense vector and initialize each value using the provided value.
/// </summary> /// </summary>

11
src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs

@ -148,6 +148,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return new DiagonalMatrix(DiagonalMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, diagonal)); return new DiagonalMatrix(DiagonalMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, diagonal));
} }
/// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DiagonalMatrix OfIndexedDiagonal(int rows, int columns, IEnumerable<(int, Complex32)> diagonal)
{
return new DiagonalMatrix(DiagonalMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, diagonal));
}
/// <summary> /// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided enumerable. /// Create a new diagonal matrix and initialize each diagonal value from the provided enumerable.
/// This new matrix will be independent from the enumerable. /// This new matrix will be independent from the enumerable.

11
src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs

@ -118,6 +118,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return new SparseMatrix(SparseCompressedRowMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, enumerable)); return new SparseMatrix(SparseCompressedRowMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, enumerable));
} }
/// <summary>
/// Create a new sparse matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static SparseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, Complex32)> enumerable)
{
return new SparseMatrix(SparseCompressedRowMatrixStorage<Complex32>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary> /// <summary>
/// Create a new sparse matrix as a copy of the given enumerable. /// Create a new sparse matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in row-major order (row by row). /// The enumerable is assumed to be in row-major order (row by row).

11
src/Numerics/LinearAlgebra/Complex32/SparseVector.cs

@ -107,6 +107,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return new SparseVector(SparseVectorStorage<Complex32>.OfIndexedEnumerable(length, enumerable)); return new SparseVector(SparseVectorStorage<Complex32>.OfIndexedEnumerable(length, enumerable));
} }
/// <summary>
/// Create a new sparse vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static SparseVector OfIndexedEnumerable(int length, IEnumerable<(int, Complex32)> enumerable)
{
return new SparseVector(SparseVectorStorage<Complex32>.OfIndexedEnumerable(length, enumerable));
}
/// <summary> /// <summary>
/// Create a new sparse vector and initialize each value using the provided value. /// Create a new sparse vector and initialize each value using the provided value.
/// </summary> /// </summary>

24
src/Numerics/LinearAlgebra/CreateMatrix.cs

@ -281,6 +281,18 @@ namespace MathNet.Numerics.LinearAlgebra
return Matrix<T>.Build.DenseOfIndexed(rows, columns, enumerable); return Matrix<T>.Build.DenseOfIndexed(rows, columns, enumerable);
} }
/// <summary>
/// Create a new dense matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static Matrix<T> DenseOfIndexed<T>(int rows, int columns, IEnumerable<(int, int, T)> enumerable)
where T : struct, IEquatable<T>, IFormattable
{
return Matrix<T>.Build.DenseOfIndexed(rows, columns, enumerable);
}
/// <summary> /// <summary>
/// Create a new dense matrix as a copy of the given enumerable. /// Create a new dense matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in column-major order (column by column). /// The enumerable is assumed to be in column-major order (column by column).
@ -605,6 +617,18 @@ namespace MathNet.Numerics.LinearAlgebra
return Matrix<T>.Build.SparseOfIndexed(rows, columns, enumerable); return Matrix<T>.Build.SparseOfIndexed(rows, columns, enumerable);
} }
/// <summary>
/// Create a new sparse matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static Matrix<T> SparseOfIndexed<T>(int rows, int columns, IEnumerable<(int, int, T)> enumerable)
where T : struct, IEquatable<T>, IFormattable
{
return Matrix<T>.Build.SparseOfIndexed(rows, columns, enumerable);
}
/// <summary> /// <summary>
/// Create a new sparse matrix as a copy of the given enumerable. /// Create a new sparse matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in row-major order (row by row). /// The enumerable is assumed to be in row-major order (row by row).

24
src/Numerics/LinearAlgebra/CreateVector.cs

@ -224,6 +224,18 @@ namespace MathNet.Numerics.LinearAlgebra
return Vector<T>.Build.DenseOfIndexed(length, enumerable); return Vector<T>.Build.DenseOfIndexed(length, enumerable);
} }
/// <summary>
/// Create a new dense vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static Vector<T> DenseOfIndexed<T>(int length, IEnumerable<(int, T)> enumerable)
where T : struct, IEquatable<T>, IFormattable
{
return Vector<T>.Build.DenseOfIndexed(length, enumerable);
}
/// <summary> /// <summary>
/// Create a new sparse vector straight from an initialized vector storage instance. /// Create a new sparse vector straight from an initialized vector storage instance.
/// The storage is used directly without copying. /// The storage is used directly without copying.
@ -308,5 +320,17 @@ namespace MathNet.Numerics.LinearAlgebra
{ {
return Vector<T>.Build.SparseOfIndexed(length, enumerable); return Vector<T>.Build.SparseOfIndexed(length, enumerable);
} }
/// <summary>
/// Create a new sparse vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static Vector<T> SparseOfIndexed<T>(int length, IEnumerable<(int, T)> enumerable)
where T : struct, IEquatable<T>, IFormattable
{
return Vector<T>.Build.SparseOfIndexed(length, enumerable);
}
} }
} }

11
src/Numerics/LinearAlgebra/Double/DenseMatrix.cs

@ -143,6 +143,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return new DenseMatrix(DenseColumnMajorMatrixStorage<double>.OfIndexedEnumerable(rows, columns, enumerable)); return new DenseMatrix(DenseColumnMajorMatrixStorage<double>.OfIndexedEnumerable(rows, columns, enumerable));
} }
/// <summary>
/// Create a new dense matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DenseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, double)> enumerable)
{
return new DenseMatrix(DenseColumnMajorMatrixStorage<double>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary> /// <summary>
/// Create a new dense matrix as a copy of the given enumerable. /// Create a new dense matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in column-major order (column by column). /// The enumerable is assumed to be in column-major order (column by column).

11
src/Numerics/LinearAlgebra/Double/DenseVector.cs

@ -130,6 +130,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return new DenseVector(DenseVectorStorage<double>.OfIndexedEnumerable(length, enumerable)); return new DenseVector(DenseVectorStorage<double>.OfIndexedEnumerable(length, enumerable));
} }
/// <summary>
/// Create a new dense vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static DenseVector OfIndexedEnumerable(int length, IEnumerable<(int,double)> enumerable)
{
return new DenseVector(DenseVectorStorage<double>.OfIndexedEnumerable(length, enumerable));
}
/// <summary> /// <summary>
/// Create a new dense vector and initialize each value using the provided value. /// Create a new dense vector and initialize each value using the provided value.
/// </summary> /// </summary>

11
src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs

@ -146,6 +146,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return new DiagonalMatrix(DiagonalMatrixStorage<double>.OfIndexedEnumerable(rows, columns, diagonal)); return new DiagonalMatrix(DiagonalMatrixStorage<double>.OfIndexedEnumerable(rows, columns, diagonal));
} }
/// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DiagonalMatrix OfIndexedDiagonal(int rows, int columns, IEnumerable<(int, double)> diagonal)
{
return new DiagonalMatrix(DiagonalMatrixStorage<double>.OfIndexedEnumerable(rows, columns, diagonal));
}
/// <summary> /// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided enumerable. /// Create a new diagonal matrix and initialize each diagonal value from the provided enumerable.
/// This new matrix will be independent from the enumerable. /// This new matrix will be independent from the enumerable.

11
src/Numerics/LinearAlgebra/Double/SparseMatrix.cs

@ -116,6 +116,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return new SparseMatrix(SparseCompressedRowMatrixStorage<double>.OfIndexedEnumerable(rows, columns, enumerable)); return new SparseMatrix(SparseCompressedRowMatrixStorage<double>.OfIndexedEnumerable(rows, columns, enumerable));
} }
/// <summary>
/// Create a new sparse matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static SparseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, double)> enumerable)
{
return new SparseMatrix(SparseCompressedRowMatrixStorage<double>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary> /// <summary>
/// Create a new sparse matrix as a copy of the given enumerable. /// Create a new sparse matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in row-major order (row by row). /// The enumerable is assumed to be in row-major order (row by row).

11
src/Numerics/LinearAlgebra/Double/SparseVector.cs

@ -107,6 +107,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return new SparseVector(SparseVectorStorage<double>.OfIndexedEnumerable(length, enumerable)); return new SparseVector(SparseVectorStorage<double>.OfIndexedEnumerable(length, enumerable));
} }
/// <summary>
/// Create a new sparse vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static SparseVector OfIndexedEnumerable(int length, IEnumerable<(int, double)> enumerable)
{
return new SparseVector(SparseVectorStorage<double>.OfIndexedEnumerable(length, enumerable));
}
/// <summary> /// <summary>
/// Create a new sparse vector and initialize each value using the provided value. /// Create a new sparse vector and initialize each value using the provided value.
/// </summary> /// </summary>

20
src/Numerics/LinearAlgebra/Matrix.cs

@ -1471,7 +1471,7 @@ namespace MathNet.Numerics.LinearAlgebra
/// and the third value being the value of the element at that index. /// and the third value being the value of the element at that index.
/// The enumerator will include all values, even if they are zero. /// The enumerator will include all values, even if they are zero.
/// </remarks> /// </remarks>
public IEnumerable<Tuple<int, int, T>> EnumerateIndexed() public IEnumerable<(int, int, T)> EnumerateIndexed()
{ {
return Storage.EnumerateIndexed(); return Storage.EnumerateIndexed();
} }
@ -1484,7 +1484,7 @@ namespace MathNet.Numerics.LinearAlgebra
/// and the third value being the value of the element at that index. /// and the third value being the value of the element at that index.
/// The enumerator will include all values, even if they are zero. /// The enumerator will include all values, even if they are zero.
/// </remarks> /// </remarks>
public IEnumerable<Tuple<int, int, T>> EnumerateIndexed(Zeros zeros = Zeros.Include) public IEnumerable<(int, int, T)> EnumerateIndexed(Zeros zeros = Zeros.Include)
{ {
switch (zeros) switch (zeros)
{ {
@ -1527,11 +1527,11 @@ namespace MathNet.Numerics.LinearAlgebra
/// The enumerator returns a Tuple with the first value being the column index /// The enumerator returns a Tuple with the first value being the column index
/// and the second value being the value of the column at that index. /// and the second value being the value of the column at that index.
/// </remarks> /// </remarks>
public IEnumerable<Tuple<int, Vector<T>>> EnumerateColumnsIndexed() public IEnumerable<(int, Vector<T>)> EnumerateColumnsIndexed()
{ {
for (var i = 0; i < ColumnCount; i++) for (var i = 0; i < ColumnCount; i++)
{ {
yield return new Tuple<int, Vector<T>>(i, Column(i)); yield return (i, Column(i));
} }
} }
@ -1544,12 +1544,12 @@ namespace MathNet.Numerics.LinearAlgebra
/// The enumerator returns a Tuple with the first value being the column index /// The enumerator returns a Tuple with the first value being the column index
/// and the second value being the value of the column at that index. /// and the second value being the value of the column at that index.
/// </remarks> /// </remarks>
public IEnumerable<Tuple<int, Vector<T>>> EnumerateColumnsIndexed(int index, int length) public IEnumerable<(int, Vector<T>)> EnumerateColumnsIndexed(int index, int length)
{ {
var maxIndex = Math.Min(index + length, ColumnCount); var maxIndex = Math.Min(index + length, ColumnCount);
for (var i = Math.Max(index, 0); i < maxIndex; i++) for (var i = Math.Max(index, 0); i < maxIndex; i++)
{ {
yield return new Tuple<int, Vector<T>>(i, Column(i)); yield return (i, Column(i));
} }
} }
@ -1585,11 +1585,11 @@ namespace MathNet.Numerics.LinearAlgebra
/// The enumerator returns a Tuple with the first value being the row index /// The enumerator returns a Tuple with the first value being the row index
/// and the second value being the value of the row at that index. /// and the second value being the value of the row at that index.
/// </remarks> /// </remarks>
public IEnumerable<Tuple<int, Vector<T>>> EnumerateRowsIndexed() public IEnumerable<(int, Vector<T>)> EnumerateRowsIndexed()
{ {
for (var i = 0; i < RowCount; i++) for (var i = 0; i < RowCount; i++)
{ {
yield return new Tuple<int, Vector<T>>(i, Row(i)); yield return (i, Row(i));
} }
} }
@ -1602,12 +1602,12 @@ namespace MathNet.Numerics.LinearAlgebra
/// The enumerator returns a Tuple with the first value being the row index /// The enumerator returns a Tuple with the first value being the row index
/// and the second value being the value of the row at that index. /// and the second value being the value of the row at that index.
/// </remarks> /// </remarks>
public IEnumerable<Tuple<int, Vector<T>>> EnumerateRowsIndexed(int index, int length) public IEnumerable<(int, Vector<T>)> EnumerateRowsIndexed(int index, int length)
{ {
var maxIndex = Math.Min(index + length, RowCount); var maxIndex = Math.Min(index + length, RowCount);
for (var i = Math.Max(index, 0); i < maxIndex; i++) for (var i = Math.Max(index, 0); i < maxIndex; i++)
{ {
yield return new Tuple<int, Vector<T>>(i, Row(i)); yield return (i, Row(i));
} }
} }

11
src/Numerics/LinearAlgebra/Single/DenseMatrix.cs

@ -143,6 +143,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return new DenseMatrix(DenseColumnMajorMatrixStorage<float>.OfIndexedEnumerable(rows, columns, enumerable)); return new DenseMatrix(DenseColumnMajorMatrixStorage<float>.OfIndexedEnumerable(rows, columns, enumerable));
} }
/// <summary>
/// Create a new dense matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DenseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, float)> enumerable)
{
return new DenseMatrix(DenseColumnMajorMatrixStorage<float>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary> /// <summary>
/// Create a new dense matrix as a copy of the given enumerable. /// Create a new dense matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in column-major order (column by column). /// The enumerable is assumed to be in column-major order (column by column).

11
src/Numerics/LinearAlgebra/Single/DenseVector.cs

@ -131,6 +131,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return new DenseVector(DenseVectorStorage<float>.OfIndexedEnumerable(length, enumerable)); return new DenseVector(DenseVectorStorage<float>.OfIndexedEnumerable(length, enumerable));
} }
/// <summary>
/// Create a new dense vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static DenseVector OfIndexedEnumerable(int length, IEnumerable<(int, float)> enumerable)
{
return new DenseVector(DenseVectorStorage<float>.OfIndexedEnumerable(length, enumerable));
}
/// <summary> /// <summary>
/// Create a new dense vector and initialize each value using the provided value. /// Create a new dense vector and initialize each value using the provided value.
/// </summary> /// </summary>

11
src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs

@ -146,6 +146,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return new DiagonalMatrix(DiagonalMatrixStorage<float>.OfIndexedEnumerable(rows, columns, diagonal)); return new DiagonalMatrix(DiagonalMatrixStorage<float>.OfIndexedEnumerable(rows, columns, diagonal));
} }
/// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static DiagonalMatrix OfIndexedDiagonal(int rows, int columns, IEnumerable<(int, float)> diagonal)
{
return new DiagonalMatrix(DiagonalMatrixStorage<float>.OfIndexedEnumerable(rows, columns, diagonal));
}
/// <summary> /// <summary>
/// Create a new diagonal matrix and initialize each diagonal value from the provided enumerable. /// Create a new diagonal matrix and initialize each diagonal value from the provided enumerable.
/// This new matrix will be independent from the enumerable. /// This new matrix will be independent from the enumerable.

11
src/Numerics/LinearAlgebra/Single/SparseMatrix.cs

@ -117,6 +117,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return new SparseMatrix(SparseCompressedRowMatrixStorage<float>.OfIndexedEnumerable(rows, columns, enumerable)); return new SparseMatrix(SparseCompressedRowMatrixStorage<float>.OfIndexedEnumerable(rows, columns, enumerable));
} }
/// <summary>
/// Create a new sparse matrix as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new matrix will be independent from the enumerable.
/// A new memory block will be allocated for storing the matrix.
/// </summary>
public static SparseMatrix OfIndexed(int rows, int columns, IEnumerable<(int, int, float)> enumerable)
{
return new SparseMatrix(SparseCompressedRowMatrixStorage<float>.OfIndexedEnumerable(rows, columns, enumerable));
}
/// <summary> /// <summary>
/// Create a new sparse matrix as a copy of the given enumerable. /// Create a new sparse matrix as a copy of the given enumerable.
/// The enumerable is assumed to be in row-major order (row by row). /// The enumerable is assumed to be in row-major order (row by row).

11
src/Numerics/LinearAlgebra/Single/SparseVector.cs

@ -107,6 +107,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return new SparseVector(SparseVectorStorage<float>.OfIndexedEnumerable(length, enumerable)); return new SparseVector(SparseVectorStorage<float>.OfIndexedEnumerable(length, enumerable));
} }
/// <summary>
/// Create a new sparse vector as a copy of the given indexed enumerable.
/// Keys must be provided at most once, zero is assumed if a key is omitted.
/// This new vector will be independent from the enumerable.
/// A new memory block will be allocated for storing the vector.
/// </summary>
public static SparseVector OfIndexedEnumerable(int length, IEnumerable<(int, float)> enumerable)
{
return new SparseVector(SparseVectorStorage<float>.OfIndexedEnumerable(length, enumerable));
}
/// <summary> /// <summary>
/// Create a new sparse vector and initialize each value using the provided value. /// Create a new sparse vector and initialize each value using the provided value.
/// </summary> /// </summary>

28
src/Numerics/LinearAlgebra/Storage/DenseColumnMajorMatrixStorage.cs

@ -329,9 +329,19 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
public static DenseColumnMajorMatrixStorage<T> OfIndexedEnumerable(int rows, int columns, IEnumerable<Tuple<int, int, T>> data) public static DenseColumnMajorMatrixStorage<T> OfIndexedEnumerable(int rows, int columns, IEnumerable<Tuple<int, int, T>> data)
{ {
var array = new T[rows*columns]; var array = new T[rows*columns];
foreach (var item in data) foreach (var (i,j,x) in data)
{ {
array[(item.Item2*rows) + item.Item1] = item.Item3; array[j * rows + i] = x;
}
return new DenseColumnMajorMatrixStorage<T>(rows, columns, array);
}
public static DenseColumnMajorMatrixStorage<T> OfIndexedEnumerable(int rows, int columns, IEnumerable<(int, int, T)> data)
{
var array = new T[rows*columns];
foreach (var (i,j,x) in data)
{
array[j * rows + i] = x;
} }
return new DenseColumnMajorMatrixStorage<T>(rows, columns, array); return new DenseColumnMajorMatrixStorage<T>(rows, columns, array);
} }
@ -669,14 +679,14 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return Data; return Data;
} }
public override IEnumerable<Tuple<int, int, T>> EnumerateIndexed() public override IEnumerable<(int, int, T)> EnumerateIndexed()
{ {
int index = 0; int index = 0;
for (int j = 0; j < ColumnCount; j++) for (int j = 0; j < ColumnCount; j++)
{ {
for (int i = 0; i < RowCount; i++) for (int i = 0; i < RowCount; i++)
{ {
yield return new Tuple<int, int, T>(i, j, Data[index]); yield return (i, j, Data[index]);
index++; index++;
} }
} }
@ -687,7 +697,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return Data.Where(x => !Zero.Equals(x)); return Data.Where(x => !Zero.Equals(x));
} }
public override IEnumerable<Tuple<int, int, T>> EnumerateNonZeroIndexed() public override IEnumerable<(int, int, T)> EnumerateNonZeroIndexed()
{ {
int index = 0; int index = 0;
for (int j = 0; j < ColumnCount; j++) for (int j = 0; j < ColumnCount; j++)
@ -697,7 +707,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
var x = Data[index]; var x = Data[index];
if (!Zero.Equals(x)) if (!Zero.Equals(x))
{ {
yield return new Tuple<int, int, T>(i, j, x); yield return (i, j, x);
} }
index++; index++;
} }
@ -712,8 +722,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
{ {
if (predicate(Data[i])) if (predicate(Data[i]))
{ {
int row, column; RowColumnAtIndex(i, out int row, out int column);
RowColumnAtIndex(i, out row, out column);
return new Tuple<int, int, T>(row, column, Data[i]); return new Tuple<int, int, T>(row, column, Data[i]);
} }
} }
@ -729,8 +738,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
{ {
if (predicate(Data[i], otherData[i])) if (predicate(Data[i], otherData[i]))
{ {
int row, column; RowColumnAtIndex(i, out int row, out int column);
RowColumnAtIndex(i, out row, out column);
return new Tuple<int, int, T, TOther>(row, column, Data[i], otherData[i]); return new Tuple<int, int, T, TOther>(row, column, Data[i], otherData[i]);
} }

27
src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs

@ -171,9 +171,24 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
} }
var array = new T[length]; var array = new T[length];
foreach (var item in data) foreach (var (index, value) in data)
{ {
array[item.Item1] = item.Item2; array[index] = value;
}
return new DenseVectorStorage<T>(array.Length, array);
}
public static DenseVectorStorage<T> OfIndexedEnumerable(int length, IEnumerable<(int, T)> data)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
var array = new T[length];
foreach (var (index, value) in data)
{
array[index] = value;
} }
return new DenseVectorStorage<T>(array.Length, array); return new DenseVectorStorage<T>(array.Length, array);
} }
@ -338,9 +353,9 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return Data; return Data;
} }
public override IEnumerable<Tuple<int, T>> EnumerateIndexed() public override IEnumerable<(int, T)> EnumerateIndexed()
{ {
return Data.Select((t, i) => new Tuple<int, T>(i, t)); return Data.Select((t, i) => (i, t));
} }
public override IEnumerable<T> EnumerateNonZero() public override IEnumerable<T> EnumerateNonZero()
@ -348,13 +363,13 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return Data.Where(x => !Zero.Equals(x)); return Data.Where(x => !Zero.Equals(x));
} }
public override IEnumerable<Tuple<int, T>> EnumerateNonZeroIndexed() public override IEnumerable<(int, T)> EnumerateNonZeroIndexed()
{ {
for (var i = 0; i < Data.Length; i++) for (var i = 0; i < Data.Length; i++)
{ {
if (!Zero.Equals(Data[i])) if (!Zero.Equals(Data[i]))
{ {
yield return new Tuple<int, T>(i, Data[i]); yield return (i, Data[i]);
} }
} }
} }

29
src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs

@ -237,9 +237,24 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
} }
var storage = new DiagonalMatrixStorage<T>(rows, columns); var storage = new DiagonalMatrixStorage<T>(rows, columns);
foreach (var item in data) foreach (var (i,x) in data)
{ {
storage.Data[item.Item1] = item.Item2; storage.Data[i] = x;
}
return storage;
}
public static DiagonalMatrixStorage<T> OfIndexedEnumerable(int rows, int columns, IEnumerable<(int, T)> data)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
var storage = new DiagonalMatrixStorage<T>(rows, columns);
foreach (var (i,x) in data)
{
storage.Data[i] = x;
} }
return storage; return storage;
} }
@ -559,16 +574,14 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
} }
} }
public override IEnumerable<Tuple<int, int, T>> EnumerateIndexed() public override IEnumerable<(int, int, T)> EnumerateIndexed()
{ {
for (int j = 0; j < ColumnCount; j++) for (int j = 0; j < ColumnCount; j++)
{ {
for (int i = 0; i < RowCount; i++) for (int i = 0; i < RowCount; i++)
{ {
// PERF: consider to break up loop to avoid branching // PERF: consider to break up loop to avoid branching
yield return i == j yield return (i, j, i == j ? Data[i] : Zero);
? new Tuple<int, int, T>(i, i, Data[i])
: new Tuple<int, int, T>(i, j, Zero);
} }
} }
} }
@ -578,13 +591,13 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return Data.Where(x => !Zero.Equals(x)); return Data.Where(x => !Zero.Equals(x));
} }
public override IEnumerable<Tuple<int, int, T>> EnumerateNonZeroIndexed() public override IEnumerable<(int, int, T)> EnumerateNonZeroIndexed()
{ {
for (int i = 0; i < Data.Length; i++) for (int i = 0; i < Data.Length; i++)
{ {
if (!Zero.Equals(Data[i])) if (!Zero.Equals(Data[i]))
{ {
yield return new Tuple<int, int, T>(i, i, Data[i]); yield return (i, i, Data[i]);
} }
} }
} }

8
src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs

@ -623,13 +623,13 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
} }
} }
public virtual IEnumerable<Tuple<int, int, T>> EnumerateIndexed() public virtual IEnumerable<(int, int, T)> EnumerateIndexed()
{ {
for (int i = 0; i < RowCount; i++) for (int i = 0; i < RowCount; i++)
{ {
for (int j = 0; j < ColumnCount; j++) for (int j = 0; j < ColumnCount; j++)
{ {
yield return new Tuple<int, int, T>(i, j, At(i, j)); yield return (i, j, At(i, j));
} }
} }
} }
@ -649,7 +649,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
} }
} }
public virtual IEnumerable<Tuple<int, int, T>> EnumerateNonZeroIndexed() public virtual IEnumerable<(int, int, T)> EnumerateNonZeroIndexed()
{ {
for (int i = 0; i < RowCount; i++) for (int i = 0; i < RowCount; i++)
{ {
@ -658,7 +658,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
var x = At(i, j); var x = At(i, j);
if (!Zero.Equals(x)) if (!Zero.Equals(x))
{ {
yield return new Tuple<int, int, T>(i, j, x); yield return (i, j, x);
} }
} }
} }

58
src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs

@ -765,12 +765,52 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
public static SparseCompressedRowMatrixStorage<T> OfIndexedEnumerable(int rows, int columns, IEnumerable<Tuple<int, int, T>> data) public static SparseCompressedRowMatrixStorage<T> OfIndexedEnumerable(int rows, int columns, IEnumerable<Tuple<int, int, T>> data)
{ {
var trows = new List<Tuple<int, T>>[rows]; var trows = new List<Tuple<int, T>>[rows];
foreach (var item in data) foreach (var (i,j,x) in data)
{ {
if (!Zero.Equals(item.Item3)) if (!Zero.Equals(x))
{
var row = trows[i] ?? (trows[i] = new List<Tuple<int, T>>());
row.Add(new Tuple<int, T>(j, x));
}
}
var storage = new SparseCompressedRowMatrixStorage<T>(rows, columns);
var rowPointers = storage.RowPointers;
var columnIndices = new List<int>();
var values = new List<T>();
int index = 0;
for (int row = 0; row < rows; row++)
{
rowPointers[row] = index;
var trow = trows[row];
if (trow != null)
{
trow.Sort();
foreach (var item in trow)
{
values.Add(item.Item2);
columnIndices.Add(item.Item1);
index++;
}
}
}
rowPointers[rows] = values.Count;
storage.ColumnIndices = columnIndices.ToArray();
storage.Values = values.ToArray();
return storage;
}
public static SparseCompressedRowMatrixStorage<T> OfIndexedEnumerable(int rows, int columns, IEnumerable<(int, int, T)> data)
{
var trows = new List<Tuple<int, T>>[rows];
foreach (var (i,j,x) in data)
{
if (!Zero.Equals(x))
{ {
var row = trows[item.Item1] ?? (trows[item.Item1] = new List<Tuple<int, T>>()); var row = trows[i] ?? (trows[i] = new List<Tuple<int, T>>());
row.Add(new Tuple<int, T>(item.Item2, item.Item3)); row.Add(new Tuple<int, T>(j, x));
} }
} }
@ -1653,16 +1693,14 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
} }
} }
public override IEnumerable<Tuple<int, int, T>> EnumerateIndexed() public override IEnumerable<(int, int, T)> EnumerateIndexed()
{ {
int k = 0; int k = 0;
for (int row = 0; row < RowCount; row++) for (int row = 0; row < RowCount; row++)
{ {
for (int col = 0; col < ColumnCount; col++) for (int col = 0; col < ColumnCount; col++)
{ {
yield return k < RowPointers[row + 1] && ColumnIndices[k] == col yield return (row, col, k < RowPointers[row + 1] && ColumnIndices[k] == col ? Values[k++] : Zero);
? new Tuple<int, int, T>(row, col, Values[k++])
: new Tuple<int, int, T>(row, col, Zero);
} }
} }
} }
@ -1672,7 +1710,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return Values.Take(ValueCount).Where(x => !Zero.Equals(x)); return Values.Take(ValueCount).Where(x => !Zero.Equals(x));
} }
public override IEnumerable<Tuple<int, int, T>> EnumerateNonZeroIndexed() public override IEnumerable<(int, int, T)> EnumerateNonZeroIndexed()
{ {
for (int row = 0; row < RowCount; row++) for (int row = 0; row < RowCount; row++)
{ {
@ -1682,7 +1720,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
{ {
if (!Zero.Equals(Values[j])) if (!Zero.Equals(Values[j]))
{ {
yield return new Tuple<int, int, T>(row, ColumnIndices[j], Values[j]); yield return (row, ColumnIndices[j], Values[j]);
} }
} }
} }

48
src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs

@ -397,12 +397,42 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
var indices = new List<int>(); var indices = new List<int>();
var values = new List<T>(); var values = new List<T>();
foreach (var item in data) foreach (var (i, x) in data)
{ {
if (!Zero.Equals(item.Item2)) if (!Zero.Equals(x))
{ {
values.Add(item.Item2); values.Add(x);
indices.Add(item.Item1); indices.Add(i);
}
}
var indicesArray = indices.ToArray();
var valuesArray = values.ToArray();
Sorting.Sort(indicesArray, valuesArray);
return new SparseVectorStorage<T>(length)
{
Indices = indicesArray,
Values = valuesArray,
ValueCount = values.Count
};
}
public static SparseVectorStorage<T> OfIndexedEnumerable(int length, IEnumerable<(int, T)> data)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
var indices = new List<int>();
var values = new List<T>();
foreach (var (i, x) in data)
{
if (!Zero.Equals(x))
{
values.Add(x);
indices.Add(i);
} }
} }
@ -631,14 +661,12 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
} }
} }
public override IEnumerable<Tuple<int, T>> EnumerateIndexed() public override IEnumerable<(int, T)> EnumerateIndexed()
{ {
int k = 0; int k = 0;
for (int i = 0; i < Length; i++) for (int i = 0; i < Length; i++)
{ {
yield return k < ValueCount && Indices[k] == i yield return (i, k < ValueCount && Indices[k] == i ? Values[k++] : Zero);
? new Tuple<int, T>(i, Values[k++])
: new Tuple<int, T>(i, Zero);
} }
} }
@ -647,13 +675,13 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return Values.Take(ValueCount).Where(x => !Zero.Equals(x)); return Values.Take(ValueCount).Where(x => !Zero.Equals(x));
} }
public override IEnumerable<Tuple<int, T>> EnumerateNonZeroIndexed() public override IEnumerable<(int, T)> EnumerateNonZeroIndexed()
{ {
for (var i = 0; i < ValueCount; i++) for (var i = 0; i < ValueCount; i++)
{ {
if (!Zero.Equals(Values[i])) if (!Zero.Equals(Values[i]))
{ {
yield return new Tuple<int, T>(Indices[i], Values[i]); yield return (Indices[i], Values[i]);
} }
} }
} }

8
src/Numerics/LinearAlgebra/Storage/VectorStorage.cs

@ -400,11 +400,11 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
} }
} }
public virtual IEnumerable<Tuple<int, T>> EnumerateIndexed() public virtual IEnumerable<(int, T)> EnumerateIndexed()
{ {
for (var i = 0; i < Length; i++) for (var i = 0; i < Length; i++)
{ {
yield return new Tuple<int, T>(i, At(i)); yield return (i, At(i));
} }
} }
@ -420,14 +420,14 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
} }
} }
public virtual IEnumerable<Tuple<int, T>> EnumerateNonZeroIndexed() public virtual IEnumerable<(int, T)> EnumerateNonZeroIndexed()
{ {
for (var i = 0; i < Length; i++) for (var i = 0; i < Length; i++)
{ {
var x = At(i); var x = At(i);
if (!Zero.Equals(x)) if (!Zero.Equals(x))
{ {
yield return new Tuple<int, T>(i, x); yield return (i, x);
} }
} }
} }

4
src/Numerics/LinearAlgebra/Vector.cs

@ -323,7 +323,7 @@ namespace MathNet.Numerics.LinearAlgebra
/// and the second value being the value of the element at that index. /// and the second value being the value of the element at that index.
/// The enumerator will include all values, even if they are zero. /// The enumerator will include all values, even if they are zero.
/// </remarks> /// </remarks>
public IEnumerable<Tuple<int, T>> EnumerateIndexed() public IEnumerable<(int, T)> EnumerateIndexed()
{ {
return Storage.EnumerateIndexed(); return Storage.EnumerateIndexed();
} }
@ -336,7 +336,7 @@ namespace MathNet.Numerics.LinearAlgebra
/// and the second value being the value of the element at that index. /// and the second value being the value of the element at that index.
/// The enumerator will include all values, even if they are zero. /// The enumerator will include all values, even if they are zero.
/// </remarks> /// </remarks>
public IEnumerable<Tuple<int, T>> EnumerateIndexed(Zeros zeros = Zeros.Include) public IEnumerable<(int, T)> EnumerateIndexed(Zeros zeros = Zeros.Include)
{ {
switch (zeros) switch (zeros)
{ {

51
src/Numerics/LinearRegression/MultipleRegression.cs

@ -208,8 +208,21 @@ namespace MathNet.Numerics.LinearRegression
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns> /// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] NormalEquations<T>(IEnumerable<Tuple<T[], T>> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable public static T[] NormalEquations<T>(IEnumerable<Tuple<T[], T>> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{ {
var xy = samples.UnpackSinglePass(); var (u, v) = samples.UnpackSinglePass();
return NormalEquations(xy.Item1, xy.Item2, intercept); return NormalEquations(u, v, intercept);
}
/// <summary>
/// Find the model parameters β such that their linear combination with all predictor-arrays in X become as close to their response in Y as possible, with least squares residuals.
/// Uses the cholesky decomposition of the normal equations.
/// </summary>
/// <param name="samples">Sequence of predictor-arrays and their response.</param>
/// <param name="intercept">True if an intercept should be added as first artificial predictor value. Default = false.</param>
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] NormalEquations<T>(IEnumerable<(T[], T)> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var (u, v) = samples.UnpackSinglePass();
return NormalEquations(u, v, intercept);
} }
/// <summary> /// <summary>
@ -294,8 +307,21 @@ namespace MathNet.Numerics.LinearRegression
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns> /// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] QR<T>(IEnumerable<Tuple<T[], T>> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable public static T[] QR<T>(IEnumerable<Tuple<T[], T>> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{ {
var xy = samples.UnpackSinglePass(); var (u, v) = samples.UnpackSinglePass();
return QR(xy.Item1, xy.Item2, intercept); return QR(u, v, intercept);
}
/// <summary>
/// Find the model parameters β such that their linear combination with all predictor-arrays in X become as close to their response in Y as possible, with least squares residuals.
/// Uses an orthogonal decomposition and is therefore more numerically stable than the normal equations but also slower.
/// </summary>
/// <param name="samples">Sequence of predictor-arrays and their response.</param>
/// <param name="intercept">True if an intercept should be added as first artificial predictor value. Default = false.</param>
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] QR<T>(IEnumerable<(T[], T)> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var (u, v) = samples.UnpackSinglePass();
return QR(u, v, intercept);
} }
/// <summary> /// <summary>
@ -380,8 +406,21 @@ namespace MathNet.Numerics.LinearRegression
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns> /// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] Svd<T>(IEnumerable<Tuple<T[], T>> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable public static T[] Svd<T>(IEnumerable<Tuple<T[], T>> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{ {
var xy = samples.UnpackSinglePass(); var (u, v) = samples.UnpackSinglePass();
return Svd(xy.Item1, xy.Item2, intercept); return Svd(u, v, intercept);
}
/// <summary>
/// Find the model parameters β such that their linear combination with all predictor-arrays in X become as close to their response in Y as possible, with least squares residuals.
/// Uses a singular value decomposition and is therefore more numerically stable (especially if ill-conditioned) than the normal equations or QR but also slower.
/// </summary>
/// <param name="samples">Sequence of predictor-arrays and their response.</param>
/// <param name="intercept">True if an intercept should be added as first artificial predictor value. Default = false.</param>
/// <returns>Best fitting list of model parameters β for each element in the predictor-arrays.</returns>
public static T[] Svd<T>(IEnumerable<(T[], T)> samples, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var (u, v) = samples.UnpackSinglePass();
return Svd(u, v, intercept);
} }
} }
} }

16
src/Numerics/LinearRegression/SimpleRegression.cs

@ -87,8 +87,20 @@ namespace MathNet.Numerics.LinearRegression
/// <param name="samples">Predictor-Response samples as tuples</param> /// <param name="samples">Predictor-Response samples as tuples</param>
public static (double A, double B) Fit(IEnumerable<Tuple<double, double>> samples) public static (double A, double B) Fit(IEnumerable<Tuple<double, double>> samples)
{ {
var xy = samples.UnpackSinglePass(); var (u, v) = samples.UnpackSinglePass();
return Fit(xy.Item1, xy.Item2); return Fit(u, v);
}
/// <summary>
/// Least-Squares fitting the points (x,y) to a line y : x -> a+b*x,
/// returning its best fitting parameters as (a, b) tuple,
/// where a is the intercept and b the slope.
/// </summary>
/// <param name="samples">Predictor-Response samples as tuples</param>
public static (double A, double B) Fit(IEnumerable<(double, double)> samples)
{
var (u, v) = samples.UnpackSinglePass();
return Fit(u, v);
} }
/// <summary> /// <summary>

34
src/Numerics/LinearRegression/Util.cs

@ -2,9 +2,9 @@
// Math.NET Numerics, part of the Math.NET Project // Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com // http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// //
// Copyright (c) 2009-2013 Math.NET // Copyright (c) 2009-2013 Math.NET
// //
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without // files (the "Software"), to deal in the Software without
@ -13,10 +13,10 @@
// copies of the Software, and to permit persons to whom the // copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following // Software is furnished to do so, subject to the following
// conditions: // conditions:
// //
// The above copyright notice and this permission notice shall be // The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software. // included in all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -34,18 +34,32 @@ namespace MathNet.Numerics.LinearRegression
{ {
internal static class Util internal static class Util
{ {
public static Tuple<TU[], TV[]> UnpackSinglePass<TU, TV>(this IEnumerable<Tuple<TU, TV>> samples) public static (TU[] U, TV[] V) UnpackSinglePass<TU, TV>(this IEnumerable<Tuple<TU, TV>> samples)
{ {
var u = new List<TU>(); var ux = new List<TU>();
var v = new List<TV>(); var vx = new List<TV>();
foreach (var tuple in samples) foreach (var tuple in samples)
{ {
u.Add(tuple.Item1); ux.Add(tuple.Item1);
v.Add(tuple.Item2); vx.Add(tuple.Item2);
} }
return new Tuple<TU[], TV[]>(u.ToArray(), v.ToArray()); return (ux.ToArray(), vx.ToArray());
}
public static (TU[] U, TV[] V) UnpackSinglePass<TU, TV>(this IEnumerable<(TU, TV)> samples)
{
var ux = new List<TU>();
var vx = new List<TV>();
foreach (var (u, v) in samples)
{
ux.Add(u);
vx.Add(v);
}
return (ux.ToArray(), vx.ToArray());
} }
} }
} }

24
src/Numerics/LinearRegression/WeightedRegression.cs

@ -2,9 +2,9 @@
// Math.NET Numerics, part of the Math.NET Project // Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com // http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// //
// Copyright (c) 2009-2013 Math.NET // Copyright (c) 2009-2013 Math.NET
// //
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without // files (the "Software"), to deal in the Software without
@ -13,10 +13,10 @@
// copies of the Software, and to permit persons to whom the // copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following // Software is furnished to do so, subject to the following
// conditions: // conditions:
// //
// The above copyright notice and this permission notice shall be // The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software. // included in all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -85,8 +85,20 @@ namespace MathNet.Numerics.LinearRegression
/// <param name="intercept">True if an intercept should be added as first artificial predictor value. Default = false.</param> /// <param name="intercept">True if an intercept should be added as first artificial predictor value. Default = false.</param>
public static T[] Weighted<T>(IEnumerable<Tuple<T[], T>> samples, T[] weights, bool intercept = false) where T : struct, IEquatable<T>, IFormattable public static T[] Weighted<T>(IEnumerable<Tuple<T[], T>> samples, T[] weights, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{ {
var xy = samples.UnpackSinglePass(); var (u, v) = samples.UnpackSinglePass();
return Weighted(xy.Item1, xy.Item2, weights, intercept); return Weighted(u, v, weights, intercept);
}
/// <summary>
/// Weighted Linear Regression using normal equations.
/// </summary>
/// <param name="samples">List of sample vectors (predictor) together with their response.</param>
/// <param name="weights">List of weights, one for each sample.</param>
/// <param name="intercept">True if an intercept should be added as first artificial predictor value. Default = false.</param>
public static T[] Weighted<T>(IEnumerable<(T[], T)> samples, T[] weights, bool intercept = false) where T : struct, IEquatable<T>, IFormattable
{
var (u, v) = samples.UnpackSinglePass();
return Weighted(u, v, weights, intercept);
} }
/// <summary> /// <summary>

8
src/Numerics/Optimization/LevenbergMarquardtMinimizer.cs

@ -129,9 +129,7 @@ namespace MathNet.Numerics.Optimization
} }
// Evaluate gradient and Hessian // Evaluate gradient and Hessian
var jac = EvaluateJacobian(objective, P); var (Gradient, Hessian) = EvaluateJacobian(objective, P);
var Gradient = jac.Item1; // objective.Gradient;
var Hessian = jac.Item2; // objective.Hessian;
var diagonalOfHessian = Hessian.Diagonal(); // diag(H) var diagonalOfHessian = Hessian.Diagonal(); // diag(H)
// if ||g||oo <= gtol, found and stop // if ||g||oo <= gtol, found and stop
@ -190,9 +188,7 @@ namespace MathNet.Numerics.Optimization
RSS = RSSnew; RSS = RSSnew;
// update gradient and Hessian // update gradient and Hessian
jac = EvaluateJacobian(objective, P); (Gradient, Hessian) = EvaluateJacobian(objective, P);
Gradient = jac.Item1; // objective.Gradient;
Hessian = jac.Item2; // objective.Hessian;
diagonalOfHessian = Hessian.Diagonal(); diagonalOfHessian = Hessian.Diagonal();
// if ||g||_oo <= gtol, found and stop // if ||g||_oo <= gtol, found and stop

4
src/Numerics/Optimization/NonlinearMinimizerBase.cs

@ -100,7 +100,7 @@ namespace MathNet.Numerics.Optimization
return objective.Value; return objective.Value;
} }
protected Tuple<Vector<double>, Matrix<double>> EvaluateJacobian(IObjectiveModel objective, Vector<double> Pint) protected (Vector<double> Gradient, Matrix<double> Hessian) EvaluateJacobian(IObjectiveModel objective, Vector<double> Pint)
{ {
var gradient = objective.Gradient; var gradient = objective.Gradient;
var hessian = objective.Hessian; var hessian = objective.Hessian;
@ -123,7 +123,7 @@ namespace MathNet.Numerics.Optimization
} }
} }
return new Tuple<Vector<double>, Matrix<double>>(gradient, hessian); return (gradient, hessian);
} }
#region Projection of Parameters #region Projection of Parameters

8
src/Numerics/Optimization/TrustRegion/TrustRegionMinimizerBase.cs

@ -137,9 +137,7 @@ namespace MathNet.Numerics.Optimization.TrustRegion
} }
// evaluate projected gradient and Hessian // evaluate projected gradient and Hessian
var jac = EvaluateJacobian(objective, P); var (Gradient, Hessian) = EvaluateJacobian(objective, P);
var Gradient = jac.Item1; // objective.Gradient;
var Hessian = jac.Item2; // objective.Hessian;
// if ||g||_oo <= gtol, found and stop // if ||g||_oo <= gtol, found and stop
if (Gradient.InfinityNorm() <= gradientTolerance) if (Gradient.InfinityNorm() <= gradientTolerance)
@ -213,9 +211,7 @@ namespace MathNet.Numerics.Optimization.TrustRegion
RSS = RSSnew; RSS = RSSnew;
// evaluate projected gradient and Hessian // evaluate projected gradient and Hessian
jac = EvaluateJacobian(objective, P); (Gradient, Hessian) = EvaluateJacobian(objective, P);
Gradient = jac.Item1; // objective.Gradient;
Hessian = jac.Item2; // objective.Hessian;
// if ||g||_oo <= gtol, found and stop // if ||g||_oo <= gtol, found and stop
if (Gradient.InfinityNorm() <= gradientTolerance) if (Gradient.InfinityNorm() <= gradientTolerance)

Loading…
Cancel
Save