public IntVar[] MakeBoolVarArray(int count) { IntVar[] array = new IntVar[count]; for (int i = 0; i < count; ++i) { array[i] = MakeBoolVar(); } return array; }
public IntVar[] MakeIntVarArray(int count, long min, long max) { IntVar[] array = new IntVar[count]; for (int i = 0; i < count; ++i) { array[i] = MakeIntVar(min, max); } return array; }
public IntVar[] MakeIntVarArray(int count, int[] values) { IntVar[] array = new IntVar[count]; for (int i = 0; i < count; ++i) { array[i] = MakeIntVar(values); } return array; }
protected IntVarExprVar( IntVar var0, IntVar var1, IntVar var2 ) : base(var0.Solver, new Variable[] { var0, var1, var2 }) { m_Var0 = var0; m_Var1 = var1; m_Var2 = var2; }
public static void minus(Solver solver, IntVar x, IntVar y, IntVar z) { solver.Add(z == (x - y).Abs()); }
public MoreMoney() : base(0, 1000000) { IntVar d = new IntVar( m_Solver, 0, 9, "d"); IntVar e = new IntVar( m_Solver, 0, 9, "e"); IntVar m = new IntVar( m_Solver, 1, 9, "m"); IntVar n = new IntVar( m_Solver, 0, 9, "n"); IntVar o = new IntVar( m_Solver, 0, 9, "o"); IntVar r = new IntVar( m_Solver, 0, 9, "r"); IntVar s = new IntVar( m_Solver, 1, 9, "s"); IntVar y = new IntVar( m_Solver, 0, 9, "y"); IntVarList list = new IntVarList( m_Solver, new IntVar[] { d, e, m, n, o, r, s, y } ); m_Solver.Add( list.AllDifferent() ); IntVarListDotProduct send = new IntVarListDotProduct( m_Solver, new IntVar[] { s, e, n, d }, new int[] { 1000, 100, 10, 1 } ); IntVarListDotProduct more = new IntVarListDotProduct( m_Solver, new IntVar[] { m, o, r, e }, new int[] { 1000, 100, 10, 1 } ); IntVarListDotProduct money = new IntVarListDotProduct( m_Solver, new IntVar[] { m, o, n, e, y }, new int[] { 10000, 1000, 100, 10, 1 } ); m_Solver.Add( send ); m_Solver.Add( more ); m_Solver.Add( money ); IntVarExpr sendMore = send.Var0 + more.Var0; m_Solver.Add( sendMore ); IntVarCmp cmp = sendMore.Var0 == money.Var0; m_Solver.Add( cmp ); }
/* * Decompositon of cumulative. * * Inspired by the MiniZinc implementation: * http://www.g12.csse.unimelb.edu.au/wiki/doku.php?id=g12:zinc:lib:minizinc:std:cumulative.mzn&s[]=cumulative * The MiniZinc decomposition is discussed in the paper: * A. Schutt, T. Feydy, P.J. Stuckey, and M. G. Wallace. * "Why cumulative decomposition is not as bad as it sounds." * Download: * http://www.cs.mu.oz.au/%7Epjs/rcpsp/papers/cp09-cu.pdf * http://www.cs.mu.oz.au/%7Epjs/rcpsp/cumu_lazyfd.pdf * * * Parameters: * * s: start_times assumption: IntVar[] * d: durations assumption: int[] * r: resources assumption: int[] * b: resource limit assumption: IntVar or int * * */ static void MyCumulative(Solver solver, IntVar[] s, int[] d, int[] r, IntVar b) { int[] tasks = (from i in Enumerable.Range(0, s.Length) where r[i] > 0 && d[i] > 0 select i).ToArray(); int times_min = tasks.Min(i => (int)s[i].Min()); int d_max = d.Max(); int times_max = tasks.Max(i => (int)s[i].Max() + d_max); for(int t = times_min; t <= times_max; t++) { ArrayList bb = new ArrayList(); foreach(int i in tasks) { bb.Add(((s[i] <= t) * (s[i] + d[i]> t) * r[i]).Var()); } solver.Add((bb.ToArray(typeof(IntVar)) as IntVar[]).Sum() <= b); } // Somewhat experimental: // This constraint is needed to constrain the upper limit of b. if (b is IntVar) { solver.Add(b <= r.Sum()); } }
/** * * A simple propagator for modulo constraint. * * This implementation is based on the ECLiPSe version * mentioned in "A Modulo propagator for ECLiPSE" * http://www.hakank.org/constraint_programming_blog/2010/05/a_modulo_propagator_for_eclips.html * The ECLiPSe Prolog source code: * http://www.hakank.org/eclipse/modulo_propagator.ecl * */ public static void MyMod(Solver solver, IntVar x, IntVar y, IntVar r) { long lbx = x.Min(); long ubx = x.Max(); long ubx_neg = -ubx; long lbx_neg = -lbx; int min_x = (int)Math.Min(lbx, ubx_neg); int max_x = (int)Math.Max(ubx, lbx_neg); IntVar d = solver.MakeIntVar(min_x, max_x, "d"); // r >= 0 solver.Add(r >= 0); // x*r >= 0 solver.Add( x*r >= 0); // -abs(y) < r solver.Add(-y.Abs() < r); // r < abs(y) solver.Add(r < y.Abs()); // min_x <= d, i.e. d > min_x solver.Add(d > min_x); // d <= max_x solver.Add(d <= max_x); // x == y*d+r solver.Add(x - (y*d + r) == 0); }
public IntObjective( Solver solver ) : base(solver) { m_Variable = null; m_Value = int.MaxValue; m_Step = 1; }
/** * * 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(); }
public IntVar[] MakeIntVarArray(int count, long min, long max, string name) { IntVar[] array = new IntVar[count]; for (int i = 0; i < count; ++i) { string var_name = name + i; array[i] = MakeIntVar(min, max, var_name); } return array; }
public IntVar[] MakeBoolVarArray(int count, string name) { IntVar[] array = new IntVar[count]; for (int i = 0; i < count; ++i) { string var_name = name + i; array[i] = MakeBoolVar(var_name); } return array; }
public IntGenerate( Solver solver, IntVar[] list, IntVarSelector.Select select, IntSearch search ) : base(solver) { m_IntVarList = list; m_SelectVar = select; m_Search = search; m_Depth = new RevValue<double>( solver.StateStack, 1 ); }
public IntGenerate( Solver solver, IntVar[] list ) : base(solver) { m_IntVarList = list; m_SelectVar = IntVarSelector.CardinalityMin; m_Search = new IntSearchDichotomize(); m_Depth = new RevValue<double>( solver.StateStack, 1 ); }
// 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)); } }
/** * * toNum(solver, a, num, base) * * channelling between the array a and the number num. * */ private static Constraint ToNum(IntVar[] a, IntVar num, int bbase) { int len = a.Length; IntVar[] tmp = new IntVar[len]; for(int i = 0; i < len; i++) { tmp[i] = (a[i]*(int)Math.Pow(bbase,(len-i-1))).Var(); } return tmp.Sum() == num; }
/** * 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); } }
// // 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])); } } }
/* * Global constraint regular * * This is a translation of MiniZinc's regular constraint (defined in * lib/zinc/globals.mzn), via the Comet code refered above. * All comments are from the MiniZinc code. * """ * The sequence of values in array 'x' (which must all be in the range 1..S) * is accepted by the DFA of 'Q' states with input 1..S and transition * function 'd' (which maps (1..Q, 1..S) -> 0..Q)) and initial state 'q0' * (which must be in 1..Q) and accepting states 'F' (which all must be in * 1..Q). We reserve state 0 to be an always failing state. * """ * * x : IntVar array * Q : number of states * S : input_max * d : transition matrix * q0: initial state * F : accepting states * */ static void MyRegular(Solver solver, IntVar[] x, int Q, int S, int[,] d, int q0, int[] F) { Debug.Assert(Q > 0, "regular: 'Q' must be greater than zero"); Debug.Assert(S > 0, "regular: 'S' must be greater than zero"); // d2 is the same as d, except we add one extra transition for // each possible input; each extra transition is from state zero // to state zero. This allows us to continue even if we hit a // non-accepted input. int[][] d2 = new int[Q+1][]; for(int i = 0; i <= Q; i++) { int[] row = new int[S]; for(int j = 0; j < S; j++) { if (i == 0) { row[j] = 0; } else { row[j] = d[i-1,j]; } } d2[i] = row; } int[] d2_flatten = (from i in Enumerable.Range(0, Q+1) from j in Enumerable.Range(0, S) select d2[i][j]).ToArray(); // If x has index set m..n, then a[m-1] holds the initial state // (q0), and a[i+1] holds the state we're in after processing // x[i]. If a[n] is in F, then we succeed (ie. accept the // string). int m = 0; int n = x.Length; IntVar[] a = solver.MakeIntVarArray(n+1-m, 0,Q+1, "a"); // Check that the final state is in F solver.Add(a[a.Length-1].Member(F)); // First state is q0 solver.Add(a[m] == q0); for(int i = 0; i < n; i++) { solver.Add(x[i] >= 1); solver.Add(x[i] <= S); // Determine a[i+1]: a[i+1] == d2[a[i], x[i]] solver.Add(a[i+1] == d2_flatten.Element(((a[i]*S)+(x[i]-1)))); } }
public IntVar[] Copy( IntVar[] other ) { IntVar[] copy = new IntVar[ other.Length ]; for( int idx = 0; idx < other.Length; ++idx ) { copy[ idx ] = m_IntVarList[ other[ idx ].Index ]; } return copy; }
// // Simple decomposition of Prod() for an IntVar array // private static Constraint MyProd(IntVar[] x, int prod) { int len = x.Length; IntVar[] tmp = new IntVar[len]; tmp[0] = x[0]; for(int i = 1; i < len; i++) { tmp[i] = (tmp[i-1]*x[i]).Var(); } return tmp[len-1] == prod; }
/** * 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); }
public Cover( Solver solver, int columns, IntVarList list ) : base(solver) { m_Columns = columns; m_List = list; m_Avail = new IntVar( solver, 0, list.Count - 1 );; m_Index = new IntVar( solver, IntDomain.Empty, "" ); m_Union = new IntVar( solver, IntDomain.Empty, "" ); }
static void CheckIntRange(IntVar var, long vmin, long vmax) { if (var.Min() != vmin) { Console.WriteLine("Error: " + var.ToString() + " does not have the expected min : " + vmin); error_count_++; } if (var.Max() != vmax) { Console.WriteLine("Error: " + var.ToString() + " does not have the expected max : " + vmax); error_count_++; } }
public void Enumerator() { Solver solver = new Solver( -1000, 1000 ); IntVar var = new IntVar( solver, 0 ); var.Difference( 0 ); foreach( int x in var ) { Assert.Fail(); } }
/** * * Decomposition of alldifferent_except_0 * * See http://www.hakank.org/google_or_tools/map.py * * */ private static void Solve() { Solver solver = new Solver("AllDifferentExcept0"); // // data // int n = 6; // // Decision variables // IntVar[] x = solver.MakeIntVarArray(n, 0, n - 1 , "x"); // // Constraints // AllDifferentExcept0(solver, x); // we also require at least 2 0's IntVar[] z_tmp = new IntVar[n]; for(int i = 0; i < n; i++) { z_tmp[i] = x[i] == 0; } IntVar z = z_tmp.Sum().VarWithName("z"); solver.Add(z == 2); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db); while (solver.NextSolution()) { Console.Write("z: {0} x: ", z.Value()); for(int i = 0; i < n; i++) { Console.Write("{0} ", x[i].Value()); } Console.WriteLine(); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
private static long Solve(long num_buses_check = 0) { SolverParameters sPrm = new SolverParameters(); sPrm.compress_trail = 0; sPrm.trace_level = 0; sPrm.profile_level = 0; Solver solver = new Solver("OrTools",sPrm); //this works // IntVar[,] x = solver.MakeIntVarMatrix(2,2, new int[] {-2,0,1,2}, "x"); //this doesn't work IntVar[,] x = solver.MakeIntVarMatrix(2, 2, new int[] { 0, 1, 2 }, "x"); for (int w = 0; w < 2; w++) { IntVar[] b = new IntVar[2]; for (int i = 0; i < 2; i++) { b[i] = solver.MakeIsEqualCstVar(x[w, i], 0); } solver.Add(solver.MakeSumGreaterOrEqual(b, 2)); } IntVar[] x_flat = x.Flatten(); DecisionBuilder db = solver.MakePhase(x_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { Console.WriteLine("x: "); for (int j = 0; j < 2; j++) { Console.Write("worker" + (j + 1).ToString() + ":"); for (int i = 0; i < 2; i++) { Console.Write(" {0,2} ", x[j, i].Value()); } Console.Write("\n"); } Console.WriteLine("End at---->" + DateTime.Now); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); return 1; }
/** * * Solve the SEND+MORE=MONEY problem * */ private static void Solve() { Solver solver = new Solver("SendMoreMoney"); // // Decision variables // IntVar S = solver.MakeIntVar(0, 9, "S"); IntVar E = solver.MakeIntVar(0, 9, "E"); IntVar N = solver.MakeIntVar(0, 9, "N"); IntVar D = solver.MakeIntVar(0, 9, "D"); IntVar M = solver.MakeIntVar(0, 9, "M"); IntVar O = solver.MakeIntVar(0, 9, "O"); IntVar R = solver.MakeIntVar(0, 9, "R"); IntVar Y = solver.MakeIntVar(0, 9, "Y"); // for AllDifferent() IntVar[] x = new IntVar[] {S,E,N,D,M,O,R,Y}; // // Constraints // solver.Add(x.AllDifferent()); solver.Add(S*1000 + E*100 + N*10 + D + M*1000 + O*100 + R*10 + E == M*10000 + O*1000 + N*100 + E*10 + Y); solver.Add(S > 0); solver.Add(M > 0); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); solver.NewSearch(db); while (solver.NextSolution()) { for(int i = 0; i < 8; i++) { Console.Write(x[i].ToString() + " "); } Console.WriteLine(); } Console.WriteLine("\nWallTime: " + solver.WallTime() + "ms "); Console.WriteLine("Failures: " + solver.Failures()); Console.WriteLine("Branches: " + solver.Branches()); solver.EndSearch(); }
private void Pack(Solver cp, IntVar[] binvars, int[] weights, IntVar[] loadvars) { IntVar[] b = new IntVar[binvars.Length]; for(long j=0; j<loadvars.Length; j++) { for (int i = 0; i < binvars.Length; i++) { b[i] = cp.MakeIsEqualCstVar(binvars[i], j); } cp.Add(cp.MakeScalProd(b, weights) == loadvars[j]); } cp.Add(cp.MakeSumEquality(loadvars, cp.MakeIntVar(weights.Sum(), weights.Sum(), "Sum"))); }
public void Test() { Solver solver = new Solver( -1000, 1000 ); IntVar i0 = new IntVar( solver, 0, 10 ); IntVar i1 = new IntVar( solver, 10, 20 ); IntVar i2 = new IntVar( solver, 20, 30 ); IntVar s = new IntVar( solver, 30, 60 ); IntVarList list = new IntVarList( solver, new IntVar[] { i0, i1, i2 } ); IntVarListSum sum = list.Sum(); solver.Add( sum ); solver.Propagate(); Assert.AreEqual( s.Domain, sum.Var0.Domain ); }
static void ConstraintWithExprTest() { Console.WriteLine("TestConstraintWithExpr"); Solver solver = new Solver("test"); IntVar x = solver.MakeIntVar(0, 10, "x"); IntVar y = solver.MakeIntVar(0, 10, "y"); Constraint c1 = x == 2; Constraint c2 = y == 3; IntExpr e2a = c1 + 1; Console.WriteLine(e2a.ToString()); IntExpr e2b = 1 + c1; Console.WriteLine(e2b.ToString()); IntExpr e2c = c1 - 1; Console.WriteLine(e2c.ToString()); IntExpr e2d = 1 - c1; Console.WriteLine(e2d.ToString()); IntExpr e2e = c1 * 2; Console.WriteLine(e2e.ToString()); IntExpr e2f = 2 * c1; Console.WriteLine(e2f.ToString()); IntExpr e3a = c1 + y; Console.WriteLine(e3a.ToString()); IntExpr e3b = y + c1; Console.WriteLine(e3b.ToString()); IntExpr e3c = c1 - y; Console.WriteLine(e3c.ToString()); IntExpr e3d = y - c1; Console.WriteLine(e3d.ToString()); IntExpr e3e = c1 * y; Console.WriteLine(e3e.ToString()); IntExpr e3f = y * c1; Console.WriteLine(e3f.ToString()); IntExpr e4 = -c1; Console.WriteLine(e4.ToString()); IntExpr e5 = c1 / 4; Console.WriteLine(e5.ToString()); IntExpr e6 = c1.Abs(); Console.WriteLine(e6.ToString()); IntExpr e7 = c1.Square(); Console.WriteLine(e7.ToString()); Constraint c8a = c1 == 1; Console.WriteLine(c8a.ToString()); Constraint c8b = 1 == c1; Console.WriteLine(c8b.ToString()); Constraint c8c = c1 != 1; Console.WriteLine(c8c.ToString()); Constraint c8d = 1 != c1; Console.WriteLine(c8d.ToString()); Constraint c8e = c1 >= 1; Console.WriteLine(c8e.ToString()); Constraint c8f = 1 >= c1; Console.WriteLine(c8f.ToString()); Constraint c8g = c1 > 1; Console.WriteLine(c8g.ToString()); Constraint c8h = 1 > c1; Console.WriteLine(c8h.ToString()); Constraint c8i = c1 <= 1; Console.WriteLine(c8i.ToString()); Constraint c8j = 1 <= c1; Console.WriteLine(c8j.ToString()); Constraint c8k = c1 < 1; Console.WriteLine(c8k.ToString()); Constraint c8l = 1 < c1; Console.WriteLine(c8l.ToString()); Constraint c9a = c1 == y; Console.WriteLine(c9a.ToString()); Constraint c9b = y == c1; Console.WriteLine(c9b.ToString()); Constraint c9c = c1 != y; Console.WriteLine(c9c.ToString()); Constraint c9d = y != c1; Console.WriteLine(c9d.ToString()); Constraint c9e = c1 >= y; Console.WriteLine(c9e.ToString()); Constraint c9f = y >= c1; Console.WriteLine(c9f.ToString()); Constraint c9g = c1 > y; Console.WriteLine(c9g.ToString()); Constraint c9h = y > c1; Console.WriteLine(c9h.ToString()); Constraint c9i = c1 <= y; Console.WriteLine(c9i.ToString()); Constraint c9j = y <= c1; Console.WriteLine(c9j.ToString()); Constraint c9k = c1 < y; Console.WriteLine(c9k.ToString()); Constraint c9l = y < c1; Console.WriteLine(c9l.ToString()); Constraint c10a = c1 == c2; Console.WriteLine(c10a.ToString()); Constraint c10c = c1 != c2; Console.WriteLine(c10c.ToString()); Constraint c10e = c1 >= c2; Console.WriteLine(c10e.ToString()); Constraint c10g = c1 > c2; Console.WriteLine(c10g.ToString()); Constraint c10i = c1 <= c2; Console.WriteLine(c10i.ToString()); Constraint c10k = c1 < c2; Console.WriteLine(c10k.ToString()); IntExpr e11a = c1 + (y == 2); Console.WriteLine(e11a.ToString()); IntExpr e11b = (y == 2) + c1; Console.WriteLine(e11b.ToString()); IntExpr e11c = c1 - (y == 2); Console.WriteLine(e11c.ToString()); IntExpr e11d = (y == 2) - c1; Console.WriteLine(e11d.ToString()); IntExpr e11e = c1 * (y == 2); Console.WriteLine(e11e.ToString()); IntExpr e11f = (y == 2) * c1; Console.WriteLine(e11f.ToString()); Constraint c12a = c1 == (y == 2); Console.WriteLine(c12a.ToString()); Constraint c12b = (y == 2) == c1; Console.WriteLine(c12b.ToString()); Constraint c12c = c1 != (y == 2); Console.WriteLine(c12c.ToString()); Constraint c12d = (y == 2) != c1; Console.WriteLine(c12d.ToString()); Constraint c12e = c1 >= (y == 2); Console.WriteLine(c12e.ToString()); Constraint c12f = (y == 2) >= c1; Console.WriteLine(c12f.ToString()); Constraint c12g = c1 > (y == 2); Console.WriteLine(c12g.ToString()); Constraint c12h = (y == 2) > c1; Console.WriteLine(c12h.ToString()); Constraint c12i = c1 <= (y == 2); Console.WriteLine(c12i.ToString()); Constraint c12j = (y == 2) <= c1; Console.WriteLine(c12j.ToString()); Constraint c12k = c1 < (y == 2); Console.WriteLine(c12k.ToString()); Constraint c12l = (y == 2) < c1; Console.WriteLine(c12l.ToString()); }
/** * * Solves a set covering deployment problem. * See See http://www.hakank.org/or-tools/set_covering_deployment.py * */ private static void Solve() { Solver solver = new Solver("SetCoveringDeployment"); // // data // // From http://mathworld.wolfram.com/SetCoveringDeployment.html string[] countries = { "Alexandria", "Asia Minor", "Britain", "Byzantium", "Gaul", "Iberia", "Rome", "Tunis" }; int n = countries.Length; // the incidence matrix (neighbours) int[,] mat = { { 0, 1, 0, 1, 0, 0, 1, 1 }, { 1, 0, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 1, 1, 0, 0 }, { 1, 1, 0, 0, 0, 0, 1, 0 }, { 0, 0, 1, 0, 0, 1, 1, 0 }, { 0, 0, 1, 0, 1, 0, 1, 1 }, { 1, 0, 0, 1, 1, 1, 0, 1 }, { 1, 0, 0, 0, 0, 1, 1, 0 } }; // // Decision variables // // First army IntVar[] x = solver.MakeIntVarArray(n, 0, 1, "x"); // Second (reserve) army IntVar[] y = solver.MakeIntVarArray(n, 0, 1, "y"); // total number of armies IntVar num_armies = (x.Sum() + y.Sum()).Var(); // // Constraints // // // Constraint 1: There is always an army in a city // (+ maybe a backup) // Or rather: Is there a backup, there // must be an an army // for (int i = 0; i < n; i++) { solver.Add(x[i] >= y[i]); } // // Constraint 2: There should always be an backup // army near every city // for (int i = 0; i < n; i++) { IntVar[] count_neighbours = (from j in Enumerable.Range(0, n) where mat[i, j] == 1 select(y[j])) .ToArray(); solver.Add((x[i] + count_neighbours.Sum()) >= 1); } // // objective // OptimizeVar objective = num_armies.Minimize(1); // // Search // DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db, objective); while (solver.NextSolution()) { Console.WriteLine("num_armies: " + num_armies.Value()); for (int i = 0; i < n; i++) { if (x[i].Value() == 1) { Console.Write("Army: " + countries[i] + " "); } if (y[i].Value() == 1) { Console.WriteLine(" Reverse army: " + countries[i]); } } Console.WriteLine("\n"); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/* * Main Method: */ public static void Solve(Tuple <int, int[], int[], string[]> input) { var solver = new Solver("Knapsack"); // Total capacity: int capacity = input.Item1; // Weights and prices for each item: int[] weights = input.Item2; int[] prices = input.Item3; // Item names for pretty printing: string[] names = input.Item4; IntVar[] items = solver.MakeIntVarArray(names.Length, 0, capacity); /* * Constraints: */ solver.Add(solver.MakeScalProd(items, weights) <= capacity); /* * Objective Function: */ IntVar obj = solver.MakeScalProd(items, prices).Var(); /* * Start Solver: */ DecisionBuilder db = solver.MakePhase(items, Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); SolutionCollector col = solver.MakeBestValueSolutionCollector(true); col.AddObjective(obj); col.Add(items); Console.WriteLine("Knapsack Problem:\n"); if (solver.Solve(db, col)) { Assignment sol = col.Solution(0); Console.WriteLine("Maximum value found: " + sol.ObjectiveValue() + "\n"); for (int i = 0; i < items.Length; i++) { Console.WriteLine("Item " + names[i] + " is smuggled " + sol.Value(items[i]) + " time(s)."); } Console.WriteLine(); } Console.WriteLine("Solutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); Console.ReadKey(); }
public void doWork() { Solver solver = new Solver("Xmas Puzzle"); // n x m Matrix IntVar[,] board = new IntVar[this.size, this.size]; // Feed IntVar-matrix and feed solver with the predefined Field value... for (int row = 0; row < this.size; row++) { for (int column = 0; column < this.size; column++) { if (this.initialField[row, column] == X) { board[row, column] = solver.MakeIntVar(X, 0); // Range of -1 to 0 } else { board[row, column] = solver.MakeIntVar(0, 8); // board[row, column] MUST have the value of field[row, column] solver.Add(board[row, column] == this.initialField[row, column]); } } } // Search field-matrix for hints about the lost gifts and group the neighbours. // Sum of neighbours with "-1"-Value should be the same value like the inverted hint-value. // As an example: If hint is "4" then there should be four times a value of "-1" around the hint. // This should be enought to solve this puzzle. // Handy C# LINQ type for sequences: IEnumerable <int> RANGE = Enumerable.Range(0, 8); IEnumerable <int> ROW_LENGTH; IEnumerable <int> COLUMN_LENGTH; int rowOffset; int columnOffset; // Maximum of lost gifts solver.Add((from di in RANGE from dj in RANGE where this.initialField[di, dj] == -1 select board[di, dj]).ToArray().Sum() == -this.maxGifts); // Outer and inner loop searches for hints for (int row = 0; row < this.size; row++) { for (int column = 0; column < this.size; column++) { // If a hint was found, then group all neighbours with a value of "-1" if (this.initialField[row, column] != X) { // Now it's getting ugly... if (row == 0) { if (column == 0) { ROW_LENGTH = Enumerable.Range(0, 2); COLUMN_LENGTH = Enumerable.Range(0, 2); rowOffset = 0; columnOffset = 0; } else if (column == this.size - 1) { ROW_LENGTH = Enumerable.Range(0, 2); COLUMN_LENGTH = Enumerable.Range(0, 2); rowOffset = 0; columnOffset = -1; } else { ROW_LENGTH = Enumerable.Range(0, 2); COLUMN_LENGTH = Enumerable.Range(0, 3); rowOffset = 0; columnOffset = -1; } } else if (row == this.size - 1) { if (column == 0) { ROW_LENGTH = Enumerable.Range(0, 2); COLUMN_LENGTH = Enumerable.Range(0, 2); rowOffset = -1; columnOffset = 0; } else if (column == this.size - 1) { ROW_LENGTH = Enumerable.Range(0, 2); COLUMN_LENGTH = Enumerable.Range(0, 2); rowOffset = -1; columnOffset = -1; } else { ROW_LENGTH = Enumerable.Range(0, 2); COLUMN_LENGTH = Enumerable.Range(0, 3); rowOffset = -1; columnOffset = -1; } } else { if (column == 0) { ROW_LENGTH = Enumerable.Range(0, 3); COLUMN_LENGTH = Enumerable.Range(0, 2); rowOffset = -1; columnOffset = 0; } else if (column == this.size - 1) { ROW_LENGTH = Enumerable.Range(0, 3); COLUMN_LENGTH = Enumerable.Range(0, 2); rowOffset = -1; columnOffset = -1; } else { ROW_LENGTH = Enumerable.Range(0, 3); COLUMN_LENGTH = Enumerable.Range(0, 3); rowOffset = -1; columnOffset = -1; } } foreach (int i in ROW_LENGTH) { foreach (int j in COLUMN_LENGTH) { solver.Add((from di in ROW_LENGTH from dj in COLUMN_LENGTH where this.initialField[row + rowOffset + di, column + columnOffset + dj] == -1 select board[row + rowOffset + di, column + columnOffset + dj]).ToArray().Sum() == -this.initialField[row, column]); } } } } } DecisionBuilder db = solver.MakePhase( board.Flatten(), Solver.INT_VAR_SIMPLE, Solver.INT_VALUE_SIMPLE); solver.NewSearch(db); // Calculate first result for this solution // If more solutions are necessary, you can extend this part with a while(...)-Loop if (solver.NextSolution()) { printField(board); } }
private void CreateIntVar() => Int = (IntVar)MTools.CreateScriptableAsset(typeof(IntVar));
/** * * 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(); }
public RemoveThreeValues(Solver solver, IntVar x) : base(solver) {x_ = x;}
public CountHoles(IntVar x) {x_ = x; count_ = 0;}
public DumbGreaterOrEqualToFive(Solver solver, IntVar x) : base(solver) {x_ = x;}
public void ApplyChange(IntVar amount) { Value += amount.Value; }
public SetMaxDemon(IntVar x) {x_ = x;}
/** * * 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(); }
static void BinpackingProblem() { // Data. int bin_capacity = 100; int slack_capacity = 20; int num_bins = 10; int[,] items = new int[, ] { { 20, 12 }, { 15, 12 }, { 30, 8 }, { 45, 5 } }; int num_items = items.GetLength(0); // Model. CpModel model = new CpModel(); // Main variables. IntVar[,] x = new IntVar[num_items, num_bins]; for (int i = 0; i < num_items; ++i) { int num_copies = items[i, 1]; for (int b = 0; b < num_bins; ++b) { x[i, b] = model.NewIntVar(0, num_copies, String.Format("x_{0}_{1}", i, b)); } } // Load variables. IntVar[] load = new IntVar[num_bins]; for (int b = 0; b < num_bins; ++b) { load[b] = model.NewIntVar(0, bin_capacity, String.Format("load_{0}", b)); } // Slack variables. IntVar[] slacks = new IntVar[num_bins]; for (int b = 0; b < num_bins; ++b) { slacks[b] = model.NewBoolVar(String.Format("slack_{0}", b)); } // Links load and x. int[] sizes = new int[num_items]; for (int i = 0; i < num_items; ++i) { sizes[i] = items[i, 0]; } for (int b = 0; b < num_bins; ++b) { IntVar[] tmp = new IntVar[num_items]; for (int i = 0; i < num_items; ++i) { tmp[i] = x[i, b]; } model.Add(load[b] == tmp.ScalProd(sizes)); } // Place all items. for (int i = 0; i < num_items; ++i) { IntVar[] tmp = new IntVar[num_bins]; for (int b = 0; b < num_bins; ++b) { tmp[b] = x[i, b]; } model.Add(tmp.Sum() == items[i, 1]); } // Links load and slack. int safe_capacity = bin_capacity - slack_capacity; for (int b = 0; b < num_bins; ++b) { // slack[b] => load[b] <= safe_capacity. model.Add(load[b] <= safe_capacity).OnlyEnforceIf(slacks[b]); // not(slack[b]) => load[b] > safe_capacity. model.Add(load[b] > safe_capacity).OnlyEnforceIf(slacks[b].Not()); } // Maximize sum of slacks. model.Maximize(slacks.Sum()); // Solves and prints out the solution. CpSolver solver = new CpSolver(); CpSolverStatus status = solver.Solve(model); Console.WriteLine(String.Format("Solve status: {0}", status)); if (status == CpSolverStatus.Optimal) { Console.WriteLine(String.Format("Optimal objective value: {0}", solver.ObjectiveValue)); for (int b = 0; b < num_bins; ++b) { Console.WriteLine(String.Format("load_{0} = {1}", b, solver.Value(load[b]))); for (int i = 0; i < num_items; ++i) { Console.WriteLine(string.Format(" item_{0}_{1} = {2}", i, b, solver.Value(x[i, b]))); } } } Console.WriteLine("Statistics"); Console.WriteLine(String.Format(" - conflicts : {0}", solver.NumConflicts())); Console.WriteLine(String.Format(" - branches : {0}", solver.NumBranches())); Console.WriteLine(String.Format(" - wall time : {0} s", solver.WallTime())); }
/** * * 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(); }
public PackingResultWrapper Run(List <long> radii) { var model = new CpModel(); const int dimension = 2; var domainConstraint = 2 * radii.Sum(); // ---------------------------------------------------------------- // Variable declaration // ---------------------------------------------------------------- // Integer bundle radius, 0 <= x <= 2 * the sum of radii var bundleRadius = model.NewIntVar(0, domainConstraint, "r"); // Coordinates (x, y) of the centers of inner circles, -2 * the sum of radii <= x, y <= 2 * the sum of radii var circleCenters = new IntVar[radii.Count, dimension]; for (var i = 0; i < radii.Count; i++) { for (var j = 0; j < dimension; j++) { circleCenters[i, j] = model.NewIntVar(-domainConstraint, domainConstraint, $"alpha_{i},{j}"); } } // Slack variable - Coordinates (x, y) of the centers of inner circles squared, 0 <= x, y < infinity var circleCentersSquared = new IntVar[radii.Count, dimension]; for (var i = 0; i < radii.Count; i++) { for (var j = 0; j < dimension; j++) { circleCentersSquared[i, j] = model.NewIntVar(0, uint.MaxValue, $"s_alpha_{i},{j}"); } } // Inner circle radii - input var circleRadii = new IntVar[radii.Count]; for (var i = 0; i < radii.Count; i++) { circleRadii[i] = model.NewIntVar(radii[i], radii[i], $"r_{i}"); } // Slack variable - bundle radius minus the inner circle radius, -2 * the sum of radii <= x <= 2 * the sum of radii var circleRadiiSlack = new IntVar[radii.Count]; for (var i = 0; i < radii.Count; i++) { circleRadiiSlack[i] = model.NewIntVar(-domainConstraint, domainConstraint, $"s_r_{i}"); } // Slack variable - bundle radius minus the inner circle radius, 0 <= x < infinity var circleRadiiSlackSquared = new IntVar[radii.Count]; for (var i = 0; i < radii.Count; i++) { circleRadiiSlackSquared[i] = model.NewIntVar(0, uint.MaxValue, $"s_r_s_{i}"); } // Slack variable - The difference of the centers of two inner circles on a single axis, // -2 * the sum of radii <= x <= 2 * the sum of radii var circleDistances = new IntVar[radii.Count, radii.Count, dimension]; for (var i = 0; i < radii.Count; i++) { for (var j = 0; j < radii.Count; j++) { for (var k = 0; k < dimension; k++) { circleDistances[i, j, k] = model.NewIntVar(-domainConstraint, domainConstraint, $"s_d_{i}_{j}_{k}"); } } } // The square distance of the centers of two inner circles on a single axis, 0 <= x < infinity var circleDistancesSquared = new IntVar[radii.Count, radii.Count, dimension]; for (var i = 0; i < radii.Count; i++) { for (var j = 0; j < radii.Count; j++) { for (var k = 0; k < dimension; k++) { circleDistancesSquared[i, j, k] = model.NewIntVar(0, uint.MaxValue, $"s_d_s_{i}_{j}_{k}"); } } } // The sum of radii of two inner circles, 0 <= x <= 2 * the sum of radii var radiiSum = new IntVar[radii.Count, radii.Count]; for (var i = 0; i < radii.Count; i++) { for (var j = 0; j < radii.Count; j++) { radiiSum[i, j] = model.NewIntVar(0, domainConstraint, $"s_rs_{i}_{j}"); } } // Slack variable - The square of the sum of radii of two inner circles, 0 <= x <= infinity var radiiSumSquared = new IntVar[radii.Count, radii.Count]; for (var i = 0; i < radii.Count; i++) { for (var j = 0; j < radii.Count; j++) { radiiSumSquared[i, j] = model.NewIntVar(0, uint.MaxValue, $"s_rs_s_{i}_{j}"); } } // ---------------------------------------------------------------- // Constraint declaration // ---------------------------------------------------------------- // (1) Bundle radius lower bound model.AddMaxEquality(bundleRadius, circleRadii); // (2) All inner circles are fully contained in the bundle for (var i = 0; i < radii.Count; i++) { // The solver doesn't support the multiplication of negative variables! Further constraints or domain limitation is needed. /* * model.Add(circleCenters[i, 0] >= 0); * model.Add(circleCenters[i, 1] >= 0); * model.Add(circleRadiiSlack[i] >= 0); */ model.AddProdEquality(circleCentersSquared[i, 0], new List <IntVar> { circleCenters[i, 0], circleCenters[i, 0] }); model.AddProdEquality(circleCentersSquared[i, 1], new List <IntVar> { circleCenters[i, 1], circleCenters[i, 1] }); // NOT FEASIBLE with this constraint model.Add(bundleRadius == circleRadiiSlack[i] + circleRadii[i]); model.AddProdEquality(circleRadiiSlackSquared[i], new[] { circleRadiiSlack[i], circleRadiiSlack[i] }); // NOT FEASIBLE with this constraint model.Add(circleCentersSquared[i, 0] + circleCentersSquared[i, 1] <= circleRadiiSlackSquared[i]); } // (3) No two inner circles overlap for (var i = 0; i < radii.Count; i++) { for (var j = 0; j < radii.Count; j++) { if (i == j) { continue; } // The solver doesn't support the multiplication of negative variables! Further constraints or domain limitation is needed. /* * model.Add(circleDistances[i, j, 0] >= 0); * model.Add(circleDistances[i, j, 1] >= 0); */ model.Add(circleDistances[i, j, 0] == circleCenters[i, 0] - circleCenters[j, 0]); model.Add(circleDistances[i, j, 1] == circleCenters[i, 1] - circleCenters[j, 1]); model.AddProdEquality(circleDistancesSquared[i, j, 0], new List <IntVar> { circleDistances[i, j, 0], circleDistances[i, j, 0] }); model.AddProdEquality(circleDistancesSquared[i, j, 1], new List <IntVar> { circleDistances[i, j, 1], circleDistances[i, j, 1] }); model.Add(radiiSum[i, j] == circleRadii[i] + circleRadii[j]); // NOT FEASIBLE with this constraint model.AddProdEquality(radiiSumSquared[i, j], new List <IntVar> { radiiSum[i, j], radiiSum[i, j] }); model.Add(circleDistancesSquared[i, j, 0] + circleDistancesSquared[i, j, 1] >= radiiSumSquared[i, j]); } } // ---------------------------------------------------------------- // Target declaration // ---------------------------------------------------------------- // Minimize the radius of the bundle model.Minimize(bundleRadius); var solver = new CpSolver(); var status = solver.Solve(model); if (status != CpSolverStatus.Feasible && status != CpSolverStatus.Optimal) { throw new NotImplementedException(); } var bundle = new Circle((long)solver.Value(bundleRadius), new Point(0, 0)); var innerCircles = new List <Circle>(); for (var i = 0; i < radii.Count; i++) { innerCircles.Add(new Circle((long)solver.Value(circleRadii[i]), new Point(solver.Value(circleCenters[i, 0]), solver.Value(circleCenters[i, 1])))); } return(new PackingResultWrapper(bundle, innerCircles)); }
public void SetValue(IntVar value) { Value = value.Value; }
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."); } }
static void BaseEqualityWithExprTest() { Console.WriteLine("TestBaseEqualityWithExpr"); Solver solver = new Solver("test"); IntVar x = solver.MakeIntVar(0, 10, "x"); IntVar y = solver.MakeIntVar(0, 10, "y"); IntExpr e2a = (x >= 1) + 1; Console.WriteLine(e2a.ToString()); IntExpr e2b = 1 + (x >= 1); Console.WriteLine(e2b.ToString()); IntExpr e2c = (x >= 1) - 1; Console.WriteLine(e2c.ToString()); IntExpr e2d = 1 - (x >= 1); Console.WriteLine(e2d.ToString()); IntExpr e2e = (x >= 1) * 2; Console.WriteLine(e2e.ToString()); IntExpr e2f = 2 * (x >= 1); Console.WriteLine(e2f.ToString()); IntExpr e3a = (x >= 1) + y; Console.WriteLine(e3a.ToString()); IntExpr e3b = y + (x >= 1); Console.WriteLine(e3b.ToString()); IntExpr e3c = (x >= 1) - y; Console.WriteLine(e3c.ToString()); IntExpr e3d = y - (x >= 1); Console.WriteLine(e3d.ToString()); IntExpr e3e = (x >= 1) * y; Console.WriteLine(e3e.ToString()); IntExpr e3f = y * (x >= 1); Console.WriteLine(e3f.ToString()); IntExpr e4 = -(x >= 1); Console.WriteLine(e4.ToString()); IntExpr e5 = (x >= 1) / 4; Console.WriteLine(e5.ToString()); IntExpr e6 = (x >= 1).Abs(); Console.WriteLine(e6.ToString()); IntExpr e7 = (x >= 1).Square(); Console.WriteLine(e7.ToString()); Constraint c8a = (x >= 1) >= 1; Console.WriteLine(c8a.ToString()); Constraint c8b = 1 >= (x >= 1); Console.WriteLine(c8b.ToString()); Constraint c8c = (x >= 1) != 1; Console.WriteLine(c8c.ToString()); Constraint c8d = 1 != (x >= 1); Console.WriteLine(c8d.ToString()); Constraint c8e = (x >= 1) >= 1; Console.WriteLine(c8e.ToString()); Constraint c8f = 1 >= (x >= 1); Console.WriteLine(c8f.ToString()); Constraint c8g = (x >= 1) > 1; Console.WriteLine(c8g.ToString()); Constraint c8h = 1 > (x >= 1); Console.WriteLine(c8h.ToString()); Constraint c8i = (x >= 1) <= 1; Console.WriteLine(c8i.ToString()); Constraint c8j = 1 <= (x >= 1); Console.WriteLine(c8j.ToString()); Constraint c8k = (x >= 1) < 1; Console.WriteLine(c8k.ToString()); Constraint c8l = 1 < (x >= 1); Console.WriteLine(c8l.ToString()); Constraint c9a = (x >= 1) >= y; Console.WriteLine(c9a.ToString()); Constraint c9b = y >= (x >= 1); Console.WriteLine(c9b.ToString()); Constraint c9c = (x >= 1) != y; Console.WriteLine(c9c.ToString()); Constraint c9d = y != (x >= 1); Console.WriteLine(c9d.ToString()); Constraint c9e = (x >= 1) >= y; Console.WriteLine(c9e.ToString()); Constraint c9f = y >= (x >= 1); Console.WriteLine(c9f.ToString()); Constraint c9g = (x >= 1) > y; Console.WriteLine(c9g.ToString()); Constraint c9h = y > (x >= 1); Console.WriteLine(c9h.ToString()); Constraint c9i = (x >= 1) <= y; Console.WriteLine(c9i.ToString()); Constraint c9j = y <= (x >= 1); Console.WriteLine(c9j.ToString()); Constraint c9k = (x >= 1) < y; Console.WriteLine(c9k.ToString()); Constraint c9l = y < (x >= 1); Console.WriteLine(c9l.ToString()); Constraint c10a = (x >= 1) >= (y >= 2); Console.WriteLine(c10a.ToString()); Constraint c10c = (x >= 1) != (y >= 2); Console.WriteLine(c10c.ToString()); Constraint c10e = (x >= 1) >= (y >= 2); Console.WriteLine(c10e.ToString()); Constraint c10g = (x >= 1) > (y >= 2); Console.WriteLine(c10g.ToString()); Constraint c10i = (x >= 1) <= (y >= 2); Console.WriteLine(c10i.ToString()); Constraint c10k = (x >= 1) < (y >= 2); Console.WriteLine(c10k.ToString()); }
/** * * A Round of Golf puzzle (Dell Logic Puzzles) in Google CP Solver. * * From http://brownbuffalo.sourceforge.net/RoundOfGolfClues.html * """ * Title: A Round of Golf * Author: Ellen K. Rodehorst * Publication: Dell Favorite Logic Problems * Issue: Summer, 2000 * Puzzle #: 9 * Stars: 1 * * When the Sunny Hills Country Club golf course isn't in use by club members, * of course, it's open to the club's employees. Recently, Jack and three * other workers at the golf course got together on their day off to play a * round of eighteen holes of golf. Afterward, all four, including Mr. Green, * went to the clubhouse to total their scorecards. Each man works at a * different job (one is a short-order cook), and each shot a different score * in the game. No one scored below 70 or above 85 strokes. From the clues * below, can you discover each man's full name, job and golf score? * * 1. Bill, who is not the maintenance man, plays golf often and had the * lowest score of the foursome. * 2. Mr. Clubb, who isn't Paul, hit several balls into the woods and scored * ten strokes more than the pro-shop clerk. * 3. In some order, Frank and the caddy scored four and seven more strokes * than Mr. Sands. * 4. Mr. Carter thought his score of 78 was one of his better games, even * though Frank's score was lower. * 5. None of the four scored exactly 81 strokes. * * Determine: First Name - Last Name - Job - Score * """ * * See http://www.hakank.org/google_or_tools/a_round_of_golf.py * */ private static void Solve() { Solver solver = new Solver("ARoundOfGolf"); // number of speakers int n = 4; int Jack = 0; int Bill = 1; int Paul = 2; int Frank = 3; // // Decision variables // IntVar[] last_name = solver.MakeIntVarArray(n, 0, n - 1, "last_name"); // IntVar Green = last_name[0]; // not used IntVar Clubb = last_name[1]; IntVar Sands = last_name[2]; IntVar Carter = last_name[3]; IntVar[] job = solver.MakeIntVarArray(n, 0, n - 1, "job"); // IntVar cook = job[0]; // not used IntVar maintenance_man = job[1]; IntVar clerk = job[2]; IntVar caddy = job[3]; IntVar[] score = solver.MakeIntVarArray(n, 70, 85, "score"); // for search IntVar[] all = new IntVar[n * 3]; for (int i = 0; i < n; i++) { all[i] = last_name[i]; all[i + n] = job[i]; all[i + 2 * n] = score[i]; } // // Constraints // solver.Add(last_name.AllDifferent()); solver.Add(job.AllDifferent()); solver.Add(score.AllDifferent()); // 1. Bill, who is not the maintenance man, plays golf often and had // the lowest score of the foursome. solver.Add(maintenance_man != Bill); solver.Add(score[Bill] < score[Jack]); solver.Add(score[Bill] < score[Paul]); solver.Add(score[Bill] < score[Frank]); // 2. Mr. Clubb, who isn't Paul, hit several balls into the woods and // scored ten strokes more than the pro-shop clerk. solver.Add(Clubb != Paul); solver.Add(score.Element(Clubb) == score.Element(clerk) + 10); // 3. In some order, Frank and the caddy scored four and seven more // strokes than Mr. Sands. solver.Add(caddy != Frank); solver.Add(Sands != Frank); solver.Add(caddy != Sands); IntVar b3_a_1 = score.Element(Sands) + 4 == score[Frank]; IntVar b3_a_2 = score.Element(caddy) == score.Element(Sands) + 7; IntVar b3_b_1 = score.Element(Sands) + 7 == score[Frank]; IntVar b3_b_2 = score.Element(caddy) == score.Element(Sands) + 4; solver.Add((b3_a_1 * b3_a_2) + (b3_b_1 * b3_b_2) == 1); // 4. Mr. Carter thought his score of 78 was one of his better games, // even though Frank's score was lower. solver.Add(Carter != Frank); solver.Add(score.Element(Carter) == 78); solver.Add(score[Frank] < score.Element(Carter)); // 5. None of the four scored exactly 81 strokes. for (int i = 0; i < n; i++) { solver.Add(score[i] != 81); } // // Search // DecisionBuilder db = solver.MakePhase(all, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); solver.NewSearch(db); while (solver.NextSolution()) { Console.WriteLine("Last name: " + String.Join(", ", (from i in last_name select i.Value().ToString()).ToArray())); Console.WriteLine("Job : " + String.Join(", ", (from i in job select i.Value().ToString()).ToArray())); Console.WriteLine("Score : " + String.Join(", ", (from i in score select i.Value().ToString()).ToArray())); } Console.WriteLine("\nSolutions: {0}", solver.Solutions()); Console.WriteLine("WallTime: {0}ms", solver.WallTime()); Console.WriteLine("Failures: {0}", solver.Failures()); Console.WriteLine("Branches: {0} ", solver.Branches()); solver.EndSearch(); }
/// <summary> Set an specific Speed for a State using IntVars </summary> public virtual void SetSpeed(IntVar speedIndex) { CurrentSpeedIndex = speedIndex; }
/// <summary>Find a Stat Using an IntVar and Return if the Stat is on the List. Also Saves it to the PinnedStat</summary> public virtual Stat Stat_Get(IntVar ID) => Stat_Get(ID.Value);
/** * * 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(); }
static void Main() { CpModel model = new CpModel(); // Three weeks. int horizon = 100; int num_tasks = 4; IntVar[] starts = new IntVar[num_tasks]; IntVar[] ends = new IntVar[num_tasks]; IntervalVar[] intervals = new IntervalVar[num_tasks]; ILiteral[] presences = new ILiteral[num_tasks]; IntVar[] ranks = new IntVar[num_tasks]; IntVar true_var = model.NewConstant(1); // Creates intervals, half of them are optional. for (int t = 0; t < num_tasks; ++t) { starts[t] = model.NewIntVar(0, horizon, String.Format("start_{0}", t)); int duration = t + 1; ends[t] = model.NewIntVar(0, horizon, String.Format("end_{0}", t)); if (t < num_tasks / 2) { intervals[t] = model.NewIntervalVar(starts[t], duration, ends[t], String.Format("interval_{0}", t)); presences[t] = true_var; } else { presences[t] = model.NewBoolVar(String.Format("presence_{0}", t)); intervals[t] = model.NewOptionalIntervalVar(starts[t], duration, ends[t], presences[t], String.Format("o_interval_{0}", t)); } // Ranks = -1 if and only if the tasks is not performed. ranks[t] = model.NewIntVar(-1, num_tasks - 1, String.Format("rank_{0}", t)); } // Adds NoOverlap constraint. model.AddNoOverlap(intervals); // Adds ranking constraint. RankTasks(model, starts, presences, ranks); // Adds a constraint on ranks. model.Add(ranks[0] < ranks[1]); // Creates makespan variable. IntVar makespan = model.NewIntVar(0, horizon, "makespan"); for (int t = 0; t < num_tasks; ++t) { model.Add(ends[t] <= makespan).OnlyEnforceIf(presences[t]); } // Minimizes makespan - fixed gain per tasks performed. // As the fixed cost is less that the duration of the last interval, // the solver will not perform the last interval. IntVar[] presences_as_int_vars = new IntVar[num_tasks]; for (int t = 0; t < num_tasks; ++t) { presences_as_int_vars[t] = (IntVar)presences[t]; } model.Minimize(2 * makespan - 7 * LinearExpr.Sum(presences_as_int_vars)); // Creates a solver and solves the model. CpSolver solver = new CpSolver(); CpSolverStatus status = solver.Solve(model); if (status == CpSolverStatus.Optimal) { Console.WriteLine(String.Format("Optimal cost: {0}", solver.ObjectiveValue)); Console.WriteLine(String.Format("Makespan: {0}", solver.Value(makespan))); for (int t = 0; t < num_tasks; ++t) { if (solver.BooleanValue(presences[t])) { Console.WriteLine(String.Format("Task {0} starts at {1} with rank {2}", t, solver.Value(starts[t]), solver.Value(ranks[t]))); } else { Console.WriteLine(String.Format("Task {0} in not performed and ranked at {1}", t, solver.Value(ranks[t]))); } } } else { Console.WriteLine(String.Format("Solver exited with nonoptimal status: {0}", status)); } }
static void RankTasks(CpModel model, IntVar[] starts, ILiteral[] presences, IntVar[] ranks) { int num_tasks = starts.Length; // Creates precedence variables between pairs of intervals. ILiteral[,] precedences = new ILiteral[num_tasks, num_tasks]; for (int i = 0; i < num_tasks; ++i) { for (int j = 0; j < num_tasks; ++j) { if (i == j) { precedences[i, i] = presences[i]; } else { IntVar prec = model.NewBoolVar(String.Format("{0} before {1}", i, j)); precedences[i, j] = prec; model.Add(starts[i] < starts[j]).OnlyEnforceIf(prec); } } } // Treats optional intervals. for (int i = 0; i < num_tasks - 1; ++i) { for (int j = i + 1; j < num_tasks; ++j) { List <ILiteral> tmp_array = new List <ILiteral>(); tmp_array.Add(precedences[i, j]); tmp_array.Add(precedences[j, i]); tmp_array.Add(presences[i].Not()); // Makes sure that if i is not performed, all precedences are false. model.AddImplication(presences[i].Not(), precedences[i, j].Not()); model.AddImplication(presences[i].Not(), precedences[j, i].Not()); tmp_array.Add(presences[j].Not()); // Makes sure that if j is not performed, all precedences are false. model.AddImplication(presences[j].Not(), precedences[i, j].Not()); model.AddImplication(presences[j].Not(), precedences[j, i].Not()); // The following bool_or will enforce that for any two intervals: // i precedes j or j precedes i or at least one interval is not // performed. model.AddBoolOr(tmp_array); // Redundant constraint: it propagates early that at most one precedence // is true. model.AddImplication(precedences[i, j], precedences[j, i].Not()); model.AddImplication(precedences[j, i], precedences[i, j].Not()); } } // Links precedences and ranks. for (int i = 0; i < num_tasks; ++i) { IntVar[] tmp_array = new IntVar[num_tasks]; for (int j = 0; j < num_tasks; ++j) { tmp_array[j] = (IntVar)precedences[j, i]; } model.Add(ranks[i] == LinearExpr.Sum(tmp_array) - 1); } }
/** * * 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(); }
/* * 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(); }
public void Solve() { CpModel model = new CpModel(); int num_vals = 9; IntVar[][] grid = new IntVar[9][]; for (int k = 0; k < 9; k++) { grid[k] = new IntVar[9]; } for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (Sudoku.getCaseInitialSudoku(i, j) == 0) { grid[i][j] = model.NewIntVar(1, num_vals, "C" + i.ToString() + j.ToString()); } else { grid[i][j] = model.NewIntVar(Sudoku.getCaseInitialSudoku(i, j), Sudoku.getCaseInitialSudoku(i, j), "C" + i.ToString() + j.ToString()); } } } for (int k = 0; k < 9; k++) { model.AddAllDifferent(grid[k]); model.AddAllDifferent(Transpose(grid)[k]); } for (int k = 0; k < 3; k++) { for (int l = 0; l < 3; l++) { List <IntVar> boxList = new List <IntVar>(); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { boxList.Add(grid[k * 3 + i][l * 3 + j]); } } model.AddAllDifferent(boxList); } } CpSolver solver = new CpSolver(); VarArraySolutionPrinter cb = new VarArraySolutionPrinter(grid); solver.SearchAllSolutions(model, cb); int[][] values = cb.getValues(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (Sudoku.getCaseSudoku(i, j) == 0) { Sudoku.setCaseSudoku(i, j, values[i][j]); } } } }
/** * * 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 SetMinAndMaxConstraint(Solver solver, IntVar x) : base(solver) {x_ = x;}
/** * * 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(); }