/** * * Solve the SEND+MORE=MONEY problem * using scalar product. * */ 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); */ // Here we use scalar product instead. int[] s1 = new int[] { 1000, 100, 10, 1 }; int[] s2 = new int[] { 10000, 1000, 100, 10, 1 }; solver.Add(new IntVar[] { S, E, N, D }.ScalProd(s1) + new IntVar[] { M, O, R, E }.ScalProd(s1) == new IntVar[] { M, O, N, E, Y }.ScalProd(s2)); 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].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(); }
/** * * Implements the all interval problem. * See http://www.hakank.org/google_or_tools/all_interval.py * */ private static void Solve(int n = 12) { Solver solver = new Solver("AllInterval"); // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 0, n - 1, "x"); IntVar[] diffs = solver.MakeIntVarArray(n - 1, 1, n - 1, "diffs"); // // Constraints // solver.Add(x.AllDifferent()); solver.Add(diffs.AllDifferent()); for (int k = 0; k < n - 1; k++) { // solver.Add(diffs[k] == (x[k + 1] - x[k]).Abs()); solver.Add(diffs[k] == (x[k + 1] - x[k].Abs())); } // symmetry breaking solver.Add(x[0] < x[n - 1]); solver.Add(diffs[0] < diffs[1]); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { Console.Write("x: "); for (int i = 0; i < n; i++) { Console.Write("{0} ", x[i].Value()); } Console.Write(" diffs: "); for (int i = 0; i < n - 1; i++) { Console.Write("{0} ", diffs[i].Value()); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Olympic puzzle. * * Benchmark for Prolog (BProlog) * """ * File : olympic.pl * Author : Neng-Fa ZHOU * Date : 1993 * * Purpose: solve a puzzle taken from Olympic Arithmetic Contest * * Given ten variables with the following configuration: * * X7 X8 X9 X10 * * X4 X5 X6 * * X2 X3 * * X1 * * We already know that X1 is equal to 3 and want to assign each variable * with a different integer from {1,2,...,10} such that for any three * variables * Xi Xj * * Xk * * the following constraint is satisfied: * * |Xi-Xj| = Xk * """ * * Also see http://www.hakank.org/or-tools/olympic.py * */ private static void Solve() { Solver solver = new Solver("Olympic"); // // Data // int n = 10; // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 1, n, "x"); IntVar X1 = x[0]; IntVar X2 = x[1]; IntVar X3 = x[2]; IntVar X4 = x[3]; IntVar X5 = x[4]; IntVar X6 = x[5]; IntVar X7 = x[6]; IntVar X8 = x[7]; IntVar X9 = x[8]; IntVar X10 = x[9]; // // Constraints // solver.Add(x.AllDifferent()); solver.Add(X1 == 3); minus(solver, X2, X3, X1); minus(solver, X4, X5, X2); minus(solver, X5, X6, X3); minus(solver, X7, X8, X4); minus(solver, X8, X9, X5); minus(solver, X9, X10, X6); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db); while (solver.NextSolution()) { for (int i = 0; i < n; i++) { Console.Write("{0,2} ", x[i].Value()); } Console.WriteLine(); } Console.WriteLine("\nSolutions: " + solver.Solutions()); Console.WriteLine("WallTime: " + solver.WallTime() + "ms "); Console.WriteLine("Failures: " + solver.Failures()); Console.WriteLine("Branches: " + solver.Branches()); solver.EndSearch(); }
/** * * 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(); }
/** * * Place number puzzle. * * From * http://ai.uwaterloo.ca/~vanbeek/Courses/Slides/introduction.pdf * """ * Place numbers 1 through 8 on nodes * - each number appears exactly once * - no connected nodes have consecutive numbers * 2 - 5 * / | X | \ * 1 - 3 - 6 - 8 * \ | X | / * 4 - 7 * """ * * Also see http://www.hakank.org/or-tools/place_number_puzzle.py * * */ private static void Solve() { Solver solver = new Solver("PlaceNumberPuzzle"); // // Data // int m = 32; int n = 8; // Note: this is 1-based for compatibility (and lazyness) int[,] graph = { { 1, 2 }, { 1, 3 }, { 1, 4 }, { 2, 1 }, { 2, 3 }, { 2, 5 }, { 2, 6 }, { 3, 2 }, { 3, 4 }, { 3, 6 }, { 3, 7 }, { 4, 1 }, { 4, 3 }, { 4, 6 }, { 4, 7 }, { 5, 2 }, { 5, 3 }, { 5, 6 }, { 5, 8 }, { 6, 2 }, { 6, 3 }, { 6, 4 }, { 6, 5 }, { 6, 7 }, { 6, 8 }, { 7, 3 }, { 7, 4 }, { 7, 6 }, { 7, 8 }, { 8, 5 }, { 8, 6 }, { 8, 7 } }; // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 1, n, "x"); // // Constraints // solver.Add(x.AllDifferent()); for (int i = 0; i < m; i++) { // (also base 0-base) solver.Add((x[graph[i, 0] - 1] - x[graph[i, 1] - 1]).Abs() > 1); } // symmetry breaking solver.Add(x[0] < x[n - 1]); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db); while (solver.NextSolution()) { Console.Write("x: "); for (int i = 0; i < n; i++) { Console.Write(x[i].Value() + " "); } Console.WriteLine(); } 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(); }
/** * * 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(); }
/** * * Secret Santa problem in Google CP Solver. * * From Ruby Quiz Secret Santa * http://www.rubyquiz.com/quiz2.html * """ * Honoring a long standing tradition started by my wife's dad, my friends * all play a Secret Santa game around Christmas time. We draw names and * spend a week sneaking that person gifts and clues to our identity. On the * last night of the game, we get together, have dinner, share stories, and, * most importantly, try to guess who our Secret Santa was. It's a crazily * fun way to enjoy each other's company during the holidays. * * To choose Santas, we use to draw names out of a hat. This system was * tedious, prone to many 'Wait, I got myself...' problems. This year, we * made a change to the rules that further complicated picking and we knew * the hat draw would not stand up to the challenge. Naturally, to solve * this problem, I scripted the process. Since that turned out to be more * interesting than I had expected, I decided to share. * * This weeks Ruby Quiz is to implement a Secret Santa selection script. * * Your script will be fed a list of names on STDIN. * ... * Your script should then choose a Secret Santa for every name in the list. * Obviously, a person cannot be their own Secret Santa. In addition, my * friends no longer allow people in the same family to be Santas for each * other and your script should take this into account. * """ * * Comment: This model skips the file input and mail parts. We * assume that the friends are identified with a number from 1..n, * and the families is identified with a number 1..num_families. * * Also see http://www.hakank.org/or-tools/secret_santa.py * Also see http://www.hakank.org/or-tools/secret_santa2.cs * */ private static void Solve() { Solver solver = new Solver("SecretSanta"); int[] family = { 1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 4, 4 }; int n = family.Length; Console.WriteLine("n = {0}", n); IEnumerable <int> RANGE = Enumerable.Range(0, n); // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 0, n - 1, "x"); // // Constraints // solver.Add(x.AllDifferent()); // Can't be one own"s Secret Santa // (i.e. ensure that there are no fix-point in the array.) foreach (int i in RANGE) { solver.Add(x[i] != i); } // No Secret Santa to a person in the same family foreach (int i in RANGE) { solver.Add(solver.MakeIntConst(family[i]) != family.Element(x[i])); } // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); solver.NewSearch(db); while (solver.NextSolution()) { Console.Write("x: "); foreach (int i in RANGE) { Console.Write(x[i].Value() + " "); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Scheduling speakers problem * * From Rina Dechter, Constraint Processing, page 72 * Scheduling of 6 speakers in 6 slots. * * See http://www.hakank.org/google_or_tools/scheduling_speakers.py * */ private static void Solve() { Solver solver = new Solver("SchedulingSpeakers"); // number of speakers int n = 6; // slots available to speak int[][] available = { // Reasoning: new int[] { 3, 4, 5, 6 }, // 2) the only one with 6 after speaker F -> 1 new int[] { 3,4 }, // 5) 3 or 4 new int[] { 2, 3, 4, 5 }, // 3) only with 5 after F -> 1 and A -> 6 new int[] { 2, 3,4 }, // 4) only with 2 after C -> 5 and F -> 1 new int[] { 3,4 }, // 5) 3 or 4 new int[] { 1, 2, 3,4, 5, 6 } // 1) the only with 1 }; // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 1, n, "x"); // // Constraints // solver.Add(x.AllDifferent()); for (int i = 0; i < n; i++) { solver.Add(x[i].Member(available[i])); } // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { Console.WriteLine(string.Join(",", (from i in x select i.Value()))); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Implements the all interval problem. * See http://www.hakank.org/google_or_tools/all_interval.py * */ private static void Solve(int n=12) { Solver solver = new Solver("AllInterval"); // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 0, n-1, "x"); IntVar[] diffs = solver.MakeIntVarArray(n-1, 1, n-1, "diffs"); // // Constraints // solver.Add(x.AllDifferent()); solver.Add(diffs.AllDifferent()); for(int k = 0; k < n - 1; k++) { // solver.Add(diffs[k] == (x[k + 1] - x[k]).Abs()); solver.Add(diffs[k] == (x[k + 1] - x[k].Abs())); } // symmetry breaking solver.Add(x[0] < x[n - 1]); solver.Add(diffs[0] < diffs[1]); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { Console.Write("x: "); for(int i = 0; i < n; i++) { Console.Write("{0} ", x[i].Value()); } Console.Write(" diffs: "); for(int i = 0; i < n-1; i++) { Console.Write("{0} ", diffs[i].Value()); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * 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(); }
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); }
/* * Main Method: */ public static void Solve() { var solver = new Solver("Cryptogram"); // One variable for each Character: IntVar S = solver.MakeIntVar(0, 9); IntVar E = solver.MakeIntVar(0, 9); IntVar N = solver.MakeIntVar(0, 9); IntVar D = solver.MakeIntVar(0, 9); IntVar M = solver.MakeIntVar(0, 9); IntVar O = solver.MakeIntVar(0, 9); IntVar R = solver.MakeIntVar(0, 9); IntVar Y = solver.MakeIntVar(0, 9); IntVar[] vars = { S, E, N, D, M, O, R, Y }; // SEND + MORE = MONEY: IntVar send = (S * 1000 + E * 100 + N * 10 + D).Var(); IntVar more = (M * 1000 + O * 100 + R * 10 + E).Var(); IntVar money = (M * 10000 + O * 1000 + N * 100 + E * 10 + Y).Var(); solver.Add(send + more == money); // Leading characters must not be zero: solver.Add(S != 0); solver.Add(M != 0); // All characters take different values: solver.Add(vars.AllDifferent()); // Start Solver: DecisionBuilder db = solver.MakePhase(vars, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); solver.NewSearch(db); while (solver.NextSolution()) { Console.WriteLine(send.Value() + " + " + more.Value() + " = " + money.Value() + "\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(); Console.ReadKey(); }
/** * * Subset sum problem. * * From Katta G. Murty: 'Optimization Models for Decision Making', page 340 * http://ioe.engin.umich.edu/people/fac/books/murty/opti_model/junior-7.pdf * """ * Example 7.8.1 * * A bank van had several bags of coins, each containing either * 16, 17, 23, 24, 39, or 40 coins. While the van was parked on the * street, thieves stole some bags. A total of 100 coins were lost. * It is required to find how many bags were stolen. * """ * * Also see http://www.hakank.org/or-tools/subset_sum.py * */ private static void Solve(int[] coins, int total) { Solver solver = new Solver("SubsetSum"); int n = coins.Length; Console.Write("Coins: "); for (int i = 0; i < n; i++) { Console.Write(coins[i] + " "); } Console.WriteLine("\nTotal: {0}", total); // // Variables // // number of coins IntVar s = solver.MakeIntVar(0, coins.Sum(), "s"); // // Constraints // IntVar[] x = subset_sum(solver, coins, total); solver.Add(x.Sum() == s); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { Console.Write("x: "); for (int i = 0; i < n; i++) { Console.Write(x[i].Value() + " "); } Console.WriteLine(" s: {0}", s.Value()); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Magic sequence problem. * * This is a port of the Python model * https://code.google.com/p/or-tools/source/browse/trunk/python/magic_sequence_distribute.py * """ * This models aims at building a sequence of numbers such that the number of * occurrences of i in this sequence is equal to the value of the ith number. * It uses an aggregated formulation of the count expression called * distribute(). * """ * */ private static void Solve(int size) { Solver solver = new Solver("MagicSequence"); Console.WriteLine("\nSize: {0}", size); // // data // int[] all_values = new int[size]; for (int i = 0; i < size; i++) { all_values[i] = i; } // // Decision variables // IntVar[] all_vars = solver.MakeIntVarArray(size, 0, size - 1, "vars"); // // Constraints // solver.Add(all_vars.Distribute(all_values, all_vars)); solver.Add(all_vars.Sum() == size); // // Search // DecisionBuilder db = solver.MakePhase(all_vars, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { for (int i = 0; i < size; i++) { Console.Write(all_vars[i].Value() + " "); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Dudeney numbers * From Pierre Schaus blog post * Dudeney number * http://cp-is-fun.blogspot.com/2010/09/test-python.html * """ * I discovered yesterday Dudeney Numbers * A Dudeney Numbers is a positive integer that is a perfect cube such that the sum * of its decimal digits is equal to the cube root of the number. There are only six * Dudeney Numbers and those are very easy to find with CP. * I made my first experience with google cp solver so find these numbers (model below) * and must say that I found it very convenient to build CP models in python! * When you take a close look at the line: * solver.Add(sum([10**(n-i-1)*x[i] for i in range(n)]) == nb) * It is difficult to argue that it is very far from dedicated * optimization languages! * """ * * Also see: http://en.wikipedia.org/wiki/Dudeney_number * */ private static void Solve() { Solver solver = new Solver("DudeneyNumbers"); // // data // int n = 6; // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 0, 9, "x"); IntVar nb = solver.MakeIntVar(3, (int)Math.Pow(10, n), "nb"); IntVar s = solver.MakeIntVar(1, 9 * n + 1, "s"); // // Constraints // solver.Add(nb == s * s * s); solver.Add(x.Sum() == s); // solver.Add(ToNum(x, nb, 10)); // alternative solver.Add((from i in Enumerable.Range(0, n) select(x[i] * (int)Math.Pow(10, n - i - 1)).Var()). ToArray().Sum() == nb); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db); while (solver.NextSolution()) { Console.WriteLine(nb.Value()); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
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; }
/** * * 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(); }
/** * * Magic sequence problem. * * This is a port of the Python model * https://code.google.com/p/or-tools/source/browse/trunk/python/magic_sequence_distribute.py * """ * This models aims at building a sequence of numbers such that the number of * occurrences of i in this sequence is equal to the value of the ith number. * It uses an aggregated formulation of the count expression called * distribute(). * """ * */ private static void Solve(int size) { Solver solver = new Solver("MagicSequence"); Console.WriteLine("\nSize: {0}", size); // // data // int[] all_values = new int[size]; for (int i = 0; i < size; i++) { all_values[i] = i; } // // Decision variables // IntVar[] all_vars = solver.MakeIntVarArray(size, 0, size - 1, "vars"); // // Constraints // solver.Add(all_vars.Distribute(all_values, all_vars)); solver.Add(all_vars.Sum() == size); // // Search // DecisionBuilder db = solver.MakePhase(all_vars, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { for(int i = 0; i < size; i++) { Console.Write(all_vars[i].Value() + " "); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * 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(); }
/* * Create Constraint Model and Solve Coloring Problem: */ public static void SolveAsConstraintProblem(int nbColors, int nbNodes, IEnumerable <Tuple <int, int> > edges) { var solver = new Solver("Coloring"); // One Decision Variable per Node: IntVar[] nodes = solver.MakeIntVarArray(nbNodes, 0, nbColors - 1); foreach (var edge in edges) { solver.Add(nodes[edge.Item1] != nodes[edge.Item2]); } // Some Symmetry breaking solver.Add(nodes[0] == 0); /* * Start Solver: */ DecisionBuilder db = solver.MakePhase(nodes, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); Console.WriteLine("Coloring Problem:\n\n"); solver.NewSearch(db); while (solver.NextSolution()) { for (int i = 0; i < nodes.Length; i++) { if (i < Names.Length) { Console.WriteLine("Node " + i + " obtains color " + Names.GetValue(nodes[i].Value())); } else { Console.WriteLine("Node " + i + " obtains color " + nodes[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(); Console.ReadKey(); }
/** * * Global constraint contiguity using regular * * This is a decomposition of the global constraint global contiguity. * * From Global Constraint Catalogue * http://www.emn.fr/x-info/sdemasse/gccat/Cglobal_contiguity.html * """ * Enforce all variables of the VARIABLES collection to be assigned to 0 or 1. * In addition, all variables assigned to value 1 appear contiguously. * * Example: * (<0, 1, 1, 0>) * * The global_contiguity constraint holds since the sequence 0 1 1 0 contains * no more than one group of contiguous 1. * """ * * Also see http://www.hakank.org/or-tools/contiguity_regular.py * */ private static void Solve() { Solver solver = new Solver("ContiguityRegular"); // // Data // int n = 7; // length of the array // // Decision variables // // Note: We use 1..2 (instead of 0..1) and subtract 1 in the solution IntVar[] reg_input = solver.MakeIntVarArray(n, 1, 2, "reg_input"); // // Constraints // MyContiguity(solver, reg_input); // // Search // DecisionBuilder db = solver.MakePhase(reg_input, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { for (int i = 0; i < n; i++) { // Note: here we subtract 1 to get 0..1 Console.Write((reg_input[i].Value() - 1) + " "); } 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(); }
/** * * Implements a (decomposition) of the global constraint circuit * and extracting the path. * * One circuit for n = 5 is 3 0 4 2 1 * Thus the extracted path is 0 -> 3 -> 2 -> 4 -> 1 -> 0 * */ private static void Solve(int n = 5) { Solver solver = new Solver("CircuitTest2"); // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 0, n - 1, "x"); IntVar[] path = solver.MakeIntVarArray(n, 0, n - 1, "path"); // // Constraints // circuit(solver, x, path); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db); while (solver.NextSolution()) { Console.Write("x : "); for (int i = 0; i < n; i++) { Console.Write("{0} ", x[i].Value()); } Console.Write("\npath: "); for (int i = 0; i < n; i++) { Console.Write("{0} ", path[i].Value()); } Console.WriteLine("\n"); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Implements toNum: channeling between a number and an array. * See http://www.hakank.org/or-tools/toNum.py * */ private static void Solve() { Solver solver = new Solver("ToNum"); int n = 5; int bbase = 10; // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 0, bbase - 1, "x"); IntVar num = solver.MakeIntVar(0, (int)Math.Pow(bbase, n) - 1, "num"); // // Constraints // solver.Add(x.AllDifferent()); solver.Add(ToNum(x, num, bbase)); // extra constraint (just for fun) // second digit should be 7 // solver.Add(x[1] == 7); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { Console.Write("\n" + num.Value() + ": "); for (int i = 0; i < n; i++) { Console.Write(x[i].Value() + " "); } } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/* * Xkcd Puzzle as Optimization Problem: */ private static void OptimizationModel(Solver solver, IntVar[] items, int[] prices) { /* * Objective Function: */ IntVar obj = solver.MakeScalProd(items, prices).Var(); /* * Constraints: */ solver.Add(obj < 2000); /* * 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("Xkcd Optimization 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("Appetizer " + items[i].Name() + " is ordered " + sol.Value(items[i]) + " times."); } 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(); Console.ReadKey(); }
/* * Main Method: */ public static void Solve() { var solver = new Solver("Grocery"); // One variable for each product: IntVar p1 = solver.MakeIntVar(0, 711); IntVar p2 = solver.MakeIntVar(0, 711); IntVar p3 = solver.MakeIntVar(0, 711); IntVar p4 = solver.MakeIntVar(0, 711); // Prices add up to 711: solver.Add(p1 + p2 + p3 + p4 == 711); // Product of individual prices is 711: solver.Add(p1 * p2 * p3 * p4 == 711 * 100 * 100 * 100); // Symmetry breaking constraint: /*solver.Add(p1 <= p2); * solver.Add(p2 <= p3); * solver.Add(p3 <= p4);*/ // Start Solver: DecisionBuilder db = solver.MakePhase(new[] { p1, p2, p3, p4 }, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); solver.NewSearch(db); while (solver.NextSolution()) { Console.WriteLine("Product 1: " + p1.Value()); Console.WriteLine("Product 2: " + p2.Value()); Console.WriteLine("Product 3: " + p3.Value()); Console.WriteLine("Product 4: " + p4.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(); Console.ReadKey(); }
/** * * Grocery problem. * * From Christian Schulte, Gert Smolka, Finite Domain * http://www.mozart-oz.org/documentation/fdt/ * Constraint Programming in Oz. A Tutorial. 2001. * """ * A kid goes into a grocery store and buys four items. The cashier * charges $7.11, the kid pays and is about to leave when the cashier * calls the kid back, and says 'Hold on, I multiplied the four items * instead of adding them; I'll try again; Hah, with adding them the * price still comes to $7.11'. What were the prices of the four items? * """ * */ private static void Solve() { Solver solver = new Solver("Grocery"); int n = 4; int c = 711; // // Decision variables // IntVar[] item = solver.MakeIntVarArray(n, 0, c / 2, "item"); // // Constraints // solver.Add(item.Sum() == c); // solver.Add(item[0] * item[1] * item[2] * item[3] == c * 100*100*100); // solver.Add(item.Prod() == c * 100*100*100); solver.Add(MyProd(item, c * 100 * 100 * 100)); // Symmetry breaking Decreasing(solver, item); // // Search // DecisionBuilder db = solver.MakePhase(item, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { for (int i = 0; i < n; i++) { Console.Write(item[i].Value() + " "); } Console.WriteLine(); } Console.WriteLine("\nWallTime: " + solver.WallTime() + "ms "); Console.WriteLine("Failures: " + solver.Failures()); Console.WriteLine("Branches: " + solver.Branches()); solver.EndSearch(); }
/** * * Solve the xkcd problem * See http://www.hakank.org/google_or_tools/xkcd.py * */ private static void Solve() { Solver solver = new Solver("Xkcd"); // // Constants, inits // int n = 6; // for price and total: multiplied by 100 to be able to use integers int[] price = { 215, 275, 335, 355, 420, 580 }; int total = 1505; // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 0, 10, "x"); // // Constraints // solver.Add(x.ScalProd(price) == total); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { for (int i = 0; i < n; i++) { Console.Write(x[i].Value() + " "); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0} ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0}", solver.Branches()); solver.EndSearch(); }
/** * * Solve the xkcd problem * See http://www.hakank.org/google_or_tools/xkcd.py * */ private static void Solve() { Solver solver = new Solver("Xkcd"); // // Constants, inits // int n = 6; // for price and total: multiplied by 100 to be able to use integers int[] price = {215, 275, 335, 355, 420, 580}; int total = 1505; // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 0, 10, "x"); // // Constraints // solver.Add(x.ScalProd(price) == total); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { for(int i = 0; i < n; i++) { Console.Write(x[i].Value() + " "); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0} ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0}", solver.Branches()); solver.EndSearch(); }
/** * Solves the rabbits + pheasants problem. We are seing 20 heads * and 56 legs. How many rabbits and how many pheasants are we thus * seeing? */ private static void Solve() { Solver solver = new Solver("RabbitsPheasants"); IntVar rabbits = solver.MakeIntVar(0, 100, "rabbits"); IntVar pheasants = solver.MakeIntVar(0, 100, "pheasants"); solver.Add(rabbits + pheasants == 20); solver.Add(rabbits * 4 + pheasants * 2 == 56); DecisionBuilder db = new AssignFirstUnboundToMin(new IntVar[] { rabbits, pheasants }); solver.NewSearch(db); solver.NextSolution(); Console.WriteLine("Solved Rabbits + Pheasants in {0} ms, and {1} search tree branches.", solver.WallTime(), solver.Branches()); Console.WriteLine(rabbits.ToString()); Console.WriteLine(pheasants.ToString()); solver.EndSearch(); }
/** * Solves the rabbits + pheasants problem. We are seing 20 heads * and 56 legs. How many rabbits and how many pheasants are we thus * seeing? */ private static void Solve() { Solver solver = new Solver("RabbitsPheasants"); IntVar rabbits = solver.MakeIntVar(0, 100, "rabbits"); IntVar pheasants = solver.MakeIntVar(0, 100, "pheasants"); solver.Add(rabbits + pheasants == 20); solver.Add(rabbits * 4 + pheasants * 2 == 56); DecisionBuilder db = new AssignFirstUnboundToMin(new IntVar[] {rabbits, pheasants}); solver.NewSearch(db); solver.NextSolution(); Console.WriteLine( "Solved Rabbits + Pheasants in {0} ms, and {1} search tree branches.", solver.WallTime(), solver.Branches()); Console.WriteLine(rabbits.ToString()); Console.WriteLine(pheasants.ToString()); solver.EndSearch(); }
/* * Xkcd Puzzle as Constraint Problem: */ private static void ConstraintModel(Solver solver, IntVar[] items, int[] prices) { /* * Constraints: */ solver.Add(solver.MakeScalProd(items, prices) == 1505); /* * Start Solver: */ DecisionBuilder db = solver.MakePhase(items, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); Console.WriteLine("XKCD Constraint Problem:\n\n"); solver.NewSearch(db); while (solver.NextSolution()) { for (int i = 0; i < items.Length; i++) { Console.WriteLine("Appetizer " + items[i].Name() + " is ordered " + items[i].Value() + " times."); } 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(); Console.ReadKey(); }
/** * * * Organizing a day. * * Simple scheduling problem. * * Problem formulation from ECLiPSe: * Slides on (Finite Domain) Constraint Logic Programming, page 38f * http://eclipse-clp.org/reports/eclipse.ppt * * * Also see http://www.hakank.org/google_or_tools/organize_day.py * */ private static void Solve() { Solver solver = new Solver("OrganizeDay"); int n = 4; int work = 0; int mail = 1; int shop = 2; int bank = 3; int[] tasks = {work, mail, shop, bank}; int[] durations = {4,1,2,1}; // task [i,0] must be finished before task [i,1] int[,] before_tasks = { {bank, shop}, {mail, work} }; // the valid times of the day int begin = 9; int end = 17; // // Decision variables // IntVar[] begins = solver.MakeIntVarArray(n, begin, end, "begins"); IntVar[] ends = solver.MakeIntVarArray(n, begin, end, "ends"); // // Constraints // foreach(int t in tasks) { solver.Add(ends[t] == begins[t] + durations[t]); } foreach(int i in tasks) { foreach(int j in tasks) { if (i < j) { NoOverlap(solver, begins[i], durations[i], begins[j], durations[j]); } } } // specific constraints for(int t = 0; t < before_tasks.GetLength(0); t++) { solver.Add(ends[before_tasks[t,0]] <= begins[before_tasks[t,1]]); } solver.Add(begins[work] >= 11); // // Search // DecisionBuilder db = solver.MakePhase(begins, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db); while (solver.NextSolution()) { foreach(int t in tasks) { Console.WriteLine("Task {0}: {1,2} .. ({2}) .. {3,2}", t, begins[t].Value(), durations[t], ends[t].Value()); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * KenKen puzzle. * * http://en.wikipedia.org/wiki/KenKen * """ * KenKen or KEN-KEN is a style of arithmetic and logical puzzle sharing * several characteristics with sudoku. The name comes from Japanese and * is translated as 'square wisdom' or 'cleverness squared'. * ... * The objective is to fill the grid in with the digits 1 through 6 such that: * * * Each row contains exactly one of each digit * * Each column contains exactly one of each digit * * Each bold-outlined group of cells is a cage containing digits which * achieve the specified result using the specified mathematical operation: * addition (+), * subtraction (-), * multiplication (x), * and division (/). * (Unlike in Killer sudoku, digits may repeat within a group.) * * ... * More complex KenKen problems are formed using the principles described * above but omitting the symbols +, -, x and /, thus leaving them as * yet another unknown to be determined. * """ * * The solution is: * * 5 6 3 4 1 2 * 6 1 4 5 2 3 * 4 5 2 3 6 1 * 3 4 1 2 5 6 * 2 3 6 1 4 5 * 1 2 5 6 3 4 * * * Also see http://www.hakank.org/or-tools/kenken2.py * though this C# model has another representation of * the problem instance. * */ private static void Solve() { Solver solver = new Solver("KenKen2"); // size of matrix int n = 6; IEnumerable<int> RANGE = Enumerable.Range(0, n); // For a better view of the problem, see // http://en.wikipedia.org/wiki/File:KenKenProblem.svg // hints // sum, the hints // Note: this is 1-based int[][] problem = { new int[] { 11, 1,1, 2,1}, new int[] { 2, 1,2, 1,3}, new int[] { 20, 1,4, 2,4}, new int[] { 6, 1,5, 1,6, 2,6, 3,6}, new int[] { 3, 2,2, 2,3}, new int[] { 3, 2,5, 3,5}, new int[] {240, 3,1, 3,2, 4,1, 4,2}, new int[] { 6, 3,3, 3,4}, new int[] { 6, 4,3, 5,3}, new int[] { 7, 4,4, 5,4, 5,5}, new int[] { 30, 4,5, 4,6}, new int[] { 6, 5,1, 5,2}, new int[] { 9, 5,6, 6,6}, new int[] { 8, 6,1, 6,2, 6,3}, new int[] { 2, 6,4, 6,5} }; int num_p = problem.GetLength(0); // Number of segments // // Decision variables // IntVar[,] x = solver.MakeIntVarMatrix(n, n, 1, n, "x"); IntVar[] x_flat = x.Flatten(); // // Constraints // // // alldifferent rows and columns foreach(int i in RANGE) { // rows solver.Add( (from j in RANGE select x[i,j]).ToArray().AllDifferent()); // cols solver.Add( (from j in RANGE select x[j,i]).ToArray().AllDifferent()); } // Calculate the segments for(int i = 0; i < num_p; i++) { int[] segment = problem[i]; // Remove the sum from the segment int len = segment.Length-1; int[] s2 = new int[len]; Array.Copy(segment, 1, s2, 0, len); // sum this segment calc(solver, s2, x, segment[0]); } // // Search // DecisionBuilder db = solver.MakePhase(x_flat, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db); while (solver.NextSolution()) { for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { Console.Write(x[i,j].Value() + " "); } Console.WriteLine(); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Crypto problem. * * This is the standard benchmark "crypto" problem. * * From GLPK:s model cryto.mod. * * """ * This problem comes from the newsgroup rec.puzzle. * The numbers from 1 to 26 are assigned to the letters of the alphabet. * The numbers beside each word are the total of the values assigned to * the letters in the word (e.g. for LYRE: L, Y, R, E might be to equal * 5, 9, 20 and 13, or any other combination that add up to 47). * Find the value of each letter under the equations: * * BALLET 45 GLEE 66 POLKA 59 SONG 61 * CELLO 43 JAZZ 58 QUARTET 50 SOPRANO 82 * CONCERT 74 LYRE 47 SAXOPHONE 134 THEME 72 * FLUTE 30 OBOE 53 SCALE 51 VIOLIN 100 * FUGUE 50 OPERA 65 SOLO 37 WALTZ 34 * * Solution: * A, B,C, D, E,F, G, H, I, J, K,L,M, N, O, P,Q, R, S,T,U, V,W, X, Y, Z * 5,13,9,16,20,4,24,21,25,17,23,2,8,12,10,19,7,11,15,3,1,26,6,22,14,18 * * Reference: * Koalog Constraint Solver <http://www.koalog.com/php/jcs.php>, * Simple problems, the crypto-arithmetic puzzle ALPHACIPHER. * """ * * Also see http://hakank.org/or-tools/crypto.py * */ private static void Solve() { Solver solver = new Solver("Crypto"); int num_letters = 26; int BALLET = 45; int CELLO = 43; int CONCERT = 74; int FLUTE = 30; int FUGUE = 50; int GLEE = 66; int JAZZ = 58; int LYRE = 47; int OBOE = 53; int OPERA = 65; int POLKA = 59; int QUARTET = 50; int SAXOPHONE = 134; int SCALE = 51; int SOLO = 37; int SONG = 61; int SOPRANO = 82; int THEME = 72; int VIOLIN = 100; int WALTZ = 34; // // Decision variables // IntVar[] LD = solver.MakeIntVarArray(num_letters, 1, num_letters, "LD"); // Note D is not used in the constraints below IntVar A = LD[0]; IntVar B = LD[1]; IntVar C = LD[2]; // IntVar D = LD[3]; IntVar E = LD[4]; IntVar F = LD[5]; IntVar G = LD[6]; IntVar H = LD[7]; IntVar I = LD[8]; IntVar J = LD[9]; IntVar K = LD[10]; IntVar L = LD[11]; IntVar M = LD[12]; IntVar N = LD[13]; IntVar O = LD[14]; IntVar P = LD[15]; IntVar Q = LD[16]; IntVar R = LD[17]; IntVar S = LD[18]; IntVar T = LD[19]; IntVar U = LD[20]; IntVar V = LD[21]; IntVar W = LD[22]; IntVar X = LD[23]; IntVar Y = LD[24]; IntVar Z = LD[25]; // // Constraints // solver.Add(LD.AllDifferent()); solver.Add( B + A + L + L + E + T == BALLET); solver.Add( C + E + L + L + O == CELLO); solver.Add( C + O + N + C + E + R + T == CONCERT); solver.Add( F + L + U + T + E == FLUTE); solver.Add( F + U + G + U + E == FUGUE); solver.Add( G + L + E + E == GLEE); solver.Add( J + A + Z + Z == JAZZ); solver.Add( L + Y + R + E == LYRE); solver.Add( O + B + O + E == OBOE); solver.Add( O + P + E + R + A == OPERA); solver.Add( P + O + L + K + A == POLKA); solver.Add( Q + U + A + R + T + E + T == QUARTET); solver.Add(S + A + X + O + P + H + O + N + E == SAXOPHONE); solver.Add( S + C + A + L + E == SCALE); solver.Add( S + O + L + O == SOLO); solver.Add( S + O + N + G == SONG); solver.Add( S + O + P + R + A + N + O == SOPRANO); solver.Add( T + H + E + M + E == THEME); solver.Add( V + I + O + L + I + N == VIOLIN); solver.Add( W + A + L + T + Z == WALTZ); // // Search // DecisionBuilder db = solver.MakePhase(LD, Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, Solver.ASSIGN_CENTER_VALUE); solver.NewSearch(db); String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; while (solver.NextSolution()) { for(int i = 0; i < num_letters; i++) { Console.WriteLine("{0}: {1,2}", str[i], LD[i].Value()); } Console.WriteLine(); } Console.WriteLine("\nWallTime: " + solver.WallTime() + "ms "); Console.WriteLine("Failures: " + solver.Failures()); Console.WriteLine("Branches: " + solver.Branches()); solver.EndSearch(); }
/** * * 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 int[, ] { { r, r, g, g }, { ry, r, y, r }, { g, g, r, r }, { 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(); }
/** * * Solves a set covering problem. * See See http://www.hakank.org/or-tools/set_covering4.py * */ private static void Solve(int set_partition) { Solver solver = new Solver("SetCovering4"); // // data // // Set partition and set covering problem from // Example from the Swedish book // Lundgren, Roennqvist, Vaebrand // 'Optimeringslaera' (translation: 'Optimization theory'), // page 408. int num_alternatives = 10; int num_objects = 8; // costs for the alternatives int[] costs = {19, 16, 18, 13, 15, 19, 15, 17, 16, 15}; // the alternatives, and their objects int[,] a = { // 1 2 3 4 5 6 7 8 the objects {1,0,0,0,0,1,0,0}, // alternative 1 {0,1,0,0,0,1,0,1}, // alternative 2 {1,0,0,1,0,0,1,0}, // alternative 3 {0,1,1,0,1,0,0,0}, // alternative 4 {0,1,0,0,1,0,0,0}, // alternative 5 {0,1,1,0,0,0,0,0}, // alternative 6 {0,1,1,1,0,0,0,0}, // alternative 7 {0,0,0,1,1,0,0,1}, // alternative 8 {0,0,1,0,0,1,0,1}, // alternative 9 {1,0,0,0,0,1,1,0}}; // alternative 10 // // Decision variables // IntVar[] x = solver.MakeIntVarArray(num_alternatives, 0, 1, "x"); // number of assigned senators, to be minimized IntVar z = x.ScalProd(costs).VarWithName("z"); // // Constraints // for(int j = 0; j < num_objects; j++) { IntVar[] b = new IntVar[num_alternatives]; for(int i = 0; i < num_alternatives; i++) { b[i] = (x[i] * a[i,j]).Var(); } if (set_partition == 1) { solver.Add(b.Sum() >= 1); } else { solver.Add(b.Sum() == 1); } } // // objective // OptimizeVar objective = z.Minimize(1); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db, objective); while (solver.NextSolution()) { Console.WriteLine("z: " + z.Value()); Console.Write("Selected alternatives: "); for(int i = 0; i < num_alternatives; i++) { if (x[i].Value() == 1) { Console.Write((i+1) + " "); } } Console.WriteLine("\n"); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Lectures problem in Google CP Solver. * * Biggs: Discrete Mathematics (2nd ed), page 187. * """ * Suppose we wish to schedule six one-hour lectures, v1, v2, v3, v4, v5, v6. * Among the the potential audience there are people who wish to hear both * * - v1 and v2 * - v1 and v4 * - v3 and v5 * - v2 and v6 * - v4 and v5 * - v5 and v6 * - v1 and v6 * * How many hours are necessary in order that the lectures can be given * without clashes? * """ * * Note: This can be seen as a coloring problem. * * Also see http://www.hakank.org/or-tools/lectures.py * */ private static void Solve() { Solver solver = new Solver("Lectures"); // // The schedule requirements: // lecture a cannot be held at the same time as b // Note: 1-based (compensated in the constraints). int[,] g = { {1, 2}, {1, 4}, {3, 5}, {2, 6}, {4, 5}, {5, 6}, {1, 6} }; // number of nodes int n = 6; // number of edges int edges = g.GetLength(0); // // Decision variables // // // declare variables // IntVar[] v = solver.MakeIntVarArray(n, 0, n-1,"v"); // Maximum color (hour) to minimize. // Note: since C# is 0-based, the // number of colors is max_c+1. IntVar max_c = v.Max().VarWithName("max_c"); // // Constraints // // Ensure that there are no clashes // also, adjust to 0-base. for(int i = 0; i < edges; i++) { solver.Add(v[g[i,0]-1] != v[g[i,1]-1]); } // Symmetry breaking: // - v0 has the color 0, // - v1 has either color 0 or 1 solver.Add(v[0] == 0); solver.Add(v[1] <= 1); // // Objective // OptimizeVar obj = max_c.Minimize(1); // // Search // DecisionBuilder db = solver.MakePhase(v, Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db, obj); while (solver.NextSolution()) { Console.WriteLine("\nmax hours: {0}", max_c.Value()+1); Console.WriteLine("v: " + String.Join(" ", (from i in Enumerable.Range(0, n) select v[i].Value()).ToArray())); for(int i = 0; i < n; i++) { Console.WriteLine("Lecture {0} at {1}h", i, v[i].Value()); } Console.WriteLine("\n"); } Console.WriteLine("\nSolutions: " + solver.Solutions()); Console.WriteLine("WallTime: " + solver.WallTime() + "ms "); Console.WriteLine("Failures: " + solver.Failures()); Console.WriteLine("Branches: " + solver.Branches()); solver.EndSearch(); }
/** * * Solves a Sudoku problem. * * This is a very simple 4x4 problem instance: * Problem 26: Shidoku from * "Taking Sudoku Seriously", page 61 * 4 _ _ _ * 3 1 _ _ * * _ _ 4 1 * _ _ _ 2 * */ private static void Solve() { Solver solver = new Solver("Sudoku"); // // data // int block_size = 2; IEnumerable<int> BLOCK = Enumerable.Range(0, block_size); int n = block_size * block_size; IEnumerable<int> RANGE = Enumerable.Range(0, n); // 0 marks an unknown value int[,] initial_grid = {{4, 0, 0, 0}, {3, 1, 0, 0}, {0, 0, 4, 1}, {0, 0, 0, 2}}; // // Decision variables // IntVar[,] grid = solver.MakeIntVarMatrix(n, n, 1, n, "grid"); IntVar[] grid_flat = grid.Flatten(); // // Constraints // // init foreach(int i in RANGE) { foreach(int j in RANGE) { if (initial_grid[i,j] > 0) { solver.Add(grid[i,j] == initial_grid[i,j]); } } } foreach(int i in RANGE) { // rows solver.Add( (from j in RANGE select grid[i,j]).ToArray().AllDifferent()); // cols solver.Add( (from j in RANGE select grid[j,i]).ToArray().AllDifferent()); } // blocks foreach(int i in BLOCK) { foreach(int j in BLOCK) { solver.Add( (from di in BLOCK from dj in BLOCK select grid[i*block_size+di, j*block_size+dj] ).ToArray().AllDifferent()); } } // // Search // DecisionBuilder db = solver.MakePhase(grid_flat, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); solver.NewSearch(db); while (solver.NextSolution()) { for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++){ Console.Write("{0} ", grid[i,j].Value()); } Console.WriteLine(); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Labeled dice problem. * * From Jim Orlin 'Colored letters, labeled dice: a logic puzzle' * http://jimorlin.wordpress.com/2009/02/17/colored-letters-labeled-dice-a-logic-puzzle/ * """ * My daughter Jenn bough a puzzle book, and showed me a cute puzzle. There * are 13 words as follows: BUOY, CAVE, CELT, FLUB, FORK, HEMP, JUDY, * JUNK, LIMN, QUIP, SWAG, VISA, WISH. * * There are 24 different letters that appear in the 13 words. The question * is: can one assign the 24 letters to 4 different cubes so that the * four letters of each word appears on different cubes. (There is one * letter from each word on each cube.) It might be fun for you to try * it. I'll give a small hint at the end of this post. The puzzle was * created by Humphrey Dudley. * """ * * Jim Orlin's followup 'Update on Logic Puzzle': * http://jimorlin.wordpress.com/2009/02/21/update-on-logic-puzzle/ * * * Also see http://www.hakank.org/or-tools/labeled_dice.py * */ private static void Solve() { Solver solver = new Solver("LabeledDice"); // // Data // int n = 4; int m = 24; int A = 0; int B = 1; int C = 2; int D = 3; int E = 4; int F = 5; int G = 6; int H = 7; int I = 8; int J = 9; int K = 10; int L = 11; int M = 12; int N = 13; int O = 14; int P = 15; int Q = 16; int R = 17; int S = 18; int T = 19; int U = 20; int V = 21; int W = 22; int Y = 23; String[] letters_str = {"A","B","C","D","E","F","G","H","I","J","K","L","M", "N","O","P","Q","R","S","T","U","V","W","Y"}; int num_words = 13; int[,] words = { {B,U,O,Y}, {C,A,V,E}, {C,E,L,T}, {F,L,U,B}, {F,O,R,K}, {H,E,M,P}, {J,U,D,Y}, {J,U,N,K}, {L,I,M,N}, {Q,U,I,P}, {S,W,A,G}, {V,I,S,A}, {W,I,S,H} }; // // Decision variables // IntVar[] dice = solver.MakeIntVarArray(m, 0, n-1, "dice"); IntVar[] gcc = solver.MakeIntVarArray(n, 6, 6, "gcc"); // // Constraints // // the letters in a word must be on a different die for(int i = 0; i < num_words; i++) { solver.Add( (from j in Enumerable.Range(0, n) select dice[words[i,j]] ).ToArray().AllDifferent()); } // there must be exactly 6 letters of each die /* for(int i = 0; i < n; i++) { solver.Add( ( from j in Enumerable.Range(0, m) select (dice[j] == i) ).ToArray().Sum() == 6 ); } */ // Use Distribute (Global Cardinality Count) instead. solver.Add(dice.Distribute(gcc)); // // Search // DecisionBuilder db = solver.MakePhase(dice, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { for(int d = 0; d < n; d++) { Console.Write("die {0}: ", d); for(int i = 0; i < m; i++) { if (dice[i].Value() == d) { Console.Write(letters_str[i]); } } Console.WriteLine(); } Console.WriteLine("The words with the cube label:"); for(int i = 0; i < num_words; i++) { for(int j = 0; j < n; j++) { Console.Write("{0} ({1})", letters_str[words[i,j]], dice[words[i,j]].Value()); } Console.WriteLine(); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Implements the Who killed Agatha problem. * See http://www.hakank.org/google_or_tools/who_killed_agatha.py * */ private static void Solve() { Solver solver = new Solver("WhoKilledAgatha"); int n = 3; int agatha = 0; int butler = 1; int charles = 2; // // Decision variables // IntVar the_killer = solver.MakeIntVar(0, 2, "the_killer"); IntVar the_victim = solver.MakeIntVar(0, 2, "the_victim"); IntVar[,] hates = solver.MakeIntVarMatrix(n, n, 0, 1, "hates"); IntVar[] hates_flat = hates.Flatten(); IntVar[,] richer = solver.MakeIntVarMatrix(n, n, 0, 1, "richer"); IntVar[] richer_flat = richer.Flatten(); IntVar[] all = new IntVar[2 * n * n]; // for branching for(int i = 0; i < n*n; i++) { all[i] = hates_flat[i]; all[(n*n)+i] = richer_flat[i]; } // // Constraints // // Agatha, the butler, and Charles live in Dreadsbury Mansion, and // are the only ones to live there. // A killer always hates, and is no richer than his victim. // hates[the_killer, the_victim] == 1 // hates_flat[the_killer * n + the_victim] == 1 solver.Add(hates_flat.Element(the_killer * n + the_victim) == 1); // richer[the_killer, the_victim] == 0 solver.Add(richer_flat.Element(the_killer * n + the_victim) == 0); // define the concept of richer: // no one is richer than him-/herself... for(int i = 0; i < n; i++) { solver.Add(richer[i,i] == 0); } // (contd...) if i is richer than j then j is not richer than i // if (i != j) => // ((richer[i,j] = 1) <=> (richer[j,i] = 0)) for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { if (i != j) { solver.Add((richer[i, j]==1) - (richer[j, i]==0) == 0); } } } // Charles hates no one that Agatha hates. // forall i in 0..2: // (hates[agatha, i] = 1) => (hates[charles, i] = 0) for(int i = 0; i < n; i++) { solver.Add((hates[agatha,i]==1) - (hates[charles,i]==0) <= 0); } // Agatha hates everybody except the butler. solver.Add(hates[agatha,charles] == 1); solver.Add(hates[agatha,agatha] == 1); solver.Add(hates[agatha,butler] == 0); // The butler hates everyone not richer than Aunt Agatha. // forall i in 0..2: // (richer[i, agatha] = 0) => (hates[butler, i] = 1) for(int i = 0; i < n; i++) { solver.Add((richer[i,agatha] == 0)-(hates[butler,i] == 1)<=0); } // The butler hates everyone whom Agatha hates. // forall i : 0..2: // (hates[agatha, i] = 1) => (hates[butler, i] = 1) for(int i = 0; i < n; i++) { solver.Add((hates[agatha,i] == 1)-(hates[butler,i] == 1)<=0); } // Noone hates everyone. // forall i in 0..2: // (sum j in 0..2: hates[i,j]) <= 2 for(int i = 0; i < n; i++) { solver.Add((from j in Enumerable.Range(0, n) select hates[i,j] ).ToArray().Sum() <= 2 ); } // Who killed Agatha? solver.Add(the_victim == agatha); // // Search // DecisionBuilder db = solver.MakePhase(all, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { Console.WriteLine("the_killer: " + the_killer.Value()); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Just forgotten puzzle (Enigma 1517) in Google CP Solver. * * From http://www.f1compiler.com/samples/Enigma 201517.f1.html * """ * Enigma 1517 Bob Walker, New Scientist magazine, October 25, 2008. * * Joe was furious when he forgot one of his bank account numbers. * He remembered that it had all the digits 0 to 9 in some order, * so he tried the following four sets without success: * * 9 4 6 2 1 5 7 8 3 0 * 8 6 0 4 3 9 1 2 5 7 * 1 6 4 0 2 9 7 8 5 3 * 6 8 2 4 3 1 9 0 7 5 * * When Joe finally remembered his account number, he realised that * in each set just four of the digits were in their correct position * and that, if one knew that, it was possible to work out his * account number. What was it? * """ * * Also see http://www.hakank.org/google_or_tools/just_forgotten.py * */ private static void Solve() { Solver solver = new Solver("JustForgotten"); int rows = 4; int cols = 10; // The four tries int[,] a = {{9,4,6,2,1,5,7,8,3,0}, {8,6,0,4,3,9,1,2,5,7}, {1,6,4,0,2,9,7,8,5,3}, {6,8,2,4,3,1,9,0,7,5}}; // // Decision variables // IntVar[] x = solver.MakeIntVarArray(cols, 0, 9, "x"); // // Constraints // solver.Add(x.AllDifferent()); for(int r = 0; r < rows; r++) { solver.Add( (from c in Enumerable.Range(0, cols) select x[c] == a[r,c]).ToArray().Sum() == 4); } // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db); while (solver.NextSolution()) { Console.WriteLine("Account number:"); for(int j = 0; j < cols; j++) { Console.Write(x[j].Value() + " "); } Console.WriteLine("\n"); Console.WriteLine("The four tries, where '!' represents a correct digit:"); for(int i = 0; i < rows; i++) { for(int j = 0; j < cols; j++) { String c = " "; if (a[i,j] == x[j].Value()) { c = "!"; } Console.Write("{0}{1} ", a[i,j], c); } Console.WriteLine(); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Solves some stable marriage problems. * * This version randomize the problem instances. * * Also, see http://www.hakank.org/or-tools/stable_marriage.cs * * */ private static void Solve(int n = 10, int sols_to_show = 0) { Solver solver = new Solver("StableMarriage"); // // data // int seed = (int)DateTime.Now.Ticks; Random generator = new Random(seed); int[][] rankMen = new int[n][]; int[][] rankWomen = new int[n][]; for (int i = 0; i < n; i++) { int[] m = shuffle(n, generator); int[] w = shuffle(n, generator); rankMen[i] = new int[n]; rankWomen[i] = new int[n]; for (int j = 0; j < n; j++) { rankMen[i][j] = m[j]; rankWomen[i][j] = w[j]; } } Console.WriteLine("after generating..."); if (n <= 20) { Console.Write("rankMen: "); printRank("rankMen", rankMen); printRank("rankWomen", rankWomen); } // // Decision variables // IntVar[] wife = solver.MakeIntVarArray(n, 0, n - 1, "wife"); IntVar[] husband = solver.MakeIntVarArray(n, 0, n - 1, "husband"); // // Constraints // // (The comments below are the Comet code) // // forall(m in Men) // cp.post(husband[wife[m]] == m); for(int m = 0; m < n; m++) { solver.Add(husband.Element(wife[m]) == m); } // forall(w in Women) // cp.post(wife[husband[w]] == w); for(int w = 0; w < n; w++) { solver.Add(wife.Element(husband[w]) == w); } // forall(m in Men, o in Women) // cp.post(rankMen[m,o] < rankMen[m, wife[m]] => // rankWomen[o,husband[o]] < rankWomen[o,m]); for(int m = 0; m < n; m++) { for(int o = 0; o < n; o++) { IntVar b1 = rankMen[m].Element(wife[m]) > rankMen[m][o]; IntVar b2 = rankWomen[o].Element(husband[o]) < rankWomen[o][m]; solver.Add(b1 <= b2); } } // forall(w in Women, o in Men) // cp.post(rankWomen[w,o] < rankWomen[w,husband[w]] => // rankMen[o,wife[o]] < rankMen[o,w]); for(int w = 0; w < n; w++) { for(int o = 0; o < n; o++) { IntVar b1 = rankWomen[w].Element(husband[w]) > rankWomen[w][o]; IntVar b2 = rankMen[o].Element(wife[o]) < rankMen[o][w]; solver.Add(b1 <= b2); } } // // Search // DecisionBuilder db = solver.MakePhase(wife, // Solver.INT_VAR_DEFAULT, // Solver.INT_VAR_SIMPLE, Solver.CHOOSE_FIRST_UNBOUND, // Solver.CHOOSE_RANDOM, // Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, // Solver.CHOOSE_MIN_SIZE_HIGHEST_MIN, // Solver.CHOOSE_MIN_SIZE_LOWEST_MAX, // Solver.CHOOSE_MIN_SIZE_HIGHEST_MAX, // Solver.CHOOSE_PATH, // Solver.CHOOSE_MIN_SIZE, // Solver.CHOOSE_MAX_SIZE, // Solver.CHOOSE_MAX_REGRET, // Solver.INT_VALUE_DEFAULT // Solver.INT_VALUE_SIMPLE Solver.ASSIGN_MIN_VALUE // Solver.ASSIGN_MAX_VALUE // Solver.ASSIGN_RANDOM_VALUE // Solver.ASSIGN_CENTER_VALUE // Solver.SPLIT_LOWER_HALF // Solver.SPLIT_UPPER_HALF ); solver.NewSearch(db); int sols = 0; while (solver.NextSolution()) { sols += 1; Console.Write("wife : "); for(int i = 0; i < n; i++) { Console.Write(wife[i].Value() + " "); } Console.Write("\nhusband: "); for(int i = 0; i < n; i++) { Console.Write(husband[i].Value() + " "); } Console.WriteLine("\n"); if (sols_to_show > 0 && sols >= sols_to_show) { break; } } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Moving furnitures (scheduling) problem in Google CP Solver. * * Marriott & Stukey: 'Programming with constraints', page 112f * * The model implements an decomposition of the global constraint * cumulative (see above). * * Also see http://www.hakank.org/or-tools/furniture_moving.py * */ private static void Solve() { Solver solver = new Solver("FurnitureMoving"); int n = 4; int[] duration = {30,10,15,15}; int[] demand = { 3, 1, 3, 2}; int upper_limit = 160; // // Decision variables // IntVar[] start_times = solver.MakeIntVarArray(n, 0, upper_limit, "start_times"); IntVar[] end_times = solver.MakeIntVarArray(n, 0, upper_limit * 2, "end_times"); IntVar end_time = solver.MakeIntVar(0, upper_limit * 2, "end_time"); // number of needed resources, to be minimized or constrained IntVar num_resources = solver.MakeIntVar(0, 10, "num_resources"); // // Constraints // for(int i = 0; i < n; i++) { solver.Add(end_times[i] == start_times[i] + duration[i]); } solver.Add(end_time == end_times.Max()); MyCumulative(solver, start_times, duration, demand, num_resources); // // Some extra constraints to play with // // all tasks must end within an hour // solver.Add(end_time <= 60); // All tasks should start at time 0 // for(int i = 0; i < n; i++) { // solver.Add(start_times[i] == 0); // } // limitation of the number of people // solver.Add(num_resources <= 3); solver.Add(num_resources <= 4); // // Objective // // OptimizeVar obj = num_resources.Minimize(1); OptimizeVar obj = end_time.Minimize(1); // // Search // DecisionBuilder db = solver.MakePhase(start_times, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db, obj); while (solver.NextSolution()) { Console.WriteLine("num_resources: {0} end_time: {1}", num_resources.Value(), end_time.Value()); for(int i = 0; i < n; i++) { Console.WriteLine("Task {0,1}: {1,2} -> {2,2} -> {3,2} (demand: {4})", i, start_times[i].Value(), duration[i], end_times[i].Value(), demand[i]); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * 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(); }
/** * * 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(); }
/** * * Implements a (decomposition) of the global constraint circuit. * See http://www.hakank.org/google_or_tools/circuit.py * */ private static void Solve(int n = 5) { Solver solver = new Solver("Circuit"); // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 0, n-1, "x"); // // Constraints // circuit(solver, x); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db); while (solver.NextSolution()) { for(int i = 0; i < n; i++) { Console.Write("{0} ", x[i].Value()); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Hidato puzzle in Google CP Solver. * * http://www.hidato.com/ * """ * Puzzles start semi-filled with numbered tiles. * The first and last numbers are circled. * Connect the numbers together to win. Consecutive * number must touch horizontally, vertically, or * diagonally. * """ * * This is a port of the Python model hidato_table.py * made by Laurent Perron (using AllowedAssignments), * based on my (much slower) model hidato.py. * */ private static void Solve(int model = 1) { Solver solver = new Solver("HidatoTable"); // // models, a 0 indicates an open cell which number is not yet known. // int[,] puzzle = null; if (model == 1) { // Simple problem // Solution 1: // 6 7 9 // 5 2 8 // 1 4 3 int[,] puzzle1 = {{6, 0, 9}, {0, 2, 8}, {1, 0, 0}}; puzzle = puzzle1; } else if (model == 2) { int[,] puzzle2 = {{0, 44, 41, 0, 0, 0, 0}, {0, 43, 0, 28, 29, 0, 0}, {0, 1, 0, 0, 0, 33, 0}, {0, 2, 25, 4, 34, 0, 36}, {49, 16, 0, 23, 0, 0, 0}, {0, 19, 0, 0, 12, 7, 0}, {0, 0, 0, 14, 0, 0, 0}}; puzzle = puzzle2; } else if (model == 3) { // Problems from the book: // Gyora Bededek: "Hidato: 2000 Pure Logic Puzzles" // Problem 1 (Practice) int[,] puzzle3 = {{0, 0, 20, 0, 0}, {0, 0, 0, 16, 18}, {22, 0, 15, 0, 0}, {23, 0, 1, 14, 11}, {0, 25, 0, 0, 12}}; puzzle = puzzle3; } else if (model == 4) { // problem 2 (Practice) int[,] puzzle4 = {{0, 0, 0, 0, 14}, {0, 18, 12, 0, 0}, {0, 0, 17, 4, 5}, {0, 0, 7, 0, 0}, {9, 8, 25, 1, 0}}; puzzle = puzzle4; } else if (model == 5) { // problem 3 (Beginner) int[,] puzzle5 = {{0, 26, 0, 0, 0, 18}, {0, 0, 27, 0, 0, 19}, {31, 23, 0, 0, 14, 0}, {0, 33, 8, 0, 15, 1}, {0, 0, 0, 5, 0, 0}, {35, 36, 0, 10, 0, 0}}; puzzle = puzzle5; } else if (model == 6) { // Problem 15 (Intermediate) int[,] puzzle6 = {{64, 0, 0, 0, 0, 0, 0, 0}, {1, 63, 0, 59, 15, 57, 53, 0}, {0, 4, 0, 14, 0, 0, 0, 0}, {3, 0, 11, 0, 20, 19, 0, 50}, {0, 0, 0, 0, 22, 0, 48, 40}, {9, 0, 0, 32, 23, 0, 0, 41}, {27, 0, 0, 0, 36, 0, 46, 0}, {28, 30, 0, 35, 0, 0, 0, 0}}; puzzle = puzzle6; } int r = puzzle.GetLength(0); int c = puzzle.GetLength(1); Console.WriteLine(); Console.WriteLine("----- Solving problem {0} -----", model); Console.WriteLine(); PrintMatrix(puzzle); // // Decision variables // IntVar[] positions = solver.MakeIntVarArray(r*c, 0, r * c - 1, "p"); // // Constraints // solver.Add(positions.AllDifferent()); // // Fill in the clues // for(int i = 0; i < r; i++) { for(int j = 0; j < c; j++) { if (puzzle[i,j] > 0) { solver.Add(positions[puzzle[i,j] - 1] == i * c + j); } } } // Consecutive numbers much touch each other in the grid. // We use an allowed assignment constraint to model it. IntTupleSet close_tuples = BuildPairs(r, c); for(int k = 1; k < r * c - 1; k++) { IntVar[] tmp = new IntVar[] {positions[k], positions[k + 1]}; solver.Add(tmp.AllowedAssignments(close_tuples)); } // // Search // DecisionBuilder db = solver.MakePhase(positions, Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); int num_solution = 0; while (solver.NextSolution()) { num_solution++; PrintOneSolution(positions, r, c, num_solution); } Console.WriteLine("\nSolutions: " + solver.Solutions()); Console.WriteLine("WallTime: " + solver.WallTime() + "ms "); Console.WriteLine("Failures: " + solver.Failures()); Console.WriteLine("Branches: " + solver.Branches()); solver.EndSearch(); }
/** * * Solves a set covering problem. * See See http://www.hakank.org/or-tools/set_covering2.py * */ private static void Solve() { Solver solver = new Solver("SetCovering2"); // // data // // Example 9.1-2 from // Taha "Operations Research - An Introduction", // page 354ff. // Minimize the number of security telephones in street // corners on a campus. int n = 8; // maximum number of corners int num_streets = 11; // number of connected streets // corners of each street // Note: 1-based (handled below) int[,] corner = {{1,2}, {2,3}, {4,5}, {7,8}, {6,7}, {2,6}, {1,6}, {4,7}, {2,4}, {5,8}, {3,5}}; // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 0, 1, "x"); // number of telephones, to be minimized IntVar z = x.Sum().Var(); // // Constraints // // ensure that all streets are covered for(int i = 0; i < num_streets; i++) { solver.Add(x[corner[i,0] - 1] + x[corner[i,1] - 1] >= 1); } // // objective // OptimizeVar objective = z.Minimize(1); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db, objective); while (solver.NextSolution()) { Console.WriteLine("z: {0}", z.Value()); Console.Write("x: "); for(int i = 0; i < n; i++) { Console.Write(x[i].Value() + " "); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Implements Young tableaux and partitions. * See http://www.hakank.org/or-tools/young_tableuax.py * */ private static void Solve(int n) { Solver solver = new Solver("YoungTableaux"); // // data // Console.WriteLine("n: {0}\n", n); // // Decision variables // IntVar[,] x = solver.MakeIntVarMatrix(n, n, 1, n + 1, "x"); IntVar[] x_flat = x.Flatten(); // partition structure IntVar[] p = solver.MakeIntVarArray(n, 0, n + 1, "p"); // // Constraints // // 1..n is used exactly once for(int i = 1; i <= n; i++) { solver.Add(x_flat.Count(i, 1)); } solver.Add(x[0,0] == 1); // row wise for(int i = 0; i < n; i++) { for(int j = 1; j < n; j++) { solver.Add(x[i,j] >= x[i,j - 1]); } } // column wise for(int j = 0; j < n; j++) { for(int i = 1; i < n; i++) { solver.Add(x[i,j] >= x[i - 1, j]); } } // calculate the structure (i.e. the partition) for(int i = 0; i < n; i++) { IntVar[] b = new IntVar[n]; for(int j = 0; j < n; j++) { b[j] = x[i, j] <= n; } solver.Add(p[i] == b.Sum()); } solver.Add(p.Sum() == n); for(int i = 1; i < n; i++) { solver.Add(p[i - 1] >= p[i]); } // // Search // DecisionBuilder db = solver.MakePhase(x_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { Console.Write("p: "); for(int i = 0; i < n; i++) { Console.Write(p[i].Value() + " "); } Console.WriteLine("\nx:"); for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { long val = x[i,j].Value(); if (val <= n) { Console.Write(val + " "); } } if (p[i].Value() > 0) { Console.WriteLine(); } } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * A programming puzzle from Einav. * * From * "A programming puzzle from Einav" * http://gcanyon.wordpress.com/2009/10/28/a-programming-puzzle-from-einav/ * """ * My friend Einav gave me this programming puzzle to work on. Given * this array of positive and negative numbers: * 33 30 -10 -6 18 7 -11 -23 6 * ... * -25 4 16 30 33 -23 -4 4 -23 * * You can flip the sign of entire rows and columns, as many of them * as you like. The goal is to make all the rows and columns sum to positive * numbers (or zero), and then to find the solution (there are more than one) * that has the smallest overall sum. So for example, for this array: * 33 30 -10 * -16 19 9 * -17 -12 -14 * You could flip the sign for the bottom row to get this array: * 33 30 -10 * -16 19 9 * 17 12 14 * Now all the rows and columns have positive sums, and the overall total is * 108. * But you could instead flip the second and third columns, and the second * row, to get this array: * 33 -30 10 * 16 19 9 * -17 12 14 * All the rows and columns still total positive, and the overall sum is just * 66. So this solution is better (I don't know if it's the best) * A pure brute force solution would have to try over 30 billion solutions. * I wrote code to solve this in J. I'll post that separately. * """ * * Note: * This is a port of Larent Perrons's Python version of my own einav_puzzle.py. * He removed some of the decision variables and made it more efficient. * Thanks! * * Also see http://www.hakank.org/or-tools/einav_puzzle2.py * */ private static void Solve() { Solver solver = new Solver("EinavPuzzle2"); // // Data // // Small problem // int rows = 3; // int cols = 3; // int[,] data = { // { 33, 30, -10}, // {-16, 19, 9}, // {-17, -12, -14} // }; // Full problem int rows = 27; int cols = 9; int[,] data = { {33,30,10,-6,18,-7,-11,23,-6}, {16,-19,9,-26,-8,-19,-8,-21,-14}, {17,12,-14,31,-30,13,-13,19,16}, {-6,-11,1,17,-12,-4,-7,14,-21}, {18,-31,34,-22,17,-19,20,24,6}, {33,-18,17,-15,31,-5,3,27,-3}, {-18,-20,-18,31,6,4,-2,-12,24}, {27,14,4,-29,-3,5,-29,8,-12}, {-15,-7,-23,23,-9,-8,6,8,-12}, {33,-23,-19,-4,-8,-7,11,-12,31}, {-20,19,-15,-30,11,32,7,14,-5}, {-23,18,-32,-2,-31,-7,8,24,16}, {32,-4,-10,-14,-6,-1,0,23,23}, {25,0,-23,22,12,28,-27,15,4}, {-30,-13,-16,-3,-3,-32,-3,27,-31}, {22,1,26,4,-2,-13,26,17,14}, {-9,-18,3,-20,-27,-32,-11,27,13}, {-17,33,-7,19,-32,13,-31,-2,-24}, {-31,27,-31,-29,15,2,29,-15,33}, {-18,-23,15,28,0,30,-4,12,-32}, {-3,34,27,-25,-18,26,1,34,26}, {-21,-31,-10,-13,-30,-17,-12,-26,31}, {23,-31,-19,21,-17,-10,2,-23,23}, {-3,6,0,-3,-32,0,-10,-25,14}, {-19,9,14,-27,20,15,-5,-27,18}, {11,-6,24,7,-17,26,20,-31,-25}, {-25,4,-16,30,33,23,-4,-4,23} }; IEnumerable<int> ROWS = Enumerable.Range(0, rows); IEnumerable<int> COLS = Enumerable.Range(0, cols); // // Decision variables // IntVar[,] x = solver.MakeIntVarMatrix(rows, cols, -100, 100, "x"); IntVar[] x_flat = x.Flatten(); int[] signs_domain = {-1,1}; // This don't work at the moment... IntVar[] row_signs = solver.MakeIntVarArray(rows, signs_domain, "row_signs"); IntVar[] col_signs = solver.MakeIntVarArray(cols, signs_domain, "col_signs"); // To optimize IntVar total_sum = x_flat.Sum().VarWithName("total_sum"); // // Constraints // foreach(int i in ROWS) { foreach(int j in COLS) { solver.Add(x[i,j] == data[i,j] * row_signs[i] * col_signs[j]); } } // row sums IntVar[] row_sums = (from i in ROWS select (from j in COLS select x[i,j] ).ToArray().Sum().Var()).ToArray(); foreach(int i in ROWS) { row_sums[i].SetMin(0); } // col sums IntVar[] col_sums = (from j in COLS select (from i in ROWS select x[i,j] ).ToArray().Sum().Var()).ToArray(); foreach(int j in COLS) { col_sums[j].SetMin(0); } // // Objective // OptimizeVar obj = total_sum.Minimize(1); // // Search // DecisionBuilder db = solver.MakePhase(col_signs.Concat(row_signs).ToArray(), Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, Solver.ASSIGN_MAX_VALUE); solver.NewSearch(db, obj); while (solver.NextSolution()) { Console.WriteLine("Sum: {0}",total_sum.Value()); Console.Write("row_sums: "); foreach(int i in ROWS) { Console.Write(row_sums[i].Value() + " "); } Console.Write("\nrow_signs: "); foreach(int i in ROWS) { Console.Write(row_signs[i].Value() + " "); } Console.Write("\ncol_sums: "); foreach(int j in COLS) { Console.Write(col_sums[j].Value() + " "); } Console.Write("\ncol_signs: "); foreach(int j in COLS) { Console.Write(col_signs[j].Value() + " "); } Console.WriteLine("\n"); foreach(int i in ROWS) { foreach(int j in COLS) { Console.Write("{0,3} ", x[i,j].Value()); } Console.WriteLine(); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
private static long Run(int[][] costs, long bestCost = 0) { bool finalSearch = bestCost > 0; long result = 0; Solver solver = new Solver("Assignment"); int bots = costs.Length; // rows int tasks = costs[0].Length; // cols // Decision variables IntVar[,] x = solver.MakeBoolVarMatrix(bots, tasks, "x"); IntVar[] x_flat = x.Flatten(); // Dynamic Constraints if (bots > tasks) { // Each bot is assigned to at most 1 task for (int i = 0; i < bots; i++) { solver.Add((from j in Enumerable.Range(0, tasks) select x[i, j]).ToArray().Sum() <= 1); } // Each task is assigned to exactly one bot for (int j = 0; j < tasks; j++) { solver.Add((from i in Enumerable.Range(0, bots) select x[i, j]).ToArray().Sum() == 1); } } else { // Each task is assigned to exactly one bot for (int i = 0; i < bots; i++) { solver.Add((from j in Enumerable.Range(0, tasks) select x[i, j]).ToArray().Sum() == 1); } // Each bot is assigned to at most 1 task for (int j = 0; j < tasks; j++) { solver.Add((from i in Enumerable.Range(0, bots) select x[i, j]).ToArray().Sum() <= 1); } } // Total cost IntVar total_cost = (from i in Enumerable.Range(0, bots) from j in Enumerable.Range(0, tasks) select(costs[i][j] * x[i, j])).ToArray().Sum().Var(); if (bestCost > 0) { solver.Add(total_cost == bestCost); } // Search DecisionBuilder db = solver.MakePhase(x_flat, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); if (!finalSearch) { // Objective OptimizeVar objective = total_cost.Minimize(1); solver.NewSearch(db, objective); } else { solver.NewSearch(db); } while (solver.NextSolution()) { output.Clear(); result = total_cost.Value(); Console.WriteLine($"total_cost: {result}"); if (finalSearch) { for (int i = 0; i < bots; i++) { for (int j = 0; j < tasks; j++) { Console.Write(x[i, j].Value() + " "); } Console.WriteLine(); } } for (int i = 0; i < bots; i++) { bool isAssigned = false; for (int j = 0; j < tasks; j++) { if (x[i, j].Value() == 1) { output.Add(new Tuple <int, int>(i, j)); isAssigned = true; } } if (!isAssigned) { output.Add(new Tuple <int, int>(i, -1)); } } } 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.WriteLine("Number of constraints = " + solver.Constraints()); solver.EndSearch(); return(result); }
/** * * Secret Santa problem in Google CP Solver. * * From Ruby Quiz Secret Santa * http://www.rubyquiz.com/quiz2.html * """ * Honoring a long standing tradition started by my wife's dad, my friends * all play a Secret Santa game around Christmas time. We draw names and * spend a week sneaking that person gifts and clues to our identity. On the * last night of the game, we get together, have dinner, share stories, and, * most importantly, try to guess who our Secret Santa was. It's a crazily * fun way to enjoy each other's company during the holidays. * * To choose Santas, we use to draw names out of a hat. This system was * tedious, prone to many 'Wait, I got myself...' problems. This year, we * made a change to the rules that further complicated picking and we knew * the hat draw would not stand up to the challenge. Naturally, to solve * this problem, I scripted the process. Since that turned out to be more * interesting than I had expected, I decided to share. * * This weeks Ruby Quiz is to implement a Secret Santa selection script. * * Your script will be fed a list of names on STDIN. * ... * Your script should then choose a Secret Santa for every name in the list. * Obviously, a person cannot be their own Secret Santa. In addition, my friends * no longer allow people in the same family to be Santas for each other and your * script should take this into account. * """ * * Comment: This model skips the file input and mail parts. We * assume that the friends are identified with a number from 1..n, * and the families is identified with a number 1..num_families. * * Also see http://www.hakank.org/or-tools/secret_santa.py * Also see http://www.hakank.org/or-tools/secret_santa2.cs * */ private static void Solve() { Solver solver = new Solver("SecretSanta"); int[] family = {1,1,1,1, 2, 3,3,3,3,3, 4,4}; int n = family.Length; Console.WriteLine("n = {0}", n); IEnumerable<int> RANGE = Enumerable.Range(0, n); // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 0, n-1, "x"); // // Constraints // solver.Add(x.AllDifferent()); // Can't be one own"s Secret Santa // (i.e. ensure that there are no fix-point in the array.) foreach(int i in RANGE) { solver.Add(x[i] != i); } // No Secret Santa to a person in the same family foreach(int i in RANGE) { solver.Add(solver.MakeIntConst(family[i]) != family.Element(x[i])); } // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); solver.NewSearch(db); while (solver.NextSolution()) { Console.Write("x: "); foreach(int i in RANGE) { Console.Write(x[i].Value() + " "); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * 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(); }
/** * * Coin application. * * From "Constraint Logic Programming using ECLiPSe" * pages 99f and 234 ff. * The solution in ECLiPSe is at page 236. * * """ * What is the minimum number of coins that allows one to pay _exactly_ * any amount smaller than one Euro? Recall that there are six different * euro cents, of denomination 1, 2, 5, 10, 20, 50 * """ * Also see http://www.hakank.org/or-tools/coins3.py * */ private static void Solve() { Solver solver = new Solver("Coins3"); // // Data // int n = 6; // number of different coins int[] variables = {1, 2, 5, 10, 25, 50}; IEnumerable<int> RANGE = Enumerable.Range(0, n); // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 0, 99, "x"); IntVar num_coins = x.Sum().VarWithName("num_coins"); // // Constraints // // Check that all changes from 1 to 99 can be made. for(int j = 1; j < 100; j++) { IntVar[] tmp = solver.MakeIntVarArray(n, 0, 99, "tmp"); solver.Add(tmp.ScalProd(variables) == j); foreach(int i in RANGE) { solver.Add(tmp[i] <= x[i]); } } // // Objective // OptimizeVar obj = num_coins.Minimize(1); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_MIN_SIZE_LOWEST_MAX, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db, obj); while (solver.NextSolution()) { Console.WriteLine("num_coins: {0}", num_coins.Value()); Console.Write("x: "); foreach(int i in RANGE) { Console.Write(x[i].Value() + " "); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Nurse rostering * * This is a simple nurse rostering model using a DFA and * the built-in TransitionConstraint. * * The DFA is from MiniZinc Tutorial, Nurse Rostering example: * - one day off every 4 days * - no 3 nights in a row. * * Also see: * - http://www.hakank.org/or-tools/nurse_rostering.py * - http://www.hakank.org/or-tools/nurse_rostering_regular.cs * which use (a decomposition of) regular constraint * */ private static void Solve(int nurse_multiplier, int week_multiplier) { Console.WriteLine("Starting Nurse Rostering"); Console.WriteLine(" - {0} teams of 7 nurses", nurse_multiplier); Console.WriteLine(" - {0} blocks of 14 days", week_multiplier); Solver solver = new Solver("NurseRostering"); // // Data // // Note: If you change num_nurses or num_days, // please also change the constraints // on nurse_stat and/or day_stat. int num_nurses = 7 * nurse_multiplier; int num_days = 14 * week_multiplier; // Note: I had to add a dummy shift. int dummy_shift = 0; int day_shift = 1; int night_shift = 2; int off_shift = 3; int[] shifts = { dummy_shift, day_shift, night_shift, off_shift }; int[] valid_shifts = { day_shift, night_shift, off_shift }; // the DFA (for regular) int initial_state = 1; int[] accepting_states = { 1, 2, 3, 4, 5, 6 }; /* * // This is the transition function * // used in nurse_rostering_regular.cs * int[,] transition_fn = { * // d,n,o * {2,3,1}, // state 1 * {4,4,1}, // state 2 * {4,5,1}, // state 3 * {6,6,1}, // state 4 * {6,0,1}, // state 5 * {0,0,1} // state 6 * }; */ // For TransitionConstraint IntTupleSet transition_tuples = new IntTupleSet(3); // state, input, next state transition_tuples.InsertAll(new long[][] { new long[] { 1, 1, 2 }, new long[] { 1, 2, 3 }, new long[] { 1, 3, 1 }, new long[] { 2, 1, 4 }, new long[] { 2, 2, 4 }, new long[] { 2, 3, 1 }, new long[] { 3, 1, 4 }, new long[] { 3, 2, 5 }, new long[] { 3, 3, 1 }, new long[] { 4, 1, 6 }, new long[] { 4, 2, 6 }, new long[] { 4, 3, 1 }, new long[] { 5, 1, 6 }, new long[] { 5, 3, 1 }, new long[] { 6, 3, 1 } }); string[] days = { "d", "n", "o" }; // for presentation // // Decision variables // // // For TransitionConstraint // IntVar[,] x = solver.MakeIntVarMatrix(num_nurses, num_days, valid_shifts, "x"); IntVar[] x_flat = x.Flatten(); // // summary of the nurses // IntVar[] nurse_stat = new IntVar[num_nurses]; // // summary of the shifts per day // int num_shifts = shifts.Length; IntVar[,] day_stat = new IntVar[num_days, num_shifts]; for (int i = 0; i < num_days; i++) { for (int j = 0; j < num_shifts; j++) { day_stat[i, j] = solver.MakeIntVar(0, num_nurses, "day_stat"); } } // // Constraints // for (int i = 0; i < num_nurses; i++) { IntVar[] reg_input = new IntVar[num_days]; for (int j = 0; j < num_days; j++) { reg_input[j] = x[i, j]; } solver.Add(reg_input.Transition(transition_tuples, initial_state, accepting_states)); } // // Statistics and constraints for each nurse // for (int nurse = 0; nurse < num_nurses; nurse++) { // Number of worked days (either day or night shift) IntVar[] nurse_days = new IntVar[num_days]; for (int day = 0; day < num_days; day++) { nurse_days[day] = x[nurse, day].IsMember(new int[] { day_shift, night_shift }); } nurse_stat[nurse] = nurse_days.Sum().Var(); // Each nurse must work between 7 and 10 // days/nights during this period solver.Add(nurse_stat[nurse] >= 7 * week_multiplier / nurse_multiplier); solver.Add(nurse_stat[nurse] <= 10 * week_multiplier / nurse_multiplier); } // // Statistics and constraints for each day // for (int day = 0; day < num_days; day++) { IntVar[] nurses = new IntVar[num_nurses]; for (int nurse = 0; nurse < num_nurses; nurse++) { nurses[nurse] = x[nurse, day]; } IntVar[] stats = new IntVar[num_shifts]; for (int shift = 0; shift < num_shifts; ++shift) { stats[shift] = day_stat[day, shift]; } solver.Add(nurses.Distribute(stats)); // // Some constraints for each day: // // Note: We have a strict requirements of // the number of shifts. // Using atleast constraints is harder // in this model. // if (day % 7 == 5 || day % 7 == 6) { // special constraints for the weekends solver.Add(day_stat[day, day_shift] == 2 * nurse_multiplier); solver.Add(day_stat[day, night_shift] == nurse_multiplier); solver.Add(day_stat[day, off_shift] == 4 * nurse_multiplier); } else { // for workdays: // - exactly 3 on day shift solver.Add(day_stat[day, day_shift] == 3 * nurse_multiplier); // - exactly 2 on night solver.Add(day_stat[day, night_shift] == 2 * nurse_multiplier); // - exactly 2 off duty solver.Add(day_stat[day, off_shift] == 2 * nurse_multiplier); } } // // Search // DecisionBuilder db = solver.MakePhase(x_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); SearchMonitor log = solver.MakeSearchLog(1000000); solver.NewSearch(db, log); int num_solutions = 0; while (solver.NextSolution()) { num_solutions++; for (int i = 0; i < num_nurses; i++) { Console.Write("Nurse #{0,-2}: ", i); var occ = new Dictionary <int, int>(); for (int j = 0; j < num_days; j++) { int v = (int)x[i, j].Value() - 1; if (!occ.ContainsKey(v)) { occ[v] = 0; } occ[v]++; Console.Write(days[v] + " "); } Console.Write(" #workdays: {0,2}", nurse_stat[i].Value()); foreach (int s in valid_shifts) { int v = 0; if (occ.ContainsKey(s - 1)) { v = occ[s - 1]; } Console.Write(" {0}:{1}", days[s - 1], v); } Console.WriteLine(); } Console.WriteLine(); Console.WriteLine("Statistics per day:\nDay d n o"); for (int j = 0; j < num_days; j++) { Console.Write("Day #{0,2}: ", j); foreach (int t in valid_shifts) { Console.Write(day_stat[j, t].Value() + " "); } Console.WriteLine(); } Console.WriteLine(); // We just show 2 solutions if (num_solutions > 1) { break; } } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Olympic puzzle. * * Benchmark for Prolog (BProlog) * """ * File : olympic.pl * Author : Neng-Fa ZHOU * Date : 1993 * * Purpose: solve a puzzle taken from Olympic Arithmetic Contest * * Given ten variables with the following configuration: * * X7 X8 X9 X10 * * X4 X5 X6 * * X2 X3 * * X1 * * We already know that X1 is equal to 3 and want to assign each variable * with a different integer from {1,2,...,10} such that for any three * variables * Xi Xj * * Xk * * the following constraint is satisfied: * * |Xi-Xj| = Xk * """ * * Also see http://www.hakank.org/or-tools/olympic.py * */ private static void Solve() { Solver solver = new Solver("Olympic"); // // Data // int n = 10; // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 1, n, "x"); IntVar X1 = x[0]; IntVar X2 = x[1]; IntVar X3 = x[2]; IntVar X4 = x[3]; IntVar X5 = x[4]; IntVar X6 = x[5]; IntVar X7 = x[6]; IntVar X8 = x[7]; IntVar X9 = x[8]; IntVar X10 = x[9]; // // Constraints // solver.Add(x.AllDifferent()); solver.Add(X1 == 3); minus(solver, X2, X3, X1); minus(solver, X4, X5, X2); minus(solver, X5, X6, X3); minus(solver, X7, X8, X4); minus(solver, X8, X9, X5); minus(solver, X9, X10, X6); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db); while (solver.NextSolution()) { for(int i = 0; i < n; i++) { Console.Write("{0,2} ", x[i].Value()); } Console.WriteLine(); } Console.WriteLine("\nSolutions: " + solver.Solutions()); Console.WriteLine("WallTime: " + solver.WallTime() + "ms "); Console.WriteLine("Failures: " + solver.Failures()); Console.WriteLine("Branches: " + solver.Branches()); solver.EndSearch(); }
/** * * Solves the Magic Square problem. * See http://www.hakank.org/or-tools/magic_square.py * */ private static void Solve(int n = 4, int num = 0, int print = 1) { Solver solver = new Solver("MagicSquare"); Console.WriteLine("n: {0}", n); // // Decision variables // IntVar[,] x = solver.MakeIntVarMatrix(n, n, 1, n * n, "x"); // for the branching IntVar[] x_flat = x.Flatten(); // // Constraints // long s = (n * (n * n + 1)) / 2; Console.WriteLine("s: " + s); IntVar[] diag1 = new IntVar[n]; IntVar[] diag2 = new IntVar[n]; for (int i = 0; i < n; i++) { IntVar[] row = new IntVar[n]; for (int j = 0; j < n; j++) { row[j] = x[i, j]; } // sum row to s solver.Add(row.Sum() == s); diag1[i] = x[i, i]; diag2[i] = x[i, n - i - 1]; } // sum diagonals to s solver.Add(diag1.Sum() == s); solver.Add(diag2.Sum() == s); // sum columns to s for (int j = 0; j < n; j++) { IntVar[] col = new IntVar[n]; for (int i = 0; i < n; i++) { col[i] = x[i, j]; } solver.Add(col.Sum() == s); } // all are different solver.Add(x_flat.AllDifferent()); // symmetry breaking: upper left is 1 // solver.Add(x[0,0] == 1); // // Search // DecisionBuilder db = solver.MakePhase(x_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_CENTER_VALUE); solver.NewSearch(db); int c = 0; while (solver.NextSolution()) { if (print != 0) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { Console.Write(x[i, j].Value() + " "); } Console.WriteLine(); } Console.WriteLine(); } c++; if (num > 0 && c >= num) { break; } } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Solves a simple map coloring problem. * * Alternative version, using a matrix to represent * the neighbours. * * See http://www.hakank.org/google_or_tools/map.py * * */ private static void Solve() { Solver solver = new Solver("Map2"); // // data // int Belgium = 0; int Denmark = 1; int France = 2; int Germany = 3; int Netherlands = 4; int Luxembourg = 5; int n = 6; int max_num_colors = 4; int[,] neighbours = {{France, Belgium}, {France, Luxembourg}, {France, Germany}, {Luxembourg, Germany}, {Luxembourg, Belgium}, {Belgium, Netherlands}, {Belgium, Germany}, {Germany, Netherlands}, {Germany, Denmark}}; // // Decision variables // IntVar[] color = solver.MakeIntVarArray(n, 1, max_num_colors, "color"); // // Constraints // for(int i = 0; i < neighbours.GetLength(0); i++) { solver.Add(color[neighbours[i,0]] != color[neighbours[i,1]]); } // Symmetry breaking solver.Add(color[Belgium] == 1); // // Search // DecisionBuilder db = solver.MakePhase(color, Solver.CHOOSE_MIN_SIZE_LOWEST_MAX, Solver.ASSIGN_CENTER_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { Console.Write("colors: "); for(int i = 0; i < n; i++) { Console.Write("{0} ", color[i].Value()); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Magic squares and cards problem. * * Martin Gardner (July 1971) * """ * Allowing duplicates values, what is the largest constant sum for an order-3 * magic square that can be formed with nine cards from the deck. * """ * * * Also see http://www.hakank.org/or-tools/magic_square_and_cards.py * */ private static void Solve(int n = 3) { Solver solver = new Solver("MagicSquareAndCards"); IEnumerable <int> RANGE = Enumerable.Range(0, n); // // Decision variables // IntVar[,] x = solver.MakeIntVarMatrix(n, n, 1, 13, "x"); IntVar[] x_flat = x.Flatten(); IntVar s = solver.MakeIntVar(1, 13 * 4, "s"); IntVar[] counts = solver.MakeIntVarArray(14, 0, 4, "counts"); // // Constraints // solver.Add(x_flat.Distribute(counts)); // the standard magic square constraints (sans all_different) foreach (int i in RANGE) { // rows solver.Add((from j in RANGE select x[i, j]).ToArray().Sum() == s); // columns solver.Add((from j in RANGE select x[j, i]).ToArray().Sum() == s); } // diagonals solver.Add((from i in RANGE select x[i, i]).ToArray().Sum() == s); solver.Add((from i in RANGE select x[i, n - i - 1]).ToArray().Sum() == s); // redundant constraint solver.Add(counts.Sum() == n * n); // // Objective // OptimizeVar obj = s.Maximize(1); // // Search // DecisionBuilder db = solver.MakePhase(x_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MAX_VALUE); solver.NewSearch(db, obj); while (solver.NextSolution()) { Console.WriteLine("s: {0}", s.Value()); Console.Write("counts:"); for (int i = 0; i < 14; i++) { Console.Write(counts[i].Value() + " "); } Console.WriteLine(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { Console.Write(x[i, j].Value() + " "); } Console.WriteLine(); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Crew allocation problem in Google CP Solver. * * From Gecode example crew * examples/crew.cc * """ * Example: Airline crew allocation * * Assign 20 flight attendants to 10 flights. Each flight needs a certain * number of cabin crew, and they have to speak certain languages. * Every cabin crew member has two flights off after an attended flight. * """ * * Also see http://www.hakank.org/or-tools/crew.pl * */ private static void Solve(int sols = 1, int minimize = 0) { Solver solver = new Solver("Crew"); // // Data // string[] names = {"Tom", "David", "Jeremy", "Ron", "Joe", "Bill", "Fred", "Bob", "Mario", "Ed", "Carol", "Janet", "Tracy", "Marilyn", "Carolyn", "Cathy", "Inez", "Jean", "Heather", "Juliet"}; int num_persons = names.Length; // // Attributes of the crew // int[,] attributes = { // steward, hostess, french, spanish, german {1,0,0,0,1}, // Tom = 0 {1,0,0,0,0}, // David = 1 {1,0,0,0,1}, // Jeremy = 2 {1,0,0,0,0}, // Ron = 3 {1,0,0,1,0}, // Joe = 4 {1,0,1,1,0}, // Bill = 5 {1,0,0,1,0}, // Fred = 6 {1,0,0,0,0}, // Bob = 7 {1,0,0,1,1}, // Mario = 8 {1,0,0,0,0}, // Ed = 9 {0,1,0,0,0}, // Carol = 10 {0,1,0,0,0}, // Janet = 11 {0,1,0,0,0}, // Tracy = 12 {0,1,0,1,1}, // Marilyn = 13 {0,1,0,0,0}, // Carolyn = 14 {0,1,0,0,0}, // Cathy = 15 {0,1,1,1,1}, // Inez = 16 {0,1,1,0,0}, // Jean = 17 {0,1,0,1,1}, // Heather = 18 {0,1,1,0,0} // Juliet = 19 }; // // Required number of crew members. // // The columns are in the following order: // staff : Overall number of cabin crew needed // stewards : How many stewards are required // hostesses : How many hostesses are required // french : How many French speaking employees are required // spanish : How many Spanish speaking employees are required // german : How many German speaking employees are required // int[,] required_crew = { {4,1,1,1,1,1}, // Flight 1 {5,1,1,1,1,1}, // Flight 2 {5,1,1,1,1,1}, // .. {6,2,2,1,1,1}, {7,3,3,1,1,1}, {4,1,1,1,1,1}, {5,1,1,1,1,1}, {6,1,1,1,1,1}, {6,2,2,1,1,1}, // ... {7,3,3,1,1,1} // Flight 10 }; int num_flights = required_crew.GetLength(0); // // Decision variables // IntVar[,] crew = solver.MakeIntVarMatrix(num_flights, num_persons, 0, 1, "crew"); IntVar[] crew_flat = crew.Flatten(); // number of working persons IntVar num_working = solver.MakeIntVar(1, num_persons, "num_working"); // // Constraints // // number of working persons IntVar[] nw = new IntVar[num_persons]; for(int p = 0; p < num_persons; p++) { IntVar[] tmp = new IntVar[num_flights]; for(int f = 0; f < num_flights; f++) { tmp[f] = crew[f,p]; } nw[p] = tmp.Sum() > 0; } solver.Add(nw.Sum() == num_working); for(int f = 0; f < num_flights; f++) { // size of crew IntVar[] tmp = new IntVar[num_persons]; for(int p = 0; p < num_persons; p++) { tmp[p] = crew[f,p]; } solver.Add(tmp.Sum() == required_crew[f,0]); // attributes and requirements for(int a = 0; a < 5; a++) { IntVar[] tmp2 = new IntVar[num_persons]; for(int p = 0; p < num_persons; p++) { tmp2[p] = (crew[f,p]*attributes[p,a]).Var(); } solver.Add(tmp2.Sum() >= required_crew[f,a+1]); } } // after a flight, break for at least two flights for(int f = 0; f < num_flights - 2; f++) { for(int i = 0; i < num_persons; i++) { solver.Add(crew[f,i] + crew[f+1,i] + crew[f+2,i] <= 1); } } // extra contraint: all must work at least two of the flights /* for(int p = 0; p < num_persons; p++) { IntVar[] tmp = new IntVar[num_flights]; for(int f = 0; f < num_flights; f++) { tmp[f] = crew[f,p]; } solver.Add(tmp.Sum() >= 2); } */ // // Search // DecisionBuilder db = solver.MakePhase(crew_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); if (minimize > 0) { OptimizeVar obj = num_working.Minimize(1); solver.NewSearch(db, obj); } else { solver.NewSearch(db); } int num_solutions = 0; while (solver.NextSolution()) { num_solutions++; Console.WriteLine("Solution #{0}", num_solutions); Console.WriteLine("Number working: {0}", num_working.Value()); for(int f = 0; f < num_flights; f++) { for(int p = 0; p < num_persons; p++) { Console.Write(crew[f,p].Value() + " "); } Console.WriteLine(); } Console.WriteLine("\nFlights: "); for(int f = 0; f < num_flights; f++) { Console.Write("Flight #{0}: ", f); for(int p = 0; p < num_persons; p++) { if (crew[f, p].Value() == 1) { Console.Write(names[p] + " "); } } Console.WriteLine(); } Console.WriteLine("\nCrew:"); for(int p = 0; p < num_persons; p++) { Console.Write("{0,-10}", names[p]); for(int f = 0; f < num_flights; f++) { if (crew[f,p].Value() == 1) { Console.Write(f + " "); } } Console.WriteLine(); } Console.WriteLine(); if (num_solutions >= sols) { break; } } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }