From 68b620ebee5aae05123e2ded90b84c0621196a5b Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Mon, 8 Apr 2013 14:59:29 +0200 Subject: [PATCH] LA: vectors of indexed enumerable --- src/FSharp/LinearAlgebra.Double.Vector.fs | 30 +++++++++----- src/FSharpUnitTests/DenseMatrixTests.fs | 2 +- src/FSharpUnitTests/DenseVectorTests.fs | 10 ++++- src/FSharpUnitTests/SparseMatrixTests.fs | 2 +- src/FSharpUnitTests/SparseVectorTests.fs | 8 ++-- .../LinearAlgebra/Complex/DenseVector.cs | 11 +++++ .../LinearAlgebra/Complex/SparseVector.cs | 11 +++++ .../LinearAlgebra/Complex32/DenseVector.cs | 11 +++++ .../LinearAlgebra/Complex32/SparseVector.cs | 11 +++++ .../LinearAlgebra/Double/DenseVector.cs | 11 +++++ .../LinearAlgebra/Double/SparseVector.cs | 11 +++++ .../LinearAlgebra/Single/DenseVector.cs | 11 +++++ .../LinearAlgebra/Single/SparseVector.cs | 11 +++++ .../Storage/DenseVectorStorage.cs | 15 +++++++ .../Storage/SparseVectorStorage.cs | 40 ++++++++++++++++--- 15 files changed, 172 insertions(+), 23 deletions(-) diff --git a/src/FSharp/LinearAlgebra.Double.Vector.fs b/src/FSharp/LinearAlgebra.Double.Vector.fs index 127743b7..211c709f 100644 --- a/src/FSharp/LinearAlgebra.Double.Vector.fs +++ b/src/FSharp/LinearAlgebra.Double.Vector.fs @@ -192,8 +192,14 @@ module DenseVector = /// Create a vector from a float list. let inline ofList (fl: float list) = DenseVector(Array.ofList fl) + /// Create a vector with a given dimension from an indexed list of index, value pairs. + let inline ofListi (dim: int) (fl: list) = DenseVector.OfIndexedEnumerable(dim, Seq.ofList fl) + /// Create a vector from a sequences. - let inline ofSeq (fs: #seq) = DenseVector(Array.ofSeq fs) + let inline ofSeq (fs: #seq) = DenseVector.OfEnumerable(fs) + + /// Create a vector with a given dimension from an indexed sequences of index, value pairs. + let inline ofSeqi (dim: int) (fs: #seq) = DenseVector.OfIndexedEnumerable(dim, fs) /// Create a vector with evenly spaced entries: e.g. rangef -1.0 0.5 1.0 = [-1.0 -0.5 0.0 0.5 1.0] let inline rangef (start: float) (step: float) (stop: float) = @@ -214,14 +220,16 @@ module SparseVector = /// Initialize a vector by calling a construction function for every element. let inline init (n: int) (f: int -> float) = SparseVector.Create(n, fun i -> f i) - /// Create a sparse vector with a given dimension from a list of entry, value pairs. - let inline ofList (dim: int) (fl: list) = - let v = new SparseVector(dim) - fl |> List.iter (fun (i, f) -> v.[i] <- f) - v + /// Create a sparse vector with a given dimension from a list of index, value pairs. + [] + let inline ofList (dim: int) (fl: list) = SparseVector.OfIndexedEnumerable(dim, Seq.ofList fl) - /// Create a sparse vector with a given dimension from a sequence of entry, value pairs. - let inline ofSeq (dim: int) (fs: #seq) = - let v = new SparseVector(dim) - fs |> Seq.iter (fun (i, f) -> v.[i] <- f) - v + /// Create a sparse vector with a given dimension from an indexed list of index, value pairs. + let inline ofListi (dim: int) (fl: list) = SparseVector.OfIndexedEnumerable(dim, Seq.ofList fl) + + /// Create a sparse vector with a given dimension from a sequence of index, value pairs. + [] + let inline ofSeq (dim: int) (fs: #seq) = SparseVector.OfIndexedEnumerable(dim, fs) + + /// Create a sparse vector with a given dimension from an indexed sequence of index, value pairs. + let inline ofSeqi (dim: int) (fs: #seq) = SparseVector.OfIndexedEnumerable(dim, fs) diff --git a/src/FSharpUnitTests/DenseMatrixTests.fs b/src/FSharpUnitTests/DenseMatrixTests.fs index 304e921b..7dbeef43 100644 --- a/src/FSharpUnitTests/DenseMatrixTests.fs +++ b/src/FSharpUnitTests/DenseMatrixTests.fs @@ -40,7 +40,7 @@ module DenseMatrixTests = [] let ``DenseMatrix.diag`` () = - DenseMatrix.diag (new DenseVector(100, 2.0)) |> should equal (2.0 * (DenseMatrix.Identity 100)) + DenseMatrix.diag (DenseVector.Create(100, fun i -> 2.0)) |> should equal (2.0 * (DenseMatrix.Identity 100)) [] let ``DenseMatrix.init_row`` () = diff --git a/src/FSharpUnitTests/DenseVectorTests.fs b/src/FSharpUnitTests/DenseVectorTests.fs index e179c0a8..8c8d0e7b 100644 --- a/src/FSharpUnitTests/DenseVectorTests.fs +++ b/src/FSharpUnitTests/DenseVectorTests.fs @@ -9,7 +9,7 @@ open MathNet.Numerics.LinearAlgebra.Double module DenseVectorTests = /// A small uniform vector. - let smallv = new DenseVector(5, 0.3 ) + let smallv = DenseVector.Create(5, fun i -> 0.3) /// A large vector with increasingly large entries let largev = new DenseVector( Array.init 100 (fun i -> float i / 100.0) ) @@ -22,10 +22,18 @@ module DenseVectorTests = let ``DenseVector.ofList`` () = DenseVector.ofList [ for i in 0 .. 99 -> float i / 100.0 ] |> should equal largev + [] + let ``DenseVector.ofListi`` () = + DenseVector.ofListi 100 [ for i in 0 .. 99 -> i, float i / 100.0 ] |> should equal largev + [] let ``DenseVector.ofSeq`` () = DenseVector.ofSeq (seq { for i in 0 .. 99 -> float i / 100.0 }) |> should equal largev + [] + let ``DenseVector.ofSeqi`` () = + DenseVector.ofSeqi 100 (seq { for i in 99 .. -1 .. 0 -> i, float i / 100.0 }) |> should equal largev + [] let ``DenseVector.rangef`` () = DenseVector.rangef 0.0 0.01 0.99 |> should equal (new DenseVector( [| for i in 0 .. 99 -> 0.01 * float i |] ) ) diff --git a/src/FSharpUnitTests/SparseMatrixTests.fs b/src/FSharpUnitTests/SparseMatrixTests.fs index 3650d35a..dbac81a3 100644 --- a/src/FSharpUnitTests/SparseMatrixTests.fs +++ b/src/FSharpUnitTests/SparseMatrixTests.fs @@ -25,4 +25,4 @@ module SparseMatrixTests = [] let ``SparseMatrix.diag`` () = - SparseMatrix.diag (new DenseVector(100, 2.0)) |> should equal (2.0 * (SparseMatrix.Identity 100)) + SparseMatrix.diag (DenseVector.Create(100, fun i -> 2.0)) |> should equal (2.0 * (SparseMatrix.Identity 100)) diff --git a/src/FSharpUnitTests/SparseVectorTests.fs b/src/FSharpUnitTests/SparseVectorTests.fs index d6753894..5e2470f8 100644 --- a/src/FSharpUnitTests/SparseVectorTests.fs +++ b/src/FSharpUnitTests/SparseVectorTests.fs @@ -12,10 +12,10 @@ module SparseVectorTests = let smallv = new DenseVector( [|0.0;0.3;0.0;0.0;0.0|] ) :> Vector [] - let ``SparseVector.ofList`` () = - (SparseVector.ofList 5 [ (1,0.3) ] :> Vector) |> should equal smallv + let ``SparseVector.ofListi`` () = + (SparseVector.ofListi 5 [ (1,0.3) ] :> Vector) |> should equal smallv [] - let ``SparseVector.ofSeq`` () = - (SparseVector.ofSeq 5 (List.toSeq [ (1,0.3) ]) :> Vector) |> should equal smallv + let ``SparseVector.ofSeqi`` () = + (SparseVector.ofSeqi 5 (List.toSeq [ (1,0.3) ]) :> Vector) |> should equal smallv diff --git a/src/Numerics/LinearAlgebra/Complex/DenseVector.cs b/src/Numerics/LinearAlgebra/Complex/DenseVector.cs index 5e379a5c..9c8e36f7 100644 --- a/src/Numerics/LinearAlgebra/Complex/DenseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex/DenseVector.cs @@ -111,6 +111,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex return new DenseVector(DenseVectorStorage.OfEnumerable(enumerable)); } + /// + /// 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. + /// + public static DenseVector OfIndexedEnumerable(int length, IEnumerable> enumerable) + { + return new DenseVector(DenseVectorStorage.OfIndexedEnumerable(length, enumerable)); + } + /// /// Create a new dense vector and initialize each value using the provided init function. /// diff --git a/src/Numerics/LinearAlgebra/Complex/SparseVector.cs b/src/Numerics/LinearAlgebra/Complex/SparseVector.cs index e281455a..aef6c753 100644 --- a/src/Numerics/LinearAlgebra/Complex/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex/SparseVector.cs @@ -101,6 +101,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex return new SparseVector(SparseVectorStorage.OfEnumerable(enumerable)); } + /// + /// 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. + /// + public static SparseVector OfIndexedEnumerable(int length, IEnumerable> enumerable) + { + return new SparseVector(SparseVectorStorage.OfIndexedEnumerable(length, enumerable)); + } + /// /// Create a new sparse vector and initialize each value using the provided init function. /// diff --git a/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs b/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs index e8e20f92..2a37daf0 100644 --- a/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex32/DenseVector.cs @@ -111,6 +111,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 return new DenseVector(DenseVectorStorage.OfEnumerable(enumerable)); } + /// + /// 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. + /// + public static DenseVector OfIndexedEnumerable(int length, IEnumerable> enumerable) + { + return new DenseVector(DenseVectorStorage.OfIndexedEnumerable(length, enumerable)); + } + /// /// Create a new dense vector and initialize each value using the provided init function. /// diff --git a/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs b/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs index 2423a792..7eca9e85 100644 --- a/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Complex32/SparseVector.cs @@ -101,6 +101,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 return new SparseVector(SparseVectorStorage.OfEnumerable(enumerable)); } + /// + /// 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. + /// + public static SparseVector OfIndexedEnumerable(int length, IEnumerable> enumerable) + { + return new SparseVector(SparseVectorStorage.OfIndexedEnumerable(length, enumerable)); + } + /// /// Create a new sparse vector and initialize each value using the provided init function. /// diff --git a/src/Numerics/LinearAlgebra/Double/DenseVector.cs b/src/Numerics/LinearAlgebra/Double/DenseVector.cs index bae631fa..bd75bf80 100644 --- a/src/Numerics/LinearAlgebra/Double/DenseVector.cs +++ b/src/Numerics/LinearAlgebra/Double/DenseVector.cs @@ -112,6 +112,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double return new DenseVector(DenseVectorStorage.OfEnumerable(enumerable)); } + /// + /// 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. + /// + public static DenseVector OfIndexedEnumerable(int length, IEnumerable> enumerable) + { + return new DenseVector(DenseVectorStorage.OfIndexedEnumerable(length, enumerable)); + } + /// /// Create a new dense vector and initialize each value using the provided init function. /// diff --git a/src/Numerics/LinearAlgebra/Double/SparseVector.cs b/src/Numerics/LinearAlgebra/Double/SparseVector.cs index 90f66900..0b75a004 100644 --- a/src/Numerics/LinearAlgebra/Double/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Double/SparseVector.cs @@ -101,6 +101,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double return new SparseVector(SparseVectorStorage.OfEnumerable(enumerable)); } + /// + /// 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. + /// + public static SparseVector OfIndexedEnumerable(int length, IEnumerable> enumerable) + { + return new SparseVector(SparseVectorStorage.OfIndexedEnumerable(length, enumerable)); + } + /// /// Create a new sparse vector and initialize each value using the provided init function. /// diff --git a/src/Numerics/LinearAlgebra/Single/DenseVector.cs b/src/Numerics/LinearAlgebra/Single/DenseVector.cs index 52585cca..abcbeabb 100644 --- a/src/Numerics/LinearAlgebra/Single/DenseVector.cs +++ b/src/Numerics/LinearAlgebra/Single/DenseVector.cs @@ -111,6 +111,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single return new DenseVector(DenseVectorStorage.OfEnumerable(enumerable)); } + /// + /// 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. + /// + public static DenseVector OfIndexedEnumerable(int length, IEnumerable> enumerable) + { + return new DenseVector(DenseVectorStorage.OfIndexedEnumerable(length, enumerable)); + } + /// /// Create a new dense vector and initialize each value using the provided init function. /// diff --git a/src/Numerics/LinearAlgebra/Single/SparseVector.cs b/src/Numerics/LinearAlgebra/Single/SparseVector.cs index 987f14b0..8415b269 100644 --- a/src/Numerics/LinearAlgebra/Single/SparseVector.cs +++ b/src/Numerics/LinearAlgebra/Single/SparseVector.cs @@ -101,6 +101,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single return new SparseVector(SparseVectorStorage.OfEnumerable(enumerable)); } + /// + /// 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. + /// + public static SparseVector OfIndexedEnumerable(int length, IEnumerable> enumerable) + { + return new SparseVector(SparseVectorStorage.OfIndexedEnumerable(length, enumerable)); + } + /// /// Create a new sparse vector and initialize each value using the provided init function. /// diff --git a/src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs b/src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs index fb4c1aab..a53b3312 100644 --- a/src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs @@ -133,6 +133,21 @@ namespace MathNet.Numerics.LinearAlgebra.Storage return new DenseVectorStorage(array.Length, array); } + public static DenseVectorStorage OfIndexedEnumerable(int length, IEnumerable> data) + { + if (data == null) + { + throw new ArgumentNullException("data"); + } + + var array = new T[length]; + foreach (var item in data) + { + array[item.Item1] = item.Item2; + } + return new DenseVectorStorage(array.Length, array); + } + // ENUMERATION public override IEnumerable Enumerate() diff --git a/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs b/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs index 04f95483..f93ff268 100644 --- a/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs @@ -306,7 +306,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage if (!Zero.Equals(item)) { values.Add(item); - indices.Add(length); + indices.Add(i); } } return new SparseVectorStorage(length) @@ -326,19 +326,19 @@ namespace MathNet.Numerics.LinearAlgebra.Storage var indices = new List(); var values = new List(); - int length = 0; + int index = 0; foreach (T item in data) { if (!Zero.Equals(item)) { values.Add(item); - indices.Add(length); + indices.Add(index); } - length++; + index++; } - return new SparseVectorStorage(length) + return new SparseVectorStorage(index) { Indices = indices.ToArray(), Values = values.ToArray(), @@ -346,6 +346,36 @@ namespace MathNet.Numerics.LinearAlgebra.Storage }; } + public static SparseVectorStorage OfIndexedEnumerable(int length, IEnumerable> data) + { + if (data == null) + { + throw new ArgumentNullException("data"); + } + + var indices = new List(); + var values = new List(); + foreach (var item in data) + { + if (!Zero.Equals(item.Item2)) + { + values.Add(item.Item2); + indices.Add(item.Item1); + } + } + + var indicesArray = indices.ToArray(); + var valuesArray = values.ToArray(); + Sorting.Sort(indicesArray, valuesArray); + + return new SparseVectorStorage(length) + { + Indices = indicesArray, + Values = valuesArray, + ValueCount = values.Count + }; + } + // ENUMERATION public override IEnumerable Enumerate()