Solved

Generate combination of integer parameter

  • 2 January 2020
  • 8 replies
  • 366 views

Userlevel 2
Badge +4

Dear All,

I want to generate an integer parameter based on the combination of a number of component as shown as:

  K1 K2 K3
C1 1 1 1
C2 1 1 0
C3 1 0 1
C4 1 0 0
C5 0 1 1
C6 0 1 0
C7 0 0 1
C8 0 0 0

 

where K1 … Kn is the number of component and C1 .. Cn is generated combination based on component number. The value of 1 means that the component is available and the value of 0 is otherwise.

Is it possible to do this in AIMMS?

Thank you very much.

icon

Best answer by Mischa 3 January 2020, 10:27

View original

8 replies

Userlevel 6
Badge +6

 

What about defining the set of Components and Combinations and then having a binary parameter over these 2 sets (like and incidence matrix). In example below I limit size of set to your example. Making it a binary parameter makes it automatically a checkbox in the UI rather than a value based input.

 Set Components {
Index: k;
Definition: data ;
}
Set Combinations {
Index: c;
Definition: data ;
}
Parameter Setup {
IndexDomain: (c,k);
Range: binary;
InitialData: {
data
{
( C1, K1 ) : 1, ( C1, K2 ) : 1, ( C1, K3 ) : 1,
( C2, K1 ) : 1, ( C2, K2 ) : 1,
( C3, K1 ) : 1, ( C3, K3 ) : 1,
( C4, K1 ) : 1,
( C5, K2 ) : 1, ( C5, K3 ) : 1,
( C6, K2 ) : 1,
( C7, K3 ) : 1 }
}
}

This results in a (changeable) parameter; e.g. via the AIMMS WebUI:

 

or in the data page in the AIMMS Developer IDE (for quick reference during creation of your model)

 

Userlevel 6
Badge +6

Or if you want to have a random assignment (not sure, but as you are mentioned the word ‘generate’ and thus might like to create data), you could do something like:

Parameter SetupRandom {
IndexDomain: (c,k);
Range: binary;
Definition:
! Create a random True (1) or False (0) for each combo
round(uniform[0,1],0);
}

 

Userlevel 2
Badge +4

Hello @Gertjan,

Many thanks for the reply.

Using “round(uniform[0,1],0)”, It will produce random matrix of SetupRandom parameter.

Perhaps, question description is not clear enough. I am sorry for that.

The components set is defined as:

Set Components {
        Index: k;
        Definition: ElementRange(1,NumberOfComponents);
    }

The combinations set is defined as:

Set Combinations {
        Index: c;
        Definition: ElementRange(1,NumberOfCombinations);
    }

where NumberOfCombinations is calculated based on:

Parameter NumberOfCombinations {
        Range: integer;
        Definition: power(2,NumberOfComponents);
    }

So, when NumberOfComponents is 3, the number of the generated combination will be 2^(3) = 8 and the matrix will be:

  K1 K2 K3   Decimal
C1 1 1 1   7
C2 1 1 0   6
C3 1 0 1   5
C4 1 0 0   4
C5 0 1 1   3
C6 0 1 0   2
C7 0 0 1   1
C8 0 0 0   0

 

The generated matrix is a kind of binary sequence with correspond decimal value is presented in the rightmost column.

When the NumberOfComponents is 2, the number of the generated combination will be 2^(2) = 4 and the matrix will be:

  K1 K2   Decimal
C1 1 1   3
C2 1 0   2
C3 0 1   1
C4 0 0   0

 

Each row of the matrix describes the availability of components. For example, in the first row, all components are running. In the second row, a component is down.

The optimization model will determine the component numbers and types so that the selected components have the highest reliability index.

I hope the description is clear enough and looking forward to your suggestion for this problem.

Thank you very much.

 

Userlevel 3
Badge +6

Dear Rahmat,

Thank you for this fun programming puzzle:yum:!

I created an AIMMS model that does what you describe above, partly based on Gertjan’s previous answers. I included the whole model as a .zip file here for completeness.

The idea is as follows:

  1. Define the set Components simply as data { K1..K3 };
  2. Introduce a NumberOfComponents parameter, defined as card(Components); .
  3. Define a NumberOfCombinations parameter, defined as power(2, NumberOfComponents);In this case the value will be 8 (being 2^3).
  4. Define the set Combinations as ElementRange(1, NumberOfCombinations,1, "C");

  5. In wrote a function BinaryNumber(n, len), which returns a string containing the binary representation of the decimal number n with a fixed length of len characters.

  6. In the MainExecution function, which looks as follows:

I loop over the number of combinations, using the built-in LoopCount parameter. For each iteration, I calculate the binary representation of the iteration minus 1. So, in the first iteration I calculate the binary representation of 0, in the second iteration of 1, etc. After doing so, I determine the current combination, which, as in your example you seem to want the decimal numbers assigned in the reverse order, is the maximum number of combinations minus the current iteration number plus 1. As the last step, I assign the right binary values to the generated matrix, for each component k, by simply picking the right sub-string from the binary representation of the current decimal number.

 

I tested the algorithm with the set Components going from K2 to K5.

I hope this helps!

 

With kind regards,

Mischa

 

 

Userlevel 2
Badge +4

Hello @Mischa,

Thank you for your complete model. It helps a lot in finishing the model.

Thank you.

 

Userlevel 6
Badge +6

Hi @rahmat@Mischa,

First of all, nice example @Mischa

Just want to add a small caution here. If your number of components is large (Kn), this might become a huge set quickly. For example, if n is 20, the number of combinations will go over 1 mln, if n=30, the number of combinations wil reach over 1 bln. This might not be ideal; I certainly would not start an optimization model using this scope. 

So not understanding your need, it is good to be smart about defining the useful combinations rather than all (or know your n is a low number).

Userlevel 2
Badge +4

Hello @Gertjan,

You are right about this. There will be a limited number of combinations used in the optimization. The selection of useful combination is based on the probability threshold. If a combination has a probability less then a defined threshold, it will not be used in the optimization.

As there are not many details in the question, I assume:

  • Your input is a natural number n and the resulting array contains all natural numbers from 1 to n.
  • The expected output given by the combinations above, resembles a symmetric relation, i. e. in your case [1, 2] is considered the same as [2, 1].
  • Combinations [x, x] are excluded.
  • There are only combinations with 2 elements.
  • There is no List<> datatype or dynamic array, so the array length has to be known before creating the array.
  • The number of elements in your result is therefore the binomial coefficient m = n over 2 = n! / (2! * (n - 2)!) (which is 4! / (2! * (4 - 2)!) = 24 / 4 = 6 in your example) with ! being the factorial.

First, initializing the array with the first n natural numbers should be quite easy using the array element index. However, the index is a property of the array elements, so you don't need to initialize them in the first place.

You need 2 nested loops processing the array. The outer loop ranges i from 1 to n - 1, the inner loop ranges j from 2 to n. If your indexes start from 0 instead of 1, you have to take this into consideration for the loop limits. Now, you only need to fill your target array with the combinations [i, j]. To find the correct index in your target array, you should use a third counter variable, initialized with the first index and incremented at the end of the inner loop.

I agree, the math behind is not that hard and I think this explanation should suffice to develop the corresponding code yourself.

Reply


Didn't find what you were looking for? Try searching on our documentation pages:

AIMMS Developer & PRO | AIMMS How-To | AIMMS SC Navigator