22
I Use This!
Low Activity

News

Analyzed about 8 hours ago. based on code collected 1 day ago.
Posted over 10 years ago
F# Interactive (FSI) is a very convenient environment to execute pieces of F# code on the fly. You can even reference managed assemblies using the #r and #I preprocessor directives. However, if one of the referenced assemblies tries to use a native ... [More] DLL using p/invoke you might end up with a DllNotFoundException even if the native DLL is in the same folder as the managed assembly, and if the folder has been included with the #I directive. Note that it is not possible to reference native DLLs explicitly in .Net. The reason is that finding and loading such DLLs in .Net works the same way as all native applications in Windows and follows the standard search order. When launched from within VisualStudio, the working directory of the F# Interactive process is the path where it is installed, in my case C:\Program Files (x86)\Microsoft SDKs\F#\3.0\Framework\v4.0. Naturally it has no chance to find a DLL in your script folder and fails. There are multiple ways how you can tell Windows where to look for the DLL: Any technique described here is only needed when using F# Interactive or run F# scripts, but not in normal compiled applications (where you’d just tell the IDE or build tool to copy the native DLLs to the output path) Change the Working Directory The simplest way is to set the process’ working directory to the directory where the DLL is located. If it is in the same place as your script file, you can do this with a one-liner: System.Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ Set Path Environment Variable Beside of the working directory, Windows also considers the Path environment variables to look for the DLL. Environment variables can be defined globally or on your user account, but also locally to a running process. You can append the path to the process-local Path variable like this: open System Environment.SetEnvironmentVariable("Path", Environment.GetEnvironmentVariable("Path") + ";" + __SOURCE_DIRECTORY__) Tell Windows: SetDllDirectory We can also tell Windows directly where to look by calling the SetDllDirectory function: open System.Runtime.InteropServices module Kernel = [] extern bool SetDllDirectory(string lpPathName); Kernel.SetDllDirectory(__SOURCE_DIRECTORY__) However, note that every time this method is called it overrides what was set in the last call. So this can work well for a while - until someone else within your process starts calling it as well. Load Explicitly: LoadLibrary If a library module with the same name is already loaded into memory, it will be used directly without even starting to look for it in the file system. We can leverage this by explicitly loading a library. For example, for the MKL extensions for Math.NET Numerics we could write: module Kernel = [] extern IntPtr LoadLibrary(string lpFileName); Kernel.LoadLibrary(Path.Combine(__SOURCE_DIRECTORY__, "libiomp5md")) Kernel.LoadLibrary(Path.Combine(__SOURCE_DIRECTORY__, "MathNet.Numerics.MKL.dll")) If you were writing this in a long running process where the DLL is used in a well defined section only, then you’d better unload the library once no longer needed with the symmetric FreeLibrary routine. But for quick experiments in F# Interactive it’s probably fine. Example: Enable the MKL native provider in Math.NET Numerics Math.NET Numerics provides a few code samples as a NuGet package. Ignoring for now that we really should add much more interesting, complete and applied examples (ideas and contributions are welcome!), these examples also do not currently leverage the Intel MKL native provider for faster linear algebra, so let’s change at least that. First get a copy of them: Create a new F# Console Application project Open the NuGet Package Manager Console and run Install-Package MathNet.Numerics.FSharp -Version 2.6.0 Install-Package MathNet.Numerics.FSharp.Sample -Version 2.6.0 Install-Package MathNet.Numerics.MKL.Win-x86 -Version 1.3.0 Open the Matrices.fsx file in Samples/MathNet.Numerics.FSharp Fix the MathNet.Numerics reference line to v2.6.1, or whatever package NuGet installed Now we would like to enable MKL and verify that it works. The native DLLs have already been copied to the project root directory by the NuGet package in step 2. Add the following lines right after the original 3 open-lines at the beginning of the file: open System open System.IO open MathNet.Numerics open MathNet.Numerics.Algorithms.LinearAlgebra.Mkl Control.LinearAlgebraProvider <- MklLinearAlgebraProvider() let m = matrix [[1.; 2.]; [3.; 4.]] let v = vector [4.;5.] m.LU().Solve(v) If you try to execute this line by line, the last line calling LU and Solve will try to use MKL and fail with a DllNotFoundException as expected. Let’s try to use the environment variables approach by adding the following lines after the open-lines. Our script is two directories down from the project root directory, so we have to fix the path accordingly: Environment.SetEnvironmentVariable("Path", Environment.GetEnvironmentVariable("Path") + ";" + Path.Combine(__SOURCE_DIRECTORY__,@"..\..\")) And suddenly it works. If it does not and you get a BadImageFormatException, you may have switched F# Interactive to run in 64-bit mode. In this case you should install the MKL.Win-x64 package instead of the x86 one. PS: We’re trying to simplify this in the upcoming v3 release so there is only one package for both platforms and it automatically loads the right one. Maybe we can also do something about this whole ‘telling windows where to find the DLLs’ thing while we’re at it… [Less]
Posted over 10 years ago
F# Interactive (FSI) is a very convenient environment to execute pieces of F# code on the fly. You can even reference managed assemblies using the #r and #I preprocessor directives. However, if one of the referenced assemblies tries to use a native ... [More] DLL using p/invoke you might end up with a DllNotFoundException even if the native DLL is in the same folder as the managed assembly, and if the folder has been included with the #I directive. Note that it is not possible to reference native DLLs explicitly in .Net. The reason is that finding and loading such DLLs in .Net works the same way as all native applications in Windows and follows the standard search order. When launched from within VisualStudio, the working directory of the F# Interactive process is the path where it is installed, in my case C:\Program Files (x86)\Microsoft SDKs\F#\3.0\Framework\v4.0. Naturally it has no chance to find a DLL in your script folder and fails. There are multiple ways how you can tell Windows where to look for the DLL: Any technique described here is only needed when using F# Interactive or run F# scripts, but not in normal compiled applications (where you’d just tell the IDE or build tool to copy the native DLLs to the output path) Change the Working Directory The simplest way is to set the process’ working directory to the directory where the DLL is located. If it is in the same place as your script file, you can do this with a one-liner: System.Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ Set Path Environment Variable Beside of the working directory, Windows also considers the Path environment variables to look for the DLL. Environment variables can be defined globally or on your user account, but also locally to a running process. You can append the path to the process-local Path variable like this: open System Environment.SetEnvironmentVariable("Path", Environment.GetEnvironmentVariable("Path") + ";" + __SOURCE_DIRECTORY__) Tell Windows: SetDllDirectory We can also tell Windows directly where to look by calling the SetDllDirectory function: open System.Runtime.InteropServices module Kernel = [<DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)>] extern bool SetDllDirectory(string lpPathName); Kernel.SetDllDirectory(__SOURCE_DIRECTORY__) However, note that every time this method is called it overrides what was set in the last call. So this can work well for a while - until someone else within your process starts calling it as well. Load Explicitly: LoadLibrary If a library module with the same name is already loaded into memory, it will be used directly without even starting to look for it in the file system. We can leverage this by explicitly loading a library. For example, for the MKL extensions for Math.NET Numerics we could write: module Kernel = [<DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)>] extern IntPtr LoadLibrary(string lpFileName); Kernel.LoadLibrary(Path.Combine(__SOURCE_DIRECTORY__, "libiomp5md")) Kernel.LoadLibrary(Path.Combine(__SOURCE_DIRECTORY__, "MathNet.Numerics.MKL.dll")) If you were writing this in a long running process where the DLL is used in a well defined section only, then you’d better unload the library once no longer needed with the symmetric FreeLibrary routine. But for quick experiments in F# Interactive it’s probably fine. Example: Enable the MKL native provider in Math.NET Numerics Math.NET Numerics provides a few code samples as a NuGet package. Ignoring for now that we really should add much more interesting, complete and applied examples (ideas and contributions are welcome!), these examples also do not currently leverage the Intel MKL native provider for faster linear algebra, so let’s change at least that. First get a copy of them: Create a new F# Console Application project Open the NuGet Package Manager Console and run Install-Package MathNet.Numerics.FSharp -Version 2.6.0 Install-Package MathNet.Numerics.FSharp.Sample -Version 2.6.0 Install-Package MathNet.Numerics.MKL.Win-x86 -Version 1.3.0 Open the Matrices.fsx file in Samples/MathNet.Numerics.FSharp Fix the MathNet.Numerics reference line to v2.6.1, or whatever package NuGet installed Now we would like to enable MKL and verify that it works. The native DLLs have already been copied to the project root directory by the NuGet package in step 2. Add the following lines right after the original 3 open-lines at the beginning of the file: open System open System.IO open MathNet.Numerics open MathNet.Numerics.Algorithms.LinearAlgebra.Mkl Control.LinearAlgebraProvider <- MklLinearAlgebraProvider() let m = matrix [[1.; 2.]; [3.; 4.]] let v = vector [4.;5.] m.LU().Solve(v) If you try to execute this line by line, the last line calling LU and Solve will try to use MKL and fail with a DllNotFoundException as expected. Let’s try to use the environment variables approach by adding the following lines after the open-lines. Our script is two directories down from the project root directory, so we have to fix the path accordingly: Environment.SetEnvironmentVariable("Path", Environment.GetEnvironmentVariable("Path") + ";" + Path.Combine(__SOURCE_DIRECTORY__,@"..\..\")) And suddenly it works. If it does not and you get a BadImageFormatException, you may have switched F# Interactive to run in 64-bit mode. In this case you should install the MKL.Win-x64 package instead of the x86 one. PS: We’re trying to simplify this in the upcoming v3 release so there is only one package for both platforms and it automatically loads the right one. Maybe we can also do something about this whole ‘telling windows where to find the DLLs’ thing while we’re at it… [Less]
Posted over 10 years ago
Math.NET Numerics is well on its way towards the next major release, v3.0. A first preview alpha has already been pushed to the NuGet gallery, even though there’s still a lot to do. If you’d like to understand a bit better where we currently are ... [More] , where we’re heading to, and why, then read on. Why a new major release? We apply the principles of semantic versioning, meaning that we are not supposed to break any parts of the public surface of the library, which is almost everything in our case, during minor releases (with the 3-part version format major.minor.patch). This makes sure you can easily upgrade within minor releases without second thoughts or breaking any of your code. Nevertheless, sometimes there really is a good reason to change the design, because it is way to complicated to use, inconsistent, leads to bad performance or was just not very well thought out. Or we simply learned how to do it in a much better way. You may have noticed that some members have been declared as obsolete over the last couple minor releases, with suggestions how to do it instead, even though the old implementation was kept intact. Over the time all that old code became a pain to maintain, and using the library was much more complicated than needed. So I decided it’s time to finally fix most of these issues and clean up. We do move some cheese around in this release. Your code will break in a few occasions. But in all cases a fix should be easy if not trivial. Also, once there we will again be bound by semantic versioning to keep the library stable over all future minor releases and thus likely for years to come. Also, we may keep providing patches for the old v2 branch if needed for a while. Nevertheless, I strongly recommend to upgrade to v3 once available. Feedback is welcome A first preview (v3.0.0-alpha1) has already been published to NuGet and I plan to do at least two more preview releases before we reach the first v3.0 release. Please do have a look at it and give feedback - now is a unique possibility for breaking changes. Overview on what has been done so far Namespace simplifications. More functional design where appropriate. Make sure everything works fine and feels native in both C# and F#. Use common short names if well known instead of very long full names (trigonometry). Linear Algebra: Using the generic types is the recommended way now; make sure it works well. The IO classes for matrix/vector serialization become separate packages. Major refactoring of the iterative solvers. Filled some missing pieces, various simplifications, lots of other changes. Distributions: Major cleanup. Direct exposure of distributions functions (pdf, cdf, etc). Parameter Estimation. New distance functions Overview on what is planned to do Iterative solvers need more work. I’d also like to design them such that they can be iterated manually, in a simple way. Integral transformations (FFT etc) need major refactoring. Backed by native provider if possible. Consider to bring back filtering (FIR, IIR, moving average, etc.) The current QR-decomposition-based curve fitting is inefficient for large data sets, but fixing it is actually not very complicated. Investigate and fix an inconsistency in the Precision class. Drop redundant null-checks Details on what’s new in version 3 so far Dropping .Algorithms Namespaces Did you ever have to open 10 different Math.NET Numerics namespaces to get all you need? This should get somewhat better in v3, as the static facades like Integrate, Interpolate, Fit or FindRoots for simple cases have been moved directly to the root namespace MathNet.Numerics and all the algorithms namespaces (for advanced uses) of the form MathNet.Numerics.X.Algorithms are now simply MathNet.Numerics.X. Interpolation In addition to the simplified namespaces, the last Differentiate overload that returns all the interpolated value and the first and second derivative at some point x has been simplified: instead of two out-parameters in an unexpected order it now returns a tuple with reasonable ordering. Integration The design of the double-exponential transformation was rather weird. It has been simplified to a static class and is much simpler to use explicitly. Probability Distributions Although it was always possible to assign a custom random source (RNG) to a distribution for random number sampling, it was somewhat complicated and required two steps. Now all distribution constructors have an overload accepting a custom random source directly at construction, in a single step. A few distributions now support maximum-likelihood parameter estimation and most distributions implement an inverse cumulative distribution function. Distribution functions like PDF, CDF and InvCDF are now exposed directly as static functions. The inline documentation and parameter naming has been improved significantly. ChiSquare became ChiSquared, and the IDistribution interface became IUnivariateDistribution. Simpler more composeable random sampling in F# with new Sample module. New Distance functions Standard routines for evaluating the Euclidean, Manhattan and Chebychev distances between arrays or vectors, also for the common Sum of Absolute Difference (SAD), Mean-Absolute Error (MAE), Sum of Squared Difference (SSD) and Mean-Squared Error (MSE) metrics. Hamming distance. Leveraging providers where appropriate. Less null checks and ArgumentNullExceptions Likely as a side effect from my exposure to functional programming over the last year, I no longer follow the arguments why in C# every routine must explicitly check all arguments for null. I’ve already dropped a few of these checks, but there are still more than 2000 places where Math.NET Numerics throws an ArgumentNullException. Most of these will likely be gone. There is one case where it does make sense to keep them though: when a routine accepts an argument but does not use it immediately (and therefore does not cause an immediate NullReferenceException), a null reference sneaking in could be hard to debug, so we’ll keep the check. But such cases are quite rare given the nature of the library. IO Library The IO library that used to be distributed as part of the core package is now a set of separate NuGet packages, e.g. MathNet.Numerics.Data.Text, and lives in a separate repository. Favoring generic linear algebra types Since the generic namespace was required all the time anyway and the recommended happy path is now to always use the generic types, everything from the .Generic namespace has been moved one namespace up. From now on you usually only need to open two namespaces when working with linear algebra, even if factorizations are needed. For example, when using the double type, you’d open MathNet.Numerics.LinearAlgebra and MathNet.Numerics.LinearAlgebra.Double. Since typing is stronger in F#, all the init/create functions in the F# module now directly return generic types so you don’t have to upcast manually all the time. Most routines have been generalized to work on generic types. For cases where you want to implement generic algorithms but also need to create new dense or sparse matrices or vectors a new generic builder has been added. This should rarely be needed in user code though. Missing scalar-matrix routines A few missing scalar-matrix routines like adding or subtracting a scalar to a matrix or dividing a scalar by a matrix have been added, backed by providers where possible. There’s now also a modulus routine. Point-wise infix operators where supported (F#) We’ve added point-wise .*, ./ and .% operators to matrices and vectors in the core library. This is not supported in all .Net languages yet, but works fine in F# even though without currying support. Of course in the other languages you can continue to use the normal methods as before. Factorization and Iterative Solvers Previously matrix factorization was only accessible by extension methods or explicit creation, which did not work very well when using generic types. The generic matrix type now provides methods to create them directly. As such, the actual implementations have been internalized as there is no longer any need for direct access. The QR factorization is now thin by default, and factorizations no longer clone their results for no practical reason. The iterative solver design has been significantly simplified and is now generic and shared where possible and accepts generic types everywhere. The namespaces are now much more flat as the very detailed structure did not add any value but meant you had to open a dozen namespaces. Misc linear algebra improvements Vectors now have a ConjugateDotProduct routine in addition to DotProduct. Vectors now explicitly provide proper L1, L2 and infinity norms Matrices/Vectors now have consistent enumerators, with a variant that skips zeros (useful if sparse). Matrix/Vector creation routines have been simplified and usually no longer require explicit dimensions. New variants to create diagonal matrices, or such where all fields have the same value. Matrices/Vectors expose whether storage is dense with a new IsDense property. Providers have been moved to a Providers namespace and are fully generic again. Misc More robust complex Asin/Acos for large real numbers. Trig functions: common short names instead of very long names. Complex: common short names for Exp, Ln, Log10, Log. Statistics: new single-pass MeanVariance method (as used often together). [Less]
Posted over 10 years ago
Math.NET Numerics is well on its way towards the next major release, v3.0. A first preview alpha has already been pushed to the NuGet gallery, even though there’s still a lot to do. If you’d like to understand a bit better where we currently are ... [More] , where we’re heading to, and why, then read on. Why a new major release? We apply the principles of semantic versioning, meaning that we are not supposed to break any parts of the public surface of the library, which is almost everything in our case, during minor releases (with the 3-part version format major.minor.patch). This makes sure you can easily upgrade within minor releases without second thoughts or breaking any of your code. Nevertheless, sometimes there really is a good reason to change the design, because it is way to complicated to use, inconsistent, leads to bad performance or was just not very well thought out. Or we simply learned how to do it in a much better way. You may have noticed that some members have been declared as obsolete over the last couple minor releases, with suggestions how to do it instead, even though the old implementation was kept intact. Over the time all that old code became a pain to maintain, and using the library was much more complicated than needed. So I decided it’s time to finally fix most of these issues and clean up. We do move some cheese around in this release. Your code will break in a few occasions. But in all cases a fix should be easy if not trivial. Also, once there we will again be bound by semantic versioning to keep the library stable over all future minor releases and thus likely for years to come. Also, we may keep providing patches for the old v2 branch if needed for a while. Nevertheless, I strongly recommend to upgrade to v3 once available. Feedback is welcome A first preview (v3.0.0-alpha1) has already been published to NuGet and I plan to do at least two more preview releases before we reach the first v3.0 release. Please do have a look at it and give feedback - now is a unique possibility for breaking changes. Overview on what has been done so far Namespace simplifications. More functional design where appropriate. Make sure everything works fine and feels native in both C# and F#. Use common short names if well known instead of very long full names (trigonometry). Linear Algebra: Using the generic types is the recommended way now; make sure it works well. The IO classes for matrix/vector serialization become separate packages. Major refactoring of the iterative solvers. Filled some missing pieces, various simplifications, lots of other changes. Distributions: Major cleanup. Direct exposure of distributions functions (pdf, cdf, etc). Parameter Estimation. New distance functions Overview on what is planned to do Iterative solvers need more work. I’d also like to design them such that they can be iterated manually, in a simple way. Integral transformations (FFT etc) need major refactoring. Backed by native provider if possible. Consider to bring back filtering (FIR, IIR, moving average, etc.) The current QR-decomposition-based curve fitting is inefficient for large data sets, but fixing it is actually not very complicated. Investigate and fix an inconsistency in the Precision class. Drop redundant null-checks Details on what’s new in version 3 so far Dropping .Algorithms Namespaces Did you ever have to open 10 different Math.NET Numerics namespaces to get all you need? This should get somewhat better in v3, as the static facades like Integrate, Interpolate, Fit or FindRoots for simple cases have been moved directly to the root namespace MathNet.Numerics and all the algorithms namespaces (for advanced uses) of the form MathNet.Numerics.X.Algorithms are now simply MathNet.Numerics.X. Interpolation In addition to the simplified namespaces, the last Differentiate overload that returns all the interpolated value and the first and second derivative at some point x has been simplified: instead of two out-parameters in an unexpected order it now returns a tuple with reasonable ordering. Integration The design of the double-exponential transformation was rather weird. It has been simplified to a static class and is much simpler to use explicitly. Probability Distributions Although it was always possible to assign a custom random source (RNG) to a distribution for random number sampling, it was somewhat complicated and required two steps. Now all distribution constructors have an overload accepting a custom random source directly at construction, in a single step. A few distributions now support maximum-likelihood parameter estimation and most distributions implement an inverse cumulative distribution function. Distribution functions like PDF, CDF and InvCDF are now exposed directly as static functions. The inline documentation and parameter naming has been improved significantly. ChiSquare became ChiSquared, and the IDistribution interface became IUnivariateDistribution. Simpler more composeable random sampling in F# with new Sample module. New Distance functions Standard routines for evaluating the Euclidean, Manhattan and Chebychev distances between arrays or vectors, also for the common Sum of Absolute Difference (SAD), Mean-Absolute Error (MAE), Sum of Squared Difference (SSD) and Mean-Squared Error (MSE) metrics. Hamming distance. Leveraging providers where appropriate. Less null checks and ArgumentNullExceptions Likely as a side effect from my exposure to functional programming over the last year, I no longer follow the arguments why in C# every routine must explicitly check all arguments for null. I’ve already dropped a few of these checks, but there are still more than 2000 places where Math.NET Numerics throws an ArgumentNullException. Most of these will likely be gone. There is one case where it does make sense to keep them though: when a routine accepts an argument but does not use it immediately (and therefore does not cause an immediate NullReferenceException), a null reference sneaking in could be hard to debug, so we’ll keep the check. But such cases are quite rare given the nature of the library. IO Library The IO library that used to be distributed as part of the core package is now a set of separate NuGet packages, e.g. MathNet.Numerics.Data.Text, and lives in a separate repository. Favoring generic linear algebra types Since the generic namespace was required all the time anyway and the recommended happy path is now to always use the generic types, everything from the .Generic namespace has been moved one namespace up. From now on you usually only need to open two namespaces when working with linear algebra, even if factorizations are needed. For example, when using the double type, you’d open MathNet.Numerics.LinearAlgebra and MathNet.Numerics.LinearAlgebra.Double. Since typing is stronger in F#, all the init/create functions in the F# module now directly return generic types so you don’t have to upcast manually all the time. Most routines have been generalized to work on generic types. For cases where you want to implement generic algorithms but also need to create new dense or sparse matrices or vectors a new generic builder has been added. This should rarely be needed in user code though. Missing scalar-matrix routines A few missing scalar-matrix routines like adding or subtracting a scalar to a matrix or dividing a scalar by a matrix have been added, backed by providers where possible. There’s now also a modulus routine. Point-wise infix operators where supported (F#) We’ve added point-wise .*, ./ and .% operators to matrices and vectors in the core library. This is not supported in all .Net languages yet, but works fine in F# even though without currying support. Of course in the other languages you can continue to use the normal methods as before. Factorization and Iterative Solvers Previously matrix factorization was only accessible by extension methods or explicit creation, which did not work very well when using generic types. The generic matrix type now provides methods to create them directly. As such, the actual implementations have been internalized as there is no longer any need for direct access. The QR factorization is now thin by default, and factorizations no longer clone their results for no practical reason. The iterative solver design has been significantly simplified and is now generic and shared where possible and accepts generic types everywhere. The namespaces are now much more flat as the very detailed structure did not add any value but meant you had to open a dozen namespaces. Misc linear algebra improvements Vectors now have a ConjugateDotProduct routine in addition to DotProduct. Vectors now explicitly provide proper L1, L2 and infinity norms Matrices/Vectors now have consistent enumerators, with a variant that skips zeros (useful if sparse). Matrix/Vector creation routines have been simplified and usually no longer require explicit dimensions. New variants to create diagonal matrices, or such where all fields have the same value. Matrices/Vectors expose whether storage is dense with a new IsDense property. Providers have been moved to a Providers namespace and are fully generic again. Misc More robust complex Asin/Acos for large real numbers. Trig functions: common short names instead of very long names. Complex: common short names for Exp, Ln, Log10, Log. Statistics: new single-pass MeanVariance method (as used often together). [Less]
Posted over 10 years ago
Math.NET Numerics v2.6, released in July 2013, is focused on filling some gaps around the very basic numerical problems of fitting a curve to data and finding solutions of nonlinear equations. As usual you’ll find a full listing of all changes in ... [More] the release notes. However, I’d like to take the chance to highlight some important changes, show some code samples and explain the reasoning behind the changes. A lot of high quality code contributions made this release possible. Just like last release, I’ve tried to attribute them directly in the release notes. Thanks again! Please let me know if these “What’s New” articles are useful in this format and whether I should continue to put the together for future releases. See also what’s new in the previous version 2.5. Linear Curve Fitting Fitting a linear-parametric curve to a set of samples such that the squared errors are minimal has always been possible with the linear algebra toolkit, but it was somewhat complicated to do and required understanding of the algorithm. See Linear Regression with Math.NET Numerics for an introduction and some examples. Note: if you need to have the curve go exactly through all your data points, use our Interpolation routines instead. We now finally provide a shortcut with a few common functions to fit to data, but also a method to fit a linear combination of arbitrary functions. For fitting a simple line it uses an efficient direct algorithm: var x = new [] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 }; var y = new [] { 4.986, 2.347, 2.061, -2.995, 2.352, -5.782 } C#: var p = Fit.Line(x, y); var offset = p[0]; // = 7.01013 var slope = p[1]; // = -2.08551 F#: let offset, slope = Fit.line x y Otherwise it usually applies an ordinary least squares regression to find the best parameters using a thin QR decomposition (leveraging a native provider like Intel MKL if enabled). This also works with arbitrary functions, like sine and cosine: F#: let p = (x, y) ||> Fit.linear [(fun _ -> 1.0); (Math.Sin); (Math.Cos)] C#: var p = Fit.LinearCombination(x, y, z => 1.0, Math.Sin, Math.Cos); // p = [ -0.287, 4.02, -1.46 ], hence f: x -> -0.287 + 4.02*sin(x) - 1.46*cos(x) The intention is to add more special cases for common curves like the logistic function in the future. Like the line they may have more appropriate direct implementations. For now there is one other special case, for fitting to a polynomial. It returns the best parameters, in ascending order (coefficient for power k has index k) compatible to the Evaluate.Polynomial routine: C#: var coeff = Fit.Polynomial(x, y, 2); // order 2 Evaluate.Polynomial(1.2, coeff); // ... F#: let coeff = Fit.polynomial 2 x y In practice your x values are not always just real numbers. Maybe you need multi-dimensional fitting where the x values are actually arrays, or even full data structures. For such cases we provide a version that is generic in x and where you can provide a list of functions that accept such x directly without the need to convert to an intermediate double vector first: C#: var p = Fit.LinearMultiDim(xarrays, y, f1, f2, f3, ...); var p = Fit.LinearGeneric(xstructs, y, f1, f2, f3, ...); F#: let p = Fit.linear [f1; f2; f3; ...] xgeneric y Often after evaluating the best fitting linear parameters you’d actually want to evaluate the function with those parameters. For this scenario we provide a shortcut as well: For each of these methods there is also a version with a “Func” suffix (“F” in F#) which, instead of the parameters, returns the composed function: F#: let f = Fit.lineF x y [1.0..0.1..2.0] |> List.map f C#: var f = Fit.LinearCombinationFunc(x, y, z => z*z, Math.Sin, SpecialFunctions.Gamma); Enumerable.Range(0,11).Select(x => f(x/10.0)) Root Finding We now provide basic root finding algorithms. A root of a function x -> f(x) is a solution of the equation f(x)=0. Root-finding algorithms can thus help finding numerical real solutions of arbitrary equations, provided f is reasonably well-behaved and we already have an idea about an interval [a,b] where we expect a root. As usual, there is a facade class FindRoots for simple scenarios: The routines usually expect a lower and upper boundary as parameters, and then optionally the accuracy we try to achieve and the maximum number of iterations. C#: FindRoots.OfFunction(x => x*x - 4, -5, 5) // -2.00000000046908 C#: FindRoots.OfFunction(x => x*x - 4, -5, 5, accuracy: 1e-14) // -2 (exact) C#: FindRoots.OfFunctionDerivative(x => x*x - 4, x => 2*x, -5, 5) // -2 (exact) F#: FindRoots.ofFunction -5.0 5.0 (fun x -> x*x - 4.0) F#: FindRoots.ofFunctionDerivative -5.0 5.0 (fun x -> x*x - 4.0) (fun x -> 2.0*x) A NonConvergenceException is thrown if no root can be found by the algorithm. In practice you’d often want to use a specific well-known algorithm. You’ll find them in the RootFinding namespace. Each of these algorithm provides a FindRoot method with similar arguments as those above. However, the algorithms may sometimes fail to find a root or the function may not actually have a root within the provided interval. Failing to find a root is thus not exactly exceptional. That’s why the algorithms also provide an exception-free TryFindRoot code path with the common Try-pattern as in TryParse. Bisection A simple and robust yet rather slow algorithm, implemented in the Bisection class. Example: Find the real roots of the cubic polynomial 2x^3 + 4x^2 - 50x + 6: Func<double, double> f = x => Evaluate.Polynomial(x, 6, -50, 4, 2); Bisection.FindRoot(f, -6.5, -5.5, 1e-8, 100); // -6.14665621970684 Bisection.FindRoot(f, -0.5, 0.5, 1e-8, 100); // 0.121247371972135 Bisection.FindRoot(f, 3.5, 4.5, 1e-8, 100); // 4.02540884774855 F#: f |> FindRoots.bisection 100 1e-8 3.5 4.5 // Some(4.0254..) Note that the F# function returns a float option. Instead of throwing an exception it will simply return None if it fails. Brent’s Method We use Brent’s method as default algorithm, implemented in the Brent class. Brent’s method is faster than bisection, but falls back to something close to bisection if the faster approaches (essentially the secant method and inverse quadratic interpolation) fails and is therefore almost as reliable. The same example as above, but using Brent’s method: Func<double, double> f = x => Evaluate.Polynomial(x, 6, -50, 4, 2); Brent.FindRoot(f, -6.5, -5.5, 1e-8, 100); // -6.14665621970684 Brent.FindRoot(f, -0.5, 0.5, 1e-8, 100); // 0.121247371972135 Brent.FindRoot(f, 3.5, 4.5, 1e-8, 100); // 4.02540884774855 F#: f |> FindRoots.brent 100 1e-8 3.5 4.5 // Some(4.0254..) Note that there are better algorithms for finding all roots of a polynomial. We plan to add specific polynomial root finding algorithms later on. Newton-Raphson The Newton-Raphson method leverages the function’s first derivative to converge much faster, but can also fail completely. The pure Newton-Raphson algorithm is implemented in the NewtonRaphson class. However, we also provide a modified algorithm that tries to recover (instead of just failing) when overshooting, converging too slowly or even when loosing bracketing in the presence of a pole. This modified algorithms is available in the RobustNewtonRaphson class. Example: Assume we want to find solutions of x+1/(x-2) == -2, hence x -> f(x) = 1/(x-2)+x+2 with a pole at x==2: Func<double, double> f = x => 1/(x - 2) + x + 2; Func<double, double> df = x => -1/(x*x - 4*x + 4) + 1; RobustNewtonRaphson.FindRoot(f, df, -2, -1, 1e-14, 100, 20); // -1.73205080756888 RobustNewtonRaphson.FindRoot(f, df, 1, 1.99, 1e-14, 100, 20); // 1.73205080756888 RobustNewtonRaphson.FindRoot(f, df, -1.5, 1.99, 1e-14, 100, 20); // 1.73205080756888 RobustNewtonRaphson.FindRoot(f, df, 1, 6, 1e-14, 100, 20); // 1.73205080756888 F#: FindRoots.newtonRaphsonRobust 100 20 1e-14 1.0 6.0 f df F#: (f, df) ||> FindRoots.newtonRaphsonRobust 100 20 1e-14 1.0 6.0 Broyden’s Method The quasi-newton method by Broyden, implemented in the Broyden class, may help you to find roots in multi-dimensional problems. Linear Algebra As usual there have been quite a few improvements around linear algebra, see the release notes for the complete list. If you’ve enabled our Intel MKL native linear algebra provider, then eigenvalue decompositions should be much faster now. Matrices now also support the new F# 3.1 array slicing syntax. Note that we’re phasing out the MathNet.Numerics.IO library and namespace and plan to drop it entirely in v3. We’ve already replaced it with two new separate NuGet packages and obsoleted all members of the old library. The new approach with separate libraries makes it possible to introduce specific dependencies e.g. to read and write Excel files, without forcing these dependencies on all of Math.NET Numerics. We recommend to switch over to the new packages as soon as possible. Statistics We’ve had a Pearson correlation coefficient routine for a while, but no Covariance routine. In addition to a new Spearman ranked correlation routine, this release finally also adds sample and population Covariance functions for arrays and IEnumerables. ArrayStatistics.Covariance(new[] {1.2, 1.3, 2.4}, new[] {2.2, 2.3, -4.5}) [Less]
Posted over 10 years ago
Math.NET Numerics v2.6, released in July 2013, is focused on filling some gaps around the very basic numerical problems of fitting a curve to data and finding solutions of nonlinear equations. As usual you’ll find a full listing of all changes in ... [More] the release notes. However, I’d like to take the chance to highlight some important changes, show some code samples and explain the reasoning behind the changes. A lot of high quality code contributions made this release possible. Just like last release, I’ve tried to attribute them directly in the release notes. Thanks again! Please let me know if these “What’s New” articles are useful in this format and whether I should continue to put the together for future releases. See also what’s new in the previous version 2.5. Linear Curve Fitting Fitting a linear-parametric curve to a set of samples such that the squared errors are minimal has always been possible with the linear algebra toolkit, but it was somewhat complicated to do and required understanding of the algorithm. See Linear Regression with Math.NET Numerics for an introduction and some examples. Note: if you need to have the curve go exactly through all your data points, use our Interpolation routines instead. We now finally provide a shortcut with a few common functions to fit to data, but also a method to fit a linear combination of arbitrary functions. For fitting a simple line it uses an efficient direct algorithm: var x = new [] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 }; var y = new [] { 4.986, 2.347, 2.061, -2.995, 2.352, -5.782 } C#: var p = Fit.Line(x, y); var offset = p[0]; // = 7.01013 var slope = p[1]; // = -2.08551 F#: let offset, slope = Fit.line x y Otherwise it usually applies an ordinary least squares regression to find the best parameters using a thin QR decomposition (leveraging a native provider like Intel MKL if enabled). This also works with arbitrary functions, like sine and cosine: F#: let p = (x, y) ||> Fit.linear [(fun _ -> 1.0); (Math.Sin); (Math.Cos)] C#: var p = Fit.LinearCombination(x, y, z => 1.0, Math.Sin, Math.Cos); // p = [ -0.287, 4.02, -1.46 ], hence f: x -> -0.287 + 4.02*sin(x) - 1.46*cos(x) The intention is to add more special cases for common curves like the logistic function in the future. Like the line they may have more appropriate direct implementations. For now there is one other special case, for fitting to a polynomial. It returns the best parameters, in ascending order (coefficient for power k has index k) compatible to the Evaluate.Polynomial routine: C#: var coeff = Fit.Polynomial(x, y, 2); // order 2 Evaluate.Polynomial(1.2, coeff); // ... F#: let coeff = Fit.polynomial 2 x y In practice your x values are not always just real numbers. Maybe you need multi-dimensional fitting where the x values are actually arrays, or even full data structures. For such cases we provide a version that is generic in x and where you can provide a list of functions that accept such x directly without the need to convert to an intermediate double vector first: C#: var p = Fit.LinearMultiDim(xarrays, y, f1, f2, f3, ...); var p = Fit.LinearGeneric(xstructs, y, f1, f2, f3, ...); F#: let p = Fit.linear [f1; f2; f3; ...] xgeneric y Often after evaluating the best fitting linear parameters you’d actually want to evaluate the function with those parameters. For this scenario we provide a shortcut as well: For each of these methods there is also a version with a “Func” suffix (“F” in F#) which, instead of the parameters, returns the composed function: F#: let f = Fit.lineF x y [1.0..0.1..2.0] |> List.map f C#: var f = Fit.LinearCombinationFunc(x, y, z => z*z, Math.Sin, SpecialFunctions.Gamma); Enumerable.Range(0,11).Select(x => f(x/10.0)) Root Finding We now provide basic root finding algorithms. A root of a function x -> f(x) is a solution of the equation f(x)=0. Root-finding algorithms can thus help finding numerical real solutions of arbitrary equations, provided f is reasonably well-behaved and we already have an idea about an interval [a,b] where we expect a root. As usual, there is a facade class FindRoots for simple scenarios: The routines usually expect a lower and upper boundary as parameters, and then optionally the accuracy we try to achieve and the maximum number of iterations. C#: FindRoots.OfFunction(x => x*x - 4, -5, 5) // -2.00000000046908 C#: FindRoots.OfFunction(x => x*x - 4, -5, 5, accuracy: 1e-14) // -2 (exact) C#: FindRoots.OfFunctionDerivative(x => x*x - 4, x => 2*x, -5, 5) // -2 (exact) F#: FindRoots.ofFunction -5.0 5.0 (fun x -> x*x - 4.0) F#: FindRoots.ofFunctionDerivative -5.0 5.0 (fun x -> x*x - 4.0) (fun x -> 2.0*x) A NonConvergenceException is thrown if no root can be found by the algorithm. In practice you’d often want to use a specific well-known algorithm. You’ll find them in the RootFinding namespace. Each of these algorithm provides a FindRoot method with similar arguments as those above. However, the algorithms may sometimes fail to find a root or the function may not actually have a root within the provided interval. Failing to find a root is thus not exactly exceptional. That’s why the algorithms also provide an exception-free TryFindRoot code path with the common Try-pattern as in TryParse. Bisection A simple and robust yet rather slow algorithm, implemented in the Bisection class. Example: Find the real roots of the cubic polynomial 2x^3 + 4x^2 - 50x + 6: Func f = x => Evaluate.Polynomial(x, 6, -50, 4, 2); Bisection.FindRoot(f, -6.5, -5.5, 1e-8, 100); // -6.14665621970684 Bisection.FindRoot(f, -0.5, 0.5, 1e-8, 100); // 0.121247371972135 Bisection.FindRoot(f, 3.5, 4.5, 1e-8, 100); // 4.02540884774855 F#: f |> FindRoots.bisection 100 1e-8 3.5 4.5 // Some(4.0254..) Note that the F# function returns a float option. Instead of throwing an exception it will simply return None if it fails. Brent’s Method We use Brent’s method as default algorithm, implemented in the Brent class. Brent’s method is faster than bisection, but falls back to something close to bisection if the faster approaches (essentially the secant method and inverse quadratic interpolation) fails and is therefore almost as reliable. The same example as above, but using Brent’s method: Func f = x => Evaluate.Polynomial(x, 6, -50, 4, 2); Brent.FindRoot(f, -6.5, -5.5, 1e-8, 100); // -6.14665621970684 Brent.FindRoot(f, -0.5, 0.5, 1e-8, 100); // 0.121247371972135 Brent.FindRoot(f, 3.5, 4.5, 1e-8, 100); // 4.02540884774855 F#: f |> FindRoots.brent 100 1e-8 3.5 4.5 // Some(4.0254..) Note that there are better algorithms for finding all roots of a polynomial. We plan to add specific polynomial root finding algorithms later on. Newton-Raphson The Newton-Raphson method leverages the function’s first derivative to converge much faster, but can also fail completely. The pure Newton-Raphson algorithm is implemented in the NewtonRaphson class. However, we also provide a modified algorithm that tries to recover (instead of just failing) when overshooting, converging too slowly or even when loosing bracketing in the presence of a pole. This modified algorithms is available in the RobustNewtonRaphson class. Example: Assume we want to find solutions of x+1/(x-2) == -2, hence x -> f(x) = 1/(x-2)+x+2 with a pole at x==2: Func f = x => 1/(x - 2) + x + 2; Func df = x => -1/(x*x - 4*x + 4) + 1; RobustNewtonRaphson.FindRoot(f, df, -2, -1, 1e-14, 100, 20); // -1.73205080756888 RobustNewtonRaphson.FindRoot(f, df, 1, 1.99, 1e-14, 100, 20); // 1.73205080756888 RobustNewtonRaphson.FindRoot(f, df, -1.5, 1.99, 1e-14, 100, 20); // 1.73205080756888 RobustNewtonRaphson.FindRoot(f, df, 1, 6, 1e-14, 100, 20); // 1.73205080756888 F#: FindRoots.newtonRaphsonRobust 100 20 1e-14 1.0 6.0 f df F#: (f, df) ||> FindRoots.newtonRaphsonRobust 100 20 1e-14 1.0 6.0 Broyden’s Method The quasi-newton method by Broyden, implemented in the Broyden class, may help you to find roots in multi-dimensional problems. Linear Algebra As usual there have been quite a few improvements around linear algebra, see the release notes for the complete list. If you’ve enabled our Intel MKL native linear algebra provider, then eigenvalue decompositions should be much faster now. Matrices now also support the new F# 3.1 array slicing syntax. Note that we’re phasing out the MathNet.Numerics.IO library and namespace and plan to drop it entirely in v3. We’ve already replaced it with two new separate NuGet packages and obsoleted all members of the old library. The new approach with separate libraries makes it possible to introduce specific dependencies e.g. to read and write Excel files, without forcing these dependencies on all of Math.NET Numerics. We recommend to switch over to the new packages as soon as possible. Statistics We’ve had a Pearson correlation coefficient routine for a while, but no Covariance routine. In addition to a new Spearman ranked correlation routine, this release finally also adds sample and population Covariance functions for arrays and IEnumerables. ArrayStatistics.Covariance(new[] {1.2, 1.3, 2.4}, new[] {2.2, 2.3, -4.5}) [Less]
Posted almost 11 years ago
Most .Net libraries should also work on Linux or OS X thanks to Mono. But, do they really? How do you verify and test that, without installing Mono on your Windows development box, or setting up a separate Linux box? Or how to compile and test some ... [More] local files without installing any .net or mono dev tools at all? Vagrant comes in handy here. Vagrant may not be very well known among .Net developers on Windows yet, so let the Vagrant team introduce it in their own words: “Vagrant is a tool for building complete development environments. With an easy-to-use workflow and focus on automation, Vagrant lowers development environment setup time, increases development/production parity, and makes the “works on my machine” excuse a relic of the past.” In my words, Vagrant lets you define a standardized development or test environment for your project that works exactly the same everywhere, no matter what OS you’re on or how you’ve set it up. It uses virtual machines in the background, but you neither see nor care about them much. Using Mono with Vagrant The Math.NET Numerics project claims that it supports Mono, but I admit I verify that claim sporadically only. Up to now, that is. I’ve just enabled Vagrant on the project, so everyone can test it on Mono without any effort. This is what you do, assuming you have Vagrant installed and you have a local checkout of the repository: open git bash at the root of the checkout and run 1 $ vagrant up This will download the box the first time it is used (~540 MB), create a virtual machine in VirtualBox and then start and provision it. After the first time this is quite fast, usually less than a minute. Then we can enter the environment. We see that both mono and fsharp are available and up to date: 1 $ vagrant ssh The trick is that the local directory is automatically available within the environment in the /vagrant path. We can compile our project using mono and xbuild right away: 1 2 3 4 5 ~$ xbuild /vagrant/MathNet.Numerics.sln # or just some projects: ~$ xbuild /vagrant/src/Numerics/Numerics.csproj ~$ xbuild /vagrant/src/FSharp/FSharp.fsproj ~$ xbuild /vagrant/src/UnitTests/UnitTests.csproj And then run all the unit tests using NUnit: 1 2 ~$ nunit-console /vagrant/out/tests/Net40/MathNet.Numerics.UnitTests.dll ~$ nunit-console /vagrant/out/tests/Net40/MathNet.Numerics.FSharp.UnitTests.dll And indeed, 37 of 11906 tests are failing - apparently there are some differences around number formatting. Seems like we’ve got some work to do. In order to fix it, I open Visual Studio on Windows as usual, compile it there (or in the Vagrant environment using xbuild), and run the tests again both in Visual Studio using .Net and in the environment using Mono. No manual file transfer or copying is needed. If you’re done working for now, leave the environment with exit and either suspend (vagrant suspend) or shutdown (vagrant halt) the virtual machine. In either case, you can bring it up again later with vagrant up, or remove it completely with vagrant destroy. Installing Vagrant I mentioned before that you need to have Vagrant installed for this to work: Download and install Vagrant from here Download and install VirtualBox from here Not sure this is still needed, but to be on the safe side add the VirtualBox folder to your system PATH environment variable. In my case the folder is “C:\Program Files\Oracle\VirtualBox”. If you need more help there, have a look at Vagrant’s getting started guide. Enabling Vagrant in your own project There are really only two things I did to enable this in Math.NET Numerics: Add “.vagrant” to the .gitignore file (or the equivalent if you don’t use git). Add a Vagrantfile text file to the repository The Vagrantfile can be generated automatically with the vagrant init command, but it may even be easier to just start from the file I currently use: Vagrant.configure("2") do |config| config.vm.box = "wheezy64-mono3.0.10-fsharp3.0.27" config.vm.box_url = "https://dl.dropboxusercontent.com/s/uelesklqouaw1gl/wheezy64-mono3.0.10-fsharp3.0.27-virtualbox.box" config.vm.provider :virtualbox do |vb| vb.gui = false vb.customize ["modifyvm", :id, "--memory", "1024"] vb.customize ["modifyvm", :id, "--cpus", "2"] end end The file declares the base box to use and where it can be downloaded from if needed. This specific box by default uses only 384 MB RAM and 1 CPU, but we override this in our project to give it some more resources. You could also declare more folders to be kept in sync or network ports to be forwarded in this file. This file is also the right place to specify additional provisioning if needed. How this works is described in the Vagrant docs. Note however that this specific box does not have ruby installed and is not prepared to be provisioned with tools like puppet or chef. Simple provisioning by shell script should work though, and good enough to install some more packages or change some settings if needed. About the Base Box Ideally we could just use an existing official Debian base box and provision mono and fsharp using Vagrant’s provisioning mechanisms. Hopefully we’ll get there in the end, e.g. by giving the Debian package maintainers a hand. Unfortunately for now the Debian packages are out of date (but they actually exist which is good news) so we need to compile both mono and fsharp from sources. Compiling them takes some time on a VM and seems inappropriate to me to do at provisioning time. So I’ve created a new VM from scratch where I can compile the tools locally and extract cleaned-up Vagrant base boxes in a relatively straight forward way, whenever a new version is released. Current Specs: OS: Debian 7 “Wheezy”, 3.2.0-4-amd64 Linux Kernel (3.2.41-2+deb7u2) VM: VirtualBox, Guest Tools for v4.2.12 (installed from VB instead of using the Debian packages) Size: 542 MB when packed Defaults to 384 MB Ram, 1 CPU. Dynamically expanding disk, max 40 GB. Mono 3.0.10 and F# 3.0.27 compiled locally from tagged sources, installed to /usr NUnit 2.6.1 official binary added manually to /usr/local, hence effectively hiding nunit-console from Mono in /usr/bin but not Mono’s nunit-console2 or nunit-console4. Note that Mono comes with NUnit 2.4.8. I’ve made the box available on Dropbox for now until we find a better place. To use it either copy the Vagrantfile above, or add the box manually using something like: 1 $ vagrant box add wheezy64monofs https://dl.dropboxusercontent.com/s/uelesklqouaw1gl/wheezy64-mono3.0.10-fsharp3.0.27-virtualbox.box Known Issues The F# tools seem to clear the shell at start which is a bit irritating. Might be related to git bash, but if I remember right this did not happen back when I used the Debian-provided VirtualBox Guest Tools. Considering going back to them. I did not manage to fully turn off USB in VirtualBox; apparently it is needed by some HID device (maybe the mouse?). I’m no expert on Vagrant or even on using Mono and F# on Linux myself, so any feedback and suggestions for improvements are very welcome. Let me know if this works for you or whether we need to go further. Of course there are also ways to get F# and/or mono straight to your box without the need for Vagrant, see the F# Software Foundation website for instructions on how to get started on your platform. [Less]
Posted almost 11 years ago
Most .Net libraries should also work on Linux or OS X thanks to Mono. But, do they really? How do you verify and test that, without installing Mono on your Windows development box, or setting up a separate Linux box? Or how to compile and test some ... [More] local files without installing any .net or mono dev tools at all? Vagrant comes in handy here. Vagrant may not be very well known among .Net developers on Windows yet, so let the Vagrant team introduce it in their own words: “Vagrant is a tool for building complete development environments. With an easy-to-use workflow and focus on automation, Vagrant lowers development environment setup time, increases development/production parity, and makes the “works on my machine” excuse a relic of the past.” In my words, Vagrant lets you define a standardized development or test environment for your project that works exactly the same everywhere, no matter what OS you’re on or how you’ve set it up. It uses virtual machines in the background, but you neither see nor care about them much. Using Mono with Vagrant The Math.NET Numerics project claims that it supports Mono, but I admit I verify that claim sporadically only. Up to now, that is. I’ve just enabled Vagrant on the project, so everyone can test it on Mono without any effort. This is what you do, assuming you have Vagrant installed and you have a local checkout of the repository: open git bash at the root of the checkout and run 1 $ vagrant up This will download the box the first time it is used (~540 MB), create a virtual machine in VirtualBox and then start and provision it. After the first time this is quite fast, usually less than a minute. Then we can enter the environment. We see that both mono and fsharp are available and up to date: 1 $ vagrant ssh The trick is that the local directory is automatically available within the environment in the /vagrant path. We can compile our project using mono and xbuild right away: 1 2 3 4 5 ~$ xbuild /vagrant/MathNet.Numerics.sln # or just some projects: ~$ xbuild /vagrant/src/Numerics/Numerics.csproj ~$ xbuild /vagrant/src/FSharp/FSharp.fsproj ~$ xbuild /vagrant/src/UnitTests/UnitTests.csproj And then run all the unit tests using NUnit: 1 2 ~$ nunit-console /vagrant/out/tests/Net40/MathNet.Numerics.UnitTests.dll ~$ nunit-console /vagrant/out/tests/Net40/MathNet.Numerics.FSharp.UnitTests.dll And indeed, 37 of 11906 tests are failing - apparently there are some differences around number formatting. Seems like we’ve got some work to do. In order to fix it, I open Visual Studio on Windows as usual, compile it there (or in the Vagrant environment using xbuild), and run the tests again both in Visual Studio using .Net and in the environment using Mono. No manual file transfer or copying is needed. If you’re done working for now, leave the environment with exit and either suspend (vagrant suspend) or shutdown (vagrant halt) the virtual machine. In either case, you can bring it up again later with vagrant up, or remove it completely with vagrant destroy. Installing Vagrant I mentioned before that you need to have Vagrant installed for this to work: Download and install Vagrant from here Download and install VirtualBox from here Not sure this is still needed, but to be on the safe side add the VirtualBox folder to your system PATH environment variable. In my case the folder is “C:\Program Files\Oracle\VirtualBox”. If you need more help there, have a look at Vagrant’s getting started guide. Enabling Vagrant in your own project There are really only two things I did to enable this in Math.NET Numerics: Add “.vagrant” to the .gitignore file (or the equivalent if you don’t use git). Add a Vagrantfile text file to the repository The Vagrantfile can be generated automatically with the vagrant init command, but it may even be easier to just start from the file I currently use: Vagrant.configure("2") do |config| config.vm.box = "wheezy64-mono3.0.10-fsharp3.0.27" config.vm.box_url = "https://dl.dropboxusercontent.com/s/uelesklqouaw1gl/wheezy64-mono3.0.10-fsharp3.0.27-virtualbox.box" config.vm.provider :virtualbox do |vb| vb.gui = false vb.customize ["modifyvm", :id, "--memory", "1024"] vb.customize ["modifyvm", :id, "--cpus", "2"] end end The file declares the base box to use and where it can be downloaded from if needed. This specific box by default uses only 384 MB RAM and 1 CPU, but we override this in our project to give it some more resources. You could also declare more folders to be kept in sync or network ports to be forwarded in this file. This file is also the right place to specify additional provisioning if needed. How this works is described in the Vagrant docs. Note however that this specific box does not have ruby installed and is not prepared to be provisioned with tools like puppet or chef. Simple provisioning by shell script should work though, and good enough to install some more packages or change some settings if needed. About the Base Box Ideally we could just use an existing official Debian base box and provision mono and fsharp using Vagrant’s provisioning mechanisms. Hopefully we’ll get there in the end, e.g. by giving the Debian package maintainers a hand. Unfortunately for now the Debian packages are out of date (but they actually exist which is good news) so we need to compile both mono and fsharp from sources. Compiling them takes some time on a VM and seems inappropriate to me to do at provisioning time. So I’ve created a new VM from scratch where I can compile the tools locally and extract cleaned-up Vagrant base boxes in a relatively straight forward way, whenever a new version is released. Current Specs: OS: Debian 7 “Wheezy”, 3.2.0-4-amd64 Linux Kernel (3.2.41-2+deb7u2) VM: VirtualBox, Guest Tools for v4.2.12 (installed from VB instead of using the Debian packages) Size: 542 MB when packed Defaults to 384 MB Ram, 1 CPU. Dynamically expanding disk, max 40 GB. Mono 3.0.10 and F# 3.0.27 compiled locally from tagged sources, installed to /usr NUnit 2.6.1 official binary added manually to /usr/local, hence effectively hiding nunit-console from Mono in /usr/bin but not Mono’s nunit-console2 or nunit-console4. Note that Mono comes with NUnit 2.4.8. I’ve made the box available on Dropbox for now until we find a better place. To use it either copy the Vagrantfile above, or add the box manually using something like: 1 $ vagrant box add wheezy64monofs https://dl.dropboxusercontent.com/s/uelesklqouaw1gl/wheezy64-mono3.0.10-fsharp3.0.27-virtualbox.box Known Issues The F# tools seem to clear the shell at start which is a bit irritating. Might be related to git bash, but if I remember right this did not happen back when I used the Debian-provided VirtualBox Guest Tools. Considering going back to them. I did not manage to fully turn off USB in VirtualBox; apparently it is needed by some HID device (maybe the mouse?). I’m no expert on Vagrant or even on using Mono and F# on Linux myself, so any feedback and suggestions for improvements are very welcome. Let me know if this works for you or whether we need to go further. Of course there are also ways to get F# and/or mono straight to your box without the need for Vagrant, see the F# Software Foundation website for instructions on how to get started on your platform. [Less]
Posted almost 11 years ago
Most .Net libraries should also work on Linux or OS X thanks to Mono. But, do they really? How do you verify and test that, without installing Mono on your Windows development box, or setting up a separate Linux box? Or how to compile and test some ... [More] local files without installing any .net or mono dev tools at all? Vagrant comes in handy here. Vagrant may not be very well known among .Net developers on Windows yet, so let the Vagrant team introduce it in their own words: “Vagrant is a tool for building complete development environments. With an easy-to-use workflow and focus on automation, Vagrant lowers development environment setup time, increases development/production parity, and makes the “works on my machine” excuse a relic of the past.” In my words, Vagrant lets you define a standardized development or test environment for your project that works exactly the same everywhere, no matter what OS you’re on or how you’ve set it up. It uses virtual machines in the background, but you neither see nor care about them much. Using Mono with Vagrant The Math.NET Numerics project claims that it supports Mono, but I admit I verify that claim sporadically only. Up to now, that is. I’ve just enabled Vagrant on the project, so everyone can test it on Mono without any effort. This is what you do, assuming you have Vagrant installed and you have a local checkout of the repository: open git bash at the root of the checkout and run 1 $ vagrant up This will download the box the first time it is used (~540 MB), create a virtual machine in VirtualBox and then start and provision it. After the first time this is quite fast, usually less than a minute. Then we can enter the environment. We see that both mono and fsharp are available and up to date: 1 $ vagrant ssh The trick is that the local directory is automatically available within the environment in the /vagrant path. We can compile our project using mono and xbuild right away: 1 2 3 4 5 ~$ xbuild /vagrant/MathNet.Numerics.sln # or just some projects: ~$ xbuild /vagrant/src/Numerics/Numerics.csproj ~$ xbuild /vagrant/src/FSharp/FSharp.fsproj ~$ xbuild /vagrant/src/UnitTests/UnitTests.csproj And then run all the unit tests using NUnit: 1 2 ~$ nunit-console /vagrant/out/tests/Net40/MathNet.Numerics.UnitTests.dll ~$ nunit-console /vagrant/out/tests/Net40/MathNet.Numerics.FSharp.UnitTests.dll And indeed, 37 of 11906 tests are failing - apparently there are some differences around number formatting. Seems like we’ve got some work to do. In order to fix it, I open Visual Studio on Windows as usual, compile it there (or in the Vagrant environment using xbuild), and run the tests again both in Visual Studio using .Net and in the environment using Mono. No manual file transfer or copying is needed. If you’re done working for now, leave the environment with exit and either suspend (vagrant suspend) or shutdown (vagrant halt) the virtual machine. In either case, you can bring it up again later with vagrant up, or remove it completely with vagrant destroy. Installing Vagrant I mentioned before that you need to have Vagrant installed for this to work: Download and install Vagrant from here Download and install VirtualBox from here Not sure this is still needed, but to be on the safe side add the VirtualBox folder to your system PATH environment variable. In my case the folder is “C:\Program Files\Oracle\VirtualBox”. If you need more help there, have a look at Vagrant’s getting started guide. Enabling Vagrant in your own project There are really only two things I did to enable this in Math.NET Numerics: Add “.vagrant” to the .gitignore file (or the equivalent if you don’t use git). Add a Vagrantfile text file to the repository The Vagrantfile can be generated automatically with the vagrant init command, but it may even be easier to just start from the file I currently use: Vagrant.configure("2") do |config| config.vm.box = "wheezy64-mono3.0.10-fsharp3.0.27" config.vm.box_url = "https://dl.dropboxusercontent.com/s/uelesklqouaw1gl/wheezy64-mono3.0.10-fsharp3.0.27-virtualbox.box" config.vm.provider :virtualbox do |vb| vb.gui = false vb.customize ["modifyvm", :id, "--memory", "1024"] vb.customize ["modifyvm", :id, "--cpus", "2"] end end The file declares the base box to use and where it can be downloaded from if needed. This specific box by default uses only 384 MB RAM and 1 CPU, but we override this in our project to give it some more resources. You could also declare more folders to be kept in sync or network ports to be forwarded in this file. This file is also the right place to specify additional provisioning if needed. How this works is described in the Vagrant docs. Note however that this specific box does not have ruby installed and is not prepared to be provisioned with tools like puppet or chef. Simple provisioning by shell script should work though, and good enough to install some more packages or change some settings if needed. About the Base Box Ideally we could just use an existing official Debian base box and provision mono and fsharp using Vagrant’s provisioning mechanisms. Hopefully we’ll get there in the end, e.g. by giving the Debian package maintainers a hand. Unfortunately for now the Debian packages are out of date (but they actually exist which is good news) so we need to compile both mono and fsharp from sources. Compiling them takes some time on a VM and seems inappropriate to me to do at provisioning time. So I’ve created a new VM from scratch where I can compile the tools locally and extract cleaned-up Vagrant base boxes in a relatively straight forward way, whenever a new version is released. Current Specs: OS: Debian 7 “Wheezy”, 3.2.0-4-amd64 Linux Kernel (3.2.41-2+deb7u2) VM: VirtualBox, Guest Tools for v4.2.12 (installed from VB instead of using the Debian packages) Size: 542 MB when packed Defaults to 384 MB Ram, 1 CPU. Dynamically expanding disk, max 40 GB. Mono 3.0.10 and F# 3.0.27 compiled locally from tagged sources, installed to /usr NUnit 2.6.1 official binary added manually to /usr/local, hence effectively hiding nunit-console from Mono in /usr/bin but not Mono’s nunit-console2 or nunit-console4. Note that Mono comes with NUnit 2.4.8. I’ve made the box available on Dropbox for now until we find a better place. To use it either copy the Vagrantfile above, or add the box manually using something like: 1 $ vagrant box add wheezy64monofs https://dl.dropboxusercontent.com/s/uelesklqouaw1gl/wheezy64-mono3.0.10-fsharp3.0.27-virtualbox.box Known Issues The F# tools seem to clear the shell at start which is a bit irritating. Might be related to git bash, but if I remember right this did not happen back when I used the Debian-provided VirtualBox Guest Tools. Considering going back to them. I did not manage to fully turn off USB in VirtualBox; apparently it is needed by some HID device (maybe the mouse?). I’m no expert on Vagrant or even on using Mono and F# on Linux myself, so any feedback and suggestions for improvements are very welcome. Let me know if this works for you or whether we need to go further. Of course there are also ways to get F# and/or mono straight to your box without the need for Vagrant, see the F# Software Foundation website for instructions on how to get started on your platform. [Less]
Posted almost 11 years ago
Math.NET Numerics v2.5, released in April 2013, is focused on statistics and linear algebra. As usual you’ll find a full listing of all changes in the release notes. However, I’d like to take the chance to highlight some important changes, show some ... [More] code samples and explain the reasoning behind the changes. Please let me know if these “What’s New” articles are useful in this format and whether I should continue to put the together for future releases. Statistics Order Statistics & Quantiles Previously our order statistics and quantile functions were quite limited. With this release we finally have almost complete quantile support: OrderStatistic Median LowerQuartile UpperQuartile InterquartileRange FiveNumberSummary Percentile Quantile QuantileCustom All of them are implemented on top of the quantile function. We always default to approximately median-unbiased quantiles, usually denoted as type R-8, which do not assume samples to be normally distributed. If you need compatibility with another implementation, you can use QuantileCustom which accepts either a QuantileDefinition enum (we support all 9 R-types, SAS 1-5, Excel, Nist, Hydrology, etc.) or a 4-parameter definition as in Mathematica. For the empirical inverse cummulative distribution, which is essentially an R1-type quantile, you can use the new Statistics.InverseCDF function. More efficient ways to compute statistics Previously there were two ways to estimate some statistics from a sample set: The Statistics class provided static extension methods to evaluate a single statistic from an enumerable, and DescriptiveStatistics to compute a whole set of standard statistics at once. This was unsatisfactory since it was not very efficient: the DescriptiveStatistics way actually required more than one pass internally (mostly because of the median) and it was not leveraging the fact that the sample set may already be sorted. To fix the first issue, we’ve marked DescriptiveStatistics.Median as obsolete and will remove it in v3. Until then, the median computation is delayed until requested the first time. In normal cases where Median is not used it now only requires a single pass. The second issue we attacked by introducing three new classes to compute a single statistic directly from the best fitting sample data format: ArrayStatistics operates on arrays which are not assumed to be sorted. SortedArrayStatistics operates on arrays which must be sorted in ascending order. StreamingStatistics operates on a stream in a single pass, without keeping the full data in memory at any time. Can thus be used to stream over data larger than system memory. ArrayStatistics implements Minimum, Maximum, Mean, Variance, StandardDeviation, PopulationVariance and PopulationStandardDeviation. In addition it implements all the order statistics/quantile functions mentioned above, but in an inplace way that reorders the data array (partial sorting) and because of that is marked with an Inplace-suffix to indicate the side effect. These inplace functions get slightly faster when calling them repeatedly, but will always be slower than the sorted array statistics. Nevertheless, since the sorting itself is quite expensive, all in all the (non-sorted) array statistics are still faster in practice if only few calls are needed. Example: We want to compute the IQR of {3,1,2,4}. var data = new double[] { 3.0, 1.0, 2.0, 4.0 }; ArrayStatistics.InterquartileRangeInplace(data); // iqr = 2.16666666666667 This is equivalent to executing IQR(c(3,1,2,4), type=8) in R, with quantile definition type R-8. SortedArrayStatistics expects data to be sorted in ascending order and implements Minimum, Maximum, and all the order statistics/quantile functions mentioned above. It leverages the ordering for very fast (constant time) order statistics. There’s also no need to reorder the data, so other than ArrayStatistics, this class never modifies the provided array and has no side effect. It does not re-implement any operations that cannot leverage the ordering, like Mean or Variance, so use the implementation from ArrayStatistics instead if needed. var data = new[] { 1.0, 2.0, 3.0, 4.0 }; var iqr = SortedArrayStatistics.InterquartileRange(data); // iqr = 2.16666666666667 StreamingStatistics estimates statistics in a single pass without memorization and implements Minimum, Maximum, Mean, Variance, StandardDeviation, PopulationVariance and PopulationStandardDeviation. It does not implement any order statistics, since they require sorting and are thus not computable in a single pass without keeping the data in memory. No function of this class has any side effects on the data. The Statistics class has been updated to leverage these new implementations internally, and implements all of the statistics mentioned above as extension methods on enumerables. No function of this class has any side effects on the data. var iqr = new[] { 3.0, 1.0, 2.0, 4.0 }.InterquartileRange(); // iqr = 2.16666666666667 Note that this is generally slower than ArrayStatistics because it requires to copy the array to make sure there are no side effects, and much slower than SortedArrayStatistics which would have constant time (assuming we sorted it manually first). Repeated Evaluation and Precomputed Functions Most of the quantile functions accept a tau-parameter. Often you need to evaluate that function with not one but a whole range of values for that parameter, say for plotting. In such scenarios it is advantageous to first sort the data and then use the SortedArrayStatistics functions with constant time complexity. For convenience we also provide alternative implementations with the Func-suffix in the Statistics class that do exactly that: instead of accepting a tau-parameter themselves, they return a function that accepts tau: var icdf = new[] { 3.0, 1.0, 2.0, 4.0 }.InverseCDFFunc(); var a = icdf(0.3); // 2 var b = new[] { 0.0, 0.1, 0.5, 0.9, 1.0 }.Select(icdf).ToArray(); // 1,1,2,4,4 Linear Algebra There have been quite a few bug fixes and performance improvements around linear algebra. See the release notes for details. Matrix and Vector String Formatting Previously the ToString method used to render the whole matrix to a string. When working with very large data sets this can be an expensive operation both on CPU and memory usage. It also makes it a pain to work with interactive consoles or REPL environments like F# Interactive that write the ToString of the resulting object to the console output. Starting from v2.5, ToString methods no longer render the whole structure to a string for large data. Instead, ToString now only renders an excerpt of the data, together with a line about dimension, type and in case of sparse data a sparseness indicator. The intention is to give a good idea about the data in a visually useful way: DenseMatrix.CreateRandom(60,80,Normal.WithMeanVariance(2.0,1.0)).ToString(); generates the following multi-line string: DenseMatrix 60x80-Double 1.68665 1.24322 3.36594 2.07444 4.13008 ... 3.01076 1.10888 2.8856 2.31662 3.94124 3.56711 ... -0.216804 0.843804 2.67243 1.097 2.34063 0.875953 ... 1.808 3.87044 2.69509 2.79642 -0.354365 2.45302 ... 2.79665 2.05722 3.39823 2.56256 1.88849 1.75259 ... 3.8987 1.9874 2.97047 1.40584 1.97734 2.37733 ... 2.875 2.06503 1.15681 3.85957 2.84836 1.25326 ... -0.108938 ... ... ... ... ... ... ... 4.39245 1.32734 2.83637 1.78257 2.44356 ... 2.58935 The output is not perfect yet, as we’d ideally align the decimal point and automatically choose the right width for each column. Hopefully we can fix that in a future version. How much data is shown by default can be adjusted in the Control class: Control.MaxToStringColumns = 6; Control.MaxToStringRows = 8; Or you can use an override or alternative: Matrix.ToString(maxRows, maxColumns, formatProvider) // Just the top info line Matrix.ToTypeString() // Just the matrix data without the top info line Matrix.ToMatrixString(maxRows, maxColumns, formatProvider) Matrix.ToMatrixString(maxRows, maxColumns, padding, format, formatProvider) Note that ToString has never been intended to serialize a matrix to a string in order to parse it back later. Please use one of our data libraries instead, e.g. the MathNet.Numerics.Data.Text package. Creating a Matrix or Vector Constructing a matrix or vector has become more consistent: Except for obsolete members which will be removed in v3, all constructors now directly use the provided data structure by reference, without any copying. This means that there are only constructors left that accept the actual inner data structure format. Usually you’d use the new static functions instead, which always either create a copy or construct the inner data structure directly from the provided data, without keeping a reference to it. Some examples below. The C# way usually works in F# just the same as well, but we provide more idiomatic alternatives for most of them: // Directly from an array in the internal column-major format (no copying) C#: new DenseMatrix(2, 3, new[] { 1.0, 2.0, 10.0, 20.0, 100.0, 300.0 }) F#: DenseMatrix.raw 2 3 [| 1.0; 2.0; 10.0; 20.0; 100.0; 300.0 |] // All-zero 3x4 (3 rows, 4 columns) matrix C#: new DenseMatrix(3, 4) F#: DenseMatrix(3, 4) F#: DenseMatrix.zeroCreate 3 4 // 3x4, all cells the same fixed value C#: DenseMatrix.Create(3, 4, (r, c) => 20.5) // note: better way is planned F#: DenseMatrix.create 3 4 20.5 // 3x4, random C#: DenseMatrix.CreateRandom(3, 4, Normal.WithMeanVariance(2.0, 0.5)); F#: DenseMatrix.randomCreate 3 4 (Normal.WithMeanVariance(2.0, 0.5)) // 3x4, using an initializer function C#: DenseMatrix.Create(3, 4, (r, c) => r/100.0 j) F#: DenseMatrix.init 3 4 (fun r c -> float r/100.0 float c) // From enumerables of enumerables (as rows or columns) C#: DenseMatrix.OfColumns(2,3, new[] { new[] { 1.0, 4.0 }, new[] { 2.0, 5.0 }, new[] { 3.0, 6.0 } }) F#: DenseMatrix.ofRows 2 3 [{ 1.0 .. 3.0 }; { 4.0 .. 6.0 }] // From F# lists of lists F#: DenseMatrix.ofRowsList 2 3 [[1.0 .. 3.0]; [4.0 .. 6.0]] F#: matrix [[1.0; 2.0; 3.0] [4.0; 5.0; 6.0]] // By calling a function to construct each row (or analog for columns) F#: DenseMatrix.initRow 10 10 (fun r -> vector [float r .. float (r 9)]) All of these work the same way also for sparse matrices, and similarly for vectors. Useful for sparse data is another way that accepts a list or sequence of indexed row * column * value tuples, where all other cells are assumed to be zero: F#: SparseMatrix.ofListi 200 100 [(4,3,20.0); (18,9,3.0); (2,1,99.9)] F#: DenseMatrix.ofSeqi 10 10 (seq {for i in 0..9 -> (i,i,float(i*i))}) C#: SparseMatrix.OfIndexed(10,10,Enumerable.Range(0,10).Select(i => Tuple.Create(i,i,(double)(i*i)))) Inplace Map The F# modules have supported (outplace) combinators like map for quite some time. We’ve now implemented inplace map directly in the storage classes so it can operate efficiently also on sparse data, and is accessible from C# code without using the F# extensions. The F# map-related functions have been updated to leverage these routines: matrix |> Matrix.map (fun x -> 2.0*x) matrix |> Matrix.mapnz (fun x -> 2.0*x) // non-zero: may skip zero values, useful if sparse matrix |> Matrix.mapi (fun i j x -> x float i - float j) // indexed with row, column matrix |> Matrix.mapinz (fun i j x -> x float i - float j) // indexed, non-zero Or the equivalent inplace versions which return unit: matrix |> Matrix.mapInPlace (fun x -> 2.0*x) matrix |> Matrix.mapnzInPlace (fun x -> 2.0*x) matrix |> Matrix.mapiInPlace (fun i j x -> x float i - float j) matrix |> Matrix.mapinzInPlace (fun i j x -> x float i - float j) In C#: matrix.MapInplace(x => 2*x); matrix.MapIndexedInplace((i,j,x) => x i-j, forceMapZeros:true); F# Slice Setters Speaking about F#, we’ve supported the slice getter syntax for a while as a nice way to get a sub-matrix. For example, to get the bottom right 2x2 sub-matrix of m we can do: let m = DenseMatrix.init 3 4 (fun i j -> float (10 * i j)) m |> printfn "%A" m.[1..2,2..3] |> printfn "%A" The same syntax now also works for setters, e.g. to overwrite the very same bottom right corner we can write: m.[1..2,2..3] <- matrix [[0.1; 0.2] [0.3; 0.4]] printfn "%A" m The 3 printfn statements generate the following output: DenseMatrix 3x4-Double 0 1 2 3 10 11 12 13 20 21 22 23 DenseMatrix 2x2-Double 12 13 22 23 DenseMatrix 3x4-Double 0 1 2 3 10 11 0.1 0.2 20 21 0.3 0.4 [Less]