Beispiel #1
0
    /**
     *
     * Solves the Minesweeper problems.
     *
     * See http://www.hakank.org/google_or_tools/minesweeper.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("Minesweeper");

        //
        // data
        //
        int[] S = { -1, 0, 1 };

        Console.WriteLine("Problem:");
        for (int i = 0; i < r; i++)
        {
            for (int j = 0; j < c; j++)
            {
                if (game[i, j] > X)
                {
                    Console.Write(game[i, j] + " ");
                }
                else
                {
                    Console.Write("X ");
                }
            }
            Console.WriteLine();
        }
        Console.WriteLine();

        //
        // Decision variables
        //
        IntVar[,] mines = solver.MakeIntVarMatrix(r, c, 0, 1, "mines");
        // for branching
        IntVar[] mines_flat = mines.Flatten();

        //
        // Constraints
        //
        for (int i = 0; i < r; i++)
        {
            for (int j = 0; j < c; j++)
            {
                if (game[i, j] >= 0)
                {
                    solver.Add(mines[i, j] == 0);

                    // this cell is the sum of all its neighbours
                    var tmp = from a in S from b in S
                              where i +
                              a >= 0 && j + b >= 0 &&
                              i + a < r && j + b < c select(mines[i + a, j + b]);

                    solver.Add(tmp.ToArray().Sum() == game[i, j]);
                }

                if (game[i, j] > X)
                {
                    // This cell cannot be a mine since it
                    // has some value assigned to it
                    solver.Add(mines[i, j] == 0);
                }
            }
        }

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(mines_flat, Solver.CHOOSE_PATH, Solver.ASSIGN_MIN_VALUE);

        solver.NewSearch(db);

        int sol = 0;

        while (solver.NextSolution())
        {
            sol++;
            Console.WriteLine("Solution #{0} ", sol + " ");
            for (int i = 0; i < r; i++)
            {
                for (int j = 0; j < c; j++)
                {
                    Console.Write("{0} ", mines[i, j].Value());
                }
                Console.WriteLine();
            }

            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #2
0
    public static void Main(String[] args)
    {
        // Instantiate the solver.
        // [START solver]
        Solver solver = new Solver("CP is fun!");
        // [END solver]

        // [START variables]
        const int kBase = 10;

        // Decision variables.
        IntVar c = solver.MakeIntVar(1, kBase - 1, "C");
        IntVar p = solver.MakeIntVar(0, kBase - 1, "P");
        IntVar i = solver.MakeIntVar(1, kBase - 1, "I");
        IntVar s = solver.MakeIntVar(0, kBase - 1, "S");
        IntVar f = solver.MakeIntVar(1, kBase - 1, "F");
        IntVar u = solver.MakeIntVar(0, kBase - 1, "U");
        IntVar n = solver.MakeIntVar(0, kBase - 1, "N");
        IntVar t = solver.MakeIntVar(1, kBase - 1, "T");
        IntVar r = solver.MakeIntVar(0, kBase - 1, "R");
        IntVar e = solver.MakeIntVar(0, kBase - 1, "E");

        // Group variables in a vector so that we can use AllDifferent.
        IntVar[] letters = new IntVar[] { c, p, i, s, f, u, n, t, r, e };

        // Verify that we have enough digits.
        if (kBase < letters.Length)
        {
            throw new Exception("kBase < letters.Length");
        }
        // [END variables]

        // Define constraints.
        // [START constraints]
        solver.Add(letters.AllDifferent());

        // CP + IS + FUN = TRUE
        solver.Add(p + s + n + kBase * (c + i + u) + kBase * kBase * f ==
                   e + kBase * u + kBase * kBase * r + kBase * kBase * kBase * t);
        // [END constraints]

        // [START solve]
        int SolutionCount = 0;
        // Create the decision builder to search for solutions.
        DecisionBuilder db = solver.MakePhase(letters, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);

        solver.NewSearch(db);
        while (solver.NextSolution())
        {
            Console.Write("C=" + c.Value() + " P=" + p.Value());
            Console.Write(" I=" + i.Value() + " S=" + s.Value());
            Console.Write(" F=" + f.Value() + " U=" + u.Value());
            Console.Write(" N=" + n.Value() + " T=" + t.Value());
            Console.Write(" R=" + r.Value() + " E=" + e.Value());
            Console.WriteLine();

            // Is CP + IS + FUN = TRUE?
            if (p.Value() + s.Value() + n.Value() + kBase * (c.Value() + i.Value() + u.Value()) +
                kBase * kBase * f.Value() !=
                e.Value() + kBase * u.Value() + kBase * kBase * r.Value() + kBase * kBase * kBase * t.Value())
            {
                throw new Exception("CP + IS + FUN != TRUE");
            }
            SolutionCount++;
        }
        solver.EndSearch();
        Console.WriteLine($"Number of solutions found: {SolutionCount}");
        // [END solve]
    }
Beispiel #3
0
    /**
     *
     * Rogo puzzle solver.
     *
     * From http://www.rogopuzzle.co.nz/
     * """
     * The object is to collect the biggest score possible using a given
     * number of steps in a loop around a grid. The best possible score
     * for a puzzle is given with it, so you can easily check that you have
     * solved the puzzle. Rogo puzzles can also include forbidden squares,
     * which must be avoided in your loop.
     * """
     *
     * Also see Mike Trick:
     * "Operations Research, Sudoko, Rogo, and Puzzles"
     * http://mat.tepper.cmu.edu/blog/?p=1302
     *
     *
     * Also see, http://www.hakank.org/or-tools/rogo2.py
     * though this model differs in a couple of central points
     * which makes it much faster:
     *
     * - it use a table (
     * AllowedAssignments) with the valid connections
     * - instead of two coordinates arrays, it use a single path array
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("Rogo2");

        Console.WriteLine("\n");
        Console.WriteLine("**********************************************");
        Console.WriteLine("    {0}", problem_name);
        Console.WriteLine("**********************************************\n");

        //
        // Data
        //
        int B = -1;

        Console.WriteLine("Rows: {0} Cols: {1} Max Steps: {2}", rows, cols, max_steps);

        int[] problem_flatten = problem.Cast <int>().ToArray();
        int   max_point       = problem_flatten.Max();
        int   max_sum         = problem_flatten.Sum();

        Console.WriteLine("max_point: {0} max_sum: {1} best: {2}", max_point, max_sum, best);

        IEnumerable <int> STEPS  = Enumerable.Range(0, max_steps);
        IEnumerable <int> STEPS1 = Enumerable.Range(0, max_steps - 1);

        // the valid connections, to be used with AllowedAssignments
        IntTupleSet valid_connections = ValidConnections(rows, cols);

        //
        // Decision variables
        //
        IntVar[] path       = solver.MakeIntVarArray(max_steps, 0, rows * cols - 1, "path");
        IntVar[] points     = solver.MakeIntVarArray(max_steps, 0, best, "points");
        IntVar   sum_points = points.Sum().VarWithName("sum_points");

        //
        // Constraints
        //

        foreach (int s in STEPS)
        {
            // calculate the points (to maximize)
            solver.Add(points[s] == problem_flatten.Element(path[s]));

            // ensure that there are no black cells in
            // the path
            solver.Add(problem_flatten.Element(path[s]) != B);
        }

        solver.Add(path.AllDifferent());

        // valid connections
        foreach (int s in STEPS1)
        {
            solver.Add(new IntVar[] { path[s], path[s + 1] }.AllowedAssignments(valid_connections));
        }
        // around the corner
        solver.Add(new IntVar[] { path[max_steps - 1], path[0] }.AllowedAssignments(valid_connections));

        // Symmetry breaking
        for (int s = 1; s < max_steps; s++)
        {
            solver.Add(path[0] < path[s]);
        }

        //
        // Objective
        //
        OptimizeVar obj = sum_points.Maximize(1);

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(path, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT);

        solver.NewSearch(db, obj);

        while (solver.NextSolution())
        {
            Console.WriteLine("sum_points: {0}", sum_points.Value());
            Console.Write("path: ");
            foreach (int s in STEPS)
            {
                Console.Write("{0} ", path[s].Value());
            }
            Console.WriteLine();
            Console.WriteLine("(Adding 1 to coords...)");
            int[,] sol = new int[rows, cols];
            foreach (int s in STEPS)
            {
                int p = (int)path[s].Value();
                int x = (int)(p / cols);
                int y = (int)(p % cols);
                Console.WriteLine("{0,2},{1,2} ({2} points)", x + 1, y + 1, points[s].Value());
                sol[x, y] = 1;
            }
            Console.WriteLine("\nThe path is marked by 'X's:");
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    String p = sol[i, j] == 1 ? "X" : " ";
                    String q = problem[i, j] == B ? "B" : problem[i, j] == 0 ? "." : problem[i, j].ToString();
                    Console.Write("{0,2}{1} ", q, p);
                }
                Console.WriteLine();
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #4
0
    /**
     *
     * Simple regular expression.
     *
     * My last name (Kjellerstrand) is quite often misspelled
     * in ways that this regular expression shows:
     *   k(je|ä)ll(er|ar)?(st|b)r?an?d
     *
     * This model generates all the words that can be construed
     * by this regular expression.
     *
     *
     * Also see http://www.hakank.org/or-tools/regex.py
     *
     */
    private static void Solve(int n, List <String> res)
    {
        Solver solver = new Solver("RegexGeneration");

        Console.WriteLine("\nn: {0}", n);

        // The DFS (for regular)
        int n_states      = 11;
        int input_max     = 12;
        int initial_state = 1; // 0 is for the failing state

        int[] accepting_states = { 12 };

        // The DFA
        int[,] transition_fn =
        {
            // 1 2 3 4 5 6 7 8 9 0 1 2   //
            { 0, 2, 3, 0, 0, 0, 0, 0, 0,  0,  0,  0 }, //  1 k
            { 0, 0, 0, 4, 0, 0, 0, 0, 0,  0,  0,  0 }, //  2 je
            { 0, 0, 0, 4, 0, 0, 0, 0, 0,  0,  0,  0 }, //  3 ä
            { 0, 0, 0, 0, 5, 6, 7, 8, 0,  0,  0,  0 }, //  4 ll
            { 0, 0, 0, 0, 0, 0, 7, 8, 0,  0,  0,  0 }, //  5 er
            { 0, 0, 0, 0, 0, 0, 7, 8, 0,  0,  0,  0 }, //  6 ar
            { 0, 0, 0, 0, 0, 0, 0, 0, 9, 10,  0,  0 }, //  7 st
            { 0, 0, 0, 0, 0, 0, 0, 0, 9, 10,  0,  0 }, //  8 b
            { 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,  0,  0 }, //  9 r
            { 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 11, 12 }, // 10 a
            { 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 12 }, // 11 n
                                                       // 12 d
        };

        // Name of the states
        String[] s = { "k", "je", "ä", "ll", "er", "ar", "st", "b", "r", "a", "n", "d" };

        //
        // Decision variables
        //
        IntVar[] x = solver.MakeIntVarArray(n, 1, input_max, "x");

        //
        // Constraints
        //
        MyRegular(solver, x, n_states, input_max, transition_fn, initial_state, accepting_states);

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);

        solver.NewSearch(db);

        while (solver.NextSolution())
        {
            List <String> res2 = new List <String>();
            // State 1 (the start state) is not included in the
            // state array (x) so we add it first.
            res2.Add(s[0]);
            for (int i = 0; i < n; i++)
            {
                res2.Add(s[x[i].Value() - 1]);
            }
            res.Add(String.Join("", res2.ToArray()));
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #5
0
    /**
     *
     * Solves the N-Queens problem.
     *
     * Syntax: nqueens.exe n num print
     * where
     *    n    : size of board
     *    num  : number of solutions to calculate
     *    print: print the results (if > 0)
     *
     */
    private static void Solve(int n = 8, int num = 0, int print = 1)
    {
        Solver solver = new Solver("N-Queens");

        //
        // Decision variables
        //
        IntVar[] q = solver.MakeIntVarArray(n, 0, n - 1, "q");

        //
        // Constraints
        //
        solver.Add(q.AllDifferent());

        IntVar[] q1 = new IntVar[n];
        IntVar[] q2 = new IntVar[n];
        for (int i = 0; i < n; i++)
        {
            q1[i] = (q[i] + i).Var();
            q2[i] = (q[i] - i).Var();
        }
        solver.Add(q1.AllDifferent());
        solver.Add(q2.AllDifferent());

        // Alternative version: it works as well but are not that clear

        /*
         * solver.Add((from i in Enumerable.Range(0, n)
         *          select (q[i] + i).Var()).ToArray().AllDifferent());
         *
         * solver.Add((from i in Enumerable.Range(0, n)
         *          select (q[i] - i).Var()).ToArray().AllDifferent());
         */

        //
        // Search
        //
        DecisionBuilder db =
            solver.MakePhase(q, Solver.CHOOSE_MIN_SIZE_LOWEST_MAX, Solver.ASSIGN_CENTER_VALUE);

        solver.NewSearch(db);
        int c = 0;

        while (solver.NextSolution())
        {
            if (print > 0)
            {
                for (int i = 0; i < n; i++)
                {
                    Console.Write("{0} ", q[i].Value());
                }

                Console.WriteLine();
            }
            c++;
            if (num > 0 && c >= num)
            {
                break;
            }
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #6
0
    /**
     *
     * Sicherman Dice.
     *
     * From http://en.wikipedia.org/wiki/Sicherman_dice
     * ""
     * Sicherman dice are the only pair of 6-sided dice which are not normal dice,
     * bear only positive integers, and have the same probability distribution for
     * the sum as normal dice.
     *
     * The faces on the dice are numbered 1, 2, 2, 3, 3, 4 and 1, 3, 4, 5, 6, 8.
     * ""
     *
     * I read about this problem in a book/column by Martin Gardner long
     * time ago, and got inspired to model it now by the WolframBlog post
     * "Sicherman Dice": http://blog.wolfram.com/2010/07/13/sicherman-dice/
     *
     * This model gets the two different ways, first the standard way and
     * then the Sicherman dice:
     *
     *  x1 = [1, 2, 3, 4, 5, 6]
     *  x2 = [1, 2, 3, 4, 5, 6]
     *  ----------
     *  x1 = [1, 2, 2, 3, 3, 4]
     *  x2 = [1, 3, 4, 5, 6, 8]
     *
     *
     * Extra: If we also allow 0 (zero) as a valid value then the
     * following two solutions are also valid:
     *
     * x1 = [0, 1, 1, 2, 2, 3]
     * x2 = [2, 4, 5, 6, 7, 9]
     * ----------
     * x1 = [0, 1, 2, 3, 4, 5]
     * x2 = [2, 3, 4, 5, 6, 7]
     *
     * These two extra cases are mentioned here:
     * http://mathworld.wolfram.com/SichermanDice.html
     *
     *
     * Also see http://www.hakank.org/or-tools/sicherman_dice.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("SichermanDice");

        //
        // Data
        //
        int n            = 6;
        int m            = 10;
        int lowest_value = 0;

        // standard distribution
        int[] standard_dist = { 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1 };


        IEnumerable <int> RANGE  = Enumerable.Range(0, n);
        IEnumerable <int> RANGE1 = Enumerable.Range(0, n - 1);


        //
        // Decision variables
        //

        IntVar[] x1 = solver.MakeIntVarArray(n, lowest_value, m, "x1");
        IntVar[] x2 = solver.MakeIntVarArray(n, lowest_value, m, "x2");

        //
        // Constraints
        //
        for (int k = 0; k < standard_dist.Length; k++)
        {
            solver.Add((from i in RANGE
                        from j in RANGE
                        select x1[i] + x2[j] == k + 2
                        ).ToArray().Sum() == standard_dist[k]);
        }

        // symmetry breaking
        foreach (int i in RANGE1)
        {
            solver.Add(x1[i] <= x1[i + 1]);
            solver.Add(x2[i] <= x2[i + 1]);
            solver.Add(x1[i] <= x2[i]);
        }


        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(x1.Concat(x2).ToArray(),
                                              Solver.INT_VAR_DEFAULT,
                                              Solver.INT_VALUE_DEFAULT);

        solver.NewSearch(db);

        while (solver.NextSolution())
        {
            Console.Write("x1: ");
            foreach (int i in RANGE)
            {
                Console.Write(x1[i].Value() + " ");
            }
            Console.Write("\nx2: ");
            foreach (int i in RANGE)
            {
                Console.Write(x2[i].Value() + " ");
            }
            Console.WriteLine("\n");
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #7
0
    /**
     *
     * Secret Santa problem in Google CP Solver.
     *
     * From Ruby Quiz Secret Santa
     * http://www.rubyquiz.com/quiz2.html
     * """
     * Honoring a long standing tradition started by my wife's dad, my friends
     * all play a Secret Santa game around Christmas time. We draw names and
     * spend a week sneaking that person gifts and clues to our identity. On the
     * last night of the game, we get together, have dinner, share stories, and,
     * most importantly, try to guess who our Secret Santa was. It's a crazily
     * fun way to enjoy each other's company during the holidays.
     *
     * To choose Santas, we use to draw names out of a hat. This system was
     * tedious, prone to many 'Wait, I got myself...' problems. This year, we
     * made a change to the rules that further complicated picking and we knew
     * the hat draw would not stand up to the challenge. Naturally, to solve
     * this problem, I scripted the process. Since that turned out to be more
     * interesting than I had expected, I decided to share.
     *
     * This weeks Ruby Quiz is to implement a Secret Santa selection script.
     * *  Your script will be fed a list of names on STDIN.
     * ...
     * Your script should then choose a Secret Santa for every name in the list.
     * Obviously, a person cannot be their own Secret Santa. In addition, my friends
     * no longer allow people in the same family to be Santas for each other and your
     * script should take this into account.
     * """
     *
     *  Comment: This model skips the file input and mail parts. We
     *        assume that the friends are identified with a number from 1..n,
     *        and the families is identified with a number 1..num_families.
     *
     * Also see http://www.hakank.org/or-tools/secret_santa.py
     * Also see http://www.hakank.org/or-tools/secret_santa2.cs
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("SecretSanta");

        int[] family = { 1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 4, 4 };
        int   n      = family.Length;

        Console.WriteLine("n = {0}", n);

        IEnumerable <int> RANGE = Enumerable.Range(0, n);

        //
        // Decision variables
        //
        IntVar[] x = solver.MakeIntVarArray(n, 0, n - 1, "x");


        //
        // Constraints
        //
        solver.Add(x.AllDifferent());

        // Can't be one own"s Secret Santa
        // (i.e. ensure that there are no fix-point in the array.)
        foreach (int i in RANGE)
        {
            solver.Add(x[i] != i);
        }


        // No Secret Santa to a person in the same family
        foreach (int i in RANGE)
        {
            solver.Add(solver.MakeIntConst(family[i]) != family.Element(x[i]));
        }

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(x,
                                              Solver.INT_VAR_SIMPLE,
                                              Solver.INT_VALUE_SIMPLE);

        solver.NewSearch(db);

        while (solver.NextSolution())
        {
            Console.Write("x:  ");
            foreach (int i in RANGE)
            {
                Console.Write(x[i].Value() + " ");
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #8
0
    /**
     *
     * Eq 10 in Google CP Solver.
     *
     * Standard benchmark problem.
     *
     * Also see http://hakank.org/or-tools/eq10.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("Eq10");

        int n = 7;

        //
        // Decision variables
        //
        IntVar X1 = solver.MakeIntVar(0, 10, "X1");
        IntVar X2 = solver.MakeIntVar(0, 10, "X2");
        IntVar X3 = solver.MakeIntVar(0, 10, "X3");
        IntVar X4 = solver.MakeIntVar(0, 10, "X4");
        IntVar X5 = solver.MakeIntVar(0, 10, "X5");
        IntVar X6 = solver.MakeIntVar(0, 10, "X6");
        IntVar X7 = solver.MakeIntVar(0, 10, "X7");

        IntVar[] X = { X1, X2, X3, X4, X5, X6, X7 };


        //
        // Constraints
        //
        solver.Add(0 + 98527 * X1 + 34588 * X2 + 5872 * X3 + 59422 * X5 + 65159 * X7
                   == 1547604 + 30704 * X4 + 29649 * X6);

        solver.Add(0 + 98957 * X2 + 83634 * X3 + 69966 * X4 + 62038 * X5 + 37164 * X6 + 85413 * X7
                   == 1823553 + 93989 * X1);

        solver.Add(900032 + 10949 * X1 + 77761 * X2 + 67052 * X5
                   == 0 + 80197 * X3 + 61944 * X4 + 92964 * X6 + 44550 * X7);

        solver.Add(0 + 73947 * X1 + 84391 * X3 + 81310 * X5
                   == 1164380 + 96253 * X2 + 44247 * X4 + 70582 * X6 + 33054 * X7);

        solver.Add(0 + 13057 * X3 + 42253 * X4 + 77527 * X5 + 96552 * X7
                   == 1185471 + 60152 * X1 + 21103 * X2 + 97932 * X6);

        solver.Add(1394152 + 66920 * X1 + 55679 * X4
                   == 0 + 64234 * X2 + 65337 * X3 + 45581 * X5 + 67707 * X6 + 98038 * X7);

        solver.Add(0 + 68550 * X1 + 27886 * X2 + 31716 * X3 + 73597 * X4 + 38835 * X7
                   == 279091 + 88963 * X5 + 76391 * X6);

        solver.Add(0 + 76132 * X2 + 71860 * X3 + 22770 * X4 + 68211 * X5 + 78587 * X6
                   == 480923 + 48224 * X1 + 82817 * X7);

        solver.Add(519878 + 94198 * X2 + 87234 * X3 + 37498 * X4
                   == 0 + 71583 * X1 + 25728 * X5 + 25495 * X6 + 70023 * X7);

        solver.Add(361921 + 78693 * X1 + 38592 * X5 + 38478 * X6
                   == 0 + 94129 * X2 + 43188 * X3 + 82528 * X4 + 69025 * X7);

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(X,
                                              Solver.INT_VAR_DEFAULT,
                                              Solver.INT_VALUE_DEFAULT);

        solver.NewSearch(db);

        while (solver.NextSolution())
        {
            for (int i = 0; i < n; i++)
            {
                Console.Write(X[i].ToString() + " ");
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: " + solver.Solutions());
        Console.WriteLine("WallTime: " + solver.WallTime() + "ms ");
        Console.WriteLine("Failures: " + solver.Failures());
        Console.WriteLine("Branches: " + solver.Branches());

        solver.EndSearch();
    }
Beispiel #9
0
    /**
     *
     * Max flow problem.
     *
     * From Winston 'Operations Research', page 420f, 423f
     * Sunco Oil example.
     *
     *
     * Also see http://www.hakank.org/or-tools/max_flow_winston1.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("MaxFlowWinston1");

        //
        // Data
        //
        int n = 5;
        IEnumerable <int> NODES = Enumerable.Range(0, n);

        // The arcs
        // Note:
        // This is 1-based to be compatible with other implementations.
        //
        int[,] arcs1 =
        {
            { 1, 2 },
            { 1, 3 },
            { 2, 3 },
            { 2, 4 },
            { 3, 5 },
            { 4, 5 },
            { 5, 1 }
        };

        // Capacities
        int [] cap = { 2, 3, 3, 4, 2, 1, 100 };

        // Convert arcs to 0-based
        int num_arcs           = arcs1.GetLength(0);
        IEnumerable <int> ARCS = Enumerable.Range(0, num_arcs);

        int[,] arcs = new int[num_arcs, 2];
        foreach (int i in ARCS)
        {
            for (int j = 0; j < 2; j++)
            {
                arcs[i, j] = arcs1[i, j] - 1;
            }
        }

        // Convert arcs to matrix (for sanity checking below)
        int[,] mat = new int[num_arcs, num_arcs];
        foreach (int i in NODES)
        {
            foreach (int j in NODES)
            {
                int c = 0;
                foreach (int k in ARCS)
                {
                    if (arcs[k, 0] == i && arcs[k, 1] == j)
                    {
                        c = 1;
                    }
                }
                mat[i, j] = c;
            }
        }

        //
        // Decision variables
        //
        IntVar[,] flow = solver.MakeIntVarMatrix(n, n, 0, 200, "flow");
        IntVar z = flow[n - 1, 0].VarWithName("z");

        //
        // Constraints
        //

        // capacity of arcs
        foreach (int i in ARCS)
        {
            solver.Add(flow[arcs[i, 0], arcs[i, 1]] <= cap[i]);
        }

        // inflows == outflows
        foreach (int i in NODES)
        {
            var s1 = (from k in ARCS
                      where arcs[k, 1] == i
                      select flow[arcs[k, 0], arcs[k, 1]]
                      ).ToArray().Sum();

            var s2 = (from k in ARCS
                      where arcs[k, 0] == i
                      select flow[arcs[k, 0], arcs[k, 1]]
                      ).ToArray().Sum();

            solver.Add(s1 == s2);
        }

        // Sanity check: just arcs with connections can have a flow.
        foreach (int i in NODES)
        {
            foreach (int j in NODES)
            {
                if (mat[i, j] == 0)
                {
                    solver.Add(flow[i, j] == 0);
                }
            }
        }


        //
        // Objective
        //
        OptimizeVar obj = z.Maximize(1);

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(flow.Flatten(),
                                              Solver.INT_VAR_DEFAULT,
                                              Solver.ASSIGN_MAX_VALUE);

        solver.NewSearch(db, obj);

        while (solver.NextSolution())
        {
            Console.WriteLine("z: {0}", z.Value());
            foreach (int i in NODES)
            {
                foreach (int j in NODES)
                {
                    Console.Write(flow[i, j].Value() + " ");
                }
                Console.WriteLine();
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #10
0
    /**
     *
     * This model was inspired by David Curran's
     * blog post "The Fairest Way to Pick a Team "
     * http://liveatthewitchtrials.blogspot.se/2012/06/fairest-way-to-pick-team.html
     * """
     * What is the best way to pick a team? As kids we would always strictly alternate
     * between teams so team 1 had first team 2 the second pick and then team 1 again etc.
     *
     * Most things you can measure about people are on a bell curve. A small number of
     * people are bad, most are in the middle and a few are good. There are a few good
     * known metrics of ability. None are perfect, there is no one number that can sum up
     * ability. The simpler the sport the more one metric can tell you, in cycling VO2 max is
     * a very good indicator. Whereas in soccer VO2 max, kicking speed, vertical leap, number
     * of keep me ups you can do etc could all measure some part of football ability.
     *
     * So say there was one good metric for a task and teams were picked based on this.
     * Is the standard strict alteration, where Team 1 picks then Team 2 alternating, fair?
     * Fair here meaning both teams end up with a similar quality.
     * """
     *
     * This version has two changes compared to http://www.hakank.org/or-tools/picking_teams.cs
     * - there can be more than 2 teams
     * - it don't have to be exactly the same number of members in each team
     *
     *
     * Model by Hakan Kjellerstrand ([email protected])
     *
     * See other or-tools/C# models at http://www.hakank.org/or-tools/#csharp
     *
     */
    private static void Solve(int n = 10, int num_teams = 2, int team_diff = 1, int max = 10, int sols_to_show = 0)
    {
        Solver solver = new Solver("PickingTeams");

        Console.WriteLine("n        : " + n);
        Console.WriteLine("num_teams: " + num_teams); // New
        Console.WriteLine("team_diff: " + team_diff); // New
        Console.WriteLine("max      : " + max);
        Console.WriteLine("sols_to_show: " + sols_to_show);

        // New: We skip this check
        // if (n % num_teams != 0) {
        //   Console.WriteLine("The number of people (n) must be divisible by 2.");
        //   System.Environment.Exit(1);
        // }

        //
        // Data
        //

        // Randomize data:
        int    seed      = (int)DateTime.Now.Ticks;
        Random generator = new Random(seed);

        int[] s = new int[n];
        for (int i = 0; i < n; i++)
        {
            s[i] = 1 + generator.Next(max);
            if (n <= 100)
            {
                Console.Write(s[i] + " ");
            }
        }
        Console.WriteLine();
        Console.WriteLine("\n" + n + " numbers generated\n");

        int the_sum  = s.Sum();
        int half_sum = (int)the_sum / num_teams;

        Console.WriteLine("sum: " + the_sum + " half_sum: " + half_sum);


        IEnumerable <int> NRange = Enumerable.Range(0, n);

        //
        // Decision variables
        //

        // To which team (s) do x[i] belong?
        // New: Added num_teams-1
        IntVar[] x = solver.MakeIntVarArray(n, 0, num_teams - 1, "x");

        // The old version for 2 teams
        // IntVar diff = (
        //          (from k in NRange select (s[k]*(x[k] == 0)) ).ToArray().Sum() -
        //          (from k in NRange select (s[k]*(x[k] == 1)) ).ToArray().Sum()
        //          ).Abs().Var();

        // New:
        // Calculate the team sums
        // Note: It is more efficient to restrict lower and upper bounds of the team sums.
        //       Here I arbitrarily allow a slack of
        //          sum +/- (half_sum/num_teams)
        //       For specific applications this might be adjusted.
        int n3 = half_sum / num_teams;

        Console.WriteLine("n3: " + n3);
        Console.WriteLine("half_sum-n3 " + (half_sum - n3) + "... half_sum+n3: " + (half_sum + n3));
        IntVar[] team_sum = solver.MakeIntVarArray(num_teams, half_sum - n3, half_sum + n3, "team_sum");
        for (int team = 0; team < num_teams; team++)
        {
            team_sum[team] = (from k in NRange select(s[k] * (x[k] == team))).ToArray().Sum().Var();
        }

        // New:
        // Calculate the total number of difference points between the
        // teams (to be minimized)
        IntVar diff = (from t1 in Enumerable.Range(0, num_teams)
                       from t2 in Enumerable.Range(0, num_teams)
                       where t1 < t2
                       select(team_sum[t1] - team_sum[t2]).Abs().Var()).ToArray().Sum().Var();

        Console.WriteLine("diff.Max(): " + diff.Max());

        //
        // New: Number of members in each team
        //
        // Note that we restrict the possible values to +/- team_diff.
        int n2 = (int)n / num_teams;

        Console.WriteLine("n2: " + n2);
        IntVar[] team_num = solver.MakeIntVarArray(num_teams, n2 - team_diff, n2 + team_diff, "team_num");
        for (int team = 0; team < num_teams; team++)
        {
            team_num[team] = (from k in NRange select(x[k] == team)).ToArray().Sum().Var();
        }

        // New: We send all the IntVar arrays to the solver
        IntVar[] all = x.Concat(team_sum).Concat(team_num).ToArray();


        //
        // Constraints
        //

        // New: Ensure that there are the (about) same number of people in each team.
        for (int t = 0; t < num_teams; t++)
        {
            solver.Add((((from k in NRange select(x[k] == t)).ToArray().Sum() - n2)).Abs() <= team_diff);
        }

        // The teams_sums should add up to the total sum
        solver.Add(team_sum.Sum() == the_sum);

        // symmetry breaking: assign first member to team 0
        solver.Add(x[0] == 0);

        // Odd sum must yield odd diff, even sum yield even diff
        IntVar even_odd = solver.MakeIntConst(the_sum % 2);

        solver.Add(solver.MakeModuloConstraint(diff, 2, even_odd));


        //
        // Search
        //

        DecisionBuilder db = solver.MakePhase(all,
                                              // Solver.INT_VAR_DEFAULT,
                                              // Solver.INT_VAR_SIMPLE,
                                              // Solver.CHOOSE_FIRST_UNBOUND,
                                              // Solver.CHOOSE_RANDOM,
                                              Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
                                              // Solver.CHOOSE_MIN_SIZE_HIGHEST_MIN,
                                              // Solver.CHOOSE_MIN_SIZE_LOWEST_MAX,
                                              // Solver.CHOOSE_MIN_SIZE_HIGHEST_MAX,
                                              // Solver.CHOOSE_PATH,


                                              // Solver.INT_VALUE_DEFAULT
                                              // Solver.INT_VALUE_SIMPLE
                                              // Solver.ASSIGN_MIN_VALUE
                                              // Solver.ASSIGN_MAX_VALUE
                                              Solver.ASSIGN_RANDOM_VALUE
                                              // Solver.ASSIGN_CENTER_VALUE
                                              );


        /*
         * DefaultPhaseParameters parameters = new DefaultPhaseParameters();
         *
         * parameters.heuristic_period = 20;
         * // parameters.heuristic_period = 10;
         *
         * // parameters.heuristic_num_failures_limit = 1000;
         * // parameters.restart_log_size = -1;
         * // parameters.restart_log_size = 100;
         * // parameters.run_all_heuristics = false;
         *
         * // parameters.var_selection_schema = DefaultPhaseParameters.CHOOSE_MAX_SUM_IMPACT;
         * // parameters.var_selection_schema = DefaultPhaseParameters.CHOOSE_MAX_AVERAGE_IMPACT ;
         * parameters.var_selection_schema = DefaultPhaseParameters.CHOOSE_MAX_VALUE_IMPACT;
         *
         * // parameters.value_selection_schema = DefaultPhaseParameters.SELECT_MIN_IMPACT;
         * parameters.value_selection_schema = DefaultPhaseParameters.SELECT_MAX_IMPACT;
         *
         * parameters.initialization_splits = 10;
         * // parameters.initialization_splits = 20;
         * // parameters.initialization_splits = n;
         *
         * // parameters.random_seed = 0;
         *
         * DecisionBuilder db = solver.MakeDefaultPhase(all, parameters);
         */


        OptimizeVar opt = diff.Minimize(1);

        solver.NewSearch(db, opt);

        int sols = 0;

        while (solver.NextSolution())
        {
            sols++;

            Console.WriteLine("\n\nDiff: " + diff.Value());

            if (n <= 10000)
            {
                Console.WriteLine("Assignment: ");
                long[] assignments = new long[n];
                foreach (int i in NRange)
                {
                    Console.Write(x[i].Value() + " ");
                    assignments[i] = x[i].Value();
                }
                Console.WriteLine();


                for (int team = 0; team < num_teams; team++)
                {
                    Console.Write("team " + team + ": ");
                    foreach (int i in NRange)
                    {
                        if (assignments[i] == team)
                        {
                            Console.Write((i) + " ");
                        }
                    }
                    Console.WriteLine();
                }
            }

            Console.Write("Sum of each team            : ");
            for (int t = 0; t < num_teams; t++)
            {
                Console.Write(team_sum[t].Value() + " ");
            }
            Console.WriteLine();

            Console.Write("Number of members in each team: ");
            for (int t = 0; t < num_teams; t++)
            {
                Console.Write(team_num[t].Value() + " ");
            }
            Console.WriteLine();

            if (sols_to_show > 0 && sols >= sols_to_show)
            {
                break;
            }
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
    /**
     *
     * Moving furnitures (scheduling) problem in Google CP Solver.
     *
     * Marriott & Stukey: 'Programming with constraints', page  112f
     *
     * The model implements an decomposition of the global constraint
     * cumulative (see above).
     *
     * Also see http://www.hakank.org/or-tools/furniture_moving.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("FurnitureMoving");

        int n = 4;

        int[] duration    = { 30, 10, 15, 15 };
        int[] demand      = { 3, 1, 3, 2 };
        int   upper_limit = 160;

        //
        // Decision variables
        //
        IntVar[] start_times = solver.MakeIntVarArray(n, 0, upper_limit, "start_times");
        IntVar[] end_times   = solver.MakeIntVarArray(n, 0, upper_limit * 2, "end_times");
        IntVar   end_time    = solver.MakeIntVar(0, upper_limit * 2, "end_time");

        // number of needed resources, to be minimized or constrained
        IntVar num_resources = solver.MakeIntVar(0, 10, "num_resources");

        //
        // Constraints
        //
        for (int i = 0; i < n; i++)
        {
            solver.Add(end_times[i] == start_times[i] + duration[i]);
        }

        solver.Add(end_time == end_times.Max());
        MyCumulative(solver, start_times, duration, demand, num_resources);

        //
        // Some extra constraints to play with
        //

        // all tasks must end within an hour
        // solver.Add(end_time <= 60);

        // All tasks should start at time 0
        // for(int i = 0; i < n; i++) {
        //   solver.Add(start_times[i] == 0);
        // }

        // limitation of the number of people
        // solver.Add(num_resources <= 3);
        solver.Add(num_resources <= 4);

        //
        // Objective
        //

        // OptimizeVar obj = num_resources.Minimize(1);
        OptimizeVar obj = end_time.Minimize(1);

        //
        // Search
        //
        DecisionBuilder db =
            solver.MakePhase(start_times, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);

        solver.NewSearch(db, obj);

        while (solver.NextSolution())
        {
            Console.WriteLine("num_resources: {0} end_time: {1}", num_resources.Value(),
                              end_time.Value());
            for (int i = 0; i < n; i++)
            {
                Console.WriteLine("Task {0,1}: {1,2} -> {2,2} -> {3,2} (demand: {4})", i,
                                  start_times[i].Value(), duration[i], end_times[i].Value(), demand[i]);
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #12
0
 public void EndSearch()
 {
     pinned_decision_builder_ = null;
     pinned_search_monitors_.Clear();
     EndSearchAux();
 }
Beispiel #13
0
    /**
     *
     * Bus scheduling.
     *
     * Minimize number of buses in timeslots.
     *
     * Problem from Taha "Introduction to Operations Research", page 58.
     *
     * This is a slightly more general model than Taha's.
     *
     * Also see, http://www.hakank.org/or-tools/bus_schedule.py
     *
     */
    private static long Solve(long num_buses_check = 0)
    {
        Solver solver = new Solver("BusSchedule");

        //
        // data
        //
        int time_slots = 6;

        int[] demands = { 8, 10, 7, 12, 4, 4 };
        int   max_num = demands.Sum();

        //
        // Decision variables
        //

        // How many buses start the schedule at time slot t
        IntVar[] x = solver.MakeIntVarArray(time_slots, 0, max_num, "x");
        // Total number of buses
        IntVar num_buses = x.Sum().VarWithName("num_buses");

        //
        // Constraints
        //

        // Meet the demands for this and the next time slot.
        for (int i = 0; i < time_slots - 1; i++)
        {
            solver.Add(x[i] + x[i + 1] >= demands[i]);
        }

        // The demand "around the clock"
        solver.Add(x[time_slots - 1] + x[0] - demands[time_slots - 1] == 0);

        // For showing all solutions of minimal number of buses
        if (num_buses_check > 0)
        {
            solver.Add(num_buses == num_buses_check);
        }

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);

        if (num_buses_check == 0)
        {
            // Minimize num_buses
            OptimizeVar obj = num_buses.Minimize(1);
            solver.NewSearch(db, obj);
        }
        else
        {
            solver.NewSearch(db);
        }

        long result = 0;

        while (solver.NextSolution())
        {
            result = num_buses.Value();
            Console.Write("x: ");
            for (int i = 0; i < time_slots; i++)
            {
                Console.Write("{0,2} ", x[i].Value());
            }
            Console.WriteLine("num_buses: " + num_buses.Value());
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();

        return(result);
    }
    /**
     *
     * Nurse rostering
     *
     * This is a simple nurse rostering model using a DFA and
     * my decomposition of regular constraint.
     *
     * The DFA is from MiniZinc Tutorial, Nurse Rostering example:
     * - one day off every 4 days
     * - no 3 nights in a row.
     *
     * Also see http://www.hakank.org/or-tools/nurse_rostering.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("NurseRostering");

        //
        // Data
        //

        // Note: If you change num_nurses or num_days,
        //       please also change the constraints
        //       on nurse_stat and/or day_stat.
        int num_nurses = 7;
        int num_days   = 14;

        // Note: I had to add a dummy shift.
        int dummy_shift = 0;
        int day_shift   = 1;
        int night_shift = 2;
        int off_shift   = 3;

        int[] shifts       = { dummy_shift, day_shift, night_shift, off_shift };
        int[] valid_shifts = { day_shift, night_shift, off_shift };

        // the DFA (for regular)
        int n_states      = 6;
        int input_max     = 3;
        int initial_state = 1; // 0 is for the failing state

        int[] accepting_states = { 1, 2, 3, 4, 5, 6 };

        int[,] transition_fn =
        {
            // d,n,o
            { 2, 3, 1 }, // state 1
            { 4, 4, 1 }, // state 2
            { 4, 5, 1 }, // state 3
            { 6, 6, 1 }, // state 4
            { 6, 0, 1 }, // state 5
            { 0, 0, 1 } // state 6
        };

        string[] days = { "d", "n", "o" }; // for presentation

        //
        // Decision variables
        //

        // For regular
        IntVar[,] x =
            solver.MakeIntVarMatrix(num_nurses, num_days, valid_shifts, "x");
        IntVar[] x_flat = x.Flatten();

        // summary of the nurses
        IntVar[] nurse_stat =
            solver.MakeIntVarArray(num_nurses, 0, num_days, "nurse_stat");

        // summary of the shifts per day
        int num_shifts = shifts.Length;

        IntVar[,] day_stat = new IntVar[num_days, num_shifts];
        for (int i = 0; i < num_days; i++)
        {
            for (int j = 0; j < num_shifts; j++)
            {
                day_stat[i, j] = solver.MakeIntVar(0, num_nurses, "day_stat");
            }
        }


        //
        // Constraints
        //
        for (int i = 0; i < num_nurses; i++)
        {
            IntVar[] reg_input = new IntVar[num_days];
            for (int j = 0; j < num_days; j++)
            {
                reg_input[j] = x[i, j];
            }
            MyRegular(solver, reg_input, n_states, input_max, transition_fn,
                      initial_state, accepting_states);
        }

        //
        // Statistics and constraints for each nurse
        //
        for (int i = 0; i < num_nurses; i++)
        {
            // Number of worked days (either day or night shift)
            IntVar[] b = new IntVar[num_days];
            for (int j = 0; j < num_days; j++)
            {
                b[j] = ((x[i, j] == day_shift) + (x[i, j] == night_shift)).Var();
            }
            solver.Add(b.Sum() == nurse_stat[i]);

            // Each nurse must work between 7 and 10
            // days/nights during this period
            solver.Add(nurse_stat[i] >= 7);
            solver.Add(nurse_stat[i] <= 10);
        }


        //
        // Statistics and constraints for each day
        //
        for (int j = 0; j < num_days; j++)
        {
            for (int t = 0; t < num_shifts; t++)
            {
                IntVar[] b = new IntVar[num_nurses];
                for (int i = 0; i < num_nurses; i++)
                {
                    b[i] = x[i, j] == t;
                }
                solver.Add(b.Sum() == day_stat[j, t]);
            }

            //
            // Some constraints for each day:
            //
            // Note: We have a strict requirements of
            //       the number of shifts.
            //       Using atleast constraints is harder
            //       in this model.
            //
            if (j % 7 == 5 || j % 7 == 6)
            {
                // special constraints for the weekends
                solver.Add(day_stat[j, day_shift] == 2);
                solver.Add(day_stat[j, night_shift] == 1);
                solver.Add(day_stat[j, off_shift] == 4);
            }
            else
            {
                // for workdays:

                // - exactly 3 on day shift
                solver.Add(day_stat[j, day_shift] == 3);
                // - exactly 2 on night
                solver.Add(day_stat[j, night_shift] == 2);
                // - exactly 2 off duty
                solver.Add(day_stat[j, off_shift] == 2);
            }
        }


        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(x_flat,
                                              Solver.CHOOSE_FIRST_UNBOUND,
                                              Solver.ASSIGN_MIN_VALUE);

        solver.NewSearch(db);

        int num_solutions = 0;

        while (solver.NextSolution())
        {
            num_solutions++;
            for (int i = 0; i < num_nurses; i++)
            {
                Console.Write("Nurse #{0,-2}: ", i);
                var occ = new Dictionary <int, int>();
                for (int j = 0; j < num_days; j++)
                {
                    int v = (int)x[i, j].Value() - 1;
                    if (!occ.ContainsKey(v))
                    {
                        occ[v] = 0;
                    }
                    occ[v]++;
                    Console.Write(days[v] + " ");
                }

                Console.Write(" #workdays: {0,2}", nurse_stat[i].Value());
                foreach (int s in valid_shifts)
                {
                    int v = 0;
                    if (occ.ContainsKey(s - 1))
                    {
                        v = occ[s - 1];
                    }
                    Console.Write("  {0}:{1}", days[s - 1], v);
                }
                Console.WriteLine();
            }
            Console.WriteLine();

            Console.WriteLine("Statistics per day:\nDay      d n o");
            for (int j = 0; j < num_days; j++)
            {
                Console.Write("Day #{0,2}: ", j);
                foreach (int t in valid_shifts)
                {
                    Console.Write(day_stat[j, t].Value() + " ");
                }
                Console.WriteLine();
            }
            Console.WriteLine();

            // We just show 2 solutions
            if (num_solutions > 1)
            {
                break;
            }
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #15
0
 public void NewSearch(DecisionBuilder db,
                       SearchMonitor sm1,
                       SearchMonitor sm2,
                       SearchMonitor sm3,
                       SearchMonitor sm4) {
   pinned_decision_builder_ = db;
   pinned_search_monitors_.Clear();
   pinned_search_monitors_.Add(sm1);
   pinned_search_monitors_.Add(sm2);
   pinned_search_monitors_.Add(sm3);
   pinned_search_monitors_.Add(sm4);
   NewSearchAux(db, sm1, sm2, sm3, sm4);
 }
Beispiel #16
0
    /**
     *
     * Set partition problem.
     *
     * Problem formulation from
     * http://www.koalog.com/resources/samples/PartitionProblem.java.html
     * """
     * This is a partition problem.
     * Given the set S = {1, 2, ..., n},
     * it consists in finding two sets A and B such that:
     *
     *  A U B = S,
     *  |A| = |B|,
     *  sum(A) = sum(B),
     *  sum_squares(A) = sum_squares(B)
     *
     * """
     *
     * This model uses a binary matrix to represent the sets.
     *
     *
     * Also see http://www.hakank.org/or-tools/set_partition.py
     *
     */
    private static void Solve(int n = 16, int num_sets = 2)
    {
        Solver solver = new Solver("SetPartition");

        Console.WriteLine("n: {0}", n);
        Console.WriteLine("num_sets: {0}", num_sets);

        IEnumerable <int> Sets   = Enumerable.Range(0, num_sets);
        IEnumerable <int> NRange = Enumerable.Range(0, n);

        //
        // Decision variables
        //
        IntVar[,] a = solver.MakeIntVarMatrix(num_sets, n, 0, 1, "a");
        IntVar[] a_flat = a.Flatten();

        //
        // Constraints
        //

        // partition set
        partition_sets(solver, a, num_sets, n);

        foreach (int i in Sets)
        {
            foreach (int j in Sets)
            {
                // same cardinality
                solver.Add((from k in NRange select a[i, k]).ToArray().Sum() ==
                           (from k in NRange select a[j, k]).ToArray().Sum());

                // same sum
                solver.Add((from k in NRange select(k * a[i, k])).ToArray().Sum() ==
                           (from k in NRange select(k * a[j, k])).ToArray().Sum());

                // same sum squared
                solver.Add((from k in NRange select(k * a[i, k] * k * a[i, k])).ToArray().Sum() ==
                           (from k in NRange select(k * a[j, k] * k * a[j, k])).ToArray().Sum());
            }
        }

        // symmetry breaking for num_sets == 2
        if (num_sets == 2)
        {
            solver.Add(a[0, 0] == 1);
        }

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(a_flat, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT);

        solver.NewSearch(db);

        while (solver.NextSolution())
        {
            int[,] a_val = new int[num_sets, n];
            foreach (int i in Sets)
            {
                foreach (int j in NRange)
                {
                    a_val[i, j] = (int)a[i, j].Value();
                }
            }
            Console.WriteLine("sums: {0}",
                              (from j in NRange select(j + 1) * a_val[0, j]).ToArray().Sum());

            Console.WriteLine(
                "sums squared: {0}",
                (from j in NRange select(int) Math.Pow((j + 1) * a_val[0, j], 2)).ToArray().Sum());

            // Show the numbers in each set
            foreach (int i in Sets)
            {
                if ((from j in NRange select a_val[i, j]).ToArray().Sum() > 0)
                {
                    Console.Write(i + 1 + ": ");
                    foreach (int j in NRange)
                    {
                        if (a_val[i, j] == 1)
                        {
                            Console.Write((j + 1) + " ");
                        }
                    }
                    Console.WriteLine();
                }
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #17
0
    /**
     *
     * Secret Santa problem II in Google CP Solver.
     *
     * From Maple Primes: 'Secret Santa Graph Theory'
     * http://www.mapleprimes.com/blog/jpmay/secretsantagraphtheory
     * """
     * Every year my extended family does a 'secret santa' gift exchange.
     * Each person draws another person at random and then gets a gift for
     * them. At first, none of my siblings were married, and so the draw was
     * completely random. Then, as people got married, we added the restriction
     * that spouses should not draw each others names. This restriction meant
     * that we moved from using slips of paper on a hat to using a simple
     * computer program to choose names. Then people began to complain when
     * they would get the same person two years in a row, so the program was
     * modified to keep some history and avoid giving anyone a name in their
     * recent history. This year, not everyone was participating, and so after
     * removing names, and limiting the number of exclusions to four per person,
     * I had data something like this:
     *
     * Name: Spouse, Recent Picks
     *
     * Noah: Ava. Ella, Evan, Ryan, John
     * Ava: Noah, Evan, Mia, John, Ryan
     * Ryan: Mia, Ella, Ava, Lily, Evan
     * Mia: Ryan, Ava, Ella, Lily, Evan
     * Ella: John, Lily, Evan, Mia, Ava
     * John: Ella, Noah, Lily, Ryan, Ava
     * Lily: Evan, John, Mia, Ava, Ella
     * Evan: Lily, Mia, John, Ryan, Noah
     * """
     *
     *  Note: I interpret this as the following three constraints:
     * 1) One cannot be a Secret Santa of one's spouse
     * 2) One cannot be a Secret Santa for somebody two years in a row
     * 3) Optimization: maximize the time since the last time
     *
     *  This model also handle single persons, something the original
     *  problem don't mention.
     *
     *
     * Also see http://www.hakank.org/or-tools/secret_santa2.py
     *
     */
    private static void Solve(int single = 0)
    {
        Solver solver = new Solver("SecretSanta2");

        Console.WriteLine("\nSingle: {0}", single);

        //
        // The matrix version of earlier rounds.
        // M means that no earlier Santa has been assigned.
        // Note: Ryan and Mia has the same recipient for years 3 and 4,
        //       and Ella and John has for year 4.
        //       This seems to be caused by modification of
        //       original data.
        //
        int n_no_single = 8;
        int M           = n_no_single + 1;

        int[][] rounds_no_single =
        {
            // N  A  R  M  El J  L  Ev
            new int[] { 0, M, 3, M, 1, 4, M, 2 }, // Noah
            new int[] { M, 0, 4, 2, M, 3, M, 1 }, // Ava
            new int[] { M, 2, 0, M, 1, M, 3, 4 }, // Ryan
            new int[] { M, 1, M, 0, 2, M, 3, 4 }, // Mia
            new int[] { M, 4, M, 3, 0, M, 1, 2 }, // Ella
            new int[] { 1, 4, 3, M, M, 0, 2, M }, // John
            new int[] { M, 3, M, 2, 4, 1, 0, M }, // Lily
            new int[] { 4, M, 3, 1, M, 2, M, 0 } // Evan
        };

        //
        // Rounds with a single person (fake data)
        //
        int n_with_single = 9;

        M = n_with_single + 1;
        int[][] rounds_single =
        {
            // N  A  R  M  El J  L  Ev S
            new int[] { 0, M, 3, M, 1, 4, M, 2, 2 }, // Noah
            new int[] { M, 0, 4, 2, M, 3, M, 1, 1 }, // Ava
            new int[] { M, 2, 0, M, 1, M, 3, 4, 4 }, // Ryan
            new int[] { M, 1, M, 0, 2, M, 3, 4, 3 }, // Mia
            new int[] { M, 4, M, 3, 0, M, 1, 2, M }, // Ella
            new int[] { 1, 4, 3, M, M, 0, 2, M, M }, // John
            new int[] { M, 3, M, 2, 4, 1, 0, M, M }, // Lily
            new int[] { 4, M, 3, 1, M, 2, M, 0, M }, // Evan
            new int[] { 1, 2, 3, 4, M, 2, M, M, 0 } // Single
        };


        int Noah = 0;
        int Ava  = 1;
        int Ryan = 2;
        int Mia  = 3;
        int Ella = 4;
        int John = 5;
        int Lily = 6;
        int Evan = 7;

        int n = n_no_single;

        int[][] rounds = rounds_no_single;
        if (single == 1)
        {
            n      = n_with_single;
            rounds = rounds_single;
        }
        M = n + 1;

        IEnumerable <int> RANGE = Enumerable.Range(0, n);



        String[] persons = { "Noah", "Ava",  "Ryan", "Mia", "Ella",
                             "John", "Lily", "Evan", "Single" };

        int[] spouses =
        {
            Ava,  // Noah
            Noah, // Ava
            Mia,  // Rya
            Ryan, // Mia
            John, // Ella
            Ella, // John
            Evan, // Lily
            Lily, // Evan
            -1    // Single has no spouse
        };


        //
        // Decision variables
        //
        IntVar[] santas         = solver.MakeIntVarArray(n, 0, n - 1, "santas");
        IntVar[] santa_distance = solver.MakeIntVarArray(n, 0, M, "santa_distance");

        // total of "distance", to maximize
        IntVar z = santa_distance.Sum().VarWithName("z");


        //
        // Constraints
        //
        solver.Add(santas.AllDifferent());

        // Can't be one own"s Secret Santa
        // (i.e. ensure that there are no fix-point in the array.)
        foreach (int i in RANGE)
        {
            solver.Add(santas[i] != i);
        }


        // no Santa for a spouses
        foreach (int i in RANGE)
        {
            if (spouses[i] > -1)
            {
                solver.Add(santas[i] != spouses[i]);
            }
        }

        // optimize "distance" to earlier rounds:
        foreach (int i in RANGE)
        {
            solver.Add(santa_distance[i] == rounds[i].Element(santas[i]));
        }


        // cannot be a Secret Santa for the same person
        // two years in a row.
        foreach (int i in RANGE)
        {
            foreach (int j in RANGE)
            {
                if (rounds[i][j] == 1)
                {
                    solver.Add(santas[i] != j);
                }
            }
        }


        //
        // Objective (minimize the distances)
        //
        OptimizeVar obj = z.Maximize(1);


        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(santas,
                                              Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
                                              Solver.ASSIGN_CENTER_VALUE);

        solver.NewSearch(db, obj);

        while (solver.NextSolution())
        {
            Console.WriteLine("\ntotal distances: {0}", z.Value());
            Console.Write("santas:  ");
            for (int i = 0; i < n; i++)
            {
                Console.Write(santas[i].Value() + " ");
            }
            Console.WriteLine();
            foreach (int i in RANGE)
            {
                Console.WriteLine("{0}\tis a Santa to {1} (distance {2})",
                                  persons[i],
                                  persons[santas[i].Value()],
                                  santa_distance[i].Value());
            }
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #18
0
    /**
     *
     * From "God plays dice"
     * "A puzzle"
     * http://gottwurfelt.wordpress.com/2012/02/22/a-puzzle/
     * And the sequel "Answer to a puzzle"
     * http://gottwurfelt.wordpress.com/2012/02/24/an-answer-to-a-puzzle/
     *
     * This problem instance was taken from the latter blog post.
     * (Problem 1)
     *
     * """
     * 8809 = 6
     * 7111 = 0
     * 2172 = 0
     * 6666 = 4
     * 1111 = 0
     * 3213 = 0
     * 7662 = 2
     * 9312 = 1
     * 0000 = 4
     * 2222 = 0
     * 3333 = 0
     * 5555 = 0
     * 8193 = 3
     * 8096 = 5
     * 7777 = 0
     * 9999 = 4
     * 7756 = 1
     * 6855 = 3
     * 9881 = 5
     * 5531 = 0
     *
     * 2581 = ?
     * """
     *
     * Note:
     * This model yields 10 solutions, since x4 is not
     * restricted in the constraints.
     * All solutions has x assigned to the correct result.
     *
     *
     * (Problem 2)
     * The problem stated in "A puzzle"
     * http://gottwurfelt.wordpress.com/2012/02/22/a-puzzle/
     * is
     * """
     * 8809 = 6
     * 7662 = 2
     * 9312 = 1
     * 8193 = 3
     * 8096 = 5
     * 7756 = 1
     * 6855 = 3
     * 9881 = 5
     *
     * 2581 = ?
     * """
     * This problem instance yields two different solutions of x,
     * one is the same (correct) as for the above problem instance,
     * and one is not.
     * This is because here x0,x1,x4 and x9 are underdefined.
     *
     *
     */
    private static void Solve(int p = 1)
    {
        Solver solver = new Solver("APuzzle");

        Console.WriteLine("\nSolving p{0}", p);

        //
        // Data
        //
        int n = 10;

        //
        // Decision variables
        //
        IntVar x0 = solver.MakeIntVar(0, n - 1, "x0");
        IntVar x1 = solver.MakeIntVar(0, n - 1, "x1");
        IntVar x2 = solver.MakeIntVar(0, n - 1, "x2");
        IntVar x3 = solver.MakeIntVar(0, n - 1, "x3");
        IntVar x4 = solver.MakeIntVar(0, n - 1, "x4");
        IntVar x5 = solver.MakeIntVar(0, n - 1, "x5");
        IntVar x6 = solver.MakeIntVar(0, n - 1, "x6");
        IntVar x7 = solver.MakeIntVar(0, n - 1, "x7");
        IntVar x8 = solver.MakeIntVar(0, n - 1, "x8");
        IntVar x9 = solver.MakeIntVar(0, n - 1, "x9");

        IntVar[] all = { x0, x1, x2, x3, x4, x5, x6, x7, x8, x9 };

        // The unknown, i.e. 2581 = x
        IntVar x = solver.MakeIntVar(0, n - 1, "x");

        //
        // Constraints
        //

        // Both problem are here shown in two
        // approaches:
        //   - using equations
        //   - using a a matrix and Sum of each row

        if (p == 1)
        {
            // Problem 1
            solver.Add(x8 + x8 + x0 + x9 == 6);
            solver.Add(x7 + x1 + x1 + x1 == 0);
            solver.Add(x2 + x1 + x7 + x2 == 0);
            solver.Add(x6 + x6 + x6 + x6 == 4);
            solver.Add(x1 + x1 + x1 + x1 == 0);
            solver.Add(x3 + x2 + x1 + x3 == 0);
            solver.Add(x7 + x6 + x6 + x2 == 2);
            solver.Add(x9 + x3 + x1 + x2 == 1);
            solver.Add(x0 + x0 + x0 + x0 == 4);
            solver.Add(x2 + x2 + x2 + x2 == 0);
            solver.Add(x3 + x3 + x3 + x3 == 0);
            solver.Add(x5 + x5 + x5 + x5 == 0);
            solver.Add(x8 + x1 + x9 + x3 == 3);
            solver.Add(x8 + x0 + x9 + x6 == 5);
            solver.Add(x7 + x7 + x7 + x7 == 0);
            solver.Add(x9 + x9 + x9 + x9 == 4);
            solver.Add(x7 + x7 + x5 + x6 == 1);
            solver.Add(x6 + x8 + x5 + x5 == 3);
            solver.Add(x9 + x8 + x8 + x1 == 5);
            solver.Add(x5 + x5 + x3 + x1 == 0);

            // The unknown
            solver.Add(x2 + x5 + x8 + x1 == x);
        }
        else if (p == 2)
        {
            // Another representation of Problem 1
            int[,] problem1 = { { 8, 8, 0, 9, 6 }, { 7, 1, 1, 1, 0 }, { 2, 1, 7, 2, 0 },
                                { 6, 6, 6, 6, 4 }, { 1, 1, 1, 1, 0 }, { 3, 2, 1, 3, 0 },
                                { 7, 6, 6, 2, 2 }, { 9, 3, 1, 2, 1 }, { 0, 0, 0, 0, 4 },
                                { 2, 2, 2, 2, 0 }, { 3, 3, 3, 3, 0 }, { 5, 5, 5, 5, 0 },
                                { 8, 1, 9, 3, 3 }, { 8, 0, 9, 6, 5 }, { 7, 7, 7, 7, 0 },
                                { 9, 9, 9, 9, 4 }, { 7, 7, 5, 6, 1 }, { 6, 8, 5, 5, 3 },
                                { 9, 8, 8, 1, 5 }, { 5, 5, 3, 1, 0 } };

            for (int i = 0; i < problem1.GetLength(0); i++)
            {
                solver.Add((from j in Enumerable.Range(0, 4) select all[problem1[i, j]]).ToArray().Sum() ==
                           problem1[i, 4]);
            }

            solver.Add(all[2] + all[5] + all[8] + all[1] == x);
        }
        else if (p == 3)
        {
            // Problem 2
            solver.Add(x8 + x8 + x0 + x9 == 6);
            solver.Add(x7 + x6 + x6 + x2 == 2);
            solver.Add(x9 + x3 + x1 + x2 == 1);
            solver.Add(x8 + x1 + x9 + x3 == 3);
            solver.Add(x8 + x0 + x9 + x6 == 5);
            solver.Add(x7 + x7 + x5 + x6 == 1);
            solver.Add(x6 + x8 + x5 + x5 == 3);
            solver.Add(x9 + x8 + x8 + x1 == 5);

            // The unknown
            solver.Add(x2 + x5 + x8 + x1 == x);
        }
        else
        {
            // Another representation of Problem 2
            int[,] problem2 = { { 8, 8, 0, 9, 6 }, { 7, 6, 6, 2, 2 }, { 9, 3, 1, 2, 1 },
                                { 8, 1, 9, 3, 3 }, { 8, 0, 9, 6, 5 }, { 7, 7, 5, 6, 1 },
                                { 6, 8, 5, 5, 3 }, { 9, 8, 8, 1, 5 } };

            for (int i = 0; i < problem2.GetLength(0); i++)
            {
                solver.Add((from j in Enumerable.Range(0, 4) select all[problem2[i, j]]).ToArray().Sum() ==
                           problem2[i, 4]);
            }

            solver.Add(all[2] + all[5] + all[8] + all[1] == x);
        }

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(all, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT);

        solver.NewSearch(db);
        while (solver.NextSolution())
        {
            Console.Write("x: {0}  x0..x9: ", x.Value());
            for (int i = 0; i < n; i++)
            {
                Console.Write(all[i].Value() + " ");
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #19
0
    /**
     *
     * Ski assignment in Google CP Solver.
     *
     * From   Jeffrey Lee Hellrung, Jr.:
     * PIC 60, Fall 2008 Final Review, December 12, 2008
     * http://www.math.ucla.edu/~jhellrun/course_files/Fall%25202008/PIC%252060%2520-%2520Data%2520Structures%2520and%2520Algorithms/final_review.pdf
     * """
     * 5. Ski Optimization! Your job at Snapple is pleasant but in the winter
     * you've decided to become a ski bum. You've hooked up with the Mount
     * Baldy Ski Resort. They'll let you ski all winter for free in exchange
     * for helping their ski rental shop with an algorithm to assign skis to
     * skiers. Ideally, each skier should obtain a pair of skis whose height
     * matches his or her own height exactly. Unfortunately, this is generally
     * not possible. We define the disparity between a skier and his or her
     * skis to be the absolute value of the difference between the height of
     * the skier and the pair of skis. Our objective is to find an assignment
     * of skis to skiers that minimizes the sum of the disparities.
     * ...
     * Illustrate your algorithm by explicitly filling out the A[i, j] table
     * for the following sample data:
     *  - Ski heights  : 1, 2, 5, 7, 13, 21.
     *  - Skier heights: 3, 4, 7, 11, 18.
     * """
     *
     * Also see http://www.hakank.org/or-tools/ski_assignment.py
     *
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("SkiAssignment");

        //
        // Data
        //
        int num_skis   = 6;
        int num_skiers = 5;

        int[] ski_heights   = { 1, 2, 5, 7, 13, 21 };
        int[] skier_heights = { 3, 4, 7, 11, 18 };

        //
        // Decision variables
        //
        IntVar[] x = solver.MakeIntVarArray(num_skiers, 0, num_skis - 1, "x");

        //
        // Constraints
        //
        solver.Add(x.AllDifferent());

        IntVar[] z_tmp = new IntVar[num_skiers];
        for (int i = 0; i < num_skiers; i++)
        {
            z_tmp[i] = (ski_heights.Element(x[i]) - skier_heights[i]).Abs().Var();
        }

        //    IntVar z = solver.MakeIntVar(0, ski_heights.Sum(), "z");
        //    solver.Add(z_tmp.Sum() == z);
        // The direct cast from IntExpr to IntVar is potentially faster than
        // the above code.
        IntVar z = z_tmp.Sum().VarWithName("z");

        //
        // Objective
        //
        OptimizeVar obj = z.Minimize(1);

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.INT_VALUE_DEFAULT);

        solver.NewSearch(db, obj);

        while (solver.NextSolution())
        {
            Console.Write("z: {0} x: ", z.Value());
            for (int i = 0; i < num_skiers; i++)
            {
                Console.Write(x[i].Value() + " ");
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #20
0
    /**
     *
     * Crypto problem.
     *
     * This is the standard benchmark "crypto" problem.
     *
     * From GLPK:s model cryto.mod.
     *
     * """
     * This problem comes from the newsgroup rec.puzzle.
     * The numbers from 1 to 26 are assigned to the letters of the alphabet.
     * The numbers beside each word are the total of the values assigned to
     * the letters in the word (e.g. for LYRE: L, Y, R, E might be to equal
     * 5, 9, 20 and 13, or any other combination that add up to 47).
     * Find the value of each letter under the equations:
     *
     * BALLET  45     GLEE  66     POLKA      59     SONG     61
     * CELLO   43     JAZZ  58     QUARTET    50     SOPRANO  82
     * CONCERT 74     LYRE  47     SAXOPHONE 134     THEME    72
     * FLUTE   30     OBOE  53     SCALE      51     VIOLIN  100
     * FUGUE   50     OPERA 65     SOLO       37     WALTZ    34
     *
     * Solution:
     * A, B,C, D, E,F, G, H, I, J, K,L,M, N, O, P,Q, R, S,T,U, V,W, X, Y, Z
     * 5,13,9,16,20,4,24,21,25,17,23,2,8,12,10,19,7,11,15,3,1,26,6,22,14,18
     *
     * Reference:
     * Koalog Constraint Solver <http://www.koalog.com/php/jcs.php>,
     * Simple problems, the crypto-arithmetic puzzle ALPHACIPHER.
     * """
     *
     * Also see http://hakank.org/or-tools/crypto.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("Crypto");

        int num_letters = 26;

        int BALLET    = 45;
        int CELLO     = 43;
        int CONCERT   = 74;
        int FLUTE     = 30;
        int FUGUE     = 50;
        int GLEE      = 66;
        int JAZZ      = 58;
        int LYRE      = 47;
        int OBOE      = 53;
        int OPERA     = 65;
        int POLKA     = 59;
        int QUARTET   = 50;
        int SAXOPHONE = 134;
        int SCALE     = 51;
        int SOLO      = 37;
        int SONG      = 61;
        int SOPRANO   = 82;
        int THEME     = 72;
        int VIOLIN    = 100;
        int WALTZ     = 34;


        //
        // Decision variables
        //
        IntVar[] LD = solver.MakeIntVarArray(num_letters, 1, num_letters, "LD");

        // Note D is not used in the constraints below
        IntVar A = LD[0]; IntVar B = LD[1]; IntVar C = LD[2]; // IntVar D =  LD[3];
        IntVar E = LD[4]; IntVar F = LD[5]; IntVar G = LD[6]; IntVar H = LD[7];
        IntVar I = LD[8]; IntVar J = LD[9]; IntVar K = LD[10]; IntVar L = LD[11];
        IntVar M = LD[12]; IntVar N = LD[13]; IntVar O = LD[14]; IntVar P = LD[15];
        IntVar Q = LD[16]; IntVar R = LD[17]; IntVar S = LD[18]; IntVar T = LD[19];
        IntVar U = LD[20]; IntVar V = LD[21]; IntVar W = LD[22]; IntVar X = LD[23];
        IntVar Y = LD[24]; IntVar Z = LD[25];

        //
        // Constraints
        //
        solver.Add(LD.AllDifferent());
        solver.Add(B + A + L + L + E + T == BALLET);
        solver.Add(C + E + L + L + O == CELLO);
        solver.Add(C + O + N + C + E + R + T == CONCERT);
        solver.Add(F + L + U + T + E == FLUTE);
        solver.Add(F + U + G + U + E == FUGUE);
        solver.Add(G + L + E + E == GLEE);
        solver.Add(J + A + Z + Z == JAZZ);
        solver.Add(L + Y + R + E == LYRE);
        solver.Add(O + B + O + E == OBOE);
        solver.Add(O + P + E + R + A == OPERA);
        solver.Add(P + O + L + K + A == POLKA);
        solver.Add(Q + U + A + R + T + E + T == QUARTET);
        solver.Add(S + A + X + O + P + H + O + N + E == SAXOPHONE);
        solver.Add(S + C + A + L + E == SCALE);
        solver.Add(S + O + L + O == SOLO);
        solver.Add(S + O + N + G == SONG);
        solver.Add(S + O + P + R + A + N + O == SOPRANO);
        solver.Add(T + H + E + M + E == THEME);
        solver.Add(V + I + O + L + I + N == VIOLIN);
        solver.Add(W + A + L + T + Z == WALTZ);


        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(LD,
                                              Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
                                              Solver.ASSIGN_CENTER_VALUE);

        solver.NewSearch(db);

        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        while (solver.NextSolution())
        {
            for (int i = 0; i < num_letters; i++)
            {
                Console.WriteLine("{0}: {1,2}", str[i], LD[i].Value());
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nWallTime: " + solver.WallTime() + "ms ");
        Console.WriteLine("Failures: " + solver.Failures());
        Console.WriteLine("Branches: " + solver.Branches());

        solver.EndSearch();
    }
Beispiel #21
0
    /**
     *
     *
     * Organizing a day.
     *
     * Simple scheduling problem.
     *
     * Problem formulation from ECLiPSe:
     * Slides on (Finite Domain) Constraint Logic Programming, page 38f
     * http://eclipse-clp.org/reports/eclipse.ppt
     *
     *
     * Also see http://www.hakank.org/google_or_tools/organize_day.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("OrganizeDayIntervals");


        int n = 4;


        int work = 0;
        int mail = 1;
        int shop = 2;
        int bank = 3;
        // the valid times of the day
        int begin = 9;
        int end   = 17;

        // tasks
        int[] tasks = { work, mail, shop, bank };
        // durations
        int[] durations = { 4, 1, 2, 1 };
        // Arrays for interval variables.
        int[] starts_max = { begin, begin, begin, begin };
        int[] ends_max   = { end - 4, end - 1, end - 2, end - 1 };

        // task [i,0] must be finished before task [i,1]
        int[,] before_tasks =
        {
            { bank, shop },
            { mail, work }
        };



        //
        // Decision variables
        //
        IntervalVar[] intervals =
            solver.MakeFixedDurationIntervalVarArray(n,
                                                     starts_max,
                                                     ends_max,
                                                     durations,
                                                     false,
                                                     "task");
        //
        // Constraints
        //
        DisjunctiveConstraint disjunctive = intervals.Disjunctive("Sequence");

        solver.Add(disjunctive);

        // specific constraints
        for (int t = 0; t < before_tasks.GetLength(0); t++)
        {
            int before = before_tasks[t, 0];
            int after  = before_tasks[t, 1];
            solver.Add(intervals[after].StartsAfterEnd(intervals[before]));
        }

        solver.Add(intervals[work].StartsAfter(11));

        //
        // Search
        //
        SequenceVar var = disjunctive.SequenceVar();

        SequenceVar[]   seq_array = new SequenceVar[] { var };
        DecisionBuilder db        = solver.MakePhase(seq_array, Solver.SEQUENCE_DEFAULT);

        solver.NewSearch(db);

        while (solver.NextSolution())
        {
            foreach (int t in tasks)
            {
                Console.WriteLine(intervals[t].ToString());
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #22
0
    /**
     *
     * KenKen puzzle.
     *
     * http://en.wikipedia.org/wiki/KenKen
     * """
     * KenKen or KEN-KEN is a style of arithmetic and logical puzzle sharing
     * several characteristics with sudoku. The name comes from Japanese and
     * is translated as 'square wisdom' or 'cleverness squared'.
     * ...
     * The objective is to fill the grid in with the digits 1 through 6 such that:
     *
     * * Each row contains exactly one of each digit
     * * Each column contains exactly one of each digit
     * * Each bold-outlined group of cells is a cage containing digits which
     *   achieve the specified result using the specified mathematical operation:
     *     addition (+),
     *     subtraction (-),
     *     multiplication (x),
     *     and division (/).
     *    (Unlike in Killer sudoku, digits may repeat within a group.)
     *
     * ...
     * More complex KenKen problems are formed using the principles described
     * above but omitting the symbols +, -, x and /, thus leaving them as
     * yet another unknown to be determined.
     * """
     *
     * The solution is:
     *
     *    5 6 3 4 1 2
     *    6 1 4 5 2 3
     *    4 5 2 3 6 1
     *    3 4 1 2 5 6
     *    2 3 6 1 4 5
     *    1 2 5 6 3 4
     *
     *
     * Also see http://www.hakank.org/or-tools/kenken2.py
     * though this C# model has another representation of
     * the problem instance.
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("KenKen2");

        // size of matrix
        int n = 6;
        IEnumerable <int> RANGE = Enumerable.Range(0, n);

        // For a better view of the problem, see
        //  http://en.wikipedia.org/wiki/File:KenKenProblem.svg

        // hints
        //  sum, the hints
        // Note: this is 1-based
        int[][] problem = { new int[] {  11, 1, 1, 2, 1 },
                            new int[] {   2, 1, 2, 1, 3 },
                            new int[] {  20, 1, 4, 2, 4 },
                            new int[] {   6, 1, 5, 1,6, 2, 6, 3, 6 },
                            new int[] {   3, 2, 2, 2, 3 },
                            new int[] {   3, 2, 5, 3, 5 },
                            new int[] { 240, 3, 1, 3,2, 4, 1, 4, 2 },
                            new int[] {   6, 3, 3, 3, 4 },
                            new int[] {   6, 4, 3, 5, 3 },
                            new int[] {   7, 4, 4, 5,4, 5, 5 },
                            new int[] {  30, 4, 5, 4, 6 },
                            new int[] {   6, 5, 1, 5, 2 },
                            new int[] {   9, 5, 6, 6, 6 },
                            new int[] {   8, 6, 1, 6,2, 6, 3 },
                            new int[] {   2, 6, 4, 6, 5 } };

        int num_p = problem.GetLength(0); // Number of segments

        //
        // Decision variables
        //
        IntVar[,] x = solver.MakeIntVarMatrix(n, n, 1, n, "x");
        IntVar[] x_flat = x.Flatten();

        //
        // Constraints
        //

        //
        //  alldifferent rows and columns
        foreach (int i in RANGE)
        {
            // rows
            solver.Add((from j in RANGE select x[i, j]).ToArray().AllDifferent());

            // cols
            solver.Add((from j in RANGE select x[j, i]).ToArray().AllDifferent());
        }

        // Calculate the segments
        for (int i = 0; i < num_p; i++)
        {
            int[] segment = problem[i];

            // Remove the sum from the segment
            int   len = segment.Length - 1;
            int[] s2  = new int[len];
            Array.Copy(segment, 1, s2, 0, len);

            // sum this segment
            calc(solver, s2, x, segment[0]);
        }

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(x_flat, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT);

        solver.NewSearch(db);

        while (solver.NextSolution())
        {
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    Console.Write(x[i, j].Value() + " ");
                }
                Console.WriteLine();
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
    /**
     *
     * Solves a set covering deployment problem.
     * See  See http://www.hakank.org/or-tools/set_covering_deployment.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("SetCoveringDeployment");

        //
        // data
        //

        // From http://mathworld.wolfram.com/SetCoveringDeployment.html
        string[] countries = { "Alexandria",
                               "Asia Minor",
                               "Britain",
                               "Byzantium",
                               "Gaul",
                               "Iberia",
                               "Rome",
                               "Tunis" };

        int n = countries.Length;

        // the incidence matrix (neighbours)
        int[,] mat = { { 0, 1, 0, 1, 0, 0, 1, 1 },
                       { 1, 0, 0, 1, 0, 0, 0, 0 },
                       { 0, 0, 0, 0, 1, 1, 0, 0 },
                       { 1, 1, 0, 0, 0, 0, 1, 0 },
                       { 0, 0, 1, 0, 0, 1, 1, 0 },
                       { 0, 0, 1, 0, 1, 0, 1, 1 },
                       { 1, 0, 0, 1, 1, 1, 0, 1 },
                       { 1, 0, 0, 0, 0, 1, 1, 0 } };

        //
        // Decision variables
        //

        // First army
        IntVar[] x = solver.MakeIntVarArray(n, 0, 1, "x");

        // Second (reserve) army
        IntVar[] y = solver.MakeIntVarArray(n, 0, 1, "y");

        // total number of armies
        IntVar num_armies = (x.Sum() + y.Sum()).Var();


        //
        // Constraints
        //

        //
        //  Constraint 1: There is always an army in a city
        //                (+ maybe a backup)
        //                Or rather: Is there a backup, there
        //                must be an an army
        //
        for (int i = 0; i < n; i++)
        {
            solver.Add(x[i] >= y[i]);
        }

        //
        // Constraint 2: There should always be an backup
        //               army near every city
        //
        for (int i = 0; i < n; i++)
        {
            IntVar[] count_neighbours = (
                from j in Enumerable.Range(0, n)
                where mat[i, j] == 1
                select(y[j])).ToArray();

            solver.Add((x[i] + count_neighbours.Sum()) >= 1);
        }


        //
        // objective
        //
        OptimizeVar objective = num_armies.Minimize(1);


        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(x,
                                              Solver.INT_VAR_DEFAULT,
                                              Solver.INT_VALUE_DEFAULT);

        solver.NewSearch(db, objective);

        while (solver.NextSolution())
        {
            Console.WriteLine("num_armies: " + num_armies.Value());
            for (int i = 0; i < n; i++)
            {
                if (x[i].Value() == 1)
                {
                    Console.Write("Army: " + countries[i] + " ");
                }

                if (y[i].Value() == 1)
                {
                    Console.WriteLine(" Reverse army: " + countries[i]);
                }
            }
            Console.WriteLine("\n");
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #24
0
    /**
     *
     * Solves a set covering problem.
     * See  See http://www.hakank.org/or-tools/set_covering3.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("SetCovering3");

        //
        // data
        //

        // Set covering problem from
        // Katta G. Murty: 'Optimization Models for Decision Making',
        // page 302f
        // http://ioe.engin.umich.edu/people/fac/books/murty/opti_model/junior-7.pdf
        int num_groups   = 6;
        int num_senators = 10;

        // which group does a senator belong to?
        int[,] belongs = { { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 },   // 1 southern
                           { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 },   // 2 northern
                           { 0, 1, 1, 0, 0, 0, 0, 1, 1, 1 },   // 3 liberals
                           { 1, 0, 0, 0, 1, 1, 1, 0, 0, 0 },   // 4 conservative
                           { 0, 0, 1, 1, 1, 1, 1, 0, 1, 0 },   // 5 democrats
                           { 1, 1, 0, 0, 0, 0, 0, 1, 0, 1 } }; // 6 republicans

        //
        // Decision variables
        //
        IntVar[] x = solver.MakeIntVarArray(num_senators, 0, 1, "x");
        // number of assigned senators, to be minimized
        IntVar z = x.Sum().Var();

        //
        // Constraints
        //

        // ensure that each group is covered by at least
        // one senator
        for (int i = 0; i < num_groups; i++)
        {
            IntVar[] b = new IntVar[num_senators];
            for (int j = 0; j < num_senators; j++)
            {
                b[j] = (x[j] * belongs[i, j]).Var();
            }
            solver.Add(b.Sum() >= 1);
        }

        //
        // objective
        //
        OptimizeVar objective = z.Minimize(1);

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT);

        solver.NewSearch(db, objective);

        while (solver.NextSolution())
        {
            Console.WriteLine("z: " + z.Value());
            Console.Write("x: ");
            for (int j = 0; j < num_senators; j++)
            {
                Console.Write(x[j].Value() + " ");
            }
            Console.WriteLine();

            // More details
            for (int j = 0; j < num_senators; j++)
            {
                if (x[j].Value() == 1)
                {
                    Console.Write("Senator " + (1 + j) + " belongs to these groups: ");
                    for (int i = 0; i < num_groups; i++)
                    {
                        if (belongs[i, j] == 1)
                        {
                            Console.Write((1 + i) + " ");
                        }
                    }
                    Console.WriteLine();
                }
            }
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
    /**
     *
     * Combinatorial auction.
     *
     * This is a more general model for the combinatorial example
     * in the Numberjack Tutorial, pages 9 and 24 (slides  19/175 and
     * 51/175).
     *
     * See http://www.hakank.org/or-tools/combinatorial_auction2.py
     *
     * The original and more talkative model is here:
     * http://www.hakank.org/numberjack/combinatorial_auction.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("CombinatorialAuction2");

        //
        // Data
        //
        int n = 5;

        // the items for each bid
        int[][] items =
        {
            new int[] { 0, 1 }, // A,B
            new int[] { 0, 2 }, // A, C
            new int[] { 1, 3 }, // B,D
            new int[] { 1,2, 3 }, // B,C,D
            new int[] { 0 }     // A
        };

        int[] bid_ids    = { 0, 1, 2, 3 };
        int[] bid_amount = { 10, 20, 30, 40, 14 };

        //
        // Decision variables
        //
        IntVar[] x = solver.MakeIntVarArray(n, 0, 1, "x");
        IntVar   z = x.ScalProd(bid_amount).VarWithName("z");

        //
        // Constraints
        //

        foreach (int bid_id in bid_ids)
        {
            var tmp2 = (from item in Enumerable.Range(0, n)
                        from i in Enumerable.Range(0, items[item].Length)
                        where items [item]
                        [i] == bid_id select x[item]);

            solver.Add(tmp2.ToArray().Sum() <= 1);
        }

        //
        // Objective
        //
        OptimizeVar obj = z.Maximize(1);

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);

        solver.NewSearch(db, obj);

        while (solver.NextSolution())
        {
            Console.Write("z: {0,2} x: ", z.Value());
            for (int i = 0; i < n; i++)
            {
                Console.Write(x[i].Value() + " ");
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #26
0
    /**
     *
     * Discrete tomography
     *
     * Problem from http://eclipse.crosscoreop.com/examples/tomo.ecl.txt
     * """
     * This is a little 'tomography' problem, taken from an old issue
     * of Scientific American.
     *
     * A matrix which contains zeroes and ones gets "x-rayed" vertically and
     * horizontally, giving the total number of ones in each row and column.
     * The problem is to reconstruct the contents of the matrix from this
     * information. Sample run:
     *
     * ?- go.
     *    0 0 7 1 6 3 4 5 2 7 0 0
     * 0
     * 0
     * 8      * * * * * * * *
     * 2      *             *
     * 6      *   * * * *   *
     * 4      *   *     *   *
     * 5      *   *   * *   *
     * 3      *   *         *
     * 7      *   * * * * * *
     * 0
     * 0
     *
     * Eclipse solution by Joachim Schimpf, IC-Parc
     * """
     *
     * See  http://www.hakank.org/or-tools/discrete_tomography.py
     *
     */
    private static void Solve(int[] rowsums, int[] colsums)
    {
        Solver solver = new Solver("DiscreteTomography");

        //
        // Data
        //
        int r = rowsums.Length;
        int c = colsums.Length;

        Console.Write("rowsums: ");
        for (int i = 0; i < r; i++)
        {
            Console.Write(rowsums[i] + " ");
        }
        Console.Write("\ncolsums: ");
        for (int j = 0; j < c; j++)
        {
            Console.Write(colsums[j] + " ");
        }
        Console.WriteLine("\n");


        //
        // Decision variables
        //
        IntVar[,] x = solver.MakeIntVarMatrix(r, c, 0, 1, "x");
        IntVar[] x_flat = x.Flatten();


        //
        // Constraints
        //

        // row sums
        for (int i = 0; i < r; i++)
        {
            var tmp = from j in Enumerable.Range(0, c) select x[i, j];
            solver.Add(tmp.ToArray().Sum() == rowsums[i]);
        }

        // cols sums
        for (int j = 0; j < c; j++)
        {
            var tmp = from i in Enumerable.Range(0, r) select x[i, j];
            solver.Add(tmp.ToArray().Sum() == colsums[j]);
        }


        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(x_flat,
                                              Solver.CHOOSE_FIRST_UNBOUND,
                                              Solver.ASSIGN_MIN_VALUE);


        solver.NewSearch(db);

        while (solver.NextSolution())
        {
            for (int i = 0; i < r; i++)
            {
                for (int j = 0; j < c; j++)
                {
                    Console.Write("{0} ", x[i, j].Value() == 1 ? "#" : ".");
                }
                Console.WriteLine();
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
    /**
     *
     * Post office problem.
     *
     * Problem statement:
     * http://www-128.ibm.com/developerworks/linux/library/l-glpk2/
     *
     * From Winston 'Operations Research: Applications and Algorithms':
     * """
     * A post office requires a different number of full-time employees working
     * on different days of the week [summarized below]. Union rules state that
     * each full-time employee must work for 5 consecutive days and then receive
     * two days off. For example, an employee who works on Monday to Friday
     * must be off on Saturday and Sunday. The post office wants to meet its
     * daily requirements using only full-time employees. Minimize the number
     * of employees that must be hired.
     *
     * To summarize the important information about the problem:
     *
     * Every full-time worker works for 5 consecutive days and takes 2 days off
     * - Day 1 (Monday): 17 workers needed
     * - Day 2 : 13 workers needed
     * - Day 3 : 15 workers needed
     * - Day 4 : 19 workers needed
     * - Day 5 : 14 workers needed
     * - Day 6 : 16 workers needed
     * - Day 7 (Sunday) : 11 workers needed
     *
     * The post office needs to minimize the number of employees it needs
     * to hire to meet its demand.
     * """
     *
     * Also see http://www.hakank.org/or-tools/post_office_problem2.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("PostOfficeProblem2");

        //
        // Data
        //

        // days 0..6, monday 0
        int n = 7;

        int[] need = { 17, 13, 15, 19, 14, 16, 11 };

        // Total cost for the 5 day schedule.
        // Base cost per day is 100.
        // Working saturday is 100 extra
        // Working sunday is 200 extra.
        int[] cost = { 500, 600, 800, 800, 800, 800, 700 };

        //
        // Decision variables
        //

        // No. of workers starting at day i
        IntVar[] x = solver.MakeIntVarArray(n, 0, 100, "x");

        IntVar total_cost  = x.ScalProd(cost).Var();
        IntVar num_workers = x.Sum().Var();

        //
        // Constraints
        //
        for (int i = 0; i < n; i++)
        {
            IntVar s = (from j in Enumerable.Range(0, n) where j != (i + 5) % n &&
                        j != (i + 6) % n select x[j])
                       .ToArray()
                       .Sum()
                       .Var();
            solver.Add(s >= need[i]);
        }

        // Add a limit for the cost
        solver.Add(total_cost <= 20000);

        //

        // objective
        //
        //
        OptimizeVar obj = total_cost.Minimize(100);

        //
        // Search
        //
        DecisionBuilder db =
            solver.MakePhase(x, Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, Solver.ASSIGN_MIN_VALUE);

        solver.NewSearch(db, obj);

        while (solver.NextSolution())
        {
            Console.WriteLine("num_workers: {0}", num_workers.Value());
            Console.WriteLine("total_cost: {0}", total_cost.Value());
            Console.Write("x: ");
            for (int i = 0; i < n; i++)
            {
                Console.Write(x[i].Value() + " ");
            }
            Console.WriteLine("\n");
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #28
0
    /**
     *
     * Assignment problem
     *
     * From Wayne Winston "Operations Research",
     * Assignment Problems, page 393f
     * (generalized version with added test column)
     *
     * See  See http://www.hakank.org/or-tools/assignment.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("Assignment");

        //
        // data
        //

        // Problem instance
        // hakank: I added the fifth column to make it more
        //         interesting
        int rows = 4;
        int cols = 5;

        int[,] cost =
        {
            { 14,  5, 8,  7, 15 },
            {  2, 12, 6,  5,  3 },
            {  7,  8, 3,  9,  7 },
            {  2,  4, 6, 10,  1 }
        };


        //
        // Decision variables
        //
        IntVar[,] x = solver.MakeBoolVarMatrix(rows, cols, "x");
        IntVar[] x_flat = x.Flatten();

        //
        // Constraints
        //

        // Exacly one assignment per row (task),
        // i.e. all rows must be assigned with one worker
        for (int i = 0; i < rows; i++)
        {
            solver.Add((from j in Enumerable.Range(0, cols)
                        select x[i, j]).ToArray().Sum() == 1);
        }

        // At most one assignments per column (worker)
        for (int j = 0; j < cols; j++)
        {
            solver.Add((from i in Enumerable.Range(0, rows)
                        select x[i, j]).ToArray().Sum() <= 1);
        }

        // Total cost
        IntVar total_cost = (from i in Enumerable.Range(0, rows)
                             from j in Enumerable.Range(0, cols)
                             select(cost[i, j] * x[i, j])).ToArray().Sum().Var();

        //
        // objective
        //
        OptimizeVar objective = total_cost.Minimize(1);


        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(x_flat,
                                              Solver.INT_VAR_DEFAULT,
                                              Solver.INT_VALUE_DEFAULT);

        solver.NewSearch(db, objective);

        while (solver.NextSolution())
        {
            Console.WriteLine("total_cost: {0}", total_cost.Value());
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    Console.Write(x[i, j].Value() + " ");
                }
                Console.WriteLine();
            }
            Console.WriteLine();
            Console.WriteLine("Assignments:");
            for (int i = 0; i < rows; i++)
            {
                Console.Write("Task " + i);
                for (int j = 0; j < cols; j++)
                {
                    if (x[i, j].Value() == 1)
                    {
                        Console.WriteLine(" is done by " + j);
                    }
                }
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #29
0
    /**
     *
     * Hidato puzzle in Google CP Solver.
     *
     * http://www.hidato.com/
     * """
     * Puzzles start semi-filled with numbered tiles.
     * The first and last numbers are circled.
     * Connect the numbers together to win. Consecutive
     * number must touch horizontally, vertically, or
     * diagonally.
     * """
     *
     * This is a port of the Python model hidato_table.py
     * made by Laurent Perron (using AllowedAssignments),
     * based on my (much slower) model hidato.py.
     *
     */
    private static void Solve(int model = 1)
    {
        Solver solver = new Solver("HidatoTable");

        //
        // models, a 0 indicates an open cell which number is not yet known.
        //

        int[,] puzzle = null;
        if (model == 1)
        {
            // Simple problem

            // Solution 1:
            // 6  7  9
            // 5  2  8
            // 1  4  3
            int[,] puzzle1 = { { 6, 0, 9 }, { 0, 2, 8 }, { 1, 0, 0 } };
            puzzle         = puzzle1;
        }
        else if (model == 2)
        {
            int[,] puzzle2 = { {  0, 44, 41,  0, 0,  0, 0 }, { 0, 43,  0, 28, 29, 0,  0 },
                               {  0,  1,  0,  0, 0, 33, 0 }, { 0,  2, 25,  4, 34, 0, 36 },
                               { 49, 16,  0, 23, 0,  0, 0 }, { 0, 19,  0,  0, 12, 7,  0 },
                               {  0,  0,  0, 14, 0,  0, 0 } };
            puzzle = puzzle2;
        }
        else if (model == 3)
        {
            // Problems from the book:
            // Gyora Bededek: "Hidato: 2000 Pure Logic Puzzles"
            // Problem 1 (Practice)
            int[,] puzzle3 = { {  0,  0, 20,  0,  0 },
                               {  0,  0,  0, 16, 18 },
                               { 22,  0, 15,  0,  0 },
                               { 23,  0,  1, 14, 11 },
                               {  0, 25,  0,  0, 12 } };
            puzzle = puzzle3;
        }
        else if (model == 4)
        {
            // problem 2 (Practice)
            int[,] puzzle4 = { { 0,  0,  0, 0, 14 },
                               { 0, 18, 12, 0,  0 },
                               { 0,  0, 17, 4,  5 },
                               { 0,  0,  7, 0,  0 },
                               { 9,  8, 25, 1,  0 } };
            puzzle = puzzle4;
        }
        else if (model == 5)
        {
            // problem 3 (Beginner)
            int[,] puzzle5 = { { 0, 26, 0, 0,  0, 18 }, { 0, 0, 27, 0, 0, 19 }, { 31, 23, 0,  0, 14, 0 },
                               { 0, 33, 8, 0, 15,  1 }, { 0, 0,  0, 5, 0,  0 }, { 35, 36, 0, 10,  0, 0 } };
            puzzle = puzzle5;
        }
        else if (model == 6)
        {
            // Problem 15 (Intermediate)
            int[,] puzzle6 = { { 64, 0, 0,  0,  0, 0,  0,  0 }, {  1, 63,  0, 59, 15, 57, 53,  0 },
                               {  0, 4, 0, 14,  0, 0,  0,  0 }, {  3,  0, 11,  0, 20, 19,  0, 50 },
                               {  0, 0, 0,  0, 22, 0, 48, 40 }, {  9,  0,  0, 32, 23,  0,  0, 41 },
                               { 27, 0, 0,  0, 36, 0, 46,  0 }, { 28, 30,  0, 35,  0,  0,  0,  0 } };
            puzzle = puzzle6;
        }

        int r = puzzle.GetLength(0);
        int c = puzzle.GetLength(1);

        Console.WriteLine();
        Console.WriteLine("----- Solving problem {0} -----", model);
        Console.WriteLine();

        PrintMatrix(puzzle);

        //
        // Decision variables
        //
        IntVar[] positions = solver.MakeIntVarArray(r * c, 0, r * c - 1, "p");

        //
        // Constraints
        //
        solver.Add(positions.AllDifferent());

        //
        // Fill in the clues
        //
        for (int i = 0; i < r; i++)
        {
            for (int j = 0; j < c; j++)
            {
                if (puzzle[i, j] > 0)
                {
                    solver.Add(positions[puzzle[i, j] - 1] == i * c + j);
                }
            }
        }

        // Consecutive numbers much touch each other in the grid.
        // We use an allowed assignment constraint to model it.
        IntTupleSet close_tuples = BuildPairs(r, c);

        for (int k = 1; k < r * c - 1; k++)
        {
            IntVar[] tmp = new IntVar[] { positions[k], positions[k + 1] };
            solver.Add(tmp.AllowedAssignments(close_tuples));
        }

        //
        // Search
        //
        DecisionBuilder db =
            solver.MakePhase(positions, Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, Solver.ASSIGN_MIN_VALUE);

        solver.NewSearch(db);

        int num_solution = 0;

        while (solver.NextSolution())
        {
            num_solution++;
            PrintOneSolution(positions, r, c, num_solution);
        }

        Console.WriteLine("\nSolutions: " + solver.Solutions());
        Console.WriteLine("WallTime: " + solver.WallTime() + "ms ");
        Console.WriteLine("Failures: " + solver.Failures());
        Console.WriteLine("Branches: " + solver.Branches());

        solver.EndSearch();
    }
    /**
     *
     * Solves the Quasigroup Completion problem.
     * See http://www.hakank.org/or-tools/quasigroup_completion.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("QuasigroupCompletion");

        //
        // data
        //
        Console.WriteLine("Problem:");
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                Console.Write(problem[i, j] + " ");
            }
            Console.WriteLine();
        }
        Console.WriteLine();


        //
        // Decision variables
        //
        IntVar[,] x = solver.MakeIntVarMatrix(n, n, 1, n, "x");
        IntVar[] x_flat = x.Flatten();

        //
        // Constraints
        //
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (problem[i, j] > X)
                {
                    solver.Add(x[i, j] == problem[i, j]);
                }
            }
        }

        //
        // rows and columns must be different
        //

        // rows
        for (int i = 0; i < n; i++)
        {
            IntVar[] row = new IntVar[n];
            for (int j = 0; j < n; j++)
            {
                row[j] = x[i, j];
            }
            solver.Add(row.AllDifferent());
        }

        // columns
        for (int j = 0; j < n; j++)
        {
            IntVar[] col = new IntVar[n];
            for (int i = 0; i < n; i++)
            {
                col[i] = x[i, j];
            }
            solver.Add(col.AllDifferent());
        }


        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(x_flat,
                                              Solver.INT_VAR_SIMPLE,
                                              Solver.ASSIGN_MIN_VALUE);

        solver.NewSearch(db);

        int sol = 0;

        while (solver.NextSolution())
        {
            sol++;
            Console.WriteLine("Solution #{0} ", sol + " ");
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    Console.Write("{0} ", x[i, j].Value());
                }
                Console.WriteLine();
            }

            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
Beispiel #31
0
 public void NewSearch(DecisionBuilder db) {
   pinned_decision_builder_ = db;
   pinned_search_monitors_.Clear();
   NewSearchAux(db);
 }
Beispiel #32
0
    /**
     *
     * Lectures problem in Google CP Solver.
     *
     * Biggs: Discrete Mathematics (2nd ed), page 187.
     * """
     * Suppose we wish to schedule six one-hour lectures, v1, v2, v3, v4, v5, v6.
     * Among the the potential audience there are people who wish to hear both
     *
     * - v1 and v2
     * - v1 and v4
     * - v3 and v5
     * - v2 and v6
     * - v4 and v5
     * - v5 and v6
     * - v1 and v6
     *
     * How many hours are necessary in order that the lectures can be given
     * without clashes?
     * """
     *
     * Note: This can be seen as a coloring problem.
     *
     * Also see http://www.hakank.org/or-tools/lectures.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("Lectures");

        //
        // The schedule requirements:
        // lecture a cannot be held at the same time as b
        // Note: 1-based (compensated in the constraints).
        int[,] g = { { 1, 2 }, { 1, 4 }, { 3, 5 }, { 2, 6 }, { 4, 5 }, { 5, 6 }, { 1, 6 } };

        // number of nodes
        int n = 6;

        // number of edges
        int edges = g.GetLength(0);

        //
        // Decision variables
        //
        //
        // declare variables
        //
        IntVar[] v = solver.MakeIntVarArray(n, 0, n - 1, "v");

        // Maximum color (hour) to minimize.
        // Note: since C# is 0-based, the
        // number of colors is max_c+1.
        IntVar max_c = v.Max().VarWithName("max_c");

        //
        // Constraints
        //

        // Ensure that there are no clashes
        // also, adjust to 0-base.
        for (int i = 0; i < edges; i++)
        {
            solver.Add(v[g[i, 0] - 1] != v[g[i, 1] - 1]);
        }

        // Symmetry breaking:
        // - v0 has the color 0,
        // - v1 has either color 0 or 1
        solver.Add(v[0] == 0);
        solver.Add(v[1] <= 1);

        //
        // Objective
        //
        OptimizeVar obj = max_c.Minimize(1);

        //
        // Search
        //
        DecisionBuilder db =
            solver.MakePhase(v, Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, Solver.ASSIGN_MIN_VALUE);

        solver.NewSearch(db, obj);

        while (solver.NextSolution())
        {
            Console.WriteLine("\nmax hours: {0}", max_c.Value() + 1);
            Console.WriteLine(
                "v: " +
                String.Join(" ", (from i in Enumerable.Range(0, n) select v[i].Value()).ToArray()));
            for (int i = 0; i < n; i++)
            {
                Console.WriteLine("Lecture {0} at {1}h", i, v[i].Value());
            }
            Console.WriteLine("\n");
        }

        Console.WriteLine("\nSolutions: " + solver.Solutions());
        Console.WriteLine("WallTime: " + solver.WallTime() + "ms ");
        Console.WriteLine("Failures: " + solver.Failures());
        Console.WriteLine("Branches: " + solver.Branches());

        solver.EndSearch();
    }
Beispiel #33
0
 public void NewSearch(DecisionBuilder db, SearchMonitor[] monitors) {
   pinned_decision_builder_ = db;
   pinned_search_monitors_.Clear();
   pinned_search_monitors_.AddRange(monitors);
   NewSearchAux(db, monitors);
 }
Beispiel #34
0
    /**
     *
     * Solves a set covering problem.
     * See  See http://www.hakank.org/or-tools/set_covering.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("SetCovering");

        //
        // data
        //

        // Placing of firestations, from Winston 'Operations Research',
        // page 486.
        int min_distance = 15;
        int num_cities   = 6;

        int[,] distance = { {  0, 10, 20, 30, 30, 20 }, { 10,  0, 25, 35, 20, 10 }, { 20, 25,  0, 15, 30, 20 },
                            { 30, 35, 15,  0, 15, 25 }, { 30, 20, 30, 15,  0, 14 }, { 20, 10, 20, 25, 14,  0 } };

        //
        // Decision variables
        //
        IntVar[] x = solver.MakeIntVarArray(num_cities, 0, 1, "x");
        IntVar   z = x.Sum().Var();

        //
        // Constraints
        //

        // ensure that all cities are covered
        for (int i = 0; i < num_cities; i++)
        {
            IntVar[] b = (from j in Enumerable.Range(0, num_cities)
                          where distance[i, j] <= min_distance select x[j])
                         .ToArray();
            solver.Add(b.Sum() >= 1);
        }

        //
        // objective
        //
        OptimizeVar objective = z.Minimize(1);

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT);

        solver.NewSearch(db, objective);

        while (solver.NextSolution())
        {
            Console.WriteLine("z: {0}", z.Value());
            Console.Write("x: ");
            for (int i = 0; i < num_cities; i++)
            {
                Console.Write(x[i].Value() + " ");
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }