Library for analytical calculation of mathematical expressions. Сurrently derivative and simplifiers are supported.
P.S. this is just my project to learn some C# basics, so take it easy
-
For all of this to work you need to prepend each piece with
using static Derivas.Expression.DvOps;
But you may use it as you want in your real code.
-
Most of the methods accept
object
as it's argument, but this means that you can pass in numeric type(shortcut for aConst
) or string(for aSym
) andIDvExpr
. This was done to prevent writing this:Add(Const(3), Sym("x"), Pow(Const(5), Const(3))
And transform it to
Add(3, "x", Pow(5, 3))
Open sln in visual studio/rider/... or from the command line:
dotnet build Derivas # to build from cli
dotnet test Derivas.Tests # to test
using static Derivas.Expression.DvOps;
namespace Usage
{
internal class Program
{
private static void Main(string[] args)
{
var finExpr = Add(Pow(Sin("x"), 2), Pow(Cos("x"), 2));
var finDict = new Dictionary<string, double>()
{
{ "x", Math.PI }, { "y", 1 }
};
Print(finExpr, finDict);
// sin(x) ^ 2 + cos(x) ^ 2
// 1
var derived = Der(finExpr, "x");
Print(derived, finDict);
// 2 * sin(x) * cos(x) - 2 * cos(x) * sin(x)
// 0
var simplified = Simpl(finExpr)
.ByCustom(Pow(Sin("x"), 2), 3)
.Simplify();
Print(simplified, finDict);
// 3 + cos(x) ^ 2
// 4
var parsedExpr = Parse("sin(x) ^ 2 + cos(x)^2");
Print(parsedExpr, finDict);
// the same as the original
}
private static void Print(IDvExpr expr, Dictionary<string, double> dict)
{
Console.WriteLine(expr.Represent());
Console.WriteLine(expr.Calculate(dict));
}
}
}
There are two main entities in Derivas: Expression
and Simplifier
, which implemented as interfaces: IDvExpr
and IDvSimplifier
accordingly.
Ultimate base interface. Symbol, Constant, Operators implement it.
interface IDvExpr : IEquatable<IDvExpr>
{
double Calculate(IDictionary<string, double> concrete);
string Represent();
}
Go to the full expressions reference here.
Simplifier performs some kind of transformation, it has only one method:
IDvExpr Simplify(IDvExpr expr)
In external API you should use it like this:
IDvExpr res = Simpl(/* IDvExpr */ expr)
.By...()
.By...()
.Simplify();
There are 4 kinds of simplifiers:
Partially reduce constants in operators:
Add(3, 5, 10) -> Const(18)
Mul(3, 5, "x") -> Add(8, "x")
Collect similar expressions in one scope:
Add("x", "x", "x") -> Mul(3, "x")
Add("x", "y", "x") -> Add(Mul(2, "x"), "y")
Partially replace some symbols from the dictionary or by hand:
The Dict
is explained here
IDictionary<string, double> d = Dict.Add("x", 5).Add("y", 3).Get();
var expr = Add("x", Pow(2, "y"), "z");
var simplified = Simpl(expr).ByPartial(d).Simplify();
// 5 + 2 ^ 3 + z
var orTheSame = Simpl(expr).ByPartial("x", 5).ByPartial("y", 3).Simplify();
// 5 + 2 ^ 3 + z
Replace one IDvExpr with another or use your own simplifiers:
var expr = Log(Mul(2, "x"), 3);
var replaced = Simpl(expr).ByCustom(3, DvConsts.E).Simplify();
var orTheSame = Simpl(expr)
.ByCustom(expr => Const(3).Equals(expr) ? DvConsts.E : expr)
.Simplify();
- API:
Add
,Mul
- Description: takes more than one argument, order doesn't matter
- Example:
Add(3, 5, "x", Add(6, 3))
- Throws:
DvNotEnoughArguments
- API:
Sub
,Div
,Pow
- Description: takes only two arguments, order does matter
- Example:
Div(Pow(1, 2), 0)
- Throws: no Dv exceptions
- API:
Cos
,Sin
,Tan
,Cotan
Acos
,Asin
,Atan
,Acotan
Cosh
,Sinh
,Tanh
,Cotanh
- Description: takes one argument
- Example:
Cos(Sin(DvConsts.PI)) // equals 1
- Throws: no Dv exceptions
Log
- acts just likeMath.Log
, takes two parameters and one is optionalDer
- takes expression and symbol to take derivative on.
All exceptions are located in Derivas.Exception
namespace.
-
DvBaseException
- base exception class for the project -
DvSymbolMismatchException
- symbol value not supplied during calculation -
DvDerivativeMimatchException
- no derivative rule for this expression -
DvNotEnoughArguments
- the wrong number of arguments passed to the operator
Some useful features to help you use the library.
Takes string and returns it's IDvExpr
equivalent. Temporarily not accepting numbers with exponent in them(like 1e-10
).
You will frequently need an IDictionary<string, double>
to pass into Calculate
or other such methods. but it's very verbose to create new dictionary each time, so here you go, a shortcut:
double res = expr.Calculate(Dict.Add("x", 1).Add("y", 3).Get());
Common mathematical constants in IDvExpr
(surrounded with DvOps.Const
):
DvOps.DvConsts.E
Dvops.DvConsts.PI