Esempio n. 1
0
        static void Main(string[] args)
        {
            try
            {
                int n = 10;
                if (args.Length > 0)
                {
                    n = Int32.Parse(args[0]);
                }
                if ((n % 2) == 1)
                {
                    n++;
                }
                Console.WriteLine("Finding schedule for {0} teams", n);
                int nbWeeks        = 2 * (n - 1);
                int nbGamesPerWeek = n / 2;
                int nbGames        = n * (n - 1);
                CP  cp             = new CP();

                IIntVar[][] games = new IIntVar[nbWeeks][];
                IIntVar[][] home  = new IIntVar[nbWeeks][];
                IIntVar[][] away  = new IIntVar[nbWeeks][];

                for (int i = 0; i < nbWeeks; i++)
                {
                    home[i]  = cp.IntVarArray(nbGamesPerWeek, 0, n - 1);
                    away[i]  = cp.IntVarArray(nbGamesPerWeek, 0, n - 1);
                    games[i] = cp.IntVarArray(nbGamesPerWeek, 0, nbGames - 1);
                }
                //
                // For each play slot, set up correspondance between game id,
                // home team, and away team
                //

                IIntTupleSet gha   = cp.IntTable(3);
                int[]        tuple = new int[3];
                for (int i = 0; i < n; i++)
                {
                    tuple[0] = i;
                    for (int j = 0; j < n; j++)
                    {
                        if (i != j)
                        {
                            tuple[1] = j;
                            tuple[2] = Game(i, j, n);
                            cp.AddTuple(gha, tuple);
                        }
                    }
                }

                for (int i = 0; i < nbWeeks; i++)
                {
                    for (int j = 0; j < nbGamesPerWeek; j++)
                    {
                        IIntVar[] vars = cp.IntVarArray(3);
                        vars[0] = home[i][j];
                        vars[1] = away[i][j];
                        vars[2] = games[i][j];
                        cp.Add(cp.AllowedAssignments(vars, gha));
                    }
                }
                //
                // All teams play each week
                //
                for (int i = 0; i < nbWeeks; i++)
                {
                    IIntVar[] teamsThisWeek = cp.IntVarArray(n);
                    for (int j = 0; j < nbGamesPerWeek; j++)
                    {
                        teamsThisWeek[j] = home[i][j];
                        teamsThisWeek[nbGamesPerWeek + j] = away[i][j];
                    }
                    cp.Add(cp.AllDiff(teamsThisWeek));
                }
                //
                // Dual representation: for each game id, the play slot is maintained
                //
                IIntVar[] weekOfGame = cp.IntVarArray(nbGames, 0, nbWeeks - 1);
                IIntVar[] allGames   = cp.IntVarArray(nbGames);
                IIntVar[] allSlots   = cp.IntVarArray(nbGames, 0, nbGames - 1);
                for (int i = 0; i < nbWeeks; i++)
                {
                    for (int j = 0; j < nbGamesPerWeek; j++)
                    {
                        allGames[i * nbGamesPerWeek + j] = games[i][j];
                    }
                }
                cp.Add(cp.Inverse(allGames, allSlots));
                for (int i = 0; i < nbGames; i++)
                {
                    cp.Add(cp.Eq(weekOfGame[i], cp.Div(allSlots[i], nbGamesPerWeek)));
                }
                //
                // Two half schedules.  Cannot play the same pair twice in the same half.
                // Plus, impose a minimum number of weeks between two games involving
                // the same teams (up to six weeks)
                //
                int mid     = nbWeeks / 2;
                int overlap = 0;
                if (n >= 6)
                {
                    overlap = min(n / 2, 6);
                }
                for (int i = 0; i < n; i++)
                {
                    for (int j = i + 1; j < n; j++)
                    {
                        int g1 = Game(i, j, n);
                        int g2 = Game(j, i, n);
                        cp.Add(cp.Equiv(cp.Ge(weekOfGame[g1], mid), cp.Lt(weekOfGame[g2], mid)));
                        // Six week difference...
                        if (overlap != 0)
                        {
                            cp.Add(cp.Ge(cp.Abs(cp.Diff(weekOfGame[g1], weekOfGame[g2])), overlap));
                        }
                    }
                }

                //
                // Can't have three homes or three aways in a row.
                //
                IIntVar[][] playHome = new IIntVar[n][];
                for (int i = 0; i < n; i++)
                {
                    playHome[i] = cp.IntVarArray(nbWeeks, 0, 1);
                    for (int j = 0; j < nbWeeks; j++)
                    {
                        cp.Add(cp.Eq(playHome[i][j], cp.Count(home[j], i)));
                    }
                    for (int j = 0; j < nbWeeks - 3; j++)
                    {
                        IIntVar[] window = cp.IntVarArray(3);
                        for (int k = j; k < j + 3; k++)
                        {
                            window[k - j] = playHome[i][k];
                        }
                        IIntExpr windowSum = cp.Sum(window);
                        cp.Add(cp.Le(1, windowSum));
                        cp.Add(cp.Le(windowSum, 2));
                    }
                }

                //
                // If we start the season home, we finish away and vice versa.
                //
                for (int i = 0; i < n; i++)
                {
                    cp.Add(cp.Neq(playHome[i][0], playHome[i][nbWeeks - 1]));
                }

                //
                // Objective: minimize the number of `breaks'.  A break is
                //            two consecutive home or away matches for a
                //            particular team
                IIntVar[] teamBreaks = cp.IntVarArray(n, 0, nbWeeks / 2);
                for (int i = 0; i < n; i++)
                {
                    IIntExpr nbreaks = cp.Constant(0);
                    for (int j = 1; j < nbWeeks; j++)
                    {
                        nbreaks = cp.Sum(nbreaks, cp.IntExpr(cp.Eq(playHome[i][j - 1], playHome[i][j])));
                    }
                    cp.Add(cp.Eq(teamBreaks[i], nbreaks));
                }
                IIntVar breaks = cp.IntVar(n - 2, n * (nbWeeks / 2));
                cp.Add(cp.Eq(breaks, cp.Sum(teamBreaks)));
                cp.Add(cp.Minimize(breaks));

                //
                // Catalyzing constraints
                //

                // Each team plays home the same number of times as away
                for (int i = 0; i < n; i++)
                {
                    cp.Add(cp.Eq(cp.Sum(playHome[i]), nbWeeks / 2));
                }

                // Breaks must be even for each team
                for (int i = 0; i < n; i++)
                {
                    cp.Add(cp.Eq(cp.Modulo(teamBreaks[i], 2), 0));
                }

                //
                // Symmetry breaking constraints
                //

                // Teams are interchangeable.  Fix first week.
                // Also breaks reflection symmetry of the whole schedule.
                for (int i = 0; i < nbGamesPerWeek; i++)
                {
                    cp.Add(cp.Eq(home[0][i], i * 2));
                    cp.Add(cp.Eq(away[0][i], i * 2 + 1));
                }

                // Order of games in each week is arbitrary.
                // Break symmetry by forcing an order.
                for (int i = 0; i < nbWeeks; i++)
                {
                    for (int j = 1; j < nbGamesPerWeek; j++)
                    {
                        cp.Add(cp.Gt(games[i][j], games[i][j - 1]));
                    }
                }

                cp.SetParameter(CP.DoubleParam.TimeLimit, 20);
                cp.SetParameter(CP.IntParam.LogPeriod, 10000);
                IVarSelector   varSel = cp.SelectSmallest(cp.VarIndex(allGames));;
                IValueSelector valSel = cp.SelectRandomValue();

                ISearchPhase phase = cp.SearchPhase(allGames,
                                                    cp.IntVarChooser(varSel),
                                                    cp.IntValueChooser(valSel));
                cp.SetSearchPhases(phase);
                cp.StartNewSearch();
                while (cp.Next())
                {
                    Console.WriteLine("Solution at {0}", cp.GetValue(breaks));
                }
                cp.EndSearch();
            }
            catch (ILOG.Concert.Exception e)
            {
                Console.WriteLine("Error {0}", e);
            }
        }
Esempio n. 2
0
        public static void Main(String[] args)
        {
            CP cp = new CP();
              dist[0]=new int[] { 16,1,1,0,0,0,0,0,1,1,1,1,1,2,2,1,1,0,0,0,2,2,1,1,1 };
              dist[1]=new int[] { 1,16,2,0,0,0,0,0,2,2,1,1,1,2,2,1,1,0,0,0,0,0,0,0,0 };
              dist[2]=new int[] { 1,2,16,0,0,0,0,0,2,2,1,1,1,2,2,1,1,0,0,0,0,0,0,0,0 };
              dist[3]=new int[] { 0,0,0,16,2,2,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1 };
              dist[4]=new int[] { 0,0,0,2,16,2,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1 };
              dist[5]=new int[] { 0,0,0,2,2,16,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1 };
              dist[6]=new int[] { 0,0,0,0,0,0,16,2,0,0,1,1,1,0,0,1,1,1,1,2,0,0,0,1,1 };
              dist[7]=new int[] { 0,0,0,0,0,0,2,16,0,0,1,1,1,0,0,1,1,1,1,2,0,0,0,1,1 };
              dist[8]=new int[] { 1,2,2,0,0,0,0,0,16,2,2,2,2,2,2,1,1,1,1,1,1,1,0,1,1 };
              dist[9]=new int[] { 1,2,2,0,0,0,0,0,2,16,2,2,2,2,2,1,1,1,1,1,1,1,0,1,1 };
              dist[10]=new int[]{ 1,1,1,0,0,0,1,1,2,2,16,2,2,2,2,2,2,1,1,2,1,1,0,1,1 };
              dist[11]=new int[]{ 1,1,1,0,0,0,1,1,2,2,2,16,2,2,2,2,2,1,1,2,1,1,0,1,1 };
              dist[12]=new int[]{ 1,1,1,0,0,0,1,1,2,2,2,2,16,2,2,2,2,1,1,2,1,1,0,1,1 };
              dist[13]=new int[]{ 2,2,2,0,0,0,0,0,2,2,2,2,2,16,2,1,1,1,1,1,1,1,1,1,1 };
              dist[14]=new int[]{ 2,2,2,0,0,0,0,0,2,2,2,2,2,2,16,1,1,1,1,1,1,1,1,1,1 };
              dist[15]=new int[]{ 1,1,1,0,0,0,1,1,1,1,2,2,2,1,1,16,2,2,2,1,2,2,1,2,2 };
              dist[16]=new int[]{ 1,1,1,0,0,0,1,1,1,1,2,2,2,1,1,2,16,2,2,1,2,2,1,2,2 };
              dist[17]=new int[]{ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,2,2,16,2,2,1,1,0,2,2 };
              dist[18]=new int[]{ 0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,16,2,1,1,0,2,2 };
              dist[19]=new int[]{ 0,0,0,1,1,1,2,2,1,1,2,2,2,1,1,1,1,2,2,16,1,1,0,1,1 };
              dist[20]=new int[]{ 2,0,0,0,0,0,0,0,1,1,1,1,1,1,1,2,2,1,1,1,16,2,1,2,2 };
              dist[21]=new int[]{ 2,0,0,0,0,0,0,0,1,1,1,1,1,1,1,2,2,1,1,1,2,16,1,2,2 };
              dist[22]=new int[]{ 1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,1,16,1,1 };
              dist[23]=new int[]{ 1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,2,2,1,16,2 };
              dist[24]=new int[]{ 1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,1,2,2,1,2,16 };

              int nbTransmitters = getTransmitterIndex(nbCell, 0);
              IIntVar[] freq = cp.IntVarArray(nbTransmitters,
                                      0, nbAvailFreq-1, "freq");
              for (int cell = 0; cell < nbCell; cell++)
            for (int channel1 = 0; channel1 < nbChannel[cell]; channel1++)
              for (int channel2= channel1+1; channel2 < nbChannel[cell]; channel2++)
            cp.Add(cp.Ge(cp.Abs(cp.Diff(freq[getTransmitterIndex(cell, channel1)],
                                        freq[getTransmitterIndex(cell, channel2)])),
                         16));
              for (int cell1 = 0; cell1 < nbCell; cell1++)
            for (int cell2 = cell1+1; cell2 < nbCell; cell2++)
              if (dist[cell1][cell2] > 0)
            for (int channel1 = 0; channel1 < nbChannel[cell1]; channel1++)
              for (int channel2 = 0; channel2 < nbChannel[cell2]; channel2++)
                cp.Add(cp.Ge(cp.Abs(cp.Diff(freq[getTransmitterIndex(cell1, channel1)],
                                            freq[getTransmitterIndex(cell2, channel2)])),
                             dist[cell1][cell2]));

              // Minimizing the total number of frequencies
              IIntExpr nbFreq = cp.CountDifferent(freq);
              cp.Add(cp.Minimize(nbFreq));

              cp.SetParameter(CP.IntParam.CountDifferentInferenceLevel,
                      CP.ParameterValues.Extended);
              cp.SetParameter(CP.IntParam.FailLimit, 40000);
              cp.SetParameter(CP.IntParam.LogPeriod, 100000);

              if (cp.Solve()) {
            for (int cell = 0; cell < nbCell; cell++) {
              for (int channel = 0; channel < nbChannel[cell]; channel++)
            Console.Write(cp.GetIntValue(freq[getTransmitterIndex(cell, channel)])
                          + "  " );
              Console.WriteLine();
            }
            Console.WriteLine("Total # of sites       " + nbTransmitters);
            Console.WriteLine("Total # of frequencies " + cp.GetValue(nbFreq));

              } else
            Console.WriteLine("No solution");
              cp.End();
        }
Esempio n. 3
0
        static void Main(string[] args)
        {
            try
              {
            int n = 10;
            if (args.Length > 0)
              n = Int32.Parse(args[0]);
            if ((n % 2) == 1)
              n++;
            Console.WriteLine("Finding schedule for {0} teams", n);
            int nbWeeks = 2 * (n - 1);
            int nbGamesPerWeek = n / 2;
            int nbGames = n * (n - 1);
            CP cp = new CP();

            IIntVar[][] games = new IIntVar[nbWeeks][];
            IIntVar[][] home = new IIntVar[nbWeeks][];
            IIntVar[][] away = new IIntVar[nbWeeks][];

            for (int i = 0; i < nbWeeks; i++)
            {
              home[i] = cp.IntVarArray(nbGamesPerWeek, 0, n - 1);
              away[i] = cp.IntVarArray(nbGamesPerWeek, 0, n - 1);
              games[i] = cp.IntVarArray(nbGamesPerWeek, 0, nbGames - 1);
            }
            //
            // For each play slot, set up correspondance between game id,
            // home team, and away team
            //

            IIntTupleSet gha = cp.IntTable(3);
            int[] tuple = new int[3];
            for (int i = 0; i < n; i++)
            {
              tuple[0] = i;
              for (int j = 0; j < n; j++)
              {
            if (i != j)
            {
              tuple[1] = j;
              tuple[2] = Game(i, j, n);
              cp.AddTuple(gha, tuple);
            }
              }
            }

            for (int i = 0; i < nbWeeks; i++)
            {
              for (int j = 0; j < nbGamesPerWeek; j++)
              {
            IIntVar[] vars = cp.IntVarArray(3);
            vars[0] = home[i][j];
            vars[1] = away[i][j];
            vars[2] = games[i][j];
            cp.Add(cp.AllowedAssignments(vars, gha));
              }
            }
            //
            // All teams play each week
            //
            for (int i = 0; i < nbWeeks; i++)
            {
              IIntVar[] teamsThisWeek = cp.IntVarArray(n);
              for (int j = 0; j < nbGamesPerWeek; j++)
              {
            teamsThisWeek[j] = home[i][j];
            teamsThisWeek[nbGamesPerWeek + j] = away[i][j];
              }
              cp.Add(cp.AllDiff(teamsThisWeek));
            }
            //
            // Dual representation: for each game id, the play slot is maintained
            //
            IIntVar[] weekOfGame = cp.IntVarArray(nbGames, 0, nbWeeks - 1);
            IIntVar[] allGames = cp.IntVarArray(nbGames);
            IIntVar[] allSlots = cp.IntVarArray(nbGames, 0, nbGames - 1);
            for (int i = 0; i < nbWeeks; i++)
              for (int j = 0; j < nbGamesPerWeek; j++)
            allGames[i * nbGamesPerWeek + j] = games[i][j];
            cp.Add(cp.Inverse(allGames, allSlots));
            for (int i = 0; i < nbGames; i++)
              cp.Add(cp.Eq(weekOfGame[i], cp.Div(allSlots[i], nbGamesPerWeek)));
            //
            // Two half schedules.  Cannot play the same pair twice in the same half.
            // Plus, impose a minimum number of weeks between two games involving
            // the same teams (up to six weeks)
            //
            int mid = nbWeeks / 2;
            int overlap = 0;
            if (n >= 6)
              overlap = min(n / 2, 6);
            for (int i = 0; i < n; i++)
            {
              for (int j = i + 1; j < n; j++)
              {
            int g1 = Game(i, j, n);
            int g2 = Game(j, i, n);
            cp.Add(cp.Equiv(cp.Ge(weekOfGame[g1], mid), cp.Lt(weekOfGame[g2], mid)));
            // Six week difference...
            if (overlap != 0)
              cp.Add(cp.Ge(cp.Abs(cp.Diff(weekOfGame[g1], weekOfGame[g2])), overlap));
              }
            }

            //
            // Can't have three homes or three aways in a row.
            //
            IIntVar[][] playHome = new IIntVar[n][];
            for (int i = 0; i < n; i++)
            {
              playHome[i] = cp.IntVarArray(nbWeeks, 0, 1);
              for (int j = 0; j < nbWeeks; j++)
            cp.Add(cp.Eq(playHome[i][j], cp.Count(home[j], i)));
              for (int j = 0; j < nbWeeks - 3; j++)
              {
            IIntVar[] window = cp.IntVarArray(3);
            for (int k = j; k < j + 3; k++)
              window[k - j] = playHome[i][k];
            IIntExpr windowSum = cp.Sum(window);
            cp.Add(cp.Le(1, windowSum));
            cp.Add(cp.Le(windowSum, 2));
              }
            }

            //
            // If we start the season home, we finish away and vice versa.
            //
            for (int i = 0; i < n; i++)
              cp.Add(cp.Neq(playHome[i][0], playHome[i][nbWeeks - 1]));

            //
            // Objective: minimize the number of `breaks'.  A break is
            //            two consecutive home or away matches for a
            //            particular team
            IIntVar[] teamBreaks = cp.IntVarArray(n, 0, nbWeeks / 2);
            for (int i = 0; i < n; i++)
            {
              IIntExpr nbreaks = cp.Constant(0);
              for (int j = 1; j < nbWeeks; j++)
            nbreaks = cp.Sum(nbreaks, cp.IntExpr(cp.Eq(playHome[i][j - 1], playHome[i][j])));
              cp.Add(cp.Eq(teamBreaks[i], nbreaks));
            }
            IIntVar breaks = cp.IntVar(n - 2, n * (nbWeeks / 2));
            cp.Add(cp.Eq(breaks, cp.Sum(teamBreaks)));
            cp.Add(cp.Minimize(breaks));

            //
            // Catalyzing constraints
            //

            // Each team plays home the same number of times as away
            for (int i = 0; i < n; i++)
              cp.Add(cp.Eq(cp.Sum(playHome[i]), nbWeeks / 2));

            // Breaks must be even for each team
            for (int i = 0; i < n; i++)
              cp.Add(cp.Eq(cp.Modulo(teamBreaks[i], 2), 0));

            //
            // Symmetry breaking constraints
            //

            // Teams are interchangeable.  Fix first week.
            // Also breaks reflection symmetry of the whole schedule.
            for (int i = 0; i < nbGamesPerWeek; i++)
            {
              cp.Add(cp.Eq(home[0][i], i * 2));
              cp.Add(cp.Eq(away[0][i], i * 2 + 1));
            }

            // Order of games in each week is arbitrary.
            // Break symmetry by forcing an order.
            for (int i = 0; i < nbWeeks; i++)
              for (int j = 1; j < nbGamesPerWeek; j++)
            cp.Add(cp.Gt(games[i][j], games[i][j - 1]));

            cp.SetParameter(CP.DoubleParam.TimeLimit, 20);
            cp.SetParameter(CP.IntParam.LogPeriod, 10000);
            IVarSelector varSel = cp.SelectSmallest(cp.VarIndex(allGames)); ;
            IValueSelector valSel = cp.SelectRandomValue();

            ISearchPhase phase = cp.SearchPhase(allGames,
                                            cp.IntVarChooser(varSel),
                                            cp.IntValueChooser(valSel));
            cp.StartNewSearch(phase);
            while (cp.Next())
            {
              Console.WriteLine("Solution at {0}", cp.GetValue(breaks));
            }
            cp.EndSearch();
              }
              catch (ILOG.Concert.Exception e)
              {
               Console.WriteLine("Error {0}", e);
              }
        }
Esempio n. 4
0
        public static void Main(String[] args)
        {
            CP cp = new CP();

            dist[0]  = new int[] { 16, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 1, 1, 0, 0, 0, 2, 2, 1, 1, 1 };
            dist[1]  = new int[] { 1, 16, 2, 0, 0, 0, 0, 0, 2, 2, 1, 1, 1, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
            dist[2]  = new int[] { 1, 2, 16, 0, 0, 0, 0, 0, 2, 2, 1, 1, 1, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
            dist[3]  = new int[] { 0, 0, 0, 16, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1 };
            dist[4]  = new int[] { 0, 0, 0, 2, 16, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1 };
            dist[5]  = new int[] { 0, 0, 0, 2, 2, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1 };
            dist[6]  = new int[] { 0, 0, 0, 0, 0, 0, 16, 2, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 2, 0, 0, 0, 1, 1 };
            dist[7]  = new int[] { 0, 0, 0, 0, 0, 0, 2, 16, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 2, 0, 0, 0, 1, 1 };
            dist[8]  = new int[] { 1, 2, 2, 0, 0, 0, 0, 0, 16, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1 };
            dist[9]  = new int[] { 1, 2, 2, 0, 0, 0, 0, 0, 2, 16, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1 };
            dist[10] = new int[] { 1, 1, 1, 0, 0, 0, 1, 1, 2, 2, 16, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 0, 1, 1 };
            dist[11] = new int[] { 1, 1, 1, 0, 0, 0, 1, 1, 2, 2, 2, 16, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 0, 1, 1 };
            dist[12] = new int[] { 1, 1, 1, 0, 0, 0, 1, 1, 2, 2, 2, 2, 16, 2, 2, 2, 2, 1, 1, 2, 1, 1, 0, 1, 1 };
            dist[13] = new int[] { 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 16, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
            dist[14] = new int[] { 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
            dist[15] = new int[] { 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 1, 1, 16, 2, 2, 2, 1, 2, 2, 1, 2, 2 };
            dist[16] = new int[] { 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 1, 1, 2, 16, 2, 2, 1, 2, 2, 1, 2, 2 };
            dist[17] = new int[] { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 16, 2, 2, 1, 1, 0, 2, 2 };
            dist[18] = new int[] { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 16, 2, 1, 1, 0, 2, 2 };
            dist[19] = new int[] { 0, 0, 0, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 16, 1, 1, 0, 1, 1 };
            dist[20] = new int[] { 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 16, 2, 1, 2, 2 };
            dist[21] = new int[] { 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 16, 1, 2, 2 };
            dist[22] = new int[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 16, 1, 1 };
            dist[23] = new int[] { 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1, 16, 2 };
            dist[24] = new int[] { 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1, 2, 16 };

            int nbTransmitters = getTransmitterIndex(nbCell, 0);

            IIntVar[] freq = cp.IntVarArray(nbTransmitters,
                                            0, nbAvailFreq - 1, "freq");
            for (int cell = 0; cell < nbCell; cell++)
            {
                for (int channel1 = 0; channel1 < nbChannel[cell]; channel1++)
                {
                    for (int channel2 = channel1 + 1; channel2 < nbChannel[cell]; channel2++)
                    {
                        cp.Add(cp.Ge(cp.Abs(cp.Diff(freq[getTransmitterIndex(cell, channel1)],
                                                    freq[getTransmitterIndex(cell, channel2)])),
                                     16));
                    }
                }
            }
            for (int cell1 = 0; cell1 < nbCell; cell1++)
            {
                for (int cell2 = cell1 + 1; cell2 < nbCell; cell2++)
                {
                    if (dist[cell1][cell2] > 0)
                    {
                        for (int channel1 = 0; channel1 < nbChannel[cell1]; channel1++)
                        {
                            for (int channel2 = 0; channel2 < nbChannel[cell2]; channel2++)
                            {
                                cp.Add(cp.Ge(cp.Abs(cp.Diff(freq[getTransmitterIndex(cell1, channel1)],
                                                            freq[getTransmitterIndex(cell2, channel2)])),
                                             dist[cell1][cell2]));
                            }
                        }
                    }
                }
            }

            // Minimizing the total number of frequencies
            IIntExpr nbFreq = cp.CountDifferent(freq);

            cp.Add(cp.Minimize(nbFreq));

            cp.SetParameter(CP.IntParam.CountDifferentInferenceLevel,
                            CP.ParameterValues.Extended);
            cp.SetParameter(CP.IntParam.FailLimit, 40000);
            cp.SetParameter(CP.IntParam.LogPeriod, 100000);

            if (cp.Solve())
            {
                for (int cell = 0; cell < nbCell; cell++)
                {
                    for (int channel = 0; channel < nbChannel[cell]; channel++)
                    {
                        Console.Write(cp.GetIntValue(freq[getTransmitterIndex(cell, channel)])
                                      + "  ");
                    }
                    Console.WriteLine();
                }
                Console.WriteLine("Total # of sites       " + nbTransmitters);
                Console.WriteLine("Total # of frequencies " + cp.GetValue(nbFreq));
            }
            else
            {
                Console.WriteLine("No solution");
            }
            cp.End();
        }
        public static void Main(String[] args)
        {
            String filename = "../../../../examples/data/learningeffect_default.data";
            int    nbJobs, nbMachines;

            if (args.Length > 0)
            {
                filename = args[0];
            }

            CP         cp   = new CP();
            DataReader data = new DataReader(filename);

            nbJobs     = data.Next();
            nbMachines = data.Next();
            IIntExpr[] ends = new IIntExpr[nbJobs];

            IIntervalVar[][] machines = new IIntervalVar[nbMachines][];
            int[][]          sizes    = new int[nbMachines][];
            for (int j = 0; j < nbMachines; j++)
            {
                machines[j] = new IIntervalVar[nbJobs];
                sizes[j]    = new int[nbJobs];
            }

            for (int i = 0; i < nbJobs; i++)
            {
                IIntervalVar prec = cp.IntervalVar();
                for (int j = 0; j < nbMachines; j++)
                {
                    int m, d;
                    m = data.Next();
                    d = data.Next();
                    IIntervalVar ti = cp.IntervalVar(0, d);
                    machines[m][i] = ti;
                    sizes[m][i]    = d;
                    if (j > 0)
                    {
                        cp.Add(cp.EndBeforeStart(prec, ti));
                    }
                    prec = ti;
                }
                ends[i] = cp.EndOf(prec);
            }

            for (int j = 0; j < nbMachines; j++)
            {
                double         alpha   = data.Next() / ((double)100);
                IIntervalVar[] chain   = new IIntervalVar[nbJobs];
                IIntervalVar   prec    = cp.IntervalVar();
                IIntExpr[]     indices = new IIntExpr[nbJobs];
                for (int i = 0; i < nbJobs; i++)
                {
                    IIntervalVar syncti = cp.IntervalVar();
                    if (i > 0)
                    {
                        cp.Add(cp.EndBeforeStart(prec, syncti));
                    }
                    prec     = syncti;
                    chain[i] = syncti;
                    IIntExpr index = cp.IntVar(0, nbJobs - 1);
                    indices[i] = index;
                    // Learning effect captured by the decreasing function
                    // of the position (0 <= alpha <= 1).
                    // At first position, in the sequence index = 0; there is no
                    // learning effect and duration of the task is its nominal duration
                    INumExpr floatDur = cp.Prod(sizes[j][i], cp.Power(alpha, index));
                    cp.Add(cp.Le(
                               cp.Abs(cp.Diff(floatDur, cp.SizeOf(machines[j][i]))),
                               0.5)
                           );
                }
                cp.Add(cp.Isomorphism(chain, machines[j], indices, nbJobs));
                // The no-overlap is a redundant constraint in this quite
                // simple model - it is used only to provide stronger inference.
                cp.Add(cp.NoOverlap(machines[j]));
            }

            IObjective objective = cp.Minimize(cp.Max(ends));

            cp.Add(objective);
            cp.SetParameter(CP.IntParam.LogPeriod, 10000);

            Console.WriteLine("Instance \t: " + filename);
            if (cp.Solve())
            {
                Console.WriteLine("Makespan \t: " + cp.ObjValue);
            }
            else
            {
                Console.WriteLine("No solution found.");
            }
        }