/* File: topology.c * Author: Jean Thierry-Mieg (mieg@mrc-lmba.cam.ac.uk) * Copyright (C) J Thierry-Mieg and R Durbin, 1992 * ------------------------------------------------------------------- * Acedb is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt * ------------------------------------------------------------------- * This file is part of the ACEDB genome database package, written by * Richard Durbin (MRC LMB, UK) rd@mrc-lmba.cam.ac.uk, and * Jean Thierry-Mieg (CRBM du CNRS, France) mieg@frmop11.bitnet * * Description: * Exported functions: topoConnectedComponents() * HISTORY: * Last edited: Mar 6 17:11 1996 (srk) * Created: Fri Oct 30 19:08:43 1992 (mieg) *------------------------------------------------------------------- */ /* $Id: topology.c,v 1.6 1999/09/01 10:57:41 fw Exp $ */ #include "acedb.h" #include "keyset.h" #include "topology.h" /********************************/ static int topoFirstKeyOrder(void*a, void*b) { return ((LINK*) a) -> a - ((LINK*) b)-> a ; } /**************************************/ static void topoDoubleUnorientedLinks(Array links) { register int i = arrayMax(links) ; register LINK *x , *y ; arrayExtend(links, 2*i) ; arrayMax(links) = 2*i ; x = arrp(links, 0, LINK) ; y = arrp(links, i, LINK) ; while(i--) { x -> group = y -> group = 0 ; *y = *x ; /* anything else, i.e. type */ y -> a = x -> b ; y -> b = x -> a ; x++ , y++ ; } arraySort(links, topoFirstKeyOrder) ; } /**************************************/ static void topoEnumerateVertex(Array links, Array vx) { register int i , n = arrayMax(links) , j = 0; register KEY k = 0 ; arrayMax(vx) = 0 ; for(i = 0 ; i < n ; i++) if ( k != arrp(links,i,LINK) -> a) { k = arrp(links,i,LINK) -> a ; array(vx, j, VERTEX).a = k ; array(vx, j, VERTEX).group = 0 ; array(vx, j, VERTEX).pos = i ; j++ ; } } /**************************************/ static Array VX, LK; static int GP ; /* number of the connected component */ /******************/ static int topoFindVertex(KEY k) { register int i = arrayMax(VX) ; while(i--) if(arrp(VX,i,VERTEX)->a == k) return i ; messcrash("Topofindvertex cannot find %d", k) ; return 0 ; /* for compiler happiness */ } /******************/ static void topoNCC2(int n) { KEY a = array(VX,n,VERTEX).a ; int pos = array(VX,n,VERTEX).pos ; array(VX,n,VERTEX).group = GP ; for(;pos < arrayMax(LK) && array(LK, pos,LINK).a == a;pos++) { n = topoFindVertex(array(LK, pos,LINK).b) ; if(!arr(VX,n,VERTEX).group) topoNCC2(n) ; else if(arr(VX,n,VERTEX).group != GP ) messcrash ("topoNCC2 : Double numbering, sorry") ; } } /******************/ static void topoNumberLinks(Array links) { KEY a ; register int i = arrayMax(links), n ; while(i--) { a = arr(links,i,LINK).a ; n = topoFindVertex(a) ; arr(links,i,LINK).group = arr(VX,n,VERTEX).group ; } } /*****************/ static int topoNumberConnectedComponents(Array links, Array vx) { register int n = arrayMax(vx) ; VX = vx ; LK = links; GP = 0 ; while(n--) if(! arr(vx,n,VERTEX).group) { GP++ ; topoNCC2(n) ; } return GP ; } /**************************************************************/ /************* Public Routines ********************************/ int topoConnectedComponents(Array links, Array vx) { Array cpLinks = arrayCopy(links) ; int i ; if(!arrayExists(links) || !arrayExists(vx)) messcrash("topoConnectedComponents called with bad array") ; topoDoubleUnorientedLinks(cpLinks) ; topoEnumerateVertex(cpLinks, vx) ; i = topoNumberConnectedComponents(cpLinks, vx) ; arrayDestroy(cpLinks) ; topoNumberLinks(links) ; return i ; } /**************************************************************/ /**************************************************************/