Circular References and Custom Functions

Nov 6, 2007 at 2:22 PM
Edited Nov 15, 2007 at 10:01 PM
Hi Eugene,

We're trying to replace Formula Engine with Flee. We have a case where we need to do a calculation on 2 formulas that have a circular reference. In Formula Engine we seed one value with something and then go back and forth until the result converges.

Our code that does this is at the bottom of this message.

In Flee, can we write a custom function that has hooks into the engine, like Formula Engine lets us do?

Thanks a lot,
Dustin Aleksiuk



        [FixedArgumentFormulaFunction(2, new OperandType[] {OperandType.String, OperandType.String})]
        public void Converge(Argument[] args, FunctionResult result, FormulaEngine engine)
        {
            decimal seed = 0;
            string lhs = args[0].ValueAsString;
            string rhs = args[1].ValueAsString;
 
            INamedReference lhsRef = engine.ReferenceFactory.Named(lhs);
            INamedReference rhsRef = engine.ReferenceFactory.Named(rhs);
 
            Formula lhsFormula = engine.GetFormulaAt(lhsRef);
            Formula rhsFormula = engine.GetFormulaAt(rhsRef);
 
            engine.RemoveFormulaAt(lhsRef);
            engine.AddFormula(seed.ToString(), lhsRef);
            engine.Recalculate(lhsRef);
            double rhsResult = 0;
            double lhsResult = 0;
            for (int i = 0; i < 10; i++)
            {
                if (i%2 == 0)
                {
                    rhsResult = Convert.ToDouble(engine.Evaluate(rhs));
                    engine.RemoveFormulaAt(rhsRef);
                    engine.RemoveFormulaAt(lhsRef);
                    engine.AddFormula(rhsResult.ToString(), rhsRef);
                    engine.AddFormula(lhsFormula, lhsRef);
                    engine.Recalculate(rhsRef);
                }
                else
                {
                    lhsResult = Convert.ToDouble(engine.Evaluate(lhs));
                    engine.RemoveFormulaAt(rhsRef);
                    engine.RemoveFormulaAt(lhsRef);
                    engine.AddFormula(lhsResult.ToString(), lhsRef);
                    engine.AddFormula(rhsFormula, rhsRef);
                    engine.Recalculate(lhsRef);
                }
            }
 
            result.SetValue(lhsResult);
        }
Coordinator
Nov 6, 2007 at 8:17 PM
You have two options:
-Declare a variable of type CalculationEngine and pass it as an argument to a static function that you import: Converge(calcEngine, "arg1", "arg2")
-Use an expression owner: this is an instance of any class to which an expression will be attached. Once attached, the expression has access to all its fields, properties, and methods. Thus you can declare a class, set a field with the calculation engine, and define your converge method. You can then use an expression like converge("arg1", "arg2") and inside the convege method, access any members you need.
Nov 6, 2007 at 9:28 PM
Thanks a lot for the reply in this topic and the other one.

I had some trouble this morning getting a smooth transition to your new changes this morning, but I'll get back to it and try again before long.

Regards,
Dustin Aleksiuk