constraintscplexibm-ilog-opl

CPLEX OPL: Force a set of decision variables to be equal


Any smarter way to force a set of decision variables to be equal?

(If not feel free to use the solution)

Declarations

Given the following set:

ID1     | ID2
------- | -------
A       | AA
B       | AA
C       | BB
C       | AA
C       | CC
D       | CC

e.g. initialized in OPL by

//Set ID
tuple ObjectID{
    string ID1;
    string ID2;
    }
{ObjectID} ID = {
    <"A", "AA">,
    <"B", "AA">,
    <"C", "BB">,
    <"C", "AA">,
    <"C", "CC">,
    <"D", "CC">,
    };

And a decision variable x[ID] to be declared in OPL as

dvar int+ x[ID]

The Problem

The decision variable x[ID] should be equal if ID1 is equal for all ID2.

Example:

x[<"C", "BB">] == x[<"C", "AA">] == x[<"C", "CC">]

Current solution

Pairwise comparison of all dvar's with identical ID1 and different ID2.

forall(
   id_1 in ID, id_2 in ID:
      id_1.ID1 == id_2.ID1 &&
      id_1.ID2 != id_2.ID2
   )
x[id_1] == x[id_2];

Solution

  • first improvement would be to use ordered to divide by 2 the number of equality constraints:

    forall(ordered id_1,id_2 in ID :id_1.ID1 == id_2.ID1 )
         x[id_1] == x[id_2];
    

    and second improvement could be to move from (n-1)*n/2 constraints to (n-1) constraints

    //Set ID
    tuple ObjectID{
        string ID1;
        string ID2;
        }
    {ObjectID} ID = {
        <"A", "AA">,
        <"B", "AA">,
        <"C", "BB">,
        <"C", "AA">,
        <"C", "CC">,
        <"D", "CC">
        };
    
    dvar int+ x[ID];
    
    {string} Id1s={i.ID1 | i in ID};
    {string} Id2PerId1[id1 in Id1s]={i.ID2 | i in ID : i.ID1==id1};
    
    
    
    subject to
    {
    
    
    forall(id1 in Id1s) forall(id2 in Id2PerId1[id1] diff     {last(Id2PerId1[id1])})
       x[<id1,id2>] == x[<id1,next(Id2PerId1[id1],id2)>];
    
    
      }
    

    `