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]
    }
Example #2
0
        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;
 }
Example #4
0
        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.");
            }
        }