Combining delegates in C# (Sum-Product Algorithm)

284 views Asked by At

I am currently implementing belief propagation for discrete variables.

The messages are functions. I need to be able to combine them using products and sums to produce new functions.

I currently have a basic implementation using delegates, but I want to know if there is a better way to handle this. I'm also concerned about how this will scale using delegates.

Here is an example of my implementation:

public Func<double, double> ProductFunc(List<Func<double, double>> messages)
{
    // Construct the product of the message functions
    Func<double, double> productFunc = delegate(double x)
    {
        double productValue = 1.0;
        foreach(Func<double, double> message in messages)
        {
            productValue *= message(x);
        }
        return productValue;
    };

    return productFunc;

}

Is there a more effective way to achieve this?

1

There are 1 answers

1
Peter Duniho On BEST ANSWER

Does the code you have actually do what you want?

I ask, because the specification isn't very clear. The code you have captures a reference to a List<Func<double, double>> object, and returns a Func<double, double> delegate that will enumerate the list as it is at the time the delegate is invoked (as opposed to using the list as it is at the time your method was called).

Maybe that's really what you want. It's consistent with the deferred execution that is used throughout e.g. LINQ. But it does mean that the caller should either intend that changes to the list will change the evaluation of the returned delegate, or it must be very careful to not change the list.

If instead what you are trying to achieve is to capture the mathematical relationship present at the time of the call, you might rather the method look something like this:

public Func<double, double> ProductFunc(List<Func<double, double>> messages)
{
    Func<double, double> productFunc = x => 1.0;

    foreach (Func<double, double> message in messages)
    {
        Func<double, double> currentFunc = productFunc;

        productFunc = x => currentFunc(x) * message(x);
    }

    return productFunc;
}

It seems to me that either way is fine. It just depends on what behavior it is you actually want the code to have. There's not enough context in your question for me to know that.

I'm also concerned about how this will scale using delegates

It should scale just fine. You're already using delegates anyway. Composing them in either fashion isn't likely to cause undue performance issues, and in any case the code is correctly expressive as-is. If you do run into a specific performance problem such that the code fails to meet some objective, measurable performance goal, then you can look at adjusting the code to address that (and likely losing at least some expressiveness in the process).