Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
mfmc_setup.cxx
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines