-
Notifications
You must be signed in to change notification settings - Fork 76
Expressions
Any expression in AngouriMath is a tree. It may include numbers, variables, operators, functions, vectors, and more.
The main class, representing the library, is called Entity
. It is an abstract record, so every expression is a derived
type of Entity
.
Include the main namespace of the library: using AngouriMath; Now, let us create a simple arithmetic expression.
To build a tree we use overriden operators, for example,
var (x, y) = MathS.Var("x", "y");
var expr = x + 4 * MathS.Sin(x / y);
expr
has the type of Entity.Sumf
, which is a derived type of Entity
.
Now, let us see another way of doing the same thing:
using static AngouriMath.MathS;
using static AngouriMath.Entity;
Variable x = "x"; // implicit conversation
Variable y = "y";
var expr = x + 4 * Sin(x / y);
The first two using
s are implied by default in all other code snippets provided in Wiki.
AngouriMath internally uses PeterO.Numbers, so here are how numbers in AM could be created:
using static AngouriMath.Entity.Number;
using PeterO.Numbers;
var a01 = Integer.Create(3);
var a02 = Integer.Create(EInteger.FromInt32(3));
var a03 = Rational.Create(3.4);
var a04 = Rational.Create(ERational.FromDouble(3.4));
var a05 = Real.Create(1.3234m);
var a06 = Real.Create(EDecimal.FromDouble(3.4535));
var a07 = Complex.Create(32.4m, 434);
var a08 = Complex.Create(EDecimal.FromDecimal(32.4m), EDecimal.FromInt32(434));
Now, let us shorten the creation of an expression and parse it from an expression. Here are two lines of the equivalent code:
Entity a = "x^2 + x + 4 / 5 + sqrt(5)";
var a = FromString("x^2 + x + 4 / 5 + sqrt(5)");
In some cases we can omit operators, for example, here are equivalent lines:
Entity a = "x2 + 4y";
Entity a = "x^2 + 4*y";
Most operators and functions have a fixed number of arguments, for instance, plus operator cannot have three or more arguments. Here are two lines of the equivalent code:
Entity a = "x + 2";
Entity b = "y";
var theirSum1 = new Sumf(a, b);
var theirSum2 = a + b;
In most code snippets in the rest of the wiki we will use implicit conversations.
Here more on different ways to parse.
To substitute a particular value instead of a variable, use method Substitute
:
Entity expr = "x + 2";
var newExpr = expr.Substitute("x", 3);
It is the same as
Entity newExpr = "3 + 2";
It does not change the initial expression. Moreover, all subtypes of Entity
are immutable and cannot be changed by any method or function.
This allows to safely pass any expression to any functions being sure that it will not change. As a result, any operation will create a
new expression.
Here info on using method Substitute
.
Nodes
is a property of every expression. This property contains all possible subnodes of a node including itself. Let us consider an example:
Entity expr = "a * x + 2";
foreach (var subExpr in expr.Nodes)
Console.WriteLine(subExpr);
The output will be the following:
a * x + 2
a * x
a
x
2
We can also analyze a given expression through patterns. Let us implement a naive differentiating:
static Entity Diff(Entity expr, Variable var)
=> expr switch
{
Variable sameVar when sameVar == var => 1,
Variable otherVar => 0,
Number => 0,
Sumf(var left, var right) => Diff(left, var) + Diff(right, var),
Mulf(var left, var right) => Diff(left, var) * right + Diff(right, var) * left,
Sinf(var arg) => Cos(arg) * Diff(arg, var),
_ => throw new Exception()
};
Thanks to C#9's pattern matching, now we can this easily switch over different types of an expression. Let us run the given function:
Console.WriteLine(Diff("a x + 3sin(x + c)", "x"));
The output will be the following:
0 * x + 1 * a + 0 * sin(x + c) + cos(x + c) * (1 + 0) * 3
When building an expression, no automatic simplification occurs.
Now let's assume we want our custom domain-specific simplification, where we assume that cos
is sin
and that sum of powers of two expressions is power of sum.
using static AngouriMath.MathS;
using static AngouriMath.Entity;
Entity SomeSimplify(Entity expr) => expr switch
{
Cosf(var e) => Sin(e),
Sumf(Powf(var e1, var p1), Powf(var e2, var p2))
when p1 == p2 => Pow(e1 + e2, p1),
var other => other
};
var (x, y) = Var("x", "y");
var expr = Sin(Cos(Sqr(x + y) + Sqr(x)));
var newExpr = expr.Replace(SomeSimplify);
Console.WriteLine(newExpr);
Should print:
sin(sin((x + y + x) ^ 2))
Here more info on Replace
method.
If you did not find what you were looking for, feel free to create an issue raising your problem.