예제 #1
0
  /*
   * Decompositon of cumulative.
   *
   * Inspired by the MiniZinc implementation:
   * http://www.g12.csse.unimelb.edu.au/wiki/doku.php?id=g12:zinc:lib:minizinc:std:cumulative.mzn&s[]=cumulative
   * The MiniZinc decomposition is discussed in the paper:
   * A. Schutt, T. Feydy, P.J. Stuckey, and M. G. Wallace.
   * "Why cumulative decomposition is not as bad as it sounds."
   * Download:
   * http://www.cs.mu.oz.au/%7Epjs/rcpsp/papers/cp09-cu.pdf
   * http://www.cs.mu.oz.au/%7Epjs/rcpsp/cumu_lazyfd.pdf
   *
   *
   * Parameters:
   *
   * s: start_times    assumption: IntVar[]
   * d: durations      assumption: int[]
   * r: resources      assumption: int[]
   * b: resource limit assumption: IntVar or int
   *
   *
   */
  static void MyCumulative(Solver solver,
                           IntVar[] s,
                           int[] d,
                           int[] r,
                           IntVar b) {

    int[] tasks = (from i in Enumerable.Range(0, s.Length)
                   where r[i] > 0 && d[i] > 0
                   select i).ToArray();
    int times_min = tasks.Min(i => (int)s[i].Min());
    int d_max = d.Max();
    int times_max = tasks.Max(i => (int)s[i].Max() + d_max);
    for(int t = times_min; t <= times_max; t++) {
      ArrayList bb = new ArrayList();
      foreach(int i in tasks) {
        bb.Add(((s[i] <= t) * (s[i] + d[i]> t) * r[i]).Var());
      }
      solver.Add((bb.ToArray(typeof(IntVar)) as IntVar[]).Sum() <= b);
    }

    // Somewhat experimental:
    // This constraint is needed to constrain the upper limit of b.
    if (b is IntVar) {
      solver.Add(b <= r.Sum());
    }

   }
예제 #2
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();

  }
예제 #3
0
    //  We don't need helper functions here
    //  Csharp syntax is easier than C++ syntax!

    private static void CPisFun (int kBase)
    {
        //  Constraint Programming engine
        Solver solver = new Solver ("CP is fun!");

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

        // We need to group variables in a vector to be able to use
        // the global constraint AllDifferent
        IntVar[] letters = new IntVar[] { c, p, i, s, f, u, n, t, r, e};

        // Check if we have enough digits
        if (kBase < letters.Length) {
          throw new Exception("kBase < letters.Length");
        }

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

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

        SolutionCollector all_solutions = solver.MakeAllSolutionCollector();
        //  Add the interesting variables to the SolutionCollector
        all_solutions.Add(c);
        all_solutions.Add(p);
        //  Create the variable kBase * c + p
        IntVar v1 = solver.MakeSum(solver.MakeProd(c, kBase), p).Var();
        //  Add it to the SolutionCollector
        all_solutions.Add(v1);

        //  Decision Builder: hot to scour the search tree
        DecisionBuilder db = solver.MakePhase (letters,
                                               Solver.CHOOSE_FIRST_UNBOUND,
                                               Solver.ASSIGN_MIN_VALUE);
        solver.Solve(db, all_solutions);

        //  Retrieve the solutions
        int numberSolutions = all_solutions.SolutionCount();
        Console.WriteLine ("Number of solutions: " + numberSolutions);

        for (int index = 0; index < numberSolutions; ++index) {
            Assignment solution = all_solutions.Solution(index);
            Console.WriteLine ("Solution found:");
            Console.WriteLine ("v1=" + solution.Value(v1));
        }
    }
예제 #4
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();

  }
예제 #5
0
  /**
   * Ensure that the sum of the segments
   * in cc == res
   *
   */
  public static void calc(Solver solver,
                           int[] cc,
                           IntVar[,] x,
                           int res)
  {

    int ccLen = cc.Length;
    if (ccLen == 4) {

      // for two operands there's
      // a lot of possible variants
      IntVar a = x[cc[0]-1, cc[1]-1];
      IntVar b = x[cc[2]-1, cc[3]-1];

      IntVar r1 = a + b == res;
      IntVar r2 = a * b == res;
      IntVar r3 = a * res == b;
      IntVar r4 = b * res == a;
      IntVar r5 = a - b == res;
      IntVar r6 = b - a == res;

      solver.Add(r1+r2+r3+r4+r5+r6 >= 1);

    } else {

      // For length > 2 then res is either the sum
      // the the product of the segment

      // sum the numbers
      int len = cc.Length / 2;
      IntVar[] xx = (from i in Enumerable.Range(0, len)
                     select x[cc[i*2]-1,cc[i*2+1]-1]).ToArray();

      // Sum
      IntVar this_sum = xx.Sum() == res;

      // Product
      // IntVar this_prod = (xx.Prod() == res).Var(); // don't work
      IntVar this_prod;
      if (xx.Length == 3) {
        this_prod = (x[cc[0]-1,cc[1]-1] *
                     x[cc[2]-1,cc[3]-1] *
                     x[cc[4]-1,cc[5]-1]) == res;
      } else {
        this_prod = (
                     x[cc[0]-1,cc[1]-1] *
                     x[cc[2]-1,cc[3]-1] *
                     x[cc[4]-1,cc[5]-1] *
                     x[cc[6]-1,cc[7]-1]) == res;

      }

      solver.Add(this_sum + this_prod >= 1);


    }
  }
예제 #6
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();

  }
예제 #7
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();

  }
예제 #8
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();

  }
예제 #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
  public static void minus(Solver solver, 
                           IntVar x, 
                           IntVar y, 
                           IntVar z) 
 {
   solver.Add(z == (x - y).Abs());
 }
예제 #12
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();

  }
예제 #13
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();

  }
예제 #14
0
  /**
   * Ensure that the sum of the segments
   * in cc == res
   *
   */
  public static void  calc(Solver solver,
                           int[] cc,
                           IntVar[,] x,
                           int res)
  {

    // ensure that the values are positive
    int len = cc.Length / 2;
    for(int i = 0; i < len; i++) {
      solver.Add(x[cc[i*2]-1,cc[i*2+1]-1] >= 1);
    }

    // sum the numbers
    solver.Add( (from i in Enumerable.Range(0, len)
                 select x[cc[i*2]-1,cc[i*2+1]-1])
                .ToArray().Sum() == res);
  }
예제 #15
0
  /**
   *
   * A simple propagator for modulo constraint.
   *
   * This implementation is based on the ECLiPSe version
   * mentioned in "A Modulo propagator for ECLiPSE"
   * http://www.hakank.org/constraint_programming_blog/2010/05/a_modulo_propagator_for_eclips.html
   * The ECLiPSe Prolog source code:
   * http://www.hakank.org/eclipse/modulo_propagator.ecl
   *
   */
  public static void MyMod(Solver solver, IntVar x, IntVar y, IntVar r) {

    long lbx = x.Min();
    long ubx = x.Max();
    long ubx_neg = -ubx;
    long lbx_neg = -lbx;
    int min_x = (int)Math.Min(lbx, ubx_neg);
    int max_x = (int)Math.Max(ubx, lbx_neg);

    IntVar d = solver.MakeIntVar(min_x, max_x, "d");

    // r >= 0
    solver.Add(r >= 0);

    // x*r >= 0
    solver.Add( x*r >= 0);

    // -abs(y) < r
    solver.Add(-y.Abs() < r);

    // r < abs(y)
    solver.Add(r < y.Abs());

    // min_x <= d, i.e. d > min_x
    solver.Add(d > min_x);

    // d <= max_x
    solver.Add(d <= max_x);

    // x == y*d+r
    solver.Add(x - (y*d + r) == 0);

  }
예제 #16
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;
  }
예제 #17
0
  //
  // Decomposition of alldifferent_except_0
  //
  public static void AllDifferentExcept0(Solver solver, IntVar[] a) {

    int n = a.Length;
    for(int i = 0; i < n; i++) {
      for(int j = 0; j < i; j++) {
        solver.Add((a[i] != 0) * (a[j] != 0) <= (a[i] != a[j]));
      }
    }
  }
예제 #18
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();
 }
예제 #19
0
  /**
   * Ensure that the sum of the segments
   * in cc == res
   *
   */
  public static void  calc(Solver solver,
                           int[] cc,
                           IntVar[,] x,
                           int res)
  {

    // sum the numbers
    int len = cc.Length / 2;
    solver.Add( (from i in Enumerable.Range(0, len)
                 select x[cc[i*2]-1,cc[i*2+1]-1]).ToArray().Sum() == res);
  }
예제 #20
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();

  }
예제 #21
0
파일: regex.cs 프로젝트: RickOne16/or-tools
  /*
   * 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))));
    }

  }
예제 #22
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;
    }
예제 #23
0
    //
    // Partition the sets (binary matrix representation).
    //
    public static void partition_sets(Solver solver,
                                      IntVar[,] x, int num_sets, int n)
    {

      for(int i = 0; i <num_sets; i++) {
        for(int j = 0; j <num_sets; j++) {
          if (i != j) {
            // b = solver.Sum([x[i,k]*x[j,k] for k in range(n)]);
            // solver.Add(b == 0);
            solver.Add( (from k in Enumerable.Range(0, n)
                         select (x[i,k]*x[j,k])).
                        ToArray().Sum() == 0);
          }
        }
      }

      // ensure that all integers is in
      // (exactly) one partition
      solver.Add( (from i in Enumerable.Range(0, num_sets)
                   from j in Enumerable.Range(0, n)
                   select x[i,j]).ToArray().Sum() == n);
    }
예제 #24
0
  /**
   *
   * Subset sum problem.
   *
   * From Katta G. Murty: 'Optimization Models for Decision Making', page 340
   * http://ioe.engin.umich.edu/people/fac/books/murty/opti_model/junior-7.pdf
   * """
   * Example 7.8.1
   * 
   * A bank van had several bags of coins, each containing either
   * 16, 17, 23, 24, 39, or 40 coins. While the van was parked on the
   * street, thieves stole some bags. A total of 100 coins were lost.
   * It is required to find how many bags were stolen.
   * """
   *
   * Also see http://www.hakank.org/or-tools/subset_sum.py
   *
   */
  private static void Solve(int[] coins, int total)
  {

    Solver solver = new Solver("SubsetSum");

    int n = coins.Length;
    Console.Write("Coins: ");
    for(int i = 0; i < n; i++) {
      Console.Write(coins[i] + " ");
    }
    Console.WriteLine("\nTotal: {0}", total);

    //
    // Variables
    //
    // number of coins
    IntVar s = solver.MakeIntVar(0, coins.Sum(), "s");


    //
    // Constraints
    // 
    IntVar[] x = subset_sum(solver, coins, total);
    solver.Add(x.Sum() == s);


    //
    // 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(x[i].Value() + " ");
      }
      Console.WriteLine("  s: {0}", s.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();

  }
예제 #25
0
파일: xkcd.cs 프로젝트: RickOne16/or-tools
  /**
   *
   * 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();

  }
예제 #26
0
  static void MyContiguity(Solver solver, IntVar[] x) {

    // the DFA (for regular)
    int initial_state = 1;

    // all states are accepting states
    int[] accepting_states = {1,2,3};

    // The regular expression 0*1*0* {state, input, next state}
    int[,] transition_tuples = { {1, 0, 1},
                                 {1, 1, 2},
                                 {2, 0, 3},
                                 {2, 1, 2},
                                 {3, 0, 3} };

    IntTupleSet result = new IntTupleSet(3);
    result.InsertAll(transition_tuples);

    solver.Add(x.Transition(result,
                            initial_state,
                            accepting_states));
  }
예제 #27
0
  /**
   * circuit(solver, x, z)
   *
   * A decomposition of the global constraint circuit, based
   * on some observation of the orbits in an array.
   *
   * This version also exposes z (the path) to the public.
   *
   * 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, IntVar[] z) {

    int n = x.Length;

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

  }
예제 #28
0
파일: coins3.cs 프로젝트: njb0401/JobShop
    /**
     *
     * 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();
    }
예제 #29
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();
    }
예제 #30
0
        static void Main(string[] args)
        {
            InitTaskList();
            int taskCount = GetTaskCount();

            Solver solver = new Solver("ResourceConstraintScheduling");

            IntervalVar[] tasks       = new IntervalVar[taskCount];
            IntVar[]      taskChoosed = new IntVar[taskCount];
            IntVar[]      makeSpan    = new IntVar[GetEndTaskCount()];

            int endJobCounter = 0;

            foreach (Job j in myJobList)
            {
                IntVar[] tmp = new IntVar[j.AlternativeTasks.Count];
                int      i   = 0;
                foreach (Task t in j.AlternativeTasks)
                {
                    long ti = taskIndexes[t.Name];
                    taskChoosed[ti] = solver.MakeIntVar(0, 1, t.Name + "_choose");
                    tmp[i++]        = taskChoosed[ti];
                    tasks[ti]       = solver.MakeFixedDurationIntervalVar(
                        0, 100000, t.Duration, false, t.Name + "_interval");
                    if (j.Successor == null)
                    {
                        makeSpan[endJobCounter++] = tasks[ti].EndExpr().Var();
                    }
                    if (!tasksToEquipment.ContainsKey(t.Equipment))
                    {
                        tasksToEquipment[t.Equipment] = new List <IntervalVar>();
                    }
                    tasksToEquipment[t.Equipment].Add(tasks[ti]);
                }
                solver.Add(IntVarArrayHelper.Sum(tmp) == 1);
            }

            List <SequenceVar> all_seq = new List <SequenceVar>();

            foreach (KeyValuePair <long, List <IntervalVar> > pair in tasksToEquipment)
            {
                DisjunctiveConstraint dc = solver.MakeDisjunctiveConstraint(
                    pair.Value.ToArray(), pair.Key.ToString());
                solver.Add(dc);
                all_seq.Add(dc.SequenceVar());
            }

            IntVar      objective_var     = solver.MakeMax(makeSpan).Var();
            OptimizeVar objective_monitor = solver.MakeMinimize(objective_var, 1);

            DecisionBuilder sequence_phase =
                solver.MakePhase(all_seq.ToArray(), Solver.SEQUENCE_DEFAULT);
            DecisionBuilder objective_phase =
                solver.MakePhase(objective_var, Solver.CHOOSE_FIRST_UNBOUND,
                                 Solver.ASSIGN_MIN_VALUE);
            DecisionBuilder main_phase = solver.Compose(sequence_phase, objective_phase);

            const int     kLogFrequency = 1000000;
            SearchMonitor search_log    =
                solver.MakeSearchLog(kLogFrequency, objective_monitor);

            SolutionCollector collector = solver.MakeLastSolutionCollector();

            collector.Add(all_seq.ToArray());
            collector.AddObjective(objective_var);

            if (solver.Solve(main_phase, search_log, objective_monitor, null, collector))
            {
                Console.Out.WriteLine("Optimal solution = " + collector.ObjectiveValue(0));
            }
            else
            {
                Console.Out.WriteLine("No solution.");
            }
        }
예제 #31
0
        ///<summary>
        /// Adds a space object to the simulation.
        ///</summary>
        ///<param name="spaceObject">Space object to add.</param>
        public void Add(ISpaceObject spaceObject)
        {
            if (spaceObject.Space != null)
            {
                throw new ArgumentException("The object belongs to some Space already; cannot add it again.");
            }
            spaceObject.Space = this;

            SimulationIslandMember simulationIslandMember = spaceObject as SimulationIslandMember;

            if (simulationIslandMember != null)
            {
                DeactivationManager.Add(simulationIslandMember);
            }

            ISimulationIslandMemberOwner simulationIslandMemberOwner = spaceObject as ISimulationIslandMemberOwner;

            if (simulationIslandMemberOwner != null)
            {
                DeactivationManager.Add(simulationIslandMemberOwner.ActivityInformation);
            }

            //Go through each stage, adding the space object to it if necessary.
            IForceUpdateable velocityUpdateable = spaceObject as IForceUpdateable;

            if (velocityUpdateable != null)
            {
                ForceUpdater.Add(velocityUpdateable);
            }

            MobileCollidable boundingBoxUpdateable = spaceObject as MobileCollidable;

            if (boundingBoxUpdateable != null)
            {
                BoundingBoxUpdater.Add(boundingBoxUpdateable);
            }

            BroadPhaseEntry broadPhaseEntry = spaceObject as BroadPhaseEntry;

            if (broadPhaseEntry != null)
            {
                BroadPhase.Add(broadPhaseEntry);
            }

            //Entites own collision proxies, but are not entries themselves.
            IBroadPhaseEntryOwner broadPhaseEntryOwner = spaceObject as IBroadPhaseEntryOwner;

            if (broadPhaseEntryOwner != null)
            {
                BroadPhase.Add(broadPhaseEntryOwner.Entry);
                boundingBoxUpdateable = broadPhaseEntryOwner.Entry as MobileCollidable;
                if (boundingBoxUpdateable != null)
                {
                    BoundingBoxUpdater.Add(boundingBoxUpdateable);
                }
            }

            SolverUpdateable solverUpdateable = spaceObject as SolverUpdateable;

            if (solverUpdateable != null)
            {
                Solver.Add(solverUpdateable);
            }

            IPositionUpdateable integrable = spaceObject as IPositionUpdateable;

            if (integrable != null)
            {
                PositionUpdater.Add(integrable);
            }

            Entity entity = spaceObject as Entity;

            if (entity != null)
            {
                BufferedStates.Add(entity);
            }

            IDeferredEventCreator deferredEventCreator = spaceObject as IDeferredEventCreator;

            if (deferredEventCreator != null)
            {
                DeferredEventDispatcher.AddEventCreator(deferredEventCreator);
            }

            IDeferredEventCreatorOwner deferredEventCreatorOwner = spaceObject as IDeferredEventCreatorOwner;

            if (deferredEventCreatorOwner != null)
            {
                DeferredEventDispatcher.AddEventCreator(deferredEventCreatorOwner.EventCreator);
            }

            //Updateable stages.
            IDuringForcesUpdateable duringForcesUpdateable = spaceObject as IDuringForcesUpdateable;

            if (duringForcesUpdateable != null)
            {
                DuringForcesUpdateables.Add(duringForcesUpdateable);
            }

            IBeforeNarrowPhaseUpdateable beforeNarrowPhaseUpdateable = spaceObject as IBeforeNarrowPhaseUpdateable;

            if (beforeNarrowPhaseUpdateable != null)
            {
                BeforeNarrowPhaseUpdateables.Add(beforeNarrowPhaseUpdateable);
            }

            IBeforeSolverUpdateable beforeSolverUpdateable = spaceObject as IBeforeSolverUpdateable;

            if (beforeSolverUpdateable != null)
            {
                BeforeSolverUpdateables.Add(beforeSolverUpdateable);
            }

            IBeforePositionUpdateUpdateable beforePositionUpdateUpdateable = spaceObject as IBeforePositionUpdateUpdateable;

            if (beforePositionUpdateUpdateable != null)
            {
                BeforePositionUpdateUpdateables.Add(beforePositionUpdateUpdateable);
            }

            IEndOfTimeStepUpdateable endOfStepUpdateable = spaceObject as IEndOfTimeStepUpdateable;

            if (endOfStepUpdateable != null)
            {
                EndOfTimeStepUpdateables.Add(endOfStepUpdateable);
            }

            IEndOfFrameUpdateable endOfFrameUpdateable = spaceObject as IEndOfFrameUpdateable;

            if (endOfFrameUpdateable != null)
            {
                EndOfFrameUpdateables.Add(endOfFrameUpdateable);
            }

            spaceObject.OnAdditionToSpace(this);
        }
예제 #32
0
    /**
     *
     * Traffic lights problem.
     *
     * CSPLib problem 16
     * http://www.cs.st-andrews.ac.uk/~ianm/CSPLib/prob/prob016/index.html
     * """
     * Specification:
     * Consider a four way traffic junction with eight traffic lights. Four of the
     * traffic lights are for the vehicles and can be represented by the variables
     * V1 to V4 with domains {r,ry,g,y} (for red, red-yellow, green and yellow).
     * The other four traffic lights are for the pedestrians and can be
     * represented by the variables P1 to P4 with domains {r,g}.
     *
     * The constraints on these variables can be modelled by quaternary
     * constraints on (Vi, Pi, Vj, Pj ) for 1<=i<=4, j=(1+i)mod 4 which allow just
     * the tuples
     * {(r,r,g,g), (ry,r,y,r), (g,g,r,r), (y,r,ry,r)}.
     *
     * It would be interesting to consider other types of junction (e.g. five
     * roads intersecting) as well as modelling the evolution over time of the
     * traffic light sequence.
     * ...
     *
     * Results
     * Only 2^2 out of the 2^12 possible assignments are solutions.
     *
     * (V1,P1,V2,P2,V3,P3,V4,P4) =
     * {(r,r,g,g,r,r,g,g), (ry,r,y,r,ry,r,y,r), (g,g,r,r,g,g,r,r),
     * (y,r,ry,r,y,r,ry,r)}
     * [(1,1,3,3,1,1,3,3), ( 2,1,4,1, 2,1,4,1), (3,3,1,1,3,3,1,1), (4,1, 2,1,4,1,
     * 2,1)} The problem has relative few constraints, but each is very tight.
     * Local propagation appears to be rather ineffective on this problem.
     *
     * """
     * Note: In this model we use only the constraint
     *  solver.AllowedAssignments().
     *
     *
     * See http://www.hakank.org/or-tools/traffic_lights.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("TrafficLights");

        //
        // data
        //
        int n = 4;

        int r  = 0;
        int ry = 1;
        int g  = 2;
        int y  = 3;

        string[] lights = { "r", "ry", "g", "y" };

        // The allowed combinations
        IntTupleSet allowed = new IntTupleSet(4);

        allowed.InsertAll(new long[][] { new long[] { r, r, g, g }, new long[] { ry, r, y, r },
                                         new long[] { g, g, r, r }, new long[] { y, r, ry, r } });
        //
        // Decision variables
        //
        IntVar[] V = solver.MakeIntVarArray(n, 0, n - 1, "V");
        IntVar[] P = solver.MakeIntVarArray(n, 0, n - 1, "P");

        // for search
        IntVar[] VP = new IntVar[2 * n];
        for (int i = 0; i < n; i++)
        {
            VP[i]     = V[i];
            VP[i + n] = P[i];
        }

        //
        // Constraints
        //
        for (int i = 0; i < n; i++)
        {
            int      j   = (1 + i) % n;
            IntVar[] tmp = new IntVar[] { V[i], P[i], V[j], P[j] };
            solver.Add(tmp.AllowedAssignments(allowed));
        }

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

        solver.NewSearch(db);

        while (solver.NextSolution())
        {
            for (int i = 0; i < n; i++)
            {
                Console.Write("{0,2} {1,2} ", lights[V[i].Value()], lights[P[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();
    }
예제 #33
0
    /**
     *
     * Solves the Survo puzzle.
     * See http://www.hakank.org/or-tools/survo_puzzle.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("SurvoPuzzle");

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


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


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

        solver.Add(x_flat.AllDifferent());


        //
        // calculate rowsums and colsums
        //
        for (int i = 0; i < r; i++)
        {
            IntVar[] row = new IntVar[c];
            for (int j = 0; j < c; j++)
            {
                row[j] = x[i, j];
            }
            solver.Add(row.Sum() == rowsums[i]);
        }

        for (int j = 0; j < c; j++)
        {
            IntVar[] col = new IntVar[r];
            for (int i = 0; i < r; i++)
            {
                col[i] = x[i, j];
            }
            solver.Add(col.Sum() == colsums[j]);
        }


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

        solver.NewSearch(db);

        int sol = 0;

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

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

        solver.EndSearch();
    }
예제 #34
0
        public Sudoku.Core.Sudoku Solve(Sudoku.Core.Sudoku sudoku)
        {
            //Sudoku -> Tableau
            int[,] sudokuInGrid = new int[9, 9];

            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    sudokuInGrid[i, j] = sudoku.GetCell(i, j);
                }
            }

            Solver solver = new Solver("Sudoku");

            int cell_size          = 3;
            IEnumerable <int> CELL = Enumerable.Range(0, cell_size);
            int n = cell_size * cell_size;
            IEnumerable <int> RANGE = Enumerable.Range(0, n);

            //Création de la grille de solution
            IntVar[,] grid = solver.MakeIntVarMatrix(n, n, 1, 9, "grid");
            IntVar[] grid_flat = grid.Flatten();

            //Tableau -> Solver
            foreach (int i in RANGE)
            {
                foreach (int j in RANGE)
                {
                    if (sudokuInGrid[i, j] > 0)
                    {
                        solver.Add(grid[i, j] == sudokuInGrid[i, j]);
                    }
                }
            }

            //Un chiffre ne figure qu'une seule fois par ligne/colonne/cellule
            foreach (int i in RANGE)
            {
                // Lignes
                solver.Add((from j in RANGE
                            select grid[i, j]).ToArray().AllDifferent());

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

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

            //Début de la résolution
            DecisionBuilder db = solver.MakePhase(grid_flat,
                                                  Solver.INT_VAR_SIMPLE,
                                                  Solver.INT_VALUE_SIMPLE);

            solver.NewSearch(db);

            // Solver -> Liste
            var gridToSudoku = new List <int>();

            while (solver.NextSolution())
            {
                for (int i = 0; i < n; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        gridToSudoku.Add((int)grid[i, j].Value());
                    }
                }
            }
            solver.EndSearch();

            //Liste -> Sudoku
            return(new Sudoku.Core.Sudoku(gridToSudoku));
        }
예제 #35
0
    static void CpLoadModelAfterSearchTest()
    {
        CpModel expected;

        const string constraintName = "equation";
        const string constraintText = "((x(0..10) + y(0..10)) == 5)";

        // Make sure that resources are isolated in the using block.
        using (var s = new Solver("TestConstraint"))
        {
            var x = s.MakeIntVar(0, 10, "x");
            var y = s.MakeIntVar(0, 10, "y");
            Check(x.Name() == "x", "x variable name incorrect.");
            Check(y.Name() == "y", "y variable name incorrect.");
            var c = x + y == 5;
//      c.Cst.SetName(constraintName);
//      Check(c.Cst.Name() == constraintName, "Constraint name incorrect.");
            Check(c.Cst.ToString() == constraintText, "Constraint is incorrect.");
            s.Add(c);
            // TODO: TBD: support solution collector?
            var db = s.MakePhase(x, y, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);
            Check(!ReferenceEquals(null, db), "Expected a valid Decision Builder");
            s.NewSearch(db);
            var count = 0;
            while (s.NextSolution())
            {
                Console.WriteLine("x = {0}, y = {1}", x.Value(), y.Value());
                ++count;
                // Break after we found at least one solution.
                break;
            }
            s.EndSearch();
            Check(count > 0, "Must find at least one solution.");
            // TODO: TBD: export with monitors and/or decision builder?
            expected = s.ExportModel();
            Console.WriteLine("Expected model string after export: {0}", expected);
        }

        // While interesting, this is not very useful nor especially typical use case scenario.
        using (var s = new Solver("TestConstraint"))
        {
            // TODO: TBD: load with monitors and/or decision builder?
            s.LoadModel(expected);
            // This is the first test that should PASS when loading; however, it FAILS because the Constraint is NOT loaded as it is a "TrueConstraint()"
            Check(s.Constraints() == 1, "Incorrect number of constraints.");
            var actual = s.ExportModel();
            Console.WriteLine("Actual model string after load: {0}", actual);
            // Should also be correct after re-load, but I suspect isn't even close, but I could be wrong.
            Check(expected.ToString() == actual.ToString(), "Model string incorrect.");
            var loader = s.ModelLoader();
            var x      = loader.IntegerExpression(0).Var();
            var y      = loader.IntegerExpression(1).Var();
            Check(!ReferenceEquals(null, x), "x variable not found after loaded model.");
            Check(!ReferenceEquals(null, y), "y variable not found after loaded model.");
            {
                // Do this sanity check that what we loaded is actually what we expected should load.
                var c = x + y == 5;
                // Further documented verification, provided we got this far, and/or with "proper" unit test Assertions...
                Check(c.Cst.ToString() == constraintText, "Constraint is incorrect.");
                Check(c.Cst.ToString() != "TrueConstraint()", "Constraint is incorrect.");
            }
            // TODO: TBD: support solution collector?
            // Should pick up where we left off.
            var db = s.MakePhase(x, y, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);
            s.NewSearch(db);
            while (s.NextSolution())
            {
                Console.WriteLine("x = {0}, y = {1}", x.Value(), y.Value());
            }
            s.EndSearch();
        }
    }
        public void Solve(GrilleSudoku s)
        {
            //Création d'un solver Or-tools
            Solver solver = new Solver("Sudoku");

            //Création de la grille de variables
            //Variables de décision

            IntVar[,] grid = solver.MakeIntVarMatrix(9, 9, 1, 9, "grid"); //VERIFIER
            IntVar[] grid_flat = grid.Flatten();                          //VERIFIER


            //Masque de résolution
            for (int i = 0; i < cellIndices.Count(); i++)
            {
                for (int j = 0; j < cellIndices.Count(); j++)
                {
                    if (s.GetCellule(i, j) > 0)
                    {
                        solver.Add(grid[i, j] == s.GetCellule(i, j));
                    }
                }
            }

            //Un chiffre ne figure qu'une seule fois par ligne/colonne/cellule
            for (int i = 0; i < cellIndices.Count(); i++)
            {
                // Lignes
                solver.Add((from j in cellIndices
                            select grid[i, j]).ToArray().AllDifferent());

                // Colonnes
                solver.Add((from j in cellIndices
                            select grid[j, i]).ToArray().AllDifferent());
            }

            //Cellules
            for (int i = 0; i < CELL.Count(); i++)
            {
                for (int j = 0; j < CELL.Count(); j++)
                {
                    solver.Add((from di in CELL
                                from dj in CELL
                                select grid[i * cell_size + di, j * cell_size + dj]
                                ).ToArray().AllDifferent());
                }
            }

            //Début de la résolution
            DecisionBuilder db = solver.MakePhase(grid_flat,
                                                  Solver.INT_VAR_SIMPLE,
                                                  Solver.INT_VALUE_SIMPLE);

            solver.NewSearch(db);

            //Mise à jour du sudoku
            //int n = cell_size * cell_size;
            //Or on sait que cell_size = 3 -> voir ligne 13
            //Inspiré de l'exemple : taille des cellules identique
            while (solver.NextSolution())
            {
                for (int i = 0; i < 9; i++)
                {
                    for (int j = 0; j < 9; j++)
                    {
                        s.SetCell(i, j, (int)grid[i, j].Value());
                    }
                }
            }

            //Si 4 lignes dessus optionnelles, EndSearch est obligatoire
            solver.EndSearch();
        }
    /**
     *
     * Solves the divisible by 9 through 1 problem.
     * See http://www.hakank.org/google_or_tools/divisible_by_9_through_1.py
     *
     */
    private static void Solve(int bbase)
    {
        Solver solver = new Solver("DivisibleBy9Through1");

        int m = (int)Math.Pow(bbase, (bbase - 1)) - 1;
        int n = bbase - 1;

        String[] digits_str = { "_", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };

        Console.WriteLine("base: " + bbase);

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

        // the numbers. t[0] contains the answe
        IntVar[] t = solver.MakeIntVarArray(n, 0, m, "t");

        //
        // Constraints
        //

        solver.Add(x.AllDifferent());

        // Ensure the divisibility of base .. 1
        IntVar zero = solver.MakeIntConst(0);

        for (int i = 0; i < n; i++)
        {
            int      mm = bbase - i - 1;
            IntVar[] tt = new IntVar[mm];
            for (int j = 0; j < mm; j++)
            {
                tt[j] = x[j];
            }
            solver.Add(ToNum(tt, t[i], bbase));
            MyMod(solver, t[i], solver.MakeIntConst(mm), zero);
        }

        //
        // 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(x[i].Value() + " ");
            }
            Console.WriteLine("\nt: ");
            for (int i = 0; i < n; i++)
            {
                Console.Write(t[i].Value() + " ");
            }
            Console.WriteLine("\n");

            if (bbase != 10)
            {
                Console.Write("Number base 10: " + t[0].Value());
                Console.Write(" Base " + bbase + ": ");
                for (int i = 0; i < n; i++)
                {
                    Console.Write(digits_str[(int)x[i].Value() + 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();
    }
예제 #38
0
    /**
     *
     * Solves a set covering deployment problem.
     * See  See http://www.hakank.org/or-tools/set_covering_deployment.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("SetCoveringDeployment");

        //
        // data
        //

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

        int n = countries.Length;

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

        //
        // Decision variables
        //

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

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

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

        //
        // Constraints
        //

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

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

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

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

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

        solver.NewSearch(db, objective);

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

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

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

        solver.EndSearch();
    }
예제 #39
0
    /**
     *
     * Solves a set covering problem.
     * See  See http://www.hakank.org/or-tools/set_covering_opl.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("SetCoveringOPL");

        //
        // data
        //
        int num_workers = 32;
        int num_tasks   = 15;

        // Which worker is qualified for each task.
        // Note: This is 1-based and will be made 0-base below.
        int[][] qualified = { new int[] {  1,  9, 19, 22, 25, 28, 31 },
                              new int[] {  2, 12, 15, 19, 21, 23,27, 29, 30, 31, 32 },
                              new int[] {  3, 10, 19, 24, 26, 30, 32 },
                              new int[] {  4, 21, 25, 28,32 },
                              new int[] {  5, 11, 16, 22, 23, 27, 31 },
                              new int[] {  6, 20, 24, 26, 30,32 },
                              new int[] {  7, 12, 17, 25, 30,31 },
                              new int[] {  8, 17, 20, 22,23 },
                              new int[] {  9, 13, 14, 26, 29, 30, 31 },
                              new int[] { 10, 21, 25, 31,32 },
                              new int[] { 14, 15, 18, 23, 24, 27,30, 32 },
                              new int[] { 18, 19, 22, 24, 26, 29, 31 },
                              new int[] { 11, 20, 25, 28, 30,32 },
                              new int[] { 16, 19, 23,31 },
                              new int[] {  9, 18, 26, 28, 31, 32 } };

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

        //
        // Decision variables
        //
        IntVar[] hire       = solver.MakeIntVarArray(num_workers, 0, 1, "workers");
        IntVar   total_cost = hire.ScalProd(cost).Var();

        //
        // Constraints
        //

        for (int j = 0; j < num_tasks; j++)
        {
            // Sum the cost for hiring the qualified workers
            // (also, make 0-base).
            int      len = qualified[j].Length;
            IntVar[] tmp = new IntVar[len];
            for (int c = 0; c < len; c++)
            {
                tmp[c] = hire[qualified[j][c] - 1];
            }
            solver.Add(tmp.Sum() >= 1);
        }

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

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

        solver.NewSearch(db, objective);

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

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

        solver.EndSearch();
    }
예제 #40
0
    /**
     *
     * Futoshiki problem.
     *
     * From http://en.wikipedia.org/wiki/Futoshiki
     * """
     * The puzzle is played on a square grid, such as 5 x 5. The objective
     * is to place the numbers 1 to 5 (or whatever the dimensions are)
     * such that each row, and column contains each of the digits 1 to 5.
     * Some digits may be given at the start. In addition, inequality
     * constraints are also initially specifed between some of the squares,
     * such that one must be higher or lower than its neighbour. These
     * constraints must be honoured as the grid is filled out.
     * """
     *
     * Also see http://www.hakank.org/or-tools/futoshiki.py
     *
     */
    private static void Solve(int[,] values, int[,] lt)
    {
        Solver solver = new Solver("Futoshiki");

        int size = values.GetLength(0);
        IEnumerable <int> RANGE = Enumerable.Range(0, size);
        IEnumerable <int> NUMQD = Enumerable.Range(0, lt.GetLength(0));

        //
        // Decision variables
        //
        IntVar[,] field = solver.MakeIntVarMatrix(size, size, 1, size, "field");
        IntVar[] field_flat = field.Flatten();

        //
        // Constraints
        //

        // set initial values
        foreach (int row in RANGE)
        {
            foreach (int col in RANGE)
            {
                if (values[row, col] > 0)
                {
                    solver.Add(field[row, col] == values[row, col]);
                }
            }
        }

        // all rows have to be different
        foreach (int row in RANGE)
        {
            solver.Add((from col in RANGE select field[row, col]).ToArray().AllDifferent());
        }

        // all columns have to be different
        foreach (int col in RANGE)
        {
            solver.Add((from row in RANGE select field[row, col]).ToArray().AllDifferent());
        }

        // all < constraints are satisfied
        // Also: make 0-based
        foreach (int i in NUMQD)
        {
            solver.Add(field[lt[i, 0] - 1, lt[i, 1] - 1] < field[lt[i, 2] - 1, lt[i, 3] - 1]);
        }

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

        solver.NewSearch(db);

        while (solver.NextSolution())
        {
            foreach (int i in RANGE)
            {
                foreach (int j in RANGE)
                {
                    Console.Write("{0} ", field[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();
    }
예제 #41
0
    /**
     *
     * Moving furnitures (scheduling) problem in Google CP Solver.
     *
     * Marriott & Stukey: 'Programming with constraints', page  112f
     *
     * Also see http://www.hakank.org/or-tools/furniture_moving.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("FurnitureMovingIntervals");

        const int n = 4;

        int[]     durations       = { 30, 10, 15, 15 };
        int[]     demand          = { 3, 1, 3, 2 };
        const int upper_limit     = 160;
        const int max_num_workers = 5;

        //
        // Decision variables
        //
        IntervalVar[] tasks = new IntervalVar[n];
        for (int i = 0; i < n; ++i)
        {
            tasks[i] = solver.MakeFixedDurationIntervalVar(0,
                                                           upper_limit - durations[i],
                                                           durations[i],
                                                           false,
                                                           "task_" + i);
        }

        // Fillers that span the whole resource and limit the available
        // number of workers.
        IntervalVar[] fillers = new IntervalVar[max_num_workers];
        for (int i = 0; i < max_num_workers; ++i)
        {
            fillers[i] = solver.MakeFixedDurationIntervalVar(0,
                                                             0,
                                                             upper_limit,
                                                             true,
                                                             "filler_" + i);
        }

        // Number of needed resources, to be minimized or constrained.
        IntVar num_workers = solver.MakeIntVar(0, max_num_workers, "num_workers");

        // Links fillers and num_workers.
        for (int i = 0; i < max_num_workers; ++i)
        {
            solver.Add((num_workers > i) + fillers[i].PerformedExpr() == 1);
        }

        // Creates makespan.
        IntVar[] ends = new IntVar[n];
        for (int i = 0; i < n; ++i)
        {
            ends[i] = tasks[i].EndExpr().Var();
        }
        IntVar end_time = ends.Max().VarWithName("end_time");

        //
        // Constraints
        //
        IntervalVar[] all_tasks   = new IntervalVar[n + max_num_workers];
        int[]         all_demands = new int[n + max_num_workers];
        for (int i = 0; i < n; ++i)
        {
            all_tasks[i]   = tasks[i];
            all_demands[i] = demand[i];
        }
        for (int i = 0; i < max_num_workers; ++i)
        {
            all_tasks[i + n]   = fillers[i];
            all_demands[i + n] = 1;
        }
        solver.Add(all_tasks.Cumulative(all_demands, max_num_workers, "workers"));

        //
        // 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(tasks[i].StartAt(0));
        // }


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

        //
        // Objective
        //

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

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(all_tasks, Solver.INTERVAL_DEFAULT);

        solver.NewSearch(db, obj);

        while (solver.NextSolution())
        {
            Console.WriteLine(num_workers.ToString() + ", " + end_time.ToString());
            for (int i = 0; i < n; i++)
            {
                Console.WriteLine("{0} (demand:{1})", tasks[i].ToString(), demand[i]);
            }
            Console.WriteLine();
        }

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

        solver.EndSearch();
    }
        /*
         * Main Method:
         */

        public static void Solve(Tuple <int, int[], int[], string[]> input)
        {
            var solver = new Solver("Knapsack");

            // Total capacity:
            int capacity = input.Item1;

            // Weights and prices for each item:
            int[] weights = input.Item2;
            int[] prices  = input.Item3;

            // Item names for pretty printing:
            string[] names = input.Item4;

            IntVar[] items = solver.MakeIntVarArray(names.Length, 0, capacity);

            /*
             * Constraints:
             */

            solver.Add(solver.MakeScalProd(items, weights) <= capacity);

            /*
             * Objective Function:
             */

            IntVar obj = solver.MakeScalProd(items, prices).Var();

            /*
             * Start Solver:
             */

            DecisionBuilder db = solver.MakePhase(items, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE);

            SolutionCollector col = solver.MakeBestValueSolutionCollector(true);

            col.AddObjective(obj);
            col.Add(items);

            Console.WriteLine("Knapsack Problem:\n");

            if (solver.Solve(db, col))
            {
                Assignment sol = col.Solution(0);
                Console.WriteLine("Maximum value found: " + sol.ObjectiveValue() + "\n");

                for (int i = 0; i < items.Length; i++)
                {
                    Console.WriteLine("Item " + names[i] + " is smuggled " + sol.Value(items[i]) + " time(s).");
                }

                Console.WriteLine();
            }

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

            Console.ReadKey();
        }
예제 #43
0
파일: p_median.cs 프로젝트: njb0401/JobShop
    /**
     *
     * 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();
    }
예제 #44
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();
    }
예제 #45
0
    /**
     *
     * Photo problem.
     *
     * Problem statement from Mozart/Oz tutorial:
     * http://www.mozart-oz.org/home/doc/fdt/node37.html#section.reified.photo
     * """
     * Betty, Chris, Donald, Fred, Gary, Mary, and Paul want to align in one
     * row for taking a photo. Some of them have preferences next to whom
     * they want to stand:
     *
     *  1. Betty wants to stand next to Gary and Mary.
     *  2. Chris wants to stand next to Betty and Gary.
     * 3. Fred wants to stand next to Mary and Donald.
     * 4. Paul wants to stand next to Fred and Donald.
     *
     * Obviously, it is impossible to satisfy all preferences. Can you find
     * an alignment that maximizes the number of satisfied preferences?
     * """
     *
     *  Oz solution:
     *     6 # alignment(betty:5  chris:6  donald:1  fred:3  gary:7   mary:4
     * paul:2) [5, 6, 1, 3, 7, 4, 2]
     *
     *
     * Also see http://www.hakank.org/or-tools/photo_problem.py
     *
     */
    private static void Solve(int show_all_max = 0)
    {
        Solver solver = new Solver("PhotoProblem");

        //
        // Data
        //
        String[]          persons = { "Betty", "Chris", "Donald", "Fred", "Gary", "Mary", "Paul" };
        int               n       = persons.Length;
        IEnumerable <int> RANGE   = Enumerable.Range(0, n);

        int[,] preferences =
        {
            // 0 1 2 3 4 5 6
            // B C D F G M P
            { 0, 0, 0, 0, 1, 1, 0 }, // Betty  0
            { 1, 0, 0, 0, 1, 0, 0 }, // Chris  1
            { 0, 0, 0, 0, 0, 0, 0 }, // Donald 2
            { 0, 0, 1, 0, 0, 1, 0 }, // Fred   3
            { 0, 0, 0, 0, 0, 0, 0 }, // Gary   4
            { 0, 0, 0, 0, 0, 0, 0 }, // Mary   5
            { 0, 0, 1, 1, 0, 0, 0 }  // Paul   6
        };

        Console.WriteLine("Preferences:");
        Console.WriteLine("1. Betty wants to stand next to Gary and Mary.");
        Console.WriteLine("2. Chris wants to stand next to Betty and Gary.");
        Console.WriteLine("3. Fred wants to stand next to Mary and Donald.");
        Console.WriteLine("4. Paul wants to stand next to Fred and Donald.\n");

        //
        // Decision variables
        //
        IntVar[] positions = solver.MakeIntVarArray(n, 0, n - 1, "positions");
        // successful preferences (to Maximize)
        IntVar z = solver.MakeIntVar(0, n * n, "z");

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

        // calculate all the successful preferences
        solver.Add((from i in RANGE from j in RANGE where preferences[i, j] ==
                    1 select(positions[i] - positions[j]).Abs() == 1)
                   .ToArray()
                   .Sum() == z);

        //
        // Symmetry breaking (from the Oz page):
        //    Fred is somewhere left of Betty
        solver.Add(positions[3] < positions[0]);

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

        if (show_all_max > 0)
        {
            Console.WriteLine("Showing all maximum solutions (z == 6).\n");
            solver.Add(z == 6);
        }

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(positions, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MAX_VALUE);

        solver.NewSearch(db, obj);

        while (solver.NextSolution())
        {
            Console.WriteLine("z: {0}", z.Value());
            int[] p = new int[n];
            Console.Write("p: ");
            for (int i = 0; i < n; i++)
            {
                p[i] = (int)positions[i].Value();
                Console.Write(p[i] + " ");
            }
            Console.WriteLine();
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    if (p[j] == i)
                    {
                        Console.Write(persons[j] + " ");
                    }
                }
            }
            Console.WriteLine();
            Console.WriteLine("Successful preferences:");
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    if (preferences[i, j] == 1 && Math.Abs(p[i] - p[j]) == 1)
                    {
                        Console.WriteLine("\t{0} {1}", persons[i], persons[j]);
                    }
                }
            }
            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();
    }
예제 #46
0
 ///<summary>
 /// Enqueues a solver updateable created by some pair for flushing into the solver later.
 ///</summary>
 ///<param name="addedItem">Updateable to add.</param>
 public void NotifyUpdateableAdded(SolverUpdateable addedItem)
 {
     Solver.Add(addedItem);
 }
예제 #47
0
    /**
     *
     * Secret Santa problem II in Google CP Solver.
     *
     * From Maple Primes: 'Secret Santa Graph Theory'
     * http://www.mapleprimes.com/blog/jpmay/secretsantagraphtheory
     * """
     * Every year my extended family does a 'secret santa' gift exchange.
     * Each person draws another person at random and then gets a gift for
     * them. At first, none of my siblings were married, and so the draw was
     * completely random. Then, as people got married, we added the restriction
     * that spouses should not draw each others names. This restriction meant
     * that we moved from using slips of paper on a hat to using a simple
     * computer program to choose names. Then people began to complain when
     * they would get the same person two years in a row, so the program was
     * modified to keep some history and avoid giving anyone a name in their
     * recent history. This year, not everyone was participating, and so after
     * removing names, and limiting the number of exclusions to four per person,
     * I had data something like this:
     *
     * Name: Spouse, Recent Picks
     *
     * Noah: Ava. Ella, Evan, Ryan, John
     * Ava: Noah, Evan, Mia, John, Ryan
     * Ryan: Mia, Ella, Ava, Lily, Evan
     * Mia: Ryan, Ava, Ella, Lily, Evan
     * Ella: John, Lily, Evan, Mia, Ava
     * John: Ella, Noah, Lily, Ryan, Ava
     * Lily: Evan, John, Mia, Ava, Ella
     * Evan: Lily, Mia, John, Ryan, Noah
     * """
     *
     *  Note: I interpret this as the following three constraints:
     * 1) One cannot be a Secret Santa of one's spouse
     * 2) One cannot be a Secret Santa for somebody two years in a row
     * 3) Optimization: maximize the time since the last time
     *
     *  This model also handle single persons, something the original
     *  problem don't mention.
     *
     *
     * Also see http://www.hakank.org/or-tools/secret_santa2.py
     *
     */
    private static void Solve(int single = 0)
    {
        Solver solver = new Solver("SecretSanta2");

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

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

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

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

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

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

        int n = n_no_single;

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

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

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

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

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

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

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

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

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

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

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

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

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

        solver.NewSearch(db, obj);

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

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

        solver.EndSearch();
    }
예제 #48
0
    /**
     * Volsay problem.
     *
     * From the OPL model volsay.mod.
     * This version use arrays and matrices
     *
     * Also see
     *  http://www.hakank.org/or-tools/volsay2.cs
     *  http://www.hakank.org/or-tools/volsay3.py
     */
    private static void Solve()
    {
        Solver solver = new Solver("Volsay3",
                                   Solver.CLP_LINEAR_PROGRAMMING);

        int num_products           = 2;
        IEnumerable <int> PRODUCTS = Enumerable.Range(0, num_products);

        String[] products   = { "Gas", "Chloride" };
        String[] components = { "nitrogen", "hydrogen", "chlorine" };

        int[,] demand = { { 1, 3, 0 }, { 1, 4, 1 } };
        int[] profit = { 30, 40 };
        int[] stock  = { 50, 180, 40 };

        //
        // Variables
        //
        Variable[] production = new Variable[num_products];
        foreach (int p in PRODUCTS)
        {
            production[p] = solver.MakeNumVar(0, 100000, products[p]);
        }

        //
        // Constraints
        //
        int c_len = components.Length;

        Constraint[] cons = new Constraint[c_len];
        for (int c = 0; c < c_len; c++)
        {
            cons[c] = solver.Add((from p in PRODUCTS
                                  select(demand[p, c] * production[p])).
                                 ToArray().Sum() <= stock[c]);
        }

        //
        // Objective
        //
        solver.Maximize((from p in PRODUCTS
                         select(profit[p] * production[p])).
                        ToArray().Sum()
                        );

        if (solver.Solve() != Solver.OPTIMAL)
        {
            Console.WriteLine("The problem don't have an optimal solution.");
            return;
        }

        Console.WriteLine("Objective: {0}", solver.Objective().Value());
        foreach (int p in PRODUCTS)
        {
            Console.WriteLine("{0,-10}: {1} ReducedCost: {2}",
                              products[p],
                              production[p].SolutionValue(),
                              production[p].ReducedCost());
        }

        double[] activities = solver.ComputeConstraintActivities();
        for (int c = 0; c < c_len; c++)
        {
            Console.WriteLine("Constraint {0} DualValue {1} Activity: {2} lb: {3} ub: {4}",
                              c,
                              cons[c].DualValue(),
                              activities[cons[c].Index()],
                              cons[c].Lb(),
                              cons[c].Ub());
        }

        Console.WriteLine("\nWallTime: " + solver.WallTime());
        Console.WriteLine("Iterations: " + solver.Iterations());
    }
예제 #49
0
파일: Coloring.cs 프로젝트: krrli/AISO
        /*
         * Create Optimization Model and Solve Coloring Problem:
         */

        public static void SolveAsOptimizationProblem(int nbNodes, IEnumerable <Tuple <int, int> > edges)
        {
            var solver = new Solver("Coloring");

            // The colors for each node:
            IntVar[] nodes = solver.MakeIntVarArray(nbNodes, 0, nbNodes - 1);

            foreach (var edge in edges)
            {
                solver.Add(nodes[edge.Item1] != nodes[edge.Item2]);
            }

            // Some Symmetry breaking
            solver.Add(nodes[0] == 0);

            // The number of times each color is used:
            IntVar[] colors = solver.MakeIntVarArray(nbNodes, 0, nbNodes - 1);

            for (int i = 0; i < colors.Length; i++)
            {
                solver.Add(solver.MakeCount(nodes, i, colors[i]));
            }

            // Objective function = number of colors used:
            IntVar obj = solver.MakeSum((from j in colors select(j > 0).Var()).ToArray()).Var();

            /*
             * Start Solver:
             */

            DecisionBuilder db = solver.MakePhase(nodes, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE);

            // Remember only the best solution found:
            SolutionCollector collector = solver.MakeBestValueSolutionCollector(false);

            collector.AddObjective(obj);

            // What to remember in addition to the objective function value:
            collector.Add(nodes);

            Console.WriteLine("Coloring Problem:\n");

            if (solver.Solve(db, collector))
            {
                // Extract best solution found:
                Assignment sol = collector.Solution(0);

                Console.WriteLine("Solution found with " + sol.ObjectiveValue() + " colors.\n");

                for (int i = 0; i < nodes.Length; i++)
                {
                    long v = sol.Value(nodes[i]);

                    if (i < Names.Length)
                    {
                        Console.WriteLine("Nodes " + i + " obtains color " + Names.GetValue(v));
                    }
                    else
                    {
                        Console.WriteLine("Nodes " + i + " obtains color " + v);
                    }
                }

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

            Console.ReadKey();
        }
예제 #50
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();

  }
예제 #51
0
        public void doWork()
        {
            if (this.size % 2 == 0 && this.size > 3)
            {
                Solver solver = new Solver("Binoxxo");

                // n x n Matrix
                IntVar[,] board = solver.MakeIntVarMatrix(this.size, this.size, 0, 1);

                // Handy C# LINQ type for sequences:
                IEnumerable <int> RANGE = Enumerable.Range(0, this.size);

                // Each row and each column should have an equal amount of X and O's:
                foreach (int i in RANGE)
                {
                    // Row
                    solver.Add((from j in RANGE select board[i, j]).ToArray().Sum() == (this.size / 2));

                    // Column
                    solver.Add((from j in RANGE select board[j, i]).ToArray().Sum() == (this.size / 2));
                }

                // Each row and column should be different: (Yes! Shit is working....)
                foreach (int i in RANGE)
                {
                    for (int x = i + 1; x < this.size; x++)
                    {
                        // Rows:
                        solver.Add(
                            (from j in RANGE select board[i, j] * (int)Math.Pow(2, j)).ToArray().Sum() !=
                            (from j in RANGE select board[x, j] * (int)Math.Pow(2, j)).ToArray().Sum()
                            );

                        // Columns:
                        solver.Add(
                            (from j in RANGE select board[j, i] * (int)Math.Pow(2, j)).ToArray().Sum() !=
                            (from j in RANGE select board[j, x] * (int)Math.Pow(2, j)).ToArray().Sum()
                            );
                    }
                    ;
                }

                // Max two cells next to each other should have the same value (This shit is working too!)
                IEnumerable <int> GROUP_START = Enumerable.Range(0, this.size - 2);
                IEnumerable <int> GROUP       = Enumerable.Range(0, 3);
                foreach (int x in RANGE)
                {
                    foreach (int y in GROUP_START)
                    {
                        // Rows:
                        solver.Add((from j in GROUP select board[x, y + j]).ToArray().Sum() > 0);
                        solver.Add((from j in GROUP select board[x, y + j]).ToArray().Sum() < 3);

                        // Columns:
                        solver.Add((from j in GROUP select board[y + j, x]).ToArray().Sum() > 0);
                        solver.Add((from j in GROUP select board[y + j, x]).ToArray().Sum() < 3);
                    }
                }

                DecisionBuilder db = solver.MakePhase(
                    board.Flatten(),
                    Solver.INT_VAR_SIMPLE,
                    Solver.INT_VALUE_SIMPLE);

                solver.NewSearch(db);

                // Calculate first result for this solution
                // If more solutions are necessary, you can extend this part with a while(...)-Loop
                if (solver.NextSolution())
                {
                    printSquare(board);
                }

                solver.EndSearch();

                if (solver.Solutions() == 0)
                {
                    Console.WriteLine("No possible solution was found for the given Binoxxo! :-(");
                }
            }
            else
            {
                Console.WriteLine("Given size of {0} not allowed! Must be multiple of 2!", this.size);
            }
        }
예제 #52
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();

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

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

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

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

        //
        // Constraints
        //

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

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

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

        solver.NewSearch(db);

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

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

        solver.EndSearch();
    }
예제 #54
0
    /**
     *
     * Langford number problem.
     * See http://www.hakank.org/or-tools/langford.py
     *
     */
    private static void Solve(int k = 8, int num_sol = 0)
    {
        Solver solver = new Solver("Langford");

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

        //
        // data
        //
        int p = 2 * k;

        //
        // Decision variables
        //
        IntVar[] position = solver.MakeIntVarArray(p, 0, p - 1, "position");
        IntVar[] solution = solver.MakeIntVarArray(p, 1, k, "solution");

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

        for (int i = 1; i <= k; i++)
        {
            solver.Add(position[i + k - 1] - (position[i - 1] + solver.MakeIntVar(i + 1, i + 1)) == 0);
            solver.Add(solution.Element(position[i - 1]) == i);
            solver.Add(solution.Element(position[k + i - 1]) == i);
        }

        // Symmetry breaking
        solver.Add(solution[0] < solution[2 * k - 1]);

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

        solver.NewSearch(db);

        int num_solutions = 0;

        while (solver.NextSolution())
        {
            Console.Write("solution : ");
            for (int i = 0; i < p; i++)
            {
                Console.Write(solution[i].Value() + " ");
            }
            Console.WriteLine();
            num_solutions++;
            if (num_sol > 0 && num_solutions >= num_sol)
            {
                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();
    }
예제 #55
0
    /**
     *
     * Fill-a-Pix problem
     *
     * From http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/basiclogic
     * """
     * Each puzzle consists of a grid containing clues in various places. The
     * object is to reveal a hidden picture by painting the squares around each
     * clue so that the number of painted squares, including the square with
     * the clue, matches the value of the clue.
     * """
     *
     * http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/rules
     * """
     * Fill-a-Pix is a Minesweeper-like puzzle based on a grid with a pixilated
     * picture hidden inside. Using logic alone, the solver determines which
     * squares are painted and which should remain empty until the hidden picture
     * is completely exposed.
     * """
     *
     * Fill-a-pix History:
     * http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/history
     *
     * Also see http://www.hakank.org/google_or_tools/fill_a_pix.py
     *
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("FillAPix");

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

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


        //
        // Decision variables
        //
        IntVar[,] pict = solver.MakeIntVarMatrix(n, n, 0, 1, "pict");
        IntVar[] pict_flat = pict.Flatten(); // for branching

        //
        // Constraints
        //
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (puzzle[i, j] > X)
                {
                    // this cell is the sum of all surrounding cells
                    var tmp = from a in S from b in S where
                              i + a >= 0 &&
                              j + b >= 0 &&
                              i + a < n &&
                              j + b < n
                              select(pict[i + a, j + b]);

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


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

        solver.NewSearch(db);

        int sol = 0;

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

            Console.WriteLine();
        }

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

        solver.EndSearch();
    }
예제 #56
0
    private static void RunLinearProgrammingExampleNaturalApi(String solverType, bool printModel)
    {
        Console.WriteLine($"---- Linear programming example (Natural API) with {solverType} ----");

        Solver solver = Solver.CreateSolver(solverType);

        if (solver == null)
        {
            Console.WriteLine("Could not create solver " + solverType);
            return;
        }
        // x1, x2 and x3 are continuous non-negative variables.
        Variable x1 = solver.MakeNumVar(0.0, double.PositiveInfinity, "x1");
        Variable x2 = solver.MakeNumVar(0.0, double.PositiveInfinity, "x2");
        Variable x3 = solver.MakeNumVar(0.0, double.PositiveInfinity, "x3");

        solver.Maximize(10 * x1 + 6 * x2 + 4 * x3);
        Constraint c0 = solver.Add(x1 + x2 + x3 <= 100);
        Constraint c1 = solver.Add(10 * x1 + x2 * 4 + 5 * x3 <= 600);
        Constraint c2 = solver.Add(2 * x1 + 2 * x2 + 6 * x3 <= 300);

        Console.WriteLine("Number of variables = " + solver.NumVariables());
        Console.WriteLine("Number of constraints = " + solver.NumConstraints());

        if (printModel)
        {
            string model = solver.ExportModelAsLpFormat(false);
            Console.WriteLine(model);
        }

        Solver.ResultStatus resultStatus = solver.Solve();

        // Check that the problem has an optimal solution.
        if (resultStatus != Solver.ResultStatus.OPTIMAL)
        {
            Console.WriteLine("The problem does not have an optimal solution!");
            return;
        }

        Console.WriteLine("Problem solved in " + solver.WallTime() + " milliseconds");

        // The objective value of the solution.
        Console.WriteLine("Optimal objective value = " + solver.Objective().Value());

        // The value of each variable in the solution.
        Console.WriteLine("x1 = " + x1.SolutionValue());
        Console.WriteLine("x2 = " + x2.SolutionValue());
        Console.WriteLine("x3 = " + x3.SolutionValue());

        Console.WriteLine("Advanced usage:");
        double[] activities = solver.ComputeConstraintActivities();
        Console.WriteLine("Problem solved in " + solver.Iterations() + " iterations");
        Console.WriteLine("x1: reduced cost = " + x1.ReducedCost());
        Console.WriteLine("x2: reduced cost = " + x2.ReducedCost());
        Console.WriteLine("x3: reduced cost = " + x3.ReducedCost());
        Console.WriteLine("c0: dual value = " + c0.DualValue());
        Console.WriteLine("    activity = " + activities[c0.Index()]);
        Console.WriteLine("c1: dual value = " + c1.DualValue());
        Console.WriteLine("    activity = " + activities[c1.Index()]);
        Console.WriteLine("c2: dual value = " + c2.DualValue());
        Console.WriteLine("    activity = " + activities[c2.Index()]);
    }
예제 #57
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();

  }
        /*
         * Create Model:
         */

        public static void Solve()
        {
            var solver = new Solver("Nurse Scheduling");

            // The total number of nurses: 4 with values {0, ..., 3}
            int num_nurses = 4;

            // The number of shifts per day: 4 with values {0, ..., 3}
            // 3x 8h, shift = 0 means not working that day
            int num_shifts = 4;

            // The number of days: 7 with values {0 ... 6}
            int num_days = 7;

            // nurse[i, j] = k means nurse k works in shift i on day j
            IntVar[,] nurse = solver.MakeIntVarMatrix(num_shifts, num_days, 0, num_nurses - 1);

            /*
             * A nurse must not work two shifts on the same day:
             */

            for (int j = 0; j < num_days; j++)
            {
                // Cells in the same nurse table column must have different values
                solver.Add(solver.MakeAllDifferent((from k in Enumerable.Range(0, num_shifts) select nurse[k, j]).ToArray()));
            }

            /*
             * Auxiliary decision variables: How many days does nurse k work in shift i
             */

            IntVar[,] days = new IntVar[num_nurses, num_shifts];

            for (int k = 0; k < num_nurses; k++)
            {
                for (int i = 0; i < num_shifts; i++)
                {
                    days[k, i] = ((from j in Enumerable.Range(0, num_days) select nurse[i, j] == k).ToArray()).Sum().Var();
                }
            }

            /*
             * Each nurse has at most 2 days off
             */

            for (int k = 0; k < num_nurses; k++)
            {
                // Less than 3 days off per week
                solver.Add(days[k, 0] < 3);

                // At least one day off per week
                solver.Add(days[k, 0] > 0);
            }

            /*
             * Work and Holiday = 7 days (this is actually redundant)
             */

            /*for (int k = 0; k < num_nurses; k++)
             * {
             *
             *  solver.Add(((from i in Enumerable.Range(0, num_shifts) select days[k, i]).ToArray()).Sum() == 7);
             *
             * }
             *
             * /*
             * Shifts are staffed by at most two nurses per week:
             * Excluse shif 0 (i.e. days off)
             */

            for (int i = 1; i < num_shifts; i++)
            {
                solver.Add(((from k in Enumerable.Range(0, num_nurses) select days[k, i] > 0).ToArray()).Sum() <= 2);
            }

            /*
             * Nurses work shift 2 or 3 on consecutive days
             *
             * Examples:
             *  nurses[2, 1] == nurses[2, 2] is true if the same nurse works shift 2 on Monday and Tuesday
             *  nurses[2, 2] == nurses[2, 3] is True if the same nurse works shift 2 on Tuesday or Wednesday
             *  => at least one of the two cases must hold
             */

            solver.Add(solver.MakeMax(nurse[2, 0] == nurse[2, 1], nurse[2, 1] == nurse[2, 2]) == 1);
            solver.Add(solver.MakeMax(nurse[2, 1] == nurse[2, 2], nurse[2, 2] == nurse[2, 3]) == 1);
            solver.Add(solver.MakeMax(nurse[2, 2] == nurse[2, 3], nurse[2, 3] == nurse[2, 4]) == 1);
            solver.Add(solver.MakeMax(nurse[2, 3] == nurse[2, 4], nurse[2, 4] == nurse[2, 5]) == 1);
            solver.Add(solver.MakeMax(nurse[2, 4] == nurse[2, 5], nurse[2, 5] == nurse[2, 6]) == 1);
            solver.Add(solver.MakeMax(nurse[2, 5] == nurse[2, 6], nurse[2, 6] == nurse[2, 0]) == 1);
            solver.Add(solver.MakeMax(nurse[2, 6] == nurse[2, 0], nurse[2, 0] == nurse[2, 1]) == 1);

            solver.Add(solver.MakeMax(nurse[3, 0] == nurse[3, 1], nurse[3, 1] == nurse[3, 2]) == 1);
            solver.Add(solver.MakeMax(nurse[3, 1] == nurse[3, 2], nurse[3, 2] == nurse[3, 3]) == 1);
            solver.Add(solver.MakeMax(nurse[3, 2] == nurse[3, 3], nurse[3, 3] == nurse[3, 4]) == 1);
            solver.Add(solver.MakeMax(nurse[3, 3] == nurse[3, 4], nurse[3, 4] == nurse[3, 5]) == 1);
            solver.Add(solver.MakeMax(nurse[3, 4] == nurse[3, 5], nurse[3, 5] == nurse[3, 6]) == 1);
            solver.Add(solver.MakeMax(nurse[3, 5] == nurse[3, 6], nurse[3, 6] == nurse[3, 0]) == 1);
            solver.Add(solver.MakeMax(nurse[3, 6] == nurse[3, 0], nurse[3, 0] == nurse[3, 1]) == 1);

            var all = nurse.Flatten().Concat(days.Flatten()).ToArray();

            /*
             * Start solver
             */

            DecisionBuilder db = solver.MakePhase(all, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE);

            Console.WriteLine("Nurse Scheduling:\n");
            int counter = 0;

            solver.NewSearch(db);

            while (solver.NextSolution() && counter < 2)
            {
                /*Console.WriteLine("Shift x Day -> Nurse\n");
                 * PrintSolution(nurse, (from i in Enumerable.Range(0, num_shifts) select "Shift "+i).ToArray(), new String[] {"M", "D", "M", "D", "F", "S", "S"});
                 * Console.WriteLine("\nNurse x Shift -> Days\n");
                 * PrintSolution(days, (from i in Enumerable.Range(0, num_nurses) select "Nurse " + i).ToArray(), (from i in Enumerable.Range(0, num_shifts) select i+"").ToArray());
                 * Console.WriteLine();
                 * counter++;*/
            }

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

            solver.EndSearch();

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

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

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

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

        //
        // Decision variables
        //

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

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

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

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

        solver.NewSearch(db);

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

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

        solver.EndSearch();
    }
예제 #60
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();
    }