Пример #1
0
  /**
   *
   * Solve the Least diff problem
   * For more info, see http://www.hakank.org/google_or_tools/least_diff.py
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("LeastDiff");

    //
    // Decision variables
    //
    IntVar A = solver.MakeIntVar(0, 9, "A");
    IntVar B = solver.MakeIntVar(0, 9, "B");
    IntVar C = solver.MakeIntVar(0, 9, "C");
    IntVar D = solver.MakeIntVar(0, 9, "D");
    IntVar E = solver.MakeIntVar(0, 9, "E");
    IntVar F = solver.MakeIntVar(0, 9, "F");
    IntVar G = solver.MakeIntVar(0, 9, "G");
    IntVar H = solver.MakeIntVar(0, 9, "H");
    IntVar I = solver.MakeIntVar(0, 9, "I");
    IntVar J = solver.MakeIntVar(0, 9, "J");

    IntVar[] all = new IntVar[] {A,B,C,D,E,F,G,H,I,J};
    int[] coeffs = {10000,1000,100,10,1};
    IntVar x = new IntVar[]{A,B,C,D,E}.ScalProd(coeffs).Var();
    IntVar y = new IntVar[]{F,G,H,I,J}.ScalProd(coeffs).Var();
    IntVar diff = (x - y).VarWithName("diff");


    //
    // Constraints
    //
    solver.Add(all.AllDifferent());
    solver.Add(A > 0);
    solver.Add(F > 0);
    solver.Add(diff > 0);


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

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

    solver.NewSearch(db, obj);
    while (solver.NextSolution()) {
      Console.WriteLine("{0} - {1} = {2}  ({3}",x.Value(), y.Value(), diff.Value(), diff.ToString());
    }

    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();

  }
Пример #2
0
  /**
   *
   * Implements the all interval problem.
   * See http://www.hakank.org/google_or_tools/all_interval.py
   *
   */
  private static void Solve(int n=12)
  {
    Solver solver = new Solver("AllInterval");


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

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

    for(int k = 0; k < n - 1; k++) {
      // solver.Add(diffs[k] == (x[k + 1] - x[k]).Abs());
      solver.Add(diffs[k] == (x[k + 1] - x[k].Abs()));
    }


    // symmetry breaking
    solver.Add(x[0] < x[n - 1]);
    solver.Add(diffs[0] < diffs[1]);


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

    solver.NewSearch(db);

    while (solver.NextSolution()) {
      Console.Write("x: ");
      for(int i = 0; i < n; i++) {
          Console.Write("{0} ", x[i].Value());
      }
      Console.Write("  diffs: ");
      for(int i = 0; i < n-1; i++) {
          Console.Write("{0} ", diffs[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();

  }
Пример #3
0
        public void VerifyThatInMemoryExportToProtoAfterSolutionFoundWorks()
        {
            CpModel model;

            // Model name must be the same because loading does not re-set it.
            const string modelName = "TestModelLoader";

            string modelText;

            using (var s = new Solver(modelName))
            {
                var x = s.MakeIntVar(0, 10, "x");
                var y = s.MakeIntVar(0, 10, "y");

                s.Add(x + y == 5);
                // Verify that adding one Constraint appears in the Count.
                Assert.That(s.ConstraintCount(), Is.EqualTo(1));

                var db = s.MakePhase(x, y, ChooseFirstUnbound, AssignMinValue);

                {
                    // TODO: TBD: consider adding a disposable search wrapper to hide that detail a bit...
                    // Ending the new search after next solution block is CRITICAL.
                    s.NewSearch(db);
                    while (s.NextSolution())
                    {
                        Console.WriteLine($"Found next solution: {x.ToString()} + {y.ToString()} == 5");
                        break;
                    }
                    s.EndSearch();
                }

                // Capture the ExportedModel textual (JSON) representation.
                model = s.ExportModel();
                Assert.That(model, Is.Not.Null);
                modelText = VerifyJsonText(model.ToString());
            }

            using (var s = new Solver(modelName))
            {
                Assert.That(s.LoadModel(model), Is.True);

                // Straight after load the Constraints should report the same number.
                Assert.That(s.ConstraintCount(), Is.EqualTo(1));

                // The textual representation must be the same.
                var actual     = s.ExportModel();
                var actualText = VerifyJsonText(actual.ToString());
                Assert.That(actualText, Is.EqualTo(modelText));
            }
        }
Пример #4
0
  /**
   *
   * Solve the SEND+MORE=MONEY problem
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("SendMoreMoney");

    //
    // Decision variables
    //
    IntVar S = solver.MakeIntVar(0, 9, "S");
    IntVar E = solver.MakeIntVar(0, 9, "E");
    IntVar N = solver.MakeIntVar(0, 9, "N");
    IntVar D = solver.MakeIntVar(0, 9, "D");
    IntVar M = solver.MakeIntVar(0, 9, "M");
    IntVar O = solver.MakeIntVar(0, 9, "O");
    IntVar R = solver.MakeIntVar(0, 9, "R");
    IntVar Y = solver.MakeIntVar(0, 9, "Y");

    // for AllDifferent()
    IntVar[] x = new IntVar[] {S,E,N,D,M,O,R,Y};

    //
    // Constraints
    //
    solver.Add(x.AllDifferent());
    solver.Add(S*1000 + E*100 + N*10 + D + M*1000 + O*100 + R*10 + E ==
               M*10000 + O*1000 + N*100 + E*10 + Y);

    solver.Add(S > 0);
    solver.Add(M > 0);

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

    solver.NewSearch(db);
    while (solver.NextSolution()) {
      for(int i = 0; i < 8; i++) {
        Console.Write(x[i].ToString() + " ");
      }
      Console.WriteLine();
    }

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

    solver.EndSearch();

  }
Пример #5
0
  /**
   *
   * Solve the xkcd problem
   * See http://www.hakank.org/google_or_tools/xkcd.py
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("Xkcd");

    //
    // Constants, inits
    //
    int n = 6;
    // for price and total: multiplied by 100 to be able to use integers
    int[] price = {215, 275, 335, 355, 420, 580};
    int total = 1505;

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

    //
    // Constraints
    //
    solver.Add(x.ScalProd(price) == total);

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

    solver.NewSearch(db);
    while (solver.NextSolution()) {
      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();

  }
Пример #6
0
 /**
  * Solves the rabbits + pheasants problem.  We are seing 20 heads
  * and 56 legs. How many rabbits and how many pheasants are we thus
  * seeing?
  */
 private static void Solve()
 {
   Solver solver = new Solver("RabbitsPheasants");
   IntVar rabbits = solver.MakeIntVar(0, 100, "rabbits");
   IntVar pheasants = solver.MakeIntVar(0, 100, "pheasants");
   solver.Add(rabbits + pheasants == 20);
   solver.Add(rabbits * 4 + pheasants * 2 == 56);
   DecisionBuilder db =
       new AssignFirstUnboundToMin(new IntVar[] {rabbits, pheasants});
   solver.NewSearch(db);
   solver.NextSolution();
   Console.WriteLine(
       "Solved Rabbits + Pheasants in {0} ms, and {1} search tree branches.",
       solver.WallTime(),  solver.Branches());
   Console.WriteLine(rabbits.ToString());
   Console.WriteLine(pheasants.ToString());
   solver.EndSearch();
 }
Пример #7
0
  /**
   *
   * A programming puzzle from Einav.
   *
   * From
   * "A programming puzzle from Einav"
   * http://gcanyon.wordpress.com/2009/10/28/a-programming-puzzle-from-einav/
   * """
   * My friend Einav gave me this programming puzzle to work on. Given
   * this array of positive and negative numbers:
   * 33   30  -10 -6  18   7  -11 -23   6
   * ...
   * -25   4  16  30  33 -23  -4   4 -23
   *
   * You can flip the sign of entire rows and columns, as many of them
   * as you like. The goal is to make all the rows and columns sum to positive
   * numbers (or zero), and then to find the solution (there are more than one)
   * that has the smallest overall sum. So for example, for this array:
   * 33  30 -10
   * -16  19   9
   * -17 -12 -14
   * You could flip the sign for the bottom row to get this array:
   * 33  30 -10
   * -16  19   9
   * 17  12  14
   * Now all the rows and columns have positive sums, and the overall total is
   * 108.
   * But you could instead flip the second and third columns, and the second
   * row, to get this array:
   * 33  -30  10
   * 16   19    9
   * -17   12   14
   * All the rows and columns still total positive, and the overall sum is just
   * 66. So this solution is better (I don't know if it's the best)
   * A pure brute force solution would have to try over 30 billion solutions.
   * I wrote code to solve this in J. I'll post that separately.
   * """
   *
   * Note:
   * This is a port of Larent Perrons's Python version of my own einav_puzzle.py.
   * He removed some of the decision variables and made it more efficient.
   * Thanks!
   *
   * Also see http://www.hakank.org/or-tools/einav_puzzle2.py
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("EinavPuzzle2");

    //
    // Data
    //

    // Small problem
    // int rows = 3;
    // int cols = 3;
    // int[,] data = {
    //   { 33,  30, -10},
    //   {-16,  19,   9},
    //   {-17, -12, -14}
    // };


    // Full problem
    int rows = 27;
    int cols = 9;
    int[,] data = {
      {33,30,10,-6,18,-7,-11,23,-6},
      {16,-19,9,-26,-8,-19,-8,-21,-14},
      {17,12,-14,31,-30,13,-13,19,16},
      {-6,-11,1,17,-12,-4,-7,14,-21},
      {18,-31,34,-22,17,-19,20,24,6},
      {33,-18,17,-15,31,-5,3,27,-3},
      {-18,-20,-18,31,6,4,-2,-12,24},
      {27,14,4,-29,-3,5,-29,8,-12},
      {-15,-7,-23,23,-9,-8,6,8,-12},
      {33,-23,-19,-4,-8,-7,11,-12,31},
      {-20,19,-15,-30,11,32,7,14,-5},
      {-23,18,-32,-2,-31,-7,8,24,16},
      {32,-4,-10,-14,-6,-1,0,23,23},
      {25,0,-23,22,12,28,-27,15,4},
      {-30,-13,-16,-3,-3,-32,-3,27,-31},
      {22,1,26,4,-2,-13,26,17,14},
      {-9,-18,3,-20,-27,-32,-11,27,13},
      {-17,33,-7,19,-32,13,-31,-2,-24},
      {-31,27,-31,-29,15,2,29,-15,33},
      {-18,-23,15,28,0,30,-4,12,-32},
      {-3,34,27,-25,-18,26,1,34,26},
      {-21,-31,-10,-13,-30,-17,-12,-26,31},
      {23,-31,-19,21,-17,-10,2,-23,23},
      {-3,6,0,-3,-32,0,-10,-25,14},
      {-19,9,14,-27,20,15,-5,-27,18},
      {11,-6,24,7,-17,26,20,-31,-25},
      {-25,4,-16,30,33,23,-4,-4,23}
    };


    IEnumerable<int> ROWS = Enumerable.Range(0, rows);
    IEnumerable<int> COLS = Enumerable.Range(0, cols);

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

    int[] signs_domain = {-1,1};
    // This don't work at the moment...
    IntVar[] row_signs = solver.MakeIntVarArray(rows, signs_domain, "row_signs");
    IntVar[] col_signs = solver.MakeIntVarArray(cols, signs_domain, "col_signs");



    // To optimize
    IntVar total_sum = x_flat.Sum().VarWithName("total_sum");

    //
    // Constraints
    //
    foreach(int i in ROWS) {
      foreach(int j in COLS) {
        solver.Add(x[i,j] == data[i,j] * row_signs[i] * col_signs[j]);
      }
    }

    // row sums
    IntVar[] row_sums = (from i in ROWS
                         select (from j in COLS
                                 select x[i,j]
                                ).ToArray().Sum().Var()).ToArray();

    foreach(int i in ROWS) {
      row_sums[i].SetMin(0);
    }

    // col sums
    IntVar[] col_sums = (from j in COLS
                         select (from i in ROWS
                                 select x[i,j]
                                 ).ToArray().Sum().Var()).ToArray();

    foreach(int j in COLS) {
      col_sums[j].SetMin(0);
    }


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


    //
    // Search
    //
    DecisionBuilder db = solver.MakePhase(col_signs.Concat(row_signs).ToArray(),
                                          Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
                                          Solver.ASSIGN_MAX_VALUE);

    solver.NewSearch(db, obj);

    while (solver.NextSolution()) {
      Console.WriteLine("Sum: {0}",total_sum.Value());
      Console.Write("row_sums: ");
      foreach(int i in ROWS) {
        Console.Write(row_sums[i].Value() + " ");
      }
      Console.Write("\nrow_signs: ");
      foreach(int i in ROWS) {
        Console.Write(row_signs[i].Value() + " ");
      }

      Console.Write("\ncol_sums: ");
      foreach(int j in COLS) {
        Console.Write(col_sums[j].Value() + " ");
      }
      Console.Write("\ncol_signs: ");
      foreach(int j in COLS) {
        Console.Write(col_signs[j].Value() + " ");
      }
      Console.WriteLine("\n");
      foreach(int i in ROWS) {
        foreach(int j in COLS) {
          Console.Write("{0,3} ", 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();

  }
Пример #8
0
  /**
   *
   * Implements a (decomposition) of the global constraint circuit.
   * See http://www.hakank.org/google_or_tools/circuit.py
   *
   */
  private static void Solve(int n = 5)
  {
    Solver solver = new Solver("Circuit");


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

    //
    // Constraints
    //
    circuit(solver, x);


    //
    // 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("{0} ", 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();

  }
Пример #9
0
  /**
   *
   * Solves a set covering problem.
   * See  See http://www.hakank.org/or-tools/set_covering2.py
   *
   */
  private static void Solve()
  {

    Solver solver = new Solver("SetCovering2");

    //
    // data
    //

    // Example 9.1-2 from
    // Taha "Operations Research - An Introduction",
    // page 354ff.
    // Minimize the number of security telephones in street
    // corners on a campus.

    int n = 8;            // maximum number of corners
    int num_streets = 11; // number of connected streets

    // corners of each street
    // Note: 1-based (handled below)
    int[,] corner = {{1,2},
                     {2,3},
                     {4,5},
                     {7,8},
                     {6,7},
                     {2,6},
                     {1,6},
                     {4,7},
                     {2,4},
                     {5,8},
                     {3,5}};

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

    //
    // Constraints
    //

    // ensure that all streets are covered
    for(int i = 0; i < num_streets; i++) {
      solver.Add(x[corner[i,0] - 1] + x[corner[i,1] - 1]  >= 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 < 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();

  }
Пример #10
0
  /**
   *
   * Implements the Who killed Agatha problem.
   * See http://www.hakank.org/google_or_tools/who_killed_agatha.py
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("WhoKilledAgatha");

    int n = 3;
    int agatha = 0;
    int butler = 1;
    int charles = 2;

    //
    // Decision variables
    //
    IntVar the_killer = solver.MakeIntVar(0, 2, "the_killer");
    IntVar the_victim = solver.MakeIntVar(0, 2, "the_victim");
    IntVar[,] hates = solver.MakeIntVarMatrix(n, n, 0, 1, "hates");
    IntVar[] hates_flat = hates.Flatten();
    IntVar[,] richer = solver.MakeIntVarMatrix(n, n, 0, 1, "richer");
    IntVar[] richer_flat = richer.Flatten();

    IntVar[] all = new IntVar[2 * n * n]; // for branching
    for(int i = 0; i < n*n; i++) {
      all[i] = hates_flat[i];
      all[(n*n)+i] = richer_flat[i]; 
    }

    //
    // Constraints
    //

    // Agatha, the butler, and Charles live in Dreadsbury Mansion, and
    // are the only ones to live there.

    // A killer always hates, and is no richer than his victim.
    //     hates[the_killer, the_victim] == 1
    //     hates_flat[the_killer * n + the_victim] == 1
    solver.Add(hates_flat.Element(the_killer * n + the_victim) == 1);

    //    richer[the_killer, the_victim] == 0
    solver.Add(richer_flat.Element(the_killer * n + the_victim) == 0);

    // define the concept of richer:
    //     no one is richer than him-/herself...
    for(int i = 0; i < n; i++) {
      solver.Add(richer[i,i] == 0);
    }

    // (contd...) if i is richer than j then j is not richer than i
    //   if (i != j) =>
    //       ((richer[i,j] = 1) <=> (richer[j,i] = 0))
    for(int i = 0; i < n; i++) {
      for(int j = 0; j < n; j++) {
        if (i != j) {
          solver.Add((richer[i, j]==1) - (richer[j, i]==0) == 0);
        }
      }
    }

    // Charles hates no one that Agatha hates.
    //    forall i in 0..2:
    //       (hates[agatha, i] = 1) => (hates[charles, i] = 0)
    for(int i = 0; i < n; i++) {
      solver.Add((hates[agatha,i]==1) - (hates[charles,i]==0) <= 0);

    }

    // Agatha hates everybody except the butler.
    solver.Add(hates[agatha,charles] == 1);
    solver.Add(hates[agatha,agatha] == 1);
    solver.Add(hates[agatha,butler] == 0);

    // The butler hates everyone not richer than Aunt Agatha.
    //    forall i in 0..2:
    //       (richer[i, agatha] = 0) => (hates[butler, i] = 1)
    for(int i = 0; i < n; i++) {
      solver.Add((richer[i,agatha] == 0)-(hates[butler,i] == 1)<=0);
    }

    // The butler hates everyone whom Agatha hates.
    //     forall i : 0..2:
    //         (hates[agatha, i] = 1) => (hates[butler, i] = 1)
    for(int i = 0; i < n; i++) {
      solver.Add((hates[agatha,i] == 1)-(hates[butler,i] == 1)<=0);
    }

    // Noone hates everyone.
    //     forall i in 0..2:
    //         (sum j in 0..2: hates[i,j]) <= 2
    for(int i = 0; i < n; i++) {
      solver.Add((from j in Enumerable.Range(0, n)
                  select hates[i,j]
                  ).ToArray().Sum() <= 2 );
    }


    // Who killed Agatha?
    solver.Add(the_victim == agatha);


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

    solver.NewSearch(db);

    while (solver.NextSolution()) {
      Console.WriteLine("the_killer: " + the_killer.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();

  }
Пример #11
0
  /**
   *
   * Labeled dice problem.
   *
   * From Jim Orlin 'Colored letters, labeled dice: a logic puzzle'
   * http://jimorlin.wordpress.com/2009/02/17/colored-letters-labeled-dice-a-logic-puzzle/
   * """
   * My daughter Jenn bough a puzzle book, and showed me a cute puzzle.  There
   * are 13 words as follows:  BUOY, CAVE, CELT, FLUB, FORK, HEMP, JUDY,
   * JUNK, LIMN, QUIP, SWAG, VISA, WISH.
   *
   * There are 24 different letters that appear in the 13 words.  The question
   * is:  can one assign the 24 letters to 4 different cubes so that the
   * four letters of each word appears on different cubes.  (There is one
   * letter from each word on each cube.)  It might be fun for you to try
   * it.  I'll give a small hint at the end of this post. The puzzle was
   * created by Humphrey Dudley.
   * """
   *
   * Jim Orlin's followup 'Update on Logic Puzzle':
   * http://jimorlin.wordpress.com/2009/02/21/update-on-logic-puzzle/
   *
   *
   * Also see http://www.hakank.org/or-tools/labeled_dice.py
   *
   */
  private static void Solve()
  {

    Solver solver = new Solver("LabeledDice");

    //
    // Data
    //
    int n = 4;
    int m = 24;

    int A = 0;
    int B = 1;
    int C = 2;
    int D = 3;
    int E = 4;
    int F = 5;
    int G = 6;
    int H = 7;
    int I = 8;
    int J = 9;
    int K = 10;
    int L = 11;
    int M = 12;
    int N = 13;
    int O = 14;
    int P = 15;
    int Q = 16;
    int R = 17;
    int S = 18;
    int T = 19;
    int U = 20;
    int V = 21;
    int W = 22;
    int Y = 23;


    String[] letters_str = {"A","B","C","D","E","F","G","H","I","J","K","L","M",
                            "N","O","P","Q","R","S","T","U","V","W","Y"};

    int num_words = 13;
    int[,] words =
      {
        {B,U,O,Y},
        {C,A,V,E},
        {C,E,L,T},
        {F,L,U,B},
        {F,O,R,K},
        {H,E,M,P},
        {J,U,D,Y},
        {J,U,N,K},
        {L,I,M,N},
        {Q,U,I,P},
        {S,W,A,G},
        {V,I,S,A},
        {W,I,S,H}
        };


    //
    // Decision variables
    //
    IntVar[] dice =  solver.MakeIntVarArray(m, 0, n-1, "dice");
    IntVar[] gcc =  solver.MakeIntVarArray(n, 6, 6, "gcc");

    //
    // Constraints
    //


    // the letters in a word must be on a different die
    for(int i = 0; i < num_words; i++) {
      solver.Add( (from j in Enumerable.Range(0, n)
                   select dice[words[i,j]]
                   ).ToArray().AllDifferent());
    }

    // there must be exactly 6 letters of each die
    /*
    for(int i = 0; i < n; i++) {
      solver.Add( ( from j in Enumerable.Range(0, m)
                    select (dice[j] == i)
                   ).ToArray().Sum() == 6 );
    }
    */
    // Use Distribute (Global Cardinality Count) instead.
    solver.Add(dice.Distribute(gcc));

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

    solver.NewSearch(db);

    while (solver.NextSolution()) {
      for(int d = 0; d < n; d++) {
        Console.Write("die {0}: ", d);
        for(int i = 0; i < m; i++) {
          if (dice[i].Value() == d) {
            Console.Write(letters_str[i]);
          }
        }
        Console.WriteLine();
      }

      Console.WriteLine("The words with the cube label:");
      for(int i = 0; i < num_words; i++) {
        for(int j = 0; j < n; j++) {
          Console.Write("{0} ({1})", letters_str[words[i,j]], dice[words[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();

  }
Пример #12
0
  /**
   *
   * Solves a set covering problem.
   * See  See http://www.hakank.org/or-tools/set_covering4.py
   *
   */
  private static void Solve(int set_partition)
  {

    Solver solver = new Solver("SetCovering4");

    //
    // data
    //

    // Set partition and set covering problem from
    // Example from the Swedish book
    // Lundgren, Roennqvist, Vaebrand
    // 'Optimeringslaera' (translation: 'Optimization theory'),
    // page 408.
    int num_alternatives = 10;
    int num_objects = 8;

    // costs for the alternatives
    int[] costs = {19, 16, 18, 13, 15, 19, 15, 17, 16, 15};

    // the alternatives, and their objects
    int[,] a = {
      // 1 2 3 4 5 6 7 8    the objects
        {1,0,0,0,0,1,0,0},  // alternative 1
        {0,1,0,0,0,1,0,1},  // alternative 2
        {1,0,0,1,0,0,1,0},  // alternative 3
        {0,1,1,0,1,0,0,0},  // alternative 4
        {0,1,0,0,1,0,0,0},  // alternative 5
        {0,1,1,0,0,0,0,0},  // alternative 6
        {0,1,1,1,0,0,0,0},  // alternative 7
        {0,0,0,1,1,0,0,1},  // alternative 8
        {0,0,1,0,0,1,0,1},  // alternative 9
        {1,0,0,0,0,1,1,0}}; // alternative 10

    //
    // Decision variables
    //
    IntVar[] x = solver.MakeIntVarArray(num_alternatives, 0, 1, "x");
    // number of assigned senators, to be minimized
    IntVar z = x.ScalProd(costs).VarWithName("z");

    //
    // Constraints
    //


    for(int j = 0; j < num_objects; j++) {
      IntVar[] b = new IntVar[num_alternatives];
      for(int i = 0; i < num_alternatives; i++) {
        b[i] = (x[i] * a[i,j]).Var();
      }

      if (set_partition == 1) {
        solver.Add(b.Sum() >= 1);
      } else {
        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("Selected alternatives: ");
      for(int i = 0; i < num_alternatives; i++) {
        if (x[i].Value() == 1) {
          Console.Write((i+1) + " ");
        }
      }
      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();

  }
Пример #13
0
        public void SimpleTestWithSearchMonitorsAndDecisionBuilder()
        {
            CpModel model;

            string modelText;

            const string modelName    = "TestModelLoader";
            const string equationText = "((x(0..10) + y(0..10)) == 5)";

            using (var s = new Solver(modelName))
            {
                var x = s.MakeIntVar(0, 10, "x");
                var y = s.MakeIntVar(0, 10, "y");
                var c = x + y == 5;
                Assert.That(c.Cst.ToString(), Is.EqualTo(equationText));
                s.Add(c);
                Assert.That(s.ConstraintCount(), Is.EqualTo(1));
                var collector = s.MakeAllSolutionCollector();
                var db        = s.MakePhase(x, y, ChooseFirstUnbound, AssignMinValue);
                Console.WriteLine("First search...");
                s.NewSearch(db, collector);
                while (s.NextSolution())
                {
                    Console.WriteLine($"{x.ToString()} + {y.ToString()} == 5");
                    break;
                }
                s.EndSearch();
                using (var vect = new SearchMonitorVector())
                {
                    vect.Add(collector);
                    model     = s.ExportModelWithSearchMonitorsAndDecisionBuilder(vect, db);
                    modelText = model.ToString();
                }
            }

            using (var s = new Solver(modelName))
            {
                // TODO: TBD: load but without any monitors and/or DB ...
                s.LoadModel(model);

                var loader = s.ModelLoader();
                // Do a quick sanity check that we at least have the proper constraint loaded.
                Assert.That(s.ConstraintCount(), Is.EqualTo(1));

                var x = loader.IntegerExpressionByName("x").Var();
                var y = loader.IntegerExpressionByName("y").Var();

                {
                    var c = x + y == 5;
                    // These should PASS as well...
                    Assert.That(c.Cst.ToString(), Is.Not.EqualTo("TrueConstraint()"));
                    Assert.That(c.Cst.ToString(), Is.EqualTo(equationText));
                }

                {
                    /* I dare say that THIS should PASS as well, but due to the fact that IntVar and
                     * derivatives are treated as IntExpr, it is FAILING. */
                    var actual = s.ExportModel();
                    Assert.That(actual.ToString(), Is.EqualTo(modelText));
                }

                var db = s.MakePhase(x, y, ChooseFirstUnbound, AssignMinValue);
                Console.WriteLine("Second search...");
                s.NewSearch(db);
                while (s.NextSolution())
                {
                    Console.WriteLine($"{x.ToString()} + {y.ToString()} == 5");
                }
                s.EndSearch();
            }
        }
Пример #14
0
  /**
   *
   * Solves a Sudoku problem.
   *
   * This is a very simple 4x4 problem instance:
   * Problem 26: Shidoku from
   * "Taking Sudoku Seriously", page 61
   *   4 _  _ _
   *   3 1  _ _
   *
   *   _ _  4 1
   *   _ _  _ 2
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("Sudoku");

    //
    // data
    //
    int block_size = 2;
    IEnumerable<int> BLOCK = Enumerable.Range(0, block_size);
    int n = block_size * block_size;
    IEnumerable<int> RANGE = Enumerable.Range(0, n);

    // 0 marks an unknown value
    int[,] initial_grid = {{4, 0,  0, 0},
                           {3, 1,  0, 0},

                           {0, 0,  4, 1},
                           {0, 0,  0, 2}};
    

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

    //
    // Constraints
    //  

    // init
    foreach(int i in RANGE) {
      foreach(int j in RANGE) {
        if (initial_grid[i,j] > 0) {
          solver.Add(grid[i,j] == initial_grid[i,j]);
        }
      }
    }

    
    foreach(int i in RANGE) {

      // rows
      solver.Add( (from j in RANGE
                   select grid[i,j]).ToArray().AllDifferent());

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

    }

    // blocks
    foreach(int i in BLOCK) {
      foreach(int j in BLOCK) {
        solver.Add( (from di in BLOCK
                     from dj in BLOCK
                     select grid[i*block_size+di, j*block_size+dj]
                     ).ToArray().AllDifferent());
      }
    }        


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

    solver.NewSearch(db);

    while (solver.NextSolution()) {
      for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++){ 
          Console.Write("{0} ", grid[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();

  }
Пример #15
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();

  }
Пример #16
0
    private static long Solve(long num_buses_check = 0)
    {
        SolverParameters sPrm = new SolverParameters();
        sPrm.compress_trail = 0;
        sPrm.trace_level = 0;
        sPrm.profile_level = 0;
        Solver solver = new Solver("OrTools",sPrm);

        //this works
        // IntVar[,] x = solver.MakeIntVarMatrix(2,2, new int[] {-2,0,1,2}, "x");

        //this doesn't work
        IntVar[,] x = solver.MakeIntVarMatrix(2, 2, new int[] { 0, 1, 2 }, "x");

        for (int w = 0; w < 2; w++)
        {
          IntVar[] b = new IntVar[2];
          for (int i = 0; i < 2; i++)
          {
        b[i] = solver.MakeIsEqualCstVar(x[w, i], 0);
          }
          solver.Add(solver.MakeSumGreaterOrEqual(b, 2));
        }

        IntVar[] x_flat = x.Flatten();
        DecisionBuilder db = solver.MakePhase(x_flat,
                                          Solver.CHOOSE_FIRST_UNBOUND,
                                          Solver.ASSIGN_MIN_VALUE);
        solver.NewSearch(db);
        while (solver.NextSolution())
        {
          Console.WriteLine("x: ");
          for (int j = 0; j < 2; j++)
          {
        Console.Write("worker" + (j + 1).ToString() + ":");
        for (int i = 0; i < 2; i++)
        {
          Console.Write(" {0,2} ", x[j, i].Value());
        }
        Console.Write("\n");
          }
          Console.WriteLine("End   at---->" + DateTime.Now);
        }

        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 1;
    }
Пример #17
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("OrganizeDay");

        int n = 4;

        int work = 0;
        int mail = 1;
        int shop = 2;
        int bank = 3;
        int[] tasks = {work, mail, shop, bank};
        int[] durations = {4,1,2,1};

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

        // the valid times of the day
        int begin = 9;
        int end   = 17;

        //
        // Decision variables
        //
        IntVar[] begins = solver.MakeIntVarArray(n, begin, end, "begins");
        IntVar[] ends = solver.MakeIntVarArray(n, begin, end, "ends");

        //
        // Constraints
        //
        foreach(int t in tasks) {
          solver.Add(ends[t] == begins[t] + durations[t]);
        }

        foreach(int i in tasks) {
          foreach(int j in tasks) {
        if (i < j) {
          NoOverlap(solver,
                    begins[i], durations[i],
                    begins[j], durations[j]);
        }
          }
        }

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

        solver.Add(begins[work] >= 11);

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

        solver.NewSearch(db);

        while (solver.NextSolution()) {
          foreach(int t in tasks) {
        Console.WriteLine("Task {0}: {1,2} .. ({2}) .. {3,2}",
                          t,
                          begins[t].Value(),
                          durations[t],
                          ends[t].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();
    }
Пример #18
0
  /**
   *
   * Crew allocation problem  in Google CP Solver.
   *
   * From Gecode example crew
   * examples/crew.cc
   * """
   * Example: Airline crew allocation
   *
   * Assign 20 flight attendants to 10 flights. Each flight needs a certain
   * number of cabin crew, and they have to speak certain languages.
   * Every cabin crew member has two flights off after an attended flight.
   * """
   *
   * Also see http://www.hakank.org/or-tools/crew.pl
   *
   */
  private static void Solve(int sols = 1, int minimize = 0)
  {
    Solver solver = new Solver("Crew");

    //
    // Data
    //
    string[] names = {"Tom",
                      "David",
                      "Jeremy",
                      "Ron",
                      "Joe",
                      "Bill",
                      "Fred",
                      "Bob",
                      "Mario",
                      "Ed",
                      "Carol",
                      "Janet",
                      "Tracy",
                      "Marilyn",
                      "Carolyn",
                      "Cathy",
                      "Inez",
                      "Jean",
                      "Heather",
                      "Juliet"};

    int num_persons = names.Length;


    //
    // Attributes of the crew
    //
    int[,] attributes = {
      // steward, hostess, french, spanish, german
      {1,0,0,0,1},   // Tom     = 0
      {1,0,0,0,0},   // David   = 1
      {1,0,0,0,1},   // Jeremy  = 2
      {1,0,0,0,0},   // Ron     = 3
      {1,0,0,1,0},   // Joe     = 4
      {1,0,1,1,0},   // Bill    = 5
      {1,0,0,1,0},   // Fred    = 6
      {1,0,0,0,0},   // Bob     = 7
      {1,0,0,1,1},   // Mario   = 8
      {1,0,0,0,0},   // Ed      = 9
      {0,1,0,0,0},   // Carol   = 10
      {0,1,0,0,0},   // Janet   = 11
      {0,1,0,0,0},   // Tracy   = 12
      {0,1,0,1,1},   // Marilyn = 13
      {0,1,0,0,0},   // Carolyn = 14
      {0,1,0,0,0},   // Cathy   = 15
      {0,1,1,1,1},   // Inez    = 16
      {0,1,1,0,0},   // Jean    = 17
      {0,1,0,1,1},   // Heather = 18
      {0,1,1,0,0}    // Juliet  = 19
    };


    //
    // Required number of crew members.
    //
    // The columns are in the following order:
    // staff     : Overall number of cabin crew needed
    // stewards  : How many stewards are required
    // hostesses : How many hostesses are required
    // french    : How many French speaking employees are required
    // spanish   : How many Spanish speaking employees are required
    // german    : How many German speaking employees are required
    //
    int[,] required_crew = {
        {4,1,1,1,1,1}, // Flight 1
        {5,1,1,1,1,1}, // Flight 2
        {5,1,1,1,1,1}, // ..
        {6,2,2,1,1,1},
        {7,3,3,1,1,1},
        {4,1,1,1,1,1},
        {5,1,1,1,1,1},
        {6,1,1,1,1,1},
        {6,2,2,1,1,1}, // ...
        {7,3,3,1,1,1}  // Flight 10
        };

    int num_flights = required_crew.GetLength(0);


    //
    // Decision variables
    //
    IntVar[,] crew = solver.MakeIntVarMatrix(num_flights, num_persons,
                                             0, 1, "crew");
    IntVar[] crew_flat = crew.Flatten();

    // number of working persons
    IntVar num_working = solver.MakeIntVar(1, num_persons, "num_working");

    //
    // Constraints
    //

    // number of working persons
    IntVar[] nw = new IntVar[num_persons];
    for(int p = 0; p < num_persons; p++) {
      IntVar[] tmp = new IntVar[num_flights];
      for(int f = 0; f < num_flights; f++) {
        tmp[f] = crew[f,p];
      }
      nw[p] = tmp.Sum() > 0;
    }
    solver.Add(nw.Sum() == num_working);

    for(int f = 0; f < num_flights; f++) {
      // size of crew
      IntVar[] tmp = new IntVar[num_persons];
      for(int p = 0; p < num_persons; p++) {
        tmp[p] = crew[f,p];
      }
      solver.Add(tmp.Sum() == required_crew[f,0]);

      // attributes and requirements
      for(int a = 0; a < 5; a++) {
        IntVar[] tmp2 = new IntVar[num_persons];
        for(int p = 0; p < num_persons; p++) {
          tmp2[p] = (crew[f,p]*attributes[p,a]).Var();
        }
        solver.Add(tmp2.Sum() >= required_crew[f,a+1]);
      }
    }

    // after a flight, break for at least two flights
    for(int f = 0; f < num_flights - 2; f++) {
      for(int i = 0; i < num_persons; i++) {
        solver.Add(crew[f,i] + crew[f+1,i] + crew[f+2,i] <= 1);
      }
    }

    // extra contraint: all must work at least two of the flights
    /*
    for(int p = 0; p < num_persons; p++) {
      IntVar[] tmp = new IntVar[num_flights];
      for(int f = 0; f < num_flights; f++) {
        tmp[f] = crew[f,p];
      }
      solver.Add(tmp.Sum() >= 2);
    }
    */


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

    if (minimize > 0) {
      OptimizeVar obj = num_working.Minimize(1);
      solver.NewSearch(db, obj);
    } else {
      solver.NewSearch(db);
    }

    int num_solutions = 0;
    while (solver.NextSolution()) {
      num_solutions++;
      Console.WriteLine("Solution #{0}", num_solutions);
      Console.WriteLine("Number working: {0}", num_working.Value());

      for(int f = 0; f < num_flights; f++) {
        for(int p = 0; p < num_persons; p++) {
          Console.Write(crew[f,p].Value() + " ");
        }
        Console.WriteLine();
      }
      Console.WriteLine("\nFlights: ");
      for(int f = 0; f < num_flights; f++) {
        Console.Write("Flight #{0}: ", f);
        for(int p = 0; p < num_persons; p++) {
          if (crew[f, p].Value() == 1) {
            Console.Write(names[p] + " ");
          }
        }
        Console.WriteLine();
      }

      Console.WriteLine("\nCrew:");
      for(int p = 0; p < num_persons; p++) {
        Console.Write("{0,-10}", names[p]);
        for(int f = 0; f < num_flights; f++) {
          if (crew[f,p].Value() == 1) {
            Console.Write(f + " ");
          }
        }
        Console.WriteLine();
      }

      Console.WriteLine();

      if (num_solutions >= sols) {
        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();

  }
Пример #19
0
  /**
   *
   * Solves a simple map coloring problem.
   *
   * Alternative version, using a matrix to represent
   * the neighbours.
   *
   * See http://www.hakank.org/google_or_tools/map.py
   *
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("Map2");

    //
    // data
    //
    int Belgium     = 0;
    int Denmark     = 1;
    int France      = 2;
    int Germany     = 3;
    int Netherlands = 4;
    int Luxembourg  = 5;

    int n = 6;
    int max_num_colors = 4;

    int[,] neighbours =  {{France,     Belgium},
                         {France,     Luxembourg},
                         {France,     Germany},
                         {Luxembourg, Germany},
                         {Luxembourg, Belgium},
                         {Belgium,    Netherlands},
                         {Belgium,    Germany},
                         {Germany,    Netherlands},
                         {Germany,    Denmark}};



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

    //
    // Constraints
    //
    for(int i = 0; i < neighbours.GetLength(0); i++) {
      solver.Add(color[neighbours[i,0]] != color[neighbours[i,1]]);
    }

    // Symmetry breaking
    solver.Add(color[Belgium] == 1);


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

    solver.NewSearch(db);
    while (solver.NextSolution()) {
      Console.Write("colors: ");
      for(int i = 0; i < n; i++) {
        Console.Write("{0} ", color[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();

  }
Пример #20
0
  /**
   *
   * Olympic puzzle.
   * 
   * Benchmark for Prolog (BProlog)
   * """
   * File   : olympic.pl
   * Author : Neng-Fa ZHOU
   * Date   : 1993
   *
   * Purpose: solve a puzzle taken from Olympic Arithmetic Contest
   *
   * Given ten variables with the following configuration:
   *
   *                 X7   X8   X9   X10
   *
   *                    X4   X5   X6
   *
   *                       X2   X3
   *
   *                          X1
   *
   * We already know that X1 is equal to 3 and want to assign each variable
   * with a different integer from {1,2,...,10} such that for any three
   * variables
   *                        Xi   Xj
   *
   *                           Xk
   *
   * the following constraint is satisfied:
   *
   *                      |Xi-Xj| = Xk
   * """
   *
   * Also see http://www.hakank.org/or-tools/olympic.py
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("Olympic");

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

    //
    // Decision variables
    //
    IntVar[] x = solver.MakeIntVarArray(n, 1, n, "x");
    IntVar X1  = x[0];
    IntVar X2  = x[1];
    IntVar X3  = x[2];
    IntVar X4  = x[3];
    IntVar X5  = x[4];
    IntVar X6  = x[5];
    IntVar X7  = x[6];
    IntVar X8  = x[7];
    IntVar X9  = x[8];
    IntVar X10 = x[9];


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

    solver.Add(X1 == 3);
    minus(solver, X2, X3, X1);
    minus(solver, X4, X5, X2);
    minus(solver, X5, X6, X3);
    minus(solver, X7, X8, X4);
    minus(solver, X8, X9, X5);
    minus(solver, X9, X10, X6);


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

    solver.NewSearch(db);

    while (solver.NextSolution()) {
      for(int i = 0; i < n; i++) {
        Console.Write("{0,2} ", x[i].Value());
      }
      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();

  }
Пример #21
0
  /**
   *
   * Coin application.
   *
   * From "Constraint Logic Programming using ECLiPSe"
   *  pages 99f and 234 ff.
   * The solution in ECLiPSe is at page 236.
   *
   * """
   * What is the minimum number of coins that allows one to pay _exactly_
   * any amount smaller than one Euro? Recall that there are six different
   * euro cents, of denomination 1, 2, 5, 10, 20, 50
   * """

   * Also see http://www.hakank.org/or-tools/coins3.py 
   *
   */
  private static void Solve()
  {

    Solver solver = new Solver("Coins3");

    //
    // Data
    //
    int n = 6; // number of different coins
    int[] variables = {1, 2, 5, 10, 25, 50};

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

    //
    // Decision variables
    //
    IntVar[] x = solver.MakeIntVarArray(n, 0, 99, "x");
    IntVar num_coins = x.Sum().VarWithName("num_coins");


    //
    // Constraints
    //

    // Check that all changes from 1 to 99 can be made.
    for(int j = 1; j < 100; j++) {
      IntVar[] tmp = solver.MakeIntVarArray(n, 0, 99, "tmp");
      solver.Add(tmp.ScalProd(variables) == j);

      foreach(int i in RANGE) {
        solver.Add(tmp[i] <= x[i]);
      }

    }

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

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

    solver.NewSearch(db, obj);

    while (solver.NextSolution()) {
      Console.WriteLine("num_coins: {0}", num_coins.Value());
      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();

  }
Пример #22
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);
    int c = 0;
    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();

  }
Пример #23
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();

  }
Пример #24
0
  /**
   *
   * P-median problem.
   *
   * Model and data from the OPL Manual, which describes the problem:
   * """
   * The P-Median problem is a well known problem in Operations Research.
   * The problem can be stated very simply, like this: given a set of customers
   * with known amounts of demand, a set of candidate locations for warehouses,
   * and the distance between each pair of customer-warehouse, choose P
   * warehouses to open that minimize the demand-weighted distance of serving
   * all customers from those P warehouses.
   * """
   *
   * Also see http://www.hakank.org/or-tools/p_median.py
   *
   */
  private static void Solve()
  {

    Solver solver = new Solver("PMedian");

    //
    // Data
    //
    int p = 2;
    int num_customers = 4;
    IEnumerable<int> CUSTOMERS = Enumerable.Range(0, num_customers);

    int num_warehouses = 3;
    IEnumerable<int> WAREHOUSES = Enumerable.Range(0, num_warehouses);

    int[] demand = {100,80,80,70};
    int [,] distance = {
      { 2, 10, 50},
      { 2, 10, 52},
      {50, 60,  3},
      {40, 60,  1}
    };

    //
    // Decision variables
    //

    IntVar[] open = solver.MakeIntVarArray(num_warehouses, 0, num_warehouses, "open");
    IntVar[,] ship = solver.MakeIntVarMatrix(num_customers, num_warehouses,
                                             0, 1, "ship");
    IntVar z = solver.MakeIntVar(0, 1000, "z");


    //
    // Constraints
    //

    solver.Add((from c in CUSTOMERS
                from w in WAREHOUSES
                select (demand[c]*distance[c,w]*ship[c,w])
                ).ToArray().Sum() == z);

    solver.Add(open.Sum() == p);

    foreach(int c in CUSTOMERS) {
      foreach(int w in WAREHOUSES) {
        solver.Add(ship[c,w] <= open[w]);
      }

      solver.Add((from w in WAREHOUSES select ship[c,w]).ToArray().Sum() == 1);
    }


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

    //
    // Search
    //
    DecisionBuilder db = solver.MakePhase(open.Concat(ship.Flatten()).ToArray(),
                                          Solver.CHOOSE_FIRST_UNBOUND,
                                          Solver.ASSIGN_MIN_VALUE);

    solver.NewSearch(db, obj);

    while (solver.NextSolution()) {
      Console.WriteLine("z: {0}",z.Value());
      Console.Write("open:");
      foreach(int w in WAREHOUSES) {
        Console.Write(open[w].Value() + " ");
      }
      Console.WriteLine();
      foreach(int c in CUSTOMERS) {
        foreach(int w in WAREHOUSES) {
          Console.Write(ship[c,w].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();

  }
Пример #25
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();

  }
Пример #26
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();

  }
Пример #27
0
  /**
   *
   * Implements Young tableaux and partitions.
   * See http://www.hakank.org/or-tools/young_tableuax.py
   *
   */
  private static void Solve(int n)
  {
    Solver solver = new Solver("YoungTableaux");

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

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

    // partition structure
    IntVar[] p = solver.MakeIntVarArray(n, 0, n + 1, "p");

    //
    // Constraints
    //
    // 1..n is used exactly once
    for(int i = 1; i <= n; i++) {
      solver.Add(x_flat.Count(i, 1));
    }

    solver.Add(x[0,0] == 1);

    // row wise
    for(int i = 0; i < n; i++) {
      for(int j = 1; j < n; j++) {
        solver.Add(x[i,j] >= x[i,j - 1]);
      }
    }

    // column wise
    for(int j = 0; j < n; j++) {
      for(int i = 1; i < n; i++) {
        solver.Add(x[i,j] >= x[i - 1, j]);
      }
    }

    // calculate the structure (i.e. the partition)
    for(int i = 0; i < n; i++) {
      IntVar[] b = new IntVar[n];
      for(int j = 0; j < n; j++) {
        b[j] = x[i, j] <= n;
      }
      solver.Add(p[i] == b.Sum());
    }

    solver.Add(p.Sum() == n);

    for(int i = 1; i < n; i++) {
      solver.Add(p[i - 1] >= p[i]);
    }



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

    solver.NewSearch(db);

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

      for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
          long val = x[i,j].Value();
          if (val <= n) {
            Console.Write(val + " ");
          }
        }
        if (p[i].Value() > 0) {
          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();

  }
Пример #28
0
  /**
   *
   * 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();

  }
Пример #29
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();

  }
Пример #30
0
  /**
   *
   * Solves some stable marriage problems.
   *
   * This version randomize the problem instances.
   *
   * Also, see http://www.hakank.org/or-tools/stable_marriage.cs
   *
   *
   */
  private static void Solve(int n = 10, int sols_to_show = 0)
  {

    Solver solver = new Solver("StableMarriage");

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

    int[][] rankMen = new int[n][];
    int[][] rankWomen = new int[n][];
    for (int i = 0; i < n; i++) {
      int[] m = shuffle(n, generator); 
      int[] w = shuffle(n, generator); 
      rankMen[i] = new int[n];
      rankWomen[i] = new int[n];
      for (int j = 0; j < n; j++) {
        rankMen[i][j] = m[j];
        rankWomen[i][j] = w[j];
      }
    } 

    Console.WriteLine("after generating...");

    if (n <= 20) {
      Console.Write("rankMen: ");

      printRank("rankMen", rankMen);
      printRank("rankWomen", rankWomen);

      
    }

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

    //
    // Constraints
    //
    // (The comments below are the Comet code)

    //
    //   forall(m in Men)
    //      cp.post(husband[wife[m]] == m);
    for(int m = 0; m < n; m++) {
      solver.Add(husband.Element(wife[m]) == m);
    }

    //   forall(w in Women)
    //     cp.post(wife[husband[w]] == w);
    for(int w = 0; w < n; w++) {
      solver.Add(wife.Element(husband[w]) == w);
    }


    //   forall(m in Men, o in Women)
    //       cp.post(rankMen[m,o] < rankMen[m, wife[m]] =>
    //               rankWomen[o,husband[o]] < rankWomen[o,m]);
    for(int m = 0; m < n; m++) {
      for(int o = 0; o < n; o++) {
        IntVar b1 = rankMen[m].Element(wife[m]) > rankMen[m][o];
        IntVar b2 = rankWomen[o].Element(husband[o]) < rankWomen[o][m];
        solver.Add(b1 <= b2);
      }

    }

    //   forall(w in Women, o in Men)
    //      cp.post(rankWomen[w,o] < rankWomen[w,husband[w]] =>
    //              rankMen[o,wife[o]] < rankMen[o,w]);
    for(int w = 0; w < n; w++) {
      for(int o = 0; o < n; o++) {
        IntVar b1 = rankWomen[w].Element(husband[w]) > rankWomen[w][o];
        IntVar b2 = rankMen[o].Element(wife[o]) < rankMen[o][w];
        solver.Add(b1 <= b2);
        }
      }


    //
    // Search
    //
    DecisionBuilder db = solver.MakePhase(wife,
                                          // 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.CHOOSE_MIN_SIZE,
                                          // Solver.CHOOSE_MAX_SIZE,
                                          // Solver.CHOOSE_MAX_REGRET,
                                        


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

    solver.NewSearch(db);

    int sols = 0;
    while (solver.NextSolution()) {
      sols += 1;
      Console.Write("wife   : ");
      for(int i = 0; i < n; i++) {
        Console.Write(wife[i].Value() + " ");
      }
      Console.Write("\nhusband: ");
      for(int i = 0; i < n; i++) {
        Console.Write(husband[i].Value() + " ");
      }
      Console.WriteLine("\n");

      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();

  }
Пример #31
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();

  }
Пример #32
0
  /**
   *
   * Just forgotten puzzle (Enigma 1517) in Google CP Solver.
   *
   * From http://www.f1compiler.com/samples/Enigma 201517.f1.html
   * """
   * Enigma 1517 Bob Walker, New Scientist magazine, October 25, 2008.
   *
   * Joe was furious when he forgot one of his bank account numbers.
   * He remembered that it had all the digits 0 to 9 in some order,
   * so he tried the following four sets without success:
   *
   * 9 4 6 2 1 5 7 8 3 0
   * 8 6 0 4 3 9 1 2 5 7
   * 1 6 4 0 2 9 7 8 5 3
   * 6 8 2 4 3 1 9 0 7 5
   *
   * When Joe finally remembered his account number, he realised that
   * in each set just four of the digits were in their correct position
   * and that, if one knew that, it was possible to work out his
   * account number. What was it?
   * """
   *
   * Also see http://www.hakank.org/google_or_tools/just_forgotten.py
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("JustForgotten");


    int rows = 4;
    int cols = 10;

    // The four tries
    int[,] a = {{9,4,6,2,1,5,7,8,3,0},
                {8,6,0,4,3,9,1,2,5,7},
                {1,6,4,0,2,9,7,8,5,3},
                {6,8,2,4,3,1,9,0,7,5}};


    //
    // Decision variables
    //
    IntVar[] x = solver.MakeIntVarArray(cols, 0, 9, "x");

    //
    // Constraints
    //
    solver.Add(x.AllDifferent());
    for(int r = 0; r < rows; r++) {
      solver.Add( (from c in Enumerable.Range(0, cols)
                   select x[c] == a[r,c]).ToArray().Sum() == 4);
    }



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

    solver.NewSearch(db);

    while (solver.NextSolution()) {
      Console.WriteLine("Account number:");
      for(int j = 0; j < cols; j++) {
        Console.Write(x[j].Value() + " ");
      }
      Console.WriteLine("\n");
      Console.WriteLine("The four tries, where '!' represents a correct digit:");
      for(int i = 0; i < rows; i++) {
        for(int j = 0; j < cols; j++) {
          String c = " ";
          if (a[i,j] == x[j].Value()) {
            c = "!";
          }
          Console.Write("{0}{1} ", a[i,j], c);
        }
        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();

  }