Open In App

Hungarian Algorithm for Assignment Problem | Set 2 (Implementation)

Last Updated : 10 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a 2D array, arr of size N*N where arr[i][j] denotes the cost to complete the jth job by the ith worker. Any worker can be assigned to perform any job. The task is to assign the jobs such that exactly one worker can perform exactly one job in such a way that the total cost of the assignment is minimized.

Example

Input: arr[][] = {{3, 5}, {10, 1}}
Output: 4
Explanation: The optimal assignment is to assign job 1 to the 1st worker, job 2 to the 2nd worker.
Hence, the optimal cost is 3 + 1 = 4.

Input: arr[][] = {{2500, 4000, 3500}, {4000, 6000, 3500}, {2000, 4000, 2500}}
Output: 4
Explanation: The optimal assignment is to assign job 2 to the 1st worker, job 3 to the 2nd worker and job 1 to the 3rd worker.
Hence, the optimal cost is 4000 + 3500 + 2000 = 9500.

Different approaches to solve this problem are discussed in this article.

Approach: The idea is to use the Hungarian Algorithm to solve this problem. The algorithm is as follows:

  1. For each row of the matrix, find the smallest element and subtract it from every element in its row.
  2. Repeat the step 1 for all columns.
  3. Cover all zeros in the matrix using the minimum number of horizontal and vertical lines.
  4. Test for Optimality: If the minimum number of covering lines is N, an optimal assignment is possible. Else if lines are lesser than N, an optimal assignment is not found and must proceed to step 5.
  5. Determine the smallest entry not covered by any line. Subtract this entry from each uncovered row, and then add it to each covered column. Return to step 3.

Consider an example to understand the approach:

Let the 2D array be:

2500 4000 3500
4000 6000 3500
2000 4000 2500

Step 1: Subtract minimum of every row. 2500, 3500 and 2000 are subtracted from rows 1, 2 and 3 respectively.

0   1500  1000
500  2500   0
0   2000  500

Step 2: Subtract minimum of every column. 0, 1500 and 0 are subtracted from columns 1, 2 and 3 respectively.

0    0   1000
500  1000   0
0   500  500

Step 3: Cover all zeroes with minimum number of horizontal and vertical lines.

Step 4: Since we need 3 lines to cover all zeroes, the optimal assignment is found. 

 2500  4000  3500
 4000  6000  3500
 2000  4000  2500

So the optimal cost is 4000 + 3500 + 2000 = 9500

For implementing the above algorithm, the idea is to use the max_cost_assignment() function defined in the dlib library. This function is an implementation of the Hungarian algorithm (also known as the Kuhn-Munkres algorithm) which runs in O(N3) time. It solves the optimal assignment problem. 

Below is the implementation of the above approach:

C




#include <stdio.h>
#include <stdlib.h>
#include "hungarian.h"
 
// Function to solve the assignment problem
void minCost(double **arr, int n) {
    // Apply the Hungarian algorithm to find the optimal assignment
    double **costMatrix = array_to_matrix(arr, n, n);
    hungarian_t prob;
    hungarian_init(&prob, costMatrix, n, n, HUNGARIAN_MODE_MINIMIZE_COST);
    hungarian_solve(&prob);
    double cost = prob.cost;
 
    // Print the optimal cost
    printf("Optimal cost: %.2f\n", cost);
 
    // Free memory allocated for the cost matrix
    matrix_free(costMatrix, n);
}
 
// Main function
int main() {
    // Given 2D array
    double arr[2][2] = {{3, 5}, {10, 1}};
 
    // Solve the assignment problem
    minCost((double **)arr, 2);
 
    return 0;
}


C++




#include <iostream>
#include <fstream>
#include <vector>
#include "Hungarian.h"
 
using namespace std;
 
// Function to solve the assignment problem
void minCost(vector<vector<double>> arr) {
    int n = arr.size();
 
    // Convert the 2D vector to a double array
    double **costMatrix = new double*[n];
    for (int i = 0; i < n; i++) {
        costMatrix[i] = new double[n];
        for (int j = 0; j < n; j++) {
            costMatrix[i][j] = arr[i][j];
        }
    }
 
    // Apply the Hungarian algorithm to find the optimal assignment
    HungarianAlgorithm algorithm;
    vector<int> assignment;
    double cost = algorithm.Solve(costMatrix, n, n, assignment);
 
    // Print the optimal cost
    cout << "Optimal cost: " << cost << endl;
 
    // Free memory allocated for the cost matrix
    for (int i = 0; i < n; i++) {
        delete[] costMatrix[i];
    }
    delete[] costMatrix;
}
 
// Main function
int main() {
    // Load the input array from a .csv file
    ifstream inputFile("input.csv");
    vector<vector<double>> arr;
    string line;
    while (getline(inputFile, line)) {
        vector<double> row;
        size_t pos = 0;
        string token;
        while ((pos = line.find(",")) != string::npos) {
            token = line.substr(0, pos);
            row.push_back(stod(token));
            line.erase(0, pos + 1);
        }
        row.push_back(stod(line));
        arr.push_back(row);
    }
 
    // Solve the assignment problem
    minCost(arr);
 
    return 0;
}


Python




# Python program for the above approach
import dlib
 
# Function to find out the best
# assignment of people to jobs so that
# total cost of the assignment is minimized
def minCost(arr):
 
    # Call the max_cost_assignment() function
    # and store the assignment
    assignment = dlib.max_cost_assignment(arr)
 
    # Print the optimal cost
    print(dlib.assignment_cost(arr, assignment))
 
 
# Driver Code
 
# Given 2D array
arr = dlib.matrix([[3, 5], [10, 1]])
 
# Function Call
minCost(arr)


Java




/*package whatever //do not write package name here */
 
import com.jmatio.io.MatFileReader;
import com.jmatio.types.MLArray;
import com.jmatio.types.MLDouble;
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.linear.RealVector;
import org.apache.commons.math3.linear.SingularValueDecomposition;
 
import java.io.IOException;
 
public class AssignmentProblem {
 
    // Function to solve the assignment problem
    public static void minCost(double[][] arr) {
 
        // Convert the 2D array to a RealMatrix
        RealMatrix matrix = new Array2DRowRealMatrix(arr);
 
        // Apply the Hungarian algorithm to find the optimal assignment
        HungarianAlgorithm algorithm = new HungarianAlgorithm(matrix);
        int[] assignment = algorithm.execute();
 
        // Calculate the total cost of the assignment
        double cost = 0.0;
        for (int i = 0; i < assignment.length; i++) {
            int j = assignment[i];
            cost += arr[i][j];
        }
 
        // Print the optimal cost
        System.out.println("Optimal cost: " + cost);
    }
 
    // Main function
    public static void main(String[] args) throws IOException {
 
        // Load the input array from a .mat file
        MatFileReader reader = new MatFileReader("input.mat");
        MLArray array = reader.getMLArray("arr");
        double[][] arr = ((MLDouble) array).getArray();
 
        // Solve the assignment problem
        minCost(arr);
    }
}
//This Program cannot run through online compiler
//This program can be run through Maven Java Project
//Required Dependency needs to be put in


C#




using System;
using System.IO;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Double;
using HungarianAlgorithmDotNet;
 
public class AssignmentProblem
{
    // Function to solve the assignment problem
    public static void MinCost(double[,] arr)
    {
        // Convert the 2D array to a Matrix<double>
        var matrix = DenseMatrix.OfArray(arr);
 
        // Apply the Hungarian algorithm to find the optimal assignment
        var algorithm = new HungarianAlgorithm(matrix);
        int[] assignment = algorithm.Run();
 
        // Calculate the total cost of the assignment
        double cost = 0.0;
        for (int i = 0; i < assignment.Length; i++)
        {
            int j = assignment[i];
            cost += arr[i, j];
        }
 
        // Print the optimal cost
        Console.WriteLine("Optimal cost: " + cost);
    }
 
    // Main function
    public static void Main()
    {
        // Load the input array from a .csv file
        var reader = new StreamReader("input.csv");
        int rows = File.ReadLines("input.csv").Count();
        int cols = reader.ReadLine().Split(',').Length;
        double[,] arr = new double[rows, cols];
        for (int i = 0; i < rows; i++)
        {
            var line = reader.ReadLine().Split(',');
            for (int j = 0; j < cols; j++)
            {
                arr[i, j] = double.Parse(line[j]);
            }
        }
 
        // Solve the assignment problem
        MinCost(arr);
    }
}


Javascript




const hungarian = require('hungarian-algorithm-js');
 
// Function to solve the assignment problem
function minCost(arr) {
    // Apply the Hungarian algorithm to find the optimal assignment
    const result = hungarian(arr, true);
 
    // Compute the optimal cost
    let cost = 0;
    for (let i = 0; i < result.length; i++) {
        const [row, col] = result[i];
        cost += arr[row][col];
    }
 
    // Print the optimal cost
    console.log(`Optimal cost: ${cost}`);
}
 
// Main function
function main() {
    // Given 2D array
    const arr = [[3, 5], [10, 1]];
 
    // Solve the assignment problem
    minCost(arr);
}
 
main();


PHP




require_once 'hungarian.php';
 
// Function to solve the assignment problem
function minCost($arr) {
    // Apply the Hungarian algorithm to find the optimal assignment
    $h = new Hungarian($arr);
    $result = $h->solve();
 
    // Compute the optimal cost
    $cost = 0;
    foreach ($result as $row => $col) {
        $cost += $arr[$row][$col];
    }
 
    // Print the optimal cost
    echo "Optimal cost: $cost\n";
}
 
// Main function
function main() {
    // Given 2D array
    $arr = array(array(3, 5), array(10, 1));
 
    // Solve the assignment problem
    minCost($arr);
}
 
main();


Output

4

Time Complexity: O(N3)
Auxiliary Space: O(N2)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads