From 01b3ed0c19a673cd686bf283bed0bcfa4ed36b91 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 13 Nov 2025 18:04:53 +0000 Subject: [PATCH 01/33] Added operator for performing `CrossProduct` --- .../LinearAlgebra/CrossProduct.cs | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs b/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs new file mode 100644 index 00000000..7627344f --- /dev/null +++ b/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs @@ -0,0 +1,34 @@ +using System; +using System.ComponentModel; +using System.Reactive.Linq; +using static TorchSharp.torch; +using static TorchSharp.torch.linalg; + +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Computes the cross product of 2 tensors. +/// +[Combinator] +[Description("Computes the cross product of 2 tensors.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class CrossProduct +{ + /// + /// The dimension to perform the operation. + /// + public long Dimension { get; set; } = -1; + + /// + /// Computes the cross product of 2 tensors. + /// + /// + /// + public IObservable Process(IObservable> source) + { + return source.Select(value => + { + return cross(value.Item1, value.Item2, Dimension); + }); + } +} \ No newline at end of file From 93adfcb9dac4fade0f144142445835d74718b830 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 13 Nov 2025 18:05:38 +0000 Subject: [PATCH 02/33] Added operator `LeastSquaresSolve` for solving systems of linear equations --- .../LinearAlgebra/LeastSquaresSolve.cs | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresSolve.cs diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresSolve.cs b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresSolve.cs new file mode 100644 index 00000000..d5560708 --- /dev/null +++ b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresSolve.cs @@ -0,0 +1,69 @@ +using System; +using System.ComponentModel; +using System.Reactive.Linq; +using static TorchSharp.torch; +using static TorchSharp.torch.linalg; + +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents an operator that computes the solution to the least squares and least norm problems for a full rank matrix A of size m×n and a matrix B of size m×k. +/// +[Combinator] +[Description("Computes the solution to the system tensordot(A, X) = B.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class LeastSquaresSolve +{ + /// + /// Computes the solution to the least squares and least norm problems for a full rank matrix A of size m×n and a matrix B of size m×k. + /// + /// + /// + public IObservable Process(IObservable> source) + { + return source.Select(value => + { + var (solution, residuals, rank, singularValues) = linalg.lstsq(value.Item1, value.Item2); + return new LeastSquaresResult( + solution, + residuals, + rank, + singularValues); + }); + } + + /// + /// Represents the result of solving of linear equations using the least squares method. + /// + /// + /// + /// + /// + public readonly struct LeastSquaresResult( + Tensor solution, + Tensor residuals, + Tensor rank, + Tensor singularValues + ) + { + /// + /// The solution to the system of equations. + /// + public Tensor Solution => solution; + + /// + /// The residual error. + /// + public Tensor Residuals => residuals; + + /// + /// The effective rank of the solution. + /// + public Tensor Rank => rank; + + /// + /// The singular values of the solution. + /// + public Tensor SingularValues => singularValues; + } +} \ No newline at end of file From a37c8c49f03c21d14ffab7aa311379ea6dfd73a8 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 13 Nov 2025 18:06:24 +0000 Subject: [PATCH 03/33] Added operator `TensorSolve` to compute a tensor solution to the problem AX=B --- .../LinearAlgebra/TensorSolve.cs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs b/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs new file mode 100644 index 00000000..1f1be9a5 --- /dev/null +++ b/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs @@ -0,0 +1,35 @@ +using System; +using System.ComponentModel; +using System.Reactive.Linq; +using static TorchSharp.torch; +using static TorchSharp.torch.linalg; + +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents an operator that computes the solution X to the system tensordot(A, X) = B. +/// +[Combinator] +[Description("Computes the solution to the system tensordot(A, X) = B.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class TensorSolve +{ + /// + /// The dimension to perform the operation. + /// + [TypeConverter(typeof(UnidimensionalArrayConverter))] + public long[] Dimensions { get; set; } = []; + + /// + /// Computes the cross product of 2 tensors. + /// + /// + /// + public IObservable Process(IObservable> source) + { + return source.Select(value => + { + return tensorsolve(value.Item1, value.Item2, Dimensions); + }); + } +} \ No newline at end of file From ace5c1f40bc10ff7e888bcd88eaba3442d81554d Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 13 Nov 2025 18:08:09 +0000 Subject: [PATCH 04/33] Updated `SingularValueDecomposition` to return a struct output instead of tuple --- .../SingularValueDecomposition.cs | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs index c440316f..ba22652f 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs @@ -23,9 +23,40 @@ public class SingularValueDecomposition /// /// /// - public IObservable> Process(IObservable source) + public IObservable Process(IObservable source) { - return source.Select(tensor => linalg.svd(tensor, fullMatrices: FullMatrices).ToTuple()); + return source.Select(tensor => + { + var (U, S, Vh) = linalg.svd(tensor, fullMatrices: FullMatrices); + return new SvdResult(U, S, Vh); + }); + } + + /// + /// Represents the result of a singular value decomposition. + /// + /// + /// + /// + public readonly struct SvdResult( + Tensor u, + Tensor s, + Tensor vh) + { + /// + /// The U tensor. + /// + public Tensor U => u; + + /// + /// The singular values. + /// + public Tensor S => s; + + /// + /// The Vh tensor. + /// + public Tensor Vh => vh; } } } \ No newline at end of file From 244ea287b383c619c41ad2175ad271c00f29ece8 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 13 Nov 2025 18:09:17 +0000 Subject: [PATCH 05/33] Added operator to support chaining matrix multiplication --- .../LinearAlgebra/MatrixMultiply.cs | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs new file mode 100644 index 00000000..94952c45 --- /dev/null +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Reactive.Linq; +using static TorchSharp.torch; +using static TorchSharp.torch.linalg; + +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents an operator that performs matrix multiplication with 2 or more tensors. +/// +[Combinator] +[Description("Performs matrix multiplication with 2 or more tensors.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class MatrixMultiply +{ + /// + /// Performs matrix multiplication with 2 tensors. + /// + /// + /// + public IObservable Process(IObservable> source) + { + return source.Select(input => + { + return matmul(input.Item1, input.Item2); + }); + } + + /// + /// Performs matrix multiplication with 3 tensors. + /// + /// + /// + public IObservable Process(IObservable> source) + { + return source.Select(input => + { + return multi_dot([input.Item1, input.Item2, input.Item3]); + }); + } + + /// + /// Performs matrix multiplication with 4 tensors. + /// + /// + /// + public IObservable Process(IObservable> source) + { + return source.Select(input => + { + return multi_dot([input.Item1, input.Item2, input.Item3, input.Item4]); + }); + } + + /// + /// Performs matrix multiplication with 5 tensors. + /// + /// + /// + public IObservable Process(IObservable> source) + { + return source.Select(input => + { + return multi_dot([input.Item1, input.Item2, input.Item3, input.Item4, input.Item5]); + }); + } + + /// + /// Performs matrix multiplication with 6 tensors. + /// + /// + /// + public IObservable Process(IObservable> source) + { + return source.Select(input => + { + return multi_dot([input.Item1, input.Item2, input.Item3, input.Item4, input.Item5, input.Item6]); + }); + } + + /// + /// Performs matrix multiplication with 7 tensors. + /// + /// + /// + public IObservable Process(IObservable> source) + { + return source.Select(input => + { + return multi_dot([input.Item1, input.Item2, input.Item3, input.Item4, input.Item5, input.Item6, input.Item7]); + }); + } + + /// + /// Performs matrix multiplication with an array of tensors. + /// + /// + /// + public IObservable Process(IObservable source) + { + return source.Select(multi_dot); + } + + /// + /// Performs matrix multiplication with a list of tensors. + /// + /// + /// + public IObservable Process(IObservable> source) + { + return source.Select(multi_dot); + } + + /// + /// Performs matrix multiplication with an enumerable of tensors. + /// + /// + /// + public IObservable Process(IObservable> source) + { + return source.Select(input => multi_dot([.. input])); + } +} \ No newline at end of file From c82c6610c629c81a087ea067f64d20216cb18c8c Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Fri, 12 Dec 2025 13:53:07 +0000 Subject: [PATCH 06/33] Improved XML documentation --- .../LinearAlgebra/CholeskyDecomposition.cs | 29 ++++--- .../LinearAlgebra/CrossProduct.cs | 4 +- .../LinearAlgebra/Determinant.cs | 29 ++++--- .../LinearAlgebra/EigenvalueDecomposition.cs | 42 +++++++--- src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs | 29 ++++--- .../LinearAlgebra/LeastSquaresSolve.cs | 36 +++------ .../LinearAlgebra/MatrixMultiply.cs | 24 +++--- src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs | 53 ++++++------ .../LinearAlgebra/SignLogDeterminant.cs | 44 ++++++---- .../SingularValueDecomposition.cs | 81 +++++++++---------- .../LinearAlgebra/TensorSolve.cs | 7 +- 11 files changed, 196 insertions(+), 182 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs index 92369615..3e901641 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs @@ -3,24 +3,23 @@ using System.Reactive.Linq; using static TorchSharp.torch; -namespace Bonsai.ML.Torch.LinearAlgebra +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents an operator that computes the Cholesky decomposition of a complex Hermitian or real symmetric positive-definite matrix. +/// +[Combinator] +[Description("Computes the Cholesky decomposition of a complex Hermitian or real symmetric positive-definite matrix.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class CholeskyDecomposition { /// /// Computes the Cholesky decomposition of a complex Hermitian or real symmetric positive-definite matrix. /// - [Combinator] - [Description("Computes the Cholesky decomposition of a complex Hermitian or real symmetric positive-definite matrix.")] - [WorkflowElementCategory(ElementCategory.Transform)] - public class CholeskyDecomposition + /// + /// + public IObservable Process(IObservable source) { - /// - /// Computes the Cholesky decomposition of a complex Hermitian or real symmetric positive-definite matrix. - /// - /// - /// - public IObservable Process(IObservable source) - { - return source.Select(linalg.cholesky); - } + return source.Select(linalg.cholesky); } -} \ No newline at end of file +} diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs b/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs index 7627344f..dd4be273 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs @@ -7,7 +7,7 @@ namespace Bonsai.ML.Torch.LinearAlgebra; /// -/// Computes the cross product of 2 tensors. +/// Represents an operator that computes the cross product of 2 tensors. /// [Combinator] [Description("Computes the cross product of 2 tensors.")] @@ -31,4 +31,4 @@ public IObservable Process(IObservable> source) return cross(value.Item1, value.Item2, Dimension); }); } -} \ No newline at end of file +} diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/Determinant.cs b/src/Bonsai.ML.Torch/LinearAlgebra/Determinant.cs index 475651d0..4a5cb78d 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/Determinant.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/Determinant.cs @@ -3,24 +3,23 @@ using System.Reactive.Linq; using static TorchSharp.torch; -namespace Bonsai.ML.Torch.LinearAlgebra +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents an operator that computes the determinant of a square matrix. +/// +[Combinator] +[Description("Computes the determinant of a square matrix.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class Determinant { /// /// Computes the determinant of a square matrix. /// - [Combinator] - [Description("Computes the determinant of a square matrix.")] - [WorkflowElementCategory(ElementCategory.Transform)] - public class Determinant + /// + /// + public IObservable Process(IObservable source) { - /// - /// Computes the determinant of a square matrix. - /// - /// - /// - public IObservable Process(IObservable source) - { - return source.Select(linalg.det); - } + return source.Select(linalg.det); } -} \ No newline at end of file +} diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs index 6784b1bf..d4029fc7 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs @@ -3,24 +3,40 @@ using System.Reactive.Linq; using static TorchSharp.torch; -namespace Bonsai.ML.Torch.LinearAlgebra +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents an operator that computes the eigenvalue decomposition of a square matrix if it exists. +/// +[Combinator] +[Description("Computes the eigenvalue decomposition of a square matrix if it exists.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class EigenvalueDecomposition { /// /// Computes the eigenvalue decomposition of a square matrix if it exists. /// - [Combinator] - [Description("Computes the eigenvalue decomposition of a square matrix if it exists.")] - [WorkflowElementCategory(ElementCategory.Transform)] - public class EigenvalueDecomposition + /// + /// + public IObservable Process(IObservable source) { + return source.Select(tensor => new EigenDecompositionResult(linalg.eig(tensor))); + } + + /// + /// Represents the result of an eigenvalue decomposition. + /// + /// The tuple containing the eigenvalues and eigenvectors. + public readonly struct EigenDecompositionResult((Tensor eigenvalues, Tensor eigenvectors) result) + { + /// + /// Gets the eigenvalues of the decomposition. + /// + public Tensor Eigenvalues => result.eigenvalues; + /// - /// Computes the eigenvalue decomposition of a square matrix if it exists. + /// Gets the eigenvectors of the decomposition. /// - /// - /// - public IObservable> Process(IObservable source) - { - return source.Select(tensor => linalg.eig(tensor).ToTuple()); - } + public Tensor Eigenvectors => result.eigenvectors; } -} \ No newline at end of file +} diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs b/src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs index 1d879b5b..530979fc 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs @@ -4,24 +4,23 @@ using static TorchSharp.torch; using static TorchSharp.torch.linalg; -namespace Bonsai.ML.Torch.LinearAlgebra +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents an operator that computes the inverse of the input matrix. +/// +[Combinator] +[Description("Computes the inverse of the input matrix.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class Inverse { /// /// Computes the inverse of the input matrix. /// - [Combinator] - [Description("Computes the inverse of the input matrix.")] - [WorkflowElementCategory(ElementCategory.Transform)] - public class Inverse + /// The input matrix to invert. + /// The inverse of the input matrix. + public IObservable Process(IObservable source) { - /// - /// Computes the inverse of the input matrix. - /// - /// - /// - public IObservable Process(IObservable source) - { - return source.Select(inv); - } + return source.Select(inv); } -} \ No newline at end of file +} diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresSolve.cs b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresSolve.cs index d5560708..aaa058c3 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresSolve.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresSolve.cs @@ -2,68 +2,56 @@ using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; -using static TorchSharp.torch.linalg; namespace Bonsai.ML.Torch.LinearAlgebra; /// -/// Represents an operator that computes the solution to the least squares and least norm problems for a full rank matrix A of size m×n and a matrix B of size m×k. +/// Represents an operator that computes the solution to the least squares and least norm problems for a full rank matrix A of size m*n and a matrix B of size m*k. /// [Combinator] -[Description("Computes the solution to the system tensordot(A, X) = B.")] +[Description("Computes the solution to the least squares and least norm problems for a full rank matrix A of size m*n and a matrix B of size m*k.")] [WorkflowElementCategory(ElementCategory.Transform)] public class LeastSquaresSolve { /// - /// Computes the solution to the least squares and least norm problems for a full rank matrix A of size m×n and a matrix B of size m×k. + /// Computes the solution to the least squares and least norm problems for a full rank matrix A of size m*n and a matrix B of size m*k. /// /// /// public IObservable Process(IObservable> source) { - return source.Select(value => - { - var (solution, residuals, rank, singularValues) = linalg.lstsq(value.Item1, value.Item2); - return new LeastSquaresResult( - solution, - residuals, - rank, - singularValues); - }); + return source.Select(value => new LeastSquaresResult(linalg.lstsq(value.Item1, value.Item2))); } /// /// Represents the result of solving of linear equations using the least squares method. /// - /// - /// - /// - /// - public readonly struct LeastSquaresResult( + /// + public readonly struct LeastSquaresResult(( Tensor solution, Tensor residuals, Tensor rank, Tensor singularValues - ) + ) result) { /// /// The solution to the system of equations. /// - public Tensor Solution => solution; + public Tensor Solution => result.solution; /// /// The residual error. /// - public Tensor Residuals => residuals; + public Tensor Residuals => result.residuals; /// /// The effective rank of the solution. /// - public Tensor Rank => rank; + public Tensor Rank => result.rank; /// /// The singular values of the solution. /// - public Tensor SingularValues => singularValues; + public Tensor SingularValues => result.singularValues; } -} \ No newline at end of file +} diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs index 94952c45..30a25c8a 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs @@ -9,15 +9,15 @@ namespace Bonsai.ML.Torch.LinearAlgebra; /// -/// Represents an operator that performs matrix multiplication with 2 or more tensors. +/// Represents an operator that performs matrix multiplication of 2 or more tensors. /// [Combinator] -[Description("Performs matrix multiplication with 2 or more tensors.")] +[Description("Performs matrix multiplication of 2 or more tensors.")] [WorkflowElementCategory(ElementCategory.Transform)] public class MatrixMultiply { /// - /// Performs matrix multiplication with 2 tensors. + /// Performs matrix multiplication of 2 tensors. /// /// /// @@ -30,7 +30,7 @@ public IObservable Process(IObservable> source) } /// - /// Performs matrix multiplication with 3 tensors. + /// Performs matrix multiplication of 3 tensors. /// /// /// @@ -43,7 +43,7 @@ public IObservable Process(IObservable> so } /// - /// Performs matrix multiplication with 4 tensors. + /// Performs matrix multiplication of 4 tensors. /// /// /// @@ -56,7 +56,7 @@ public IObservable Process(IObservable - /// Performs matrix multiplication with 5 tensors. + /// Performs matrix multiplication of 5 tensors. /// /// /// @@ -69,7 +69,7 @@ public IObservable Process(IObservable - /// Performs matrix multiplication with 6 tensors. + /// Performs matrix multiplication of 6 tensors. /// /// /// @@ -82,7 +82,7 @@ public IObservable Process(IObservable - /// Performs matrix multiplication with 7 tensors. + /// Performs matrix multiplication of 7 tensors. /// /// /// @@ -95,7 +95,7 @@ public IObservable Process(IObservable - /// Performs matrix multiplication with an array of tensors. + /// Performs matrix multiplication of an array of tensors. /// /// /// @@ -105,7 +105,7 @@ public IObservable Process(IObservable source) } /// - /// Performs matrix multiplication with a list of tensors. + /// Performs matrix multiplication of a list of tensors. /// /// /// @@ -115,7 +115,7 @@ public IObservable Process(IObservable> source) } /// - /// Performs matrix multiplication with an enumerable of tensors. + /// Performs matrix multiplication of an enumerable of tensors. /// /// /// @@ -123,4 +123,4 @@ public IObservable Process(IObservable> source) { return source.Select(input => multi_dot([.. input])); } -} \ No newline at end of file +} diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs b/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs index eb18920d..510a7b59 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs @@ -3,35 +3,36 @@ using System.Reactive.Linq; using static TorchSharp.torch; -namespace Bonsai.ML.Torch.LinearAlgebra +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents an operator that computes a vector or matrix norm. +/// +[Combinator] +[Description("Computes a vector or matrix norm.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class Norm { /// - /// Computes a vector or matrix norm. + /// The dimensions along which to compute the norm. /// - [Combinator] - [Description("Computes a vector or matrix norm.")] - [WorkflowElementCategory(ElementCategory.Transform)] - public class Norm - { - /// - /// The dimensions along which to compute the norm. - /// - [TypeConverter(typeof(UnidimensionalArrayConverter))] - public long[] Dimensions { get; set; } = null; + [TypeConverter(typeof(UnidimensionalArrayConverter))] + [Description("The dimensions along which to compute the norm.")] + public long[] Dimensions { get; set; } = null; - /// - /// If true, the reduced dimensions are retained in the result as dimensions with size one. - /// - public bool Keepdim { get; set; } = false; + /// + /// If true, the reduced dimensions are retained in the result as dimensions with size one. + /// + [Description("If true, the reduced dimensions are retained in the result as dimensions with size one.")] + public bool Keepdim { get; set; } = false; - /// - /// Computes a matrix norm. - /// - /// - /// - public IObservable Process(IObservable source) - { - return source.Select(tensor => linalg.norm(tensor, dims: Dimensions, keepdim: Keepdim)); - } + /// + /// Computes a matrix norm. + /// + /// + /// + public IObservable Process(IObservable source) + { + return source.Select(tensor => linalg.norm(tensor, dims: Dimensions, keepdim: Keepdim)); } -} \ No newline at end of file +} diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs index 6d29c910..2b9eb66d 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs @@ -3,24 +3,40 @@ using System.Reactive.Linq; using static TorchSharp.torch; -namespace Bonsai.ML.Torch.LinearAlgebra +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents an operator that computes the sign and natural logarithm of the absolute value of the determinant of a square matrix. +/// +[Combinator] +[Description("Computes the sign and natural logarithm of the absolute value of the determinant of a square matrix.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class SignLogDeterminant { /// - /// Computes the determinant of a square matrix. + /// Computes the sign and natural logarithm of the absolute value of the determinant of a square matrix. /// - [Combinator] - [Description("Computes the sign and natural logarithm of the absolute value of the determinant of a square matrix.")] - [WorkflowElementCategory(ElementCategory.Transform)] - public class SignLogDeterminant + /// + /// + public IObservable Process(IObservable source) { + return source.Select(result => new SignLogDeterminantResult(linalg.slogdet(result))); + } + + /// + /// Represents the result of computing the sign and natural logarithm of the absolute value of the determinant. + /// + /// + public readonly struct SignLogDeterminantResult((Tensor sign, Tensor logabsdet) result) + { + /// + /// Gets the sign of the determinant. + /// + public Tensor Sign => result.sign; + /// - /// Computes the determinant of a square matrix. + /// Gets the natural logarithm of the absolute value of the determinant. /// - /// - /// - public IObservable<(Tensor, Tensor)> Process(IObservable source) - { - return source.Select(linalg.slogdet); - } + public Tensor LogAbsDeterminant => result.logabsdet; } -} \ No newline at end of file +} diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs index ba22652f..25ac9581 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs @@ -3,60 +3,55 @@ using System.Reactive.Linq; using static TorchSharp.torch; -namespace Bonsai.ML.Torch.LinearAlgebra +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents an operator that computes the singular value decomposition (SVD) of a matrix. +/// +[Combinator] +[Description("Computes the singular value decomposition (SVD) of a matrix.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class SingularValueDecomposition { + /// + /// Whether to compute the full or reduced SVD. + /// + [Description("Whether to compute the full or reduced SVD.")] + public bool FullMatrices { get; set; } = false; + /// /// Computes the singular value decomposition (SVD) of a matrix. /// - [Combinator] - [Description("Computes the singular value decomposition (SVD) of a matrix.")] - [WorkflowElementCategory(ElementCategory.Transform)] - public class SingularValueDecomposition + /// + /// + public IObservable Process(IObservable source) + { + return source.Select(tensor => new SingularValueDecompositionResult(linalg.svd(tensor, fullMatrices: FullMatrices))); + } + + /// + /// Represents the result of a singular value decomposition. + /// + /// + public readonly struct SingularValueDecompositionResult(( + Tensor u, + Tensor s, + Tensor vh + ) result) { /// - /// Whether to compute the full or reduced SVD. + /// The U tensor. /// - public bool FullMatrices { get; set; } = false; + public Tensor U => result.u; /// - /// Computes the singular value decomposition (SVD) of a matrix. + /// The singular values. /// - /// - /// - public IObservable Process(IObservable source) - { - return source.Select(tensor => - { - var (U, S, Vh) = linalg.svd(tensor, fullMatrices: FullMatrices); - return new SvdResult(U, S, Vh); - }); - } + public Tensor S => result.s; /// - /// Represents the result of a singular value decomposition. + /// The Vh tensor. /// - /// - /// - /// - public readonly struct SvdResult( - Tensor u, - Tensor s, - Tensor vh) - { - /// - /// The U tensor. - /// - public Tensor U => u; - - /// - /// The singular values. - /// - public Tensor S => s; - - /// - /// The Vh tensor. - /// - public Tensor Vh => vh; - } + public Tensor Vh => result.vh; } -} \ No newline at end of file +} diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs b/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs index 1f1be9a5..52b5f5d3 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs @@ -15,13 +15,14 @@ namespace Bonsai.ML.Torch.LinearAlgebra; public class TensorSolve { /// - /// The dimension to perform the operation. + /// The dimensions to perform the operation. /// [TypeConverter(typeof(UnidimensionalArrayConverter))] + [Description("The dimensions to perform the operation.")] public long[] Dimensions { get; set; } = []; /// - /// Computes the cross product of 2 tensors. + /// Computes the solution to the system tensordot(A, X) = B. /// /// /// @@ -32,4 +33,4 @@ public IObservable Process(IObservable> source) return tensorsolve(value.Item1, value.Item2, Dimensions); }); } -} \ No newline at end of file +} From 6ceedd1e1b1d20fe5592bc88e4181e17809b8a55 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Fri, 19 Dec 2025 13:52:37 +0000 Subject: [PATCH 07/33] Refactored `MatrixMultiply` overload with a tuple of 2 tensors to use object instead of static method --- src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs index 30a25c8a..0703dc3d 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs @@ -23,10 +23,7 @@ public class MatrixMultiply /// public IObservable Process(IObservable> source) { - return source.Select(input => - { - return matmul(input.Item1, input.Item2); - }); + return source.Select(input =>input.Item1.matmul(input.Item2)); } /// From 6aa9dbd100784c2b71b75d467f7cbd586eb6e7ce Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Fri, 19 Dec 2025 13:53:19 +0000 Subject: [PATCH 08/33] Added operator to compute the rank of a matrix --- .../LinearAlgebra/MatrixRank.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs new file mode 100644 index 00000000..84eb4c37 --- /dev/null +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Reactive.Linq; +using static TorchSharp.torch; +using static TorchSharp.torch.linalg; + +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents an operator that computes the numerical rank of a matrix. +/// +[Combinator] +[Description("Computes the numerical rank of a matrix.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class MatrixRank +{ + /// + /// Gets or sets the absolute tolerance for singular values to be considered non-zero. + /// + [Description("The absolute tolerance for singular values to be considered non-zero.")] + public double? AbsoluteTolerance { get; set; } = null; + + /// + /// Gets or sets the relative tolerance for singular values to be considered non-zero. + /// + [Description("The relative tolerance for singular values to be considered non-zero.")] + public double? RelativeTolerance { get; set; } = null; + + /// + /// Gets or sets a value indicating whether to treat the input matrix as Hermitian if input is complex or symmetric if real. + /// + [Description("Indicates whether to treat the input matrix as Hermitian if input is complex or symmetric if real.")] + public bool Hermitian { get; set; } = false; + + /// + /// Computes the numerical rank of a matrix. + /// + /// + /// + public IObservable Process(IObservable source) + { + return source.Select(input => matrix_rank(input, atol: AbsoluteTolerance, rtol: RelativeTolerance, hermitian: Hermitian)); + } +} From 06d81b6a763b1029ad318d2b073981998a1c39bb Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Fri, 19 Dec 2025 13:53:44 +0000 Subject: [PATCH 09/33] Added operator to compute the QR decomposition of a matrix --- .../LinearAlgebra/QRDecomposition.cs | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/Bonsai.ML.Torch/LinearAlgebra/QRDecomposition.cs diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/QRDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/QRDecomposition.cs new file mode 100644 index 00000000..eb01aaf3 --- /dev/null +++ b/src/Bonsai.ML.Torch/LinearAlgebra/QRDecomposition.cs @@ -0,0 +1,50 @@ +using System; +using System.ComponentModel; +using System.Reactive.Linq; +using static TorchSharp.torch; +using static TorchSharp.torch.linalg; + +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents an operator that computes the QR decomposition of a matrix. +/// +[Combinator] +[Description("Computes the QR decomposition of a matrix.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class QRDecomposition +{ + /// + /// Gets or sets the mode of the QR decomposition. + /// + [Description("The mode of the QR decomposition.")] + public QRMode Mode { get; set; } = QRMode.Reduced; + + /// + /// Computes the QR decomposition of a matrix. + /// + /// + /// + public IObservable Process(IObservable source) + { + return source.Select(tensor => new QRDecompositionResult(qr(tensor, mode: Mode))); + } + + /// + /// Represents the result of a QR decomposition. + /// + /// + public readonly struct QRDecompositionResult((Tensor Q, Tensor R) result) + { + /// + /// Gets the orthogonal matrix Q. + /// + public Tensor Q => result.Q; + + /// + /// Gets the upper triangular matrix R. + /// + public Tensor R => result.R; + } + +} From 99f73aa07a3f833c59662e8853dc925a258b0b1b Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Fri, 19 Dec 2025 13:54:10 +0000 Subject: [PATCH 10/33] Added an operator to solve a triangular system of equations --- .../LinearAlgebra/TriangularSolve.cs | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/Bonsai.ML.Torch/LinearAlgebra/TriangularSolve.cs diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/TriangularSolve.cs b/src/Bonsai.ML.Torch/LinearAlgebra/TriangularSolve.cs new file mode 100644 index 00000000..8f7b1f54 --- /dev/null +++ b/src/Bonsai.ML.Torch/LinearAlgebra/TriangularSolve.cs @@ -0,0 +1,47 @@ +using System; +using System.ComponentModel; +using System.Reactive.Linq; +using static TorchSharp.torch; +using static TorchSharp.torch.linalg; + +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents an operator that computes the solution to a triangular system of linear equations with a unique solution. +/// +[Combinator] +[Description("Computes the solution to a triangular system of linear equations with a unique solution.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class TriangularSolve +{ + /// + /// Gets or sets a value indicating whether the first matrix is upper triangular. + /// + [Description("Indicates whether the first matrix is upper triangular.")] + public bool Upper { get; set; } = true; + + /// + /// Gets or sets a value indicating whether to solve the system with the first matrix on the left or right (AX = B or XA = B). + /// + [Description("Indicates whether to solve the system with the first matrix on the left or right (AX = B or XA = B).")] + public bool Left { get; set; } = true; + + /// + /// Gets or sets a value indicating whether the first matrix has a unit diagonal, i.e., all diagonal elements are assumed to be 1. + /// + [Description("Indicates whether the first matrix has a unit diagonal, i.e., all diagonal elements are assumed to be 1.")] + public bool UnitDiagonal { get; set; } = false; + + /// + /// Computes the solution to a triangular system of linear equations for each pair of input tensors. + /// + /// + /// + public IObservable Process(IObservable> source) + { + return source.Select(value => + { + return solve_triangular(value.Item1, value.Item2, upper: Upper, left: Left, unitriangular: UnitDiagonal); + }); + } +} From e29465e5cce7abdf9e5825e866bda09c20b21232 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Wed, 15 Jul 2026 12:56:43 +0100 Subject: [PATCH 11/33] Rename LeastSquaresSolve -> LeastSquares --- .../LinearAlgebra/{LeastSquaresSolve.cs => LeastSquares.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename src/Bonsai.ML.Torch/LinearAlgebra/{LeastSquaresSolve.cs => LeastSquares.cs} (97%) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresSolve.cs b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs similarity index 97% rename from src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresSolve.cs rename to src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs index aaa058c3..ec6ab970 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresSolve.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; @@ -11,7 +11,7 @@ namespace Bonsai.ML.Torch.LinearAlgebra; [Combinator] [Description("Computes the solution to the least squares and least norm problems for a full rank matrix A of size m*n and a matrix B of size m*k.")] [WorkflowElementCategory(ElementCategory.Transform)] -public class LeastSquaresSolve +public class LeastSquares { /// /// Computes the solution to the least squares and least norm problems for a full rank matrix A of size m*n and a matrix B of size m*k. From f95495d83a7f571cf5839a5993e9b70d21d0ad1c Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Wed, 15 Jul 2026 12:57:14 +0100 Subject: [PATCH 12/33] Rename TriangularSolve -> SolveTriangular --- .../LinearAlgebra/{TriangularSolve.cs => SolveTriangular.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename src/Bonsai.ML.Torch/LinearAlgebra/{TriangularSolve.cs => SolveTriangular.cs} (97%) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/TriangularSolve.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs similarity index 97% rename from src/Bonsai.ML.Torch/LinearAlgebra/TriangularSolve.cs rename to src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs index 8f7b1f54..cc265d0d 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/TriangularSolve.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; @@ -12,7 +12,7 @@ namespace Bonsai.ML.Torch.LinearAlgebra; [Combinator] [Description("Computes the solution to a triangular system of linear equations with a unique solution.")] [WorkflowElementCategory(ElementCategory.Transform)] -public class TriangularSolve +public class SolveTriangular { /// /// Gets or sets a value indicating whether the first matrix is upper triangular. From 25b6f6d243f3533eef0c1f9bf8065d9dc87d32cc Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Wed, 15 Jul 2026 13:01:09 +0100 Subject: [PATCH 13/33] Move result structs outside of nested classes --- .../LinearAlgebra/EigenDecompositionResult.cs | 20 +++++++++++ .../LinearAlgebra/EigenvalueDecomposition.cs | 19 +--------- .../LinearAlgebra/LeastSquares.cs | 32 ----------------- .../LinearAlgebra/LeastSquaresResult.cs | 35 +++++++++++++++++++ .../LinearAlgebra/QRDecomposition.cs | 20 +---------- .../LinearAlgebra/QRDecompositionResult.cs | 20 +++++++++++ .../LinearAlgebra/SignLogDeterminant.cs | 19 +--------- .../LinearAlgebra/SignLogDeterminantResult.cs | 20 +++++++++++ .../SingularValueDecomposition.cs | 28 +-------------- .../SingularValueDecompositionResult.cs | 29 +++++++++++++++ 10 files changed, 128 insertions(+), 114 deletions(-) create mode 100644 src/Bonsai.ML.Torch/LinearAlgebra/EigenDecompositionResult.cs create mode 100644 src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresResult.cs create mode 100644 src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs create mode 100644 src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminantResult.cs create mode 100644 src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecompositionResult.cs diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/EigenDecompositionResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/EigenDecompositionResult.cs new file mode 100644 index 00000000..919332a1 --- /dev/null +++ b/src/Bonsai.ML.Torch/LinearAlgebra/EigenDecompositionResult.cs @@ -0,0 +1,20 @@ +using static TorchSharp.torch; + +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents the result of an eigenvalue decomposition. +/// +/// The tuple containing the eigenvalues and eigenvectors. +public readonly struct EigenDecompositionResult((Tensor eigenvalues, Tensor eigenvectors) result) +{ + /// + /// Gets the eigenvalues of the decomposition. + /// + public Tensor Eigenvalues => result.eigenvalues; + + /// + /// Gets the eigenvectors of the decomposition. + /// + public Tensor Eigenvectors => result.eigenvectors; +} diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs index d4029fc7..e645afbf 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; @@ -22,21 +22,4 @@ public IObservable Process(IObservable source) { return source.Select(tensor => new EigenDecompositionResult(linalg.eig(tensor))); } - - /// - /// Represents the result of an eigenvalue decomposition. - /// - /// The tuple containing the eigenvalues and eigenvectors. - public readonly struct EigenDecompositionResult((Tensor eigenvalues, Tensor eigenvectors) result) - { - /// - /// Gets the eigenvalues of the decomposition. - /// - public Tensor Eigenvalues => result.eigenvalues; - - /// - /// Gets the eigenvectors of the decomposition. - /// - public Tensor Eigenvectors => result.eigenvectors; - } } diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs index ec6ab970..8a749376 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs @@ -22,36 +22,4 @@ public IObservable Process(IObservable { return source.Select(value => new LeastSquaresResult(linalg.lstsq(value.Item1, value.Item2))); } - - /// - /// Represents the result of solving of linear equations using the least squares method. - /// - /// - public readonly struct LeastSquaresResult(( - Tensor solution, - Tensor residuals, - Tensor rank, - Tensor singularValues - ) result) - { - /// - /// The solution to the system of equations. - /// - public Tensor Solution => result.solution; - - /// - /// The residual error. - /// - public Tensor Residuals => result.residuals; - - /// - /// The effective rank of the solution. - /// - public Tensor Rank => result.rank; - - /// - /// The singular values of the solution. - /// - public Tensor SingularValues => result.singularValues; - } } diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresResult.cs new file mode 100644 index 00000000..998321b9 --- /dev/null +++ b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresResult.cs @@ -0,0 +1,35 @@ +using static TorchSharp.torch; + +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents the result of solving of linear equations using the least squares method. +/// +/// +public readonly struct LeastSquaresResult(( + Tensor solution, + Tensor residuals, + Tensor rank, + Tensor singularValues +) result) +{ + /// + /// The solution to the system of equations. + /// + public Tensor Solution => result.solution; + + /// + /// The residual error. + /// + public Tensor Residuals => result.residuals; + + /// + /// The effective rank of the solution. + /// + public Tensor Rank => result.rank; + + /// + /// The singular values of the solution. + /// + public Tensor SingularValues => result.singularValues; +} diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/QRDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/QRDecomposition.cs index eb01aaf3..6e9c481e 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/QRDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/QRDecomposition.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; @@ -29,22 +29,4 @@ public IObservable Process(IObservable source) { return source.Select(tensor => new QRDecompositionResult(qr(tensor, mode: Mode))); } - - /// - /// Represents the result of a QR decomposition. - /// - /// - public readonly struct QRDecompositionResult((Tensor Q, Tensor R) result) - { - /// - /// Gets the orthogonal matrix Q. - /// - public Tensor Q => result.Q; - - /// - /// Gets the upper triangular matrix R. - /// - public Tensor R => result.R; - } - } diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs new file mode 100644 index 00000000..17fef1bf --- /dev/null +++ b/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs @@ -0,0 +1,20 @@ +using static TorchSharp.torch; + +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents the result of a QR decomposition. +/// +/// +public readonly struct QRDecompositionResult((Tensor Q, Tensor R) result) +{ + /// + /// Gets the orthogonal matrix Q. + /// + public Tensor Q => result.Q; + + /// + /// Gets the upper triangular matrix R. + /// + public Tensor R => result.R; +} diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs index 2b9eb66d..5090fa90 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; @@ -22,21 +22,4 @@ public IObservable Process(IObservable source) { return source.Select(result => new SignLogDeterminantResult(linalg.slogdet(result))); } - - /// - /// Represents the result of computing the sign and natural logarithm of the absolute value of the determinant. - /// - /// - public readonly struct SignLogDeterminantResult((Tensor sign, Tensor logabsdet) result) - { - /// - /// Gets the sign of the determinant. - /// - public Tensor Sign => result.sign; - - /// - /// Gets the natural logarithm of the absolute value of the determinant. - /// - public Tensor LogAbsDeterminant => result.logabsdet; - } } diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminantResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminantResult.cs new file mode 100644 index 00000000..9646f644 --- /dev/null +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminantResult.cs @@ -0,0 +1,20 @@ +using static TorchSharp.torch; + +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents the result of computing the sign and natural logarithm of the absolute value of the determinant. +/// +/// +public readonly struct SignLogDeterminantResult((Tensor sign, Tensor logabsdet) result) +{ + /// + /// Gets the sign of the determinant. + /// + public Tensor Sign => result.sign; + + /// + /// Gets the natural logarithm of the absolute value of the determinant. + /// + public Tensor LogAbsDeterminant => result.logabsdet; +} diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs index 25ac9581..bc45fc1f 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; @@ -28,30 +28,4 @@ public IObservable Process(IObservable { return source.Select(tensor => new SingularValueDecompositionResult(linalg.svd(tensor, fullMatrices: FullMatrices))); } - - /// - /// Represents the result of a singular value decomposition. - /// - /// - public readonly struct SingularValueDecompositionResult(( - Tensor u, - Tensor s, - Tensor vh - ) result) - { - /// - /// The U tensor. - /// - public Tensor U => result.u; - - /// - /// The singular values. - /// - public Tensor S => result.s; - - /// - /// The Vh tensor. - /// - public Tensor Vh => result.vh; - } } diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecompositionResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecompositionResult.cs new file mode 100644 index 00000000..01045881 --- /dev/null +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecompositionResult.cs @@ -0,0 +1,29 @@ +using static TorchSharp.torch; + +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents the result of a singular value decomposition. +/// +/// +public readonly struct SingularValueDecompositionResult(( + Tensor u, + Tensor s, + Tensor vh +) result) +{ + /// + /// The U tensor. + /// + public Tensor U => result.u; + + /// + /// The singular values. + /// + public Tensor S => result.s; + + /// + /// The Vh tensor. + /// + public Tensor Vh => result.vh; +} From f0dd68c0740102f84d5e566df19621b0e35c21de Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 17:02:39 +0100 Subject: [PATCH 14/33] Fix formatting issues Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs | 2 +- src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs | 2 +- src/Bonsai.ML.Torch/LinearAlgebra/Determinant.cs | 2 +- src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs | 2 +- src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs | 2 +- src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs | 2 +- src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs | 2 +- src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs index 3e901641..ac8c8812 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs b/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs index dd4be273..a4dfbf80 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/Determinant.cs b/src/Bonsai.ML.Torch/LinearAlgebra/Determinant.cs index 4a5cb78d..24b2ab26 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/Determinant.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/Determinant.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs b/src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs index 530979fc..0f17eda1 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs index 0703dc3d..d247e271 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs index 84eb4c37..af5cc05b 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs b/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs index 510a7b59..ee3bcd02 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs b/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs index 52b5f5d3..72701b92 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; From a7fcd4de74f7179036d63dfe7672930c4b5a33fa Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 17:09:26 +0100 Subject: [PATCH 15/33] Align xml docs and description attributes across package Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs | 3 ++- src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs | 6 +++--- .../LinearAlgebra/SingularValueDecomposition.cs | 2 +- src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs | 12 ++++++------ src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs | 4 ++-- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs b/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs index a4dfbf80..9972a3ac 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs @@ -15,8 +15,9 @@ namespace Bonsai.ML.Torch.LinearAlgebra; public class CrossProduct { /// - /// The dimension to perform the operation. + /// Gets or sets the dimension along which to perform the operation. /// + [Description("The dimension along which to perform the operation.")] public long Dimension { get; set; } = -1; /// diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs b/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs index ee3bcd02..d3734e2c 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs @@ -14,16 +14,16 @@ namespace Bonsai.ML.Torch.LinearAlgebra; public class Norm { /// - /// The dimensions along which to compute the norm. + /// Gets or sets the dimensions along which to compute the norm. /// [TypeConverter(typeof(UnidimensionalArrayConverter))] [Description("The dimensions along which to compute the norm.")] public long[] Dimensions { get; set; } = null; /// - /// If true, the reduced dimensions are retained in the result as dimensions with size one. + /// Gets or sets whether the reduced dimensions are retained in the result as dimensions with size one. /// - [Description("If true, the reduced dimensions are retained in the result as dimensions with size one.")] + [Description("Whether the reduced dimensions are retained in the result as dimensions with size one.")] public bool Keepdim { get; set; } = false; /// diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs index bc45fc1f..d06e6a03 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs @@ -14,7 +14,7 @@ namespace Bonsai.ML.Torch.LinearAlgebra; public class SingularValueDecomposition { /// - /// Whether to compute the full or reduced SVD. + /// Gets or sets whether to compute the full or reduced SVD. /// [Description("Whether to compute the full or reduced SVD.")] public bool FullMatrices { get; set; } = false; diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs index cc265d0d..0b3c5417 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs @@ -15,21 +15,21 @@ namespace Bonsai.ML.Torch.LinearAlgebra; public class SolveTriangular { /// - /// Gets or sets a value indicating whether the first matrix is upper triangular. + /// Gets or sets whether the first matrix is upper triangular. /// - [Description("Indicates whether the first matrix is upper triangular.")] + [Description("Whether the first matrix is upper triangular.")] public bool Upper { get; set; } = true; /// - /// Gets or sets a value indicating whether to solve the system with the first matrix on the left or right (AX = B or XA = B). + /// Gets or sets whether to solve the system with the first matrix on the left or right (AX = B or XA = B). /// - [Description("Indicates whether to solve the system with the first matrix on the left or right (AX = B or XA = B).")] + [Description("Whether to solve the system with the first matrix on the left or right (AX = B or XA = B).")] public bool Left { get; set; } = true; /// - /// Gets or sets a value indicating whether the first matrix has a unit diagonal, i.e., all diagonal elements are assumed to be 1. + /// Gets or sets whether the first matrix has a unit diagonal, i.e., all diagonal elements are assumed to be 1. /// - [Description("Indicates whether the first matrix has a unit diagonal, i.e., all diagonal elements are assumed to be 1.")] + [Description("Whether the first matrix has a unit diagonal, i.e., all diagonal elements are assumed to be 1.")] public bool UnitDiagonal { get; set; } = false; /// diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs b/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs index 72701b92..c1a8cfa1 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs @@ -15,10 +15,10 @@ namespace Bonsai.ML.Torch.LinearAlgebra; public class TensorSolve { /// - /// The dimensions to perform the operation. + /// Gets or sets the dimensions along which to perform the operation. /// [TypeConverter(typeof(UnidimensionalArrayConverter))] - [Description("The dimensions to perform the operation.")] + [Description("The dimensions along which to perform the operation.")] public long[] Dimensions { get; set; } = []; /// From 7c4e69c92f54893593fb96e45086148e980d0e7b Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 17:09:56 +0100 Subject: [PATCH 16/33] Rename EigenDecompositionResult -> EigenvalueDecompositionResult Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs | 4 ++-- ...ecompositionResult.cs => EigenvalueDecompositionResult.cs} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/Bonsai.ML.Torch/LinearAlgebra/{EigenDecompositionResult.cs => EigenvalueDecompositionResult.cs} (84%) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs index e645afbf..f3a8c88e 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs @@ -18,8 +18,8 @@ public class EigenvalueDecomposition /// /// /// - public IObservable Process(IObservable source) + public IObservable Process(IObservable source) { - return source.Select(tensor => new EigenDecompositionResult(linalg.eig(tensor))); + return source.Select(tensor => new EigenvalueDecompositionResult(linalg.eig(tensor))); } } diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/EigenDecompositionResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecompositionResult.cs similarity index 84% rename from src/Bonsai.ML.Torch/LinearAlgebra/EigenDecompositionResult.cs rename to src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecompositionResult.cs index 919332a1..57b98a0d 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/EigenDecompositionResult.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecompositionResult.cs @@ -6,7 +6,7 @@ namespace Bonsai.ML.Torch.LinearAlgebra; /// Represents the result of an eigenvalue decomposition. /// /// The tuple containing the eigenvalues and eigenvectors. -public readonly struct EigenDecompositionResult((Tensor eigenvalues, Tensor eigenvectors) result) +public readonly struct EigenvalueDecompositionResult((Tensor eigenvalues, Tensor eigenvectors) result) { /// /// Gets the eigenvalues of the decomposition. From b6c26b3457f258d58f3e1ee2e3463c5af34d01f1 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 17:23:31 +0100 Subject: [PATCH 17/33] Refactor long, single line doc strings into multiple lines Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs | 3 ++- src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs | 6 ++++-- src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs index ac8c8812..15f50bc0 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs @@ -6,7 +6,8 @@ namespace Bonsai.ML.Torch.LinearAlgebra; /// -/// Represents an operator that computes the Cholesky decomposition of a complex Hermitian or real symmetric positive-definite matrix. +/// Represents an operator that computes the Cholesky decomposition of a complex Hermitian or real symmetric +/// positive-definite matrix. /// [Combinator] [Description("Computes the Cholesky decomposition of a complex Hermitian or real symmetric positive-definite matrix.")] diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs index 8a749376..43f4d198 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs @@ -6,7 +6,8 @@ namespace Bonsai.ML.Torch.LinearAlgebra; /// -/// Represents an operator that computes the solution to the least squares and least norm problems for a full rank matrix A of size m*n and a matrix B of size m*k. +/// Represents an operator that computes the solution to the least squares and least norm problems for a full rank +/// matrix A of size m*n and a matrix B of size m*k. /// [Combinator] [Description("Computes the solution to the least squares and least norm problems for a full rank matrix A of size m*n and a matrix B of size m*k.")] @@ -14,7 +15,8 @@ namespace Bonsai.ML.Torch.LinearAlgebra; public class LeastSquares { /// - /// Computes the solution to the least squares and least norm problems for a full rank matrix A of size m*n and a matrix B of size m*k. + /// Computes the solution to the least squares and least norm problems for a full rank matrix A of size m*n and a + /// matrix B of size m*k. /// /// /// diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs index 5090fa90..087e8141 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs @@ -6,7 +6,8 @@ namespace Bonsai.ML.Torch.LinearAlgebra; /// -/// Represents an operator that computes the sign and natural logarithm of the absolute value of the determinant of a square matrix. +/// Represents an operator that computes the sign and natural logarithm of the absolute value of the determinant of a +/// square matrix. /// [Combinator] [Description("Computes the sign and natural logarithm of the absolute value of the determinant of a square matrix.")] From b06095230cfd810d5ba57a3f0b29a2c6c51fffb0 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 17:27:21 +0100 Subject: [PATCH 18/33] Align member doc strings across package Co-authored-by: glopesdev --- .../LinearAlgebra/EigenvalueDecompositionResult.cs | 4 ++-- src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs | 4 ++-- src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs | 4 ++-- src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminantResult.cs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecompositionResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecompositionResult.cs index 57b98a0d..bfa59a0f 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecompositionResult.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecompositionResult.cs @@ -9,12 +9,12 @@ namespace Bonsai.ML.Torch.LinearAlgebra; public readonly struct EigenvalueDecompositionResult((Tensor eigenvalues, Tensor eigenvectors) result) { /// - /// Gets the eigenvalues of the decomposition. + /// The eigenvalues of the decomposition. /// public Tensor Eigenvalues => result.eigenvalues; /// - /// Gets the eigenvectors of the decomposition. + /// The eigenvectors of the decomposition. /// public Tensor Eigenvectors => result.eigenvectors; } diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs index af5cc05b..535d521e 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs @@ -29,9 +29,9 @@ public class MatrixRank public double? RelativeTolerance { get; set; } = null; /// - /// Gets or sets a value indicating whether to treat the input matrix as Hermitian if input is complex or symmetric if real. + /// Gets or sets whether to treat the input matrix as Hermitian if input is complex or symmetric if real. /// - [Description("Indicates whether to treat the input matrix as Hermitian if input is complex or symmetric if real.")] + [Description("Whether to treat the input matrix as Hermitian if input is complex or symmetric if real.")] public bool Hermitian { get; set; } = false; /// diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs index 17fef1bf..c4b73950 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs @@ -9,12 +9,12 @@ namespace Bonsai.ML.Torch.LinearAlgebra; public readonly struct QRDecompositionResult((Tensor Q, Tensor R) result) { /// - /// Gets the orthogonal matrix Q. + /// The orthogonal matrix Q. /// public Tensor Q => result.Q; /// - /// Gets the upper triangular matrix R. + /// The upper triangular matrix R. /// public Tensor R => result.R; } diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminantResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminantResult.cs index 9646f644..62f258ac 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminantResult.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminantResult.cs @@ -9,12 +9,12 @@ namespace Bonsai.ML.Torch.LinearAlgebra; public readonly struct SignLogDeterminantResult((Tensor sign, Tensor logabsdet) result) { /// - /// Gets the sign of the determinant. + /// The sign of the determinant. /// public Tensor Sign => result.sign; /// - /// Gets the natural logarithm of the absolute value of the determinant. + /// The natural logarithm of the absolute value of the determinant. /// public Tensor LogAbsDeterminant => result.logabsdet; } From 80f53df93e64148c70a924d6c6903ab744cfa19e Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 17:28:20 +0100 Subject: [PATCH 19/33] Remove redundant using statements Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs | 1 - src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs index d247e271..9c00198f 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Reactive.Linq; diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs index 535d521e..5ba53eec 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs @@ -1,6 +1,4 @@ using System; -using System.Collections; -using System.Collections.Generic; using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; From e8fb927c76fe5f7646780d7d6fe5008caf03db8e Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 17:31:33 +0100 Subject: [PATCH 20/33] Remove empty and tags Co-authored-by: glopesdev --- .../LinearAlgebra/CholeskyDecomposition.cs | 2 -- .../LinearAlgebra/CrossProduct.cs | 2 -- .../LinearAlgebra/Determinant.cs | 2 -- .../LinearAlgebra/EigenvalueDecomposition.cs | 2 -- src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs | 2 -- .../LinearAlgebra/LeastSquares.cs | 2 -- .../LinearAlgebra/LeastSquaresResult.cs | 1 - .../LinearAlgebra/MatrixMultiply.cs | 18 ------------------ .../LinearAlgebra/MatrixRank.cs | 2 -- src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs | 2 -- .../LinearAlgebra/QRDecomposition.cs | 2 -- .../LinearAlgebra/QRDecompositionResult.cs | 1 - .../LinearAlgebra/SignLogDeterminant.cs | 2 -- .../LinearAlgebra/SignLogDeterminantResult.cs | 1 - .../SingularValueDecomposition.cs | 2 -- .../SingularValueDecompositionResult.cs | 1 - .../LinearAlgebra/SolveTriangular.cs | 2 -- .../LinearAlgebra/TensorSolve.cs | 2 -- 18 files changed, 48 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs index 15f50bc0..1dbab601 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/CholeskyDecomposition.cs @@ -17,8 +17,6 @@ public class CholeskyDecomposition /// /// Computes the Cholesky decomposition of a complex Hermitian or real symmetric positive-definite matrix. /// - /// - /// public IObservable Process(IObservable source) { return source.Select(linalg.cholesky); diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs b/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs index 9972a3ac..890f1395 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/CrossProduct.cs @@ -23,8 +23,6 @@ public class CrossProduct /// /// Computes the cross product of 2 tensors. /// - /// - /// public IObservable Process(IObservable> source) { return source.Select(value => diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/Determinant.cs b/src/Bonsai.ML.Torch/LinearAlgebra/Determinant.cs index 24b2ab26..54e81ba7 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/Determinant.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/Determinant.cs @@ -16,8 +16,6 @@ public class Determinant /// /// Computes the determinant of a square matrix. /// - /// - /// public IObservable Process(IObservable source) { return source.Select(linalg.det); diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs index f3a8c88e..b1a8d62a 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs @@ -16,8 +16,6 @@ public class EigenvalueDecomposition /// /// Computes the eigenvalue decomposition of a square matrix if it exists. /// - /// - /// public IObservable Process(IObservable source) { return source.Select(tensor => new EigenvalueDecompositionResult(linalg.eig(tensor))); diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs b/src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs index 0f17eda1..f8e3c873 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/Inverse.cs @@ -17,8 +17,6 @@ public class Inverse /// /// Computes the inverse of the input matrix. /// - /// The input matrix to invert. - /// The inverse of the input matrix. public IObservable Process(IObservable source) { return source.Select(inv); diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs index 43f4d198..dad9be6e 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquares.cs @@ -18,8 +18,6 @@ public class LeastSquares /// Computes the solution to the least squares and least norm problems for a full rank matrix A of size m*n and a /// matrix B of size m*k. /// - /// - /// public IObservable Process(IObservable> source) { return source.Select(value => new LeastSquaresResult(linalg.lstsq(value.Item1, value.Item2))); diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresResult.cs index 998321b9..20f8a523 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresResult.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/LeastSquaresResult.cs @@ -5,7 +5,6 @@ namespace Bonsai.ML.Torch.LinearAlgebra; /// /// Represents the result of solving of linear equations using the least squares method. /// -/// public readonly struct LeastSquaresResult(( Tensor solution, Tensor residuals, diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs index 9c00198f..97d45f3e 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs @@ -18,8 +18,6 @@ public class MatrixMultiply /// /// Performs matrix multiplication of 2 tensors. /// - /// - /// public IObservable Process(IObservable> source) { return source.Select(input =>input.Item1.matmul(input.Item2)); @@ -28,8 +26,6 @@ public IObservable Process(IObservable> source) /// /// Performs matrix multiplication of 3 tensors. /// - /// - /// public IObservable Process(IObservable> source) { return source.Select(input => @@ -41,8 +37,6 @@ public IObservable Process(IObservable> so /// /// Performs matrix multiplication of 4 tensors. /// - /// - /// public IObservable Process(IObservable> source) { return source.Select(input => @@ -54,8 +48,6 @@ public IObservable Process(IObservable /// Performs matrix multiplication of 5 tensors. /// - /// - /// public IObservable Process(IObservable> source) { return source.Select(input => @@ -67,8 +59,6 @@ public IObservable Process(IObservable /// Performs matrix multiplication of 6 tensors. /// - /// - /// public IObservable Process(IObservable> source) { return source.Select(input => @@ -80,8 +70,6 @@ public IObservable Process(IObservable /// Performs matrix multiplication of 7 tensors. /// - /// - /// public IObservable Process(IObservable> source) { return source.Select(input => @@ -93,8 +81,6 @@ public IObservable Process(IObservable /// Performs matrix multiplication of an array of tensors. /// - /// - /// public IObservable Process(IObservable source) { return source.Select(multi_dot); @@ -103,8 +89,6 @@ public IObservable Process(IObservable source) /// /// Performs matrix multiplication of a list of tensors. /// - /// - /// public IObservable Process(IObservable> source) { return source.Select(multi_dot); @@ -113,8 +97,6 @@ public IObservable Process(IObservable> source) /// /// Performs matrix multiplication of an enumerable of tensors. /// - /// - /// public IObservable Process(IObservable> source) { return source.Select(input => multi_dot([.. input])); diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs index 5ba53eec..818eadd8 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs @@ -35,8 +35,6 @@ public class MatrixRank /// /// Computes the numerical rank of a matrix. /// - /// - /// public IObservable Process(IObservable source) { return source.Select(input => matrix_rank(input, atol: AbsoluteTolerance, rtol: RelativeTolerance, hermitian: Hermitian)); diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs b/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs index d3734e2c..f091043b 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs @@ -29,8 +29,6 @@ public class Norm /// /// Computes a matrix norm. /// - /// - /// public IObservable Process(IObservable source) { return source.Select(tensor => linalg.norm(tensor, dims: Dimensions, keepdim: Keepdim)); diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/QRDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/QRDecomposition.cs index 6e9c481e..fbfa3396 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/QRDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/QRDecomposition.cs @@ -23,8 +23,6 @@ public class QRDecomposition /// /// Computes the QR decomposition of a matrix. /// - /// - /// public IObservable Process(IObservable source) { return source.Select(tensor => new QRDecompositionResult(qr(tensor, mode: Mode))); diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs index c4b73950..60336ce5 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs @@ -5,7 +5,6 @@ namespace Bonsai.ML.Torch.LinearAlgebra; /// /// Represents the result of a QR decomposition. /// -/// public readonly struct QRDecompositionResult((Tensor Q, Tensor R) result) { /// diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs index 087e8141..e0ae2fda 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs @@ -17,8 +17,6 @@ public class SignLogDeterminant /// /// Computes the sign and natural logarithm of the absolute value of the determinant of a square matrix. /// - /// - /// public IObservable Process(IObservable source) { return source.Select(result => new SignLogDeterminantResult(linalg.slogdet(result))); diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminantResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminantResult.cs index 62f258ac..cf8315e8 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminantResult.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminantResult.cs @@ -5,7 +5,6 @@ namespace Bonsai.ML.Torch.LinearAlgebra; /// /// Represents the result of computing the sign and natural logarithm of the absolute value of the determinant. /// -/// public readonly struct SignLogDeterminantResult((Tensor sign, Tensor logabsdet) result) { /// diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs index d06e6a03..34c1b83e 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs @@ -22,8 +22,6 @@ public class SingularValueDecomposition /// /// Computes the singular value decomposition (SVD) of a matrix. /// - /// - /// public IObservable Process(IObservable source) { return source.Select(tensor => new SingularValueDecompositionResult(linalg.svd(tensor, fullMatrices: FullMatrices))); diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecompositionResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecompositionResult.cs index 01045881..3cfa1740 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecompositionResult.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecompositionResult.cs @@ -5,7 +5,6 @@ namespace Bonsai.ML.Torch.LinearAlgebra; /// /// Represents the result of a singular value decomposition. /// -/// public readonly struct SingularValueDecompositionResult(( Tensor u, Tensor s, diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs index 0b3c5417..2f52b885 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs @@ -35,8 +35,6 @@ public class SolveTriangular /// /// Computes the solution to a triangular system of linear equations for each pair of input tensors. /// - /// - /// public IObservable Process(IObservable> source) { return source.Select(value => diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs b/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs index c1a8cfa1..31c0d90f 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs @@ -24,8 +24,6 @@ public class TensorSolve /// /// Computes the solution to the system tensordot(A, X) = B. /// - /// - /// public IObservable Process(IObservable> source) { return source.Select(value => From aabfdecf2f71d911ded91c52cf9f9b16a388e923 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 18:02:15 +0100 Subject: [PATCH 21/33] Move MatrixMultiply operator to root namespace consistent with torch Co-authored-by: glopesdev --- .../{LinearAlgebra => }/MatrixMultiply.cs | 57 ++++++------------- 1 file changed, 17 insertions(+), 40 deletions(-) rename src/Bonsai.ML.Torch/{LinearAlgebra => }/MatrixMultiply.cs (57%) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs b/src/Bonsai.ML.Torch/MatrixMultiply.cs similarity index 57% rename from src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs rename to src/Bonsai.ML.Torch/MatrixMultiply.cs index 97d45f3e..203b5927 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixMultiply.cs +++ b/src/Bonsai.ML.Torch/MatrixMultiply.cs @@ -1,11 +1,11 @@ using System; +using System.Linq; using System.Collections.Generic; using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; -using static TorchSharp.torch.linalg; -namespace Bonsai.ML.Torch.LinearAlgebra; +namespace Bonsai.ML.Torch; /// /// Represents an operator that performs matrix multiplication of 2 or more tensors. @@ -20,7 +20,7 @@ public class MatrixMultiply /// public IObservable Process(IObservable> source) { - return source.Select(input =>input.Item1.matmul(input.Item2)); + return source.Select(input => input.Item1.matmul(input.Item2)); } /// @@ -28,10 +28,7 @@ public IObservable Process(IObservable> source) /// public IObservable Process(IObservable> source) { - return source.Select(input => - { - return multi_dot([input.Item1, input.Item2, input.Item3]); - }); + return source.Select(input => input.Item1.matmul(input.Item2).matmul(input.Item3)); } /// @@ -39,10 +36,7 @@ public IObservable Process(IObservable> so /// public IObservable Process(IObservable> source) { - return source.Select(input => - { - return multi_dot([input.Item1, input.Item2, input.Item3, input.Item4]); - }); + return source.Select(input => input.Item1.matmul(input.Item2).matmul(input.Item3).matmul(input.Item4)); } /// @@ -50,10 +44,7 @@ public IObservable Process(IObservable public IObservable Process(IObservable> source) { - return source.Select(input => - { - return multi_dot([input.Item1, input.Item2, input.Item3, input.Item4, input.Item5]); - }); + return source.Select(input => input.Item1.matmul(input.Item2).matmul(input.Item3).matmul(input.Item4).matmul(input.Item5)); } /// @@ -61,10 +52,7 @@ public IObservable Process(IObservable public IObservable Process(IObservable> source) { - return source.Select(input => - { - return multi_dot([input.Item1, input.Item2, input.Item3, input.Item4, input.Item5, input.Item6]); - }); + return source.Select(input => input.Item1.matmul(input.Item2).matmul(input.Item3).matmul(input.Item4).matmul(input.Item5).matmul(input.Item6)); } /// @@ -72,26 +60,7 @@ public IObservable Process(IObservable public IObservable Process(IObservable> source) { - return source.Select(input => - { - return multi_dot([input.Item1, input.Item2, input.Item3, input.Item4, input.Item5, input.Item6, input.Item7]); - }); - } - - /// - /// Performs matrix multiplication of an array of tensors. - /// - public IObservable Process(IObservable source) - { - return source.Select(multi_dot); - } - - /// - /// Performs matrix multiplication of a list of tensors. - /// - public IObservable Process(IObservable> source) - { - return source.Select(multi_dot); + return source.Select(input => input.Item1.matmul(input.Item2).matmul(input.Item3).matmul(input.Item4).matmul(input.Item5).matmul(input.Item6).matmul(input.Item7)); } /// @@ -99,6 +68,14 @@ public IObservable Process(IObservable> source) /// public IObservable Process(IObservable> source) { - return source.Select(input => multi_dot([.. input])); + return source.Select(input => + { + var result = input.FirstOrDefault(); + foreach (var tensor in input.Skip(1)) + { + result = result.matmul(tensor); + } + return result; + }); } } From 357fb3efccefb1f8d4b136a2de0fcd78b4b5da99 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 18:02:59 +0100 Subject: [PATCH 22/33] Add separate MultiDot operator for optimized matrix multiplication Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs new file mode 100644 index 00000000..335688d5 --- /dev/null +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Reactive.Linq; +using static TorchSharp.torch; +using static TorchSharp.torch.linalg; + +namespace Bonsai.ML.Torch.LinearAlgebra; + +/// +/// Represents an operator that performs optimized matrix multiplication of 2 or more tensors so that the fewest number +/// of operations are performed. +/// +/// +/// Every tensor in the input sequence must be 2D, except for the first or last tensor which may be 1D. If the first +/// tensor is 1D, it is treated as a row vector and if the last tensor is 1D, it is treated as a column vector. The +/// output will be 2D if both the first and last tensors are 2D, otherwise the output will be 1D. +/// +[Combinator] +[Description("Performs optimized matrix multiplication of 2 or more tensors using the multi_dot function.")] +[WorkflowElementCategory(ElementCategory.Transform)] +public class MultiDot +{ + /// + /// Performs optimized matrix multiplication of 2 tensors. + /// + public IObservable Process(IObservable> source) + { + return source.Select(input => multi_dot([input.Item1, input.Item2])); + } + + /// + /// Performs optimized matrix multiplication of 3 tensors. + /// + public IObservable Process(IObservable> source) + { + return source.Select(input => multi_dot([input.Item1, input.Item2, input.Item3])); + } + + /// + /// Performs optimized matrix multiplication of 4 tensors. + /// + public IObservable Process(IObservable> source) + { + return source.Select(input => multi_dot([input.Item1, input.Item2, input.Item3, input.Item4])); + } + + /// + /// Performs optimized matrix multiplication of 5 tensors. + /// + public IObservable Process(IObservable> source) + { + return source.Select(input => multi_dot([input.Item1, input.Item2, input.Item3, input.Item4, input.Item5])); + } + + /// + /// Performs optimized matrix multiplication of 6 tensors. + /// + public IObservable Process(IObservable> source) + { + return source.Select(input => multi_dot([input.Item1, input.Item2, input.Item3, input.Item4, input.Item5, input.Item6])); + } + + /// + /// Performs optimized matrix multiplication of 7 tensors. + /// + public IObservable Process(IObservable> source) + { + return source.Select(input => multi_dot([input.Item1, input.Item2, input.Item3, input.Item4, input.Item5, input.Item6, input.Item7])); + } + + /// + /// Performs optimized matrix multiplication of an enumerable of tensors. + /// + public IObservable Process(IObservable> source) + { + return source.Select(input => multi_dot([.. input])); + } +} From aea5210a6fa6a548ec3888a8a40f24a57c265d11 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 18:06:17 +0100 Subject: [PATCH 23/33] Refactor MultiDot to handle collections with less than two tensors Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs index 335688d5..68798a25 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Collections.Generic; using System.ComponentModel; using System.Reactive.Linq; @@ -74,6 +75,12 @@ public IObservable Process(IObservable public IObservable Process(IObservable> source) { - return source.Select(input => multi_dot([.. input])); + return source.Select(input => + { + if (input.Count() < 2) + return input.FirstOrDefault(); + + return multi_dot([.. input]); + }); } } From 6912521432680852e312544b77de7256ab041d4f Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 18:12:23 +0100 Subject: [PATCH 24/33] Remove explicit property initializers that default to the same value Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs | 6 +++--- src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs | 4 ++-- .../LinearAlgebra/SingularValueDecomposition.cs | 2 +- src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs index 818eadd8..9831fea2 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs @@ -18,19 +18,19 @@ public class MatrixRank /// Gets or sets the absolute tolerance for singular values to be considered non-zero. /// [Description("The absolute tolerance for singular values to be considered non-zero.")] - public double? AbsoluteTolerance { get; set; } = null; + public double? AbsoluteTolerance { get; set; } /// /// Gets or sets the relative tolerance for singular values to be considered non-zero. /// [Description("The relative tolerance for singular values to be considered non-zero.")] - public double? RelativeTolerance { get; set; } = null; + public double? RelativeTolerance { get; set; } /// /// Gets or sets whether to treat the input matrix as Hermitian if input is complex or symmetric if real. /// [Description("Whether to treat the input matrix as Hermitian if input is complex or symmetric if real.")] - public bool Hermitian { get; set; } = false; + public bool Hermitian { get; set; } /// /// Computes the numerical rank of a matrix. diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs b/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs index f091043b..801bb6a2 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs @@ -18,13 +18,13 @@ public class Norm /// [TypeConverter(typeof(UnidimensionalArrayConverter))] [Description("The dimensions along which to compute the norm.")] - public long[] Dimensions { get; set; } = null; + public long[]? Dimensions { get; set; } = null; /// /// Gets or sets whether the reduced dimensions are retained in the result as dimensions with size one. /// [Description("Whether the reduced dimensions are retained in the result as dimensions with size one.")] - public bool Keepdim { get; set; } = false; + public bool Keepdim { get; set; } /// /// Computes a matrix norm. diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs index 34c1b83e..6e42d0b6 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs @@ -17,7 +17,7 @@ public class SingularValueDecomposition /// Gets or sets whether to compute the full or reduced SVD. /// [Description("Whether to compute the full or reduced SVD.")] - public bool FullMatrices { get; set; } = false; + public bool FullMatrices { get; set; } = true; /// /// Computes the singular value decomposition (SVD) of a matrix. diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs index 2f52b885..1d97f873 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs @@ -30,7 +30,7 @@ public class SolveTriangular /// Gets or sets whether the first matrix has a unit diagonal, i.e., all diagonal elements are assumed to be 1. /// [Description("Whether the first matrix has a unit diagonal, i.e., all diagonal elements are assumed to be 1.")] - public bool UnitDiagonal { get; set; } = false; + public bool UnitDiagonal { get; set; } /// /// Computes the solution to a triangular system of linear equations for each pair of input tensors. From 9bc86a8f0e0ac0e0826fef307bf1bb6d529d6f57 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 18:14:05 +0100 Subject: [PATCH 25/33] Rename to camelCase Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs index 60336ce5..8f17c098 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/QRDecompositionResult.cs @@ -5,15 +5,15 @@ namespace Bonsai.ML.Torch.LinearAlgebra; /// /// Represents the result of a QR decomposition. /// -public readonly struct QRDecompositionResult((Tensor Q, Tensor R) result) +public readonly struct QRDecompositionResult((Tensor q, Tensor r) result) { /// /// The orthogonal matrix Q. /// - public Tensor Q => result.Q; + public Tensor Q => result.q; /// /// The upper triangular matrix R. /// - public Tensor R => result.R; + public Tensor R => result.r; } From a68138a829d1ed755fd597926a08dc7eb94fca4e Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 18:18:34 +0100 Subject: [PATCH 26/33] Rename input variable in lambda expression to tensor for clarity Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs index e0ae2fda..d16a91e4 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SignLogDeterminant.cs @@ -19,6 +19,6 @@ public class SignLogDeterminant /// public IObservable Process(IObservable source) { - return source.Select(result => new SignLogDeterminantResult(linalg.slogdet(result))); + return source.Select(tensor => new SignLogDeterminantResult(linalg.slogdet(tensor))); } } From 596498fb1145feba46780087cf3c0314e9a2191a Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 18:19:09 +0100 Subject: [PATCH 27/33] Improve doc strings for members of SingularValueDecompositionResult Co-authored-by: glopesdev --- .../LinearAlgebra/SingularValueDecompositionResult.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecompositionResult.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecompositionResult.cs index 3cfa1740..884e4a2c 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecompositionResult.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecompositionResult.cs @@ -12,7 +12,7 @@ Tensor vh ) result) { /// - /// The U tensor. + /// The unitary matrix with left singular vectors as columns. /// public Tensor U => result.u; @@ -22,7 +22,7 @@ Tensor vh public Tensor S => result.s; /// - /// The Vh tensor. + /// The unitary matrix with right singular vectors as rows. /// public Tensor Vh => result.vh; } From d5c7279d0b9a99983c132f1345844d380fa64f9d Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 19:03:14 +0100 Subject: [PATCH 28/33] Add using statement for TorchSharp.torch.linalg Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs index b1a8d62a..9bd3c7e9 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/EigenvalueDecomposition.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.Reactive.Linq; using static TorchSharp.torch; +using static TorchSharp.torch.linalg; namespace Bonsai.ML.Torch.LinearAlgebra; @@ -18,6 +19,6 @@ public class EigenvalueDecomposition /// public IObservable Process(IObservable source) { - return source.Select(tensor => new EigenvalueDecompositionResult(linalg.eig(tensor))); + return source.Select(tensor => new EigenvalueDecompositionResult(eig(tensor))); } } From 8e125ccd1b9206fcda890faf70ea21142515ddce Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 19:03:59 +0100 Subject: [PATCH 29/33] Add missing reference to tensor X in doc string Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs b/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs index 31c0d90f..7ee660b7 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs @@ -22,7 +22,7 @@ public class TensorSolve public long[] Dimensions { get; set; } = []; /// - /// Computes the solution to the system tensordot(A, X) = B. + /// Computes the solution X to the system tensordot(A, X) = B. /// public IObservable Process(IObservable> source) { From c6a361fabdacbfbc1a244fbbafbd6ed38e157ce1 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 19:24:45 +0100 Subject: [PATCH 30/33] Update docs strings and descriptions of boolean properties Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs | 6 +++++- src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs | 5 ++++- .../LinearAlgebra/SingularValueDecomposition.cs | 7 ++++++- .../LinearAlgebra/SolveTriangular.cs | 17 ++++++++++++++--- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs index 9831fea2..0ff58b60 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs @@ -29,7 +29,11 @@ public class MatrixRank /// /// Gets or sets whether to treat the input matrix as Hermitian if input is complex or symmetric if real. /// - [Description("Whether to treat the input matrix as Hermitian if input is complex or symmetric if real.")] + /// + /// True indicates that the input matrix is Hermitian if complex or symmetric if real; otherwise, the input matrix + /// is treated as a generic matrix. + /// + [Description("True indicates that the input matrix is Hermitian if complex or symmetric if real; otherwise, the input matrix is treated as a generic matrix.")] public bool Hermitian { get; set; } /// diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs b/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs index 801bb6a2..5564575c 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/Norm.cs @@ -23,7 +23,10 @@ public class Norm /// /// Gets or sets whether the reduced dimensions are retained in the result as dimensions with size one. /// - [Description("Whether the reduced dimensions are retained in the result as dimensions with size one.")] + /// + /// True indicates that the reduced dimensions are retained in the result as dimensions with size one; otherwise, the reduced dimensions are removed from the result. + /// + [Description("True indicates that the reduced dimensions are retained in the result as dimensions with size one; otherwise, the reduced dimensions are removed from the result.")] public bool Keepdim { get; set; } /// diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs index 6e42d0b6..55f5c909 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SingularValueDecomposition.cs @@ -16,7 +16,12 @@ public class SingularValueDecomposition /// /// Gets or sets whether to compute the full or reduced SVD. /// - [Description("Whether to compute the full or reduced SVD.")] + /// + /// True indicates that the full SVD is computed and the vector matrices U and Vh may be padded with extra columns/ + /// rows to make them square and unitary; otherwise, the reduced SVD is computed and the vector matrices U and Vh + /// have only the minimum number of columns/rows. + /// + [Description("True indicates that the full SVD is computed and the vector matrices U and Vh have extra columns/rows to make them unitary; otherwise, the reduced SVD is computed and the vector matrices U and Vh have the minimum number of columns/rows.")] public bool FullMatrices { get; set; } = true; /// diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs index 1d97f873..951ef6c3 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs @@ -17,19 +17,30 @@ public class SolveTriangular /// /// Gets or sets whether the first matrix is upper triangular. /// - [Description("Whether the first matrix is upper triangular.")] + /// + /// True indicates that the first matrix is upper triangular; otherwise, it is lower triangular. + /// + [Description("True indicates that the first matrix is upper triangular; otherwise, it is lower triangular.")] public bool Upper { get; set; } = true; /// /// Gets or sets whether to solve the system with the first matrix on the left or right (AX = B or XA = B). /// - [Description("Whether to solve the system with the first matrix on the left or right (AX = B or XA = B).")] + /// + /// True indicates that the system is solved with the first matrix on the left (AX = B); otherwise, it is solved + /// with the first matrix on the right (XA = B). + /// + [Description("True indicates that the system is solved with the first matrix on the left (AX = B); otherwise, it is solved with the first matrix on the right (XA = B).")] public bool Left { get; set; } = true; /// /// Gets or sets whether the first matrix has a unit diagonal, i.e., all diagonal elements are assumed to be 1. /// - [Description("Whether the first matrix has a unit diagonal, i.e., all diagonal elements are assumed to be 1.")] + /// + /// True indicates that the first matrix has a unit diagonal, i.e., all diagonal elements are assumed to be 1; + /// otherwise, the diagonal elements are used as-is. + /// + [Description("True indicates that the first matrix has a unit diagonal, i.e., all diagonal elements are assumed to be 1; otherwise, the diagonal elements are used as-is.")] public bool UnitDiagonal { get; set; } /// From 7646fc2847d0b965879b2291a93c6de1f1f1b3f1 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 19:43:29 +0100 Subject: [PATCH 31/33] Rename to tensor for single tensor input Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs index 0ff58b60..1fa1c761 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MatrixRank.cs @@ -41,6 +41,6 @@ public class MatrixRank /// public IObservable Process(IObservable source) { - return source.Select(input => matrix_rank(input, atol: AbsoluteTolerance, rtol: RelativeTolerance, hermitian: Hermitian)); + return source.Select(tensor => matrix_rank(tensor, atol: AbsoluteTolerance, rtol: RelativeTolerance, hermitian: Hermitian)); } } From 2912207d99a55a89bcf079d37cbfe06873cb1fb5 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 19:44:39 +0100 Subject: [PATCH 32/33] Rename input to value for multi tensor input Co-authored-by: glopesdev --- src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs | 20 +++++++++---------- src/Bonsai.ML.Torch/MatrixMultiply.cs | 18 ++++++++--------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs b/src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs index 68798a25..3c2aa883 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/MultiDot.cs @@ -27,7 +27,7 @@ public class MultiDot /// public IObservable Process(IObservable> source) { - return source.Select(input => multi_dot([input.Item1, input.Item2])); + return source.Select(value => multi_dot([value.Item1, value.Item2])); } /// @@ -35,7 +35,7 @@ public IObservable Process(IObservable> source) /// public IObservable Process(IObservable> source) { - return source.Select(input => multi_dot([input.Item1, input.Item2, input.Item3])); + return source.Select(value => multi_dot([value.Item1, value.Item2, value.Item3])); } /// @@ -43,7 +43,7 @@ public IObservable Process(IObservable> so /// public IObservable Process(IObservable> source) { - return source.Select(input => multi_dot([input.Item1, input.Item2, input.Item3, input.Item4])); + return source.Select(value => multi_dot([value.Item1, value.Item2, value.Item3, value.Item4])); } /// @@ -51,7 +51,7 @@ public IObservable Process(IObservable public IObservable Process(IObservable> source) { - return source.Select(input => multi_dot([input.Item1, input.Item2, input.Item3, input.Item4, input.Item5])); + return source.Select(value => multi_dot([value.Item1, value.Item2, value.Item3, value.Item4, value.Item5])); } /// @@ -59,7 +59,7 @@ public IObservable Process(IObservable public IObservable Process(IObservable> source) { - return source.Select(input => multi_dot([input.Item1, input.Item2, input.Item3, input.Item4, input.Item5, input.Item6])); + return source.Select(value => multi_dot([value.Item1, value.Item2, value.Item3, value.Item4, value.Item5, value.Item6])); } /// @@ -67,7 +67,7 @@ public IObservable Process(IObservable public IObservable Process(IObservable> source) { - return source.Select(input => multi_dot([input.Item1, input.Item2, input.Item3, input.Item4, input.Item5, input.Item6, input.Item7])); + return source.Select(value => multi_dot([value.Item1, value.Item2, value.Item3, value.Item4, value.Item5, value.Item6, value.Item7])); } /// @@ -75,12 +75,12 @@ public IObservable Process(IObservable public IObservable Process(IObservable> source) { - return source.Select(input => + return source.Select(value => { - if (input.Count() < 2) - return input.FirstOrDefault(); + if (value.Count() < 2) + return value.FirstOrDefault(); - return multi_dot([.. input]); + return multi_dot([.. value]); }); } } diff --git a/src/Bonsai.ML.Torch/MatrixMultiply.cs b/src/Bonsai.ML.Torch/MatrixMultiply.cs index 203b5927..ba698141 100644 --- a/src/Bonsai.ML.Torch/MatrixMultiply.cs +++ b/src/Bonsai.ML.Torch/MatrixMultiply.cs @@ -20,7 +20,7 @@ public class MatrixMultiply /// public IObservable Process(IObservable> source) { - return source.Select(input => input.Item1.matmul(input.Item2)); + return source.Select(value => value.Item1.matmul(value.Item2)); } /// @@ -28,7 +28,7 @@ public IObservable Process(IObservable> source) /// public IObservable Process(IObservable> source) { - return source.Select(input => input.Item1.matmul(input.Item2).matmul(input.Item3)); + return source.Select(value => value.Item1.matmul(value.Item2).matmul(value.Item3)); } /// @@ -36,7 +36,7 @@ public IObservable Process(IObservable> so /// public IObservable Process(IObservable> source) { - return source.Select(input => input.Item1.matmul(input.Item2).matmul(input.Item3).matmul(input.Item4)); + return source.Select(value => value.Item1.matmul(value.Item2).matmul(value.Item3).matmul(value.Item4)); } /// @@ -44,7 +44,7 @@ public IObservable Process(IObservable public IObservable Process(IObservable> source) { - return source.Select(input => input.Item1.matmul(input.Item2).matmul(input.Item3).matmul(input.Item4).matmul(input.Item5)); + return source.Select(value => value.Item1.matmul(value.Item2).matmul(value.Item3).matmul(value.Item4).matmul(value.Item5)); } /// @@ -52,7 +52,7 @@ public IObservable Process(IObservable public IObservable Process(IObservable> source) { - return source.Select(input => input.Item1.matmul(input.Item2).matmul(input.Item3).matmul(input.Item4).matmul(input.Item5).matmul(input.Item6)); + return source.Select(value => value.Item1.matmul(value.Item2).matmul(value.Item3).matmul(value.Item4).matmul(value.Item5).matmul(value.Item6)); } /// @@ -60,7 +60,7 @@ public IObservable Process(IObservable public IObservable Process(IObservable> source) { - return source.Select(input => input.Item1.matmul(input.Item2).matmul(input.Item3).matmul(input.Item4).matmul(input.Item5).matmul(input.Item6).matmul(input.Item7)); + return source.Select(value => value.Item1.matmul(value.Item2).matmul(value.Item3).matmul(value.Item4).matmul(value.Item5).matmul(value.Item6).matmul(value.Item7)); } /// @@ -68,10 +68,10 @@ public IObservable Process(IObservable public IObservable Process(IObservable> source) { - return source.Select(input => + return source.Select(value => { - var result = input.FirstOrDefault(); - foreach (var tensor in input.Skip(1)) + var result = value.FirstOrDefault(); + foreach (var tensor in value.Skip(1)) { result = result.matmul(tensor); } From 5591b3d44c863d5ba0eeef1144c041cb6d9ae112 Mon Sep 17 00:00:00 2001 From: ncguilbeault Date: Thu, 20 Aug 2026 19:45:03 +0100 Subject: [PATCH 33/33] Refactor to use simplified return statement --- src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs | 5 +---- src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs b/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs index 951ef6c3..5cac4300 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/SolveTriangular.cs @@ -48,9 +48,6 @@ public class SolveTriangular /// public IObservable Process(IObservable> source) { - return source.Select(value => - { - return solve_triangular(value.Item1, value.Item2, upper: Upper, left: Left, unitriangular: UnitDiagonal); - }); + return source.Select(value => solve_triangular(value.Item1, value.Item2, upper: Upper, left: Left, unitriangular: UnitDiagonal)); } } diff --git a/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs b/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs index 7ee660b7..0e0e9882 100644 --- a/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs +++ b/src/Bonsai.ML.Torch/LinearAlgebra/TensorSolve.cs @@ -26,9 +26,6 @@ public class TensorSolve /// public IObservable Process(IObservable> source) { - return source.Select(value => - { - return tensorsolve(value.Item1, value.Item2, Dimensions); - }); + return source.Select(value => tensorsolve(value.Item1, value.Item2, Dimensions)); } }