eg_shrink_graph.c

Go to the documentation of this file.
00001 /* EGlib "Efficient General Library" provides some basic structures and
00002  * algorithms commons in many optimization algorithms.
00003  *
00004  * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
00005  * 
00006  * This library is free software; you can redistribute it and/or modify it
00007  * under the terms of the GNU Lesser General Public License as published by the
00008  * Free Software Foundation; either version 2.1 of the License, or (at your
00009  * option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful, but 
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
00013  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
00014  * License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this library; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
00019  * */
00020 /** @file 
00021  * @ingroup EGsrkGraph */
00022 /** @addtogroup EGsrkGraph */
00023 /** @{ */
00024 /* ========================================================================= */
00025 #include "eg_shrink_graph.h"
00026 
00027 /* ========================================================================= */
00028 EGsrkNode_t *EGsrkIdentifyNodes (EGsrkGraph_t * const G,
00029                                  EGsrkNode_t * const base,
00030                                  EGsrkNode_t * const srkN)
00031 {
00032   EGsrkNode_t *o_end;
00033   EGsrkEdge_t *c_edge,
00034    *o_edge;
00035   EGeUgraphEP_t *c_ep;
00036   EGeList_t *e_it,
00037    *e_end,
00038    *e_next;
00039   unsigned o_type;
00040   /* now we start performing the srhinking procedure */
00041   EGesLink (&(base->parent), &(srkN->parent));
00042   EGlpNumAddTo (base->weight, srkN->weight);
00043   /* first put the other elements in the shrunken node list in the new list */
00044   EGeListSplice (&(srkN->members), &(base->members));
00045   /* and then put the srunken element in the new member list */
00046   EGeListAddAfter (&(srkN->members), &(base->members));
00047   base->mmb_sz += srkN->mmb_sz + 1;
00048 
00049   /* now we initialize all things related to the base node */
00050   e_end = &(base->node.edges);
00051   for (e_it = e_end->next; e_it != e_end; e_it = e_it->next)
00052   {
00053     c_ep = EGcontainerOf (e_it, EGeUgraphEP_t, cn);
00054     c_edge = EGcontainerOf (c_ep, EGsrkEdge_t, edge.ep[c_ep->type]);
00055     o_type = c_ep->type ? 0 : 1;
00056     o_end = EGcontainerOf (c_edge->edge.ep[o_type].node, EGsrkNode_t, node);
00057     o_end->hit = c_edge;
00058   }
00059   e_end = &(srkN->node.edges);
00060   e_next = e_it = e_end->next;
00061   /* we have to be carefull, note that we will move the endpoint pointed by
00062    * e_it, so we keep also the next iterator when we enter the iteration */
00063   for (; e_it != e_end; e_it = e_next)
00064   {
00065     e_next = e_next->next;
00066     c_ep = EGcontainerOf (e_it, EGeUgraphEP_t, cn);
00067     c_edge = EGcontainerOf (c_ep, EGsrkEdge_t, edge.ep[c_ep->type]);
00068     o_type = c_ep->type ? 0 : 1;
00069     o_end = EGcontainerOf (c_edge->edge.ep[o_type].node, EGsrkNode_t, node);
00070     /* if the edge will become a loop, we delete it from the graph */
00071     if (o_end == base)
00072     {
00073       EGlpNumSubTo (base->weight, c_edge->weight);
00074       EGlpNumSubTo (base->weight, c_edge->weight);
00075       EGeUgraphDelEdge (&(G->G), &(c_edge->edge));
00076       continue;
00077     }
00078     o_edge = o_end->hit;
00079     /* now if this edge touch a previously untouch node, just change it's
00080      * endpoint */
00081     if (!o_edge)
00082     {
00083       EGeUgraphChangeEP (&(G->G), &(c_edge->edge), &(base->node), c_ep->type);
00084       continue;
00085     }
00086     /* otherwise, this edge is entering an already touched node, in wich case,
00087      * we update the weight of the edge already in place, splice the
00088      * edge-members list, update it's size, and delete this current edge */
00089     EGlpNumAddTo (o_edge->weight, c_edge->weight);
00090     EGeListSplice (&(c_edge->members), &(o_edge->members));
00091     EGeListAddAfter (&(c_edge->members), &(o_edge->members));
00092     o_edge->mmb_sz += c_edge->mmb_sz + 1;
00093     EGeUgraphDelEdge (&(G->G), &(c_edge->edge));
00094   }
00095   /* now we finally delete the shrunken node from the graph. */
00096   EGeUgraphDelNode (&(G->G), &(srkN->node));
00097 
00098   /* and reset the hit list to NULL */
00099   e_end = &(base->node.edges);
00100   for (e_it = e_end->next; e_end != e_it; e_it = e_it->next)
00101   {
00102     c_ep = EGcontainerOf (e_it, EGeUgraphEP_t, cn);
00103     c_edge = EGcontainerOf (c_ep, EGsrkEdge_t, edge.ep[c_ep->type]);
00104     o_type = c_ep->type ? 0 : 1;
00105     o_end = EGcontainerOf (c_edge->edge.ep[o_type].node, EGsrkNode_t, node);
00106     o_end->hit = 0;
00107   }
00108 
00109   /* ending */
00110   return base;
00111 }
00112 
00113 /* ========================================================================= */
00114 /** @}
00115  * end of eg_shrink_graph.c */

Generated on Mon Jan 30 08:48:54 2006 for EGlib by  doxygen 1.4.5