Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
uvahotspot
GitHub Repository: uvahotspot/HotSpot
Path: blob/master/npe.c
612 views
1
#include <stdio.h>
2
#ifdef _MSC_VER
3
#define strcasecmp _stricmp
4
#define strncasecmp _strnicmp
5
#else
6
#include <strings.h>
7
#endif
8
#include <string.h>
9
#include <stdlib.h>
10
#include <math.h>
11
12
#include "npe.h"
13
#include "flp.h"
14
#include "util.h"
15
16
void fill_unit_pos(NPE_t *expr)
17
{
18
int i, j=0;
19
for (i=0; i < expr->size; i++)
20
if (expr->elements[i] >= 0) {
21
expr->unit_pos[j] = i;
22
j++;
23
}
24
expr->n_units = j;
25
}
26
27
void fill_flip_pos(NPE_t *expr)
28
{
29
int i, j=0;
30
for (i=0; i < expr->size - 1; i++)
31
if ((expr->elements[i] < 0 && expr->elements[i+1] >= 0) ||
32
(expr->elements[i] >= 0 && expr->elements[i+1] < 0)) {
33
expr->flip_pos[j] = i;
34
j++;
35
}
36
expr->n_flips = j;
37
}
38
39
void fill_chain_pos(NPE_t *expr)
40
{
41
int i=0, j=0, prev;
42
43
while (i < expr->size) {
44
if (expr->elements[i] < 0) {
45
expr->chain_pos[j] = i;
46
j++;
47
48
/* skip this chain of successive cuts */
49
prev = expr->elements[i];
50
i++;
51
while(i < expr->size && expr->elements[i] < 0) {
52
if (expr->elements[i] == prev)
53
fatal("NPE not normalized\n");
54
prev = expr->elements[i];
55
i++;
56
}
57
} else
58
i++;
59
}
60
expr->n_chains = j;
61
}
62
63
void fill_ballot_count(NPE_t *expr)
64
{
65
int i, ballot_count = 0;
66
67
for (i=0; i < expr->size; i++) {
68
if (expr->elements[i] < 0)
69
ballot_count++;
70
expr->ballot_count[i] = ballot_count;
71
}
72
}
73
74
/* the starting solution for simulated annealing */
75
NPE_t *NPE_get_initial(flp_desc_t *flp_desc)
76
{
77
int i;
78
NPE_t *expr = (NPE_t *) calloc(1, sizeof(NPE_t));
79
if (!expr)
80
fatal("memory allocation error\n");
81
expr->size = 2 * flp_desc->n_units - 1;
82
expr->elements = (int *) calloc(expr->size, sizeof(int));
83
expr->unit_pos = (int *) calloc(flp_desc->n_units, sizeof(int));
84
expr->flip_pos = (int *) calloc(expr->size, sizeof(int));
85
expr->chain_pos = (int *) calloc(flp_desc->n_units-1, sizeof(int));
86
expr->ballot_count = (int *) calloc(expr->size, sizeof(int));
87
88
if(!expr->elements || !expr->unit_pos || !expr->flip_pos
89
|| !expr->chain_pos || !expr->ballot_count)
90
fatal("memory allocation error\n");
91
92
/* starting solution - 0, 1, V, 2, V, ..., n-1, V */
93
expr->elements[0] = 0;
94
for (i=1; i < expr->size; i+=2) {
95
expr->elements[i] = (i+1) / 2;
96
expr->elements[i+1] = CUT_VERTICAL;
97
}
98
99
fill_unit_pos(expr);
100
fill_flip_pos(expr);
101
fill_chain_pos(expr);
102
fill_ballot_count(expr);
103
104
return expr;
105
}
106
107
void free_NPE(NPE_t *expr)
108
{
109
free(expr->elements);
110
free(expr->unit_pos);
111
free(expr->flip_pos);
112
free(expr->chain_pos);
113
free(expr->ballot_count);
114
free(expr);
115
}
116
117
/* debug print */
118
void print_NPE(NPE_t *expr, flp_desc_t *flp_desc)
119
{
120
int i;
121
122
fprintf(stdout, "printing normalized polish expression ");
123
fprintf(stdout, "of size %d\n", expr->size);
124
fprintf(stdout, "%s", flp_desc->units[expr->elements[0]].name);
125
126
for(i=1; i < expr->size; i++) {
127
if (expr->elements[i] >= 0)
128
fprintf(stdout, ", %s", flp_desc->units[expr->elements[i]].name);
129
else if (expr->elements[i] == CUT_VERTICAL)
130
fprintf(stdout, ", V");
131
else if (expr->elements[i] == CUT_HORIZONTAL)
132
fprintf(stdout, ", H");
133
else
134
fprintf(stdout, ", X");
135
}
136
fprintf(stdout, "\n");
137
138
fprintf(stdout, "unit_pos:\n");
139
for(i=0; i < expr->n_units; i++)
140
fprintf(stdout, "%d\t", expr->unit_pos[i]);
141
fprintf(stdout, "\nflip_pos:\n");
142
for(i=0; i < expr->n_flips; i++)
143
fprintf(stdout, "%d\t", expr->flip_pos[i]);
144
fprintf(stdout, "\nchain_pos:\n");
145
for(i=0; i < expr->n_chains; i++)
146
fprintf(stdout, "%d\t", expr->chain_pos[i]);
147
fprintf(stdout, "\nballot_count:\n");
148
for(i=0; i < expr->size; i++)
149
fprintf(stdout, "%d\t", expr->ballot_count[i]);
150
fprintf(stdout, "\n");
151
}
152
153
/*
154
* move M1 of the floorplan paper
155
* swap two units adjacent in the NPE
156
*/
157
void NPE_swap_units(NPE_t *expr, int pos)
158
{
159
int i, t;
160
161
/* find adjacent unit */
162
for (i=pos+1; i < expr->size; i++)
163
if (expr->elements[i] >= 0)
164
break;
165
if (i >= expr->size)
166
fatal("unable to find adjacent unit\n");
167
168
/* swap */
169
t = expr->elements[pos];
170
expr->elements[pos] = expr->elements[i];
171
expr->elements[i] = t;
172
}
173
174
/* move M2 - invert a chain of cut_types in the NPE */
175
void NPE_invert_chain(NPE_t *expr, int pos)
176
{
177
int i = pos+1, prev = expr->elements[pos];
178
179
if (expr->elements[pos] == CUT_VERTICAL)
180
expr->elements[pos] = CUT_HORIZONTAL;
181
else if (expr->elements[pos] == CUT_HORIZONTAL)
182
expr->elements[pos] = CUT_VERTICAL;
183
else
184
fatal("invalid NPE in invert_chain\n");
185
186
while(i < expr->size && expr->elements[i] < 0) {
187
if (expr->elements[i] == prev)
188
fatal("NPE not normalized\n");
189
prev = expr->elements[i];
190
if (expr->elements[i] == CUT_VERTICAL)
191
expr->elements[i] = CUT_HORIZONTAL;
192
else if (expr->elements[i] == CUT_HORIZONTAL)
193
expr->elements[i] = CUT_VERTICAL;
194
else
195
fatal("unknown cut type\n");
196
i++;
197
}
198
}
199
200
/* binary search and increment the unit position by delta */
201
int update_unit_pos(NPE_t *expr, int pos, int delta,
202
int start, int end)
203
{
204
int mid;
205
206
if (start > end)
207
return FALSE;
208
209
mid = (start + end) / 2;
210
211
if (expr->unit_pos[mid] == pos) {
212
expr->unit_pos[mid] += delta;
213
return TRUE;
214
} else if (expr->unit_pos[mid] > pos)
215
return update_unit_pos(expr, pos, delta, start, mid-1);
216
else
217
return update_unit_pos(expr, pos, delta, mid+1, end);
218
}
219
220
/*
221
* move M3 - swap adjacent cut_type and unit in the NPE
222
* - could result in a non-allowable move. hence returns
223
* if the move is legal or not
224
*/
225
int NPE_swap_cut_unit(NPE_t *expr, int pos)
226
{
227
int t;
228
229
if (pos <= 0 || pos >= expr->size -1)
230
fatal("invalid position in NPE_swap_cut_unit\n");
231
232
/* unit, cut_type swap */
233
if (expr->elements[pos] >= 0) {
234
/* swap leads to consecutive cut_types that are identical? */
235
if (expr->elements[pos-1] == expr->elements[pos+1])
236
return FALSE;
237
/* move should not violate the balloting property */
238
if (2 * expr->ballot_count[pos+1] >= pos+1)
239
return FALSE;
240
/* unit's position is advanced by 1 */
241
if (!update_unit_pos(expr, pos, 1, 0, expr->n_units-1))
242
fatal("unit position not found\n");
243
expr->ballot_count[pos]++;
244
} else { /* cut_type, unit swap */
245
/* swap leads to consecutive cut_types that are identical? */
246
if ((pos < expr->size - 2) && (expr->elements[pos] == expr->elements[pos+2]))
247
return FALSE;
248
/* unit's position is reduced by 1 */
249
if (!update_unit_pos(expr, pos+1, -1, 0, expr->n_units-1))
250
fatal("unit position not found\n");
251
expr->ballot_count[pos]--;
252
}
253
254
/* swap O.K */
255
t = expr->elements[pos];
256
expr->elements[pos] = expr->elements[pos+1];
257
expr->elements[pos+1] = t;
258
259
/* flip and chain positions altered. recompute them */
260
fill_flip_pos(expr);
261
fill_chain_pos(expr);
262
263
return TRUE;
264
}
265
266
/* make a random move out of the above */
267
NPE_t *make_random_move(NPE_t *expr)
268
{
269
int i, move, count = 0, done = FALSE, m3_count;
270
NPE_t *copy = NPE_duplicate(expr);
271
272
while (!done && count < MAX_MOVES) {
273
/* choose one of three moves */
274
move = rand_upto(3);
275
switch(move) {
276
case 0: /* swap adjacent units */
277
/* leave the unit last in the NPE */
278
i = rand_upto(expr->n_units-1);
279
#if VERBOSE > 2
280
fprintf(stdout, "making M1 at %d\n", expr->unit_pos[i]);
281
#endif
282
NPE_swap_units(copy, expr->unit_pos[i]);
283
done = TRUE;
284
break;
285
286
case 1: /* invert an arbitrary chain */
287
i = rand_upto(expr->n_chains);
288
#if VERBOSE > 2
289
fprintf(stdout, "making M2 at %d\n", expr->chain_pos[i]);
290
#endif
291
NPE_invert_chain(copy, expr->chain_pos[i]);
292
done = TRUE;
293
break;
294
295
case 2: /* swap a unit and an adjacent cut_type */
296
m3_count = 0;
297
while (!done && m3_count < MAX_MOVES) {
298
i = rand_upto(expr->n_flips);
299
#if VERBOSE > 2
300
fprintf(stdout, "making M3 at %d\n", expr->flip_pos[i]);
301
#endif
302
done = NPE_swap_cut_unit(copy, expr->flip_pos[i]);
303
m3_count++;
304
}
305
break;
306
307
default:
308
fatal("unknown move type\n");
309
break;
310
}
311
count++;
312
}
313
314
if (count == MAX_MOVES) {
315
char msg[STR_SIZE];
316
sprintf(msg, "tried %d moves, now giving up\n", MAX_MOVES);
317
fatal(msg);
318
}
319
320
return copy;
321
}
322
323
/* make a copy of this NPE */
324
NPE_t *NPE_duplicate(NPE_t *expr)
325
{
326
int i;
327
NPE_t *copy = (NPE_t *) calloc(1, sizeof(NPE_t));
328
if (!copy)
329
fatal("memory allocation error\n");
330
copy->elements = (int *) calloc(expr->size, sizeof(int));
331
copy->unit_pos = (int *) calloc(expr->n_units, sizeof(int));
332
copy->flip_pos = (int *) calloc(expr->size, sizeof(int));
333
copy->chain_pos = (int *) calloc(expr->n_units-1, sizeof(int));
334
copy->ballot_count = (int *) calloc(expr->size, sizeof(int));
335
336
if(!copy->elements || !copy->unit_pos || !copy->flip_pos
337
|| !copy->chain_pos || !copy->ballot_count)
338
fatal("memory allocation error\n");
339
340
copy->size = expr->size;
341
for (i=0; i < expr->size; i++)
342
copy->elements[i] = expr->elements[i];
343
copy->n_units = expr->n_units;
344
for (i=0; i < expr->n_units; i++)
345
copy->unit_pos[i] = expr->unit_pos[i];
346
copy->n_flips = expr->n_flips;
347
for (i=0; i < expr->n_flips; i++)
348
copy->flip_pos[i] = expr->flip_pos[i];
349
copy->n_chains = expr->n_chains;
350
for (i=0; i < expr->n_chains; i++)
351
copy->chain_pos[i] = expr->chain_pos[i];
352
for (i=0; i < expr->size; i++)
353
copy->ballot_count[i] = expr->ballot_count[i];
354
355
return copy;
356
}
357
358
359