Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define a function dynamically

I am testing the Extreme Optimization C# library, precisely the nonlinear system solvers. As an example I find that I have to pass the solver the nonlinear system in the following shape:

Func<Vector, double>[] f = {
  x => Math.Exp(x[0])*Math.Cos(x[1]) - x[0]*x[0] + x[1]*x[1],
  x => Math.Exp(x[0])*Math.Sin(x[1]) - 2*x[0]*x[1]
};

The problem is that the system I try to solve cannot be specified at design time. It is a nonlinear system composed by the load flow equations to solve an electrical circuit of altern current (AC). The equations are composed by a number of variables that depend of the number of nodes in the grid, which is especified by the user, the equations are these:

enter image description here

So basically I have 2 equations per node, this is 2*n equations, which cannot be composed in a single line bacause they depend of i,j indices, therefore I have to have 2 nested for loops to create the P and Q equations.

Is there a way to create Func<Vector, double>[] f = { equation system of variable lenght }; ?

I have seen the post Creating a function dynamically at run-time, but it doesn't answer my quetion (I believe)

//************************EDIT**************************************

The creation of the equations is something like this:

For (int i=0; i< n; i++){
   double A=0.0;
   double B=0.0;
   For (int j=0; j< n; j++){
      A+= G[i,j]*Math.Cos(Theta[i,j]) + B[i,j]*Math.Sin(Theta[i,j])
      B+= G[i,j]*Math.Sin(Theta[i,j]) + B[i,j]*Math.Cos(Theta[i,j])
   }
   P[i]=V[i]*A;
   Q[i]=V[i]*B;
}

Ofcourse A and B contain the variables, and this loop formulation as it is makes little sense.

Thanks in advance.

like image 658
Santi Peñate-Vera Avatar asked Nov 01 '22 03:11

Santi Peñate-Vera


1 Answers

You're passing a function array, so it should be pretty easy to do what you want:

Func<Vector, double>[] funcs = new Func<Vector, double>[howeverManyYouWant];

for (var i = 0; i < howeverManyYouWant; i++)
{
  var someConstant = 0.1f * i; // You need to define "constants" in scope

  funcs[i] = x => Math.Exp(x[0])*Math.Cos(x[1]) - x[0]*x[0] + x[1]*x[1];
}

You can then pass the array as needed.

If you can't determine the size of the array in advance, you can use List<Func<Vector, double>> instead of an array, and then just call ToArray() on it when it's ready.

EDIT: I've just realized you aren't actually passing Expression<Func<...>> - this makes everything all that much simpler, since you can use a for cycle inside the function you're passing:

List<Func<Vector, double>> funcs 
  = new List<Func<Vector, double>>(howeverManyYouWant * 2);

for (var i = 0; i < howeverManyYouWant; i++)
{
  // P[i] equation
  funcs.Add
  (
    x => 
    {
      var a = 0d;

      for (var j = 0; j < howeverManyYouWant; j++)
      {
        a += G[i, j] * Math.Cos(Theta[i, j]) + B[i, j] * Math.Sin(Theta[i, j]);
      }

      return x[i] * a;
    }
  );

  // Add your Q[i] equation here the same way.
  funcs.Add(...);
}

You'll have to modify it to really fit your case, because I have no idea how the func array is called, what's passed to the function, what you want to have as a constant or a variable etc. (I've just replaced V with x in this example), but it does show the basic idea.

Of course you'll want to refer to x somewhere, otherwise you could obviously just precompute the value - but that would hardly be helpful :)

Given that, I can't know if that's what you're after. You'll have to specify what should be considered a constant, what's being passed to the functions etc.

like image 110
Luaan Avatar answered Nov 09 '22 06:11

Luaan