From a9385fc3d2691d049a1b141f82ee0d5aa4e113f8 Mon Sep 17 00:00:00 2001 From: Corentin Le Molgat Date: Tue, 3 Nov 2020 10:04:19 +0100 Subject: [PATCH] Format all .Net using Microsoft style --- .clang-format | 2 +- examples/contrib/3_jugs_regular.cs | 472 ++-- examples/contrib/a_puzzle.cs | 373 +-- examples/contrib/a_round_of_golf.cs | 277 +-- examples/contrib/all_interval.cs | 126 +- examples/contrib/alldifferent_except_0.cs | 143 +- examples/contrib/assignment.cs | 191 +- examples/contrib/broken_weights.cs | 261 ++- examples/contrib/bus_schedule.cs | 175 +- examples/contrib/circuit.cs | 155 +- examples/contrib/circuit2.cs | 176 +- examples/contrib/coins3.cs | 150 +- examples/contrib/coins_grid.cs | 165 +- examples/contrib/combinatorial_auction2.cs | 146 +- examples/contrib/contiguity_regular.cs | 305 +-- examples/contrib/contiguity_transition.cs | 160 +- examples/contrib/costas_array.cs | 262 ++- examples/contrib/covering_opl.cs | 169 +- examples/contrib/crew.cs | 405 ++-- examples/contrib/crossword.cs | 308 +-- examples/contrib/crypta.cs | 164 +- examples/contrib/crypto.cs | 272 +-- examples/contrib/csdiet.cs | 125 +- examples/contrib/curious_set_of_integers.cs | 158 +- examples/contrib/debruijn.cs | 331 +-- examples/contrib/discrete_tomography.cs | 332 +-- examples/contrib/divisible_by_9_through_1.cs | 285 +-- examples/contrib/dudeney.cs | 161 +- examples/contrib/einav_puzzle2.cs | 345 +-- examples/contrib/eq10.cs | 141 +- examples/contrib/eq20.cs | 194 +- examples/contrib/fill_a_pix.cs | 387 ++-- examples/contrib/furniture_moving.cs | 234 +- .../contrib/furniture_moving_intervals.cs | 227 +- examples/contrib/futoshiki.cs | 247 +- examples/contrib/golomb_ruler.cs | 171 +- examples/contrib/grocery.cs | 158 +- examples/contrib/hidato_table.cs | 421 ++-- examples/contrib/just_forgotten.cs | 175 +- examples/contrib/kakuro.cs | 340 +-- examples/contrib/kenken2.cs | 368 +-- examples/contrib/killer_sudoku.cs | 377 +-- examples/contrib/labeled_dice.cs | 256 ++- examples/contrib/langford.cs | 146 +- examples/contrib/least_diff.cs | 117 +- examples/contrib/lectures.cs | 286 +-- examples/contrib/magic_sequence.cs | 146 +- examples/contrib/magic_square.cs | 212 +- examples/contrib/magic_square_and_cards.cs | 176 +- examples/contrib/map.cs | 128 +- examples/contrib/map2.cs | 139 +- examples/contrib/marathon2.cs | 209 +- examples/contrib/max_flow_taha.cs | 173 +- examples/contrib/max_flow_winston1.cs | 220 +- examples/contrib/minesweeper.cs | 360 +-- examples/contrib/mr_smith.cs | 192 +- examples/contrib/nontransitive_dice.cs | 331 +-- examples/contrib/nqueens.cs | 166 +- examples/contrib/nurse_rostering_regular.cs | 550 ++--- .../contrib/nurse_rostering_transition.cs | 461 ++-- examples/contrib/olympic.cs | 204 +- examples/contrib/organize_day.cs | 187 +- examples/contrib/organize_day_intervals.cs | 162 +- examples/contrib/p_median.cs | 184 +- examples/contrib/pandigital_numbers.cs | 305 +-- examples/contrib/partition.cs | 195 +- examples/contrib/perfect_square_sequence.cs | 224 +- examples/contrib/photo_problem.cs | 214 +- examples/contrib/place_number_puzzle.cs | 151 +- examples/contrib/post_office_problem2.cs | 201 +- examples/contrib/quasigroup_completion.cs | 370 +-- examples/contrib/regex.cs | 295 +-- examples/contrib/rogo2.cs | 552 ++--- examples/contrib/scheduling_speakers.cs | 117 +- examples/contrib/secret_santa.cs | 181 +- examples/contrib/secret_santa2.cs | 405 ++-- examples/contrib/send_more_money.cs | 103 +- examples/contrib/send_more_money2.cs | 122 +- examples/contrib/send_most_money.cs | 168 +- examples/contrib/seseman.cs | 173 +- examples/contrib/set_covering.cs | 125 +- examples/contrib/set_covering2.cs | 138 +- examples/contrib/set_covering3.cs | 181 +- examples/contrib/set_covering4.cs | 189 +- examples/contrib/set_covering_deployment.cs | 169 +- examples/contrib/set_covering_skiena.cs | 174 +- examples/contrib/set_partition.cs | 298 +-- examples/contrib/sicherman_dice.cs | 216 +- examples/contrib/ski_assignment.cs | 176 +- examples/contrib/stable_marriage.cs | 325 +-- examples/contrib/strimko2.cs | 158 +- examples/contrib/subset_sum.cs | 156 +- examples/contrib/sudoku.cs | 168 +- examples/contrib/survo_puzzle.cs | 378 ++-- examples/contrib/to_num.cs | 141 +- examples/contrib/traffic_lights.cs | 209 +- examples/contrib/volsay.cs | 87 +- examples/contrib/volsay2.cs | 122 +- examples/contrib/volsay3.cs | 136 +- examples/contrib/wedding_optimal_chart.cs | 238 +- examples/contrib/who_killed_agatha.cs | 242 +- examples/contrib/word_square.cs | 292 +-- examples/contrib/xkcd.cs | 95 +- examples/contrib/young_tableaux.cs | 213 +- examples/contrib/zebra.cs | 244 +- examples/dotnet/BalanceGroupSat.cs | 328 +-- examples/dotnet/GateSchedulingSat.cs | 180 +- examples/dotnet/JobshopFt06Sat.cs | 179 +- examples/dotnet/JobshopSat.cs | 325 +-- examples/dotnet/NetworkRoutingSat.cs | 2014 +++++++++-------- examples/dotnet/NursesSat.cs | 309 +-- examples/dotnet/ShiftSchedulingSat.cs | 887 ++++---- examples/dotnet/SpeakerSchedulingSat.cs | 326 +-- examples/dotnet/TaskSchedulingSat.cs | 333 +-- examples/dotnet/cscvrptw.cs | 611 ++--- examples/dotnet/csflow.cs | 148 +- examples/dotnet/csintegerprogramming.cs | 176 +- examples/dotnet/csknapsack.cs | 39 +- examples/dotnet/cslinearprogramming.cs | 247 +- examples/dotnet/csls_api.cs | 286 +-- examples/dotnet/csrabbitspheasants.cs | 82 +- examples/dotnet/cstsp.cs | 189 +- examples/tests/ConstraintSolverTests.cs | 1752 +++++++------- examples/tests/LinearSolverTests.cs | 761 ++++--- examples/tests/RoutingSolverTests.cs | 67 +- examples/tests/SatSolverTests.cs | 708 +++--- examples/tests/issue18.cs | 58 +- examples/tests/issue22.cs | 104 +- examples/tests/issue33.cs | 1156 +++++----- ortools/algorithms/samples/Knapsack.cs | 50 +- .../csharp/IntArrayHelper.cs | 28 +- .../csharp/IntVarArrayHelper.cs | 666 +++--- .../csharp/IntervalVarArrayHelper.cs | 56 +- .../csharp/NetDecisionBuilder.cs | 369 +-- .../constraint_solver/csharp/SolverHelper.cs | 991 ++++---- .../constraint_solver/csharp/ValCstPair.cs | 542 +++-- .../samples/SimpleCpProgram.cs | 83 +- .../samples/SimpleRoutingProgram.cs | 113 +- ortools/constraint_solver/samples/Tsp.cs | 245 +- .../samples/TspCircuitBoard.cs | 278 +-- .../constraint_solver/samples/TspCities.cs | 168 +- .../samples/TspDistanceMatrix.cs | 178 +- ortools/constraint_solver/samples/Vrp.cs | 190 +- .../constraint_solver/samples/VrpCapacity.cs | 239 +- .../constraint_solver/samples/VrpDropNodes.cs | 291 +-- .../samples/VrpGlobalSpan.cs | 204 +- .../samples/VrpInitialRoutes.cs | 234 +- .../samples/VrpPickupDelivery.cs | 244 +- .../samples/VrpPickupDeliveryFifo.cs | 246 +- .../samples/VrpPickupDeliveryLifo.cs | 246 +- .../constraint_solver/samples/VrpResources.cs | 340 +-- .../samples/VrpStartsEnds.cs | 210 +- .../samples/VrpTimeWindows.cs | 291 +-- .../samples/VrpWithTimeLimit.cs | 167 +- ortools/dotnet/CreateSigningKey/Program.cs | 40 +- ortools/graph/samples/SimpleMaxFlowProgram.cs | 91 +- .../graph/samples/SimpleMinCostFlowProgram.cs | 116 +- .../linear_solver/csharp/LinearConstraint.cs | 250 +- ortools/linear_solver/csharp/LinearExpr.cs | 558 +++-- ortools/linear_solver/csharp/SolverHelper.cs | 354 +-- .../linear_solver/csharp/VariableHelper.cs | 363 +-- .../linear_solver/samples/AssignmentMip.cs | 172 +- .../linear_solver/samples/BinPackingMip.cs | 182 +- .../samples/LinearProgrammingExample.cs | 92 +- ortools/linear_solver/samples/MipVarArray.cs | 161 +- .../samples/MultipleKnapsackMip.cs | 180 +- .../linear_solver/samples/SimpleLpProgram.cs | 74 +- .../linear_solver/samples/SimpleMipProgram.cs | 91 +- ortools/sat/csharp/Constraints.cs | 78 +- ortools/sat/csharp/CpModel.cs | 1265 ++++++----- ortools/sat/csharp/CpSolver.cs | 296 ++- ortools/sat/csharp/IntegerExpressions.cs | 1294 ++++++----- ortools/sat/csharp/IntervalVariables.cs | 121 +- ortools/sat/csharp/SearchHelpers.cs | 164 +- ortools/sat/samples/AssignmentSat.cs | 181 +- ortools/sat/samples/BinPackingProblemSat.cs | 177 +- ortools/sat/samples/BoolOrSampleSat.cs | 16 +- ortools/sat/samples/ChannelingSampleSat.cs | 85 +- ortools/sat/samples/CpIsFunSat.cs | 119 +- .../EarlinessTardinessCostSampleSat.cs | 109 +- ortools/sat/samples/IntervalSampleSat.cs | 22 +- ortools/sat/samples/LiteralSampleSat.cs | 14 +- ortools/sat/samples/NoOverlapSampleSat.cs | 82 +- .../sat/samples/OptionalIntervalSampleSat.cs | 25 +- ortools/sat/samples/RabbitsAndPheasantsSat.cs | 37 +- ortools/sat/samples/RankingSampleSat.cs | 272 ++- ortools/sat/samples/ReifiedSampleSat.cs | 32 +- .../samples/SearchForAllSolutionsSampleSat.cs | 92 +- ortools/sat/samples/SimpleSatProgram.cs | 57 +- .../sat/samples/SolutionHintingSampleSat.cs | 102 +- ...eAndPrintIntermediateSolutionsSampleSat.cs | 100 +- .../samples/SolveWithTimeLimitSampleSat.cs | 45 +- ortools/sat/samples/StepFunctionSampleSat.cs | 120 +- .../samples/StopAfterNSolutionsSampleSat.cs | 81 +- ortools/util/csharp/NestedArrayHelper.cs | 85 +- ortools/util/csharp/ProtoHelper.cs | 27 +- 196 files changed, 26140 insertions(+), 23301 deletions(-) diff --git a/.clang-format b/.clang-format index b2fec7b2e5..11d13507ac 100644 --- a/.clang-format +++ b/.clang-format @@ -9,5 +9,5 @@ Language: Java BasedOnStyle: Google --- Language: CSharp -BasedOnStyle: Google +BasedOnStyle: Microsoft ... diff --git a/examples/contrib/3_jugs_regular.cs b/examples/contrib/3_jugs_regular.cs index 05d3c332b2..c1fbacbe0d 100644 --- a/examples/contrib/3_jugs_regular.cs +++ b/examples/contrib/3_jugs_regular.cs @@ -19,247 +19,267 @@ using System.Linq; using System.Diagnostics; using Google.OrTools.ConstraintSolver; -public class ThreeJugsRegular { - /* - * 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)))); - } - } - - /** - * - * 3 jugs problem using regular constraint in Google CP Solver. - * - * A.k.a. water jugs problem. - * - * Problem from Taha 'Introduction to Operations Research', - * page 245f . - * - * For more info about the problem, see: - * http://mathworld.wolfram.com/ThreeJugProblem.html - * - * This model use a regular constraint for handling the - * transitions between the states. Instead of minimizing - * the cost in a cost matrix (as shortest path problem), - * we here call the model with increasing length of the - * sequence array (x). - * - * - * Also see http://www.hakank.org/or-tools/3_jugs_regular.py - * - */ - private static bool Solve(int n) { - Solver solver = new Solver("ThreeJugProblem"); - - // - // Data - // - - // the DFA (for regular) - int n_states = 14; - int input_max = 15; - int initial_state = 1; // state 0 is for the failing state - int[] accepting_states = { 15 }; - - // - // Manually crafted DFA - // (from the adjacency matrix used in the other models) - // +public class ThreeJugsRegular +{ /* - int[,] transition_fn = { - // 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - {0, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0}, // 1 - {0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 2 - {0, 0, 0, 4, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0}, // 3 - {0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 4 - {0, 0, 0, 0, 0, 6, 0, 0, 9, 0, 0, 0, 0, 0, 0}, // 5 - {0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, // 6 - {0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0}, // 7 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, // 8 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0}, // 9 - {0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0}, // 10 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0}, // 11 - {0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0}, // 12 - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0}, // 13 - {0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, // 14 - // 15 - }; - */ + * 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"); - // - // However, the DFA is easy to create from adjacency lists. - // - int[][] states = { - new int[] { 2, 9 }, // state 1 - new int[] { 3 }, // state 2 - new int[] { 4, 9 }, // state 3 - new int[] { 5 }, // state 4 - new int[] { 6, 9 }, // state 5 - new int[] { 7 }, // state 6 - new int[] { 8, 9 }, // state 7 - new int[] { 15 }, // state 8 - new int[] { 10 }, // state 9 - new int[] { 11 }, // state 10 - new int[] { 12 }, // state 11 - new int[] { 13 }, // state 12 - new int[] { 14 }, // state 13 - new int[] { 15 } // state 14 - }; - - int[,] transition_fn = new int[n_states, input_max]; - for (int i = 0; i < n_states; i++) { - for (int j = 1; j <= input_max; j++) { - bool in_states = false; - for (int s = 0; s < states[i].Length; s++) { - if (j == states[i][s]) { - in_states = true; - break; - } + // 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; } - if (in_states) { - transition_fn[i, j - 1] = j; - } else { - transition_fn[i, j - 1] = 0; + + 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)))); } - } } - // - // The name of the nodes, for printing - // the solution. - // - string[] nodes = { - "8,0,0", // 1 start - "5,0,3", // 2 - "5,3,0", // 3 - "2,3,3", // 4 - "2,5,1", // 5 - "7,0,1", // 6 - "7,1,0", // 7 - "4,1,3", // 8 - "3,5,0", // 9 - "3,2,3", // 10 - "6,2,0", // 11 - "6,0,2", // 12 - "1,5,2", // 13 - "1,4,3", // 14 - "4,4,0" // 15 goal - }; + /** + * + * 3 jugs problem using regular constraint in Google CP Solver. + * + * A.k.a. water jugs problem. + * + * Problem from Taha 'Introduction to Operations Research', + * page 245f . + * + * For more info about the problem, see: + * http://mathworld.wolfram.com/ThreeJugProblem.html + * + * This model use a regular constraint for handling the + * transitions between the states. Instead of minimizing + * the cost in a cost matrix (as shortest path problem), + * we here call the model with increasing length of the + * sequence array (x). + * + * + * Also see http://www.hakank.org/or-tools/3_jugs_regular.py + * + */ + private static bool Solve(int n) + { + Solver solver = new Solver("ThreeJugProblem"); - // - // Decision variables - // + // + // Data + // - // Note: We use 1..2 (instead of 0..1) and subtract 1 in the solution - IntVar[] x = solver.MakeIntVarArray(n, 1, input_max, "x"); + // the DFA (for regular) + int n_states = 14; + int input_max = 15; + int initial_state = 1; // state 0 is for the failing state + int[] accepting_states = { 15 }; - // - // Constraints - // - MyRegular(solver, x, n_states, input_max, transition_fn, initial_state, accepting_states); + // + // Manually crafted DFA + // (from the adjacency matrix used in the other models) + // + /* + int[,] transition_fn = { + // 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + {0, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0}, // 1 + {0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 2 + {0, 0, 0, 4, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0}, // 3 + {0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 4 + {0, 0, 0, 0, 0, 6, 0, 0, 9, 0, 0, 0, 0, 0, 0}, // 5 + {0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, // 6 + {0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0}, // 7 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, // 8 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0}, // 9 + {0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0}, // 10 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0}, // 11 + {0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0}, // 12 + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0}, // 13 + {0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, // 14 + // 15 + }; + */ - // - // Search - // - DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); + // + // However, the DFA is easy to create from adjacency lists. + // + int[][] states = { + new int[] { 2, 9 }, // state 1 + new int[] { 3 }, // state 2 + new int[] { 4, 9 }, // state 3 + new int[] { 5 }, // state 4 + new int[] { 6, 9 }, // state 5 + new int[] { 7 }, // state 6 + new int[] { 8, 9 }, // state 7 + new int[] { 15 }, // state 8 + new int[] { 10 }, // state 9 + new int[] { 11 }, // state 10 + new int[] { 12 }, // state 11 + new int[] { 13 }, // state 12 + new int[] { 14 }, // state 13 + new int[] { 15 } // state 14 + }; - solver.NewSearch(db); + int[,] transition_fn = new int[n_states, input_max]; + for (int i = 0; i < n_states; i++) + { + for (int j = 1; j <= input_max; j++) + { + bool in_states = false; + for (int s = 0; s < states[i].Length; s++) + { + if (j == states[i][s]) + { + in_states = true; + break; + } + } + if (in_states) + { + transition_fn[i, j - 1] = j; + } + else + { + transition_fn[i, j - 1] = 0; + } + } + } - bool found = false; - while (solver.NextSolution()) { - Console.WriteLine("\nFound a solution of length {0}", n + 1); - int[] x_val = new int[n]; - x_val[0] = 1; - Console.WriteLine("{0} -> {1}", nodes[0], nodes[x_val[0]]); - for (int i = 1; i < n; i++) { - // Note: here we subtract 1 to get 0..1 - int val = (int)x[i].Value() - 1; - x_val[i] = val; - Console.WriteLine("{0} -> {1}", nodes[x_val[i - 1]], nodes[x_val[i]]); - } - Console.WriteLine(); + // + // The name of the nodes, for printing + // the solution. + // + string[] nodes = { + "8,0,0", // 1 start + "5,0,3", // 2 + "5,3,0", // 3 + "2,3,3", // 4 + "2,5,1", // 5 + "7,0,1", // 6 + "7,1,0", // 7 + "4,1,3", // 8 + "3,5,0", // 9 + "3,2,3", // 10 + "6,2,0", // 11 + "6,0,2", // 12 + "1,5,2", // 13 + "1,4,3", // 14 + "4,4,0" // 15 goal + }; - 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()); + // + // Decision variables + // - found = true; + // Note: We use 1..2 (instead of 0..1) and subtract 1 in the solution + IntVar[] x = solver.MakeIntVarArray(n, 1, input_max, "x"); + + // + // Constraints + // + MyRegular(solver, x, n_states, input_max, transition_fn, initial_state, accepting_states); + + // + // Search + // + DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); + + solver.NewSearch(db); + + bool found = false; + while (solver.NextSolution()) + { + Console.WriteLine("\nFound a solution of length {0}", n + 1); + int[] x_val = new int[n]; + x_val[0] = 1; + Console.WriteLine("{0} -> {1}", nodes[0], nodes[x_val[0]]); + for (int i = 1; i < n; i++) + { + // Note: here we subtract 1 to get 0..1 + int val = (int)x[i].Value() - 1; + x_val[i] = val; + Console.WriteLine("{0} -> {1}", nodes[x_val[i - 1]], nodes[x_val[i]]); + } + Console.WriteLine(); + + Console.WriteLine("\nSolutions: {0}", solver.Solutions()); + Console.WriteLine("WallTime: {0}ms", solver.WallTime()); + Console.WriteLine("Failures: {0}", solver.Failures()); + Console.WriteLine("Branches: {0} ", solver.Branches()); + + found = true; + } + + solver.EndSearch(); + + return found; } - solver.EndSearch(); - - return found; - } - - public static void Main(String[] args) { - for (int n = 1; n < 15; n++) { - bool found = Solve(n); - if (found) { - break; - } + public static void Main(String[] args) + { + for (int n = 1; n < 15; n++) + { + bool found = Solve(n); + if (found) + { + break; + } + } } - } } diff --git a/examples/contrib/a_puzzle.cs b/examples/contrib/a_puzzle.cs index 39b9a407c7..dba4bf67d7 100644 --- a/examples/contrib/a_puzzle.cs +++ b/examples/contrib/a_puzzle.cs @@ -17,206 +17,215 @@ using System; using System.Linq; using Google.OrTools.ConstraintSolver; -public class APuzzle { - /** - * - * From "God plays dice" - * "A puzzle" - * http://gottwurfelt.wordpress.com/2012/02/22/a-puzzle/ - * And the sequel "Answer to a puzzle" - * http://gottwurfelt.wordpress.com/2012/02/24/an-answer-to-a-puzzle/ - * - * This problem instance was taken from the latter blog post. - * (Problem 1) - * - * """ - * 8809 = 6 - * 7111 = 0 - * 2172 = 0 - * 6666 = 4 - * 1111 = 0 - * 3213 = 0 - * 7662 = 2 - * 9312 = 1 - * 0000 = 4 - * 2222 = 0 - * 3333 = 0 - * 5555 = 0 - * 8193 = 3 - * 8096 = 5 - * 7777 = 0 - * 9999 = 4 - * 7756 = 1 - * 6855 = 3 - * 9881 = 5 - * 5531 = 0 - * - * 2581 = ? - * """ - * - * Note: - * This model yields 10 solutions, since x4 is not - * restricted in the constraints. - * All solutions has x assigned to the correct result. - * - * - * (Problem 2) - * The problem stated in "A puzzle" - * http://gottwurfelt.wordpress.com/2012/02/22/a-puzzle/ - * is - * """ - * 8809 = 6 - * 7662 = 2 - * 9312 = 1 - * 8193 = 3 - * 8096 = 5 - * 7756 = 1 - * 6855 = 3 - * 9881 = 5 - * - * 2581 = ? - * """ - * This problem instance yields two different solutions of x, - * one is the same (correct) as for the above problem instance, - * and one is not. - * This is because here x0,x1,x4 and x9 are underdefined. - * - * - */ - private static void Solve(int p = 1) { - Solver solver = new Solver("APuzzle"); +public class APuzzle +{ + /** + * + * From "God plays dice" + * "A puzzle" + * http://gottwurfelt.wordpress.com/2012/02/22/a-puzzle/ + * And the sequel "Answer to a puzzle" + * http://gottwurfelt.wordpress.com/2012/02/24/an-answer-to-a-puzzle/ + * + * This problem instance was taken from the latter blog post. + * (Problem 1) + * + * """ + * 8809 = 6 + * 7111 = 0 + * 2172 = 0 + * 6666 = 4 + * 1111 = 0 + * 3213 = 0 + * 7662 = 2 + * 9312 = 1 + * 0000 = 4 + * 2222 = 0 + * 3333 = 0 + * 5555 = 0 + * 8193 = 3 + * 8096 = 5 + * 7777 = 0 + * 9999 = 4 + * 7756 = 1 + * 6855 = 3 + * 9881 = 5 + * 5531 = 0 + * + * 2581 = ? + * """ + * + * Note: + * This model yields 10 solutions, since x4 is not + * restricted in the constraints. + * All solutions has x assigned to the correct result. + * + * + * (Problem 2) + * The problem stated in "A puzzle" + * http://gottwurfelt.wordpress.com/2012/02/22/a-puzzle/ + * is + * """ + * 8809 = 6 + * 7662 = 2 + * 9312 = 1 + * 8193 = 3 + * 8096 = 5 + * 7756 = 1 + * 6855 = 3 + * 9881 = 5 + * + * 2581 = ? + * """ + * This problem instance yields two different solutions of x, + * one is the same (correct) as for the above problem instance, + * and one is not. + * This is because here x0,x1,x4 and x9 are underdefined. + * + * + */ + private static void Solve(int p = 1) + { + Solver solver = new Solver("APuzzle"); - Console.WriteLine("\nSolving p{0}", p); + Console.WriteLine("\nSolving p{0}", p); - // - // Data - // - int n = 10; + // + // Data + // + int n = 10; - // - // Decision variables - // - IntVar x0 = solver.MakeIntVar(0, n - 1, "x0"); - IntVar x1 = solver.MakeIntVar(0, n - 1, "x1"); - IntVar x2 = solver.MakeIntVar(0, n - 1, "x2"); - IntVar x3 = solver.MakeIntVar(0, n - 1, "x3"); - IntVar x4 = solver.MakeIntVar(0, n - 1, "x4"); - IntVar x5 = solver.MakeIntVar(0, n - 1, "x5"); - IntVar x6 = solver.MakeIntVar(0, n - 1, "x6"); - IntVar x7 = solver.MakeIntVar(0, n - 1, "x7"); - IntVar x8 = solver.MakeIntVar(0, n - 1, "x8"); - IntVar x9 = solver.MakeIntVar(0, n - 1, "x9"); + // + // Decision variables + // + IntVar x0 = solver.MakeIntVar(0, n - 1, "x0"); + IntVar x1 = solver.MakeIntVar(0, n - 1, "x1"); + IntVar x2 = solver.MakeIntVar(0, n - 1, "x2"); + IntVar x3 = solver.MakeIntVar(0, n - 1, "x3"); + IntVar x4 = solver.MakeIntVar(0, n - 1, "x4"); + IntVar x5 = solver.MakeIntVar(0, n - 1, "x5"); + IntVar x6 = solver.MakeIntVar(0, n - 1, "x6"); + IntVar x7 = solver.MakeIntVar(0, n - 1, "x7"); + IntVar x8 = solver.MakeIntVar(0, n - 1, "x8"); + IntVar x9 = solver.MakeIntVar(0, n - 1, "x9"); - IntVar[] all = { x0, x1, x2, x3, x4, x5, x6, x7, x8, x9 }; + IntVar[] all = { x0, x1, x2, x3, x4, x5, x6, x7, x8, x9 }; - // The unknown, i.e. 2581 = x - IntVar x = solver.MakeIntVar(0, n - 1, "x"); + // The unknown, i.e. 2581 = x + IntVar x = solver.MakeIntVar(0, n - 1, "x"); - // - // Constraints - // + // + // Constraints + // - // Both problem are here shown in two - // approaches: - // - using equations - // - using a a matrix and Sum of each row + // Both problem are here shown in two + // approaches: + // - using equations + // - using a a matrix and Sum of each row - if (p == 1) { - // Problem 1 - solver.Add(x8 + x8 + x0 + x9 == 6); - solver.Add(x7 + x1 + x1 + x1 == 0); - solver.Add(x2 + x1 + x7 + x2 == 0); - solver.Add(x6 + x6 + x6 + x6 == 4); - solver.Add(x1 + x1 + x1 + x1 == 0); - solver.Add(x3 + x2 + x1 + x3 == 0); - solver.Add(x7 + x6 + x6 + x2 == 2); - solver.Add(x9 + x3 + x1 + x2 == 1); - solver.Add(x0 + x0 + x0 + x0 == 4); - solver.Add(x2 + x2 + x2 + x2 == 0); - solver.Add(x3 + x3 + x3 + x3 == 0); - solver.Add(x5 + x5 + x5 + x5 == 0); - solver.Add(x8 + x1 + x9 + x3 == 3); - solver.Add(x8 + x0 + x9 + x6 == 5); - solver.Add(x7 + x7 + x7 + x7 == 0); - solver.Add(x9 + x9 + x9 + x9 == 4); - solver.Add(x7 + x7 + x5 + x6 == 1); - solver.Add(x6 + x8 + x5 + x5 == 3); - solver.Add(x9 + x8 + x8 + x1 == 5); - solver.Add(x5 + x5 + x3 + x1 == 0); + if (p == 1) + { + // Problem 1 + solver.Add(x8 + x8 + x0 + x9 == 6); + solver.Add(x7 + x1 + x1 + x1 == 0); + solver.Add(x2 + x1 + x7 + x2 == 0); + solver.Add(x6 + x6 + x6 + x6 == 4); + solver.Add(x1 + x1 + x1 + x1 == 0); + solver.Add(x3 + x2 + x1 + x3 == 0); + solver.Add(x7 + x6 + x6 + x2 == 2); + solver.Add(x9 + x3 + x1 + x2 == 1); + solver.Add(x0 + x0 + x0 + x0 == 4); + solver.Add(x2 + x2 + x2 + x2 == 0); + solver.Add(x3 + x3 + x3 + x3 == 0); + solver.Add(x5 + x5 + x5 + x5 == 0); + solver.Add(x8 + x1 + x9 + x3 == 3); + solver.Add(x8 + x0 + x9 + x6 == 5); + solver.Add(x7 + x7 + x7 + x7 == 0); + solver.Add(x9 + x9 + x9 + x9 == 4); + solver.Add(x7 + x7 + x5 + x6 == 1); + solver.Add(x6 + x8 + x5 + x5 == 3); + solver.Add(x9 + x8 + x8 + x1 == 5); + solver.Add(x5 + x5 + x3 + x1 == 0); - // The unknown - solver.Add(x2 + x5 + x8 + x1 == x); + // The unknown + solver.Add(x2 + x5 + x8 + x1 == x); + } + else if (p == 2) + { + // Another representation of Problem 1 + int[,] problem1 = { { 8, 8, 0, 9, 6 }, { 7, 1, 1, 1, 0 }, { 2, 1, 7, 2, 0 }, { 6, 6, 6, 6, 4 }, + { 1, 1, 1, 1, 0 }, { 3, 2, 1, 3, 0 }, { 7, 6, 6, 2, 2 }, { 9, 3, 1, 2, 1 }, + { 0, 0, 0, 0, 4 }, { 2, 2, 2, 2, 0 }, { 3, 3, 3, 3, 0 }, { 5, 5, 5, 5, 0 }, + { 8, 1, 9, 3, 3 }, { 8, 0, 9, 6, 5 }, { 7, 7, 7, 7, 0 }, { 9, 9, 9, 9, 4 }, + { 7, 7, 5, 6, 1 }, { 6, 8, 5, 5, 3 }, { 9, 8, 8, 1, 5 }, { 5, 5, 3, 1, 0 } }; - } else if (p == 2) { - // Another representation of Problem 1 - int[,] problem1 = { { 8, 8, 0, 9, 6 }, { 7, 1, 1, 1, 0 }, { 2, 1, 7, 2, 0 }, - { 6, 6, 6, 6, 4 }, { 1, 1, 1, 1, 0 }, { 3, 2, 1, 3, 0 }, - { 7, 6, 6, 2, 2 }, { 9, 3, 1, 2, 1 }, { 0, 0, 0, 0, 4 }, - { 2, 2, 2, 2, 0 }, { 3, 3, 3, 3, 0 }, { 5, 5, 5, 5, 0 }, - { 8, 1, 9, 3, 3 }, { 8, 0, 9, 6, 5 }, { 7, 7, 7, 7, 0 }, - { 9, 9, 9, 9, 4 }, { 7, 7, 5, 6, 1 }, { 6, 8, 5, 5, 3 }, - { 9, 8, 8, 1, 5 }, { 5, 5, 3, 1, 0 } }; + for (int i = 0; i < problem1.GetLength(0); i++) + { + solver.Add((from j in Enumerable.Range(0, 4) select all[problem1[i, j]]).ToArray().Sum() == + problem1[i, 4]); + } - for (int i = 0; i < problem1.GetLength(0); i++) { - solver.Add((from j in Enumerable.Range(0, 4) select all[problem1[i, j]]).ToArray().Sum() == - problem1[i, 4]); - } + solver.Add(all[2] + all[5] + all[8] + all[1] == x); + } + else if (p == 3) + { + // Problem 2 + solver.Add(x8 + x8 + x0 + x9 == 6); + solver.Add(x7 + x6 + x6 + x2 == 2); + solver.Add(x9 + x3 + x1 + x2 == 1); + solver.Add(x8 + x1 + x9 + x3 == 3); + solver.Add(x8 + x0 + x9 + x6 == 5); + solver.Add(x7 + x7 + x5 + x6 == 1); + solver.Add(x6 + x8 + x5 + x5 == 3); + solver.Add(x9 + x8 + x8 + x1 == 5); - solver.Add(all[2] + all[5] + all[8] + all[1] == x); + // The unknown + solver.Add(x2 + x5 + x8 + x1 == x); + } + else + { + // Another representation of Problem 2 + int[,] problem2 = { { 8, 8, 0, 9, 6 }, { 7, 6, 6, 2, 2 }, { 9, 3, 1, 2, 1 }, { 8, 1, 9, 3, 3 }, + { 8, 0, 9, 6, 5 }, { 7, 7, 5, 6, 1 }, { 6, 8, 5, 5, 3 }, { 9, 8, 8, 1, 5 } }; - } else if (p == 3) { - // Problem 2 - solver.Add(x8 + x8 + x0 + x9 == 6); - solver.Add(x7 + x6 + x6 + x2 == 2); - solver.Add(x9 + x3 + x1 + x2 == 1); - solver.Add(x8 + x1 + x9 + x3 == 3); - solver.Add(x8 + x0 + x9 + x6 == 5); - solver.Add(x7 + x7 + x5 + x6 == 1); - solver.Add(x6 + x8 + x5 + x5 == 3); - solver.Add(x9 + x8 + x8 + x1 == 5); + for (int i = 0; i < problem2.GetLength(0); i++) + { + solver.Add((from j in Enumerable.Range(0, 4) select all[problem2[i, j]]).ToArray().Sum() == + problem2[i, 4]); + } - // The unknown - solver.Add(x2 + x5 + x8 + x1 == x); + solver.Add(all[2] + all[5] + all[8] + all[1] == x); + } - } else { - // Another representation of Problem 2 - int[,] problem2 = { { 8, 8, 0, 9, 6 }, { 7, 6, 6, 2, 2 }, { 9, 3, 1, 2, 1 }, - { 8, 1, 9, 3, 3 }, { 8, 0, 9, 6, 5 }, { 7, 7, 5, 6, 1 }, - { 6, 8, 5, 5, 3 }, { 9, 8, 8, 1, 5 } }; + // + // Search + // + DecisionBuilder db = solver.MakePhase(all, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); - for (int i = 0; i < problem2.GetLength(0); i++) { - solver.Add((from j in Enumerable.Range(0, 4) select all[problem2[i, j]]).ToArray().Sum() == - problem2[i, 4]); - } + solver.NewSearch(db); + while (solver.NextSolution()) + { + Console.Write("x: {0} x0..x9: ", x.Value()); + for (int i = 0; i < n; i++) + { + Console.Write(all[i].Value() + " "); + } + Console.WriteLine(); + } - solver.Add(all[2] + all[5] + all[8] + all[1] == x); + 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(); } - // - // Search - // - DecisionBuilder db = solver.MakePhase(all, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); - - solver.NewSearch(db); - while (solver.NextSolution()) { - Console.Write("x: {0} x0..x9: ", x.Value()); - for (int i = 0; i < n; i++) { - Console.Write(all[i].Value() + " "); - } - Console.WriteLine(); + public static void Main(String[] args) + { + for (int p = 1; p <= 4; p++) + { + Solve(p); + } } - - 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 Main(String[] args) { - for (int p = 1; p <= 4; p++) { - Solve(p); - } - } } diff --git a/examples/contrib/a_round_of_golf.cs b/examples/contrib/a_round_of_golf.cs index 0b912547e9..13b5902e38 100644 --- a/examples/contrib/a_round_of_golf.cs +++ b/examples/contrib/a_round_of_golf.cs @@ -20,149 +20,154 @@ using System.Linq; using System.Text.RegularExpressions; using Google.OrTools.ConstraintSolver; -public class ARoundOfGolf { - /** - * - * 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"); +public class ARoundOfGolf +{ + /** + * + * 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; + // number of speakers + int n = 4; - int Jack = 0; - int Bill = 1; - int Paul = 2; - int Frank = 3; + 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]; + // + // 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[] 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"); + 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]; + // 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(); } - // - // 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); + public static void Main(String[] args) + { + Solve(); } - - // - // 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(); - } - - public static void Main(String[] args) { - Solve(); - } } diff --git a/examples/contrib/all_interval.cs b/examples/contrib/all_interval.cs index 31d3f10bbd..9e8ca074d1 100644 --- a/examples/contrib/all_interval.cs +++ b/examples/contrib/all_interval.cs @@ -19,70 +19,78 @@ using System.IO; using System.Text.RegularExpressions; using Google.OrTools.ConstraintSolver; -public class AllInterval { - /** - * - * 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"); +public class AllInterval +{ + /** + * + * 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"); + // + // 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()); + // + // 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())); + 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(); } - // symmetry breaking - solver.Add(x[0] < x[n - 1]); - solver.Add(diffs[0] < diffs[1]); + public static void Main(String[] args) + { + int n = 12; + if (args.Length > 0) + { + n = Convert.ToInt32(args[0]); + } - // - // 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(); + Solve(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 static void Main(String[] args) { - int n = 12; - if (args.Length > 0) { - n = Convert.ToInt32(args[0]); - } - - Solve(n); - } } diff --git a/examples/contrib/alldifferent_except_0.cs b/examples/contrib/alldifferent_except_0.cs index c35c681d02..6977d17a8b 100644 --- a/examples/contrib/alldifferent_except_0.cs +++ b/examples/contrib/alldifferent_except_0.cs @@ -16,77 +16,86 @@ using System; using Google.OrTools.ConstraintSolver; -public class AllDifferentExcept0Test { - // - // 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])); - } - } - } - - /** - * - * Decomposition of alldifferent_except_0 - * - * See http://www.hakank.org/google_or_tools/map.py - * - * - */ - private static void Solve() { - Solver solver = new Solver("AllDifferentExcept0"); - +public class AllDifferentExcept0Test +{ // - // data + // Decomposition of alldifferent_except_0 // - 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(); + 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])); + } + } } - 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()); + /** + * + * Decomposition of alldifferent_except_0 + * + * See http://www.hakank.org/google_or_tools/map.py + * + * + */ + private static void Solve() + { + Solver solver = new Solver("AllDifferentExcept0"); - solver.EndSearch(); - } + // + // data + // + int n = 6; - public static void Main(String[] args) { - Solve(); - } + // + // 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(); + } + + public static void Main(String[] args) + { + Solve(); + } } diff --git a/examples/contrib/assignment.cs b/examples/contrib/assignment.cs index 56b2b9b4f5..59d4776388 100644 --- a/examples/contrib/assignment.cs +++ b/examples/contrib/assignment.cs @@ -20,104 +20,113 @@ using System.Linq; using System.Text.RegularExpressions; using Google.OrTools.ConstraintSolver; -public class Assignment { - /** - * - * Assignment problem - * - * From Wayne Winston "Operations Research", - * Assignment Problems, page 393f - * (generalized version with added test column) - * - * See See http://www.hakank.org/or-tools/assignment.py - * - */ - private static void Solve() { - Solver solver = new Solver("Assignment"); +public class Assignment +{ + /** + * + * Assignment problem + * + * From Wayne Winston "Operations Research", + * Assignment Problems, page 393f + * (generalized version with added test column) + * + * See See http://www.hakank.org/or-tools/assignment.py + * + */ + private static void Solve() + { + Solver solver = new Solver("Assignment"); - // - // data - // + // + // data + // - // Problem instance - // hakank: I added the fifth column to make it more - // interesting - int rows = 4; - int cols = 5; - int[,] cost = { - { 14, 5, 8, 7, 15 }, { 2, 12, 6, 5, 3 }, { 7, 8, 3, 9, 7 }, { 2, 4, 6, 10, 1 } - }; + // Problem instance + // hakank: I added the fifth column to make it more + // interesting + int rows = 4; + int cols = 5; + int[,] cost = { { 14, 5, 8, 7, 15 }, { 2, 12, 6, 5, 3 }, { 7, 8, 3, 9, 7 }, { 2, 4, 6, 10, 1 } }; - // - // Decision variables - // - IntVar[,] x = solver.MakeBoolVarMatrix(rows, cols, "x"); - IntVar[] x_flat = x.Flatten(); + // + // Decision variables + // + IntVar[,] x = solver.MakeBoolVarMatrix(rows, cols, "x"); + IntVar[] x_flat = x.Flatten(); - // - // Constraints - // + // + // Constraints + // - // Exacly one assignment per row (task), - // i.e. all rows must be assigned with one worker - for (int i = 0; i < rows; i++) { - solver.Add((from j in Enumerable.Range(0, cols) select x[i, j]).ToArray().Sum() == 1); - } - - // At most one assignments per column (worker) - for (int j = 0; j < cols; j++) { - solver.Add((from i in Enumerable.Range(0, rows) select x[i, j]).ToArray().Sum() <= 1); - } - - // Total cost - IntVar total_cost = (from i in Enumerable.Range(0, rows) from j in Enumerable.Range(0, cols) - select(cost[i, j] * x[i, j])) - .ToArray() - .Sum() - .Var(); - - // - // objective - // - OptimizeVar objective = total_cost.Minimize(1); - - // - // Search - // - DecisionBuilder db = solver.MakePhase(x_flat, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); - - solver.NewSearch(db, objective); - - while (solver.NextSolution()) { - Console.WriteLine("total_cost: {0}", total_cost.Value()); - for (int i = 0; i < rows; i++) { - for (int j = 0; j < cols; j++) { - Console.Write(x[i, j].Value() + " "); + // Exacly one assignment per row (task), + // i.e. all rows must be assigned with one worker + for (int i = 0; i < rows; i++) + { + solver.Add((from j in Enumerable.Range(0, cols) select x[i, j]).ToArray().Sum() == 1); } - Console.WriteLine(); - } - Console.WriteLine(); - Console.WriteLine("Assignments:"); - for (int i = 0; i < rows; i++) { - Console.Write("Task " + i); - for (int j = 0; j < cols; j++) { - if (x[i, j].Value() == 1) { - Console.WriteLine(" is done by " + j); - } + + // At most one assignments per column (worker) + for (int j = 0; j < cols; j++) + { + solver.Add((from i in Enumerable.Range(0, rows) select x[i, j]).ToArray().Sum() <= 1); } - } - Console.WriteLine(); + + // Total cost + IntVar total_cost = + (from i in Enumerable.Range(0, rows) from j in Enumerable.Range(0, cols) select(cost[i, j] * x[i, j])) + .ToArray() + .Sum() + .Var(); + + // + // objective + // + OptimizeVar objective = total_cost.Minimize(1); + + // + // Search + // + DecisionBuilder db = solver.MakePhase(x_flat, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); + + solver.NewSearch(db, objective); + + while (solver.NextSolution()) + { + Console.WriteLine("total_cost: {0}", total_cost.Value()); + for (int i = 0; i < rows; i++) + { + for (int j = 0; j < cols; j++) + { + Console.Write(x[i, j].Value() + " "); + } + Console.WriteLine(); + } + Console.WriteLine(); + Console.WriteLine("Assignments:"); + for (int i = 0; i < rows; i++) + { + Console.Write("Task " + i); + for (int j = 0; j < cols; j++) + { + if (x[i, j].Value() == 1) + { + Console.WriteLine(" is done by " + j); + } + } + } + Console.WriteLine(); + } + + Console.WriteLine("\nSolutions: {0}", solver.Solutions()); + Console.WriteLine("WallTime: {0}ms", solver.WallTime()); + Console.WriteLine("Failures: {0}", solver.Failures()); + Console.WriteLine("Branches: {0} ", solver.Branches()); + + solver.EndSearch(); } - Console.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 Main(String[] args) { - Solve(); - } + public static void Main(String[] args) + { + Solve(); + } } diff --git a/examples/contrib/broken_weights.cs b/examples/contrib/broken_weights.cs index 0a0a90e473..e2fd4f0140 100644 --- a/examples/contrib/broken_weights.cs +++ b/examples/contrib/broken_weights.cs @@ -17,136 +17,149 @@ using System; using System.Linq; using Google.OrTools.ConstraintSolver; -public class BrokenWeights { - /** - * - * Broken weights problem. - * - * From http://www.mathlesstraveled.com/?p=701 - * """ - * Here's a fantastic problem I recently heard. Apparently it was first - * posed by Claude Gaspard Bachet de Meziriac in a book of arithmetic problems - * published in 1612, and can also be found in Heinrich Dorrie's 100 - * Great Problems of Elementary Mathematics. - * - * A merchant had a forty pound measuring weight that broke - * into four pieces as the result of a fall. When the pieces were - * subsequently weighed, it was found that the weight of each piece - * was a whole number of pounds and that the four pieces could be - * used to weigh every integral weight between 1 and 40 pounds. What - * were the weights of the pieces? - * - * Note that since this was a 17th-century merchant, he of course used a - * balance scale to weigh things. So, for example, he could use a 1-pound - * weight and a 4-pound weight to weigh a 3-pound object, by placing the - * 3-pound object and 1-pound weight on one side of the scale, and - * the 4-pound weight on the other side. - * """ - * - * Also see http://www.hakank.org/or-tools/broken_weights.py - * - */ - private static void Solve(int m = 40, int n = 4) { - Solver solver = new Solver("BrokenWeights"); +public class BrokenWeights +{ + /** + * + * Broken weights problem. + * + * From http://www.mathlesstraveled.com/?p=701 + * """ + * Here's a fantastic problem I recently heard. Apparently it was first + * posed by Claude Gaspard Bachet de Meziriac in a book of arithmetic problems + * published in 1612, and can also be found in Heinrich Dorrie's 100 + * Great Problems of Elementary Mathematics. + * + * A merchant had a forty pound measuring weight that broke + * into four pieces as the result of a fall. When the pieces were + * subsequently weighed, it was found that the weight of each piece + * was a whole number of pounds and that the four pieces could be + * used to weigh every integral weight between 1 and 40 pounds. What + * were the weights of the pieces? + * + * Note that since this was a 17th-century merchant, he of course used a + * balance scale to weigh things. So, for example, he could use a 1-pound + * weight and a 4-pound weight to weigh a 3-pound object, by placing the + * 3-pound object and 1-pound weight on one side of the scale, and + * the 4-pound weight on the other side. + * """ + * + * Also see http://www.hakank.org/or-tools/broken_weights.py + * + */ + private static void Solve(int m = 40, int n = 4) + { + Solver solver = new Solver("BrokenWeights"); - Console.WriteLine("Total weight (m): {0}", m); - Console.WriteLine("Number of pieces (n): {0}", n); - Console.WriteLine(); - - // - // Decision variables - // - - IntVar[] weights = solver.MakeIntVarArray(n, 1, m, "weights"); - IntVar[,] x = new IntVar[m, n]; - // Note: in x_flat we insert the weights array before x - IntVar[] x_flat = new IntVar[m * n + n]; - for (int j = 0; j < n; j++) { - x_flat[j] = weights[j]; - } - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { - x[i, j] = solver.MakeIntVar(-1, 1, "x[" + i + "," + j + "]"); - x_flat[n + i * n + j] = x[i, j]; - } - } - - // - // Constraints - // - - // symmetry breaking - for (int j = 1; j < n; j++) { - solver.Add(weights[j - 1] < weights[j]); - } - - solver.Add(weights.Sum() == m); - - // Check that all weights from 1 to n (default 40) can be made. - // - // Since all weights can be on either side - // of the side of the scale we allow either - // -1, 0, or 1 of the weights, assuming that - // -1 is the weights on the left and 1 is on the right. - // - for (int i = 0; i < m; i++) { - solver.Add((from j in Enumerable.Range(0, n) select weights[j] * x[i, j]).ToArray().Sum() == - i + 1); - } - - // - // The objective is to minimize the last weight. - // - OptimizeVar obj = weights[n - 1].Minimize(1); - - // - // Search - // - DecisionBuilder db = - solver.MakePhase(x_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); - - solver.NewSearch(db, obj); - - while (solver.NextSolution()) { - Console.Write("weights: "); - for (int i = 0; i < n; i++) { - Console.Write("{0,3} ", weights[i].Value()); - } - Console.WriteLine(); - for (int i = 0; i < 10 + n * 4; i++) { - Console.Write("-"); - } - Console.WriteLine(); - for (int i = 0; i < m; i++) { - Console.Write("weight {0,2}:", i + 1); - for (int j = 0; j < n; j++) { - Console.Write("{0,3} ", x[i, j].Value()); - } + Console.WriteLine("Total weight (m): {0}", m); + Console.WriteLine("Number of pieces (n): {0}", n); Console.WriteLine(); - } - Console.WriteLine(); + + // + // Decision variables + // + + IntVar[] weights = solver.MakeIntVarArray(n, 1, m, "weights"); + IntVar[,] x = new IntVar[m, n]; + // Note: in x_flat we insert the weights array before x + IntVar[] x_flat = new IntVar[m * n + n]; + for (int j = 0; j < n; j++) + { + x_flat[j] = weights[j]; + } + for (int i = 0; i < m; i++) + { + for (int j = 0; j < n; j++) + { + x[i, j] = solver.MakeIntVar(-1, 1, "x[" + i + "," + j + "]"); + x_flat[n + i * n + j] = x[i, j]; + } + } + + // + // Constraints + // + + // symmetry breaking + for (int j = 1; j < n; j++) + { + solver.Add(weights[j - 1] < weights[j]); + } + + solver.Add(weights.Sum() == m); + + // Check that all weights from 1 to n (default 40) can be made. + // + // Since all weights can be on either side + // of the side of the scale we allow either + // -1, 0, or 1 of the weights, assuming that + // -1 is the weights on the left and 1 is on the right. + // + for (int i = 0; i < m; i++) + { + solver.Add((from j in Enumerable.Range(0, n) select weights[j] * x[i, j]).ToArray().Sum() == i + 1); + } + + // + // The objective is to minimize the last weight. + // + OptimizeVar obj = weights[n - 1].Minimize(1); + + // + // Search + // + DecisionBuilder db = solver.MakePhase(x_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); + + solver.NewSearch(db, obj); + + while (solver.NextSolution()) + { + Console.Write("weights: "); + for (int i = 0; i < n; i++) + { + Console.Write("{0,3} ", weights[i].Value()); + } + Console.WriteLine(); + for (int i = 0; i < 10 + n * 4; i++) + { + Console.Write("-"); + } + Console.WriteLine(); + for (int i = 0; i < m; i++) + { + Console.Write("weight {0,2}:", i + 1); + for (int j = 0; j < n; j++) + { + Console.Write("{0,3} ", x[i, j].Value()); + } + Console.WriteLine(); + } + Console.WriteLine(); + } + + Console.WriteLine("\nSolutions: {0}", solver.Solutions()); + Console.WriteLine("WallTime: {0}ms", solver.WallTime()); + Console.WriteLine("Failures: {0}", solver.Failures()); + Console.WriteLine("Branches: {0} ", solver.Branches()); + + solver.EndSearch(); } - 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()); + public static void Main(String[] args) + { + int m = 40; + int n = 4; - solver.EndSearch(); - } + if (args.Length > 0) + { + m = Convert.ToInt32(args[0]); + } - public static void Main(String[] args) { - int m = 40; - int n = 4; + if (args.Length > 1) + { + n = Convert.ToInt32(args[1]); + } - if (args.Length > 0) { - m = Convert.ToInt32(args[0]); + Solve(m, n); } - - if (args.Length > 1) { - n = Convert.ToInt32(args[1]); - } - - Solve(m, n); - } } diff --git a/examples/contrib/bus_schedule.cs b/examples/contrib/bus_schedule.cs index 0d2e77af1c..40323c221a 100644 --- a/examples/contrib/bus_schedule.cs +++ b/examples/contrib/bus_schedule.cs @@ -20,95 +20,104 @@ using System.Linq; using System.Text.RegularExpressions; using Google.OrTools.ConstraintSolver; -public class BusSchedule { - /** - * - * Bus scheduling. - * - * Minimize number of buses in timeslots. - * - * Problem from Taha "Introduction to Operations Research", page 58. - * - * This is a slightly more general model than Taha's. - * - * Also see, http://www.hakank.org/or-tools/bus_schedule.py - * - */ - private static long Solve(long num_buses_check = 0) { - Solver solver = new Solver("BusSchedule"); +public class BusSchedule +{ + /** + * + * Bus scheduling. + * + * Minimize number of buses in timeslots. + * + * Problem from Taha "Introduction to Operations Research", page 58. + * + * This is a slightly more general model than Taha's. + * + * Also see, http://www.hakank.org/or-tools/bus_schedule.py + * + */ + private static long Solve(long num_buses_check = 0) + { + Solver solver = new Solver("BusSchedule"); - // - // data - // - int time_slots = 6; - int[] demands = { 8, 10, 7, 12, 4, 4 }; - int max_num = demands.Sum(); + // + // data + // + int time_slots = 6; + int[] demands = { 8, 10, 7, 12, 4, 4 }; + int max_num = demands.Sum(); - // - // Decision variables - // + // + // Decision variables + // - // How many buses start the schedule at time slot t - IntVar[] x = solver.MakeIntVarArray(time_slots, 0, max_num, "x"); - // Total number of buses - IntVar num_buses = x.Sum().VarWithName("num_buses"); + // How many buses start the schedule at time slot t + IntVar[] x = solver.MakeIntVarArray(time_slots, 0, max_num, "x"); + // Total number of buses + IntVar num_buses = x.Sum().VarWithName("num_buses"); - // - // Constraints - // + // + // Constraints + // - // Meet the demands for this and the next time slot. - for (int i = 0; i < time_slots - 1; i++) { - solver.Add(x[i] + x[i + 1] >= demands[i]); + // Meet the demands for this and the next time slot. + for (int i = 0; i < time_slots - 1; i++) + { + solver.Add(x[i] + x[i + 1] >= demands[i]); + } + + // The demand "around the clock" + solver.Add(x[time_slots - 1] + x[0] - demands[time_slots - 1] == 0); + + // For showing all solutions of minimal number of buses + if (num_buses_check > 0) + { + solver.Add(num_buses == num_buses_check); + } + + // + // Search + // + DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); + + if (num_buses_check == 0) + { + // Minimize num_buses + OptimizeVar obj = num_buses.Minimize(1); + solver.NewSearch(db, obj); + } + else + { + solver.NewSearch(db); + } + + long result = 0; + while (solver.NextSolution()) + { + result = num_buses.Value(); + Console.Write("x: "); + for (int i = 0; i < time_slots; i++) + { + Console.Write("{0,2} ", x[i].Value()); + } + Console.WriteLine("num_buses: " + num_buses.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(); + + return result; } - // The demand "around the clock" - solver.Add(x[time_slots - 1] + x[0] - demands[time_slots - 1] == 0); - - // For showing all solutions of minimal number of buses - if (num_buses_check > 0) { - solver.Add(num_buses == num_buses_check); + public static void Main(String[] args) + { + Console.WriteLine("Check for minimum number of buses: "); + long num_buses = Solve(); + Console.WriteLine("\n... got {0} as minimal value.", num_buses); + Console.WriteLine("\nAll solutions: ", num_buses); + num_buses = Solve(num_buses); } - - // - // Search - // - DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); - - if (num_buses_check == 0) { - // Minimize num_buses - OptimizeVar obj = num_buses.Minimize(1); - solver.NewSearch(db, obj); - - } else { - solver.NewSearch(db); - } - - long result = 0; - while (solver.NextSolution()) { - result = num_buses.Value(); - Console.Write("x: "); - for (int i = 0; i < time_slots; i++) { - Console.Write("{0,2} ", x[i].Value()); - } - Console.WriteLine("num_buses: " + num_buses.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(); - - return result; - } - - public static void Main(String[] args) { - Console.WriteLine("Check for minimum number of buses: "); - long num_buses = Solve(); - Console.WriteLine("\n... got {0} as minimal value.", num_buses); - Console.WriteLine("\nAll solutions: ", num_buses); - num_buses = Solve(num_buses); - } } diff --git a/examples/contrib/circuit.cs b/examples/contrib/circuit.cs index 51990ae77b..d611b0e018 100644 --- a/examples/contrib/circuit.cs +++ b/examples/contrib/circuit.cs @@ -19,85 +19,94 @@ using System.IO; using System.Text.RegularExpressions; using Google.OrTools.ConstraintSolver; -public class CircuitTest { - /** - * circuit(solver, x) - * - * A decomposition of the global constraint circuit, based - * on some observation of the orbits in an array. - * - * 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) { - int n = x.Length; - IntVar[] z = solver.MakeIntVarArray(n, 0, n - 1, "z"); +public class CircuitTest +{ + /** + * circuit(solver, x) + * + * A decomposition of the global constraint circuit, based + * on some observation of the orbits in an array. + * + * 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) + { + int n = x.Length; + IntVar[] z = solver.MakeIntVarArray(n, 0, n - 1, "z"); - solver.Add(x.AllDifferent()); - solver.Add(z.AllDifferent()); + 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])); + // 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); } - // z may not be 0 for i < n-1 - for (int i = 1; i < n - 1; i++) { - solver.Add(z[i] != 0); + /** + * + * Implements a (decomposition) of the global constraint circuit. + * See http://www.hakank.org/google_or_tools/circuit.py + * + */ + private static void Solve(int n = 5) + { + Solver solver = new Solver("Circuit"); + + // + // Decision variables + // + IntVar[] x = solver.MakeIntVarArray(n, 0, n - 1, "x"); + + // + // Constraints + // + circuit(solver, x); + + // + // Search + // + DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); + + solver.NewSearch(db); + + while (solver.NextSolution()) + { + for (int i = 0; i < n; i++) + { + Console.Write("{0} ", x[i].Value()); + } + Console.WriteLine(); + } + + Console.WriteLine("\nSolutions: {0}", solver.Solutions()); + Console.WriteLine("WallTime: {0}ms", solver.WallTime()); + Console.WriteLine("Failures: {0}", solver.Failures()); + Console.WriteLine("Branches: {0} ", solver.Branches()); + + solver.EndSearch(); } - // when i = n-1 it must be 0 - solver.Add(z[n - 1] == 0); - } + public static void Main(String[] args) + { + int n = 5; + if (args.Length > 0) + { + n = Convert.ToInt32(args[0]); + } - /** - * - * Implements a (decomposition) of the global constraint circuit. - * See http://www.hakank.org/google_or_tools/circuit.py - * - */ - private static void Solve(int n = 5) { - Solver solver = new Solver("Circuit"); - - // - // Decision variables - // - IntVar[] x = solver.MakeIntVarArray(n, 0, n - 1, "x"); - - // - // Constraints - // - circuit(solver, x); - - // - // Search - // - DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); - - solver.NewSearch(db); - - while (solver.NextSolution()) { - for (int i = 0; i < n; i++) { - Console.Write("{0} ", x[i].Value()); - } - Console.WriteLine(); + Solve(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 static void Main(String[] args) { - int n = 5; - if (args.Length > 0) { - n = Convert.ToInt32(args[0]); - } - - Solve(n); - } } diff --git a/examples/contrib/circuit2.cs b/examples/contrib/circuit2.cs index e0a6ef68f5..a3485326b4 100644 --- a/examples/contrib/circuit2.cs +++ b/examples/contrib/circuit2.cs @@ -19,95 +19,105 @@ using System.IO; using System.Text.RegularExpressions; using Google.OrTools.ConstraintSolver; -public class CircuitTest2 { - /** - * 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; +public class CircuitTest2 +{ + /** + * 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()); + 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])); + // 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); } - // z may not be 0 for i < n-1 - for (int i = 1; i < n - 1; i++) { - solver.Add(z[i] != 0); + /** + * + * Implements a (decomposition) of the global constraint circuit + * and extracting the path. + * + * One circuit for n = 5 is 3 0 4 2 1 + * Thus the extracted path is 0 -> 3 -> 2 -> 4 -> 1 -> 0 + * + */ + private static void Solve(int n = 5) + { + Solver solver = new Solver("CircuitTest2"); + + // + // Decision variables + // + IntVar[] x = solver.MakeIntVarArray(n, 0, n - 1, "x"); + IntVar[] path = solver.MakeIntVarArray(n, 0, n - 1, "path"); + + // + // Constraints + // + circuit(solver, x, path); + + // + // Search + // + DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); + + solver.NewSearch(db); + + while (solver.NextSolution()) + { + Console.Write("x : "); + for (int i = 0; i < n; i++) + { + Console.Write("{0} ", x[i].Value()); + } + Console.Write("\npath: "); + for (int i = 0; i < n; i++) + { + Console.Write("{0} ", path[i].Value()); + } + Console.WriteLine("\n"); + } + + Console.WriteLine("\nSolutions: {0}", solver.Solutions()); + Console.WriteLine("WallTime: {0}ms", solver.WallTime()); + Console.WriteLine("Failures: {0}", solver.Failures()); + Console.WriteLine("Branches: {0} ", solver.Branches()); + + solver.EndSearch(); } - // when i = n-1 it must be 0 - solver.Add(z[n - 1] == 0); - } + public static void Main(String[] args) + { + int n = 5; + if (args.Length > 0) + { + n = Convert.ToInt32(args[0]); + } - /** - * - * Implements a (decomposition) of the global constraint circuit - * and extracting the path. - * - * One circuit for n = 5 is 3 0 4 2 1 - * Thus the extracted path is 0 -> 3 -> 2 -> 4 -> 1 -> 0 - * - */ - private static void Solve(int n = 5) { - Solver solver = new Solver("CircuitTest2"); - - // - // Decision variables - // - IntVar[] x = solver.MakeIntVarArray(n, 0, n - 1, "x"); - IntVar[] path = solver.MakeIntVarArray(n, 0, n - 1, "path"); - - // - // Constraints - // - circuit(solver, x, path); - - // - // Search - // - DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); - - solver.NewSearch(db); - - while (solver.NextSolution()) { - Console.Write("x : "); - for (int i = 0; i < n; i++) { - Console.Write("{0} ", x[i].Value()); - } - Console.Write("\npath: "); - for (int i = 0; i < n; i++) { - Console.Write("{0} ", path[i].Value()); - } - Console.WriteLine("\n"); + Solve(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 static void Main(String[] args) { - int n = 5; - if (args.Length > 0) { - n = Convert.ToInt32(args[0]); - } - - Solve(n); - } } diff --git a/examples/contrib/coins3.cs b/examples/contrib/coins3.cs index 896bad38fa..892a883719 100644 --- a/examples/contrib/coins3.cs +++ b/examples/contrib/coins3.cs @@ -19,86 +19,92 @@ using System.Collections.Generic; using System.Linq; using Google.OrTools.ConstraintSolver; -public class Coins3 { - /** - * - * 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 - * """ +public class Coins3 +{ + /** + * + * 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"); + * 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 }; + // + // Data + // + int n = 6; // number of different coins + int[] variables = { 1, 2, 5, 10, 25, 50 }; - IEnumerable RANGE = Enumerable.Range(0, n); + IEnumerable RANGE = Enumerable.Range(0, n); - // - // Decision variables - // - IntVar[] x = solver.MakeIntVarArray(n, 0, 99, "x"); - IntVar num_coins = x.Sum().VarWithName("num_coins"); + // + // Decision variables + // + IntVar[] x = solver.MakeIntVarArray(n, 0, 99, "x"); + IntVar num_coins = x.Sum().VarWithName("num_coins"); - // - // Constraints - // + // + // 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); + // 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]); - } + 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(); } - // - // 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(); + public static void Main(String[] args) + { + Solve(); } - - 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 Main(String[] args) { - Solve(); - } } diff --git a/examples/contrib/coins_grid.cs b/examples/contrib/coins_grid.cs index e0e385f7a7..65b3e3cded 100644 --- a/examples/contrib/coins_grid.cs +++ b/examples/contrib/coins_grid.cs @@ -16,91 +16,102 @@ using System; using Google.OrTools.ConstraintSolver; -public class CoinsGrid { - /** - * - * Solves the Coins Grid problm. - * See http://www.hakank.org/google_or_tools/coins_grid.py - * - */ - private static void Solve(int n = 31, int c = 14) { - Solver solver = new Solver("CoinsGrid"); +public class CoinsGrid +{ + /** + * + * Solves the Coins Grid problm. + * See http://www.hakank.org/google_or_tools/coins_grid.py + * + */ + private static void Solve(int n = 31, int c = 14) + { + Solver solver = new Solver("CoinsGrid"); - // - // Decision variables - // - IntVar[,] x = solver.MakeIntVarMatrix(n, n, 0, 1, "x"); - IntVar[] x_flat = x.Flatten(); + // + // Decision variables + // + IntVar[,] x = solver.MakeIntVarMatrix(n, n, 0, 1, "x"); + IntVar[] x_flat = x.Flatten(); - // - // Constraints - // + // + // Constraints + // - // sum row/columns == c - for (int i = 0; i < n; i++) { - IntVar[] row = new IntVar[n]; - IntVar[] col = new IntVar[n]; - for (int j = 0; j < n; j++) { - row[j] = x[i, j]; - col[j] = x[j, i]; - } - solver.Add(row.Sum() == c); - solver.Add(col.Sum() == c); - } - - // quadratic horizonal distance - IntVar[] obj_tmp = new IntVar[n * n]; - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - obj_tmp[i * n + j] = (x[i, j] * (i - j) * (i - j)).Var(); - } - } - IntVar obj_var = obj_tmp.Sum().Var(); - - // - // Objective - // - OptimizeVar obj = obj_var.Minimize(1); - - // - // Search - // - DecisionBuilder db = - solver.MakePhase(x_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MAX_VALUE); - - solver.NewSearch(db, obj); - - while (solver.NextSolution()) { - Console.WriteLine("obj: " + obj_var.Value()); - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - Console.Write(x[i, j].Value() + " "); + // sum row/columns == c + for (int i = 0; i < n; i++) + { + IntVar[] row = new IntVar[n]; + IntVar[] col = new IntVar[n]; + for (int j = 0; j < n; j++) + { + row[j] = x[i, j]; + col[j] = x[j, i]; + } + solver.Add(row.Sum() == c); + solver.Add(col.Sum() == c); } - Console.WriteLine(); - } - Console.WriteLine(); + + // quadratic horizonal distance + IntVar[] obj_tmp = new IntVar[n * n]; + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + obj_tmp[i * n + j] = (x[i, j] * (i - j) * (i - j)).Var(); + } + } + IntVar obj_var = obj_tmp.Sum().Var(); + + // + // Objective + // + OptimizeVar obj = obj_var.Minimize(1); + + // + // Search + // + DecisionBuilder db = solver.MakePhase(x_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MAX_VALUE); + + solver.NewSearch(db, obj); + + while (solver.NextSolution()) + { + Console.WriteLine("obj: " + obj_var.Value()); + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + Console.Write(x[i, j].Value() + " "); + } + Console.WriteLine(); + } + Console.WriteLine(); + } + + Console.WriteLine("\nSolutions: {0}", solver.Solutions()); + Console.WriteLine("WallTime: {0}ms", solver.WallTime()); + Console.WriteLine("Failures: {0}", solver.Failures()); + Console.WriteLine("Branches: {0} ", solver.Branches()); + + solver.EndSearch(); } - 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()); + public static void Main(String[] args) + { + int n = 31; + int c = 14; - solver.EndSearch(); - } + if (args.Length > 0) + { + n = Convert.ToInt32(args[0]); + } - public static void Main(String[] args) { - int n = 31; - int c = 14; + if (args.Length > 1) + { + c = Convert.ToInt32(args[1]); + } - if (args.Length > 0) { - n = Convert.ToInt32(args[0]); + Solve(n, c); } - - if (args.Length > 1) { - c = Convert.ToInt32(args[1]); - } - - Solve(n, c); - } } diff --git a/examples/contrib/combinatorial_auction2.cs b/examples/contrib/combinatorial_auction2.cs index f68d4e6d57..c7c60f3a34 100644 --- a/examples/contrib/combinatorial_auction2.cs +++ b/examples/contrib/combinatorial_auction2.cs @@ -19,89 +19,95 @@ using System.Collections; using System.Collections.Generic; using Google.OrTools.ConstraintSolver; -public class CombinatorialAuction2 { - /** - * - * Combinatorial auction. - * - * This is a more general model for the combinatorial example - * in the Numberjack Tutorial, pages 9 and 24 (slides 19/175 and - * 51/175). - * - * See http://www.hakank.org/or-tools/combinatorial_auction2.py - * - * The original and more talkative model is here: - * http://www.hakank.org/numberjack/combinatorial_auction.py - * - */ - private static void Solve() { - Solver solver = new Solver("CombinatorialAuction2"); +public class CombinatorialAuction2 +{ + /** + * + * Combinatorial auction. + * + * This is a more general model for the combinatorial example + * in the Numberjack Tutorial, pages 9 and 24 (slides 19/175 and + * 51/175). + * + * See http://www.hakank.org/or-tools/combinatorial_auction2.py + * + * The original and more talkative model is here: + * http://www.hakank.org/numberjack/combinatorial_auction.py + * + */ + private static void Solve() + { + Solver solver = new Solver("CombinatorialAuction2"); - // - // Data - // - int n = 5; + // + // Data + // + int n = 5; - // the items for each bid - int[][] items = { - new int[] { 0, 1 }, // A,B - new int[] { 0, 2 }, // A, C - new int[] { 1, 3 }, // B,D - new int[] { 1, 2, 3 }, // B,C,D - new int[] { 0 } // A - }; + // the items for each bid + int[][] items = { + new int[] { 0, 1 }, // A,B + new int[] { 0, 2 }, // A, C + new int[] { 1, 3 }, // B,D + new int[] { 1, 2, 3 }, // B,C,D + new int[] { 0 } // A + }; - int[] bid_ids = { 0, 1, 2, 3 }; - int[] bid_amount = { 10, 20, 30, 40, 14 }; + int[] bid_ids = { 0, 1, 2, 3 }; + int[] bid_amount = { 10, 20, 30, 40, 14 }; - // - // Decision variables - // - IntVar[] x = solver.MakeIntVarArray(n, 0, 1, "x"); - IntVar z = x.ScalProd(bid_amount).VarWithName("z"); + // + // Decision variables + // + IntVar[] x = solver.MakeIntVarArray(n, 0, 1, "x"); + IntVar z = x.ScalProd(bid_amount).VarWithName("z"); - // - // Constraints - // + // + // Constraints + // - foreach (int bid_id in bid_ids) { + foreach (int bid_id in bid_ids) + { var tmp2 = (from item in Enumerable.Range(0, n) from i in Enumerable.Range(0, items[item].Length) where items [item] [i] == bid_id select x[item]); solver.Add(tmp2.ToArray().Sum() <= 1); + } + + // + // Objective + // + OptimizeVar obj = z.Maximize(1); + + // + // Search + // + DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); + + solver.NewSearch(db, obj); + + while (solver.NextSolution()) + { + Console.Write("z: {0,2} x: ", z.Value()); + 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(); } - // - // Objective - // - OptimizeVar obj = z.Maximize(1); - - // - // Search - // - DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); - - solver.NewSearch(db, obj); - - while (solver.NextSolution()) { - Console.Write("z: {0,2} x: ", z.Value()); - for (int i = 0; i < n; i++) { - Console.Write(x[i].Value() + " "); - } - Console.WriteLine(); + public static void Main(String[] args) + { + Solve(); } - - 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 Main(String[] args) { - Solve(); - } } diff --git a/examples/contrib/contiguity_regular.cs b/examples/contrib/contiguity_regular.cs index ad825ee77d..2bb00e24ef 100644 --- a/examples/contrib/contiguity_regular.cs +++ b/examples/contrib/contiguity_regular.cs @@ -19,162 +19,173 @@ using System.Linq; using System.Diagnostics; using Google.OrTools.ConstraintSolver; -public class ContiguityRegular { - /* - * 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"); +public class ContiguityRegular +{ + /* + * 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 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)))); } - } - 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(); + static void MyContiguity(Solver solver, IntVar[] x) + { + // the DFA (for regular) + int n_states = 3; + int input_max = 2; + int initial_state = 1; // note: state 0 is used for the failing state + // in MyRegular - // 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; + // all states are accepting states + int[] accepting_states = { 1, 2, 3 }; - 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); + // The regular expression 0*1*0* + int[,] transition_fn = { + { 1, 2 }, // state 1 (start): input 0 -> state 1, input 1 -> state 2 i.e. 0* + { 3, 2 }, // state 2: 1* + { 3, 0 }, // state 3: 0* + }; - 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)))); - } - } - - static void MyContiguity(Solver solver, IntVar[] x) { - // the DFA (for regular) - int n_states = 3; - int input_max = 2; - int initial_state = 1; // note: state 0 is used for the failing state - // in MyRegular - - // all states are accepting states - int[] accepting_states = { 1, 2, 3 }; - - // The regular expression 0*1*0* - int[,] transition_fn = { - { 1, 2 }, // state 1 (start): input 0 -> state 1, input 1 -> state 2 i.e. 0* - { 3, 2 }, // state 2: 1* - { 3, 0 }, // state 3: 0* - }; - - MyRegular(solver, x, n_states, input_max, transition_fn, initial_state, accepting_states); - } - - /** - * - * Global constraint contiguity using regular - * - * This is a decomposition of the global constraint global contiguity. - * - * From Global Constraint Catalogue - * http://www.emn.fr/x-info/sdemasse/gccat/Cglobal_contiguity.html - * """ - * Enforce all variables of the VARIABLES collection to be assigned to 0 or 1. - * In addition, all variables assigned to value 1 appear contiguously. - * - * Example: - * (<0, 1, 1, 0>) - * - * The global_contiguity constraint holds since the sequence 0 1 1 0 contains - * no more than one group of contiguous 1. - * """ - * - * Also see http://www.hakank.org/or-tools/contiguity_regular.py - * - */ - private static void Solve() { - Solver solver = new Solver("ContiguityRegular"); - - // - // Data - // - int n = 7; // length of the array - - // - // Decision variables - // - - // Note: We use 1..2 (instead of 0..1) and subtract 1 in the solution - IntVar[] reg_input = solver.MakeIntVarArray(n, 1, 2, "reg_input"); - - // - // Constraints - // - MyContiguity(solver, reg_input); - - // - // Search - // - DecisionBuilder db = - solver.MakePhase(reg_input, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); - - solver.NewSearch(db); - - while (solver.NextSolution()) { - for (int i = 0; i < n; i++) { - // Note: here we subtract 1 to get 0..1 - Console.Write((reg_input[i].Value() - 1) + " "); - } - Console.WriteLine(); + MyRegular(solver, x, n_states, input_max, transition_fn, initial_state, accepting_states); } - 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()); + /** + * + * Global constraint contiguity using regular + * + * This is a decomposition of the global constraint global contiguity. + * + * From Global Constraint Catalogue + * http://www.emn.fr/x-info/sdemasse/gccat/Cglobal_contiguity.html + * """ + * Enforce all variables of the VARIABLES collection to be assigned to 0 or 1. + * In addition, all variables assigned to value 1 appear contiguously. + * + * Example: + * (<0, 1, 1, 0>) + * + * The global_contiguity constraint holds since the sequence 0 1 1 0 contains + * no more than one group of contiguous 1. + * """ + * + * Also see http://www.hakank.org/or-tools/contiguity_regular.py + * + */ + private static void Solve() + { + Solver solver = new Solver("ContiguityRegular"); - solver.EndSearch(); - } + // + // Data + // + int n = 7; // length of the array - public static void Main(String[] args) { - Solve(); - } + // + // Decision variables + // + + // Note: We use 1..2 (instead of 0..1) and subtract 1 in the solution + IntVar[] reg_input = solver.MakeIntVarArray(n, 1, 2, "reg_input"); + + // + // Constraints + // + MyContiguity(solver, reg_input); + + // + // Search + // + DecisionBuilder db = solver.MakePhase(reg_input, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); + + solver.NewSearch(db); + + while (solver.NextSolution()) + { + for (int i = 0; i < n; i++) + { + // Note: here we subtract 1 to get 0..1 + Console.Write((reg_input[i].Value() - 1) + " "); + } + Console.WriteLine(); + } + + Console.WriteLine("\nSolutions: {0}", solver.Solutions()); + Console.WriteLine("WallTime: {0}ms", solver.WallTime()); + Console.WriteLine("Failures: {0}", solver.Failures()); + Console.WriteLine("Branches: {0} ", solver.Branches()); + + solver.EndSearch(); + } + + public static void Main(String[] args) + { + Solve(); + } } diff --git a/examples/contrib/contiguity_transition.cs b/examples/contrib/contiguity_transition.cs index 3af485cfdd..4476139b08 100644 --- a/examples/contrib/contiguity_transition.cs +++ b/examples/contrib/contiguity_transition.cs @@ -19,90 +19,94 @@ using System.Linq; using System.Diagnostics; using Google.OrTools.ConstraintSolver; -public class ContiguityRegular { - static void MyContiguity(Solver solver, IntVar[] x) { - // the DFA (for regular) - int initial_state = 1; +public class ContiguityRegular +{ + 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 }; + // all states are accepting states + int[] accepting_states = { 1, 2, 3 }; - // The regular expression 0*1*0* {state, input, next state} - long[][] transition_tuples = { new long[] { 1, 0, 1 }, new long[] { 1, 1, 2 }, - new long[] { 2, 0, 3 }, new long[] { 2, 1, 2 }, - new long[] { 3, 0, 3 } }; + // The regular expression 0*1*0* {state, input, next state} + long[][] transition_tuples = { new long[] { 1, 0, 1 }, new long[] { 1, 1, 2 }, new long[] { 2, 0, 3 }, + new long[] { 2, 1, 2 }, new long[] { 3, 0, 3 } }; - IntTupleSet result = new IntTupleSet(3); - result.InsertAll(transition_tuples); + IntTupleSet result = new IntTupleSet(3); + result.InsertAll(transition_tuples); - solver.Add(x.Transition(result, initial_state, accepting_states)); - } - - /** - * - * Global constraint contiguity using Transition - * - * This version use the built-in TransitionConstraint. - * - * From Global Constraint Catalogue - * http://www.emn.fr/x-info/sdemasse/gccat/Cglobal_contiguity.html - * """ - * Enforce all variables of the VARIABLES collection to be assigned to 0 or 1. - * In addition, all variables assigned to value 1 appear contiguously. - * - * Example: - * (<0, 1, 1, 0>) - * - * The global_contiguity constraint holds since the sequence 0 1 1 0 contains - * no more than one group of contiguous 1. - * """ - * - * Also see http://www.hakank.org/or-tools/contiguity_regular.py - * - */ - private static void Solve() { - Solver solver = new Solver("ContiguityRegular"); - - // - // Data - // - int n = 7; // length of the array - - // - // Decision variables - // - - IntVar[] reg_input = solver.MakeIntVarArray(n, 0, 1, "reg_input"); - - // - // Constraints - // - MyContiguity(solver, reg_input); - - // - // Search - // - DecisionBuilder db = - solver.MakePhase(reg_input, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); - - solver.NewSearch(db); - - while (solver.NextSolution()) { - for (int i = 0; i < n; i++) { - Console.Write((reg_input[i].Value()) + " "); - } - Console.WriteLine(); + solver.Add(x.Transition(result, initial_state, accepting_states)); } - 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()); + /** + * + * Global constraint contiguity using Transition + * + * This version use the built-in TransitionConstraint. + * + * From Global Constraint Catalogue + * http://www.emn.fr/x-info/sdemasse/gccat/Cglobal_contiguity.html + * """ + * Enforce all variables of the VARIABLES collection to be assigned to 0 or 1. + * In addition, all variables assigned to value 1 appear contiguously. + * + * Example: + * (<0, 1, 1, 0>) + * + * The global_contiguity constraint holds since the sequence 0 1 1 0 contains + * no more than one group of contiguous 1. + * """ + * + * Also see http://www.hakank.org/or-tools/contiguity_regular.py + * + */ + private static void Solve() + { + Solver solver = new Solver("ContiguityRegular"); - solver.EndSearch(); - } + // + // Data + // + int n = 7; // length of the array - public static void Main(String[] args) { - Solve(); - } + // + // Decision variables + // + + IntVar[] reg_input = solver.MakeIntVarArray(n, 0, 1, "reg_input"); + + // + // Constraints + // + MyContiguity(solver, reg_input); + + // + // Search + // + DecisionBuilder db = solver.MakePhase(reg_input, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); + + solver.NewSearch(db); + + while (solver.NextSolution()) + { + for (int i = 0; i < n; i++) + { + Console.Write((reg_input[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 static void Main(String[] args) + { + Solve(); + } } diff --git a/examples/contrib/costas_array.cs b/examples/contrib/costas_array.cs index 0caa09bf88..a948fb5864 100644 --- a/examples/contrib/costas_array.cs +++ b/examples/contrib/costas_array.cs @@ -20,144 +20,166 @@ using System.Linq; using System.Text.RegularExpressions; using Google.OrTools.ConstraintSolver; -public class CostasArray { - /** - * - * Costas array - * - * From http://mathworld.wolfram.com/CostasArray.html: - * """ - * An order-n Costas array is a permutation on {1,...,n} such - * that the distances in each row of the triangular difference - * table are distinct. For example, the permutation {1,3,4,2,5} - * has triangular difference table {2,1,-2,3}, {3,-1,1}, {1,2}, - * and {4}. Since each row contains no duplications, the permutation - * is therefore a Costas array. - * """ - * - * Also see - * http://en.wikipedia.org/wiki/Costas_array - * http://hakank.org/or-tools/costas_array.py - * - */ - private static void Solve(int n = 6) { - Solver solver = new Solver("CostasArray"); +public class CostasArray +{ + /** + * + * Costas array + * + * From http://mathworld.wolfram.com/CostasArray.html: + * """ + * An order-n Costas array is a permutation on {1,...,n} such + * that the distances in each row of the triangular difference + * table are distinct. For example, the permutation {1,3,4,2,5} + * has triangular difference table {2,1,-2,3}, {3,-1,1}, {1,2}, + * and {4}. Since each row contains no duplications, the permutation + * is therefore a Costas array. + * """ + * + * Also see + * http://en.wikipedia.org/wiki/Costas_array + * http://hakank.org/or-tools/costas_array.py + * + */ + private static void Solve(int n = 6) + { + Solver solver = new Solver("CostasArray"); - // - // Data - // - Console.WriteLine("n: {0}", n); + // + // Data + // + Console.WriteLine("n: {0}", n); - // - // Decision variables - // - IntVar[] costas = solver.MakeIntVarArray(n, 1, n, "costas"); - IntVar[,] differences = solver.MakeIntVarMatrix(n, n, -n + 1, n - 1, "differences"); + // + // Decision variables + // + IntVar[] costas = solver.MakeIntVarArray(n, 1, n, "costas"); + IntVar[,] differences = solver.MakeIntVarMatrix(n, n, -n + 1, n - 1, "differences"); - // - // Constraints - // + // + // Constraints + // - // Fix the values in the lower triangle in the - // difference matrix to -n+1. This removes variants - // of the difference matrix for the the same Costas array. - for (int i = 0; i < n; i++) { - for (int j = 0; j <= i; j++) { - solver.Add(differences[i, j] == -n + 1); - } - } - - // hakank: All the following constraints are from - // Barry O'Sullivans's original model. - // - solver.Add(costas.AllDifferent()); - - // "How do the positions in the Costas array relate - // to the elements of the distance triangle." - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - if (i < j) { - solver.Add(differences[i, j] - (costas[j] - costas[j - i - 1]) == 0); + // Fix the values in the lower triangle in the + // difference matrix to -n+1. This removes variants + // of the difference matrix for the the same Costas array. + for (int i = 0; i < n; i++) + { + for (int j = 0; j <= i; j++) + { + solver.Add(differences[i, j] == -n + 1); + } } - } - } - // "All entries in a particular row of the difference - // triangle must be distint." - for (int i = 0; i < n - 2; i++) { + // hakank: All the following constraints are from + // Barry O'Sullivans's original model. + // + solver.Add(costas.AllDifferent()); + + // "How do the positions in the Costas array relate + // to the elements of the distance triangle." + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + if (i < j) + { + solver.Add(differences[i, j] - (costas[j] - costas[j - i - 1]) == 0); + } + } + } + + // "All entries in a particular row of the difference + // triangle must be distint." + for (int i = 0; i < n - 2; i++) + { IntVar[] tmp = (from j in Enumerable.Range(0, n) where j > i select differences[i, j]) .ToArray(); solver.Add(tmp.AllDifferent()); - } - - // - // "All the following are redundant - only here to speed up search." - // - - // "We can never place a 'token' in the same row as any other." - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - if (i < j) { - solver.Add(differences[i, j] != 0); - solver.Add(differences[i, j] != 0); } - } - } - for (int k = 2; k < n; k++) { - for (int l = 2; l < n; l++) { - if (k < l) { - solver.Add((differences[k - 2, l - 1] + differences[k, l]) - - (differences[k - 1, l - 1] + differences[k - 1, l]) == - 0); + // + // "All the following are redundant - only here to speed up search." + // + + // "We can never place a 'token' in the same row as any other." + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + if (i < j) + { + solver.Add(differences[i, j] != 0); + solver.Add(differences[i, j] != 0); + } + } } - } - } - // - // Search - // - DecisionBuilder db = - solver.MakePhase(costas, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); - - solver.NewSearch(db); - - while (solver.NextSolution()) { - Console.Write("costas: "); - for (int i = 0; i < n; i++) { - Console.Write("{0} ", costas[i].Value()); - } - Console.WriteLine("\ndifferences:"); - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - long v = differences[i, j].Value(); - if (v == -n + 1) { - Console.Write(" "); - } else { - Console.Write("{0,2} ", v); - } + for (int k = 2; k < n; k++) + { + for (int l = 2; l < n; l++) + { + if (k < l) + { + solver.Add((differences[k - 2, l - 1] + differences[k, l]) - + (differences[k - 1, l - 1] + differences[k - 1, l]) == + 0); + } + } } - Console.WriteLine(); - } - Console.WriteLine(); + + // + // Search + // + DecisionBuilder db = solver.MakePhase(costas, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); + + solver.NewSearch(db); + + while (solver.NextSolution()) + { + Console.Write("costas: "); + for (int i = 0; i < n; i++) + { + Console.Write("{0} ", costas[i].Value()); + } + Console.WriteLine("\ndifferences:"); + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + long v = differences[i, j].Value(); + if (v == -n + 1) + { + Console.Write(" "); + } + else + { + Console.Write("{0,2} ", v); + } + } + 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(); } - 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()); + public static void Main(String[] args) + { + int n = 6; - solver.EndSearch(); - } + if (args.Length > 0) + { + n = Convert.ToInt32(args[0]); + } - public static void Main(String[] args) { - int n = 6; - - if (args.Length > 0) { - n = Convert.ToInt32(args[0]); + Solve(n); } - - Solve(n); - } } diff --git a/examples/contrib/covering_opl.cs b/examples/contrib/covering_opl.cs index 02d79b0304..a6234e4a21 100644 --- a/examples/contrib/covering_opl.cs +++ b/examples/contrib/covering_opl.cs @@ -19,97 +19,98 @@ using System.IO; using System.Text.RegularExpressions; using Google.OrTools.ConstraintSolver; -public class SetCoveringOPL { - /** - * - * 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"); +public class SetCoveringOPL +{ + /** + * + * 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; + // + // 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 } }; + // 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 }; + 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(); + // + // Decision variables + // + IntVar[] hire = solver.MakeIntVarArray(num_workers, 0, 1, "workers"); + IntVar total_cost = hire.ScalProd(cost).Var(); - // - // Constraints - // + // + // 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 + " "); + 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); } - } - Console.WriteLine("\n"); + + // + // 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(); } - 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 Main(String[] args) { - Solve(); - } + public static void Main(String[] args) + { + Solve(); + } } diff --git a/examples/contrib/crew.cs b/examples/contrib/crew.cs index 71561df59a..dc505836a6 100644 --- a/examples/contrib/crew.cs +++ b/examples/contrib/crew.cs @@ -20,218 +20,243 @@ using System.Linq; using System.Text.RegularExpressions; using Google.OrTools.ConstraintSolver; -public class Crew { - /** - * - * Crew allocation problem in Google CP Solver. - * - * From Gecode example crew - * examples/crew.cc - * """ - * Example: Airline crew allocation - * - * Assign 20 flight attendants to 10 flights. Each flight needs a certain - * number of cabin crew, and they have to speak certain languages. - * Every cabin crew member has two flights off after an attended flight. - * """ - * - * Also see http://www.hakank.org/or-tools/crew.pl - * - */ - private static void Solve(int sols = 1, int minimize = 0) { - Solver solver = new Solver("Crew"); +public class Crew +{ + /** + * + * Crew allocation problem in Google CP Solver. + * + * From Gecode example crew + * examples/crew.cc + * """ + * Example: Airline crew allocation + * + * Assign 20 flight attendants to 10 flights. Each flight needs a certain + * number of cabin crew, and they have to speak certain languages. + * Every cabin crew member has two flights off after an attended flight. + * """ + * + * Also see http://www.hakank.org/or-tools/crew.pl + * + */ + private static void Solve(int sols = 1, int minimize = 0) + { + Solver solver = new Solver("Crew"); - // - // Data - // - string[] names = { "Tom", "David", "Jeremy", "Ron", "Joe", "Bill", "Fred", - "Bob", "Mario", "Ed", "Carol", "Janet", "Tracy", "Marilyn", - "Carolyn", "Cathy", "Inez", "Jean", "Heather", "Juliet" }; + // + // Data + // + string[] names = { "Tom", "David", "Jeremy", "Ron", "Joe", "Bill", "Fred", + "Bob", "Mario", "Ed", "Carol", "Janet", "Tracy", "Marilyn", + "Carolyn", "Cathy", "Inez", "Jean", "Heather", "Juliet" }; - int num_persons = names.Length; + int num_persons = names.Length; - // - // Attributes of the crew - // - int[,] attributes = { - // steward, hostess, french, spanish, german - { 1, 0, 0, 0, 1 }, // Tom = 0 - { 1, 0, 0, 0, 0 }, // David = 1 - { 1, 0, 0, 0, 1 }, // Jeremy = 2 - { 1, 0, 0, 0, 0 }, // Ron = 3 - { 1, 0, 0, 1, 0 }, // Joe = 4 - { 1, 0, 1, 1, 0 }, // Bill = 5 - { 1, 0, 0, 1, 0 }, // Fred = 6 - { 1, 0, 0, 0, 0 }, // Bob = 7 - { 1, 0, 0, 1, 1 }, // Mario = 8 - { 1, 0, 0, 0, 0 }, // Ed = 9 - { 0, 1, 0, 0, 0 }, // Carol = 10 - { 0, 1, 0, 0, 0 }, // Janet = 11 - { 0, 1, 0, 0, 0 }, // Tracy = 12 - { 0, 1, 0, 1, 1 }, // Marilyn = 13 - { 0, 1, 0, 0, 0 }, // Carolyn = 14 - { 0, 1, 0, 0, 0 }, // Cathy = 15 - { 0, 1, 1, 1, 1 }, // Inez = 16 - { 0, 1, 1, 0, 0 }, // Jean = 17 - { 0, 1, 0, 1, 1 }, // Heather = 18 - { 0, 1, 1, 0, 0 } // Juliet = 19 - }; + // + // Attributes of the crew + // + int[,] attributes = { + // steward, hostess, french, spanish, german + { 1, 0, 0, 0, 1 }, // Tom = 0 + { 1, 0, 0, 0, 0 }, // David = 1 + { 1, 0, 0, 0, 1 }, // Jeremy = 2 + { 1, 0, 0, 0, 0 }, // Ron = 3 + { 1, 0, 0, 1, 0 }, // Joe = 4 + { 1, 0, 1, 1, 0 }, // Bill = 5 + { 1, 0, 0, 1, 0 }, // Fred = 6 + { 1, 0, 0, 0, 0 }, // Bob = 7 + { 1, 0, 0, 1, 1 }, // Mario = 8 + { 1, 0, 0, 0, 0 }, // Ed = 9 + { 0, 1, 0, 0, 0 }, // Carol = 10 + { 0, 1, 0, 0, 0 }, // Janet = 11 + { 0, 1, 0, 0, 0 }, // Tracy = 12 + { 0, 1, 0, 1, 1 }, // Marilyn = 13 + { 0, 1, 0, 0, 0 }, // Carolyn = 14 + { 0, 1, 0, 0, 0 }, // Cathy = 15 + { 0, 1, 1, 1, 1 }, // Inez = 16 + { 0, 1, 1, 0, 0 }, // Jean = 17 + { 0, 1, 0, 1, 1 }, // Heather = 18 + { 0, 1, 1, 0, 0 } // Juliet = 19 + }; - // - // Required number of crew members. - // - // The columns are in the following order: - // staff : Overall number of cabin crew needed - // stewards : How many stewards are required - // hostesses : How many hostesses are required - // french : How many French speaking employees are required - // spanish : How many Spanish speaking employees are required - // german : How many German speaking employees are required - // - int[,] required_crew = { - { 4, 1, 1, 1, 1, 1 }, // Flight 1 - { 5, 1, 1, 1, 1, 1 }, // Flight 2 - { 5, 1, 1, 1, 1, 1 }, // .. - { 6, 2, 2, 1, 1, 1 }, { 7, 3, 3, 1, 1, 1 }, { 4, 1, 1, 1, 1, 1 }, - { 5, 1, 1, 1, 1, 1 }, { 6, 1, 1, 1, 1, 1 }, { 6, 2, 2, 1, 1, 1 }, // ... - { 7, 3, 3, 1, 1, 1 } // Flight 10 - }; + // + // Required number of crew members. + // + // The columns are in the following order: + // staff : Overall number of cabin crew needed + // stewards : How many stewards are required + // hostesses : How many hostesses are required + // french : How many French speaking employees are required + // spanish : How many Spanish speaking employees are required + // german : How many German speaking employees are required + // + int[,] required_crew = { + { 4, 1, 1, 1, 1, 1 }, // Flight 1 + { 5, 1, 1, 1, 1, 1 }, // Flight 2 + { 5, 1, 1, 1, 1, 1 }, // .. + { 6, 2, 2, 1, 1, 1 }, { 7, 3, 3, 1, 1, 1 }, { 4, 1, 1, 1, 1, 1 }, + { 5, 1, 1, 1, 1, 1 }, { 6, 1, 1, 1, 1, 1 }, { 6, 2, 2, 1, 1, 1 }, // ... + { 7, 3, 3, 1, 1, 1 } // Flight 10 + }; - int num_flights = required_crew.GetLength(0); + int num_flights = required_crew.GetLength(0); - // - // Decision variables - // - IntVar[,] crew = solver.MakeIntVarMatrix(num_flights, num_persons, 0, 1, "crew"); - IntVar[] crew_flat = crew.Flatten(); + // + // Decision variables + // + IntVar[,] crew = solver.MakeIntVarMatrix(num_flights, num_persons, 0, 1, "crew"); + IntVar[] crew_flat = crew.Flatten(); - // number of working persons - IntVar num_working = solver.MakeIntVar(1, num_persons, "num_working"); + // number of working persons + IntVar num_working = solver.MakeIntVar(1, num_persons, "num_working"); - // - // Constraints - // + // + // Constraints + // - // number of working persons - IntVar[] nw = new IntVar[num_persons]; - for (int p = 0; p < num_persons; p++) { - IntVar[] tmp = new IntVar[num_flights]; - for (int f = 0; f < num_flights; f++) { - tmp[f] = crew[f, p]; - } - nw[p] = tmp.Sum() > 0; - } - solver.Add(nw.Sum() == num_working); - - for (int f = 0; f < num_flights; f++) { - // size of crew - IntVar[] tmp = new IntVar[num_persons]; - for (int p = 0; p < num_persons; p++) { - tmp[p] = crew[f, p]; - } - solver.Add(tmp.Sum() == required_crew[f, 0]); - - // attributes and requirements - for (int a = 0; a < 5; a++) { - IntVar[] tmp2 = new IntVar[num_persons]; - for (int p = 0; p < num_persons; p++) { - tmp2[p] = (crew[f, p] * attributes[p, a]).Var(); + // number of working persons + IntVar[] nw = new IntVar[num_persons]; + for (int p = 0; p < num_persons; p++) + { + IntVar[] tmp = new IntVar[num_flights]; + for (int f = 0; f < num_flights; f++) + { + tmp[f] = crew[f, p]; + } + nw[p] = tmp.Sum() > 0; } - solver.Add(tmp2.Sum() >= required_crew[f, a + 1]); - } - } + solver.Add(nw.Sum() == num_working); - // after a flight, break for at least two flights - for (int f = 0; f < num_flights - 2; f++) { - for (int i = 0; i < num_persons; i++) { - solver.Add(crew[f, i] + crew[f + 1, i] + crew[f + 2, i] <= 1); - } - } + for (int f = 0; f < num_flights; f++) + { + // size of crew + IntVar[] tmp = new IntVar[num_persons]; + for (int p = 0; p < num_persons; p++) + { + tmp[p] = crew[f, p]; + } + solver.Add(tmp.Sum() == required_crew[f, 0]); - // extra contraint: all must work at least two of the flights - /* - for(int p = 0; p < num_persons; p++) { - IntVar[] tmp = new IntVar[num_flights]; - for(int f = 0; f < num_flights; f++) { - tmp[f] = crew[f,p]; - } - solver.Add(tmp.Sum() >= 2); - } - */ - - // - // Search - // - DecisionBuilder db = - solver.MakePhase(crew_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); - - if (minimize > 0) { - OptimizeVar obj = num_working.Minimize(1); - solver.NewSearch(db, obj); - } else { - solver.NewSearch(db); - } - - int num_solutions = 0; - while (solver.NextSolution()) { - num_solutions++; - Console.WriteLine("Solution #{0}", num_solutions); - Console.WriteLine("Number working: {0}", num_working.Value()); - - for (int f = 0; f < num_flights; f++) { - for (int p = 0; p < num_persons; p++) { - Console.Write(crew[f, p].Value() + " "); + // attributes and requirements + for (int a = 0; a < 5; a++) + { + IntVar[] tmp2 = new IntVar[num_persons]; + for (int p = 0; p < num_persons; p++) + { + tmp2[p] = (crew[f, p] * attributes[p, a]).Var(); + } + solver.Add(tmp2.Sum() >= required_crew[f, a + 1]); + } } - Console.WriteLine(); - } - Console.WriteLine("\nFlights: "); - for (int f = 0; f < num_flights; f++) { - Console.Write("Flight #{0}: ", f); - for (int p = 0; p < num_persons; p++) { - if (crew[f, p].Value() == 1) { - Console.Write(names[p] + " "); + + // after a flight, break for at least two flights + for (int f = 0; f < num_flights - 2; f++) + { + for (int i = 0; i < num_persons; i++) + { + solver.Add(crew[f, i] + crew[f + 1, i] + crew[f + 2, i] <= 1); + } + } + + // extra contraint: all must work at least two of the flights + /* + for(int p = 0; p < num_persons; p++) { + IntVar[] tmp = new IntVar[num_flights]; + for(int f = 0; f < num_flights; f++) { + tmp[f] = crew[f,p]; } + solver.Add(tmp.Sum() >= 2); } - Console.WriteLine(); - } + */ - Console.WriteLine("\nCrew:"); - for (int p = 0; p < num_persons; p++) { - Console.Write("{0,-10}", names[p]); - for (int f = 0; f < num_flights; f++) { - if (crew[f, p].Value() == 1) { - Console.Write(f + " "); - } + // + // Search + // + DecisionBuilder db = solver.MakePhase(crew_flat, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE); + + if (minimize > 0) + { + OptimizeVar obj = num_working.Minimize(1); + solver.NewSearch(db, obj); + } + else + { + solver.NewSearch(db); } - Console.WriteLine(); - } - Console.WriteLine(); + int num_solutions = 0; + while (solver.NextSolution()) + { + num_solutions++; + Console.WriteLine("Solution #{0}", num_solutions); + Console.WriteLine("Number working: {0}", num_working.Value()); - if (num_solutions >= sols) { - break; - } + for (int f = 0; f < num_flights; f++) + { + for (int p = 0; p < num_persons; p++) + { + Console.Write(crew[f, p].Value() + " "); + } + Console.WriteLine(); + } + Console.WriteLine("\nFlights: "); + for (int f = 0; f < num_flights; f++) + { + Console.Write("Flight #{0}: ", f); + for (int p = 0; p < num_persons; p++) + { + if (crew[f, p].Value() == 1) + { + Console.Write(names[p] + " "); + } + } + Console.WriteLine(); + } + + Console.WriteLine("\nCrew:"); + for (int p = 0; p < num_persons; p++) + { + Console.Write("{0,-10}", names[p]); + for (int f = 0; f < num_flights; f++) + { + if (crew[f, p].Value() == 1) + { + Console.Write(f + " "); + } + } + Console.WriteLine(); + } + + Console.WriteLine(); + + if (num_solutions >= sols) + { + break; + } + } + + Console.WriteLine("\nSolutions: {0}", solver.Solutions()); + Console.WriteLine("WallTime: {0}ms", solver.WallTime()); + Console.WriteLine("Failures: {0}", solver.Failures()); + Console.WriteLine("Branches: {0} ", solver.Branches()); + + solver.EndSearch(); } - 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()); + public static void Main(String[] args) + { + int n = 1; + int min = 0; // > 0 -> minimize num_working + if (args.Length > 0) + { + n = Convert.ToInt32(args[0]); + } - solver.EndSearch(); - } + if (args.Length > 1) + { + min = Convert.ToInt32(args[1]); + } - public static void Main(String[] args) { - int n = 1; - int min = 0; // > 0 -> minimize num_working - if (args.Length > 0) { - n = Convert.ToInt32(args[0]); + Solve(n, min); } - - if (args.Length > 1) { - min = Convert.ToInt32(args[1]); - } - - Solve(n, min); - } } diff --git a/examples/contrib/crossword.cs b/examples/contrib/crossword.cs index a029745de1..4bd491b556 100644 --- a/examples/contrib/crossword.cs +++ b/examples/contrib/crossword.cs @@ -23,166 +23,178 @@ using Google.OrTools.ConstraintSolver; // warnings about assigned but never used variables. // It's the characters a..z so it's quite benign. -public class Crossword { - /** - * - * Solving a simple crossword. - * See http://www.hakank.org/or-tools/crossword2.py - * - * - */ - private static void Solve() { - Solver solver = new Solver("Crossword"); +public class Crossword +{ + /** + * + * Solving a simple crossword. + * See http://www.hakank.org/or-tools/crossword2.py + * + * + */ + private static void Solve() + { + Solver solver = new Solver("Crossword"); - // - // data - // - String[] alpha = { "_", "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" }; + // + // data + // + String[] alpha = { "_", "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" }; - int a = 1; - int b = 2; - int c = 3; - int d = 4; - int e = 5; - int f = 6; - int g = 7; - int h = 8; - int i = 9; - int j = 10; - int k = 11; - int l = 12; - int m = 13; - int n = 14; - int o = 15; - int p = 16; - int q = 17; - int r = 18; - int s = 19; - int t = 20; - int u = 21; - int v = 22; - int w = 23; - int x = 24; - int y = 25; - int z = 26; + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 6; + int g = 7; + int h = 8; + int i = 9; + int j = 10; + int k = 11; + int l = 12; + int m = 13; + int n = 14; + int o = 15; + int p = 16; + int q = 17; + int r = 18; + int s = 19; + int t = 20; + int u = 21; + int v = 22; + int w = 23; + int x = 24; + int y = 25; + int z = 26; - const int num_words = 15; - int word_len = 5; + const int num_words = 15; + int word_len = 5; - int[,] AA = { { h, o, s, e, s }, // HOSES - { l, a, s, e, r }, // LASER - { s, a, i, l, s }, // SAILS - { s, h, e, e, t }, // SHEET - { s, t, e, e, r }, // STEER - { h, e, e, l, 0 }, // HEEL - { h, i, k, e, 0 }, // HIKE - { k, e, e, l, 0 }, // KEEL - { k, n, o, t, 0 }, // KNOT - { l, i, n, e, 0 }, // LINE - { a, f, t, 0, 0 }, // AFT - { a, l, e, 0, 0 }, // ALE - { e, e, l, 0, 0 }, // EEL - { l, e, e, 0, 0 }, // LEE - { t, i, e, 0, 0 } }; // TIE + int[,] AA = { { h, o, s, e, s }, // HOSES + { l, a, s, e, r }, // LASER + { s, a, i, l, s }, // SAILS + { s, h, e, e, t }, // SHEET + { s, t, e, e, r }, // STEER + { h, e, e, l, 0 }, // HEEL + { h, i, k, e, 0 }, // HIKE + { k, e, e, l, 0 }, // KEEL + { k, n, o, t, 0 }, // KNOT + { l, i, n, e, 0 }, // LINE + { a, f, t, 0, 0 }, // AFT + { a, l, e, 0, 0 }, // ALE + { e, e, l, 0, 0 }, // EEL + { l, e, e, 0, 0 }, // LEE + { t, i, e, 0, 0 } }; // TIE - int num_overlapping = 12; - int[,] overlapping = { { 0, 2, 1, 0 }, // s - { 0, 4, 2, 0 }, // s + int num_overlapping = 12; + int[,] overlapping = { { 0, 2, 1, 0 }, // s + { 0, 4, 2, 0 }, // s - { 3, 1, 1, 2 }, // i - { 3, 2, 4, 0 }, // k - { 3, 3, 2, 2 }, // e + { 3, 1, 1, 2 }, // i + { 3, 2, 4, 0 }, // k + { 3, 3, 2, 2 }, // e - { 6, 0, 1, 3 }, // l - { 6, 1, 4, 1 }, // e - { 6, 2, 2, 3 }, // e + { 6, 0, 1, 3 }, // l + { 6, 1, 4, 1 }, // e + { 6, 2, 2, 3 }, // e - { 7, 0, 5, 1 }, // l - { 7, 2, 1, 4 }, // s - { 7, 3, 4, 2 }, // e - { 7, 4, 2, 4 } }; // r + { 7, 0, 5, 1 }, // l + { 7, 2, 1, 4 }, // s + { 7, 3, 4, 2 }, // e + { 7, 4, 2, 4 } }; // r - int N = 8; + int N = 8; - // - // Decision variables - // - // for labeling on A and E - IntVar[,] A = solver.MakeIntVarMatrix(num_words, word_len, 0, 26, "A"); - IntVar[] A_flat = A.Flatten(); - IntVar[] all = new IntVar[(num_words * word_len) + N]; - for (int I = 0; I < num_words; I++) { - for (int J = 0; J < word_len; J++) { - all[I * word_len + J] = A[I, J]; - } - } - - IntVar[] E = solver.MakeIntVarArray(N, 0, num_words, "E"); - for (int I = 0; I < N; I++) { - all[num_words * word_len + I] = E[I]; - } - - // - // Constraints - // - solver.Add(E.AllDifferent()); - - for (int I = 0; I < num_words; I++) { - for (int J = 0; J < word_len; J++) { - solver.Add(A[I, J] == AA[I, J]); - } - } - - // This contraint handles the overlappings. - // - // It's coded in MiniZinc as - // - // forall(i in 1..num_overlapping) ( - // A[E[overlapping[i,1]], overlapping[i,2]] = - // A[E[overlapping[i,3]], overlapping[i,4]] - // ) - // and in or-tools/Python as - // solver.Add( - // solver.Element(A_flat,E[overlapping[I][0]]*word_len+overlapping[I][1]) - // == - // solver.Element(A_flat,E[overlapping[I][2]]*word_len+overlapping[I][3])) - // - for (int I = 0; I < num_overlapping; I++) { - solver.Add(A_flat.Element(E[overlapping[I, 0]] * word_len + overlapping[I, 1]) == - A_flat.Element(E[overlapping[I, 2]] * word_len + overlapping[I, 3])); - } - - // - // Search - // - DecisionBuilder db = solver.MakePhase(all, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); - - solver.NewSearch(db); - - while (solver.NextSolution()) { - Console.WriteLine("E: "); - for (int ee = 0; ee < N; ee++) { - int e_val = (int)E[ee].Value(); - Console.Write(ee + ": (" + e_val + ") "); - for (int ii = 0; ii < word_len; ii++) { - Console.Write(alpha[(int)A[ee, ii].Value()]); + // + // Decision variables + // + // for labeling on A and E + IntVar[,] A = solver.MakeIntVarMatrix(num_words, word_len, 0, 26, "A"); + IntVar[] A_flat = A.Flatten(); + IntVar[] all = new IntVar[(num_words * word_len) + N]; + for (int I = 0; I < num_words; I++) + { + for (int J = 0; J < word_len; J++) + { + all[I * word_len + J] = A[I, J]; + } } - Console.WriteLine(); - } - Console.WriteLine(); + IntVar[] E = solver.MakeIntVarArray(N, 0, num_words, "E"); + for (int I = 0; I < N; I++) + { + all[num_words * word_len + I] = E[I]; + } + + // + // Constraints + // + solver.Add(E.AllDifferent()); + + for (int I = 0; I < num_words; I++) + { + for (int J = 0; J < word_len; J++) + { + solver.Add(A[I, J] == AA[I, J]); + } + } + + // This contraint handles the overlappings. + // + // It's coded in MiniZinc as + // + // forall(i in 1..num_overlapping) ( + // A[E[overlapping[i,1]], overlapping[i,2]] = + // A[E[overlapping[i,3]], overlapping[i,4]] + // ) + // and in or-tools/Python as + // solver.Add( + // solver.Element(A_flat,E[overlapping[I][0]]*word_len+overlapping[I][1]) + // == + // solver.Element(A_flat,E[overlapping[I][2]]*word_len+overlapping[I][3])) + // + for (int I = 0; I < num_overlapping; I++) + { + solver.Add(A_flat.Element(E[overlapping[I, 0]] * word_len + overlapping[I, 1]) == + A_flat.Element(E[overlapping[I, 2]] * word_len + overlapping[I, 3])); + } + + // + // Search + // + DecisionBuilder db = solver.MakePhase(all, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); + + solver.NewSearch(db); + + while (solver.NextSolution()) + { + Console.WriteLine("E: "); + for (int ee = 0; ee < N; ee++) + { + int e_val = (int)E[ee].Value(); + Console.Write(ee + ": (" + e_val + ") "); + for (int ii = 0; ii < word_len; ii++) + { + Console.Write(alpha[(int)A[ee, ii].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(); } - 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 Main(String[] args) { - Solve(); - } + public static void Main(String[] args) + { + Solve(); + } } diff --git a/examples/contrib/crypta.cs b/examples/contrib/crypta.cs index 292fe5f60b..aa837ada98 100644 --- a/examples/contrib/crypta.cs +++ b/examples/contrib/crypta.cs @@ -16,97 +16,99 @@ using System; using Google.OrTools.ConstraintSolver; -public class Crypta { - /** - * - * Cryptarithmetic puzzle. - * - * Prolog benchmark problem GNU Prolog (crypta.pl) - * """ - * Name : crypta.pl - * Title : crypt-arithmetic - * Original Source: P. Van Hentenryck's book - * Adapted by : Daniel Diaz - INRIA France - * Date : September 1992 - * - * Solve the operation: - * - * B A I J J A J I I A H F C F E B B J E A - * + D H F G A B C D I D B I F F A G F E J E - * ----------------------------------------- - * = G J E G A C D D H F A F J B F I H E E F - * """ - * - * - * Also see http://hakank.org/or-tools/crypta.py - * - */ - private static void Solve() { - Solver solver = new Solver("Crypta"); +public class Crypta +{ + /** + * + * Cryptarithmetic puzzle. + * + * Prolog benchmark problem GNU Prolog (crypta.pl) + * """ + * Name : crypta.pl + * Title : crypt-arithmetic + * Original Source: P. Van Hentenryck's book + * Adapted by : Daniel Diaz - INRIA France + * Date : September 1992 + * + * Solve the operation: + * + * B A I J J A J I I A H F C F E B B J E A + * + D H F G A B C D I D B I F F A G F E J E + * ----------------------------------------- + * = G J E G A C D D H F A F J B F I H E E F + * """ + * + * + * Also see http://hakank.org/or-tools/crypta.py + * + */ + private static void Solve() + { + Solver solver = new Solver("Crypta"); - // - // 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"); + // + // 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[] LD = new IntVar[] { A, B, C, D, E, F, G, H, I, J }; + IntVar[] LD = new IntVar[] { A, B, C, D, E, F, G, H, I, J }; - IntVar Sr1 = solver.MakeIntVar(0, 1, "Sr1"); - IntVar Sr2 = solver.MakeIntVar(0, 1, "Sr2"); + IntVar Sr1 = solver.MakeIntVar(0, 1, "Sr1"); + IntVar Sr2 = solver.MakeIntVar(0, 1, "Sr2"); - // - // Constraints - // - solver.Add(LD.AllDifferent()); - solver.Add(B >= 1); - solver.Add(D >= 1); - solver.Add(G >= 1); + // + // Constraints + // + solver.Add(LD.AllDifferent()); + solver.Add(B >= 1); + solver.Add(D >= 1); + solver.Add(G >= 1); - solver.Add( - (A + 10 * E + 100 * J + 1000 * B + 10000 * B + 100000 * E + 1000000 * F + E + 10 * J + - 100 * E + 1000 * F + 10000 * G + 100000 * A + 1000000 * F) == - (F + 10 * E + 100 * E + 1000 * H + 10000 * I + 100000 * F + 1000000 * B + 10000000 * Sr1)); + solver.Add((A + 10 * E + 100 * J + 1000 * B + 10000 * B + 100000 * E + 1000000 * F + E + 10 * J + 100 * E + + 1000 * F + 10000 * G + 100000 * A + 1000000 * F) == + (F + 10 * E + 100 * E + 1000 * H + 10000 * I + 100000 * F + 1000000 * B + 10000000 * Sr1)); - solver.Add( - (C + 10 * F + 100 * H + 1000 * A + 10000 * I + 100000 * I + 1000000 * J + F + 10 * I + - 100 * B + 1000 * D + 10000 * I + 100000 * D + 1000000 * C + Sr1) == - (J + 10 * F + 100 * A + 1000 * F + 10000 * H + 100000 * D + 1000000 * D + 10000000 * Sr2)); + solver.Add((C + 10 * F + 100 * H + 1000 * A + 10000 * I + 100000 * I + 1000000 * J + F + 10 * I + 100 * B + + 1000 * D + 10000 * I + 100000 * D + 1000000 * C + Sr1) == + (J + 10 * F + 100 * A + 1000 * F + 10000 * H + 100000 * D + 1000000 * D + 10000000 * Sr2)); - solver.Add((A + 10 * J + 100 * J + 1000 * I + 10000 * A + 100000 * B + B + 10 * A + 100 * G + - 1000 * F + 10000 * H + 100000 * D + Sr2) == - (C + 10 * A + 100 * G + 1000 * E + 10000 * J + 100000 * G)); + solver.Add((A + 10 * J + 100 * J + 1000 * I + 10000 * A + 100000 * B + B + 10 * A + 100 * G + 1000 * F + + 10000 * H + 100000 * D + Sr2) == (C + 10 * A + 100 * G + 1000 * E + 10000 * J + 100000 * G)); - // - // Search - // - DecisionBuilder db = solver.MakePhase(LD, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); + // + // Search + // + DecisionBuilder db = solver.MakePhase(LD, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); - solver.NewSearch(db); + solver.NewSearch(db); - while (solver.NextSolution()) { - for (int i = 0; i < 10; i++) { - Console.Write(LD[i].ToString() + " "); - } - Console.WriteLine(); + while (solver.NextSolution()) + { + for (int i = 0; i < 10; i++) + { + Console.Write(LD[i].ToString() + " "); + } + Console.WriteLine(); + } + + Console.WriteLine("\nWallTime: " + solver.WallTime() + "ms "); + Console.WriteLine("Failures: " + solver.Failures()); + Console.WriteLine("Branches: " + solver.Branches()); + + solver.EndSearch(); } - Console.WriteLine("\nWallTime: " + solver.WallTime() + "ms "); - Console.WriteLine("Failures: " + solver.Failures()); - Console.WriteLine("Branches: " + solver.Branches()); - - solver.EndSearch(); - } - - public static void Main(String[] args) { - Solve(); - } + public static void Main(String[] args) + { + Solve(); + } } diff --git a/examples/contrib/crypto.cs b/examples/contrib/crypto.cs index be31d3a474..c2296859a0 100644 --- a/examples/contrib/crypto.cs +++ b/examples/contrib/crypto.cs @@ -16,148 +16,152 @@ using System; using Google.OrTools.ConstraintSolver; -public class Crypto { - /** - * - * 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 , - * 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"); +public class Crypto +{ + /** + * + * 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 , + * 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 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; + 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"); + // + // 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]; + // 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); + // + // 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); + // + // Search + // + DecisionBuilder db = solver.MakePhase(LD, Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, Solver.ASSIGN_CENTER_VALUE); - solver.NewSearch(db); + 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(); + 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(); } - Console.WriteLine("\nWallTime: " + solver.WallTime() + "ms "); - Console.WriteLine("Failures: " + solver.Failures()); - Console.WriteLine("Branches: " + solver.Branches()); - - solver.EndSearch(); - } - - public static void Main(String[] args) { - Solve(); - } + public static void Main(String[] args) + { + Solve(); + } } diff --git a/examples/contrib/csdiet.cs b/examples/contrib/csdiet.cs index cde15a2952..a0db9d1dc2 100644 --- a/examples/contrib/csdiet.cs +++ b/examples/contrib/csdiet.cs @@ -16,76 +16,81 @@ using System; using Google.OrTools.ConstraintSolver; -public class Diet { - /** - * - * Solves the Diet problem - * - * See http://www.hakank.org/google_or_tools/diet1.py - * - */ - private static void Solve() { - Solver solver = new Solver("Diet"); +public class Diet +{ + /** + * + * Solves the Diet problem + * + * See http://www.hakank.org/google_or_tools/diet1.py + * + */ + private static void Solve() + { + Solver solver = new Solver("Diet"); - int n = 4; - int[] price = { 50, 20, 30, 80 }; // in cents + int n = 4; + int[] price = { 50, 20, 30, 80 }; // in cents - // requirements for each nutrition type - int[] limits = { 500, 6, 10, 8 }; - string[] products = { "A", "B", "C", "D" }; + // requirements for each nutrition type + int[] limits = { 500, 6, 10, 8 }; + string[] products = { "A", "B", "C", "D" }; - // nutritions for each product - int[] calories = { 400, 200, 150, 500 }; - int[] chocolate = { 3, 2, 0, 0 }; - int[] sugar = { 2, 2, 4, 4 }; - int[] fat = { 2, 4, 1, 5 }; + // nutritions for each product + int[] calories = { 400, 200, 150, 500 }; + int[] chocolate = { 3, 2, 0, 0 }; + int[] sugar = { 2, 2, 4, 4 }; + int[] fat = { 2, 4, 1, 5 }; - // - // Decision variables - // - IntVar[] x = solver.MakeIntVarArray(n, 0, 100, "x"); - IntVar cost = x.ScalProd(price).Var(); + // + // Decision variables + // + IntVar[] x = solver.MakeIntVarArray(n, 0, 100, "x"); + IntVar cost = x.ScalProd(price).Var(); - // - // Constraints - // + // + // Constraints + // - // solver.Add(solver.MakeScalProdGreaterOrEqual(x, calories, limits[0])); - solver.Add(x.ScalProd(calories) >= limits[0]); - solver.Add(x.ScalProd(chocolate) >= limits[1]); - solver.Add(x.ScalProd(sugar) >= limits[2]); - solver.Add(x.ScalProd(fat) >= limits[3]); + // solver.Add(solver.MakeScalProdGreaterOrEqual(x, calories, limits[0])); + solver.Add(x.ScalProd(calories) >= limits[0]); + solver.Add(x.ScalProd(chocolate) >= limits[1]); + solver.Add(x.ScalProd(sugar) >= limits[2]); + solver.Add(x.ScalProd(fat) >= limits[3]); - // - // Objective - // - OptimizeVar obj = cost.Minimize(1); + // + // Objective + // + OptimizeVar obj = cost.Minimize(1); - // - // Search - // - DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_PATH, Solver.ASSIGN_MIN_VALUE); + // + // Search + // + DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_PATH, Solver.ASSIGN_MIN_VALUE); - solver.NewSearch(db, obj); - while (solver.NextSolution()) { - Console.WriteLine("cost: {0}", cost.Value()); - Console.WriteLine("Products: "); - for (int i = 0; i < n; i++) { - Console.WriteLine("{0}: {1}", products[i], x[i].Value()); - } + solver.NewSearch(db, obj); + while (solver.NextSolution()) + { + Console.WriteLine("cost: {0}", cost.Value()); + Console.WriteLine("Products: "); + for (int i = 0; i < n; i++) + { + Console.WriteLine("{0}: {1}", products[i], x[i].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(); } - 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 Main(String[] args) { - Solve(); - } + public static void Main(String[] args) + { + Solve(); + } } diff --git a/examples/contrib/curious_set_of_integers.cs b/examples/contrib/curious_set_of_integers.cs index 65f0a6b20c..7f8c499212 100644 --- a/examples/contrib/curious_set_of_integers.cs +++ b/examples/contrib/curious_set_of_integers.cs @@ -20,87 +20,95 @@ using System.Linq; using System.Text.RegularExpressions; using Google.OrTools.ConstraintSolver; -public class CuriousSetOfIntegers { - public static void Decreasing(Solver solver, IntVar[] x) { - for (int i = 0; i < x.Length - 1; i++) { - solver.Add(x[i] <= x[i + 1]); - } - } - - /** - * - * Crypto problem in Google CP Solver. - * - * Martin Gardner (February 1967): - * """ - * The integers 1,3,8, and 120 form a set with a remarkable property: the - * product of any two integers is one less than a perfect square. Find - * a fifth number that can be added to the set without destroying - * this property. - * """ - * - * Also see, http://www.hakank.org/or-tools/curious_set_of_integers.py - * - */ - private static void Solve() { - Solver solver = new Solver("CuriousSetOfIntegers"); - - // - // data - // - int n = 5; - int max_val = 10000; - - // - // Decision variables - // - IntVar[] x = solver.MakeIntVarArray(n, 0, max_val, "x"); - - // - // Constraints - // - solver.Add(x.AllDifferent()); - - for (int i = 0; i < n - 1; i++) { - for (int j = i + 1; j < n; j++) { - IntVar p = solver.MakeIntVar(0, max_val); - solver.Add((p.Square() - 1) - (x[i] * x[j]) == 0); - } +public class CuriousSetOfIntegers +{ + public static void Decreasing(Solver solver, IntVar[] x) + { + for (int i = 0; i < x.Length - 1; i++) + { + solver.Add(x[i] <= x[i + 1]); + } } - // Symmetry breaking - Decreasing(solver, x); + /** + * + * Crypto problem in Google CP Solver. + * + * Martin Gardner (February 1967): + * """ + * The integers 1,3,8, and 120 form a set with a remarkable property: the + * product of any two integers is one less than a perfect square. Find + * a fifth number that can be added to the set without destroying + * this property. + * """ + * + * Also see, http://www.hakank.org/or-tools/curious_set_of_integers.py + * + */ + private static void Solve() + { + Solver solver = new Solver("CuriousSetOfIntegers"); - // This is the original problem - // Which is the fifth number? - int[] v = { 1, 3, 8, 120 }; - IntVar[] b = (from i in Enumerable.Range(0, n) select x[i].IsMember(v)).ToArray(); - solver.Add(b.Sum() == 4); + // + // data + // + int n = 5; + int max_val = 10000; - // - // Search - // - DecisionBuilder db = - solver.MakePhase(x, Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, Solver.ASSIGN_MIN_VALUE); + // + // Decision variables + // + IntVar[] x = solver.MakeIntVarArray(n, 0, max_val, "x"); - solver.NewSearch(db); + // + // Constraints + // + solver.Add(x.AllDifferent()); - while (solver.NextSolution()) { - for (int i = 0; i < n; i++) { - Console.Write(x[i].Value() + " "); - } - Console.WriteLine(); + for (int i = 0; i < n - 1; i++) + { + for (int j = i + 1; j < n; j++) + { + IntVar p = solver.MakeIntVar(0, max_val); + solver.Add((p.Square() - 1) - (x[i] * x[j]) == 0); + } + } + + // Symmetry breaking + Decreasing(solver, x); + + // This is the original problem + // Which is the fifth number? + int[] v = { 1, 3, 8, 120 }; + IntVar[] b = (from i in Enumerable.Range(0, n) select x[i].IsMember(v)).ToArray(); + solver.Add(b.Sum() == 4); + + // + // Search + // + DecisionBuilder db = solver.MakePhase(x, Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, 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(); } - 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 Main(String[] args) { - Solve(); - } + public static void Main(String[] args) + { + Solve(); + } } diff --git a/examples/contrib/debruijn.cs b/examples/contrib/debruijn.cs index d0d75dbf40..0584d38262 100644 --- a/examples/contrib/debruijn.cs +++ b/examples/contrib/debruijn.cs @@ -16,170 +16,191 @@ using System; using Google.OrTools.ConstraintSolver; -public class DeBruijn { - /** - * - * 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; +public class DeBruijn +{ + /** + * + * 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; - } - - /** - * - * Implements "arbitrary" de Bruijn sequences. - * See http://www.hakank.org/or-tools/debruijn_binary.py - * - */ - private static void Solve(int bbase, int n, int m) { - Solver solver = new Solver("DeBruijn"); - - // Ensure that the number of each digit in bin_code is - // the same. Nice feature, but it can slow things down... - bool check_same_gcc = false; // true; - - // - // Decision variables - // - IntVar[] x = solver.MakeIntVarArray(m, 0, (int)Math.Pow(bbase, n) - 1, "x"); - IntVar[,] binary = solver.MakeIntVarMatrix(m, n, 0, bbase - 1, "binary"); - - // this is the de Bruijn sequence - IntVar[] bin_code = solver.MakeIntVarArray(m, 0, bbase - 1, "bin_code"); - - // occurences of each number in bin_code - IntVar[] gcc = solver.MakeIntVarArray(bbase, 0, m, "gcc"); - - // for the branching - IntVar[] all = new IntVar[2 * m + bbase]; - for (int i = 0; i < m; i++) { - all[i] = x[i]; - all[m + i] = bin_code[i]; - } - for (int i = 0; i < bbase; i++) { - all[2 * m + i] = gcc[i]; - } - - // - // Constraints - // - - solver.Add(x.AllDifferent()); - - // converts x <-> binary - for (int i = 0; i < m; i++) { - IntVar[] t = new IntVar[n]; - for (int j = 0; j < n; j++) { - t[j] = binary[i, j]; - } - solver.Add(ToNum(t, x[i], bbase)); - } - - // the de Bruijn condition: - // the first elements in binary[i] is the same as the last - // elements in binary[i-1] - for (int i = 1; i < m; i++) { - for (int j = 1; j < n; j++) { - solver.Add(binary[i - 1, j] == binary[i, j - 1]); - } - } - - // ... and around the corner - for (int j = 1; j < n; j++) { - solver.Add(binary[m - 1, j] == binary[0, j - 1]); - } - - // converts binary -> bin_code (de Bruijn sequence) - for (int i = 0; i < m; i++) { - solver.Add(bin_code[i] == binary[i, 0]); - } - - // extra: ensure that all the numbers in the de Bruijn sequence - // (bin_code) has the same occurrences (if check_same_gcc is True - // and mathematically possible) - solver.Add(bin_code.Distribute(gcc)); - if (check_same_gcc && m % bbase == 0) { - for (int i = 1; i < bbase; i++) { - solver.Add(gcc[i] == gcc[i - 1]); - } - } - - // symmetry breaking: - // the minimum value of x should be first - // solver.Add(x[0] == x.Min()); - - // - // Search - // - DecisionBuilder db = - solver.MakePhase(all, Solver.CHOOSE_MIN_SIZE_LOWEST_MAX, Solver.ASSIGN_MIN_VALUE); - - solver.NewSearch(db); - - while (solver.NextSolution()) { - Console.Write("x: "); - for (int i = 0; i < m; i++) { - Console.Write(x[i].Value() + " "); - } - - Console.Write("\nde Bruijn sequence:"); - for (int i = 0; i < m; i++) { - Console.Write(bin_code[i].Value() + " "); - } - - Console.Write("\ngcc: "); - for (int i = 0; i < bbase; i++) { - Console.Write(gcc[i].Value() + " "); - } - Console.WriteLine("\n"); - - // for debugging etc: show the full binary table - /* - Console.Write("binary:"); - for(int i = 0; i < m; i++) { - for(int j = 0; j < n; j++) { - Console.Write(binary[i][j].Value() + " "); + IntVar[] tmp = new IntVar[len]; + for (int i = 0; i < len; i++) + { + tmp[i] = (a[i] * (int)Math.Pow(bbase, (len - i - 1))).Var(); } - Console.WriteLine(); - } - Console.WriteLine(); - */ + return tmp.Sum() == num; } - 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()); + /** + * + * Implements "arbitrary" de Bruijn sequences. + * See http://www.hakank.org/or-tools/debruijn_binary.py + * + */ + private static void Solve(int bbase, int n, int m) + { + Solver solver = new Solver("DeBruijn"); - solver.EndSearch(); - } + // Ensure that the number of each digit in bin_code is + // the same. Nice feature, but it can slow things down... + bool check_same_gcc = false; // true; - public static void Main(String[] args) { - int bbase = 2; - int n = 3; - int m = 8; + // + // Decision variables + // + IntVar[] x = solver.MakeIntVarArray(m, 0, (int)Math.Pow(bbase, n) - 1, "x"); + IntVar[,] binary = solver.MakeIntVarMatrix(m, n, 0, bbase - 1, "binary"); - if (args.Length > 0) { - bbase = Convert.ToInt32(args[0]); + // this is the de Bruijn sequence + IntVar[] bin_code = solver.MakeIntVarArray(m, 0, bbase - 1, "bin_code"); + + // occurences of each number in bin_code + IntVar[] gcc = solver.MakeIntVarArray(bbase, 0, m, "gcc"); + + // for the branching + IntVar[] all = new IntVar[2 * m + bbase]; + for (int i = 0; i < m; i++) + { + all[i] = x[i]; + all[m + i] = bin_code[i]; + } + for (int i = 0; i < bbase; i++) + { + all[2 * m + i] = gcc[i]; + } + + // + // Constraints + // + + solver.Add(x.AllDifferent()); + + // converts x <-> binary + for (int i = 0; i < m; i++) + { + IntVar[] t = new IntVar[n]; + for (int j = 0; j < n; j++) + { + t[j] = binary[i, j]; + } + solver.Add(ToNum(t, x[i], bbase)); + } + + // the de Bruijn condition: + // the first elements in binary[i] is the same as the last + // elements in binary[i-1] + for (int i = 1; i < m; i++) + { + for (int j = 1; j < n; j++) + { + solver.Add(binary[i - 1, j] == binary[i, j - 1]); + } + } + + // ... and around the corner + for (int j = 1; j < n; j++) + { + solver.Add(binary[m - 1, j] == binary[0, j - 1]); + } + + // converts binary -> bin_code (de Bruijn sequence) + for (int i = 0; i < m; i++) + { + solver.Add(bin_code[i] == binary[i, 0]); + } + + // extra: ensure that all the numbers in the de Bruijn sequence + // (bin_code) has the same occurrences (if check_same_gcc is True + // and mathematically possible) + solver.Add(bin_code.Distribute(gcc)); + if (check_same_gcc && m % bbase == 0) + { + for (int i = 1; i < bbase; i++) + { + solver.Add(gcc[i] == gcc[i - 1]); + } + } + + // symmetry breaking: + // the minimum value of x should be first + // solver.Add(x[0] == x.Min()); + + // + // Search + // + DecisionBuilder db = solver.MakePhase(all, Solver.CHOOSE_MIN_SIZE_LOWEST_MAX, Solver.ASSIGN_MIN_VALUE); + + solver.NewSearch(db); + + while (solver.NextSolution()) + { + Console.Write("x: "); + for (int i = 0; i < m; i++) + { + Console.Write(x[i].Value() + " "); + } + + Console.Write("\nde Bruijn sequence:"); + for (int i = 0; i < m; i++) + { + Console.Write(bin_code[i].Value() + " "); + } + + Console.Write("\ngcc: "); + for (int i = 0; i < bbase; i++) + { + Console.Write(gcc[i].Value() + " "); + } + Console.WriteLine("\n"); + + // for debugging etc: show the full binary table + /* + Console.Write("binary:"); + for(int i = 0; i < m; i++) { + for(int j = 0; j < n; j++) { + Console.Write(binary[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(); } - if (args.Length > 1) { - n = Convert.ToInt32(args[1]); - } + public static void Main(String[] args) + { + int bbase = 2; + int n = 3; + int m = 8; - if (args.Length > 2) { - m = Convert.ToInt32(args[2]); - } + if (args.Length > 0) + { + bbase = Convert.ToInt32(args[0]); + } - Solve(bbase, n, m); - } + if (args.Length > 1) + { + n = Convert.ToInt32(args[1]); + } + + if (args.Length > 2) + { + m = Convert.ToInt32(args[2]); + } + + Solve(bbase, n, m); + } } diff --git a/examples/contrib/discrete_tomography.cs b/examples/contrib/discrete_tomography.cs index 4ca2a03eb8..144f45daad 100644 --- a/examples/contrib/discrete_tomography.cs +++ b/examples/contrib/discrete_tomography.cs @@ -20,179 +20,199 @@ using System.Linq; using System.Text.RegularExpressions; using Google.OrTools.ConstraintSolver; -public class DiscreteTomography { - // default problem - static int[] default_rowsums = { 0, 0, 8, 2, 6, 4, 5, 3, 7, 0, 0 }; - static int[] default_colsums = { 0, 0, 7, 1, 6, 3, 4, 5, 2, 7, 0, 0 }; +public class DiscreteTomography +{ + // default problem + static int[] default_rowsums = { 0, 0, 8, 2, 6, 4, 5, 3, 7, 0, 0 }; + static int[] default_colsums = { 0, 0, 7, 1, 6, 3, 4, 5, 2, 7, 0, 0 }; - static int[] rowsums2; - static int[] colsums2; + static int[] rowsums2; + static int[] colsums2; - /** - * - * 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"); + /** + * + * 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; + // + // 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.Write("rowsums: "); + for (int i = 0; i < r; i++) + { + Console.Write(rowsums[i] + " "); } - Console.WriteLine(); - } - Console.WriteLine(); + 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(); } - 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()); + /** + * + * Reads a discrete tomography file. + * File format: + * # a comment which is ignored + * % a comment which also is ignored + * rowsums separated by [,\s] + * colsums separated by [,\s] + * + * e.g. + * """ + * 0,0,8,2,6,4,5,3,7,0,0 + * 0,0,7,1,6,3,4,5,2,7,0,0 + * # comment + * % another comment + * """ + * + */ + private static void readFile(String file) + { + Console.WriteLine("readFile(" + file + ")"); - solver.EndSearch(); - } + TextReader inr = new StreamReader(file); + String str; + int lineCount = 0; + while ((str = inr.ReadLine()) != null && str.Length > 0) + { + str = str.Trim(); - /** - * - * Reads a discrete tomography file. - * File format: - * # a comment which is ignored - * % a comment which also is ignored - * rowsums separated by [,\s] - * colsums separated by [,\s] - * - * e.g. - * """ - * 0,0,8,2,6,4,5,3,7,0,0 - * 0,0,7,1,6,3,4,5,2,7,0,0 - * # comment - * % another comment - * """ - * - */ - private static void readFile(String file) { - Console.WriteLine("readFile(" + file + ")"); + // ignore comments + if (str.StartsWith("#") || str.StartsWith("%")) + { + continue; + } - TextReader inr = new StreamReader(file); - String str; - int lineCount = 0; - while ((str = inr.ReadLine()) != null && str.Length > 0) { - str = str.Trim(); + if (lineCount == 0) + { + rowsums2 = ConvLine(str); + } + else if (lineCount == 1) + { + colsums2 = ConvLine(str); + break; + } - // ignore comments - if (str.StartsWith("#") || str.StartsWith("%")) { - continue; - } + lineCount++; - if (lineCount == 0) { - rowsums2 = ConvLine(str); - } else if (lineCount == 1) { - colsums2 = ConvLine(str); - break; - } + } // end while - lineCount++; + inr.Close(); - } // end while + } // end readFile - inr.Close(); + private static int[] ConvLine(String str) + { + String[] tmp = Regex.Split(str, "[,\\s]+"); + int len = tmp.Length; + int[] sums = new int[len]; + for (int i = 0; i < len; i++) + { + sums[i] = Convert.ToInt32(tmp[i]); + } - } // end readFile - - private static int[] ConvLine(String str) { - String[] tmp = Regex.Split(str, "[,\\s]+"); - int len = tmp.Length; - int[] sums = new int[len]; - for (int i = 0; i < len; i++) { - sums[i] = Convert.ToInt32(tmp[i]); + return sums; } - return sums; - } - - public static void Main(String[] args) { - if (args.Length > 0) { - readFile(args[0]); - Solve(rowsums2, colsums2); - } else { - Solve(default_rowsums, default_colsums); + public static void Main(String[] args) + { + if (args.Length > 0) + { + readFile(args[0]); + Solve(rowsums2, colsums2); + } + else + { + Solve(default_rowsums, default_colsums); + } } - } } diff --git a/examples/contrib/divisible_by_9_through_1.cs b/examples/contrib/divisible_by_9_through_1.cs index f1a07340eb..76672ef418 100644 --- a/examples/contrib/divisible_by_9_through_1.cs +++ b/examples/contrib/divisible_by_9_through_1.cs @@ -19,157 +19,172 @@ using System.IO; using System.Text.RegularExpressions; using Google.OrTools.ConstraintSolver; -public class DivisibleBy9Through1 { - /** - * - * 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); +public class DivisibleBy9Through1 +{ + /** + * + * 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"); + IntVar d = solver.MakeIntVar(min_x, max_x, "d"); - // r >= 0 - solver.Add(r >= 0); + // r >= 0 + solver.Add(r >= 0); - // x*r >= 0 - solver.Add(x * r >= 0); + // x*r >= 0 + solver.Add(x * r >= 0); - // -abs(y) < r - solver.Add(-y.Abs() < r); + // -abs(y) < r + solver.Add(-y.Abs() < r); - // r < abs(y) - solver.Add(r < y.Abs()); + // r < abs(y) + solver.Add(r < y.Abs()); - // min_x <= d, i.e. d > min_x - solver.Add(d > min_x); + // min_x <= d, i.e. d > min_x + solver.Add(d > min_x); - // d <= max_x - solver.Add(d <= max_x); + // d <= max_x + solver.Add(d <= max_x); - // x == y*d+r - solver.Add(x - (y * d + r) == 0); - } - - /** - * - * ToNum(solver, a, num, base) - * - * channelling between the array a and the number num - * - */ - private static Constraint ToNum(IntVar[] a, IntVar num, int bbase) { - int len = a.Length; - - IntVar[] tmp = new IntVar[len]; - for (int i = 0; i < len; i++) { - tmp[i] = (a[i] * (int)Math.Pow(bbase, (len - i - 1))).Var(); - } - return tmp.Sum() == num; - } - - /** - * - * 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); + // x == y*d+r + solver.Add(x - (y * d + r) == 0); } - // - // Search - // - DecisionBuilder db = solver.MakePhase(x, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); + /** + * + * 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; - 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]); + IntVar[] tmp = new IntVar[len]; + for (int i = 0; i < len; i++) + { + tmp[i] = (a[i] * (int)Math.Pow(bbase, (len - i - 1))).Var(); } - Console.WriteLine("\n"); - } + return tmp.Sum() == num; } - 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()); + /** + * + * 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"); - solver.EndSearch(); - } + int m = (int)Math.Pow(bbase, (bbase - 1)) - 1; + int n = bbase - 1; - public static void Main(String[] args) { - int bbase = 10; - if (args.Length > 0) { - bbase = Convert.ToInt32(args[0]); - if (bbase > 12) { - // Though base = 12 has no solution... - Console.WriteLine("Sorry, max relevant base is 12. Setting base to 12."); - bbase = 10; - } + 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(); } - Solve(bbase); - } + public static void Main(String[] args) + { + int bbase = 10; + if (args.Length > 0) + { + bbase = Convert.ToInt32(args[0]); + if (bbase > 12) + { + // Though base = 12 has no solution... + Console.WriteLine("Sorry, max relevant base is 12. Setting base to 12."); + bbase = 10; + } + } + + Solve(bbase); + } } diff --git a/examples/contrib/dudeney.cs b/examples/contrib/dudeney.cs index e026672d26..96de4999a2 100644 --- a/examples/contrib/dudeney.cs +++ b/examples/contrib/dudeney.cs @@ -20,87 +20,92 @@ using System.Linq; using System.Text.RegularExpressions; using Google.OrTools.ConstraintSolver; -public class DudeneyNumbers { - private static Constraint ToNum(IntVar[] a, IntVar num, int bbase) { - int len = a.Length; +public class DudeneyNumbers +{ + 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; - } - - /** - * - * 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()); + 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; } - 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()); + /** + * + * 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"); - solver.EndSearch(); - } + // + // data + // + int n = 6; - public static void Main(String[] args) { - Solve(); - } + // + // 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(); + } + + public static void Main(String[] args) + { + Solve(); + } } diff --git a/examples/contrib/einav_puzzle2.cs b/examples/contrib/einav_puzzle2.cs index f902ebaa06..8ceeb855d3 100644 --- a/examples/contrib/einav_puzzle2.cs +++ b/examples/contrib/einav_puzzle2.cs @@ -19,183 +19,192 @@ using System.Collections.Generic; using System.Linq; using Google.OrTools.ConstraintSolver; -public class EinavPuzzle2 { - /** - * - * A programming puzzle from Einav. - * - * From - * "A programming puzzle from Einav" - * http://gcanyon.wordpress.com/2009/10/28/a-programming-puzzle-from-einav/ - * """ - * My friend Einav gave me this programming puzzle to work on. Given - * this array of positive and negative numbers: - * 33 30 -10 -6 18 7 -11 -23 6 - * ... - * -25 4 16 30 33 -23 -4 4 -23 - * - * You can flip the sign of entire rows and columns, as many of them - * as you like. The goal is to make all the rows and columns sum to positive - * numbers (or zero), and then to find the solution (there are more than one) - * that has the smallest overall sum. So for example, for this array: - * 33 30 -10 - * -16 19 9 - * -17 -12 -14 - * You could flip the sign for the bottom row to get this array: - * 33 30 -10 - * -16 19 9 - * 17 12 14 - * Now all the rows and columns have positive sums, and the overall total is - * 108. - * But you could instead flip the second and third columns, and the second - * row, to get this array: - * 33 -30 10 - * 16 19 9 - * -17 12 14 - * All the rows and columns still total positive, and the overall sum is just - * 66. So this solution is better (I don't know if it's the best) - * A pure brute force solution would have to try over 30 billion solutions. - * I wrote code to solve this in J. I'll post that separately. - * """ - * - * Note: - * This is a port of Larent Perrons's Python version of my own - * einav_puzzle.py. He removed some of the decision variables and made it more - * efficient. Thanks! - * - * Also see http://www.hakank.org/or-tools/einav_puzzle2.py - * - */ - private static void Solve() { - Solver solver = new Solver("EinavPuzzle2"); +public class EinavPuzzle2 +{ + /** + * + * A programming puzzle from Einav. + * + * From + * "A programming puzzle from Einav" + * http://gcanyon.wordpress.com/2009/10/28/a-programming-puzzle-from-einav/ + * """ + * My friend Einav gave me this programming puzzle to work on. Given + * this array of positive and negative numbers: + * 33 30 -10 -6 18 7 -11 -23 6 + * ... + * -25 4 16 30 33 -23 -4 4 -23 + * + * You can flip the sign of entire rows and columns, as many of them + * as you like. The goal is to make all the rows and columns sum to positive + * numbers (or zero), and then to find the solution (there are more than one) + * that has the smallest overall sum. So for example, for this array: + * 33 30 -10 + * -16 19 9 + * -17 -12 -14 + * You could flip the sign for the bottom row to get this array: + * 33 30 -10 + * -16 19 9 + * 17 12 14 + * Now all the rows and columns have positive sums, and the overall total is + * 108. + * But you could instead flip the second and third columns, and the second + * row, to get this array: + * 33 -30 10 + * 16 19 9 + * -17 12 14 + * All the rows and columns still total positive, and the overall sum is just + * 66. So this solution is better (I don't know if it's the best) + * A pure brute force solution would have to try over 30 billion solutions. + * I wrote code to solve this in J. I'll post that separately. + * """ + * + * Note: + * This is a port of Larent Perrons's Python version of my own + * einav_puzzle.py. He removed some of the decision variables and made it more + * efficient. Thanks! + * + * Also see http://www.hakank.org/or-tools/einav_puzzle2.py + * + */ + private static void Solve() + { + Solver solver = new Solver("EinavPuzzle2"); - // - // Data - // + // + // Data + // - // Small problem - // int rows = 3; - // int cols = 3; - // int[,] data = { - // { 33, 30, -10}, - // {-16, 19, 9}, - // {-17, -12, -14} - // }; + // Small problem + // int rows = 3; + // int cols = 3; + // int[,] data = { + // { 33, 30, -10}, + // {-16, 19, 9}, + // {-17, -12, -14} + // }; - // Full problem - int rows = 27; - int cols = 9; - int[,] data = { - { 33, 30, 10, -6, 18, -7, -11, 23, -6 }, { 16, -19, 9, -26, -8, -19, -8, -21, -14 }, - { 17, 12, -14, 31, -30, 13, -13, 19, 16 }, { -6, -11, 1, 17, -12, -4, -7, 14, -21 }, - { 18, -31, 34, -22, 17, -19, 20, 24, 6 }, { 33, -18, 17, -15, 31, -5, 3, 27, -3 }, - { -18, -20, -18, 31, 6, 4, -2, -12, 24 }, { 27, 14, 4, -29, -3, 5, -29, 8, -12 }, - { -15, -7, -23, 23, -9, -8, 6, 8, -12 }, { 33, -23, -19, -4, -8, -7, 11, -12, 31 }, - { -20, 19, -15, -30, 11, 32, 7, 14, -5 }, { -23, 18, -32, -2, -31, -7, 8, 24, 16 }, - { 32, -4, -10, -14, -6, -1, 0, 23, 23 }, { 25, 0, -23, 22, 12, 28, -27, 15, 4 }, - { -30, -13, -16, -3, -3, -32, -3, 27, -31 }, { 22, 1, 26, 4, -2, -13, 26, 17, 14 }, - { -9, -18, 3, -20, -27, -32, -11, 27, 13 }, { -17, 33, -7, 19, -32, 13, -31, -2, -24 }, - { -31, 27, -31, -29, 15, 2, 29, -15, 33 }, { -18, -23, 15, 28, 0, 30, -4, 12, -32 }, - { -3, 34, 27, -25, -18, 26, 1, 34, 26 }, { -21, -31, -10, -13, -30, -17, -12, -26, 31 }, - { 23, -31, -19, 21, -17, -10, 2, -23, 23 }, { -3, 6, 0, -3, -32, 0, -10, -25, 14 }, - { -19, 9, 14, -27, 20, 15, -5, -27, 18 }, { 11, -6, 24, 7, -17, 26, 20, -31, -25 }, - { -25, 4, -16, 30, 33, 23, -4, -4, 23 } - }; + // Full problem + int rows = 27; + int cols = 9; + int[,] data = { { 33, 30, 10, -6, 18, -7, -11, 23, -6 }, { 16, -19, 9, -26, -8, -19, -8, -21, -14 }, + { 17, 12, -14, 31, -30, 13, -13, 19, 16 }, { -6, -11, 1, 17, -12, -4, -7, 14, -21 }, + { 18, -31, 34, -22, 17, -19, 20, 24, 6 }, { 33, -18, 17, -15, 31, -5, 3, 27, -3 }, + { -18, -20, -18, 31, 6, 4, -2, -12, 24 }, { 27, 14, 4, -29, -3, 5, -29, 8, -12 }, + { -15, -7, -23, 23, -9, -8, 6, 8, -12 }, { 33, -23, -19, -4, -8, -7, 11, -12, 31 }, + { -20, 19, -15, -30, 11, 32, 7, 14, -5 }, { -23, 18, -32, -2, -31, -7, 8, 24, 16 }, + { 32, -4, -10, -14, -6, -1, 0, 23, 23 }, { 25, 0, -23, 22, 12, 28, -27, 15, 4 }, + { -30, -13, -16, -3, -3, -32, -3, 27, -31 }, { 22, 1, 26, 4, -2, -13, 26, 17, 14 }, + { -9, -18, 3, -20, -27, -32, -11, 27, 13 }, { -17, 33, -7, 19, -32, 13, -31, -2, -24 }, + { -31, 27, -31, -29, 15, 2, 29, -15, 33 }, { -18, -23, 15, 28, 0, 30, -4, 12, -32 }, + { -3, 34, 27, -25, -18, 26, 1, 34, 26 }, { -21, -31, -10, -13, -30, -17, -12, -26, 31 }, + { 23, -31, -19, 21, -17, -10, 2, -23, 23 }, { -3, 6, 0, -3, -32, 0, -10, -25, 14 }, + { -19, 9, 14, -27, 20, 15, -5, -27, 18 }, { 11, -6, 24, 7, -17, 26, 20, -31, -25 }, + { -25, 4, -16, 30, 33, 23, -4, -4, 23 } }; - IEnumerable ROWS = Enumerable.Range(0, rows); - IEnumerable COLS = Enumerable.Range(0, cols); + IEnumerable ROWS = Enumerable.Range(0, rows); + IEnumerable COLS = Enumerable.Range(0, cols); - // - // Decision variables - // - IntVar[,] x = solver.MakeIntVarMatrix(rows, cols, -100, 100, "x"); - IntVar[] x_flat = x.Flatten(); + // + // Decision variables + // + IntVar[,] x = solver.MakeIntVarMatrix(rows, cols, -100, 100, "x"); + IntVar[] x_flat = x.Flatten(); - int[] signs_domain = { -1, 1 }; - // This don't work at the moment... - IntVar[] row_signs = solver.MakeIntVarArray(rows, signs_domain, "row_signs"); - IntVar[] col_signs = solver.MakeIntVarArray(cols, signs_domain, "col_signs"); + int[] signs_domain = { -1, 1 }; + // This don't work at the moment... + IntVar[] row_signs = solver.MakeIntVarArray(rows, signs_domain, "row_signs"); + IntVar[] col_signs = solver.MakeIntVarArray(cols, signs_domain, "col_signs"); - // To optimize - IntVar total_sum = x_flat.Sum().VarWithName("total_sum"); + // To optimize + IntVar total_sum = x_flat.Sum().VarWithName("total_sum"); - // - // Constraints - // - foreach (int i in ROWS) { - foreach (int j in COLS) { - solver.Add(x[i, j] == data[i, j] * row_signs[i] * col_signs[j]); - } - } - - // row sums - IntVar[] row_sums = - (from i in ROWS select(from j in COLS select x[i, j]).ToArray().Sum().Var()).ToArray(); - - foreach (int i in ROWS) { - row_sums[i].SetMin(0); - } - - // col sums - IntVar[] col_sums = - (from j in COLS select(from i in ROWS select x[i, j]).ToArray().Sum().Var()).ToArray(); - - foreach (int j in COLS) { - col_sums[j].SetMin(0); - } - - // - // Objective - // - OptimizeVar obj = total_sum.Minimize(1); - - // - // Search - // - DecisionBuilder db = - solver.MakePhase(col_signs.Concat(row_signs).ToArray(), Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, - Solver.ASSIGN_MAX_VALUE); - - solver.NewSearch(db, obj); - - while (solver.NextSolution()) { - Console.WriteLine("Sum: {0}", total_sum.Value()); - Console.Write("row_sums: "); - foreach (int i in ROWS) { - Console.Write(row_sums[i].Value() + " "); - } - Console.Write("\nrow_signs: "); - foreach (int i in ROWS) { - Console.Write(row_signs[i].Value() + " "); - } - - Console.Write("\ncol_sums: "); - foreach (int j in COLS) { - Console.Write(col_sums[j].Value() + " "); - } - Console.Write("\ncol_signs: "); - foreach (int j in COLS) { - Console.Write(col_signs[j].Value() + " "); - } - Console.WriteLine("\n"); - foreach (int i in ROWS) { - foreach (int j in COLS) { - Console.Write("{0,3} ", x[i, j].Value()); + // + // Constraints + // + foreach (int i in ROWS) + { + foreach (int j in COLS) + { + solver.Add(x[i, j] == data[i, j] * row_signs[i] * col_signs[j]); + } } - Console.WriteLine(); - } - Console.WriteLine(); + + // row sums + IntVar[] row_sums = (from i in ROWS select(from j in COLS select x[i, j]).ToArray().Sum().Var()).ToArray(); + + foreach (int i in ROWS) + { + row_sums[i].SetMin(0); + } + + // col sums + IntVar[] col_sums = (from j in COLS select(from i in ROWS select x[i, j]).ToArray().Sum().Var()).ToArray(); + + foreach (int j in COLS) + { + col_sums[j].SetMin(0); + } + + // + // Objective + // + OptimizeVar obj = total_sum.Minimize(1); + + // + // Search + // + DecisionBuilder db = solver.MakePhase(col_signs.Concat(row_signs).ToArray(), Solver.CHOOSE_MIN_SIZE_LOWEST_MIN, + Solver.ASSIGN_MAX_VALUE); + + solver.NewSearch(db, obj); + + while (solver.NextSolution()) + { + Console.WriteLine("Sum: {0}", total_sum.Value()); + Console.Write("row_sums: "); + foreach (int i in ROWS) + { + Console.Write(row_sums[i].Value() + " "); + } + Console.Write("\nrow_signs: "); + foreach (int i in ROWS) + { + Console.Write(row_signs[i].Value() + " "); + } + + Console.Write("\ncol_sums: "); + foreach (int j in COLS) + { + Console.Write(col_sums[j].Value() + " "); + } + Console.Write("\ncol_signs: "); + foreach (int j in COLS) + { + Console.Write(col_signs[j].Value() + " "); + } + Console.WriteLine("\n"); + foreach (int i in ROWS) + { + foreach (int j in COLS) + { + Console.Write("{0,3} ", x[i, j].Value()); + } + Console.WriteLine(); + } + Console.WriteLine(); + } + + Console.WriteLine("\nSolutions: {0}", solver.Solutions()); + Console.WriteLine("WallTime: {0}ms", solver.WallTime()); + Console.WriteLine("Failures: {0}", solver.Failures()); + Console.WriteLine("Branches: {0} ", solver.Branches()); + + solver.EndSearch(); } - 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 Main(String[] args) { - Solve(); - } + public static void Main(String[] args) + { + Solve(); + } } diff --git a/examples/contrib/eq10.cs b/examples/contrib/eq10.cs index 643cbc270a..e6cd1e15d2 100644 --- a/examples/contrib/eq10.cs +++ b/examples/contrib/eq10.cs @@ -16,90 +16,95 @@ using System; using Google.OrTools.ConstraintSolver; -public class Eq10 { - /** - * - * Eq 10 in Google CP Solver. - * - * Standard benchmark problem. - * - * Also see http://hakank.org/or-tools/eq10.py - * - */ - private static void Solve() { - Solver solver = new Solver("Eq10"); +public class Eq10 +{ + /** + * + * Eq 10 in Google CP Solver. + * + * Standard benchmark problem. + * + * Also see http://hakank.org/or-tools/eq10.py + * + */ + private static void Solve() + { + Solver solver = new Solver("Eq10"); - int n = 7; + int n = 7; - // - // Decision variables - // - IntVar X1 = solver.MakeIntVar(0, 10, "X1"); - IntVar X2 = solver.MakeIntVar(0, 10, "X2"); - IntVar X3 = solver.MakeIntVar(0, 10, "X3"); - IntVar X4 = solver.MakeIntVar(0, 10, "X4"); - IntVar X5 = solver.MakeIntVar(0, 10, "X5"); - IntVar X6 = solver.MakeIntVar(0, 10, "X6"); - IntVar X7 = solver.MakeIntVar(0, 10, "X7"); + // + // Decision variables + // + IntVar X1 = solver.MakeIntVar(0, 10, "X1"); + IntVar X2 = solver.MakeIntVar(0, 10, "X2"); + IntVar X3 = solver.MakeIntVar(0, 10, "X3"); + IntVar X4 = solver.MakeIntVar(0, 10, "X4"); + IntVar X5 = solver.MakeIntVar(0, 10, "X5"); + IntVar X6 = solver.MakeIntVar(0, 10, "X6"); + IntVar X7 = solver.MakeIntVar(0, 10, "X7"); - IntVar[] X = { X1, X2, X3, X4, X5, X6, X7 }; + IntVar[] X = { X1, X2, X3, X4, X5, X6, X7 }; - // - // Constraints - // - solver.Add(0 + 98527 * X1 + 34588 * X2 + 5872 * X3 + 59422 * X5 + 65159 * X7 == - 1547604 + 30704 * X4 + 29649 * X6); + // + // Constraints + // + solver.Add(0 + 98527 * X1 + 34588 * X2 + 5872 * X3 + 59422 * X5 + 65159 * X7 == + 1547604 + 30704 * X4 + 29649 * X6); - solver.Add(0 + 98957 * X2 + 83634 * X3 + 69966 * X4 + 62038 * X5 + 37164 * X6 + 85413 * X7 == - 1823553 + 93989 * X1); + solver.Add(0 + 98957 * X2 + 83634 * X3 + 69966 * X4 + 62038 * X5 + 37164 * X6 + 85413 * X7 == + 1823553 + 93989 * X1); - solver.Add(900032 + 10949 * X1 + 77761 * X2 + 67052 * X5 == - 0 + 80197 * X3 + 61944 * X4 + 92964 * X6 + 44550 * X7); + solver.Add(900032 + 10949 * X1 + 77761 * X2 + 67052 * X5 == + 0 + 80197 * X3 + 61944 * X4 + 92964 * X6 + 44550 * X7); - solver.Add(0 + 73947 * X1 + 84391 * X3 + 81310 * X5 == - 1164380 + 96253 * X2 + 44247 * X4 + 70582 * X6 + 33054 * X7); + solver.Add(0 + 73947 * X1 + 84391 * X3 + 81310 * X5 == + 1164380 + 96253 * X2 + 44247 * X4 + 70582 * X6 + 33054 * X7); - solver.Add(0 + 13057 * X3 + 42253 * X4 + 77527 * X5 + 96552 * X7 == - 1185471 + 60152 * X1 + 21103 * X2 + 97932 * X6); + solver.Add(0 + 13057 * X3 + 42253 * X4 + 77527 * X5 + 96552 * X7 == + 1185471 + 60152 * X1 + 21103 * X2 + 97932 * X6); - solver.Add(1394152 + 66920 * X1 + 55679 * X4 == - 0 + 64234 * X2 + 65337 * X3 + 45581 * X5 + 67707 * X6 + 98038 * X7); + solver.Add(1394152 + 66920 * X1 + 55679 * X4 == + 0 + 64234 * X2 + 65337 * X3 + 45581 * X5 + 67707 * X6 + 98038 * X7); - solver.Add(0 + 68550 * X1 + 27886 * X2 + 31716 * X3 + 73597 * X4 + 38835 * X7 == - 279091 + 88963 * X5 + 76391 * X6); + solver.Add(0 + 68550 * X1 + 27886 * X2 + 31716 * X3 + 73597 * X4 + 38835 * X7 == + 279091 + 88963 * X5 + 76391 * X6); - solver.Add(0 + 76132 * X2 + 71860 * X3 + 22770 * X4 + 68211 * X5 + 78587 * X6 == - 480923 + 48224 * X1 + 82817 * X7); + solver.Add(0 + 76132 * X2 + 71860 * X3 + 22770 * X4 + 68211 * X5 + 78587 * X6 == + 480923 + 48224 * X1 + 82817 * X7); - solver.Add(519878 + 94198 * X2 + 87234 * X3 + 37498 * X4 == - 0 + 71583 * X1 + 25728 * X5 + 25495 * X6 + 70023 * X7); + solver.Add(519878 + 94198 * X2 + 87234 * X3 + 37498 * X4 == + 0 + 71583 * X1 + 25728 * X5 + 25495 * X6 + 70023 * X7); - solver.Add(361921 + 78693 * X1 + 38592 * X5 + 38478 * X6 == - 0 + 94129 * X2 + 43188 * X3 + 82528 * X4 + 69025 * X7); + solver.Add(361921 + 78693 * X1 + 38592 * X5 + 38478 * X6 == + 0 + 94129 * X2 + 43188 * X3 + 82528 * X4 + 69025 * X7); - // - // Search - // - DecisionBuilder db = solver.MakePhase(X, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); + // + // Search + // + DecisionBuilder db = solver.MakePhase(X, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); - solver.NewSearch(db); + solver.NewSearch(db); - while (solver.NextSolution()) { - for (int i = 0; i < n; i++) { - Console.Write(X[i].ToString() + " "); - } - Console.WriteLine(); + while (solver.NextSolution()) + { + for (int i = 0; i < n; i++) + { + Console.Write(X[i].ToString() + " "); + } + 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(); } - Console.WriteLine("\nSolutions: " + solver.Solutions()); - Console.WriteLine("WallTime: " + solver.WallTime() + "ms "); - Console.WriteLine("Failures: " + solver.Failures()); - Console.WriteLine("Branches: " + solver.Branches()); - - solver.EndSearch(); - } - - public static void Main(String[] args) { - Solve(); - } + public static void Main(String[] args) + { + Solve(); + } } diff --git a/examples/contrib/eq20.cs b/examples/contrib/eq20.cs index 33228b1c7c..bf2bab5ffe 100644 --- a/examples/contrib/eq20.cs +++ b/examples/contrib/eq20.cs @@ -16,121 +16,99 @@ using System; using Google.OrTools.ConstraintSolver; -public class Eq20 { - /** - * - * Eq 20 in Google CP Solver. - * - * Standard benchmark problem. - * - * Also see http://hakank.org/or-tools/eq20.py - * - */ - private static void Solve() { - Solver solver = new Solver("Eq20"); +public class Eq20 +{ + /** + * + * Eq 20 in Google CP Solver. + * + * Standard benchmark problem. + * + * Also see http://hakank.org/or-tools/eq20.py + * + */ + private static void Solve() + { + Solver solver = new Solver("Eq20"); - int n = 7; + int n = 7; - // - // Decision variables - // - IntVar X0 = solver.MakeIntVar(0, 10, "X0"); - IntVar X1 = solver.MakeIntVar(0, 10, "X1"); - IntVar X2 = solver.MakeIntVar(0, 10, "X2"); - IntVar X3 = solver.MakeIntVar(0, 10, "X3"); - IntVar X4 = solver.MakeIntVar(0, 10, "X4"); - IntVar X5 = solver.MakeIntVar(0, 10, "X5"); - IntVar X6 = solver.MakeIntVar(0, 10, "X6"); + // + // Decision variables + // + IntVar X0 = solver.MakeIntVar(0, 10, "X0"); + IntVar X1 = solver.MakeIntVar(0, 10, "X1"); + IntVar X2 = solver.MakeIntVar(0, 10, "X2"); + IntVar X3 = solver.MakeIntVar(0, 10, "X3"); + IntVar X4 = solver.MakeIntVar(0, 10, "X4"); + IntVar X5 = solver.MakeIntVar(0, 10, "X5"); + IntVar X6 = solver.MakeIntVar(0, 10, "X6"); - IntVar[] X = { X0, X1, X2, X3, X4, X5, X6 }; + IntVar[] X = { X0, X1, X2, X3, X4, X5, X6 }; - // - // Constraints - // - solver.Add(-76706 * X0 + 98205 * X1 + 23445 * X2 + 67921 * X3 + 24111 * X4 + -48614 * X5 + - -41906 * X6 == - 821228); - solver.Add(87059 * X0 + -29101 * X1 + -5513 * X2 + -21219 * X3 + 22128 * X4 + 7276 * X5 + - 57308 * X6 == - 22167); - solver.Add(-60113 * X0 + 29475 * X1 + 34421 * X2 + -76870 * X3 + 62646 * X4 + 29278 * X5 + - -15212 * X6 == - 251591); - solver.Add(49149 * X0 + 52871 * X1 + -7132 * X2 + 56728 * X3 + -33576 * X4 + -49530 * X5 + - -62089 * X6 == - 146074); - solver.Add(-10343 * X0 + 87758 * X1 + -11782 * X2 + 19346 * X3 + 70072 * X4 + -36991 * X5 + - 44529 * X6 == - 740061); - solver.Add(85176 * X0 + -95332 * X1 + -1268 * X2 + 57898 * X3 + 15883 * X4 + 50547 * X5 + - 83287 * X6 == - 373854); - solver.Add(-85698 * X0 + 29958 * X1 + 57308 * X2 + 48789 * X3 + -78219 * X4 + 4657 * X5 + - 34539 * X6 == - 249912); - solver.Add(-67456 * X0 + 84750 * X1 + -51553 * X2 + 21239 * X3 + 81675 * X4 + -99395 * X5 + - -4254 * X6 == - 277271); - solver.Add(94016 * X0 + -82071 * X1 + 35961 * X2 + 66597 * X3 + -30705 * X4 + -44404 * X5 + - -38304 * X6 == - 25334); - solver.Add(-60301 * X0 + 31227 * X1 + 93951 * X2 + 73889 * X3 + 81526 * X4 + -72702 * X5 + - 68026 * X6 == - 1410723); - solver.Add(-16835 * X0 + 47385 * X1 + 97715 * X2 + -12640 * X3 + 69028 * X4 + 76212 * X5 + - -81102 * X6 == - 1244857); - solver.Add(-43277 * X0 + 43525 * X1 + 92298 * X2 + 58630 * X3 + 92590 * X4 + -9372 * X5 + - -60227 * X6 == - 1503588); - solver.Add(-64919 * X0 + 80460 * X1 + 90840 * X2 + -59624 * X3 + -75542 * X4 + 25145 * X5 + - -47935 * X6 == - 18465); - solver.Add(-45086 * X0 + 51830 * X1 + -4578 * X2 + 96120 * X3 + 21231 * X4 + 97919 * X5 + - 65651 * X6 == - 1198280); - solver.Add(85268 * X0 + 54180 * X1 + -18810 * X2 + -48219 * X3 + 6013 * X4 + 78169 * X5 + - -79785 * X6 == - 90614); - solver.Add(8874 * X0 + -58412 * X1 + 73947 * X2 + 17147 * X3 + 62335 * X4 + 16005 * X5 + - 8632 * X6 == - 752447); - solver.Add(71202 * X0 + -11119 * X1 + 73017 * X2 + -38875 * X3 + -14413 * X4 + -29234 * X5 + - 72370 * X6 == - 129768); - solver.Add(1671 * X0 + -34121 * X1 + 10763 * X2 + 80609 * X3 + 42532 * X4 + 93520 * X5 + - -33488 * X6 == - 915683); - solver.Add(51637 * X0 + 67761 * X1 + 95951 * X2 + 3834 * X3 + -96722 * X4 + 59190 * X5 + - 15280 * X6 == - 533909); - solver.Add(-16105 * X0 + 62397 * X1 + -6704 * X2 + 43340 * X3 + 95100 * X4 + -68610 * X5 + - 58301 * X6 == - 876370); + // + // Constraints + // + solver.Add(-76706 * X0 + 98205 * X1 + 23445 * X2 + 67921 * X3 + 24111 * X4 + -48614 * X5 + -41906 * X6 == + 821228); + solver.Add(87059 * X0 + -29101 * X1 + -5513 * X2 + -21219 * X3 + 22128 * X4 + 7276 * X5 + 57308 * X6 == 22167); + solver.Add(-60113 * X0 + 29475 * X1 + 34421 * X2 + -76870 * X3 + 62646 * X4 + 29278 * X5 + -15212 * X6 == + 251591); + solver.Add(49149 * X0 + 52871 * X1 + -7132 * X2 + 56728 * X3 + -33576 * X4 + -49530 * X5 + -62089 * X6 == + 146074); + solver.Add(-10343 * X0 + 87758 * X1 + -11782 * X2 + 19346 * X3 + 70072 * X4 + -36991 * X5 + 44529 * X6 == + 740061); + solver.Add(85176 * X0 + -95332 * X1 + -1268 * X2 + 57898 * X3 + 15883 * X4 + 50547 * X5 + 83287 * X6 == 373854); + solver.Add(-85698 * X0 + 29958 * X1 + 57308 * X2 + 48789 * X3 + -78219 * X4 + 4657 * X5 + 34539 * X6 == 249912); + solver.Add(-67456 * X0 + 84750 * X1 + -51553 * X2 + 21239 * X3 + 81675 * X4 + -99395 * X5 + -4254 * X6 == + 277271); + solver.Add(94016 * X0 + -82071 * X1 + 35961 * X2 + 66597 * X3 + -30705 * X4 + -44404 * X5 + -38304 * X6 == + 25334); + solver.Add(-60301 * X0 + 31227 * X1 + 93951 * X2 + 73889 * X3 + 81526 * X4 + -72702 * X5 + 68026 * X6 == + 1410723); + solver.Add(-16835 * X0 + 47385 * X1 + 97715 * X2 + -12640 * X3 + 69028 * X4 + 76212 * X5 + -81102 * X6 == + 1244857); + solver.Add(-43277 * X0 + 43525 * X1 + 92298 * X2 + 58630 * X3 + 92590 * X4 + -9372 * X5 + -60227 * X6 == + 1503588); + solver.Add(-64919 * X0 + 80460 * X1 + 90840 * X2 + -59624 * X3 + -75542 * X4 + 25145 * X5 + -47935 * X6 == + 18465); + solver.Add(-45086 * X0 + 51830 * X1 + -4578 * X2 + 96120 * X3 + 21231 * X4 + 97919 * X5 + 65651 * X6 == + 1198280); + solver.Add(85268 * X0 + 54180 * X1 + -18810 * X2 + -48219 * X3 + 6013 * X4 + 78169 * X5 + -79785 * X6 == 90614); + solver.Add(8874 * X0 + -58412 * X1 + 73947 * X2 + 17147 * X3 + 62335 * X4 + 16005 * X5 + 8632 * X6 == 752447); + solver.Add(71202 * X0 + -11119 * X1 + 73017 * X2 + -38875 * X3 + -14413 * X4 + -29234 * X5 + 72370 * X6 == + 129768); + solver.Add(1671 * X0 + -34121 * X1 + 10763 * X2 + 80609 * X3 + 42532 * X4 + 93520 * X5 + -33488 * X6 == 915683); + solver.Add(51637 * X0 + 67761 * X1 + 95951 * X2 + 3834 * X3 + -96722 * X4 + 59190 * X5 + 15280 * X6 == 533909); + solver.Add(-16105 * X0 + 62397 * X1 + -6704 * X2 + 43340 * X3 + 95100 * X4 + -68610 * X5 + 58301 * X6 == + 876370); - // - // Search - // - DecisionBuilder db = solver.MakePhase(X, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); + // + // Search + // + DecisionBuilder db = solver.MakePhase(X, Solver.INT_VAR_DEFAULT, Solver.INT_VALUE_DEFAULT); - solver.NewSearch(db); + solver.NewSearch(db); - while (solver.NextSolution()) { - for (int i = 0; i < n; i++) { - Console.Write(X[i].ToString() + " "); - } - Console.WriteLine(); + while (solver.NextSolution()) + { + for (int i = 0; i < n; i++) + { + Console.Write(X[i].ToString() + " "); + } + 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(); } - Console.WriteLine("\nSolutions: " + solver.Solutions()); - Console.WriteLine("WallTime: " + solver.WallTime() + "ms "); - Console.WriteLine("Failures: " + solver.Failures()); - Console.WriteLine("Branches: " + solver.Branches()); - - solver.EndSearch(); - } - - public static void Main(String[] args) { - Solve(); - } + public static void Main(String[] args) + { + Solve(); + } } diff --git a/examples/contrib/fill_a_pix.cs b/examples/contrib/fill_a_pix.cs index f95f7026e9..7c2acd3bc8 100644 --- a/examples/contrib/fill_a_pix.cs +++ b/examples/contrib/fill_a_pix.cs @@ -20,207 +20,230 @@ using System.Linq; using System.Text.RegularExpressions; using Google.OrTools.ConstraintSolver; -public class FillAPix { - static int X = -1; - - // - // Default problem. - // Puzzle 1 from - // http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/rules - - // - static int default_n = 10; - static int[,] default_puzzle = { - { X, X, X, X, X, X, X, X, 0, X }, { X, 8, 8, X, 2, X, 0, X, X, X }, - { 5, X, 8, X, X, X, X, X, X, X }, { X, X, X, X, X, 2, X, X, X, 2 }, - { 1, X, X, X, 4, 5, 6, X, X, X }, { X, 0, X, X, X, 7, 9, X, X, 6 }, - { X, X, X, 6, X, X, 9, X, X, 6 }, { X, X, 6, 6, 8, 7, 8, 7, X, 5 }, - { X, 4, X, 6, 6, 6, X, 6, X, 4 }, { X, X, X, X, X, X, 3, X, X, X } - }; - - // for the actual problem - static int n; - static int[,] puzzle; - - /** - * - * 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"); +public class FillAPix +{ + static int X = -1; // - // 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(); + // Default problem. + // Puzzle 1 from + // http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/rules // - // Decision variables - // - IntVar[,] pict = solver.MakeIntVarMatrix(n, n, 0, 1, "pict"); - IntVar[] pict_flat = pict.Flatten(); // for branching + static int default_n = 10; + static int[,] default_puzzle = { { X, X, X, X, X, X, X, X, 0, X }, { X, 8, 8, X, 2, X, 0, X, X, X }, + { 5, X, 8, X, X, X, X, X, X, X }, { X, X, X, X, X, 2, X, X, X, 2 }, + { 1, X, X, X, 4, 5, 6, X, X, X }, { X, 0, X, X, X, 7, 9, X, X, 6 }, + { X, X, X, 6, X, X, 9, X, X, 6 }, { X, X, 6, 6, 8, 7, 8, 7, X, 5 }, + { X, 4, X, 6, 6, 6, X, 6, X, 4 }, { X, X, X, X, X, X, 3, X, X, X } }; - // - // 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