Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 /* TODO: Tracing 00037 */ 00038 00039 #if 0 00040 00041 #include "errors.h" 00042 #include "mfmc.h" 00043 #include "mfmc_defs.h" 00044 00045 MFMC_HANDLE 00046 MFMC_Init_problem(MEM_POOL *mem_pool, 00047 BOOL trace, 00048 INT32 n, 00049 INT32 m, 00050 INT32 n_sources, 00051 INT32 n_sinks) 00052 { 00053 INT32 i; 00054 00055 /* allocating memory for 'nodes', 'arcs' and internal arrays */ 00056 MFMC_HANDLE handle = (MFMC_HANDLE) MEM_POOL_Alloc(mem_pool, 00057 sizeof(*handle)); 00058 00059 if (handle == NULL) { 00060 return NULL; 00061 } 00062 00063 handle->mem_pool = mem_pool; 00064 handle->trace = trace; 00065 00066 handle->n = handle->user_n = n; 00067 handle->m = handle->user_m = m; 00068 00069 handle->n_sources = n_sources; 00070 handle->n_sinks = n_sinks; 00071 00072 handle->pos_current = 0; 00073 00074 if (n_sources > 1) { 00075 /* We will introduce a source. It will be nodes[handle->user_n]. 00076 */ 00077 handle->n++; 00078 handle->m += n_sources; 00079 } 00080 00081 if (n_sinks > 1) { 00082 /* We will introduce a sink. It will be nodes[handle->n - 1]. 00083 */ 00084 handle->n++; 00085 handle->m += n_sinks; 00086 } 00087 00088 /* Allocate memory that will live beyond the final query. These 00089 * resources will be freed by the user when s/he pops or deletes the 00090 * MEM_POOL. 00091 */ 00092 handle->nodes = TYPE_MEM_POOL_ALLOC_N(MFMC_NODE, 00093 mem_pool, 00094 handle->n + 2); 00095 handle->arcs = TYPE_MEM_POOL_ALLOC_N(MFMC_ARC, 00096 mem_pool, 00097 2 * handle->m + 1); 00098 handle->acap = TYPE_MEM_POOL_ALLOC_N(INT64, 00099 mem_pool, 00100 2 * handle->m); 00101 00102 /* Allocate memory that will live through the end of the 00103 * push-relabel algorithm, but that need not stay around for the 00104 * first query. 00105 */ 00106 MEM_POOL_Push(mem_pool); 00107 00108 handle->queue = TYPE_MEM_POOL_ALLOC_N(MFMC_NODE *, 00109 mem_pool, 00110 handle->n); 00111 handle->layers = TYPE_MEM_POOL_ALLOC_N(MFMC_LAYER, 00112 mem_pool, 00113 handle->n + 2); 00114 00115 /* Allocate memory that will live only as long as it takes us to set 00116 * up the problem instance. 00117 */ 00118 MEM_POOL_Push(handle->mem_pool); 00119 00120 handle->arc_tail = TYPE_MEM_POOL_ALLOC_N(INT32, 00121 mem_pool, 00122 2 * handle->m); 00123 handle->arc_first = TYPE_MEM_POOL_ALLOC_N(INT32, 00124 mem_pool, 00125 handle->n + 2); 00126 00127 if (handle->nodes == NULL || handle->arcs == NULL || 00128 handle->arc_first == NULL || handle->arc_tail == NULL) { 00129 return NULL; 00130 } 00131 00132 for (i = 0; i < n; i++) { 00133 handle->nodes[i].node_type = TRANSSHIPMENT; 00134 } 00135 00136 for (i = 0; i < m; i++) { 00137 handle->arc_first[i] = 0; 00138 } 00139 00140 if (n_sources > 1) { 00141 handle->the_source = &handle->nodes[handle->user_n]; 00142 } 00143 else { 00144 handle->the_source = NULL; 00145 } 00146 00147 if (n_sinks > 1) { 00148 handle->the_sink = &handle->nodes[handle->n - 1]; 00149 } 00150 else { 00151 handle->the_sink = NULL; 00152 } 00153 00154 /* setting pointer to the first arc */ 00155 handle->arc_current = handle->arcs; 00156 00157 handle->n_sources_set = 0; 00158 handle->n_sinks_set = 0; 00159 handle->max_cap = 0; 00160 00161 return handle; 00162 } 00163 00164 MFMC_EC 00165 MFMC_Place_arc(MFMC_HANDLE handle, 00166 INT32 tail, 00167 INT32 head, 00168 INT64 lower_cap, 00169 INT64 upper_cap, 00170 MFMC_ARC_HANDLE *arc_handle) 00171 00172 { 00173 FmtAssert(tail >= 0 && tail < handle->n, 00174 ("Tail node out of range")); 00175 FmtAssert(head >= 0 && head < handle->n, 00176 ("Head node out of range")); 00177 00178 if (upper_cap < lower_cap) { 00179 return MFMC_INFEASIBLE; 00180 } 00181 00182 if (upper_cap < 0 || lower_cap > 0) { 00183 return MFMC_ZERO_INFEASIBLE; 00184 } 00185 00186 /* For the sake of the following check, user_m gets modified so that 00187 * user_m == m, just prior to the construction of auxiliary source 00188 * and/or sink node(s). 00189 */ 00190 if (handle->pos_current + 1 >= 2 * handle->user_m) { 00191 return MFMC_BAD_ARC_COUNT; 00192 } 00193 00194 /* no of arcs incident to node i is stored in arc_first[i+1] */ 00195 handle->arc_first[tail + 1] ++; 00196 handle->arc_first[head + 1] ++; 00197 00198 /* storing information about the arc */ 00199 handle->arc_tail[handle->pos_current] = tail; 00200 handle->arc_tail[handle->pos_current+1] = head; 00201 00202 handle->arc_current->head = handle->nodes + head; 00203 handle->arc_current->r_cap = upper_cap; 00204 handle->arc_current->reverse = handle->arc_current + 1; 00205 00206 (handle->arc_current + 1)->head = handle->nodes + tail; 00207 (handle->arc_current + 1)->r_cap = -lower_cap; 00208 (handle->arc_current + 1)->reverse = handle->arc_current; 00209 00210 /* searching minimum and maximum node */ 00211 handle->arc_current += 2; 00212 handle->pos_current += 2; 00213 00214 if (upper_cap > handle->max_cap) { 00215 handle->max_cap = upper_cap; 00216 } 00217 if (-lower_cap > handle->max_cap) { 00218 handle->max_cap = -lower_cap; 00219 } 00220 00221 if (arc_handle != NULL) { 00222 /* Arc handles not implemented yet */ 00223 return MFMC_NOT_IMPLEMENTED; 00224 } 00225 00226 return MFMC_NO_ERROR; 00227 } 00228 00229 MFMC_EC 00230 MFMC_Set_source(MFMC_HANDLE handle, INT32 s) 00231 { 00232 FmtAssert(s >= 0 && s < handle->n, 00233 ("Source node out of range")); 00234 00235 if (handle->nodes[s].node_type == TRANSSHIPMENT) { 00236 if (handle->n_sources == 1) { 00237 handle->nodes[s].node_type = SOURCE; 00238 handle->the_source = &handle->nodes[s]; 00239 } 00240 else { 00241 handle->nodes[s].node_type = USER_SOURCE; 00242 /* We cannot place the introduced arc now because we don't yet 00243 * know the largest capacity in the problem. 00244 */ 00245 } 00246 handle->n_sources_set++; 00247 return MFMC_NO_ERROR; 00248 } 00249 else { 00250 return MFMC_S_T_OVERLAP; 00251 } 00252 } 00253 00254 MFMC_EC 00255 MFMC_Set_sink(MFMC_HANDLE handle, INT32 t) 00256 { 00257 FmtAssert(t >= 0 && t < handle->n, 00258 ("Sink node out of range")); 00259 00260 if (handle->nodes[t].node_type != SOURCE) { 00261 if (handle->n_sinks == 1) { 00262 handle->nodes[t].node_type = SINK; 00263 handle->the_sink = &handle->nodes[t]; 00264 } 00265 else { 00266 handle->nodes[t].node_type = USER_SINK; 00267 /* We cannot place the introduced arc now because we don't yet 00268 * know the largest capacity in the problem. 00269 */ 00270 } 00271 handle->n_sinks_set++; 00272 return MFMC_NO_ERROR; 00273 } 00274 else { 00275 return MFMC_S_T_OVERLAP; 00276 } 00277 } 00278 00279 /* User interface to code to solve the flow/cut problem. Included in 00280 * mfmc_setup.c because we do the tail end of setup here before 00281 * passing the problem off to the solver. 00282 */ 00283 00284 MFMC_EC 00285 MFMC_Solve_problem(MFMC_HANDLE handle) 00286 { 00287 INT64 big_cap = handle->max_cap * handle->m; 00288 INT32 i; 00289 INT32 tail, 00290 last, 00291 arc_num, 00292 arc_new_num; 00293 INT64 cap; 00294 MFMC_ARC *arc_current, 00295 *arc_new, 00296 *arc_tmp; 00297 MFMC_NODE *head_p, 00298 *ndp; 00299 00300 if (handle->n_sources != handle->n_sources_set || 00301 handle->n_sinks != handle->n_sinks_set) { 00302 return MFMC_UNSEEN_S_T; 00303 } 00304 00305 if (handle->pos_current != 2 * handle->user_m) { 00306 return MFMC_BAD_ARC_COUNT; 00307 } 00308 00309 /* The following cheat is to pacify the arc count check in 00310 * MFMC_Place_arc. 00311 */ 00312 handle->user_m = handle->m; 00313 00314 if (handle->n_sources > 1) { 00315 /* Place a high capacity arc out of the source to each of the 00316 * user's sources. 00317 */ 00318 for (i = 0; i < handle->user_n; i++) { 00319 if (handle->nodes[i].node_type == USER_SOURCE) { 00320 MFMC_Place_arc(handle, handle->the_source - handle->nodes, i, 00321 0, big_cap, NULL); 00322 } 00323 } 00324 } 00325 00326 if (handle->n_sinks > 1) { 00327 /* Make an artificial sink and place a high capacity arc into it 00328 * from each of the user's sinks. 00329 */ 00330 for (i = handle->user_n; i >= 0; i--) { 00331 if (handle->nodes[i].node_type == USER_SINK) { 00332 MFMC_Place_arc(handle, i, handle->the_sink - handle->nodes, 00333 0, big_cap, NULL); 00334 } 00335 } 00336 } 00337 00338 FmtAssert(handle->pos_current == 2 * handle->m, 00339 ("Arc count mismatch in auxiliary source/sink placement")); 00340 00341 /* Now that there are no more arcs to place, build the ordered arc 00342 * and list and connect the node list to it. 00343 */ 00344 /********** ordering arcs - linear time algorithm ***********/ 00345 00346 /* first arc from the first node */ 00347 handle->nodes[0].first = handle->arcs; 00348 00349 /* before below loop arc_first[i+1] is the number of arcs outgoing 00350 * from i; after this loop arc_first[i] is the position of the first 00351 * outgoing from node i arcs after they would be ordered; this value 00352 * is transformed to pointer and written to node. 00353 */ 00354 00355 for (i = 1; i <= handle->n + 1; i++) { 00356 handle->arc_first[i] += handle->arc_first[i - 1]; 00357 handle->nodes[i].first = handle->arcs + handle->arc_first[i]; 00358 } 00359 00360 /* scanning all the nodes except the last */ 00361 for ( i = 0; i < handle->n; i++) { 00362 last = handle->nodes[i + 1].first - handle->arcs; 00363 /* arcs outgoing from i must be sited 00364 * from position arc_first[i] to the position 00365 * equal to initial value of arc_first[i+1]-1 00366 */ 00367 00368 for (arc_num = handle->arc_first[i]; 00369 arc_num < last; 00370 arc_num++) { 00371 tail = handle->arc_tail[arc_num]; 00372 00373 /* the arc no arc_num is not in place because arc sited here 00374 must go out from i; 00375 we'll put it to its place and continue this process 00376 until an arc in this position would go out from i */ 00377 00378 while ( tail != i ) { 00379 arc_new_num = handle->arc_first[tail]; 00380 arc_current = handle->arcs + arc_num; 00381 arc_new = handle->arcs + arc_new_num; 00382 00383 /* arc_current must be sited in the position arc_new 00384 swapping these arcs: */ 00385 00386 head_p = arc_new->head; 00387 arc_new->head = arc_current->head; 00388 arc_current->head = head_p; 00389 00390 cap = arc_new->r_cap; 00391 arc_new->r_cap = arc_current->r_cap; 00392 arc_current->r_cap = cap; 00393 00394 if (arc_new != arc_current->reverse) { 00395 arc_tmp = arc_new->reverse; 00396 arc_new->reverse = arc_current->reverse; 00397 arc_current->reverse = arc_tmp; 00398 00399 (arc_current->reverse)->reverse = arc_current; 00400 (arc_new->reverse)->reverse = arc_new; 00401 } 00402 00403 handle->arc_tail[arc_num] = handle->arc_tail[arc_new_num]; 00404 handle->arc_tail[arc_new_num] = tail; 00405 00406 /* we increase arc_first[tail] */ 00407 handle->arc_first[tail] ++ ; 00408 00409 tail = handle->arc_tail[arc_num]; 00410 } 00411 } 00412 /* all arcs outgoing from i are in place */ 00413 } 00414 00415 /* ----------------------- arcs are ordered ------------------------- */ 00416 00417 /*----------- constructing lists ---------------*/ 00418 00419 00420 for (ndp = handle->nodes; 00421 ndp <= handle->nodes + handle->n; 00422 ndp++) { 00423 ndp->first = NULL; 00424 } 00425 00426 /* Why do we maintain the "next" field for arcs? It would seem 00427 * always to be the case that (a->next == a + 1). 00428 */ 00429 for (arc_current = handle->arcs + (2 * handle->m - 1); 00430 arc_current >= handle->arcs; 00431 arc_current--) { 00432 arc_num = arc_current - handle->arcs; 00433 handle->acap[arc_num] = arc_current->r_cap; 00434 tail = handle->arc_tail[arc_num]; 00435 ndp = handle->nodes + tail; 00436 arc_current->next = ndp->first; 00437 ndp->first = arc_current; 00438 } 00439 00440 /* Free the arc_first and arc_tail memory */ 00441 MEM_POOL_Pop(handle->mem_pool); 00442 00443 /* Now solve the problem. */ 00444 MFMC_Find_max_flow_min_cut(handle->n, 00445 handle->nodes, 00446 handle->arcs, 00447 handle->acap, 00448 handle->the_source, 00449 handle->the_sink, 00450 handle->queue, 00451 handle->layers, 00452 big_cap, 00453 &handle->stats, 00454 &handle->flow_value); 00455 00456 /* Free the queue and layers memory used internally by the algorithm */ 00457 MEM_POOL_Pop(handle->mem_pool); 00458 00459 return MFMC_NO_ERROR; 00460 } 00461 00462 #endif