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

  }
Пример #2
0
  /**
   *
   * Implements a (decomposition) of the global constraint circuit
   * and extracting the path.
   *
   * One circuit for n = 5 is    3 0 4 2 1
   * Thus the extracted path is  0 -> 3 -> 2 -> 4 -> 1 -> 0
   *
   */
  private static void Solve(int n = 5)
  {
    Solver solver = new Solver("CircuitTest2");


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

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



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


    solver.NewSearch(db);

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

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

    solver.EndSearch();

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

  }
Пример #4
0
  public static IntVar[] subset_sum(Solver solver, 
                                    int[] values, 
                                    int total) {
    int n = values.Length;
    IntVar[] x = solver.MakeIntVarArray(n, 0, n, "x");
    solver.Add(x.ScalProd(values) == total);

    return x;
  }
Пример #5
0
  /**
   *
   * Scheduling speakers problem
   *
   *  From Rina Dechter, Constraint Processing, page 72
   *  Scheduling of 6 speakers in 6 slots.
   *
   * See http://www.hakank.org/google_or_tools/scheduling_speakers.py
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("SchedulingSpeakers");


    // number of speakers
    int n = 6;

    // slots available to speak
    int[][] available = {
                    // Reasoning:
      new int[] {3,4,5,6},    // 2) the only one with 6 after speaker F -> 1
      new int[] {3,4},        // 5) 3 or 4
      new int[] {2,3,4,5},    // 3) only with 5 after F -> 1 and A -> 6
      new int[] {2,3,4},      // 4) only with 2 after C -> 5 and F -> 1
      new int[] {3,4},        // 5) 3 or 4
      new int[] {1,2,3,4,5,6} // 1) the only with 1
    };


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

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

    for(int i = 0; i < n; i++) {
      solver.Add(x[i].Member(available[i]));
    }


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

    solver.NewSearch(db);

    while (solver.NextSolution()) {
      Console.WriteLine(string.Join(",", (from i in x select i.Value())));
    }

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

    solver.EndSearch();

  }
Пример #6
0
  /**
   *
   * Dudeney numbers
   * From Pierre Schaus blog post
   * Dudeney number
   * http://cp-is-fun.blogspot.com/2010/09/test-python.html
   * """
   * I discovered yesterday Dudeney Numbers
   * A Dudeney Numbers is a positive integer that is a perfect cube such that the sum
   * of its decimal digits is equal to the cube root of the number. There are only six
   * Dudeney Numbers and those are very easy to find with CP.
   * I made my first experience with google cp solver so find these numbers (model below)
   * and must say that I found it very convenient to build CP models in python!
   * When you take a close look at the line:
   *     solver.Add(sum([10**(n-i-1)*x[i] for i in range(n)]) == nb)
   * It is difficult to argue that it is very far from dedicated
   * optimization languages!
   * """
   *
   * Also see: http://en.wikipedia.org/wiki/Dudeney_number
   *
   */
  private static void Solve()
  {

    Solver solver = new Solver("DudeneyNumbers");

    //
    // data
    //
    int n = 6;

    //
    // Decision variables
    //
    IntVar[] x = solver.MakeIntVarArray(n, 0, 9, "x");
    IntVar nb = solver.MakeIntVar(3, (int)Math.Pow(10,n), "nb");
    IntVar s = solver.MakeIntVar(1,9*n+1,"s");

    //
    // Constraints
    //
    solver.Add(nb == s*s*s);
    solver.Add(x.Sum() == s);

    // solver.Add(ToNum(x, nb, 10));

    // alternative
    solver.Add((from i in Enumerable.Range(0, n)
                select (x[i]*(int)Math.Pow(10,n-i-1)).Var()).
               ToArray().Sum() == nb);


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


    solver.NewSearch(db);

    while (solver.NextSolution()) {
      Console.WriteLine(nb.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();

  }
Пример #7
0
  /**
   *
   * Decomposition of alldifferent_except_0
   *
   * See http://www.hakank.org/google_or_tools/map.py
   *
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("AllDifferentExcept0");

    //
    // data
    //
    int n = 6;

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

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

    // we also require at least 2 0's
    IntVar[] z_tmp = new IntVar[n];
    for(int i = 0; i < n; i++) {
      z_tmp[i] = x[i] == 0;
    }
    IntVar z = z_tmp.Sum().VarWithName("z");
    solver.Add(z == 2);


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

    solver.NewSearch(db);
    while (solver.NextSolution()) {
      Console.Write("z: {0}  x: ", z.Value());
      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();

  }
Пример #8
0
  /*
   * Global constraint regular
   *
   * This is a translation of MiniZinc's regular constraint (defined in
   * lib/zinc/globals.mzn), via the Comet code refered above.
   * All comments are from the MiniZinc code.
   * """
   * The sequence of values in array 'x' (which must all be in the range 1..S)
   * is accepted by the DFA of 'Q' states with input 1..S and transition
   * function 'd' (which maps (1..Q, 1..S) -> 0..Q)) and initial state 'q0'
   * (which must be in 1..Q) and accepting states 'F' (which all must be in
   * 1..Q).  We reserve state 0 to be an always failing state.
   * """
   *
   * x : IntVar array
   * Q : number of states
   * S : input_max
   * d : transition matrix
   * q0: initial state
   * F : accepting states
   *
   */
  static void MyRegular(Solver solver,
                        IntVar[] x,
                        int Q,
                        int S,
                        int[,] d,
                        int q0,
                        int[] F) {



    // d2 is the same as d, except we add one extra transition for
    // each possible input;  each extra transition is from state zero
    // to state zero.  This allows us to continue even if we hit a
    // non-accepted input.
    int[][] d2 = new int[Q+1][];
    for(int i = 0; i <= Q; i++) {
      int[] row = new int[S];
      for(int j = 0; j < S; j++) {
        if (i == 0) {
          row[j] = 0;
        } else {
          row[j] = d[i-1,j];
        }
      }
      d2[i] = row;
    }

    int[] d2_flatten = (from i in Enumerable.Range(0, Q+1)
                        from j in Enumerable.Range(0, S)
                        select d2[i][j]).ToArray();

    // If x has index set m..n, then a[m-1] holds the initial state
    // (q0), and a[i+1] holds the state we're in after processing
    // x[i].  If a[n] is in F, then we succeed (ie. accept the
    // string).
    int m = 0;
    int n = x.Length;

    IntVar[] a = solver.MakeIntVarArray(n+1-m, 0,Q+1, "a");
    // Check that the final state is in F
    solver.Add(a[a.Length-1].Member(F));
    // First state is q0
    solver.Add(a[m] == q0);

    for(int i = 0; i < n; i++) {
      solver.Add(x[i] >= 1);
      solver.Add(x[i] <= S);
      // Determine a[i+1]: a[i+1] == d2[a[i], x[i]]
      solver.Add(a[i+1] == d2_flatten.Element(((a[i]*S)+(x[i]-1))));
    }

  }
Пример #9
0
  /**
   *
   * Magic sequence problem.
   *
   * This is a port of the Python model
   * https://code.google.com/p/or-tools/source/browse/trunk/python/magic_sequence_distribute.py
   * """
   * This models aims at building a sequence of numbers such that the number of
   * occurrences of i in this sequence is equal to the value of the ith number.
   * It uses an aggregated formulation of the count expression called
   * distribute().
   * """
   *
   */
  private static void Solve(int size)
  {

    Solver solver = new Solver("MagicSequence");

    Console.WriteLine("\nSize: {0}", size);

    //
    // data
    //
    int[] all_values = new int[size];
    for (int i = 0; i < size; i++) {
      all_values[i] = i;
    }

    //
    // Decision variables
    //
    IntVar[] all_vars  = solver.MakeIntVarArray(size, 0, size - 1, "vars");

    //
    // Constraints
    //
    solver.Add(all_vars.Distribute(all_values, all_vars));
    solver.Add(all_vars.Sum() == size);


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

    solver.NewSearch(db);

    while (solver.NextSolution()) {
      for(int i = 0; i < size; i++) {
        Console.Write(all_vars[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 toNum: channeling between a number and an array.
   * See http://www.hakank.org/or-tools/toNum.py
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("ToNum");

    int n = 5;
    int bbase = 10;

    //
    // Decision variables
    //
    IntVar[] x = solver.MakeIntVarArray(n, 0, bbase - 1, "x");
    IntVar num = solver.MakeIntVar(0, (int)Math.Pow(bbase, n) - 1, "num");

    //
    // Constraints
    //

    solver.Add(x.AllDifferent());
    solver.Add(ToNum(x, num, bbase));

    // extra constraint (just for fun)
    // second digit should be 7
    // solver.Add(x[1] == 7);

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

    solver.NewSearch(db);

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

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

    solver.EndSearch();

  }
Пример #11
0
  /**
   *
   * Global constraint contiguity using Transition
   *
   * This version use the built-in TransitionConstraint.
   *
   * From Global Constraint Catalogue
   * http://www.emn.fr/x-info/sdemasse/gccat/Cglobal_contiguity.html
   * """
   * Enforce all variables of the VARIABLES collection to be assigned to 0 or 1.
   * In addition, all variables assigned to value 1 appear contiguously.
   *
   * Example:
   * (<0, 1, 1, 0>)
   *
   * The global_contiguity constraint holds since the sequence 0 1 1 0 contains
   * no more than one group of contiguous 1.
   * """
   *
   * Also see http://www.hakank.org/or-tools/contiguity_regular.py
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("ContiguityRegular");

    //
    // Data
    //
    int n = 7; // length of the array


    //
    // Decision variables
    //

    IntVar[] reg_input = solver.MakeIntVarArray(n, 0, 1, "reg_input");


    //
    // Constraints
    //
    MyContiguity(solver, reg_input);


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

    solver.NewSearch(db);

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

  }
Пример #12
0
  /**
   *
   * Grocery problem.
   *
   * From  Christian Schulte, Gert Smolka, Finite Domain
   * http://www.mozart-oz.org/documentation/fdt/
   * Constraint Programming in Oz. A Tutorial. 2001.
   * """
   * A kid goes into a grocery store and buys four items. The cashier
   * charges $7.11, the kid pays and is about to leave when the cashier
   * calls the kid back, and says 'Hold on, I multiplied the four items
   * instead of adding them; I'll try again; Hah, with adding them the
   * price still comes to $7.11'. What were the prices of the four items?
   * """
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("Grocery");

    int n = 4;
    int c = 711;

    //
    // Decision variables
    //

    IntVar[] item = solver.MakeIntVarArray(n, 0, c / 2, "item");

    //
    // Constraints
    //
    solver.Add(item.Sum() == c);
    // solver.Add(item[0] * item[1] * item[2] * item[3] == c * 100*100*100);
    // solver.Add(item.Prod() == c * 100*100*100);
    solver.Add(MyProd(item, c * 100*100*100));


    // Symmetry breaking
    Decreasing(solver, item);

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

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

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

    solver.EndSearch();

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

  }
Пример #14
0
  /**
   * circuit(solver, x)
   *
   * A decomposition of the global constraint circuit, based
   * on some observation of the orbits in an array.
   *
   * Note: The domain of x must be 0..n-1 (not 1..n)
   * since C# is 0-based.
   */
  public static void circuit(Solver solver, IntVar[] x) {

    int n = x.Length;
    IntVar[] z = solver.MakeIntVarArray(n, 0, n - 1, "z");

    solver.Add(x.AllDifferent());
    solver.Add(z.AllDifferent());

    // put the orbit of x[0] in z[0..n-1]
    solver.Add(z[0] == x[0]);
    for(int i = 1; i < n-1; i++) {
      solver.Add(z[i] == x.Element(z[i-1]));
    }

    // z may not be 0 for i < n-1
    for(int i = 1; i < n - 1; i++) {
      solver.Add(z[i] != 0);
    }

    // when i = n-1 it must be 0
    solver.Add(z[n - 1] == 0);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  }