Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Such a thing as a calculation engine for C#?

Tags:

c#

propagation

Is there any calculation engine for C# that can automatically recalculate dependent fields when a value changes?

Let me freestyle for a second, I'm imagining something like this..

 Field<double> quantity = Field.Create<double>("Quantity");
 Field<double> unitCost = Field.Create<double>("Unit Cost");
 Field<double> total = Field.Create<double>("Total");

 total.Calculation((q,uc) => q * uc, quantity, value);
      // would have signature something like this:
      // void Calculation<TR,T1,T1>(Func<TR,T1,T2>, Field<T1>, Field<T2>)

This would set up fields that auto-propagate dependent values.

 quantity.Value = 5.0;
 unitCost.Value = 1.5;
 Assert.That(total.Value, Is.EqualTo(7.5));

Obviously this is a simple example, the end uses would be much more akin to the calculations of a complex spreadsheet.

Thinking further it would be amazing if the field/cells would support change notification.

like image 855
chillitom Avatar asked Feb 01 '11 16:02

chillitom


2 Answers

Have you seen http://ncalc.codeplex.com ?

It's extensible, fast (e.g. has its own cache) enables you to provide custom functions and varaibles at run time by handling EvaluateFunction/EvaluateParameter events. Example expressions it can parse:

Expression e = new Expression("Round(Pow(Pi, 2) + Pow([Pi2], 2) + X, 2)");

  e.Parameters["Pi2"] = new Expression("Pi * Pi");
  e.Parameters["X"] = 10;

  e.EvaluateParameter += delegate(string name, ParameterArgs args)
    {
      if (name == "Pi")
      args.Result = 3.14;
    };

  Debug.Assert(117.07 == e.Evaluate());

It also handles unicode & many data type natively. It comes with an antler file if you want to change the grammer. There is also a fork which supports MEF to load new functions.

It also supports logical operators, date/time's strings and if statements.

a solution

You could possibly do automatic recalculation by implementing INotifyPropertyChanged then doing something like

  • set a field's expression this.Field.Expression = new Expression("Field1+Field2");

On notifypropertyupdated in the class

  • for each field (with reflection) that is a Function
  • if it's expression refers to the changed field then recalculate the variable.
  • on recalculation you'd need to handle the EvaluateParameter event to use reflection to find the right field and extract its value (you could cache to avoid reflection if needed)
like image 54
GreyCloud Avatar answered Oct 03 '22 05:10

GreyCloud


There are calculation engines for scalar parameters, and there are higher-level calculation engines for tables, typically used for applications like financial planning, fee and commission calculations, network and contract computations...

Let me explain this shortly. Consider following formulas for scalars:

1) z = f1(x,y)
2) p = f2(z,n)
3) q = f3(x,p)
...

and so on. Configuring such functions and dependency trees requires a calculation engine with scalar parameters. I would (also) recommend following link for such a calculation engine written in c# as a good starting point: http://www.codeproject.com/Articles/246374/A-Calculation-Engine-for-NET

As mentioned, there are also calculation engines with table functions that take tables as parameters. The main principle is but the same:

1) (T4, T5) = TableFunction1(T1, T2, T3)  
2) (T7, T8) = TableFunction2(T2, T4)
...

and so on. Note that a table function can return multiple tables as outputs, as shown above.

There two key issues to be observed here:

a) The values of tables T7 and T8 depend on tables T2 and T4. Therefore, the tables T7 and T8 need to be updated by executing the function "TableFunction2" only if there is a change in one of the input parameters T2 or T4.

Similarly, T4 need to be updated only if T1, T2 or T3 is updated; dependency tree!

b) Separation of database from the calculation process: The calculation engine must work independent of any fixed data structure or database schema so that it can be integrated with any database and data structure.

You can find my related article where these principles are explained at:

Logical Architecture of a Rule-Based Calculation Framework http://finaquant.com/logical-architecture-of-a-rule-based-calculation-framework/1053

Now, a C#/.NET library for a calculation engine with tables as input and output parameters is being developed based on these principles.

Note to moderators: Please delete the link above if it is counted as self-promotion.

like image 29
tuncalik Avatar answered Oct 03 '22 03:10

tuncalik