2

I am trying to use the Microsoft Solver Foundation to optimize a problem with a matrix of binary decision variables. Here is the format of my decision matrix:

X[i,j] = { { x11, x12, ..., x1n }, { x21, x22, ..., x2n }, ... { xm1, xm2, ..., xmn }, };

I also have a vector of parameters, which is dependent on Xij matrix (each element of the vector is sum of one column of Xij:

Y[i] = { Sum(x11, x21, ..., xm1), Sum(x12, x22, ..., xm2), ..., Sum(x1n, x2n, ..., xmn) }

I know that i should work with indexed Decision objects, but I have trouble doing that. Could anyone please help me. I understand there is two ways of indexing Decisions:

Decision Xij = new Decision(Domain.Any, "x", Some Set, Some other set);

and also there's:

`Decision[,] = new Decsion [i, j];`

What's the difference?

oguz ismail
  • 1
  • 16
  • 47
  • 69
  • Thanks for the answer. I tried c# array to define Decision variable. Problem is, in this case i can't use indexes to loop through decisions using static functions of the Model (e.g. Model.ForEach). I get this error: Cannot implicitly convert type Microsoft.SolverFoundation.Services.Term' to 'int' – Behrooz Ebrahimi Sep 28 '14 at 19:36
  • 'Model.ForEach' is only applicable for indexed *Decision* variables. If you use arrays, you simple write a ´for()´ loop which calculates the sum *Term*. This sum *Term* can than be put in a constraint. – Axel Kemper Sep 29 '14 at 11:34

2 Answers2

3

I created 2D arrays for Xij as follows:

static Decision[,] XijMatrix()
    {
        Decision[,] d = new Decision[int rows, int cols];
        for (int row = 0; row < rows; row++)
            for (int col = 0; col < cols; col++)
                d[row, col] = new Decision(Domain.Boolean, "X" + row + col);

        return d;
    }

and another array for Yj:

static Decision[,] YjMatrix()
    {
        Decision[,] d = new Decision[1, int cols];
        for (int col = 0; col < cols; col++)
            d[0, col] = new Decision(Domain.Boolean, "Y" + col);
        return d;
    }

and to bound these two matrices together, I added a constraint to moedl:

for (int i = 0; i < Yj.GetLength(1); i++)
     {
        model.AddConstraint("C" + i, Yj[0, i] == matColSum(Xij, i));
     }

and the matColSum is used to add elements of a column (i):

static Term matColSum(Decision[,] Xij, int i)
    {
        Term r = Xij[0, i];
        for (int row = 1; row < Xij.GetLength(0); row++)
        {
            r += Xij[row, i];
        }
        return r;
    }

Now this creates an Xij matrix, which in every column has just one true value (1); It's like the matColSum considers Xij and Yj elements as integers! What am I doing wrong? I don't understand.

  • Your Decision variables are constructed in Domain.Boolean. Use a different Domain, if you want them to be integer or floating point. You can also specify a range like Domain.RealRange(0.0, 100.0) or Domain.IntegerRange(0, 10). – Axel Kemper Oct 01 '14 at 16:13
  • What I want is for Yj to take maximum value of column j in Xij. In other words if there's one or more true values (or 1s) in column j, Yj should be equal 1. Is such a thing possible? – Behrooz Ebrahimi Oct 07 '14 at 04:52
2

Yes, you can either use a C# array to define a non-scalar Decision variable or use indexed Decision objects as explained in Nathan Brixius' blog.

There might be better ways to do it, but I would define one Sum constraint for every element in your parameter vector Y[i]. The parameter vector or its elements can be defined as Decision variables, or you could declare them as Term objects, which might be more efficient.

Be aware that Microsoft seems no longer be working on the Solver Foundation. So, it might make sense to look for other solvers. My personal favorite is MiniZinc, but this certainly depends on the problem type to solve. Some people prefer Google OR-Tools.

Axel Kemper
  • 10,544
  • 2
  • 31
  • 54
  • Thanks to you I managed to construct my decision matrices in MSF, and it works fine. But due to limitation in number of decision variables and constraints, I'm trying to add LpSolve dll to my code. And I keep getting this error that this is not a "valid assembly or COM component"! Where this error is coming from? – Behrooz Ebrahimi Oct 18 '14 at 17:56
  • Thanks for your useful declarations. I used these in my project but I have some problems, could you please help me ? here is my question: https://stackoverflow.com/questions/70628769/microsoft-solver-foundation-gives-wrong-answer-for-a-simple-ilp – shm Jan 08 '22 at 01:14