예제 #1
0
 public IntVar[] MakeBoolVarArray(int count) {
   IntVar[] array = new IntVar[count];
   for (int i = 0; i < count; ++i) {
     array[i] = MakeBoolVar();
   }
   return array;
 }
예제 #2
0
 public IntVar[] MakeIntVarArray(int count, long min, long max) {
   IntVar[] array = new IntVar[count];
   for (int i = 0; i < count; ++i) {
     array[i] = MakeIntVar(min, max);
   }
   return array;
 }
예제 #3
0
 public IntVar[] MakeIntVarArray(int count, int[] values) {
   IntVar[] array = new IntVar[count];
   for (int i = 0; i < count; ++i) {
     array[i] = MakeIntVar(values);
   }
   return array;
 }
예제 #4
0
 protected IntVarExprVar( IntVar var0, IntVar var1, IntVar var2 )
     : base(var0.Solver, new Variable[] { var0, var1, var2 })
 {
     m_Var0	= var0;
     m_Var1	= var1;
     m_Var2	= var2;
 }
예제 #5
0
  public static void minus(Solver solver, 
                           IntVar x, 
                           IntVar y, 
                           IntVar z) 
 {
   solver.Add(z == (x - y).Abs());
 }
예제 #6
0
파일: MoreMoney.cs 프로젝트: nofear/Mara
        public MoreMoney()
            : base(0, 1000000)
        {
            IntVar d	= new IntVar( m_Solver, 0, 9, "d");
            IntVar e	= new IntVar( m_Solver, 0, 9, "e");
            IntVar m	= new IntVar( m_Solver, 1, 9, "m");
            IntVar n	= new IntVar( m_Solver, 0, 9, "n");
            IntVar o	= new IntVar( m_Solver, 0, 9, "o");
            IntVar r	= new IntVar( m_Solver, 0, 9, "r");
            IntVar s	= new IntVar( m_Solver, 1, 9, "s");
            IntVar y	= new IntVar( m_Solver, 0, 9, "y");

            IntVarList list	= new IntVarList( m_Solver, new IntVar[] { d, e, m, n, o, r, s, y } );
            m_Solver.Add( list.AllDifferent() );

            IntVarListDotProduct send		= new IntVarListDotProduct( m_Solver,
                                                            new IntVar[] { s, e, n, d },
                                                            new int[] { 1000, 100, 10, 1 } );
            IntVarListDotProduct more		= new IntVarListDotProduct( m_Solver,
                                                            new IntVar[] { m, o, r, e },
                                                            new int[] { 1000, 100, 10, 1 } );
            IntVarListDotProduct money		= new IntVarListDotProduct( m_Solver,
                                                            new IntVar[] { m, o, n, e, y },
                                                            new int[] { 10000, 1000, 100, 10, 1 } );
            m_Solver.Add( send );
            m_Solver.Add( more );
            m_Solver.Add( money );

            IntVarExpr sendMore = send.Var0 + more.Var0;
            m_Solver.Add( sendMore );

            IntVarCmp cmp = sendMore.Var0 == money.Var0;
            m_Solver.Add( cmp );
        }
예제 #7
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());
    }

   }
  /**
   *
   * 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);

  }
예제 #9
0
파일: IntObjective.cs 프로젝트: nofear/Mara
 public IntObjective( Solver solver )
     : base(solver)
 {
     m_Variable	= null;
     m_Value		= int.MaxValue;
     m_Step		= 1;
 }
예제 #10
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();

  }
예제 #11
0
 public IntVar[] MakeIntVarArray(int count, long min, long max, string name) {
   IntVar[] array = new IntVar[count];
   for (int i = 0; i < count; ++i) {
     string var_name = name + i;
     array[i] = MakeIntVar(min, max, var_name);
   }
   return array;
 }
예제 #12
0
 public IntVar[] MakeBoolVarArray(int count, string name) {
   IntVar[] array = new IntVar[count];
   for (int i = 0; i < count; ++i) {
     string var_name = name + i;
     array[i] = MakeBoolVar(var_name);
   }
   return array;
 }
예제 #13
0
파일: IntGenerate.cs 프로젝트: nofear/Mara
 public IntGenerate( Solver solver, IntVar[] list, IntVarSelector.Select select, IntSearch search )
     : base(solver)
 {
     m_IntVarList		= list;
     m_SelectVar			= select;
     m_Search			= search;
     m_Depth				= new RevValue<double>( solver.StateStack, 1 );
 }
예제 #14
0
파일: IntGenerate.cs 프로젝트: nofear/Mara
 public IntGenerate( Solver solver, IntVar[] list )
     : base(solver)
 {
     m_IntVarList		= list;
     m_SelectVar			= IntVarSelector.CardinalityMin;
     m_Search			= new IntSearchDichotomize();
     m_Depth				= new RevValue<double>( solver.StateStack, 1 );
 }
예제 #15
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));
        }
    }
예제 #16
0
  /**
   *
   *  toNum(solver, a, num, base)
   *
   *  channelling between the array a and the number num.
   *
   */
  private static Constraint ToNum(IntVar[] a, IntVar num, int bbase) {
    int len = a.Length;

    IntVar[] tmp = new IntVar[len];
    for(int i = 0; i < len; i++) {
      tmp[i] = (a[i]*(int)Math.Pow(bbase,(len-i-1))).Var();
    }
     return tmp.Sum() == num;
  }
예제 #17
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);


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



    Debug.Assert(Q > 0, "regular: 'Q' must be greater than zero");
    Debug.Assert(S > 0, "regular: 'S' must be greater than zero");

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

    }

  }
예제 #20
0
파일: SolverCopy.cs 프로젝트: nofear/Mara
        public IntVar[] Copy( IntVar[] other )
        {
            IntVar[] copy	= new IntVar[ other.Length ];
            for( int idx = 0; idx < other.Length; ++idx )
            {
                copy[ idx ]		= m_IntVarList[ other[ idx ].Index ];
            }

            return copy;
        }
예제 #21
0
  //
  // Simple decomposition of Prod() for an IntVar array
  //
  private static Constraint MyProd(IntVar[] x, int prod) {
    int len = x.Length;
    IntVar[] tmp = new IntVar[len];
    tmp[0] = x[0];
    for(int i = 1; i < len; i++) {
      tmp[i] = (tmp[i-1]*x[i]).Var();
    }

    return tmp[len-1] == prod;
  }
예제 #22
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);
  }
예제 #23
0
파일: Cover.cs 프로젝트: nofear/Mara
        public Cover( Solver solver, int columns, IntVarList list )
            : base(solver)
        {
            m_Columns	= columns;

            m_List		= list;
            m_Avail		= new IntVar( solver, 0, list.Count - 1 );;

            m_Index		= new IntVar( solver, IntDomain.Empty, "" );
            m_Union		= new IntVar( solver, IntDomain.Empty, "" );
        }
예제 #24
0
 static void CheckIntRange(IntVar var, long vmin, long vmax) {
   if (var.Min() != vmin) {
     Console.WriteLine("Error: " + var.ToString() +
                       " does not have the expected min : " + vmin);
     error_count_++;
   }
   if (var.Max() != vmax) {
     Console.WriteLine("Error: " + var.ToString() +
                       " does not have the expected max : " + vmax);
     error_count_++;
   }
 }
예제 #25
0
파일: IntVarTest.cs 프로젝트: nofear/Mara
        public void Enumerator()
        {
            Solver solver	= new Solver( -1000, 1000 );
            IntVar var		= new IntVar( solver, 0 );

            var.Difference( 0 );

            foreach( int x in var )
            {
                Assert.Fail();
            }
        }
예제 #26
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();

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

  }
        private void Pack(Solver cp, IntVar[] binvars, int[] weights, IntVar[] loadvars)
        {
            IntVar[] b = new IntVar[binvars.Length];

            for(long j=0; j<loadvars.Length; j++)
            {
                for (int i = 0; i < binvars.Length; i++)
                {
                    b[i] = cp.MakeIsEqualCstVar(binvars[i], j);
                }
                cp.Add(cp.MakeScalProd(b, weights) == loadvars[j]);
            }
            
            cp.Add(cp.MakeSumEquality(loadvars, cp.MakeIntVar(weights.Sum(), weights.Sum(), "Sum")));
        }
예제 #30
0
        public void Test()
        {
            Solver solver	= new Solver( -1000, 1000 );
            IntVar i0	= new IntVar( solver, 0, 10 );
            IntVar i1	= new IntVar( solver, 10, 20 );
            IntVar i2	= new IntVar( solver, 20, 30 );
            IntVar s	= new IntVar( solver, 30, 60 );

            IntVarList list		= new IntVarList( solver, new IntVar[] { i0, i1, i2 } );
            IntVarListSum sum	= list.Sum();

            solver.Add( sum );
            solver.Propagate();

            Assert.AreEqual( s.Domain, sum.Var0.Domain );
        }
예제 #31
0
    static void ConstraintWithExprTest()
    {
        Console.WriteLine("TestConstraintWithExpr");
        Solver     solver = new Solver("test");
        IntVar     x      = solver.MakeIntVar(0, 10, "x");
        IntVar     y      = solver.MakeIntVar(0, 10, "y");
        Constraint c1     = x == 2;
        Constraint c2     = y == 3;
        IntExpr    e2a    = c1 + 1;

        Console.WriteLine(e2a.ToString());
        IntExpr e2b = 1 + c1;

        Console.WriteLine(e2b.ToString());
        IntExpr e2c = c1 - 1;

        Console.WriteLine(e2c.ToString());
        IntExpr e2d = 1 - c1;

        Console.WriteLine(e2d.ToString());
        IntExpr e2e = c1 * 2;

        Console.WriteLine(e2e.ToString());
        IntExpr e2f = 2 * c1;

        Console.WriteLine(e2f.ToString());
        IntExpr e3a = c1 + y;

        Console.WriteLine(e3a.ToString());
        IntExpr e3b = y + c1;

        Console.WriteLine(e3b.ToString());
        IntExpr e3c = c1 - y;

        Console.WriteLine(e3c.ToString());
        IntExpr e3d = y - c1;

        Console.WriteLine(e3d.ToString());
        IntExpr e3e = c1 * y;

        Console.WriteLine(e3e.ToString());
        IntExpr e3f = y * c1;

        Console.WriteLine(e3f.ToString());
        IntExpr e4 = -c1;

        Console.WriteLine(e4.ToString());
        IntExpr e5 = c1 / 4;

        Console.WriteLine(e5.ToString());
        IntExpr e6 = c1.Abs();

        Console.WriteLine(e6.ToString());
        IntExpr e7 = c1.Square();

        Console.WriteLine(e7.ToString());
        Constraint c8a = c1 == 1;

        Console.WriteLine(c8a.ToString());
        Constraint c8b = 1 == c1;

        Console.WriteLine(c8b.ToString());
        Constraint c8c = c1 != 1;

        Console.WriteLine(c8c.ToString());
        Constraint c8d = 1 != c1;

        Console.WriteLine(c8d.ToString());
        Constraint c8e = c1 >= 1;

        Console.WriteLine(c8e.ToString());
        Constraint c8f = 1 >= c1;

        Console.WriteLine(c8f.ToString());
        Constraint c8g = c1 > 1;

        Console.WriteLine(c8g.ToString());
        Constraint c8h = 1 > c1;

        Console.WriteLine(c8h.ToString());
        Constraint c8i = c1 <= 1;

        Console.WriteLine(c8i.ToString());
        Constraint c8j = 1 <= c1;

        Console.WriteLine(c8j.ToString());
        Constraint c8k = c1 < 1;

        Console.WriteLine(c8k.ToString());
        Constraint c8l = 1 < c1;

        Console.WriteLine(c8l.ToString());
        Constraint c9a = c1 == y;

        Console.WriteLine(c9a.ToString());
        Constraint c9b = y == c1;

        Console.WriteLine(c9b.ToString());
        Constraint c9c = c1 != y;

        Console.WriteLine(c9c.ToString());
        Constraint c9d = y != c1;

        Console.WriteLine(c9d.ToString());
        Constraint c9e = c1 >= y;

        Console.WriteLine(c9e.ToString());
        Constraint c9f = y >= c1;

        Console.WriteLine(c9f.ToString());
        Constraint c9g = c1 > y;

        Console.WriteLine(c9g.ToString());
        Constraint c9h = y > c1;

        Console.WriteLine(c9h.ToString());
        Constraint c9i = c1 <= y;

        Console.WriteLine(c9i.ToString());
        Constraint c9j = y <= c1;

        Console.WriteLine(c9j.ToString());
        Constraint c9k = c1 < y;

        Console.WriteLine(c9k.ToString());
        Constraint c9l = y < c1;

        Console.WriteLine(c9l.ToString());
        Constraint c10a = c1 == c2;

        Console.WriteLine(c10a.ToString());
        Constraint c10c = c1 != c2;

        Console.WriteLine(c10c.ToString());
        Constraint c10e = c1 >= c2;

        Console.WriteLine(c10e.ToString());
        Constraint c10g = c1 > c2;

        Console.WriteLine(c10g.ToString());
        Constraint c10i = c1 <= c2;

        Console.WriteLine(c10i.ToString());
        Constraint c10k = c1 < c2;

        Console.WriteLine(c10k.ToString());
        IntExpr e11a = c1 + (y == 2);

        Console.WriteLine(e11a.ToString());
        IntExpr e11b = (y == 2) + c1;

        Console.WriteLine(e11b.ToString());
        IntExpr e11c = c1 - (y == 2);

        Console.WriteLine(e11c.ToString());
        IntExpr e11d = (y == 2) - c1;

        Console.WriteLine(e11d.ToString());
        IntExpr e11e = c1 * (y == 2);

        Console.WriteLine(e11e.ToString());
        IntExpr e11f = (y == 2) * c1;

        Console.WriteLine(e11f.ToString());
        Constraint c12a = c1 == (y == 2);

        Console.WriteLine(c12a.ToString());
        Constraint c12b = (y == 2) == c1;

        Console.WriteLine(c12b.ToString());
        Constraint c12c = c1 != (y == 2);

        Console.WriteLine(c12c.ToString());
        Constraint c12d = (y == 2) != c1;

        Console.WriteLine(c12d.ToString());
        Constraint c12e = c1 >= (y == 2);

        Console.WriteLine(c12e.ToString());
        Constraint c12f = (y == 2) >= c1;

        Console.WriteLine(c12f.ToString());
        Constraint c12g = c1 > (y == 2);

        Console.WriteLine(c12g.ToString());
        Constraint c12h = (y == 2) > c1;

        Console.WriteLine(c12h.ToString());
        Constraint c12i = c1 <= (y == 2);

        Console.WriteLine(c12i.ToString());
        Constraint c12j = (y == 2) <= c1;

        Console.WriteLine(c12j.ToString());
        Constraint c12k = c1 < (y == 2);

        Console.WriteLine(c12k.ToString());
        Constraint c12l = (y == 2) < c1;

        Console.WriteLine(c12l.ToString());
    }
예제 #32
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();
    }
        /*
         * 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();
        }
예제 #34
0
        public void doWork()
        {
            Solver solver = new Solver("Xmas Puzzle");

            // n x m Matrix
            IntVar[,] board = new IntVar[this.size, this.size];

            // Feed IntVar-matrix and feed solver with the predefined Field value...
            for (int row = 0; row < this.size; row++)
            {
                for (int column = 0; column < this.size; column++)
                {
                    if (this.initialField[row, column] == X)
                    {
                        board[row, column] = solver.MakeIntVar(X, 0);  // Range of -1 to 0
                    }
                    else
                    {
                        board[row, column] = solver.MakeIntVar(0, 8);

                        // board[row, column] MUST have the value of field[row, column]
                        solver.Add(board[row, column] == this.initialField[row, column]);
                    }
                }
            }

            // Search field-matrix for hints about the lost gifts and group the neighbours.
            // Sum of neighbours with "-1"-Value should be the same value like the inverted hint-value.
            // As an example: If hint is "4" then there should be four times a value of "-1" around the hint.
            // This should be enought to solve this puzzle.

            // Handy C# LINQ type for sequences:
            IEnumerable <int> RANGE = Enumerable.Range(0, 8);
            IEnumerable <int> ROW_LENGTH;
            IEnumerable <int> COLUMN_LENGTH;
            int rowOffset;
            int columnOffset;

            // Maximum of lost gifts
            solver.Add((from di in RANGE from dj in RANGE where this.initialField[di, dj] == -1 select board[di, dj]).ToArray().Sum() == -this.maxGifts);

            // Outer and inner loop searches for hints
            for (int row = 0; row < this.size; row++)
            {
                for (int column = 0; column < this.size; column++)
                {
                    // If a hint was found, then group all neighbours with a value of "-1"
                    if (this.initialField[row, column] != X)
                    {
                        // Now it's getting ugly...
                        if (row == 0)
                        {
                            if (column == 0)
                            {
                                ROW_LENGTH    = Enumerable.Range(0, 2);
                                COLUMN_LENGTH = Enumerable.Range(0, 2);
                                rowOffset     = 0;
                                columnOffset  = 0;
                            }
                            else if (column == this.size - 1)
                            {
                                ROW_LENGTH    = Enumerable.Range(0, 2);
                                COLUMN_LENGTH = Enumerable.Range(0, 2);
                                rowOffset     = 0;
                                columnOffset  = -1;
                            }
                            else
                            {
                                ROW_LENGTH    = Enumerable.Range(0, 2);
                                COLUMN_LENGTH = Enumerable.Range(0, 3);
                                rowOffset     = 0;
                                columnOffset  = -1;
                            }
                        }
                        else if (row == this.size - 1)
                        {
                            if (column == 0)
                            {
                                ROW_LENGTH    = Enumerable.Range(0, 2);
                                COLUMN_LENGTH = Enumerable.Range(0, 2);
                                rowOffset     = -1;
                                columnOffset  = 0;
                            }
                            else if (column == this.size - 1)
                            {
                                ROW_LENGTH    = Enumerable.Range(0, 2);
                                COLUMN_LENGTH = Enumerable.Range(0, 2);
                                rowOffset     = -1;
                                columnOffset  = -1;
                            }
                            else
                            {
                                ROW_LENGTH    = Enumerable.Range(0, 2);
                                COLUMN_LENGTH = Enumerable.Range(0, 3);
                                rowOffset     = -1;
                                columnOffset  = -1;
                            }
                        }
                        else
                        {
                            if (column == 0)
                            {
                                ROW_LENGTH    = Enumerable.Range(0, 3);
                                COLUMN_LENGTH = Enumerable.Range(0, 2);
                                rowOffset     = -1;
                                columnOffset  = 0;
                            }
                            else if (column == this.size - 1)
                            {
                                ROW_LENGTH    = Enumerable.Range(0, 3);
                                COLUMN_LENGTH = Enumerable.Range(0, 2);
                                rowOffset     = -1;
                                columnOffset  = -1;
                            }
                            else
                            {
                                ROW_LENGTH    = Enumerable.Range(0, 3);
                                COLUMN_LENGTH = Enumerable.Range(0, 3);
                                rowOffset     = -1;
                                columnOffset  = -1;
                            }
                        }

                        foreach (int i in ROW_LENGTH)
                        {
                            foreach (int j in COLUMN_LENGTH)
                            {
                                solver.Add((from di in ROW_LENGTH from dj in COLUMN_LENGTH where this.initialField[row + rowOffset + di, column + columnOffset + dj] == -1 select board[row + rowOffset + di, column + columnOffset + dj]).ToArray().Sum() == -this.initialField[row, column]);
                            }
                        }
                    }
                }
            }

            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())
            {
                printField(board);
            }
        }
예제 #35
0
 private void CreateIntVar() => Int = (IntVar)MTools.CreateScriptableAsset(typeof(IntVar));
예제 #36
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();
    }
예제 #37
0
 public RemoveThreeValues(Solver solver, IntVar x) : base(solver) {x_ = x;}
예제 #38
0
 public CountHoles(IntVar x) {x_ = x; count_ = 0;}
예제 #39
0
 public DumbGreaterOrEqualToFive(Solver solver, IntVar x) : base(solver) {x_ = x;}
예제 #40
0
 public void ApplyChange(IntVar amount)
 {
     Value += amount.Value;
 }
예제 #41
0
 public SetMaxDemon(IntVar x) {x_ = x;}
예제 #42
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();
    }
예제 #43
0
    static void BinpackingProblem()
    {
        // Data.
        int bin_capacity   = 100;
        int slack_capacity = 20;
        int num_bins       = 10;

        int[,] items = new int[, ] {
            { 20, 12 }, { 15, 12 }, { 30, 8 }, { 45, 5 }
        };
        int num_items = items.GetLength(0);

        // Model.
        CpModel model = new CpModel();

        // Main variables.
        IntVar[,] x = new IntVar[num_items, num_bins];
        for (int i = 0; i < num_items; ++i)
        {
            int num_copies = items[i, 1];
            for (int b = 0; b < num_bins; ++b)
            {
                x[i, b] = model.NewIntVar(0, num_copies, String.Format("x_{0}_{1}", i, b));
            }
        }

        // Load variables.
        IntVar[] load = new IntVar[num_bins];
        for (int b = 0; b < num_bins; ++b)
        {
            load[b] = model.NewIntVar(0, bin_capacity, String.Format("load_{0}", b));
        }

        // Slack variables.
        IntVar[] slacks = new IntVar[num_bins];
        for (int b = 0; b < num_bins; ++b)
        {
            slacks[b] = model.NewBoolVar(String.Format("slack_{0}", b));
        }

        // Links load and x.
        int[] sizes = new int[num_items];
        for (int i = 0; i < num_items; ++i)
        {
            sizes[i] = items[i, 0];
        }
        for (int b = 0; b < num_bins; ++b)
        {
            IntVar[] tmp = new IntVar[num_items];
            for (int i = 0; i < num_items; ++i)
            {
                tmp[i] = x[i, b];
            }
            model.Add(load[b] == tmp.ScalProd(sizes));
        }

        // Place all items.
        for (int i = 0; i < num_items; ++i)
        {
            IntVar[] tmp = new IntVar[num_bins];
            for (int b = 0; b < num_bins; ++b)
            {
                tmp[b] = x[i, b];
            }
            model.Add(tmp.Sum() == items[i, 1]);
        }

        // Links load and slack.
        int safe_capacity = bin_capacity - slack_capacity;

        for (int b = 0; b < num_bins; ++b)
        {
            //  slack[b] => load[b] <= safe_capacity.
            model.Add(load[b] <= safe_capacity).OnlyEnforceIf(slacks[b]);
            // not(slack[b]) => load[b] > safe_capacity.
            model.Add(load[b] > safe_capacity).OnlyEnforceIf(slacks[b].Not());
        }

        // Maximize sum of slacks.
        model.Maximize(slacks.Sum());

        // Solves and prints out the solution.
        CpSolver       solver = new CpSolver();
        CpSolverStatus status = solver.Solve(model);

        Console.WriteLine(String.Format("Solve status: {0}", status));
        if (status == CpSolverStatus.Optimal)
        {
            Console.WriteLine(String.Format("Optimal objective value: {0}",
                                            solver.ObjectiveValue));
            for (int b = 0; b < num_bins; ++b)
            {
                Console.WriteLine(String.Format("load_{0} = {1}",
                                                b, solver.Value(load[b])));
                for (int i = 0; i < num_items; ++i)
                {
                    Console.WriteLine(string.Format("  item_{0}_{1} = {2}",
                                                    i, b, solver.Value(x[i, b])));
                }
            }
        }
        Console.WriteLine("Statistics");
        Console.WriteLine(String.Format("  - conflicts : {0}",
                                        solver.NumConflicts()));
        Console.WriteLine(String.Format("  - branches  : {0}",
                                        solver.NumBranches()));
        Console.WriteLine(String.Format("  - wall time : {0} s",
                                        solver.WallTime()));
    }
예제 #44
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();
    }
예제 #45
0
        public PackingResultWrapper Run(List <long> radii)
        {
            var model = new CpModel();

            const int dimension        = 2;
            var       domainConstraint = 2 * radii.Sum();

            // ----------------------------------------------------------------
            // Variable declaration
            // ----------------------------------------------------------------

            // Integer bundle radius, 0 <= x <= 2 * the sum of radii
            var bundleRadius = model.NewIntVar(0, domainConstraint, "r");

            // Coordinates (x, y) of the centers of inner circles, -2 * the sum of radii <= x, y <= 2 * the sum of radii
            var circleCenters = new IntVar[radii.Count, dimension];

            for (var i = 0; i < radii.Count; i++)
            {
                for (var j = 0; j < dimension; j++)
                {
                    circleCenters[i, j] = model.NewIntVar(-domainConstraint, domainConstraint, $"alpha_{i},{j}");
                }
            }

            // Slack variable - Coordinates (x, y) of the centers of inner circles squared, 0 <= x, y < infinity
            var circleCentersSquared = new IntVar[radii.Count, dimension];

            for (var i = 0; i < radii.Count; i++)
            {
                for (var j = 0; j < dimension; j++)
                {
                    circleCentersSquared[i, j] = model.NewIntVar(0, uint.MaxValue, $"s_alpha_{i},{j}");
                }
            }

            // Inner circle radii - input
            var circleRadii = new IntVar[radii.Count];

            for (var i = 0; i < radii.Count; i++)
            {
                circleRadii[i] = model.NewIntVar(radii[i], radii[i], $"r_{i}");
            }

            // Slack variable - bundle radius minus the inner circle radius, -2 * the sum of radii <= x <= 2 * the sum of radii
            var circleRadiiSlack = new IntVar[radii.Count];

            for (var i = 0; i < radii.Count; i++)
            {
                circleRadiiSlack[i] = model.NewIntVar(-domainConstraint, domainConstraint, $"s_r_{i}");
            }

            // Slack variable - bundle radius minus the inner circle radius, 0 <= x < infinity
            var circleRadiiSlackSquared = new IntVar[radii.Count];

            for (var i = 0; i < radii.Count; i++)
            {
                circleRadiiSlackSquared[i] = model.NewIntVar(0, uint.MaxValue, $"s_r_s_{i}");
            }

            // Slack variable - The difference of the centers of two inner circles on a single axis,
            // -2 * the sum of radii <= x <= 2 * the sum of radii
            var circleDistances = new IntVar[radii.Count, radii.Count, dimension];

            for (var i = 0; i < radii.Count; i++)
            {
                for (var j = 0; j < radii.Count; j++)
                {
                    for (var k = 0; k < dimension; k++)
                    {
                        circleDistances[i, j, k] = model.NewIntVar(-domainConstraint, domainConstraint, $"s_d_{i}_{j}_{k}");
                    }
                }
            }

            // The square distance of the centers of two inner circles on a single axis, 0 <= x < infinity
            var circleDistancesSquared = new IntVar[radii.Count, radii.Count, dimension];

            for (var i = 0; i < radii.Count; i++)
            {
                for (var j = 0; j < radii.Count; j++)
                {
                    for (var k = 0; k < dimension; k++)
                    {
                        circleDistancesSquared[i, j, k] = model.NewIntVar(0, uint.MaxValue, $"s_d_s_{i}_{j}_{k}");
                    }
                }
            }

            // The sum of radii of two inner circles, 0 <= x <= 2 * the sum of radii
            var radiiSum = new IntVar[radii.Count, radii.Count];

            for (var i = 0; i < radii.Count; i++)
            {
                for (var j = 0; j < radii.Count; j++)
                {
                    radiiSum[i, j] = model.NewIntVar(0, domainConstraint, $"s_rs_{i}_{j}");
                }
            }

            // Slack variable - The square of the sum of radii of two inner circles, 0 <= x <= infinity
            var radiiSumSquared = new IntVar[radii.Count, radii.Count];

            for (var i = 0; i < radii.Count; i++)
            {
                for (var j = 0; j < radii.Count; j++)
                {
                    radiiSumSquared[i, j] = model.NewIntVar(0, uint.MaxValue, $"s_rs_s_{i}_{j}");
                }
            }

            // ----------------------------------------------------------------
            // Constraint declaration
            // ----------------------------------------------------------------

            // (1) Bundle radius lower bound
            model.AddMaxEquality(bundleRadius, circleRadii);


            // (2) All inner circles are fully contained in the bundle
            for (var i = 0; i < radii.Count; i++)
            {
                // The solver doesn't support the multiplication of negative variables! Further constraints or domain limitation is needed.

                /*
                 * model.Add(circleCenters[i, 0] >= 0);
                 * model.Add(circleCenters[i, 1] >= 0);
                 * model.Add(circleRadiiSlack[i] >= 0);
                 */

                model.AddProdEquality(circleCentersSquared[i, 0],
                                      new List <IntVar> {
                    circleCenters[i, 0], circleCenters[i, 0]
                });

                model.AddProdEquality(circleCentersSquared[i, 1],
                                      new List <IntVar> {
                    circleCenters[i, 1], circleCenters[i, 1]
                });

                // NOT FEASIBLE with this constraint
                model.Add(bundleRadius == circleRadiiSlack[i] + circleRadii[i]);

                model.AddProdEquality(circleRadiiSlackSquared[i], new[] { circleRadiiSlack[i], circleRadiiSlack[i] });

                // NOT FEASIBLE with this constraint
                model.Add(circleCentersSquared[i, 0] + circleCentersSquared[i, 1] <= circleRadiiSlackSquared[i]);
            }


            // (3) No two inner circles overlap
            for (var i = 0; i < radii.Count; i++)
            {
                for (var j = 0; j < radii.Count; j++)
                {
                    if (i == j)
                    {
                        continue;
                    }

                    // The solver doesn't support the multiplication of negative variables! Further constraints or domain limitation is needed.

                    /*
                     * model.Add(circleDistances[i, j, 0] >= 0);
                     * model.Add(circleDistances[i, j, 1] >= 0);
                     */

                    model.Add(circleDistances[i, j, 0] == circleCenters[i, 0] - circleCenters[j, 0]);
                    model.Add(circleDistances[i, j, 1] == circleCenters[i, 1] - circleCenters[j, 1]);

                    model.AddProdEquality(circleDistancesSquared[i, j, 0],
                                          new List <IntVar> {
                        circleDistances[i, j, 0], circleDistances[i, j, 0]
                    });

                    model.AddProdEquality(circleDistancesSquared[i, j, 1],
                                          new List <IntVar> {
                        circleDistances[i, j, 1], circleDistances[i, j, 1]
                    });

                    model.Add(radiiSum[i, j] == circleRadii[i] + circleRadii[j]);

                    // NOT FEASIBLE with this constraint
                    model.AddProdEquality(radiiSumSquared[i, j], new List <IntVar> {
                        radiiSum[i, j], radiiSum[i, j]
                    });

                    model.Add(circleDistancesSquared[i, j, 0] + circleDistancesSquared[i, j, 1] >= radiiSumSquared[i, j]);
                }
            }


            // ----------------------------------------------------------------
            // Target declaration
            // ----------------------------------------------------------------

            // Minimize the radius of the bundle
            model.Minimize(bundleRadius);

            var solver = new CpSolver();
            var status = solver.Solve(model);

            if (status != CpSolverStatus.Feasible && status != CpSolverStatus.Optimal)
            {
                throw new NotImplementedException();
            }

            var bundle       = new Circle((long)solver.Value(bundleRadius), new Point(0, 0));
            var innerCircles = new List <Circle>();

            for (var i = 0; i < radii.Count; i++)
            {
                innerCircles.Add(new Circle((long)solver.Value(circleRadii[i]),
                                            new Point(solver.Value(circleCenters[i, 0]), solver.Value(circleCenters[i, 1]))));
            }

            return(new PackingResultWrapper(bundle, innerCircles));
        }
예제 #46
0
 public void SetValue(IntVar value)
 {
     Value = value.Value;
 }
예제 #47
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.");
            }
        }
예제 #48
0
    static void BaseEqualityWithExprTest()
    {
        Console.WriteLine("TestBaseEqualityWithExpr");
        Solver  solver = new Solver("test");
        IntVar  x      = solver.MakeIntVar(0, 10, "x");
        IntVar  y      = solver.MakeIntVar(0, 10, "y");
        IntExpr e2a    = (x >= 1) + 1;

        Console.WriteLine(e2a.ToString());
        IntExpr e2b = 1 + (x >= 1);

        Console.WriteLine(e2b.ToString());
        IntExpr e2c = (x >= 1) - 1;

        Console.WriteLine(e2c.ToString());
        IntExpr e2d = 1 - (x >= 1);

        Console.WriteLine(e2d.ToString());
        IntExpr e2e = (x >= 1) * 2;

        Console.WriteLine(e2e.ToString());
        IntExpr e2f = 2 * (x >= 1);

        Console.WriteLine(e2f.ToString());
        IntExpr e3a = (x >= 1) + y;

        Console.WriteLine(e3a.ToString());
        IntExpr e3b = y + (x >= 1);

        Console.WriteLine(e3b.ToString());
        IntExpr e3c = (x >= 1) - y;

        Console.WriteLine(e3c.ToString());
        IntExpr e3d = y - (x >= 1);

        Console.WriteLine(e3d.ToString());
        IntExpr e3e = (x >= 1) * y;

        Console.WriteLine(e3e.ToString());
        IntExpr e3f = y * (x >= 1);

        Console.WriteLine(e3f.ToString());
        IntExpr e4 = -(x >= 1);

        Console.WriteLine(e4.ToString());
        IntExpr e5 = (x >= 1) / 4;

        Console.WriteLine(e5.ToString());
        IntExpr e6 = (x >= 1).Abs();

        Console.WriteLine(e6.ToString());
        IntExpr e7 = (x >= 1).Square();

        Console.WriteLine(e7.ToString());
        Constraint c8a = (x >= 1) >= 1;

        Console.WriteLine(c8a.ToString());
        Constraint c8b = 1 >= (x >= 1);

        Console.WriteLine(c8b.ToString());
        Constraint c8c = (x >= 1) != 1;

        Console.WriteLine(c8c.ToString());
        Constraint c8d = 1 != (x >= 1);

        Console.WriteLine(c8d.ToString());
        Constraint c8e = (x >= 1) >= 1;

        Console.WriteLine(c8e.ToString());
        Constraint c8f = 1 >= (x >= 1);

        Console.WriteLine(c8f.ToString());
        Constraint c8g = (x >= 1) > 1;

        Console.WriteLine(c8g.ToString());
        Constraint c8h = 1 > (x >= 1);

        Console.WriteLine(c8h.ToString());
        Constraint c8i = (x >= 1) <= 1;

        Console.WriteLine(c8i.ToString());
        Constraint c8j = 1 <= (x >= 1);

        Console.WriteLine(c8j.ToString());
        Constraint c8k = (x >= 1) < 1;

        Console.WriteLine(c8k.ToString());
        Constraint c8l = 1 < (x >= 1);

        Console.WriteLine(c8l.ToString());
        Constraint c9a = (x >= 1) >= y;

        Console.WriteLine(c9a.ToString());
        Constraint c9b = y >= (x >= 1);

        Console.WriteLine(c9b.ToString());
        Constraint c9c = (x >= 1) != y;

        Console.WriteLine(c9c.ToString());
        Constraint c9d = y != (x >= 1);

        Console.WriteLine(c9d.ToString());
        Constraint c9e = (x >= 1) >= y;

        Console.WriteLine(c9e.ToString());
        Constraint c9f = y >= (x >= 1);

        Console.WriteLine(c9f.ToString());
        Constraint c9g = (x >= 1) > y;

        Console.WriteLine(c9g.ToString());
        Constraint c9h = y > (x >= 1);

        Console.WriteLine(c9h.ToString());
        Constraint c9i = (x >= 1) <= y;

        Console.WriteLine(c9i.ToString());
        Constraint c9j = y <= (x >= 1);

        Console.WriteLine(c9j.ToString());
        Constraint c9k = (x >= 1) < y;

        Console.WriteLine(c9k.ToString());
        Constraint c9l = y < (x >= 1);

        Console.WriteLine(c9l.ToString());
        Constraint c10a = (x >= 1) >= (y >= 2);

        Console.WriteLine(c10a.ToString());
        Constraint c10c = (x >= 1) != (y >= 2);

        Console.WriteLine(c10c.ToString());
        Constraint c10e = (x >= 1) >= (y >= 2);

        Console.WriteLine(c10e.ToString());
        Constraint c10g = (x >= 1) > (y >= 2);

        Console.WriteLine(c10g.ToString());
        Constraint c10i = (x >= 1) <= (y >= 2);

        Console.WriteLine(c10i.ToString());
        Constraint c10k = (x >= 1) < (y >= 2);

        Console.WriteLine(c10k.ToString());
    }
예제 #49
0
    /**
     *
     * A Round of Golf puzzle (Dell Logic Puzzles) in Google CP Solver.
     *
     * From http://brownbuffalo.sourceforge.net/RoundOfGolfClues.html
     * """
     * Title: A Round of Golf
     * Author: Ellen K. Rodehorst
     * Publication: Dell Favorite Logic Problems
     * Issue: Summer, 2000
     * Puzzle #: 9
     * Stars: 1
     *
     * When the Sunny Hills Country Club golf course isn't in use by club members,
     * of course, it's open to the club's employees. Recently, Jack and three
     * other workers at the golf course got together on their day off to play a
     * round of eighteen holes of golf. Afterward, all four, including Mr. Green,
     * went to the clubhouse to total their scorecards. Each man works at a
     * different job (one is a short-order cook), and each shot a different score
     * in the game. No one scored below 70 or above 85 strokes. From the clues
     * below, can you discover each man's full name, job and golf score?
     *
     * 1. Bill, who is not the maintenance man, plays golf often and had the
     * lowest score of the foursome.
     * 2. Mr. Clubb, who isn't Paul, hit several balls into the woods and scored
     * ten strokes more than the pro-shop clerk.
     * 3. In some order, Frank and the caddy scored four and seven more strokes
     * than Mr. Sands.
     * 4. Mr. Carter thought his score of 78 was one of his better games, even
     *    though Frank's score  was lower.
     * 5. None of the four scored exactly 81 strokes.
     *
     * Determine: First Name - Last Name - Job - Score
     * """
     *
     * See http://www.hakank.org/google_or_tools/a_round_of_golf.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("ARoundOfGolf");

        // number of speakers
        int n = 4;

        int Jack  = 0;
        int Bill  = 1;
        int Paul  = 2;
        int Frank = 3;

        //
        // Decision variables
        //
        IntVar[] last_name = solver.MakeIntVarArray(n, 0, n - 1, "last_name");
        // IntVar Green  = last_name[0]; // not used
        IntVar Clubb  = last_name[1];
        IntVar Sands  = last_name[2];
        IntVar Carter = last_name[3];

        IntVar[] job = solver.MakeIntVarArray(n, 0, n - 1, "job");
        // IntVar cook            = job[0]; // not used
        IntVar maintenance_man = job[1];
        IntVar clerk           = job[2];
        IntVar caddy           = job[3];

        IntVar[] score = solver.MakeIntVarArray(n, 70, 85, "score");

        // for search
        IntVar[] all = new IntVar[n * 3];
        for (int i = 0; i < n; i++)
        {
            all[i]         = last_name[i];
            all[i + n]     = job[i];
            all[i + 2 * n] = score[i];
        }

        //
        // Constraints
        //
        solver.Add(last_name.AllDifferent());
        solver.Add(job.AllDifferent());
        solver.Add(score.AllDifferent());

        // 1. Bill, who is not the maintenance man, plays golf often and had
        //    the lowest score of the foursome.
        solver.Add(maintenance_man != Bill);
        solver.Add(score[Bill] < score[Jack]);
        solver.Add(score[Bill] < score[Paul]);
        solver.Add(score[Bill] < score[Frank]);

        // 2. Mr. Clubb, who isn't Paul, hit several balls into the woods and
        //    scored ten strokes more than the pro-shop clerk.
        solver.Add(Clubb != Paul);
        solver.Add(score.Element(Clubb) == score.Element(clerk) + 10);

        // 3. In some order, Frank and the caddy scored four and seven more
        //    strokes than Mr. Sands.
        solver.Add(caddy != Frank);
        solver.Add(Sands != Frank);
        solver.Add(caddy != Sands);

        IntVar b3_a_1 = score.Element(Sands) + 4 == score[Frank];
        IntVar b3_a_2 = score.Element(caddy) == score.Element(Sands) + 7;
        IntVar b3_b_1 = score.Element(Sands) + 7 == score[Frank];
        IntVar b3_b_2 = score.Element(caddy) == score.Element(Sands) + 4;

        solver.Add((b3_a_1 * b3_a_2) + (b3_b_1 * b3_b_2) == 1);

        // 4. Mr. Carter thought his score of 78 was one of his better games,
        //    even though Frank's score was lower.
        solver.Add(Carter != Frank);
        solver.Add(score.Element(Carter) == 78);
        solver.Add(score[Frank] < score.Element(Carter));

        // 5. None of the four scored exactly 81 strokes.
        for (int i = 0; i < n; i++)
        {
            solver.Add(score[i] != 81);
        }

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

        solver.NewSearch(db);

        while (solver.NextSolution())
        {
            Console.WriteLine("Last name: " +
                              String.Join(",  ", (from i in last_name select i.Value().ToString()).ToArray()));
            Console.WriteLine("Job      : " +
                              String.Join(",  ", (from i in job select i.Value().ToString()).ToArray()));
            Console.WriteLine("Score    : " +
                              String.Join(", ", (from i in score select i.Value().ToString()).ToArray()));
        }

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

        solver.EndSearch();
    }
예제 #50
0
 /// <summary> Set an specific Speed for a State using IntVars </summary>
 public virtual void SetSpeed(IntVar speedIndex)
 {
     CurrentSpeedIndex = speedIndex;
 }
예제 #51
0
 /// <summary>Find a Stat Using an IntVar and Return if the Stat is on the List. Also Saves it to the PinnedStat</summary>
 public virtual Stat Stat_Get(IntVar ID) => Stat_Get(ID.Value);
예제 #52
0
    /**
     *
     * P-median problem.
     *
     * Model and data from the OPL Manual, which describes the problem:
     * """
     * The P-Median problem is a well known problem in Operations Research.
     * The problem can be stated very simply, like this: given a set of customers
     * with known amounts of demand, a set of candidate locations for warehouses,
     * and the distance between each pair of customer-warehouse, choose P
     * warehouses to open that minimize the demand-weighted distance of serving
     * all customers from those P warehouses.
     * """
     *
     * Also see http://www.hakank.org/or-tools/p_median.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("PMedian");

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

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

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

        //
        // Decision variables
        //

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

        //
        // Constraints
        //

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

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

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

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

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

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

        solver.NewSearch(db, obj);

        while (solver.NextSolution())
        {
            Console.WriteLine("z: {0}", z.Value());
            Console.Write("open:");
            foreach (int w in WAREHOUSES)
            {
                Console.Write(open[w].Value() + " ");
            }
            Console.WriteLine();
            foreach (int c in CUSTOMERS)
            {
                foreach (int w in WAREHOUSES)
                {
                    Console.Write(ship[c, w].Value() + " ");
                }
                Console.WriteLine();
            }
            Console.WriteLine();
        }

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

        solver.EndSearch();
    }
예제 #53
0
    static void Main()
    {
        CpModel model = new CpModel();
        // Three weeks.
        int horizon   = 100;
        int num_tasks = 4;

        IntVar[]      starts    = new IntVar[num_tasks];
        IntVar[]      ends      = new IntVar[num_tasks];
        IntervalVar[] intervals = new IntervalVar[num_tasks];
        ILiteral[]    presences = new ILiteral[num_tasks];
        IntVar[]      ranks     = new IntVar[num_tasks];

        IntVar true_var = model.NewConstant(1);

        // Creates intervals, half of them are optional.
        for (int t = 0; t < num_tasks; ++t)
        {
            starts[t] = model.NewIntVar(0, horizon, String.Format("start_{0}", t));
            int duration = t + 1;
            ends[t] = model.NewIntVar(0, horizon, String.Format("end_{0}", t));
            if (t < num_tasks / 2)
            {
                intervals[t] =
                    model.NewIntervalVar(starts[t], duration, ends[t], String.Format("interval_{0}", t));
                presences[t] = true_var;
            }
            else
            {
                presences[t] = model.NewBoolVar(String.Format("presence_{0}", t));
                intervals[t] = model.NewOptionalIntervalVar(starts[t], duration, ends[t], presences[t],
                                                            String.Format("o_interval_{0}", t));
            }

            // Ranks = -1 if and only if the tasks is not performed.
            ranks[t] = model.NewIntVar(-1, num_tasks - 1, String.Format("rank_{0}", t));
        }

        // Adds NoOverlap constraint.
        model.AddNoOverlap(intervals);

        // Adds ranking constraint.
        RankTasks(model, starts, presences, ranks);

        // Adds a constraint on ranks.
        model.Add(ranks[0] < ranks[1]);

        // Creates makespan variable.
        IntVar makespan = model.NewIntVar(0, horizon, "makespan");

        for (int t = 0; t < num_tasks; ++t)
        {
            model.Add(ends[t] <= makespan).OnlyEnforceIf(presences[t]);
        }
        // Minimizes makespan - fixed gain per tasks performed.
        // As the fixed cost is less that the duration of the last interval,
        // the solver will not perform the last interval.
        IntVar[] presences_as_int_vars = new IntVar[num_tasks];
        for (int t = 0; t < num_tasks; ++t)
        {
            presences_as_int_vars[t] = (IntVar)presences[t];
        }
        model.Minimize(2 * makespan - 7 * LinearExpr.Sum(presences_as_int_vars));

        // Creates a solver and solves the model.
        CpSolver       solver = new CpSolver();
        CpSolverStatus status = solver.Solve(model);

        if (status == CpSolverStatus.Optimal)
        {
            Console.WriteLine(String.Format("Optimal cost: {0}", solver.ObjectiveValue));
            Console.WriteLine(String.Format("Makespan: {0}", solver.Value(makespan)));
            for (int t = 0; t < num_tasks; ++t)
            {
                if (solver.BooleanValue(presences[t]))
                {
                    Console.WriteLine(String.Format("Task {0} starts at {1} with rank {2}", t,
                                                    solver.Value(starts[t]), solver.Value(ranks[t])));
                }
                else
                {
                    Console.WriteLine(String.Format("Task {0} in not performed and ranked at {1}", t,
                                                    solver.Value(ranks[t])));
                }
            }
        }
        else
        {
            Console.WriteLine(String.Format("Solver exited with nonoptimal status: {0}", status));
        }
    }
예제 #54
0
    static void RankTasks(CpModel model, IntVar[] starts, ILiteral[] presences, IntVar[] ranks)
    {
        int num_tasks = starts.Length;

        // Creates precedence variables between pairs of intervals.
        ILiteral[,] precedences = new ILiteral[num_tasks, num_tasks];
        for (int i = 0; i < num_tasks; ++i)
        {
            for (int j = 0; j < num_tasks; ++j)
            {
                if (i == j)
                {
                    precedences[i, i] = presences[i];
                }
                else
                {
                    IntVar prec = model.NewBoolVar(String.Format("{0} before {1}", i, j));
                    precedences[i, j] = prec;
                    model.Add(starts[i] < starts[j]).OnlyEnforceIf(prec);
                }
            }
        }

        // Treats optional intervals.
        for (int i = 0; i < num_tasks - 1; ++i)
        {
            for (int j = i + 1; j < num_tasks; ++j)
            {
                List <ILiteral> tmp_array = new List <ILiteral>();
                tmp_array.Add(precedences[i, j]);
                tmp_array.Add(precedences[j, i]);
                tmp_array.Add(presences[i].Not());
                // Makes sure that if i is not performed, all precedences are false.
                model.AddImplication(presences[i].Not(), precedences[i, j].Not());
                model.AddImplication(presences[i].Not(), precedences[j, i].Not());
                tmp_array.Add(presences[j].Not());
                // Makes sure that if j is not performed, all precedences are false.
                model.AddImplication(presences[j].Not(), precedences[i, j].Not());
                model.AddImplication(presences[j].Not(), precedences[j, i].Not());
                // The following bool_or will enforce that for any two intervals:
                //    i precedes j or j precedes i or at least one interval is not
                //        performed.
                model.AddBoolOr(tmp_array);
                // Redundant constraint: it propagates early that at most one precedence
                // is true.
                model.AddImplication(precedences[i, j], precedences[j, i].Not());
                model.AddImplication(precedences[j, i], precedences[i, j].Not());
            }
        }

        // Links precedences and ranks.
        for (int i = 0; i < num_tasks; ++i)
        {
            IntVar[] tmp_array = new IntVar[num_tasks];
            for (int j = 0; j < num_tasks; ++j)
            {
                tmp_array[j] = (IntVar)precedences[j, i];
            }
            model.Add(ranks[i] == LinearExpr.Sum(tmp_array) - 1);
        }
    }
예제 #55
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();
    }
예제 #56
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();
        }
예제 #57
0
        public void Solve()
        {
            CpModel model    = new CpModel();
            int     num_vals = 9;

            IntVar[][] grid = new IntVar[9][];

            for (int k = 0; k < 9; k++)
            {
                grid[k] = new IntVar[9];
            }

            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    if (Sudoku.getCaseInitialSudoku(i, j) == 0)
                    {
                        grid[i][j] = model.NewIntVar(1, num_vals, "C" + i.ToString() + j.ToString());
                    }
                    else
                    {
                        grid[i][j] = model.NewIntVar(Sudoku.getCaseInitialSudoku(i, j), Sudoku.getCaseInitialSudoku(i, j), "C" + i.ToString() + j.ToString());
                    }
                }
            }

            for (int k = 0; k < 9; k++)
            {
                model.AddAllDifferent(grid[k]);
                model.AddAllDifferent(Transpose(grid)[k]);
            }

            for (int k = 0; k < 3; k++)
            {
                for (int l = 0; l < 3; l++)
                {
                    List <IntVar> boxList = new List <IntVar>();
                    for (int i = 0; i < 3; i++)
                    {
                        for (int j = 0; j < 3; j++)
                        {
                            boxList.Add(grid[k * 3 + i][l * 3 + j]);
                        }
                    }
                    model.AddAllDifferent(boxList);
                }
            }
            CpSolver solver            = new CpSolver();
            VarArraySolutionPrinter cb = new VarArraySolutionPrinter(grid);

            solver.SearchAllSolutions(model, cb);
            int[][] values = cb.getValues();

            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    if (Sudoku.getCaseSudoku(i, j) == 0)
                    {
                        Sudoku.setCaseSudoku(i, j, values[i][j]);
                    }
                }
            }
        }
예제 #58
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();
    }
예제 #59
0
 public SetMinAndMaxConstraint(Solver solver, IntVar x) : base(solver) {x_ = x;}
예제 #60
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();
    }