5

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.

Community
  • 1
  • 1
Santi Peñate-Vera
  • 1,053
  • 4
  • 33
  • 68
  • 1
    Can you give some more examles of what is changing? For example show what your currently have ie your *2 nested for loops*.... – Chris Moutray Mar 21 '14 at 08:58
  • Yes, so the constants are G and B, and the variables can be (V, theta) or (Q, theta) depending of the node type, but for simplicity sake the variables are V and Theta. if I have 3 nodes, I will have 6 equations P1, Q1, P2, Q2, P3, Q3 with 6 unkowns (V1, theta1, V2, theta2, V3, theta3), but the number of nodes is specified at runtime – Santi Peñate-Vera Mar 21 '14 at 09:03
  • You would probably have to build a basic DSL. – Rezo Megrelidze Mar 21 '14 at 09:13
  • ... and can you update the question to include your existing code the *2 nested for loops* – Chris Moutray Mar 21 '14 at 09:14

1 Answers1

2

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.

Luaan
  • 62,244
  • 7
  • 97
  • 116
  • I think I got it, I'll try if I can apply this. – Santi Peñate-Vera Mar 21 '14 at 09:12
  • Luaan, How would you define the sumation, I'm new to this kind of functions and I don't know how to implement the "For (int j=0; j< n; j++){...}" – Santi Peñate-Vera Mar 21 '14 at 12:18
  • @user3020849 This is outside of the scope of the original question, however... what are you actually trying to do? What are you trying to solve? What inputs and outputs are you expecting? As for the summation, that's very tricky. First, I'd have a look at the EO library - maybe they have a sum function that's optimized for their use. If not, you'll have to dynamically build the functions as well, which means manually calling the various `Expression.Call` and such; however, I'm affraid that might be too complicated for EO to handle fast - you should be able to approximate the solution better. – Luaan Mar 21 '14 at 12:33
  • Well the problem is called Power Flow, it is solved using Newton Raphson for systems of equations (amongh other methods) and of course there's no simple way of solving it.http://en.wikipedia.org/wiki/Power-flow_study – Santi Peñate-Vera Mar 21 '14 at 12:58
  • @user3020849 Yeah, that's what I've found. How do you expect the EO library to help you? What can it actually do finding a solution to that? – Luaan Mar 21 '14 at 13:17
  • The solution to the equations is knowing the state of a power system (complex power and complex voltage for every node) given generation values and load values. Actually my objective is to include the equations plus contour conditions to get optimum values (optimization), such as economic dispatch of generators, minimum loses, etc. – Santi Peñate-Vera Mar 21 '14 at 13:59