This repository has been archived by the owner on Jul 6, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
AssignmentProblemSolver.scala
120 lines (104 loc) · 3.9 KB
/
AssignmentProblemSolver.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import scala.collection.mutable
object AssignmentProblemSolver {
// Implementation of the Hungarian algorithm
def hungarianAlgorithm(costMatrix: Array[Array[Int]]): Array[(Int, Int)] = {
val numRows = costMatrix.length
val numCols = costMatrix(0).length
// Step 1: Subtract the minimum value of each row from all elements of that row
val reducedMatrix = Array.ofDim[Int](numRows, numCols)
for (i <- 0 until numRows) {
val minRowValue = costMatrix(i).min
for (j <- 0 until numCols) {
reducedMatrix(i)(j) = costMatrix(i)(j) - minRowValue
}
}
// Step 2: Subtract the minimum value of each column from all elements of that column
for (j <- 0 until numCols) {
val minColValue = (for (i <- 0 until numRows) yield reducedMatrix(i)(j)).min
for (i <- 0 until numRows) {
reducedMatrix(i)(j) -= minColValue
}
}
// Step 3: Initialize variables
val rowCovered = Array.fill[Boolean](numRows)(false)
val colCovered = Array.fill[Boolean](numCols)(false)
val assignment = mutable.Map[Int, Int]() // Map from column to row
// Step 4: Try to find a valid assignment
var numAssigned = 0
while (numAssigned < numRows) {
val (row, col) = findUncoveredZero(reducedMatrix, rowCovered, colCovered)
if (row == -1) {
// If no uncovered zero found, perform step 6
val (minUncoveredValue, (uncoveredRow, uncoveredCol)) = findMinUncoveredValue(reducedMatrix, rowCovered, colCovered)
updateMatrix(reducedMatrix, rowCovered, colCovered, minUncoveredValue)
} else {
// If uncovered zero found, mark row and column as covered
rowCovered(row) = true
colCovered(col) = true
assignment(col) = row
numAssigned += 1
}
}
// Convert assignment map to array of (row, col) pairs
assignment.toArray.sortBy(_._1)
}
// Helper function to find an uncovered zero and return its coordinates
private def findUncoveredZero(matrix: Array[Array[Int]], rowCovered: Array[Boolean], colCovered: Array[Boolean]): (Int, Int) = {
val numRows = matrix.length
val numCols = matrix(0).length
for (i <- 0 until numRows) {
for (j <- 0 until numCols) {
if (matrix(i)(j) == 0 && !rowCovered(i) && !colCovered(j)) {
return (i, j)
}
}
}
(-1, -1)
}
// Helper function to find the minimum uncovered value in the reduced matrix
private def findMinUncoveredValue(matrix: Array[Array[Int]], rowCovered: Array[Boolean], colCovered: Array[Boolean]): (Int, (Int, Int)) = {
val numRows = matrix.length
val numCols = matrix(0).length
var minUncoveredValue = Int.MaxValue
var minCoordinates = (-1, -1)
for (i <- 0 until numRows) {
for (j <- 0 until numCols) {
if (!rowCovered(i) && !colCovered(j) && matrix(i)(j) < minUncoveredValue) {
minUncoveredValue = matrix(i)(j)
minCoordinates = (i, j)
}
}
}
(minUncoveredValue, minCoordinates)
}
// Helper function to update the reduced matrix after step 6
private def updateMatrix(matrix: Array[Array[Int]], rowCovered: Array[Boolean], colCovered: Array[Boolean], minUncoveredValue: Int): Unit = {
val numRows = matrix.length
val numCols = matrix(0).length
for (i <- 0 until numRows) {
for (j <- 0 until numCols) {
if (rowCovered(i)) {
matrix(i)(j) += minUncoveredValue
}
if (!colCovered(j)) {
matrix(i)(j) -= minUncoveredValue
}
}
}
}
def main(args: Array[String]): Unit = {
// Example cost matrix
val costMatrix = Array(
Array(3, 2, 7),
Array(2, 4, 6),
Array(5, 8, 1)
)
// Solve the assignment problem
val assignment = hungarianAlgorithm(costMatrix)
// Print the result
println("Optimal Assignment:")
assignment.foreach { case (col, row) =>
println(s"Assign task $col to agent $row")
}
}
}