/* * Decompositon of cumulative. * * Inspired by the MiniZinc implementation: * http://www.g12.csse.unimelb.edu.au/wiki/doku.php?id=g12:zinc:lib:minizinc:std:cumulative.mzn&s[]=cumulative * The MiniZinc decomposition is discussed in the paper: * A. Schutt, T. Feydy, P.J. Stuckey, and M. G. Wallace. * "Why cumulative decomposition is not as bad as it sounds." * Download: * http://www.cs.mu.oz.au/%7Epjs/rcpsp/papers/cp09-cu.pdf * http://www.cs.mu.oz.au/%7Epjs/rcpsp/cumu_lazyfd.pdf * * * Parameters: * * s: start_times assumption: IntVar[] * d: durations assumption: int[] * r: resources assumption: int[] * b: resource limit assumption: IntVar or int * * */ static void MyCumulative(Solver solver, IntVar[] s, int[] d, int[] r, IntVar b) { int[] tasks = (from i in Enumerable.Range(0, s.Length) where r[i] > 0 && d[i] > 0 select i).ToArray(); int times_min = tasks.Min(i => (int)s[i].Min()); int d_max = d.Max(); int times_max = tasks.Max(i => (int)s[i].Max() + d_max); for(int t = times_min; t <= times_max; t++) { ArrayList bb = new ArrayList(); foreach(int i in tasks) { bb.Add(((s[i] <= t) * (s[i] + d[i]> t) * r[i]).Var()); } solver.Add((bb.ToArray(typeof(IntVar)) as IntVar[]).Sum() <= b); } // Somewhat experimental: // This constraint is needed to constrain the upper limit of b. if (b is IntVar) { solver.Add(b <= r.Sum()); } }
/** * * 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(); }
// We don't need helper functions here // Csharp syntax is easier than C++ syntax! private static void CPisFun (int kBase) { // Constraint Programming engine Solver solver = new Solver ("CP is fun!"); // Decision variables IntVar c = solver.MakeIntVar (1, kBase - 1, "C"); IntVar p = solver.MakeIntVar (0, kBase - 1, "P"); IntVar i = solver.MakeIntVar (1, kBase - 1, "I"); IntVar s = solver.MakeIntVar (0, kBase - 1, "S"); IntVar f = solver.MakeIntVar (1, kBase - 1, "F"); IntVar u = solver.MakeIntVar (0, kBase - 1, "U"); IntVar n = solver.MakeIntVar (0, kBase - 1, "N"); IntVar t = solver.MakeIntVar (1, kBase - 1, "T"); IntVar r = solver.MakeIntVar (0, kBase - 1, "R"); IntVar e = solver.MakeIntVar (0, kBase - 1, "E"); // We need to group variables in a vector to be able to use // the global constraint AllDifferent IntVar[] letters = new IntVar[] { c, p, i, s, f, u, n, t, r, e}; // Check if we have enough digits if (kBase < letters.Length) { throw new Exception("kBase < letters.Length"); } // Constraints solver.Add (letters.AllDifferent ()); // CP + IS + FUN = TRUE solver.Add (p + s + n + kBase * (c + i + u) + kBase * kBase * f == e + kBase * u + kBase * kBase * r + kBase * kBase * kBase * t); SolutionCollector all_solutions = solver.MakeAllSolutionCollector(); // Add the interesting variables to the SolutionCollector all_solutions.Add(c); all_solutions.Add(p); // Create the variable kBase * c + p IntVar v1 = solver.MakeSum(solver.MakeProd(c, kBase), p).Var(); // Add it to the SolutionCollector all_solutions.Add(v1); // Decision Builder: hot to scour the search tree DecisionBuilder db = solver.MakePhase (letters, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.Solve(db, all_solutions); // Retrieve the solutions int numberSolutions = all_solutions.SolutionCount(); Console.WriteLine ("Number of solutions: " + numberSolutions); for (int index = 0; index < numberSolutions; ++index) { Assignment solution = all_solutions.Solution(index); Console.WriteLine ("Solution found:"); Console.WriteLine ("v1=" + solution.Value(v1)); } }
/** * * 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(); }
/** * Ensure that the sum of the segments * in cc == res * */ public static void calc(Solver solver, int[] cc, IntVar[,] x, int res) { int ccLen = cc.Length; if (ccLen == 4) { // for two operands there's // a lot of possible variants IntVar a = x[cc[0]-1, cc[1]-1]; IntVar b = x[cc[2]-1, cc[3]-1]; IntVar r1 = a + b == res; IntVar r2 = a * b == res; IntVar r3 = a * res == b; IntVar r4 = b * res == a; IntVar r5 = a - b == res; IntVar r6 = b - a == res; solver.Add(r1+r2+r3+r4+r5+r6 >= 1); } else { // For length > 2 then res is either the sum // the the product of the segment // sum the numbers int len = cc.Length / 2; IntVar[] xx = (from i in Enumerable.Range(0, len) select x[cc[i*2]-1,cc[i*2+1]-1]).ToArray(); // Sum IntVar this_sum = xx.Sum() == res; // Product // IntVar this_prod = (xx.Prod() == res).Var(); // don't work IntVar this_prod; if (xx.Length == 3) { this_prod = (x[cc[0]-1,cc[1]-1] * x[cc[2]-1,cc[3]-1] * x[cc[4]-1,cc[5]-1]) == res; } else { this_prod = ( x[cc[0]-1,cc[1]-1] * x[cc[2]-1,cc[3]-1] * x[cc[4]-1,cc[5]-1] * x[cc[6]-1,cc[7]-1]) == res; } solver.Add(this_sum + this_prod >= 1); } }
/** * * 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(); }
/** * * 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(); }
/** * * 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(); }
/** * * 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(); }
public static void minus(Solver solver, IntVar x, IntVar y, IntVar z) { solver.Add(z == (x - y).Abs()); }
/** * * 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(); }
/** * * 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(); }
/** * Ensure that the sum of the segments * in cc == res * */ public static void calc(Solver solver, int[] cc, IntVar[,] x, int res) { // ensure that the values are positive int len = cc.Length / 2; for(int i = 0; i < len; i++) { solver.Add(x[cc[i*2]-1,cc[i*2+1]-1] >= 1); } // sum the numbers solver.Add( (from i in Enumerable.Range(0, len) select x[cc[i*2]-1,cc[i*2+1]-1]) .ToArray().Sum() == res); }
/** * * A simple propagator for modulo constraint. * * This implementation is based on the ECLiPSe version * mentioned in "A Modulo propagator for ECLiPSE" * http://www.hakank.org/constraint_programming_blog/2010/05/a_modulo_propagator_for_eclips.html * The ECLiPSe Prolog source code: * http://www.hakank.org/eclipse/modulo_propagator.ecl * */ public static void MyMod(Solver solver, IntVar x, IntVar y, IntVar r) { long lbx = x.Min(); long ubx = x.Max(); long ubx_neg = -ubx; long lbx_neg = -lbx; int min_x = (int)Math.Min(lbx, ubx_neg); int max_x = (int)Math.Max(ubx, lbx_neg); IntVar d = solver.MakeIntVar(min_x, max_x, "d"); // r >= 0 solver.Add(r >= 0); // x*r >= 0 solver.Add( x*r >= 0); // -abs(y) < r solver.Add(-y.Abs() < r); // r < abs(y) solver.Add(r < y.Abs()); // min_x <= d, i.e. d > min_x solver.Add(d > min_x); // d <= max_x solver.Add(d <= max_x); // x == y*d+r solver.Add(x - (y*d + r) == 0); }
public static IntVar[] subset_sum(Solver solver, int[] values, int total) { int n = values.Length; IntVar[] x = solver.MakeIntVarArray(n, 0, n, "x"); solver.Add(x.ScalProd(values) == total); return x; }
// // Decomposition of alldifferent_except_0 // public static void AllDifferentExcept0(Solver solver, IntVar[] a) { int n = a.Length; for(int i = 0; i < n; i++) { for(int j = 0; j < i; j++) { solver.Add((a[i] != 0) * (a[j] != 0) <= (a[i] != a[j])); } } }
/** * 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(); }
/** * Ensure that the sum of the segments * in cc == res * */ public static void calc(Solver solver, int[] cc, IntVar[,] x, int res) { // sum the numbers int len = cc.Length / 2; solver.Add( (from i in Enumerable.Range(0, len) select x[cc[i*2]-1,cc[i*2+1]-1]).ToArray().Sum() == res); }
/** * * 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(); }
/* * Global constraint regular * * This is a translation of MiniZinc's regular constraint (defined in * lib/zinc/globals.mzn), via the Comet code refered above. * All comments are from the MiniZinc code. * """ * The sequence of values in array 'x' (which must all be in the range 1..S) * is accepted by the DFA of 'Q' states with input 1..S and transition * function 'd' (which maps (1..Q, 1..S) -> 0..Q)) and initial state 'q0' * (which must be in 1..Q) and accepting states 'F' (which all must be in * 1..Q). We reserve state 0 to be an always failing state. * """ * * x : IntVar array * Q : number of states * S : input_max * d : transition matrix * q0: initial state * F : accepting states * */ static void MyRegular(Solver solver, IntVar[] x, int Q, int S, int[,] d, int q0, int[] F) { // d2 is the same as d, except we add one extra transition for // each possible input; each extra transition is from state zero // to state zero. This allows us to continue even if we hit a // non-accepted input. int[][] d2 = new int[Q+1][]; for(int i = 0; i <= Q; i++) { int[] row = new int[S]; for(int j = 0; j < S; j++) { if (i == 0) { row[j] = 0; } else { row[j] = d[i-1,j]; } } d2[i] = row; } int[] d2_flatten = (from i in Enumerable.Range(0, Q+1) from j in Enumerable.Range(0, S) select d2[i][j]).ToArray(); // If x has index set m..n, then a[m-1] holds the initial state // (q0), and a[i+1] holds the state we're in after processing // x[i]. If a[n] is in F, then we succeed (ie. accept the // string). int m = 0; int n = x.Length; IntVar[] a = solver.MakeIntVarArray(n+1-m, 0,Q+1, "a"); // Check that the final state is in F solver.Add(a[a.Length-1].Member(F)); // First state is q0 solver.Add(a[m] == q0); for(int i = 0; i < n; i++) { solver.Add(x[i] >= 1); solver.Add(x[i] <= S); // Determine a[i+1]: a[i+1] == d2[a[i], x[i]] solver.Add(a[i+1] == d2_flatten.Element(((a[i]*S)+(x[i]-1)))); } }
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; }
// // Partition the sets (binary matrix representation). // public static void partition_sets(Solver solver, IntVar[,] x, int num_sets, int n) { for(int i = 0; i <num_sets; i++) { for(int j = 0; j <num_sets; j++) { if (i != j) { // b = solver.Sum([x[i,k]*x[j,k] for k in range(n)]); // solver.Add(b == 0); solver.Add( (from k in Enumerable.Range(0, n) select (x[i,k]*x[j,k])). ToArray().Sum() == 0); } } } // ensure that all integers is in // (exactly) one partition solver.Add( (from i in Enumerable.Range(0, num_sets) from j in Enumerable.Range(0, n) select x[i,j]).ToArray().Sum() == n); }
/** * * 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(); }
/** * * 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(); }
static void MyContiguity(Solver solver, IntVar[] x) { // the DFA (for regular) int initial_state = 1; // all states are accepting states int[] accepting_states = {1,2,3}; // The regular expression 0*1*0* {state, input, next state} int[,] transition_tuples = { {1, 0, 1}, {1, 1, 2}, {2, 0, 3}, {2, 1, 2}, {3, 0, 3} }; IntTupleSet result = new IntTupleSet(3); result.InsertAll(transition_tuples); solver.Add(x.Transition(result, initial_state, accepting_states)); }
/** * circuit(solver, x, z) * * A decomposition of the global constraint circuit, based * on some observation of the orbits in an array. * * This version also exposes z (the path) to the public. * * Note: The domain of x must be 0..n-1 (not 1..n) * since C# is 0-based. */ public static void circuit(Solver solver, IntVar[] x, IntVar[] z) { int n = x.Length; solver.Add(x.AllDifferent()); solver.Add(z.AllDifferent()); // put the orbit of x[0] in z[0..n-1] solver.Add(z[0] == x[0]); for(int i = 1; i < n-1; i++) { solver.Add(z[i] == x.Element(z[i-1])); } // z may not be 0 for i < n-1 for(int i = 1; i < n - 1; i++) { solver.Add(z[i] != 0); } // when i = n-1 it must be 0 solver.Add(z[n - 1] == 0); }
/** * * 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(); }
/** * * 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(); }
static void Main(string[] args) { InitTaskList(); int taskCount = GetTaskCount(); Solver solver = new Solver("ResourceConstraintScheduling"); IntervalVar[] tasks = new IntervalVar[taskCount]; IntVar[] taskChoosed = new IntVar[taskCount]; IntVar[] makeSpan = new IntVar[GetEndTaskCount()]; int endJobCounter = 0; foreach (Job j in myJobList) { IntVar[] tmp = new IntVar[j.AlternativeTasks.Count]; int i = 0; foreach (Task t in j.AlternativeTasks) { long ti = taskIndexes[t.Name]; taskChoosed[ti] = solver.MakeIntVar(0, 1, t.Name + "_choose"); tmp[i++] = taskChoosed[ti]; tasks[ti] = solver.MakeFixedDurationIntervalVar( 0, 100000, t.Duration, false, t.Name + "_interval"); if (j.Successor == null) { makeSpan[endJobCounter++] = tasks[ti].EndExpr().Var(); } if (!tasksToEquipment.ContainsKey(t.Equipment)) { tasksToEquipment[t.Equipment] = new List <IntervalVar>(); } tasksToEquipment[t.Equipment].Add(tasks[ti]); } solver.Add(IntVarArrayHelper.Sum(tmp) == 1); } List <SequenceVar> all_seq = new List <SequenceVar>(); foreach (KeyValuePair <long, List <IntervalVar> > pair in tasksToEquipment) { DisjunctiveConstraint dc = solver.MakeDisjunctiveConstraint( pair.Value.ToArray(), pair.Key.ToString()); solver.Add(dc); all_seq.Add(dc.SequenceVar()); } IntVar objective_var = solver.MakeMax(makeSpan).Var(); OptimizeVar objective_monitor = solver.MakeMinimize(objective_var, 1); DecisionBuilder sequence_phase = solver.MakePhase(all_seq.ToArray(), Solver.SEQUENCE_DEFAULT); DecisionBuilder objective_phase = solver.MakePhase(objective_var, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); DecisionBuilder main_phase = solver.Compose(sequence_phase, objective_phase); const int kLogFrequency = 1000000; SearchMonitor search_log = solver.MakeSearchLog(kLogFrequency, objective_monitor); SolutionCollector collector = solver.MakeLastSolutionCollector(); collector.Add(all_seq.ToArray()); collector.AddObjective(objective_var); if (solver.Solve(main_phase, search_log, objective_monitor, null, collector)) { Console.Out.WriteLine("Optimal solution = " + collector.ObjectiveValue(0)); } else { Console.Out.WriteLine("No solution."); } }
///<summary> /// Adds a space object to the simulation. ///</summary> ///<param name="spaceObject">Space object to add.</param> public void Add(ISpaceObject spaceObject) { if (spaceObject.Space != null) { throw new ArgumentException("The object belongs to some Space already; cannot add it again."); } spaceObject.Space = this; SimulationIslandMember simulationIslandMember = spaceObject as SimulationIslandMember; if (simulationIslandMember != null) { DeactivationManager.Add(simulationIslandMember); } ISimulationIslandMemberOwner simulationIslandMemberOwner = spaceObject as ISimulationIslandMemberOwner; if (simulationIslandMemberOwner != null) { DeactivationManager.Add(simulationIslandMemberOwner.ActivityInformation); } //Go through each stage, adding the space object to it if necessary. IForceUpdateable velocityUpdateable = spaceObject as IForceUpdateable; if (velocityUpdateable != null) { ForceUpdater.Add(velocityUpdateable); } MobileCollidable boundingBoxUpdateable = spaceObject as MobileCollidable; if (boundingBoxUpdateable != null) { BoundingBoxUpdater.Add(boundingBoxUpdateable); } BroadPhaseEntry broadPhaseEntry = spaceObject as BroadPhaseEntry; if (broadPhaseEntry != null) { BroadPhase.Add(broadPhaseEntry); } //Entites own collision proxies, but are not entries themselves. IBroadPhaseEntryOwner broadPhaseEntryOwner = spaceObject as IBroadPhaseEntryOwner; if (broadPhaseEntryOwner != null) { BroadPhase.Add(broadPhaseEntryOwner.Entry); boundingBoxUpdateable = broadPhaseEntryOwner.Entry as MobileCollidable; if (boundingBoxUpdateable != null) { BoundingBoxUpdater.Add(boundingBoxUpdateable); } } SolverUpdateable solverUpdateable = spaceObject as SolverUpdateable; if (solverUpdateable != null) { Solver.Add(solverUpdateable); } IPositionUpdateable integrable = spaceObject as IPositionUpdateable; if (integrable != null) { PositionUpdater.Add(integrable); } Entity entity = spaceObject as Entity; if (entity != null) { BufferedStates.Add(entity); } IDeferredEventCreator deferredEventCreator = spaceObject as IDeferredEventCreator; if (deferredEventCreator != null) { DeferredEventDispatcher.AddEventCreator(deferredEventCreator); } IDeferredEventCreatorOwner deferredEventCreatorOwner = spaceObject as IDeferredEventCreatorOwner; if (deferredEventCreatorOwner != null) { DeferredEventDispatcher.AddEventCreator(deferredEventCreatorOwner.EventCreator); } //Updateable stages. IDuringForcesUpdateable duringForcesUpdateable = spaceObject as IDuringForcesUpdateable; if (duringForcesUpdateable != null) { DuringForcesUpdateables.Add(duringForcesUpdateable); } IBeforeNarrowPhaseUpdateable beforeNarrowPhaseUpdateable = spaceObject as IBeforeNarrowPhaseUpdateable; if (beforeNarrowPhaseUpdateable != null) { BeforeNarrowPhaseUpdateables.Add(beforeNarrowPhaseUpdateable); } IBeforeSolverUpdateable beforeSolverUpdateable = spaceObject as IBeforeSolverUpdateable; if (beforeSolverUpdateable != null) { BeforeSolverUpdateables.Add(beforeSolverUpdateable); } IBeforePositionUpdateUpdateable beforePositionUpdateUpdateable = spaceObject as IBeforePositionUpdateUpdateable; if (beforePositionUpdateUpdateable != null) { BeforePositionUpdateUpdateables.Add(beforePositionUpdateUpdateable); } IEndOfTimeStepUpdateable endOfStepUpdateable = spaceObject as IEndOfTimeStepUpdateable; if (endOfStepUpdateable != null) { EndOfTimeStepUpdateables.Add(endOfStepUpdateable); } IEndOfFrameUpdateable endOfFrameUpdateable = spaceObject as IEndOfFrameUpdateable; if (endOfFrameUpdateable != null) { EndOfFrameUpdateables.Add(endOfFrameUpdateable); } spaceObject.OnAdditionToSpace(this); }
/** * * Traffic lights problem. * * CSPLib problem 16 * http://www.cs.st-andrews.ac.uk/~ianm/CSPLib/prob/prob016/index.html * """ * Specification: * Consider a four way traffic junction with eight traffic lights. Four of the * traffic lights are for the vehicles and can be represented by the variables * V1 to V4 with domains {r,ry,g,y} (for red, red-yellow, green and yellow). * The other four traffic lights are for the pedestrians and can be * represented by the variables P1 to P4 with domains {r,g}. * * The constraints on these variables can be modelled by quaternary * constraints on (Vi, Pi, Vj, Pj ) for 1<=i<=4, j=(1+i)mod 4 which allow just * the tuples * {(r,r,g,g), (ry,r,y,r), (g,g,r,r), (y,r,ry,r)}. * * It would be interesting to consider other types of junction (e.g. five * roads intersecting) as well as modelling the evolution over time of the * traffic light sequence. * ... * * Results * Only 2^2 out of the 2^12 possible assignments are solutions. * * (V1,P1,V2,P2,V3,P3,V4,P4) = * {(r,r,g,g,r,r,g,g), (ry,r,y,r,ry,r,y,r), (g,g,r,r,g,g,r,r), * (y,r,ry,r,y,r,ry,r)} * [(1,1,3,3,1,1,3,3), ( 2,1,4,1, 2,1,4,1), (3,3,1,1,3,3,1,1), (4,1, 2,1,4,1, * 2,1)} The problem has relative few constraints, but each is very tight. * Local propagation appears to be rather ineffective on this problem. * * """ * Note: In this model we use only the constraint * solver.AllowedAssignments(). * * * See http://www.hakank.org/or-tools/traffic_lights.py * */ private static void Solve() { Solver solver = new Solver("TrafficLights"); // // data // int n = 4; int r = 0; int ry = 1; int g = 2; int y = 3; string[] lights = { "r", "ry", "g", "y" }; // The allowed combinations IntTupleSet allowed = new IntTupleSet(4); allowed.InsertAll(new long[][] { new long[] { r, r, g, g }, new long[] { ry, r, y, r }, new long[] { g, g, r, r }, new long[] { y, r, ry, r } }); // // Decision variables // IntVar[] V = solver.MakeIntVarArray(n, 0, n - 1, "V"); IntVar[] P = solver.MakeIntVarArray(n, 0, n - 1, "P"); // for search IntVar[] VP = new IntVar[2 * n]; for (int i = 0; i < n; i++) { VP[i] = V[i]; VP[i + n] = P[i]; } // // Constraints // for (int i = 0; i < n; i++) { int j = (1 + i) % n; IntVar[] tmp = new IntVar[] { V[i], P[i], V[j], P[j] }; solver.Add(tmp.AllowedAssignments(allowed)); } // // Search // DecisionBuilder db = solver.MakePhase(VP, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { for (int i = 0; i < n; i++) { Console.Write("{0,2} {1,2} ", lights[V[i].Value()], lights[P[i].Value()]); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Solves the Survo puzzle. * See http://www.hakank.org/or-tools/survo_puzzle.py * */ private static void Solve() { Solver solver = new Solver("SurvoPuzzle"); // // data // Console.WriteLine("Problem:"); for (int i = 0; i < r; i++) { for (int j = 0; j < c; j++) { Console.Write(game[i, j] + " "); } Console.WriteLine(); } Console.WriteLine(); // // Decision variables // IntVar[,] x = solver.MakeIntVarMatrix(r, c, 1, r * c, "x"); IntVar[] x_flat = x.Flatten(); // // Constraints // for (int i = 0; i < r; i++) { for (int j = 0; j < c; j++) { if (game[i, j] > 0) { solver.Add(x[i, j] == game[i, j]); } } } solver.Add(x_flat.AllDifferent()); // // calculate rowsums and colsums // for (int i = 0; i < r; i++) { IntVar[] row = new IntVar[c]; for (int j = 0; j < c; j++) { row[j] = x[i, j]; } solver.Add(row.Sum() == rowsums[i]); } for (int j = 0; j < c; j++) { IntVar[] col = new IntVar[r]; for (int i = 0; i < r; i++) { col[i] = x[i, j]; } solver.Add(col.Sum() == colsums[j]); } // // Search // DecisionBuilder db = solver.MakePhase(x_flat, Solver.INT_VAR_SIMPLE, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); int sol = 0; while (solver.NextSolution()) { sol++; Console.WriteLine("Solution #{0} ", sol + " "); for (int i = 0; i < r; i++) { for (int j = 0; j < c; j++) { Console.Write("{0} ", x[i, j].Value()); } Console.WriteLine(); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
public Sudoku.Core.Sudoku Solve(Sudoku.Core.Sudoku sudoku) { //Sudoku -> Tableau int[,] sudokuInGrid = new int[9, 9]; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { sudokuInGrid[i, j] = sudoku.GetCell(i, j); } } Solver solver = new Solver("Sudoku"); int cell_size = 3; IEnumerable <int> CELL = Enumerable.Range(0, cell_size); int n = cell_size * cell_size; IEnumerable <int> RANGE = Enumerable.Range(0, n); //Création de la grille de solution IntVar[,] grid = solver.MakeIntVarMatrix(n, n, 1, 9, "grid"); IntVar[] grid_flat = grid.Flatten(); //Tableau -> Solver foreach (int i in RANGE) { foreach (int j in RANGE) { if (sudokuInGrid[i, j] > 0) { solver.Add(grid[i, j] == sudokuInGrid[i, j]); } } } //Un chiffre ne figure qu'une seule fois par ligne/colonne/cellule foreach (int i in RANGE) { // Lignes solver.Add((from j in RANGE select grid[i, j]).ToArray().AllDifferent()); // Colonnes solver.Add((from j in RANGE select grid[j, i]).ToArray().AllDifferent()); } //Cellules foreach (int i in CELL) { foreach (int j in CELL) { solver.Add((from di in CELL from dj in CELL select grid[i * cell_size + di, j * cell_size + dj] ).ToArray().AllDifferent()); } } //Début de la résolution DecisionBuilder db = solver.MakePhase(grid_flat, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); solver.NewSearch(db); // Solver -> Liste var gridToSudoku = new List <int>(); while (solver.NextSolution()) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { gridToSudoku.Add((int)grid[i, j].Value()); } } } solver.EndSearch(); //Liste -> Sudoku return(new Sudoku.Core.Sudoku(gridToSudoku)); }
static void CpLoadModelAfterSearchTest() { CpModel expected; const string constraintName = "equation"; const string constraintText = "((x(0..10) + y(0..10)) == 5)"; // Make sure that resources are isolated in the using block. using (var s = new Solver("TestConstraint")) { var x = s.MakeIntVar(0, 10, "x"); var y = s.MakeIntVar(0, 10, "y"); Check(x.Name() == "x", "x variable name incorrect."); Check(y.Name() == "y", "y variable name incorrect."); var c = x + y == 5; // c.Cst.SetName(constraintName); // Check(c.Cst.Name() == constraintName, "Constraint name incorrect."); Check(c.Cst.ToString() == constraintText, "Constraint is incorrect."); s.Add(c); // TODO: TBD: support solution collector? var db = s.MakePhase(x, y, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); Check(!ReferenceEquals(null, db), "Expected a valid Decision Builder"); s.NewSearch(db); var count = 0; while (s.NextSolution()) { Console.WriteLine("x = {0}, y = {1}", x.Value(), y.Value()); ++count; // Break after we found at least one solution. break; } s.EndSearch(); Check(count > 0, "Must find at least one solution."); // TODO: TBD: export with monitors and/or decision builder? expected = s.ExportModel(); Console.WriteLine("Expected model string after export: {0}", expected); } // While interesting, this is not very useful nor especially typical use case scenario. using (var s = new Solver("TestConstraint")) { // TODO: TBD: load with monitors and/or decision builder? s.LoadModel(expected); // This is the first test that should PASS when loading; however, it FAILS because the Constraint is NOT loaded as it is a "TrueConstraint()" Check(s.Constraints() == 1, "Incorrect number of constraints."); var actual = s.ExportModel(); Console.WriteLine("Actual model string after load: {0}", actual); // Should also be correct after re-load, but I suspect isn't even close, but I could be wrong. Check(expected.ToString() == actual.ToString(), "Model string incorrect."); var loader = s.ModelLoader(); var x = loader.IntegerExpression(0).Var(); var y = loader.IntegerExpression(1).Var(); Check(!ReferenceEquals(null, x), "x variable not found after loaded model."); Check(!ReferenceEquals(null, y), "y variable not found after loaded model."); { // Do this sanity check that what we loaded is actually what we expected should load. var c = x + y == 5; // Further documented verification, provided we got this far, and/or with "proper" unit test Assertions... Check(c.Cst.ToString() == constraintText, "Constraint is incorrect."); Check(c.Cst.ToString() != "TrueConstraint()", "Constraint is incorrect."); } // TODO: TBD: support solution collector? // Should pick up where we left off. var db = s.MakePhase(x, y, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); s.NewSearch(db); while (s.NextSolution()) { Console.WriteLine("x = {0}, y = {1}", x.Value(), y.Value()); } s.EndSearch(); } }
public void Solve(GrilleSudoku s) { //Création d'un solver Or-tools Solver solver = new Solver("Sudoku"); //Création de la grille de variables //Variables de décision IntVar[,] grid = solver.MakeIntVarMatrix(9, 9, 1, 9, "grid"); //VERIFIER IntVar[] grid_flat = grid.Flatten(); //VERIFIER //Masque de résolution for (int i = 0; i < cellIndices.Count(); i++) { for (int j = 0; j < cellIndices.Count(); j++) { if (s.GetCellule(i, j) > 0) { solver.Add(grid[i, j] == s.GetCellule(i, j)); } } } //Un chiffre ne figure qu'une seule fois par ligne/colonne/cellule for (int i = 0; i < cellIndices.Count(); i++) { // Lignes solver.Add((from j in cellIndices select grid[i, j]).ToArray().AllDifferent()); // Colonnes solver.Add((from j in cellIndices select grid[j, i]).ToArray().AllDifferent()); } //Cellules for (int i = 0; i < CELL.Count(); i++) { for (int j = 0; j < CELL.Count(); j++) { solver.Add((from di in CELL from dj in CELL select grid[i * cell_size + di, j * cell_size + dj] ).ToArray().AllDifferent()); } } //Début de la résolution DecisionBuilder db = solver.MakePhase(grid_flat, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); solver.NewSearch(db); //Mise à jour du sudoku //int n = cell_size * cell_size; //Or on sait que cell_size = 3 -> voir ligne 13 //Inspiré de l'exemple : taille des cellules identique while (solver.NextSolution()) { for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { s.SetCell(i, j, (int)grid[i, j].Value()); } } } //Si 4 lignes dessus optionnelles, EndSearch est obligatoire solver.EndSearch(); }
/** * * Solves the divisible by 9 through 1 problem. * See http://www.hakank.org/google_or_tools/divisible_by_9_through_1.py * */ private static void Solve(int bbase) { Solver solver = new Solver("DivisibleBy9Through1"); int m = (int)Math.Pow(bbase, (bbase - 1)) - 1; int n = bbase - 1; String[] digits_str = { "_", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; Console.WriteLine("base: " + bbase); // // Decision variables // // digits IntVar[] x = solver.MakeIntVarArray(n, 1, bbase - 1, "x"); // the numbers. t[0] contains the answe IntVar[] t = solver.MakeIntVarArray(n, 0, m, "t"); // // Constraints // solver.Add(x.AllDifferent()); // Ensure the divisibility of base .. 1 IntVar zero = solver.MakeIntConst(0); for (int i = 0; i < n; i++) { int mm = bbase - i - 1; IntVar[] tt = new IntVar[mm]; for (int j = 0; j < mm; j++) { tt[j] = x[j]; } solver.Add(ToNum(tt, t[i], bbase)); MyMod(solver, t[i], solver.MakeIntConst(mm), zero); } // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db); while (solver.NextSolution()) { Console.Write("x: "); for (int i = 0; i < n; i++) { Console.Write(x[i].Value() + " "); } Console.WriteLine("\nt: "); for (int i = 0; i < n; i++) { Console.Write(t[i].Value() + " "); } Console.WriteLine("\n"); if (bbase != 10) { Console.Write("Number base 10: " + t[0].Value()); Console.Write(" Base " + bbase + ": "); for (int i = 0; i < n; i++) { Console.Write(digits_str[(int)x[i].Value() + 1]); } Console.WriteLine("\n"); } } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Solves a set covering deployment problem. * See See http://www.hakank.org/or-tools/set_covering_deployment.py * */ private static void Solve() { Solver solver = new Solver("SetCoveringDeployment"); // // data // // From http://mathworld.wolfram.com/SetCoveringDeployment.html string[] countries = { "Alexandria", "Asia Minor", "Britain", "Byzantium", "Gaul", "Iberia", "Rome", "Tunis" }; int n = countries.Length; // the incidence matrix (neighbours) int[,] mat = { { 0, 1, 0, 1, 0, 0, 1, 1 }, { 1, 0, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 1, 1, 0, 0 }, { 1, 1, 0, 0, 0, 0, 1, 0 }, { 0, 0, 1, 0, 0, 1, 1, 0 }, { 0, 0, 1, 0, 1, 0, 1, 1 }, { 1, 0, 0, 1, 1, 1, 0, 1 }, { 1, 0, 0, 0, 0, 1, 1, 0 } }; // // Decision variables // // First army IntVar[] x = solver.MakeIntVarArray(n, 0, 1, "x"); // Second (reserve) army IntVar[] y = solver.MakeIntVarArray(n, 0, 1, "y"); // total number of armies IntVar num_armies = (x.Sum() + y.Sum()).Var(); // // Constraints // // // Constraint 1: There is always an army in a city // (+ maybe a backup) // Or rather: Is there a backup, there // must be an an army // for (int i = 0; i < n; i++) { solver.Add(x[i] >= y[i]); } // // Constraint 2: There should always be an backup // army near every city // for (int i = 0; i < n; i++) { IntVar[] count_neighbours = (from j in Enumerable.Range(0, n) where mat[i, j] == 1 select(y[j])) .ToArray(); solver.Add((x[i] + count_neighbours.Sum()) >= 1); } // // objective // OptimizeVar objective = num_armies.Minimize(1); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db, objective); while (solver.NextSolution()) { Console.WriteLine("num_armies: " + num_armies.Value()); for (int i = 0; i < n; i++) { if (x[i].Value() == 1) { Console.Write("Army: " + countries[i] + " "); } if (y[i].Value() == 1) { Console.WriteLine(" Reverse army: " + countries[i]); } } Console.WriteLine("\n"); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Solves a set covering problem. * See See http://www.hakank.org/or-tools/set_covering_opl.py * */ private static void Solve() { Solver solver = new Solver("SetCoveringOPL"); // // data // int num_workers = 32; int num_tasks = 15; // Which worker is qualified for each task. // Note: This is 1-based and will be made 0-base below. int[][] qualified = { new int[] { 1, 9, 19, 22, 25, 28, 31 }, new int[] { 2, 12, 15, 19, 21, 23,27, 29, 30, 31, 32 }, new int[] { 3, 10, 19, 24, 26, 30, 32 }, new int[] { 4, 21, 25, 28,32 }, new int[] { 5, 11, 16, 22, 23, 27, 31 }, new int[] { 6, 20, 24, 26, 30,32 }, new int[] { 7, 12, 17, 25, 30,31 }, new int[] { 8, 17, 20, 22,23 }, new int[] { 9, 13, 14, 26, 29, 30, 31 }, new int[] { 10, 21, 25, 31,32 }, new int[] { 14, 15, 18, 23, 24, 27,30, 32 }, new int[] { 18, 19, 22, 24, 26, 29, 31 }, new int[] { 11, 20, 25, 28, 30,32 }, new int[] { 16, 19, 23,31 }, new int[] { 9, 18, 26, 28, 31, 32 } }; int[] cost = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 8, 9 }; // // Decision variables // IntVar[] hire = solver.MakeIntVarArray(num_workers, 0, 1, "workers"); IntVar total_cost = hire.ScalProd(cost).Var(); // // Constraints // for (int j = 0; j < num_tasks; j++) { // Sum the cost for hiring the qualified workers // (also, make 0-base). int len = qualified[j].Length; IntVar[] tmp = new IntVar[len]; for (int c = 0; c < len; c++) { tmp[c] = hire[qualified[j][c] - 1]; } solver.Add(tmp.Sum() >= 1); } // // objective // OptimizeVar objective = total_cost.Minimize(1); // // Search // DecisionBuilder db = solver.MakePhase(hire, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db, objective); while (solver.NextSolution()) { Console.WriteLine("Cost: " + total_cost.Value()); Console.Write("Hire: "); for (int i = 0; i < num_workers; i++) { if (hire[i].Value() == 1) { Console.Write(i + " "); } } Console.WriteLine("\n"); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Futoshiki problem. * * From http://en.wikipedia.org/wiki/Futoshiki * """ * The puzzle is played on a square grid, such as 5 x 5. The objective * is to place the numbers 1 to 5 (or whatever the dimensions are) * such that each row, and column contains each of the digits 1 to 5. * Some digits may be given at the start. In addition, inequality * constraints are also initially specifed between some of the squares, * such that one must be higher or lower than its neighbour. These * constraints must be honoured as the grid is filled out. * """ * * Also see http://www.hakank.org/or-tools/futoshiki.py * */ private static void Solve(int[,] values, int[,] lt) { Solver solver = new Solver("Futoshiki"); int size = values.GetLength(0); IEnumerable <int> RANGE = Enumerable.Range(0, size); IEnumerable <int> NUMQD = Enumerable.Range(0, lt.GetLength(0)); // // Decision variables // IntVar[,] field = solver.MakeIntVarMatrix(size, size, 1, size, "field"); IntVar[] field_flat = field.Flatten(); // // Constraints // // set initial values foreach (int row in RANGE) { foreach (int col in RANGE) { if (values[row, col] > 0) { solver.Add(field[row, col] == values[row, col]); } } } // all rows have to be different foreach (int row in RANGE) { solver.Add((from col in RANGE select field[row, col]).ToArray().AllDifferent()); } // all columns have to be different foreach (int col in RANGE) { solver.Add((from row in RANGE select field[row, col]).ToArray().AllDifferent()); } // all < constraints are satisfied // Also: make 0-based foreach (int i in NUMQD) { solver.Add(field[lt[i, 0] - 1, lt[i, 1] - 1] < field[lt[i, 2] - 1, lt[i, 3] - 1]); } // // Search // DecisionBuilder db = solver.MakePhase(field_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { foreach (int i in RANGE) { foreach (int j in RANGE) { Console.Write("{0} ", field[i, j].Value()); } Console.WriteLine(); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Moving furnitures (scheduling) problem in Google CP Solver. * * Marriott & Stukey: 'Programming with constraints', page 112f * * Also see http://www.hakank.org/or-tools/furniture_moving.py * */ private static void Solve() { Solver solver = new Solver("FurnitureMovingIntervals"); const int n = 4; int[] durations = { 30, 10, 15, 15 }; int[] demand = { 3, 1, 3, 2 }; const int upper_limit = 160; const int max_num_workers = 5; // // Decision variables // IntervalVar[] tasks = new IntervalVar[n]; for (int i = 0; i < n; ++i) { tasks[i] = solver.MakeFixedDurationIntervalVar(0, upper_limit - durations[i], durations[i], false, "task_" + i); } // Fillers that span the whole resource and limit the available // number of workers. IntervalVar[] fillers = new IntervalVar[max_num_workers]; for (int i = 0; i < max_num_workers; ++i) { fillers[i] = solver.MakeFixedDurationIntervalVar(0, 0, upper_limit, true, "filler_" + i); } // Number of needed resources, to be minimized or constrained. IntVar num_workers = solver.MakeIntVar(0, max_num_workers, "num_workers"); // Links fillers and num_workers. for (int i = 0; i < max_num_workers; ++i) { solver.Add((num_workers > i) + fillers[i].PerformedExpr() == 1); } // Creates makespan. IntVar[] ends = new IntVar[n]; for (int i = 0; i < n; ++i) { ends[i] = tasks[i].EndExpr().Var(); } IntVar end_time = ends.Max().VarWithName("end_time"); // // Constraints // IntervalVar[] all_tasks = new IntervalVar[n + max_num_workers]; int[] all_demands = new int[n + max_num_workers]; for (int i = 0; i < n; ++i) { all_tasks[i] = tasks[i]; all_demands[i] = demand[i]; } for (int i = 0; i < max_num_workers; ++i) { all_tasks[i + n] = fillers[i]; all_demands[i + n] = 1; } solver.Add(all_tasks.Cumulative(all_demands, max_num_workers, "workers")); // // Some extra constraints to play with // // all tasks must end within an hour // solver.Add(end_time <= 60); // All tasks should start at time 0 // for(int i = 0; i < n; i++) { // solver.Add(tasks[i].StartAt(0)); // } // limitation of the number of people // solver.Add(num_workers <= 3); solver.Add(num_workers <= 4); // // Objective // // OptimizeVar obj = num_workers.Minimize(1); OptimizeVar obj = end_time.Minimize(1); // // Search // DecisionBuilder db = solver.MakePhase(all_tasks, Solver.INTERVAL_DEFAULT); solver.NewSearch(db, obj); while (solver.NextSolution()) { Console.WriteLine(num_workers.ToString() + ", " + end_time.ToString()); for (int i = 0; i < n; i++) { Console.WriteLine("{0} (demand:{1})", tasks[i].ToString(), demand[i]); } Console.WriteLine(); } Console.WriteLine("Solutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0} ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/* * Main Method: */ public static void Solve(Tuple <int, int[], int[], string[]> input) { var solver = new Solver("Knapsack"); // Total capacity: int capacity = input.Item1; // Weights and prices for each item: int[] weights = input.Item2; int[] prices = input.Item3; // Item names for pretty printing: string[] names = input.Item4; IntVar[] items = solver.MakeIntVarArray(names.Length, 0, capacity); /* * Constraints: */ solver.Add(solver.MakeScalProd(items, weights) <= capacity); /* * Objective Function: */ IntVar obj = solver.MakeScalProd(items, prices).Var(); /* * Start Solver: */ DecisionBuilder db = solver.MakePhase(items, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); SolutionCollector col = solver.MakeBestValueSolutionCollector(true); col.AddObjective(obj); col.Add(items); Console.WriteLine("Knapsack Problem:\n"); if (solver.Solve(db, col)) { Assignment sol = col.Solution(0); Console.WriteLine("Maximum value found: " + sol.ObjectiveValue() + "\n"); for (int i = 0; i < items.Length; i++) { Console.WriteLine("Item " + names[i] + " is smuggled " + sol.Value(items[i]) + " time(s)."); } Console.WriteLine(); } Console.WriteLine("Solutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); Console.ReadKey(); }
/** * * 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(); }
/** * * 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(); }
/** * * Photo problem. * * Problem statement from Mozart/Oz tutorial: * http://www.mozart-oz.org/home/doc/fdt/node37.html#section.reified.photo * """ * Betty, Chris, Donald, Fred, Gary, Mary, and Paul want to align in one * row for taking a photo. Some of them have preferences next to whom * they want to stand: * * 1. Betty wants to stand next to Gary and Mary. * 2. Chris wants to stand next to Betty and Gary. * 3. Fred wants to stand next to Mary and Donald. * 4. Paul wants to stand next to Fred and Donald. * * Obviously, it is impossible to satisfy all preferences. Can you find * an alignment that maximizes the number of satisfied preferences? * """ * * Oz solution: * 6 # alignment(betty:5 chris:6 donald:1 fred:3 gary:7 mary:4 * paul:2) [5, 6, 1, 3, 7, 4, 2] * * * Also see http://www.hakank.org/or-tools/photo_problem.py * */ private static void Solve(int show_all_max = 0) { Solver solver = new Solver("PhotoProblem"); // // Data // String[] persons = { "Betty", "Chris", "Donald", "Fred", "Gary", "Mary", "Paul" }; int n = persons.Length; IEnumerable <int> RANGE = Enumerable.Range(0, n); int[,] preferences = { // 0 1 2 3 4 5 6 // B C D F G M P { 0, 0, 0, 0, 1, 1, 0 }, // Betty 0 { 1, 0, 0, 0, 1, 0, 0 }, // Chris 1 { 0, 0, 0, 0, 0, 0, 0 }, // Donald 2 { 0, 0, 1, 0, 0, 1, 0 }, // Fred 3 { 0, 0, 0, 0, 0, 0, 0 }, // Gary 4 { 0, 0, 0, 0, 0, 0, 0 }, // Mary 5 { 0, 0, 1, 1, 0, 0, 0 } // Paul 6 }; Console.WriteLine("Preferences:"); Console.WriteLine("1. Betty wants to stand next to Gary and Mary."); Console.WriteLine("2. Chris wants to stand next to Betty and Gary."); Console.WriteLine("3. Fred wants to stand next to Mary and Donald."); Console.WriteLine("4. Paul wants to stand next to Fred and Donald.\n"); // // Decision variables // IntVar[] positions = solver.MakeIntVarArray(n, 0, n - 1, "positions"); // successful preferences (to Maximize) IntVar z = solver.MakeIntVar(0, n * n, "z"); // // Constraints // solver.Add(positions.AllDifferent()); // calculate all the successful preferences solver.Add((from i in RANGE from j in RANGE where preferences[i, j] == 1 select(positions[i] - positions[j]).Abs() == 1) .ToArray() .Sum() == z); // // Symmetry breaking (from the Oz page): // Fred is somewhere left of Betty solver.Add(positions[3] < positions[0]); // // Objective // OptimizeVar obj = z.Maximize(1); if (show_all_max > 0) { Console.WriteLine("Showing all maximum solutions (z == 6).\n"); solver.Add(z == 6); } // // Search // DecisionBuilder db = solver.MakePhase(positions, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MAX_VALUE); solver.NewSearch(db, obj); while (solver.NextSolution()) { Console.WriteLine("z: {0}", z.Value()); int[] p = new int[n]; Console.Write("p: "); for (int i = 0; i < n; i++) { p[i] = (int)positions[i].Value(); Console.Write(p[i] + " "); } Console.WriteLine(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (p[j] == i) { Console.Write(persons[j] + " "); } } } Console.WriteLine(); Console.WriteLine("Successful preferences:"); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (preferences[i, j] == 1 && Math.Abs(p[i] - p[j]) == 1) { Console.WriteLine("\t{0} {1}", persons[i], persons[j]); } } } Console.WriteLine(); } Console.WriteLine("\nSolutions: " + solver.Solutions()); Console.WriteLine("WallTime: " + solver.WallTime() + "ms "); Console.WriteLine("Failures: " + solver.Failures()); Console.WriteLine("Branches: " + solver.Branches()); solver.EndSearch(); }
///<summary> /// Enqueues a solver updateable created by some pair for flushing into the solver later. ///</summary> ///<param name="addedItem">Updateable to add.</param> public void NotifyUpdateableAdded(SolverUpdateable addedItem) { Solver.Add(addedItem); }
/** * * Secret Santa problem II in Google CP Solver. * * From Maple Primes: 'Secret Santa Graph Theory' * http://www.mapleprimes.com/blog/jpmay/secretsantagraphtheory * """ * Every year my extended family does a 'secret santa' gift exchange. * Each person draws another person at random and then gets a gift for * them. At first, none of my siblings were married, and so the draw was * completely random. Then, as people got married, we added the restriction * that spouses should not draw each others names. This restriction meant * that we moved from using slips of paper on a hat to using a simple * computer program to choose names. Then people began to complain when * they would get the same person two years in a row, so the program was * modified to keep some history and avoid giving anyone a name in their * recent history. This year, not everyone was participating, and so after * removing names, and limiting the number of exclusions to four per person, * I had data something like this: * * Name: Spouse, Recent Picks * * Noah: Ava. Ella, Evan, Ryan, John * Ava: Noah, Evan, Mia, John, Ryan * Ryan: Mia, Ella, Ava, Lily, Evan * Mia: Ryan, Ava, Ella, Lily, Evan * Ella: John, Lily, Evan, Mia, Ava * John: Ella, Noah, Lily, Ryan, Ava * Lily: Evan, John, Mia, Ava, Ella * Evan: Lily, Mia, John, Ryan, Noah * """ * * Note: I interpret this as the following three constraints: * 1) One cannot be a Secret Santa of one's spouse * 2) One cannot be a Secret Santa for somebody two years in a row * 3) Optimization: maximize the time since the last time * * This model also handle single persons, something the original * problem don't mention. * * * Also see http://www.hakank.org/or-tools/secret_santa2.py * */ private static void Solve(int single = 0) { Solver solver = new Solver("SecretSanta2"); Console.WriteLine("\nSingle: {0}", single); // // The matrix version of earlier rounds. // M means that no earlier Santa has been assigned. // Note: Ryan and Mia has the same recipient for years 3 and 4, // and Ella and John has for year 4. // This seems to be caused by modification of // original data. // int n_no_single = 8; int M = n_no_single + 1; int[][] rounds_no_single = { // N A R M El J L Ev new int[] { 0, M, 3, M, 1, 4, M, 2 }, // Noah new int[] { M, 0, 4, 2, M, 3, M, 1 }, // Ava new int[] { M, 2, 0, M, 1, M, 3, 4 }, // Ryan new int[] { M, 1, M, 0, 2, M, 3, 4 }, // Mia new int[] { M, 4, M, 3, 0, M, 1, 2 }, // Ella new int[] { 1, 4, 3, M, M, 0, 2, M }, // John new int[] { M, 3, M, 2, 4, 1, 0, M }, // Lily new int[] { 4, M, 3, 1, M, 2, M, 0 } // Evan }; // // Rounds with a single person (fake data) // int n_with_single = 9; M = n_with_single + 1; int[][] rounds_single = { // N A R M El J L Ev S new int[] { 0, M, 3, M, 1, 4, M, 2, 2 }, // Noah new int[] { M, 0, 4, 2, M, 3, M, 1, 1 }, // Ava new int[] { M, 2, 0, M, 1, M, 3, 4, 4 }, // Ryan new int[] { M, 1, M, 0, 2, M, 3, 4, 3 }, // Mia new int[] { M, 4, M, 3, 0, M, 1, 2, M }, // Ella new int[] { 1, 4, 3, M, M, 0, 2, M, M }, // John new int[] { M, 3, M, 2, 4, 1, 0, M, M }, // Lily new int[] { 4, M, 3, 1, M, 2, M, 0, M }, // Evan new int[] { 1, 2, 3, 4, M, 2, M, M, 0 } // Single }; int Noah = 0; int Ava = 1; int Ryan = 2; int Mia = 3; int Ella = 4; int John = 5; int Lily = 6; int Evan = 7; int n = n_no_single; int[][] rounds = rounds_no_single; if (single == 1) { n = n_with_single; rounds = rounds_single; } M = n + 1; IEnumerable <int> RANGE = Enumerable.Range(0, n); String[] persons = { "Noah", "Ava", "Ryan", "Mia", "Ella", "John", "Lily", "Evan", "Single" }; int[] spouses = { Ava, // Noah Noah, // Ava Mia, // Rya Ryan, // Mia John, // Ella Ella, // John Evan, // Lily Lily, // Evan -1 // Single has no spouse }; // // Decision variables // IntVar[] santas = solver.MakeIntVarArray(n, 0, n - 1, "santas"); IntVar[] santa_distance = solver.MakeIntVarArray(n, 0, M, "santa_distance"); // total of "distance", to maximize IntVar z = santa_distance.Sum().VarWithName("z"); // // Constraints // solver.Add(santas.AllDifferent()); // Can't be one own"s Secret Santa // (i.e. ensure that there are no fix-point in the array.) foreach (int i in RANGE) { solver.Add(santas[i] != i); } // no Santa for a spouses foreach (int i in RANGE) { if (spouses[i] > -1) { solver.Add(santas[i] != spouses[i]); } } // optimize "distance" to earlier rounds: foreach (int i in RANGE) { solver.Add(santa_distance[i] == rounds[i].Element(santas[i])); } // cannot be a Secret Santa for the same person // two years in a row. foreach (int i in RANGE) { foreach (int j in RANGE) { if (rounds[i][j] == 1) { solver.Add(santas[i] != j); } } } // // Objective (minimize the distances) // OptimizeVar obj = z.Maximize(1); // // Search // DecisionBuilder db = solver.MakePhase(santas, Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, Solver.ASSIGN_CENTER_VALUE); solver.NewSearch(db, obj); while (solver.NextSolution()) { Console.WriteLine("\ntotal distances: {0}", z.Value()); Console.Write("santas: "); for (int i = 0; i < n; i++) { Console.Write(santas[i].Value() + " "); } Console.WriteLine(); foreach (int i in RANGE) { Console.WriteLine("{0}\tis a Santa to {1} (distance {2})", persons[i], persons[santas[i].Value()], santa_distance[i].Value()); } } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * Volsay problem. * * From the OPL model volsay.mod. * This version use arrays and matrices * * Also see * http://www.hakank.org/or-tools/volsay2.cs * http://www.hakank.org/or-tools/volsay3.py */ private static void Solve() { Solver solver = new Solver("Volsay3", Solver.CLP_LINEAR_PROGRAMMING); int num_products = 2; IEnumerable <int> PRODUCTS = Enumerable.Range(0, num_products); String[] products = { "Gas", "Chloride" }; String[] components = { "nitrogen", "hydrogen", "chlorine" }; int[,] demand = { { 1, 3, 0 }, { 1, 4, 1 } }; int[] profit = { 30, 40 }; int[] stock = { 50, 180, 40 }; // // Variables // Variable[] production = new Variable[num_products]; foreach (int p in PRODUCTS) { production[p] = solver.MakeNumVar(0, 100000, products[p]); } // // Constraints // int c_len = components.Length; Constraint[] cons = new Constraint[c_len]; for (int c = 0; c < c_len; c++) { cons[c] = solver.Add((from p in PRODUCTS select(demand[p, c] * production[p])). ToArray().Sum() <= stock[c]); } // // Objective // solver.Maximize((from p in PRODUCTS select(profit[p] * production[p])). ToArray().Sum() ); if (solver.Solve() != Solver.OPTIMAL) { Console.WriteLine("The problem don't have an optimal solution."); return; } Console.WriteLine("Objective: {0}", solver.Objective().Value()); foreach (int p in PRODUCTS) { Console.WriteLine("{0,-10}: {1} ReducedCost: {2}", products[p], production[p].SolutionValue(), production[p].ReducedCost()); } double[] activities = solver.ComputeConstraintActivities(); for (int c = 0; c < c_len; c++) { Console.WriteLine("Constraint {0} DualValue {1} Activity: {2} lb: {3} ub: {4}", c, cons[c].DualValue(), activities[cons[c].Index()], cons[c].Lb(), cons[c].Ub()); } Console.WriteLine("\nWallTime: " + solver.WallTime()); Console.WriteLine("Iterations: " + solver.Iterations()); }
/* * Create Optimization Model and Solve Coloring Problem: */ public static void SolveAsOptimizationProblem(int nbNodes, IEnumerable <Tuple <int, int> > edges) { var solver = new Solver("Coloring"); // The colors for each node: IntVar[] nodes = solver.MakeIntVarArray(nbNodes, 0, nbNodes - 1); foreach (var edge in edges) { solver.Add(nodes[edge.Item1] != nodes[edge.Item2]); } // Some Symmetry breaking solver.Add(nodes[0] == 0); // The number of times each color is used: IntVar[] colors = solver.MakeIntVarArray(nbNodes, 0, nbNodes - 1); for (int i = 0; i < colors.Length; i++) { solver.Add(solver.MakeCount(nodes, i, colors[i])); } // Objective function = number of colors used: IntVar obj = solver.MakeSum((from j in colors select(j > 0).Var()).ToArray()).Var(); /* * Start Solver: */ DecisionBuilder db = solver.MakePhase(nodes, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); // Remember only the best solution found: SolutionCollector collector = solver.MakeBestValueSolutionCollector(false); collector.AddObjective(obj); // What to remember in addition to the objective function value: collector.Add(nodes); Console.WriteLine("Coloring Problem:\n"); if (solver.Solve(db, collector)) { // Extract best solution found: Assignment sol = collector.Solution(0); Console.WriteLine("Solution found with " + sol.ObjectiveValue() + " colors.\n"); for (int i = 0; i < nodes.Length; i++) { long v = sol.Value(nodes[i]); if (i < Names.Length) { Console.WriteLine("Nodes " + i + " obtains color " + Names.GetValue(v)); } else { Console.WriteLine("Nodes " + i + " obtains color " + v); } } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); Console.ReadKey(); }
/** * * 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(); }
public void doWork() { if (this.size % 2 == 0 && this.size > 3) { Solver solver = new Solver("Binoxxo"); // n x n Matrix IntVar[,] board = solver.MakeIntVarMatrix(this.size, this.size, 0, 1); // Handy C# LINQ type for sequences: IEnumerable <int> RANGE = Enumerable.Range(0, this.size); // Each row and each column should have an equal amount of X and O's: foreach (int i in RANGE) { // Row solver.Add((from j in RANGE select board[i, j]).ToArray().Sum() == (this.size / 2)); // Column solver.Add((from j in RANGE select board[j, i]).ToArray().Sum() == (this.size / 2)); } // Each row and column should be different: (Yes! Shit is working....) foreach (int i in RANGE) { for (int x = i + 1; x < this.size; x++) { // Rows: solver.Add( (from j in RANGE select board[i, j] * (int)Math.Pow(2, j)).ToArray().Sum() != (from j in RANGE select board[x, j] * (int)Math.Pow(2, j)).ToArray().Sum() ); // Columns: solver.Add( (from j in RANGE select board[j, i] * (int)Math.Pow(2, j)).ToArray().Sum() != (from j in RANGE select board[j, x] * (int)Math.Pow(2, j)).ToArray().Sum() ); } ; } // Max two cells next to each other should have the same value (This shit is working too!) IEnumerable <int> GROUP_START = Enumerable.Range(0, this.size - 2); IEnumerable <int> GROUP = Enumerable.Range(0, 3); foreach (int x in RANGE) { foreach (int y in GROUP_START) { // Rows: solver.Add((from j in GROUP select board[x, y + j]).ToArray().Sum() > 0); solver.Add((from j in GROUP select board[x, y + j]).ToArray().Sum() < 3); // Columns: solver.Add((from j in GROUP select board[y + j, x]).ToArray().Sum() > 0); solver.Add((from j in GROUP select board[y + j, x]).ToArray().Sum() < 3); } } DecisionBuilder db = solver.MakePhase( board.Flatten(), Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); solver.NewSearch(db); // Calculate first result for this solution // If more solutions are necessary, you can extend this part with a while(...)-Loop if (solver.NextSolution()) { printSquare(board); } solver.EndSearch(); if (solver.Solutions() == 0) { Console.WriteLine("No possible solution was found for the given Binoxxo! :-("); } } else { Console.WriteLine("Given size of {0} not allowed! Must be multiple of 2!", this.size); } }
/** * * 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(); }
/** * * Discrete tomography * * Problem from http://eclipse.crosscoreop.com/examples/tomo.ecl.txt * """ * This is a little 'tomography' problem, taken from an old issue * of Scientific American. * * A matrix which contains zeroes and ones gets "x-rayed" vertically and * horizontally, giving the total number of ones in each row and column. * The problem is to reconstruct the contents of the matrix from this * information. Sample run: * * ?- go. * 0 0 7 1 6 3 4 5 2 7 0 0 * 0 * 0 * 8 * * * * * * * * * 2 * * * 6 * * * * * * * 4 * * * * * 5 * * * * * * 3 * * * * 7 * * * * * * * * 0 * 0 * * Eclipse solution by Joachim Schimpf, IC-Parc * """ * * See http://www.hakank.org/or-tools/discrete_tomography.py * */ private static void Solve(int[] rowsums, int[] colsums) { Solver solver = new Solver("DiscreteTomography"); // // Data // int r = rowsums.Length; int c = colsums.Length; Console.Write("rowsums: "); for (int i = 0; i < r; i++) { Console.Write(rowsums[i] + " "); } Console.Write("\ncolsums: "); for (int j = 0; j < c; j++) { Console.Write(colsums[j] + " "); } Console.WriteLine("\n"); // // Decision variables // IntVar[,] x = solver.MakeIntVarMatrix(r, c, 0, 1, "x"); IntVar[] x_flat = x.Flatten(); // // Constraints // // row sums for (int i = 0; i < r; i++) { var tmp = from j in Enumerable.Range(0, c) select x[i, j]; solver.Add(tmp.ToArray().Sum() == rowsums[i]); } // cols sums for (int j = 0; j < c; j++) { var tmp = from i in Enumerable.Range(0, r) select x[i, j]; solver.Add(tmp.ToArray().Sum() == colsums[j]); } // // Search // DecisionBuilder db = solver.MakePhase(x_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { for (int i = 0; i < r; i++) { for (int j = 0; j < c; j++) { Console.Write("{0} ", x[i, j].Value() == 1 ? "#" : "."); } Console.WriteLine(); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Langford number problem. * See http://www.hakank.org/or-tools/langford.py * */ private static void Solve(int k = 8, int num_sol = 0) { Solver solver = new Solver("Langford"); Console.WriteLine("k: {0}", k); // // data // int p = 2 * k; // // Decision variables // IntVar[] position = solver.MakeIntVarArray(p, 0, p - 1, "position"); IntVar[] solution = solver.MakeIntVarArray(p, 1, k, "solution"); // // Constraints // solver.Add(position.AllDifferent()); for (int i = 1; i <= k; i++) { solver.Add(position[i + k - 1] - (position[i - 1] + solver.MakeIntVar(i + 1, i + 1)) == 0); solver.Add(solution.Element(position[i - 1]) == i); solver.Add(solution.Element(position[k + i - 1]) == i); } // Symmetry breaking solver.Add(solution[0] < solution[2 * k - 1]); // // Search // DecisionBuilder db = solver.MakePhase(position, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); int num_solutions = 0; while (solver.NextSolution()) { Console.Write("solution : "); for (int i = 0; i < p; i++) { Console.Write(solution[i].Value() + " "); } Console.WriteLine(); num_solutions++; if (num_sol > 0 && num_solutions >= num_sol) { break; } } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * Fill-a-Pix problem * * From http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/basiclogic * """ * Each puzzle consists of a grid containing clues in various places. The * object is to reveal a hidden picture by painting the squares around each * clue so that the number of painted squares, including the square with * the clue, matches the value of the clue. * """ * * http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/rules * """ * Fill-a-Pix is a Minesweeper-like puzzle based on a grid with a pixilated * picture hidden inside. Using logic alone, the solver determines which * squares are painted and which should remain empty until the hidden picture * is completely exposed. * """ * * Fill-a-pix History: * http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/history * * Also see http://www.hakank.org/google_or_tools/fill_a_pix.py * * */ private static void Solve() { Solver solver = new Solver("FillAPix"); // // data // int[] S = { -1, 0, 1 }; Console.WriteLine("Problem:"); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (puzzle[i, j] > X) { Console.Write(puzzle[i, j] + " "); } else { Console.Write("X "); } } Console.WriteLine(); } Console.WriteLine(); // // Decision variables // IntVar[,] pict = solver.MakeIntVarMatrix(n, n, 0, 1, "pict"); IntVar[] pict_flat = pict.Flatten(); // for branching // // Constraints // for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (puzzle[i, j] > X) { // this cell is the sum of all surrounding cells var tmp = from a in S from b in S where i + a >= 0 && j + b >= 0 && i + a < n && j + b < n select(pict[i + a, j + b]); solver.Add(tmp.ToArray().Sum() == puzzle[i, j]); } } } // // Search // DecisionBuilder db = solver.MakePhase(pict_flat, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db); int sol = 0; while (solver.NextSolution()) { sol++; Console.WriteLine("Solution #{0} ", sol + " "); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { Console.Write(pict[i, j].Value() == 1 ? "#" : " "); } Console.WriteLine(); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
private static void RunLinearProgrammingExampleNaturalApi(String solverType, bool printModel) { Console.WriteLine($"---- Linear programming example (Natural API) with {solverType} ----"); Solver solver = Solver.CreateSolver(solverType); if (solver == null) { Console.WriteLine("Could not create solver " + solverType); return; } // x1, x2 and x3 are continuous non-negative variables. Variable x1 = solver.MakeNumVar(0.0, double.PositiveInfinity, "x1"); Variable x2 = solver.MakeNumVar(0.0, double.PositiveInfinity, "x2"); Variable x3 = solver.MakeNumVar(0.0, double.PositiveInfinity, "x3"); solver.Maximize(10 * x1 + 6 * x2 + 4 * x3); Constraint c0 = solver.Add(x1 + x2 + x3 <= 100); Constraint c1 = solver.Add(10 * x1 + x2 * 4 + 5 * x3 <= 600); Constraint c2 = solver.Add(2 * x1 + 2 * x2 + 6 * x3 <= 300); Console.WriteLine("Number of variables = " + solver.NumVariables()); Console.WriteLine("Number of constraints = " + solver.NumConstraints()); if (printModel) { string model = solver.ExportModelAsLpFormat(false); Console.WriteLine(model); } Solver.ResultStatus resultStatus = solver.Solve(); // Check that the problem has an optimal solution. if (resultStatus != Solver.ResultStatus.OPTIMAL) { Console.WriteLine("The problem does not have an optimal solution!"); return; } Console.WriteLine("Problem solved in " + solver.WallTime() + " milliseconds"); // The objective value of the solution. Console.WriteLine("Optimal objective value = " + solver.Objective().Value()); // The value of each variable in the solution. Console.WriteLine("x1 = " + x1.SolutionValue()); Console.WriteLine("x2 = " + x2.SolutionValue()); Console.WriteLine("x3 = " + x3.SolutionValue()); Console.WriteLine("Advanced usage:"); double[] activities = solver.ComputeConstraintActivities(); Console.WriteLine("Problem solved in " + solver.Iterations() + " iterations"); Console.WriteLine("x1: reduced cost = " + x1.ReducedCost()); Console.WriteLine("x2: reduced cost = " + x2.ReducedCost()); Console.WriteLine("x3: reduced cost = " + x3.ReducedCost()); Console.WriteLine("c0: dual value = " + c0.DualValue()); Console.WriteLine(" activity = " + activities[c0.Index()]); Console.WriteLine("c1: dual value = " + c1.DualValue()); Console.WriteLine(" activity = " + activities[c1.Index()]); Console.WriteLine("c2: dual value = " + c2.DualValue()); Console.WriteLine(" activity = " + activities[c2.Index()]); }
/** * * Crypto problem. * * This is the standard benchmark "crypto" problem. * * From GLPK:s model cryto.mod. * * """ * This problem comes from the newsgroup rec.puzzle. * The numbers from 1 to 26 are assigned to the letters of the alphabet. * The numbers beside each word are the total of the values assigned to * the letters in the word (e.g. for LYRE: L, Y, R, E might be to equal * 5, 9, 20 and 13, or any other combination that add up to 47). * Find the value of each letter under the equations: * * BALLET 45 GLEE 66 POLKA 59 SONG 61 * CELLO 43 JAZZ 58 QUARTET 50 SOPRANO 82 * CONCERT 74 LYRE 47 SAXOPHONE 134 THEME 72 * FLUTE 30 OBOE 53 SCALE 51 VIOLIN 100 * FUGUE 50 OPERA 65 SOLO 37 WALTZ 34 * * Solution: * A, B,C, D, E,F, G, H, I, J, K,L,M, N, O, P,Q, R, S,T,U, V,W, X, Y, Z * 5,13,9,16,20,4,24,21,25,17,23,2,8,12,10,19,7,11,15,3,1,26,6,22,14,18 * * Reference: * Koalog Constraint Solver <http://www.koalog.com/php/jcs.php>, * Simple problems, the crypto-arithmetic puzzle ALPHACIPHER. * """ * * Also see http://hakank.org/or-tools/crypto.py * */ private static void Solve() { Solver solver = new Solver("Crypto"); int num_letters = 26; int BALLET = 45; int CELLO = 43; int CONCERT = 74; int FLUTE = 30; int FUGUE = 50; int GLEE = 66; int JAZZ = 58; int LYRE = 47; int OBOE = 53; int OPERA = 65; int POLKA = 59; int QUARTET = 50; int SAXOPHONE = 134; int SCALE = 51; int SOLO = 37; int SONG = 61; int SOPRANO = 82; int THEME = 72; int VIOLIN = 100; int WALTZ = 34; // // Decision variables // IntVar[] LD = solver.MakeIntVarArray(num_letters, 1, num_letters, "LD"); // Note D is not used in the constraints below IntVar A = LD[0]; IntVar B = LD[1]; IntVar C = LD[2]; // IntVar D = LD[3]; IntVar E = LD[4]; IntVar F = LD[5]; IntVar G = LD[6]; IntVar H = LD[7]; IntVar I = LD[8]; IntVar J = LD[9]; IntVar K = LD[10]; IntVar L = LD[11]; IntVar M = LD[12]; IntVar N = LD[13]; IntVar O = LD[14]; IntVar P = LD[15]; IntVar Q = LD[16]; IntVar R = LD[17]; IntVar S = LD[18]; IntVar T = LD[19]; IntVar U = LD[20]; IntVar V = LD[21]; IntVar W = LD[22]; IntVar X = LD[23]; IntVar Y = LD[24]; IntVar Z = LD[25]; // // Constraints // solver.Add(LD.AllDifferent()); solver.Add( B + A + L + L + E + T == BALLET); solver.Add( C + E + L + L + O == CELLO); solver.Add( C + O + N + C + E + R + T == CONCERT); solver.Add( F + L + U + T + E == FLUTE); solver.Add( F + U + G + U + E == FUGUE); solver.Add( G + L + E + E == GLEE); solver.Add( J + A + Z + Z == JAZZ); solver.Add( L + Y + R + E == LYRE); solver.Add( O + B + O + E == OBOE); solver.Add( O + P + E + R + A == OPERA); solver.Add( P + O + L + K + A == POLKA); solver.Add( Q + U + A + R + T + E + T == QUARTET); solver.Add(S + A + X + O + P + H + O + N + E == SAXOPHONE); solver.Add( S + C + A + L + E == SCALE); solver.Add( S + O + L + O == SOLO); solver.Add( S + O + N + G == SONG); solver.Add( S + O + P + R + A + N + O == SOPRANO); solver.Add( T + H + E + M + E == THEME); solver.Add( V + I + O + L + I + N == VIOLIN); solver.Add( W + A + L + T + Z == WALTZ); // // Search // DecisionBuilder db = solver.MakePhase(LD, Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, Solver.ASSIGN_CENTER_VALUE); solver.NewSearch(db); String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; while (solver.NextSolution()) { for(int i = 0; i < num_letters; i++) { Console.WriteLine("{0}: {1,2}", str[i], LD[i].Value()); } Console.WriteLine(); } Console.WriteLine("\nWallTime: " + solver.WallTime() + "ms "); Console.WriteLine("Failures: " + solver.Failures()); Console.WriteLine("Branches: " + solver.Branches()); solver.EndSearch(); }
/* * Create Model: */ public static void Solve() { var solver = new Solver("Nurse Scheduling"); // The total number of nurses: 4 with values {0, ..., 3} int num_nurses = 4; // The number of shifts per day: 4 with values {0, ..., 3} // 3x 8h, shift = 0 means not working that day int num_shifts = 4; // The number of days: 7 with values {0 ... 6} int num_days = 7; // nurse[i, j] = k means nurse k works in shift i on day j IntVar[,] nurse = solver.MakeIntVarMatrix(num_shifts, num_days, 0, num_nurses - 1); /* * A nurse must not work two shifts on the same day: */ for (int j = 0; j < num_days; j++) { // Cells in the same nurse table column must have different values solver.Add(solver.MakeAllDifferent((from k in Enumerable.Range(0, num_shifts) select nurse[k, j]).ToArray())); } /* * Auxiliary decision variables: How many days does nurse k work in shift i */ IntVar[,] days = new IntVar[num_nurses, num_shifts]; for (int k = 0; k < num_nurses; k++) { for (int i = 0; i < num_shifts; i++) { days[k, i] = ((from j in Enumerable.Range(0, num_days) select nurse[i, j] == k).ToArray()).Sum().Var(); } } /* * Each nurse has at most 2 days off */ for (int k = 0; k < num_nurses; k++) { // Less than 3 days off per week solver.Add(days[k, 0] < 3); // At least one day off per week solver.Add(days[k, 0] > 0); } /* * Work and Holiday = 7 days (this is actually redundant) */ /*for (int k = 0; k < num_nurses; k++) * { * * solver.Add(((from i in Enumerable.Range(0, num_shifts) select days[k, i]).ToArray()).Sum() == 7); * * } * * /* * Shifts are staffed by at most two nurses per week: * Excluse shif 0 (i.e. days off) */ for (int i = 1; i < num_shifts; i++) { solver.Add(((from k in Enumerable.Range(0, num_nurses) select days[k, i] > 0).ToArray()).Sum() <= 2); } /* * Nurses work shift 2 or 3 on consecutive days * * Examples: * nurses[2, 1] == nurses[2, 2] is true if the same nurse works shift 2 on Monday and Tuesday * nurses[2, 2] == nurses[2, 3] is True if the same nurse works shift 2 on Tuesday or Wednesday * => at least one of the two cases must hold */ solver.Add(solver.MakeMax(nurse[2, 0] == nurse[2, 1], nurse[2, 1] == nurse[2, 2]) == 1); solver.Add(solver.MakeMax(nurse[2, 1] == nurse[2, 2], nurse[2, 2] == nurse[2, 3]) == 1); solver.Add(solver.MakeMax(nurse[2, 2] == nurse[2, 3], nurse[2, 3] == nurse[2, 4]) == 1); solver.Add(solver.MakeMax(nurse[2, 3] == nurse[2, 4], nurse[2, 4] == nurse[2, 5]) == 1); solver.Add(solver.MakeMax(nurse[2, 4] == nurse[2, 5], nurse[2, 5] == nurse[2, 6]) == 1); solver.Add(solver.MakeMax(nurse[2, 5] == nurse[2, 6], nurse[2, 6] == nurse[2, 0]) == 1); solver.Add(solver.MakeMax(nurse[2, 6] == nurse[2, 0], nurse[2, 0] == nurse[2, 1]) == 1); solver.Add(solver.MakeMax(nurse[3, 0] == nurse[3, 1], nurse[3, 1] == nurse[3, 2]) == 1); solver.Add(solver.MakeMax(nurse[3, 1] == nurse[3, 2], nurse[3, 2] == nurse[3, 3]) == 1); solver.Add(solver.MakeMax(nurse[3, 2] == nurse[3, 3], nurse[3, 3] == nurse[3, 4]) == 1); solver.Add(solver.MakeMax(nurse[3, 3] == nurse[3, 4], nurse[3, 4] == nurse[3, 5]) == 1); solver.Add(solver.MakeMax(nurse[3, 4] == nurse[3, 5], nurse[3, 5] == nurse[3, 6]) == 1); solver.Add(solver.MakeMax(nurse[3, 5] == nurse[3, 6], nurse[3, 6] == nurse[3, 0]) == 1); solver.Add(solver.MakeMax(nurse[3, 6] == nurse[3, 0], nurse[3, 0] == nurse[3, 1]) == 1); var all = nurse.Flatten().Concat(days.Flatten()).ToArray(); /* * Start solver */ DecisionBuilder db = solver.MakePhase(all, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); Console.WriteLine("Nurse Scheduling:\n"); int counter = 0; solver.NewSearch(db); while (solver.NextSolution() && counter < 2) { /*Console.WriteLine("Shift x Day -> Nurse\n"); * PrintSolution(nurse, (from i in Enumerable.Range(0, num_shifts) select "Shift "+i).ToArray(), new String[] {"M", "D", "M", "D", "F", "S", "S"}); * Console.WriteLine("\nNurse x Shift -> Days\n"); * PrintSolution(days, (from i in Enumerable.Range(0, num_nurses) select "Nurse " + i).ToArray(), (from i in Enumerable.Range(0, num_shifts) select i+"").ToArray()); * Console.WriteLine(); * counter++;*/ } Console.WriteLine("Solutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); Console.ReadKey(); }
/** * * Sicherman Dice. * * From http://en.wikipedia.org/wiki/Sicherman_dice * "" * Sicherman dice are the only pair of 6-sided dice which are not normal dice, * bear only positive integers, and have the same probability distribution for * the sum as normal dice. * * The faces on the dice are numbered 1, 2, 2, 3, 3, 4 and 1, 3, 4, 5, 6, 8. * "" * * I read about this problem in a book/column by Martin Gardner long * time ago, and got inspired to model it now by the WolframBlog post * "Sicherman Dice": http://blog.wolfram.com/2010/07/13/sicherman-dice/ * * This model gets the two different ways, first the standard way and * then the Sicherman dice: * * x1 = [1, 2, 3, 4, 5, 6] * x2 = [1, 2, 3, 4, 5, 6] * ---------- * x1 = [1, 2, 2, 3, 3, 4] * x2 = [1, 3, 4, 5, 6, 8] * * * Extra: If we also allow 0 (zero) as a valid value then the * following two solutions are also valid: * * x1 = [0, 1, 1, 2, 2, 3] * x2 = [2, 4, 5, 6, 7, 9] * ---------- * x1 = [0, 1, 2, 3, 4, 5] * x2 = [2, 3, 4, 5, 6, 7] * * These two extra cases are mentioned here: * http://mathworld.wolfram.com/SichermanDice.html * * * Also see http://www.hakank.org/or-tools/sicherman_dice.py * */ private static void Solve() { Solver solver = new Solver("SichermanDice"); // // Data // int n = 6; int m = 10; int lowest_value = 0; // standard distribution int[] standard_dist = { 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1 }; IEnumerable <int> RANGE = Enumerable.Range(0, n); IEnumerable <int> RANGE1 = Enumerable.Range(0, n - 1); // // Decision variables // IntVar[] x1 = solver.MakeIntVarArray(n, lowest_value, m, "x1"); IntVar[] x2 = solver.MakeIntVarArray(n, lowest_value, m, "x2"); // // Constraints // for (int k = 0; k < standard_dist.Length; k++) { solver.Add((from i in RANGE from j in RANGE select x1[i] + x2[j] == k + 2).ToArray().Sum() == standard_dist[k]); } // symmetry breaking foreach (int i in RANGE1) { solver.Add(x1[i] <= x1[i + 1]); solver.Add(x2[i] <= x2[i + 1]); solver.Add(x1[i] <= x2[i]); } // // Search // DecisionBuilder db = solver.MakePhase(x1.Concat(x2).ToArray(), Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db); while (solver.NextSolution()) { Console.Write("x1: "); foreach (int i in RANGE) { Console.Write(x1[i].Value() + " "); } Console.Write("\nx2: "); foreach (int i in RANGE) { Console.Write(x2[i].Value() + " "); } Console.WriteLine("\n"); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/** * * 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(); }