IBM ILOG Solver User's Manual > More on Modeling > Reducing Symmetry: Configuring Racks > Model

You use Concert Technology classes to model this problem.

This program reads the description of racks and cards in the file rack.dat. First, the data are represented like this in the code:

const IloInt nbRackTypes = 2;
const IloInt maxSlots = 16;
enum {power, price, nbSlot};

IloInt Racks[3][nbRackTypes+1] = {
    { 0, 150, 200 },
    { 0, 150, 200 },
    { 0, 8,    16 }
};


const IloInt nbCardTypes = 4;

const IloInt nbRack = 5;
IloInt nbCards[nbCardTypes] = {10, 4, 2, 1};


One way to model this problem would be to define a class of objects representing the cards. Unfortunately, this model is highly symmetrical. With this model, each permutation of two cards of the same type gives a new "solution." Those symmetries increase the size of the search space without really offering any more authentic solutions.

A better way to model the problem is to focus on modeling the racks and reducing symmetry. Since the features of racks and the maximal number of racks to use are fixed, you can assume that you have n racks, and you want to find for each one:

Rack types are identified by integers. The type zero indicates the unused racks. This convention avoids introducing one constrained variable per rack to indicate whether the rack is used or not.

You define the class Rack. Its instances have the following characteristics:

To avoid the symmetries introduced by the first model, you manipulate the number of cards of a given type plugged into a rack (rather than the cards plugged into a rack). This model suppresses the symmetries introduced by the first one and thus reduces the search space.

In this model, each rack has an array of counters. Each counter is associated with a card type. It counts the number of cards of this type plugged into this rack. The values of the counters are unknowns, so they are represented by constrained integer variables.

To represent those counters, you add a new data member _counters to the instances of the class Rack. For a given rack, this data member contains its array of card counters. It is defined like this:

class Rack {
  public:
    IloIntVar      _type;
    IloIntVar      _price;
    IloIntVarArray _counters;

The arrays of card counters associated with racks all have the same size. This size is equal to the number of card types, given by nbCardTypes.

Searching for a solution using this model consists of finding, for each rack, the values of its associated counters.