Math.NET Symbolics
Math.NET Symbolics is a basic open source computer algebra library for .Net and Mono written in F#.
This project does not aim to become a full computer algebra system. If you need such a system, have a look at Axiom or Maxima instead, or for commercial solutions Maple, Mathematica or Wolfram Alpha.
Math.NET Symbolics is part of the Math.NET initiative. Available for free under the MIT/X11 License.
NuGet Packages
The recommended way to get Math.NET Symbolics is to use NuGet. The following packages are provided and maintained in the public NuGet Gallery:
Core Package:
- MathNet.Symbolics - core package
Platform Support and Dependencies
- .NETFramework 4.5, .NETFramework 4.6.1 and .NETStandard 2.0
Package Dependencies:
- FParsec (isolated usage only for infix parsing)
Math.NET Symbolics with F# and F# Interactive
With NuGet you can start quickly by installing the MathNet.Symbolics
package,
which automatically loads its dependencies MathNet.Numerics
and MathNet.Numerics.FSharp
.
In F# interactive you can reference them by loading two scripts, along the lines of
1: 2: |
|
To get started, open the namespaces and the Operators module and declare the variables and constants you intend to use as symbols:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: |
|
Then we're all set to start writing expressions:
1: 2: 3: 4: |
|
Math.NET Symbolics expressions are always in a simplified form according to a set of rules. Expressions are tree structures, but F# interactive shows them in a readable infix form thanks to a display printer added in the script loaded above. You can also use these printers manually to format any expression as infix string, LaTeX expression or in strict mode to see the actual internal representation:
1: 2: 3: |
|
Strings in infix notation can be parsed back into expressions:
1: 2: 3: 4: 5: |
|
Number Literals
Numbers can be forced to become expressions using the Q
suffix, e.g. 3Q
is an expression representing an integer with value 3. This is usually not needed
if at least one of the operands is an expression, e.g. a symbol. But if all operands
are standard .Net numbers, they will be treated as such. For example (3 + 2)*4/6
is
a standard F# integer expression and will result in 3
due to .Net integer arithmetics.
However, if we force it to become an expression by writing (3Q + 2)*4/6
, it will
result in the fraction expression 10/3
as expected.
Since Math.NET Symbolics is about algebra, all number literals are arbitrarily big rational numbers, i.e. integers or fractions. If you need floating point numbers, use a symbol for them instead and provide their value at evaluation time.
Evaluating Expressions
Often you need to evaluate the resulting number value of an expression given the values for all its symbols. To do so, prepare the value set as map or dictionary and pass it to the evaluate function. Values need to be of type FloatingPoint which is a discriminated union that can represent not only float and complex but also vectors and matrices of the same.
1: 2: |
|
Manipulating Expressions
There are various modules to help you combine and manipulate expressions:
- Operators: standard operators, recommended to open always.
- Structure: structural analysis, operand access, substitution, map
- Algebraic: algebraic expansion, separate factors
- Polynomial: properties, degrees, coefficients, terms, divide, gcd, expansion, partial fraction
- Rational: numerator/denominator, properties, rationalize, expand, simplify
- Exponential: expand, contract, simplify
- Trigonometric: expand, separate, contract, substitute, simplify
- Calculus: differentiate
For example, let's try to contract the trigonometric expression \((\cos{x})^4\) into \(\frac{3}{8} + \frac{1}{2}\cos{2x} + \frac{1}{8}\cos{4x}\):
1:
|
|
Algebraic Algorithms
These modules can also be combined to build more interesting manipulations. For example, let's implement a taylor expansion routine to approximate the shape of a differentiable function \(x(\zeta)\) at some point \(\zeta = a\) by its \(k-1\) first derivatives at that point (order \(k\)). We can leverage the existing structural substitute routine to substitute \(\zeta\) with \(a\) to get the resulting expression at \(a\), and the differentiate routine to evaluate the partial derivative \(\frac{\partial{x}}{\partial\zeta}\).
1: 2: 3: 4: 5: 6: 7: |
|
Let's use this routine to approximate \(\sin{x}+\cos{x}\) at \(x = 0\) using the first 4 derivatives:
1:
|
|
Math.NET Symbolics with C#, VB.NET and C++/CLI
Even though Math.NET Symbolics is written entirely in F#, it can be used in C# almost exactly the same way. The equivalent C# code to the F# code above could look as follows:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: |
|
Code for C++/CLI project is almost exactly the same but there are some things that worth to mention separately:
1.NuGet package manager doesn't have support for C++/CLI projects yet. So if you try to install the package with NuGet you may see this error:
Could not install package 'MathNet.Symbolics 0.19.0'. You are trying to install this package into a project that targets 'native,Version=v0.0', but the package does not contain any assembly references or content files that are compatible with that framework.
There are other ways to add the library to the project:
- Use other dependency manager like Paket.
-
Add references manually:
- Download packages. Although NuGet cannot include packages to the project it is downloading them to common package directory anyway.
- Right click on the project in the Solution Explorer
- Add -> References...
- Click Browse button
- Navigate to packages directory.
-
Add reference to the next dlls:
- FParsec.dll
- FParsecCS.dll
- FSharp.Core.dll
- MathNet.Numerics.FSharp.dll
- MathNet.Symbolics.dll
Also to avoid version conflict of FSharp.Core you have to set AutoGenerateBindingRedirects
to true
. Put the instruction in your .vcxproj file under "Globals" property section:
1: 2: 3: |
|
- Instead of using
+
and-
operators it's better to chooseAdd
andSubtract
methods to get away from warning about matching more than one operator.
Here is F# sample translated into C++/CLI:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: |
|
For VB.NET we won't do the same thing here but instead we just show basic usage for now
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: |
|