Skip to content
211 changes: 210 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,215 @@
Math.NET Symbolics
Math.NET Symbolics (With Matrix/Vector/Customized Function supported)
# if you are interested about it, send me an email to join this repo:

https://github.com/ingted/coldfar-symbolics

# 2022-03-21 The progress is really great. Critical lambda compilation and evaluation bugs are resolved. So you can easily extend symbolic operation with tensor value in Math.Net.

```
let a0 = SymbolicExpression(Infix.parseOrThrow("v * 2")).Evaluate(symbols2)
printfn "%A" a0.RealVectorValue
let a1 = SymbolicExpression(Infix.parseOrThrow("v + 1")).Evaluate(symbols2)
printfn "%A" a1.RealVectorValue
let a2 = SymbolicExpression(Infix.parseOrThrow("mat_by_row(v, v)")).Evaluate(symbols2)
printfn "%A" a2.RealMatrixValue
let a3 = SymbolicExpression(Infix.parseOrThrow("mat_by_col(v, v)")).Evaluate(symbols2)
printfn "a3: %A" a3.RealMatrixValue
let a4 = SymbolicExpression(Infix.parseOrThrow("mat_multiply(m, mat_by_col(v, vec(1.0,2.0,3.0), v), v)")).Evaluate(symbols2)
printfn "a4: %A" a4

cFun ("mat_by_row", []) |> ignore

let symV = Symbol "v"
let symW = Symbol "w"

let symV1 = Symbol "v1"
let symW1 = Symbol "w1"
let symV2 = Symbol "v2"
let symW2 = Symbol "w2"
let symX = Symbol "x"
let syml = dict [ "x", FloatingPoint.Real 9.0; ]
let _ = define "t0" ([symV; symW], (v + w))
let _ = define "t1" ([symV; symW], Infix.parseOrThrow("t0(v, w)"))
let _ = define "t2" ([symV; symW], Infix.parseOrThrow("2 * t0(v, w) / 3"))

let lambdaExp =
try
MathNet.Symbolics.Linq.formatLambda (cFun("t0", [x; x])) [symV; symW] //intensive error
with
| _ -> None

printfn "t0: %A" <| SymbolicExpression(cFun("t0", [x; x])).Evaluate(syml)
printfn "t0-2: %A" <| SymbolicExpression.Parse("1 + t0(x, x)").Evaluate(syml)
printfn "2 * t1(x, t1(x, x)) / t1(2 * x, x) * 4: %A" <| SymbolicExpression.Parse("2 * t1(x, t1(x, x)) / t1(2 * x, x) * 4").Evaluate(syml)

let infix2 = Infix.parseOrThrow("2 * t0(v1, w1) / 3")
let lambdaExp2 =
try
MathNet.Symbolics.Linq.formatLambda infix2 [symV2; symW2] //intensive error
with
| _ -> None

let infix3_0 = Infix.parseOrThrow("t0(x, x)")
let infix3_1 = Infix.parseOrThrow("t1(x, x)")
let infix3_2 = Infix.parseOrThrow("t2(x, x * 2)")
let infix3 = Infix.parseOrThrow("2 * t2(x, x) / 3 + t2(x, x * 2)")


let (Some lambdaExp3_0) = MathNet.Symbolics.Linq.formatLambda infix3_0 [symX]
let (Some lambdaExp3_2) = MathNet.Symbolics.Linq.formatLambda infix3_2 [symX]
let (Some lambdaExp3) = MathNet.Symbolics.Linq.formatLambda infix3 [symX]

let toEvaluate = SymbolicExpression.Parse("2 * t2(x, x) / 3 + t2(x, x * 2)")
let (Some toLambda) = MathNet.Symbolics.Linq.formatLambda toEvaluate.Expression [symX]

printfn "2 * t2(x, x) / 3 + t2(x, x * 2): %A" <| toEvaluate.Evaluate(syml)
printfn "t1(x, 2 * t0(x,x)): %A" <| SymbolicExpression(cFun("t1", [x; 2 * cFun("t0", [x; x])])).Evaluate(syml)
printfn "t1(x, 2 * t1(x,x)): %A" <| SymbolicExpression(cFun("t1", [x; 2 * cFun("t1", [x; x])])).Evaluate(syml)
printfn "t0(x, t0(x, x) * 2): %A" <| SymbolicExpression(cFun("t0", [x; cFun("t0", [x; x]) * 2])).Evaluate(syml)
printfn "t0(x, t1(x, x) * 2): %A" <| SymbolicExpression(cFun("t0", [x; cFun("t1", [x; x]) * 2])).Evaluate(syml)

let a5 = SymbolicExpression(Infix.parseOrThrow("2 * mat_multiply(m, mat_by_col(v, vec(1.0,2.0,3.0), v), v)")).Evaluate(symbols2)
printfn "a5: %A" a5

let a6 = SymbolicExpression.Parse("2 * htensor(lo(lo(lo(vec(1,2,3), vec(4,5,6)), lo(vec(7,8,9), vec(10,11,12)))))").Evaluate(symbols2)
printfn "a6:%A" a6

let a7expr = SymbolicExpression.Parse("t0(1, 2 * htensor(lo(lo(lo(vec(1,2,3), vec(4,5,6)), lo(vec(7,8,9), vec(10,11,12))))))")
let a7 = a7expr.Evaluate(symbols2)
printfn "a7:%A" a7
```
Results:
```
seq [2.0; 4.0; 6.0]
seq [2.0; 3.0; 4.0]
DenseMatrix 2x3-Double
1 2 3
1 2 3

a3: DenseMatrix 3x2-Double
1 1
2 2
3 3

a4: RealVector (seq [18.0; 30.0; 84.0])
t0: Real 18.0
t0-2: Real 19.0
2 * t1(x, t1(x, x)) / t1(2 * x, x) * 4: Real 8.0
2 * t2(x, x) / 3 + t2(x, x * 2): Real 26.0
t1(x, 2 * t0(x,x)): Real 45.0
t1(x, 2 * t1(x,x)): Real 45.0
t0(x, t0(x, x) * 2): Real 45.0
t0(x, t1(x, x) * 2): Real 45.0
a5: RealVector (seq [36.0; 60.0; 168.0])
twl.Length: 1
twl.Length: 2
twl.Length: 2
v.Count: 3
v.Count: 3
twl.Length: 2
v.Count: 3
v.Count: 3
a6:WTensor
(DSTensor
tensor([[[[ 2., 4., 6.],
[ 8., 10., 12.]],

[[14., 16., 18.],
[20., 22., 24.]]]]))
twl.Length: 1
twl.Length: 2
twl.Length: 2
v.Count: 3
v.Count: 3
twl.Length: 2
v.Count: 3
v.Count: 3
a7:WTensor
(DSTensor
tensor([[[[ 3., 5., 7.],
[ 9., 11., 13.]],

[[15., 17., 19.],
[21., 23., 25.]]]]))
```






2022-03-12 Now there is a private repo which supports DiffSharp Tensor within Math.NET Symbolics. (very rough/early stage)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add small interesting functions to support Vector, Matrix, Tensor values.

The code would look like this:

open System
open MathNet.Numerics.LinearAlgebra
open MathNet.Symbolics
open Definition
open Operators
open VariableSets.Alphabet

let V = FloatingPoint.RealVector <| vector[1.0;2.0;3.0]

let M = FloatingPoint.RealMatrix <|
        matrix [[3.0; 0.0; 0.0]
                [1.0; 2.0; 0.0]
                [0.0; 1.0; 4.0]]

let symbols2 = dict[ "a", V; "m", M ]


type A = {
    trivial: bool
}


[<EntryPoint>]
let main argv =
    let a0 = SymbolicExpression(Infix.parseOrThrow("a * 2")).Evaluate(symbols2)
    printfn "%A" a0.RealVectorValue
    let a1 = SymbolicExpression(Infix.parseOrThrow("a + 1")).Evaluate(symbols2)
    printfn "%A" a1.RealVectorValue
    let a2 = SymbolicExpression(Infix.parseOrThrow("mat_by_row(a, a)")).Evaluate(symbols2)
    printfn "%A" a2.RealMatrixValue
    let a3 = SymbolicExpression(Infix.parseOrThrow("mat_by_col(a, a)")).Evaluate(symbols2)
    printfn "%A" a3.RealMatrixValue
    let a4 = SymbolicExpression(Infix.parseOrThrow("mat_multiply(m, mat_by_col(a, vec(1.0,2.0,3.0), a), a)")).Evaluate(symbols2)
    printfn "%A" a4

    cFun ("mat_by_row", []) |> ignore

    let symV = Symbol "v"
    let symW = Symbol "w"
    let syml = dict[ "x", FloatingPoint.Real 9.0; ]
    let _ = define "t0" ([symV; symW], (v + w))
    printfn "t0: %A" <| SymbolicExpression(cFun("t0", [x; x])).Evaluate(syml)
    let _ = define "t1" ([symV; symW], Infix.parseOrThrow("t0(v, w)"))
    printfn "2 * t1(x, t1(x, x)) / t1(2 * x, x) * 4: %A" <| SymbolicExpression.Parse("2 * t1(x, t1(x, x)) / t1(2 * x, x) * 4").Evaluate(syml)
    let _ = define "t2" ([symV; symW], Infix.parseOrThrow("2 * t0(v, w) / 3"))
    printfn "2 * t2(x, x) / 3 + t2(x, x * 2): %A" <| SymbolicExpression.Parse("2 * t2(x, x) / 3 + t2(x, x * 2)").Evaluate(syml)
    printfn "t1(x, 2 * t0(x,x)): %A" <| SymbolicExpression(cFun("t1", [x; 2 * cFun("t0", [x; x])])).Evaluate(syml)
    printfn "t1(x, 2 * t1(x,x)): %A" <| SymbolicExpression(cFun("t1", [x; 2 * cFun("t1", [x; x])])).Evaluate(syml)
    printfn "t0(x, t0(x, x) * 2): %A" <| SymbolicExpression(cFun("t0", [x; cFun("t0", [x; x]) * 2])).Evaluate(syml)
    printfn "t0(x, t1(x, x) * 2): %A" <| SymbolicExpression(cFun("t0", [x; cFun("t1", [x; x]) * 2])).Evaluate(syml)

    let a5 = SymbolicExpression(Infix.parseOrThrow("2 * mat_multiply(m, mat_by_col(a, vec(1.0,2.0,3.0), a), a)")).Evaluate(symbols2)
    printfn "%A" a5

    let a6 = SymbolicExpression.Parse("2 * htensor(lo(lo(lo(vec(1,2,3), vec(4,5,6)), lo(vec(7,8,9), vec(10,11,12)))))").Evaluate(symbols2)
    printfn "%A" a6

If you are interested about it, I can add you...
(Why private? Because it is just like a toy and still a lot of works to do... )

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output:

seq [2.0; 4.0; 6.0]
seq [2.0; 3.0; 4.0]
DenseMatrix 2x3-Double
1  2  3
1  2  3

DenseMatrix 3x2-Double
1  1
2  2
3  3

RealVector (seq [18.0; 30.0; 84.0])
t0: Real 18.0
2 * t1(x, t1(x, x)) / t1(2 * x, x) * 4: Real 8.0
2 * t2(x, x) / 3 + t2(x, x * 2): Real 26.0
t1(x, 2 * t0(x,x)): Real 45.0
t1(x, 2 * t1(x,x)): Real 45.0
t0(x, t0(x, x) * 2): Real 45.0
t0(x, t1(x, x) * 2): Real 45.0
RealVector (seq [36.0; 60.0; 168.0])
twl.Length: 1
twl.Length: 2
twl.Length: 2
v.Count: 3
v.Count: 3
twl.Length: 2
v.Count: 3
v.Count: 3
WTensor
  (DSTensor
     tensor([[[[ 2.,  4.,  6.],
          [ 8., 10., 12.]],

         [[14., 16., 18.],
          [20., 22., 24.]]]]))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Why private? Because it is just like a toy and still a lot of works to do... )

Then, it should not be mentioned in ReadMe. Feel free to create issue though.

If you are interested about it, please leave a message in issues.

==================

For supporting code like the following:

```
#r @"src\Symbolics\bin\Debug\netstandard2.0\MathNet.Symbolics.dll"
#r @"nuget:MathNet.Numerics"
#r @"nuget:FsUnit"
#r @"nuget:FParsec"
#r @"nuget:MathNet.Numerics.FSharp"
#load @"src\Symbolics.Tests\Global.fs"

open MathNet.Numerics
open MathNet.Symbolics
open Global
open Operators
open VariableSets.Alphabet
type Expr = SymbolicExpression

let symV = Symbol "v"
let symW = Symbol "w"
let symX = Symbol "x"
let symY = Symbol "y"
let symZ = Symbol "z"


open Definition
define "test" ([symV; symW], (v + w)*2)
SymbolicExpression(Infix.parseOrThrow("2^test(x, 2 * x)")).Evaluate(dict[ "x", FloatingPoint.Real 2.0; ])
```

Result:
```
val it : FloatingPoint = Real 4096.0
```

Code:
```
SymbolicExpression(cFun("test", [x + (fromInt32 10); (fromDouble 100.0)])*2).Evaluate(dict[ "x", FloatingPoint.Real 9.0; ])

```

Result:
```
val it : FloatingPoint = Real 476.0
```


```
open System
open MathNet.Numerics.LinearAlgebra
open MathNet.Symbolics
let v = FloatingPoint.RealVector <| vector[1.0;2.0;3.0]

let symbols2 = dict[ "a", v ]

[<EntryPoint>]
let main argv =
let a0 = SymbolicExpression(Infix.parseOrThrow("a * 2")).Evaluate(symbols2)
printfn "%A" a0.RealVectorValue
let a1 = SymbolicExpression(Infix.parseOrThrow("a + 1")).Evaluate(symbols2)
printfn "%A" a1.RealVectorValue
let a2 = SymbolicExpression(Infix.parseOrThrow("mat_by_row(a, a)")).Evaluate(symbols2)
printfn "%A" a2.RealMatrixValue
let a4 = SymbolicExpression(Infix.parseOrThrow("mat_multiply(m, m, a)")).Evaluate(symbols2)
printfn "%A" a4
0 // return an integer exit code
```

Math.NET Symbolics is a basic open source **computer algebra library for .NET, Silverlight and Mono** written entirely 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 proprietary commercial solutions Maple, Mathematica or Wolfram Alpha.
Expand Down
18 changes: 18 additions & 0 deletions debugger/Program.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Learn more about F# at http://fsharp.org

open System
open MathNet.Numerics.LinearAlgebra
open MathNet.Symbolics
let v = FloatingPoint.RealVector <| vector[1.0;2.0;3.0]

let symbols2 = dict[ "a", v ]

[<EntryPoint>]
let main argv =
let a0 = SymbolicExpression(Infix.parseOrThrow("a * 2")).Evaluate(symbols2)
printfn "%A" a0.RealVectorValue
let a1 = SymbolicExpression(Infix.parseOrThrow("a + 1")).Evaluate(symbols2)
printfn "%A" a1.RealVectorValue
let a2 = SymbolicExpression(Infix.parseOrThrow("mat_by_row(a, a)")).Evaluate(symbols2)
printfn "%A" a2.RealMatrixValue
0 // return an integer exit code
16 changes: 16 additions & 0 deletions debugger/debugger.fsproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Compile Include="Program.fs" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\src\Symbolics\Symbolics.fsproj" />
</ItemGroup>

</Project>
3 changes: 3 additions & 0 deletions src/Symbolics.Tests/Compilation/Compilation.fs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ module Compilation =
let expr9 = x + 1
(Compile.compileExpression1OrThrow expr9 symX).Invoke(1.0) --> 2.0

let expr10' = y * y + Expression.I * y + (besselk x (Expression.I * y)) / (besselk (negate x) (Expression.I * y))
(Compile.compileComplexExpression2OrThrow expr10' symX symY).Invoke(toComplex 0.5, System.Numerics.Complex.One) --> complex 2.0 1.0

let expr1' = x
(Compile.compileComplexExpression1OrThrow expr1' symX).Invoke(toComplex 3.0) --> toComplex 3.0

Expand Down
49 changes: 49 additions & 0 deletions src/Symbolics/Definition.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
namespace MathNet.Symbolics

module Definition =

type DefType =
| DTExp of (Symbol list) * Expression
| DTFunAction of (unit -> unit)
| DTFunI1toI1 of (int -> int)
| KeyWord

let funDict = new System.Collections.Concurrent.ConcurrentDictionary<string, DefType>()

let kwlist = [ "vec", true; "mat_by_row", true; "mat_by_col", true ]

let keyWord = dict kwlist

kwlist |> List.iter (fun (k, _) -> funDict.TryAdd(k, KeyWord) |> ignore)

let defineSafe fnm exp =
if keyWord.ContainsKey fnm then
failwith "used function name"
funDict.TryAdd (fnm, DTExp exp)

let define fnm exp =
if keyWord.ContainsKey fnm then
failwith "used function name"
funDict.AddOrUpdate(
fnm
, (fun nm -> DTExp exp)
, (fun nm cur_exp -> DTExp exp)
)

let defAct fnm f =
if keyWord.ContainsKey fnm then
failwith "used function name"
funDict.AddOrUpdate(
fnm
, (fun nm -> DTFunAction f)
, (fun nm cur_exp -> DTFunAction f)
)

let def1ito1i fnm f =
if keyWord.ContainsKey fnm then
failwith "used function name"
funDict.AddOrUpdate(
fnm
, (fun nm -> DTFunI1toI1 f)
, (fun nm cur_exp -> DTFunI1toI1 f)
)
Loading