6161# End Region
6262
6363Imports System.Runtime.CompilerServices
64+ Imports Microsoft.VisualBasic.ComponentModel.Collection
6465Imports Microsoft.VisualBasic.Math.LinearAlgebra.Matrix
6566Imports std = System.Math
6667
@@ -97,19 +98,19 @@ Namespace HungarianAlgorithm
9798 ''' is the column of the task assigned to agent <em>i</em>.</returns>
9899 ''' <exception cref="ArgumentNullException"><paramref name="costs"/> is null.</exception>
99100 <Extension()>
100- Public Function FindAssignments(costs As Double (, )) As Integer ()
101- Dim h = costs.GetLength( 0 )
102- Dim w = costs.GetLength( 1 )
101+ Public Function FindAssignments(costs As Double ()( )) As Integer ()
102+ Dim h = costs.Length
103+ Dim w = costs( 0 ).Length
103104 Dim rowsGreaterThanCols = h > w
104105
105106 If rowsGreaterThanCols Then
106107 ' make sure cost matrix has number of rows greater than columns
107108 Dim row = w
108109 Dim col = h
109- Dim transposeCosts = New Double (row - 1 , col - 1 ) {}
110+ Dim transposeCosts As Double ()() = RectangularArray.Matrix( Of Double ) (row, col)
110111 For i As Integer = 0 To row - 1
111112 For j As Integer = 0 To col - 1
112- transposeCosts(i, j) = costs(j, i)
113+ transposeCosts(i)( j) = costs(j)( i)
113114 Next
114115 Next
115116 costs = transposeCosts
@@ -121,22 +122,22 @@ Namespace HungarianAlgorithm
121122 Dim min As Double = Double .MaxValue
122123
123124 For j As Integer = 0 To w - 1
124- min = std.Min(min, costs(i, j))
125+ min = std.Min(min, costs(i)( j))
125126 Next
126127
127128 For j As Integer = 0 To w - 1
128- costs(i, j) -= min
129+ costs(i)( j) -= min
129130 Next
130131 Next
131132
132- Dim masks = New Byte (h - 1 , w - 1 ) {}
133+ Dim masks As Byte ()() = RectangularArray.Matrix( Of Byte )(h , w)
133134 Dim rowsCovered = New Boolean (h - 1 ) {}
134135 Dim colsCovered = New Boolean (w - 1 ) {}
135136
136137 For i As Integer = 0 To h - 1
137138 For j As Integer = 0 To w - 1
138- If costs(i, j) = 0.0 AndAlso Not rowsCovered(i) AndAlso Not colsCovered(j) Then
139- masks(i, j) = 1
139+ If costs(i)( j) = 0.0 AndAlso Not rowsCovered(i) AndAlso Not colsCovered(j) Then
140+ masks(i)( j) = 1
140141 rowsCovered(i) = True
141142 colsCovered(j) = True
142143 End If
@@ -145,8 +146,8 @@ Namespace HungarianAlgorithm
145146
146147 Call ClearCovers(rowsCovered, colsCovered, w, h)
147148
148- Dim path = New Location (w * h - 1 ) {}
149- Dim pathStart As Location = Nothing
149+ Dim path = New (row As Integer , column As Integer ) (w * h - 1 ) {}
150+ Dim pathStart As (row As Integer , column As Integer ) = Nothing
150151 Dim [step] = 1
151152
152153 While [step] <> - 1
@@ -167,7 +168,7 @@ Namespace HungarianAlgorithm
167168
168169 For i As Integer = 0 To h - 1
169170 For j As Integer = 0 To w - 1
170- If masks(i, j) = 1 Then
171+ If masks(i)( j) = 1 Then
171172 agentsTasks(i) = j
172173 Exit For
173174 Else
@@ -191,10 +192,10 @@ Namespace HungarianAlgorithm
191192 Return agentsTasks
192193 End Function
193194
194- Private Function RunStep1(masks As Byte (,), colsCovered As Boolean (), w As Integer , h As Integer ) As Integer
195+ Private Function RunStep1( ByRef masks As Byte ()(), ByRef colsCovered As Boolean (), w As Integer , h As Integer ) As Integer
195196 For i As Integer = 0 To h - 1
196197 For j As Integer = 0 To w - 1
197- If masks(i, j) = 1 Then colsCovered(j) = True
198+ If masks(i)( j) = 1 Then colsCovered(j) = True
198199 Next
199200 Next
200201
@@ -209,14 +210,19 @@ Namespace HungarianAlgorithm
209210 Return 2
210211 End Function
211212
212- Private Function RunStep2(costs As Double (,), masks As Byte (,), rowsCovered As Boolean (), colsCovered As Boolean (), w As Integer , h As Integer , ByRef pathStart As Location) As Integer
213+ Private Function RunStep2( ByRef costs As Double ()(),
214+ ByRef masks As Byte ()(),
215+ ByRef rowsCovered As Boolean (),
216+ ByRef colsCovered As Boolean (),
217+ w As Integer , h As Integer ,
218+ ByRef pathStart As (row As Integer , column As Integer )) As Integer
213219 While True
214220 Dim loc = FindZero(costs, rowsCovered, colsCovered, w, h)
215221
216222 If loc.row = - 1 Then
217223 Return 4
218224 Else
219- masks(loc.row, loc.column) = 2
225+ masks(loc.row)( loc.column) = 2
220226 End If
221227
222228 Dim starCol = FindStarInRow(masks, w, loc.row)
@@ -233,7 +239,13 @@ Namespace HungarianAlgorithm
233239 Throw New Exception( "never!" )
234240 End Function
235241
236- Private Function RunStep3(masks As Byte (,), rowsCovered As Boolean (), colsCovered As Boolean (), w As Integer , h As Integer , path As Location(), pathStart As Location) As Integer
242+ Private Function RunStep3( ByRef masks As Byte ()(),
243+ ByRef rowsCovered As Boolean (),
244+ ByRef colsCovered As Boolean (),
245+ w As Integer , h As Integer ,
246+ path As (row As Integer , column As Integer )(),
247+ pathStart As (row As Integer , column As Integer )) As Integer
248+
237249 Dim pathIndex As Integer = 0
238250 path( 0 ) = pathStart
239251
@@ -242,12 +254,12 @@ Namespace HungarianAlgorithm
242254 If row = - 1 Then Exit While
243255
244256 pathIndex += 1
245- path(pathIndex) = New Location (row, path(pathIndex - 1 ).column)
257+ path(pathIndex) = (row, path(pathIndex - 1 ).column)
246258
247259 Dim col = FindPrimeInRow(masks, w, path(pathIndex).row)
248260
249261 pathIndex += 1
250- path(pathIndex) = New Location (path(pathIndex - 1 ).row, col)
262+ path(pathIndex) = (path(pathIndex - 1 ).row, col)
251263 End While
252264
253265 ConvertPath(masks, path, pathIndex + 1 )
@@ -257,93 +269,121 @@ Namespace HungarianAlgorithm
257269 Return 1
258270 End Function
259271
260- Private Function RunStep4(costs As Double (,), rowsCovered As Boolean (), colsCovered As Boolean (), w As Integer , h As Integer ) As Integer
261- Dim minValue = FindMinimum(costs, rowsCovered, colsCovered, w, h)
272+ Private Function RunStep4( ByRef costs As Double ()(),
273+ ByRef rowsCovered As Boolean (),
274+ ByRef colsCovered As Boolean (),
275+ w As Integer , h As Integer ) As Integer
276+
277+ Dim minValue As Double = FindMinimum(costs, rowsCovered, colsCovered, w, h)
262278
263279 For i As Integer = 0 To h - 1
264280 For j As Integer = 0 To w - 1
265- If rowsCovered(i) Then costs(i, j) += minValue
266- If Not colsCovered(j) Then costs(i, j) -= minValue
281+ If rowsCovered(i) Then
282+ costs(i)(j) += minValue
283+ End If
284+ If Not colsCovered(j) Then
285+ costs(i)(j) -= minValue
286+ End If
267287 Next
268288 Next
269289
270290 Return 2
271291 End Function
272292
273- Private Function FindMinimum(costs As Double (,), rowsCovered As Boolean (), colsCovered As Boolean (), w As Integer , h As Integer ) As Double
293+ Private Function FindMinimum( ByRef costs As Double ()(),
294+ ByRef rowsCovered As Boolean (),
295+ ByRef colsCovered As Boolean (),
296+ w As Integer , h As Integer ) As Double
297+
274298 Dim minValue = Double .MaxValue
275299
276300 For i As Integer = 0 To h - 1
277301 For j As Integer = 0 To w - 1
278302 If Not rowsCovered(i) AndAlso Not colsCovered(j) Then
279- minValue = std.Min(minValue, costs(i, j))
303+ minValue = std.Min(minValue, costs(i)( j))
280304 End If
281305 Next
282306 Next
283307
284308 Return minValue
285309 End Function
286310
287- Private Function FindStarInRow(masks As Byte (, ), w As Integer , row As Integer ) As Integer
311+ Private Function FindStarInRow( ByRef masks As Byte ()( ), w As Integer , row As Integer ) As Integer
288312 For j As Integer = 0 To w - 1
289- If masks(row, j) = 1 Then Return j
313+ If masks(row)(j) = 1 Then
314+ Return j
315+ End If
290316 Next
291317
292318 Return - 1
293319 End Function
294320
295- Private Function FindStarInColumn(masks As Byte (, ), h As Integer , col As Integer ) As Integer
321+ Private Function FindStarInColumn( ByRef masks As Byte ()( ), h As Integer , col As Integer ) As Integer
296322 For i As Integer = 0 To h - 1
297- If masks(i, col) = 1 Then Return i
323+ If masks(i)(col) = 1 Then
324+ Return i
325+ End If
298326 Next
299327
300328 Return - 1
301329 End Function
302330
303- Private Function FindPrimeInRow(masks As Byte (, ), w As Integer , row As Integer ) As Integer
331+ Private Function FindPrimeInRow( ByRef masks As Byte ()( ), w As Integer , row As Integer ) As Integer
304332 For j As Integer = 0 To w - 1
305- If masks(row, j) = 2 Then Return j
333+ If masks(row)(j) = 2 Then
334+ Return j
335+ End If
306336 Next
307337
308338 Return - 1
309339 End Function
310340
311- Private Function FindZero(costs As Double (,), rowsCovered As Boolean (), colsCovered As Boolean (), w As Integer , h As Integer ) As Location
341+ Private Function FindZero( ByRef costs As Double ()(),
342+ ByRef rowsCovered As Boolean (),
343+ ByRef colsCovered As Boolean (), w As Integer , h As Integer ) As (row As Integer , column As Integer )
344+
312345 For i As Integer = 0 To h - 1
313346 For j As Integer = 0 To w - 1
314- If costs(i, j) = 0.0 AndAlso Not rowsCovered(i) AndAlso Not colsCovered(j) Then
315- Return New Location (i, j)
347+ If costs(i)( j) = 0.0 AndAlso Not rowsCovered(i) AndAlso Not colsCovered(j) Then
348+ Return (i, j)
316349 End If
317350 Next
318351 Next
319352
320- Return New Location (-1 , - 1 )
353+ Return (- 1 , - 1 )
321354 End Function
322355
323- Private Sub ConvertPath(masks As Byte (,), path As Location(), pathLength As Integer )
356+ Private Sub ConvertPath( ByRef masks As Byte ()(),
357+ ByRef path As (row As Integer , column As Integer )(),
358+ pathLength As Integer )
359+
324360 For i As Integer = 0 To pathLength - 1
325- Dim x = masks(path(i).row, path(i).column)
361+ Dim x = masks(path(i).row)( path(i).column)
326362
327363 Select Case x
328364 Case 1
329365 x = 0
330366 Case 2
331367 x = 1
332368 Case Else
333- x = masks(path(i).row, path(i).column)
369+ x = masks(path(i).row)( path(i).column)
334370 End Select
335371
336- masks(path(i).row, path(i).column) = x
372+ masks(path(i).row)( path(i).column) = x
337373 Next
338374 End Sub
339- Private Sub ClearPrimes(masks As Byte (,), w As Integer , h As Integer )
375+
376+ Private Sub ClearPrimes( ByRef masks As Byte ()(), w As Integer , h As Integer )
340377 For i As Integer = 0 To h - 1
341378 For j As Integer = 0 To w - 1
342- If masks(i, j) = 2 Then masks(i, j) = 0
379+ If masks(i)(j) = 2 Then
380+ masks(i)(j) = 0
381+ End If
343382 Next
344383 Next
345384 End Sub
346- Private Sub ClearCovers(rowsCovered As Boolean (), colsCovered As Boolean (), w As Integer , h As Integer )
385+
386+ Private Sub ClearCovers( ByRef rowsCovered As Boolean (), ByRef colsCovered As Boolean (), w As Integer , h As Integer )
347387 For i As Integer = 0 To h - 1
348388 rowsCovered(i) = False
349389 Next
@@ -352,16 +392,5 @@ Namespace HungarianAlgorithm
352392 colsCovered(j) = False
353393 Next
354394 End Sub
355-
356- Private Structure Location
357-
358- Friend ReadOnly row As Integer
359- Friend ReadOnly column As Integer
360-
361- Friend Sub New (row As Integer , col As Integer )
362- Me .row = row
363- Me .column = col
364- End Sub
365- End Structure
366395 End Module
367396End Namespace
0 commit comments