static void Main() { // [START solver] LinearSumAssignment assignment = new LinearSumAssignment(); // [END solver] // [START data] int[,] costs = { { 90, 76, 75, 70 }, { 35, 85, 55, 65 }, { 125, 95, 90, 105 }, { 45, 110, 95, 115 }, }; int numWorkers = 4; int[] allWorkers = Enumerable.Range(0, numWorkers).ToArray(); int numTasks = 4; int[] allTasks = Enumerable.Range(0, numTasks).ToArray(); // [END data] // [START constraints] // Add each arc. foreach (int w in allWorkers) { foreach (int t in allTasks) { if (costs[w, t] != 0) { assignment.AddArcWithCost(w, t, costs[w, t]); } } } // [END constraints] // [START solve] LinearSumAssignment.Status status = assignment.Solve(); // [END solve] // [START print_solution] if (status == LinearSumAssignment.Status.OPTIMAL) { Console.WriteLine($"Total cost: {assignment.OptimalCost()}."); foreach (int worker in allWorkers) { Console.WriteLine($"Worker {worker} assigned to task {assignment.RightMate(worker)}. " + $"Cost: {assignment.AssignmentCost(worker)}."); } } else { Console.WriteLine("Solving the linear assignment problem failed."); Console.WriteLine($"Solver status: {status}."); } // [END print_solution] }
public override Decision Next(Solver solver) { int large = 100000; int number_of_variables = vars_.Length; long last_slot = last_slot_var_.Max(); // Lets build a bipartite graph with equal number of nodes left and right. // Variables will be on the left, slots on the right. // We will add dummy variables when needed. // Arcs will have a cost x is slot x is possible for a variable, a large // number otherwise. For dummy variables, the cost will be 0 always. LinearSumAssignment matching = new LinearSumAssignment(); for (int speaker = 0; speaker < number_of_variables; ++speaker) { IntVar var = vars_[speaker]; for (int value = first_slot_; value <= last_slot; ++value) { if (var.Contains(value)) { matching.AddArcWithCost(speaker, value - first_slot_, value); } else { matching.AddArcWithCost(speaker, value - first_slot_, large); } } } // The Matching algorithms expect the same number of left and right nodes. // So we fill the rest with dense zero-cost arcs. for (int dummy = number_of_variables; dummy <= last_slot - first_slot_; ++dummy) { for (int value = first_slot_; value <= last_slot; ++value) { matching.AddArcWithCost(dummy, value - first_slot_, 0); } } if (matching.Solve() == LinearSumAssignment.OPTIMAL && matching.OptimalCost() < large) // No violated arcs. { for (int speaker = 0; speaker < number_of_variables; ++speaker) { vars_[speaker].SetValue(matching.RightMate(speaker) + first_slot_); } } else { solver.Fail(); } return(null); }
public override Decision Next(Solver solver) { int large = 100000; int number_of_variables = vars_.Length; long last_slot = last_slot_var_.Max(); // Lets build a bipartite graph with equal number of nodes left and right. // Variables will be on the left, slots on the right. // We will add dummy variables when needed. // Arcs will have a cost x is slot x is possible for a variable, a large // number otherwise. For dummy variables, the cost will be 0 always. LinearSumAssignment matching = new LinearSumAssignment(); for (int speaker = 0; speaker < number_of_variables; ++speaker) { IntVar var = vars_[speaker]; for (int value = first_slot_; value <= last_slot; ++value) { if (var.Contains(value)) { matching.AddArcWithCost(speaker, value - first_slot_, value); } else { matching.AddArcWithCost(speaker, value - first_slot_, large); } } } // The Matching algorithms expect the same number of left and right nodes. // So we fill the rest with dense zero-cost arcs. for (int dummy = number_of_variables; dummy <= last_slot - first_slot_; ++dummy) { for (int value = first_slot_; value <= last_slot; ++value) { matching.AddArcWithCost(dummy, value - first_slot_, 0); } } if (matching.Solve() == LinearSumAssignment.OPTIMAL && matching.OptimalCost() < large) // No violated arcs. { for (int speaker = 0; speaker < number_of_variables; ++speaker) { vars_[speaker].SetValue(matching.RightMate(speaker) + first_slot_); } } else { solver.Fail(); } return null; }
private static void Run(int[][] costs) { var botsCount = costs.Length; var tasksCount = costs[0].Length; Console.WriteLine($"*** Start with Bots = {botsCount} , tasks = {tasksCount} ***"); // Solver usage var assignment = new LinearSumAssignment(); for (var bot = 0; bot < botsCount; bot++) { for (var task = 0; task < tasksCount; task++) { assignment.AddArcWithCost(bot, task, costs[bot][task]); } } var solveStatus = assignment.Solve(); // Check the result if (solveStatus == LinearSumAssignment.Status.OPTIMAL) { Console.WriteLine($" Optimal Cost = {assignment.OptimalCost()}"); for (int i = 0; i < assignment.NumNodes(); i++) { Console.WriteLine($"Task {assignment.RightMate(i)} assigned to Bot {i}, distance {assignment.AssignmentCost(i)}"); } } else if (solveStatus == LinearSumAssignment.Status.INFEASIBLE) { Console.WriteLine("No assignment is possible."); } else if (solveStatus == LinearSumAssignment.Status.POSSIBLE_OVERFLOW) { Console.WriteLine("Some input costs are too large and may cause an integer overflow."); } }