git

Форк
0
/
linear-assignment.c 
207 строк · 4.1 Кб
1
/*
2
 * Based on: Jonker, R., & Volgenant, A. (1987). <i>A shortest augmenting path
3
 * algorithm for dense and sparse linear assignment problems</i>. Computing,
4
 * 38(4), 325-340.
5
 */
6
#include "git-compat-util.h"
7
#include "linear-assignment.h"
8

9
#define COST(column, row) cost[(column) + column_count * (row)]
10

11
/*
12
 * The parameter `cost` is the cost matrix: the cost to assign column j to row
13
 * i is `cost[j + column_count * i].
14
 */
15
void compute_assignment(int column_count, int row_count, int *cost,
16
			int *column2row, int *row2column)
17
{
18
	int *v, *d;
19
	int *free_row, free_count = 0, saved_free_count, *pred, *col;
20
	int i, j, phase;
21

22
	if (column_count < 2) {
23
		memset(column2row, 0, sizeof(int) * column_count);
24
		memset(row2column, 0, sizeof(int) * row_count);
25
		return;
26
	}
27

28
	memset(column2row, -1, sizeof(int) * column_count);
29
	memset(row2column, -1, sizeof(int) * row_count);
30
	ALLOC_ARRAY(v, column_count);
31

32
	/* column reduction */
33
	for (j = column_count - 1; j >= 0; j--) {
34
		int i1 = 0;
35

36
		for (i = 1; i < row_count; i++)
37
			if (COST(j, i1) > COST(j, i))
38
				i1 = i;
39
		v[j] = COST(j, i1);
40
		if (row2column[i1] == -1) {
41
			/* row i1 unassigned */
42
			row2column[i1] = j;
43
			column2row[j] = i1;
44
		} else {
45
			if (row2column[i1] >= 0)
46
				row2column[i1] = -2 - row2column[i1];
47
			column2row[j] = -1;
48
		}
49
	}
50

51
	/* reduction transfer */
52
	ALLOC_ARRAY(free_row, row_count);
53
	for (i = 0; i < row_count; i++) {
54
		int j1 = row2column[i];
55
		if (j1 == -1)
56
			free_row[free_count++] = i;
57
		else if (j1 < -1)
58
			row2column[i] = -2 - j1;
59
		else {
60
			int min = COST(!j1, i) - v[!j1];
61
			for (j = 1; j < column_count; j++)
62
				if (j != j1 && min > COST(j, i) - v[j])
63
					min = COST(j, i) - v[j];
64
			v[j1] -= min;
65
		}
66
	}
67

68
	if (free_count ==
69
	    (column_count < row_count ? row_count - column_count : 0)) {
70
		free(v);
71
		free(free_row);
72
		return;
73
	}
74

75
	/* augmenting row reduction */
76
	for (phase = 0; phase < 2; phase++) {
77
		int k = 0;
78

79
		saved_free_count = free_count;
80
		free_count = 0;
81
		while (k < saved_free_count) {
82
			int u1, u2;
83
			int j1 = 0, j2, i0;
84

85
			i = free_row[k++];
86
			u1 = COST(j1, i) - v[j1];
87
			j2 = -1;
88
			u2 = INT_MAX;
89
			for (j = 1; j < column_count; j++) {
90
				int c = COST(j, i) - v[j];
91
				if (u2 > c) {
92
					if (u1 < c) {
93
						u2 = c;
94
						j2 = j;
95
					} else {
96
						u2 = u1;
97
						u1 = c;
98
						j2 = j1;
99
						j1 = j;
100
					}
101
				}
102
			}
103
			if (j2 < 0) {
104
				j2 = j1;
105
				u2 = u1;
106
			}
107

108
			i0 = column2row[j1];
109
			if (u1 < u2)
110
				v[j1] -= u2 - u1;
111
			else if (i0 >= 0) {
112
				j1 = j2;
113
				i0 = column2row[j1];
114
			}
115

116
			if (i0 >= 0) {
117
				if (u1 < u2)
118
					free_row[--k] = i0;
119
				else
120
					free_row[free_count++] = i0;
121
			}
122
			row2column[i] = j1;
123
			column2row[j1] = i;
124
		}
125
	}
126

127
	/* augmentation */
128
	saved_free_count = free_count;
129
	ALLOC_ARRAY(d, column_count);
130
	ALLOC_ARRAY(pred, column_count);
131
	ALLOC_ARRAY(col, column_count);
132
	for (free_count = 0; free_count < saved_free_count; free_count++) {
133
		int i1 = free_row[free_count], low = 0, up = 0, last, k;
134
		int min, c, u1;
135

136
		for (j = 0; j < column_count; j++) {
137
			d[j] = COST(j, i1) - v[j];
138
			pred[j] = i1;
139
			col[j] = j;
140
		}
141

142
		j = -1;
143
		do {
144
			last = low;
145
			min = d[col[up++]];
146
			for (k = up; k < column_count; k++) {
147
				j = col[k];
148
				c = d[j];
149
				if (c <= min) {
150
					if (c < min) {
151
						up = low;
152
						min = c;
153
					}
154
					col[k] = col[up];
155
					col[up++] = j;
156
				}
157
			}
158
			for (k = low; k < up; k++)
159
				if (column2row[col[k]] == -1)
160
					goto update;
161

162
			/* scan a row */
163
			do {
164
				int j1 = col[low++];
165

166
				i = column2row[j1];
167
				u1 = COST(j1, i) - v[j1] - min;
168
				for (k = up; k < column_count; k++) {
169
					j = col[k];
170
					c = COST(j, i) - v[j] - u1;
171
					if (c < d[j]) {
172
						d[j] = c;
173
						pred[j] = i;
174
						if (c == min) {
175
							if (column2row[j] == -1)
176
								goto update;
177
							col[k] = col[up];
178
							col[up++] = j;
179
						}
180
					}
181
				}
182
			} while (low != up);
183
		} while (low == up);
184

185
update:
186
		/* updating of the column pieces */
187
		for (k = 0; k < last; k++) {
188
			int j1 = col[k];
189
			v[j1] += d[j1] - min;
190
		}
191

192
		/* augmentation */
193
		do {
194
			if (j < 0)
195
				BUG("negative j: %d", j);
196
			i = pred[j];
197
			column2row[j] = i;
198
			SWAP(j, row2column[i]);
199
		} while (i1 != i);
200
	}
201

202
	free(col);
203
	free(pred);
204
	free(d);
205
	free(v);
206
	free(free_row);
207
}
208

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.