Path: blob/devel/elmergrid/src/metis-5.1.0/libmetis/checkgraph.c
3206 views
/*1* Copyright 1997, Regents of the University of Minnesota2*3* checkgraph.c4*5* This file contains routines related to I/O6*7* Started 8/28/948* George9*10*/1112#include "metislib.h"13141516/*************************************************************************/17/*! This function checks if a graph is valid. A valid graph must satisfy18the following constraints:19- It should contain no self-edges.20- It should be undirected; i.e., (u,v) and (v,u) should be present.21- The adjacency list should not contain multiple edges to the same22other vertex.2324\param graph is the graph to be checked, whose numbering starts from 0.25\param numflag is 0 if error reporting will be done using 0 as the26numbering, or 1 if the reporting should be done using 1.27\param verbose is 1 the identified errors will be displayed, or 0, if28it should run silently.29*/30/*************************************************************************/31int CheckGraph(graph_t *graph, int numflag, int verbose)32{33idx_t i, j, k, l;34idx_t nvtxs, err=0;35idx_t minedge, maxedge, minewgt, maxewgt;36idx_t *xadj, *adjncy, *adjwgt, *htable;3738numflag = (numflag == 0 ? 0 : 1); /* make sure that numflag is 0 or 1 */3940nvtxs = graph->nvtxs;41xadj = graph->xadj;42adjncy = graph->adjncy;43adjwgt = graph->adjwgt;4445ASSERT(adjwgt != NULL);4647htable = ismalloc(nvtxs, 0, "htable");4849minedge = maxedge = adjncy[0];50minewgt = maxewgt = adjwgt[0];5152for (i=0; i<nvtxs; i++) {53for (j=xadj[i]; j<xadj[i+1]; j++) {54k = adjncy[j];5556minedge = (k < minedge) ? k : minedge;57maxedge = (k > maxedge) ? k : maxedge;58minewgt = (adjwgt[j] < minewgt) ? adjwgt[j] : minewgt;59maxewgt = (adjwgt[j] > maxewgt) ? adjwgt[j] : maxewgt;6061if (i == k) {62if (verbose)63printf("Vertex %"PRIDX" contains a self-loop "64"(i.e., diagonal entry in the matrix)!\n", i+numflag);65err++;66}67else {68for (l=xadj[k]; l<xadj[k+1]; l++) {69if (adjncy[l] == i) {70if (adjwgt[l] != adjwgt[j]) {71if (verbose)72printf("Edges (u:%"PRIDX" v:%"PRIDX" wgt:%"PRIDX") and "73"(v:%"PRIDX" u:%"PRIDX" wgt:%"PRIDX") "74"do not have the same weight!\n",75i+numflag, k+numflag, adjwgt[j],76k+numflag, i+numflag, adjwgt[l]);77err++;78}79break;80}81}82if (l == xadj[k+1]) {83if (verbose)84printf("Missing edge: (%"PRIDX" %"PRIDX")!\n", k+numflag, i+numflag);85err++;86}87}8889if (htable[k] == 0) {90htable[k]++;91}92else {93if (verbose)94printf("Edge %"PRIDX" from vertex %"PRIDX" is repeated %"PRIDX" times\n",95k+numflag, i+numflag, htable[k]++);96err++;97}98}99100for (j=xadj[i]; j<xadj[i+1]; j++)101htable[adjncy[j]] = 0;102}103104105if (err > 0 && verbose) {106printf("A total of %"PRIDX" errors exist in the input file. "107"Correct them, and run again!\n", err);108}109110gk_free((void **)&htable, LTERM);111112return (err == 0 ? 1 : 0);113}114115116/*************************************************************************/117/*! This function performs a quick check of the weights of the graph */118/*************************************************************************/119int CheckInputGraphWeights(idx_t nvtxs, idx_t ncon, idx_t *xadj, idx_t *adjncy,120idx_t *vwgt, idx_t *vsize, idx_t *adjwgt)121{122idx_t i;123124if (ncon <= 0) {125printf("Input Error: ncon must be >= 1.\n");126return 0;127}128129if (vwgt) {130for (i=ncon*nvtxs; i>=0; i--) {131if (vwgt[i] < 0) {132printf("Input Error: negative vertex weight(s).\n");133return 0;134}135}136}137if (vsize) {138for (i=nvtxs; i>=0; i--) {139if (vsize[i] < 0) {140printf("Input Error: negative vertex sizes(s).\n");141return 0;142}143}144}145if (adjwgt) {146for (i=xadj[nvtxs]-1; i>=0; i--) {147if (adjwgt[i] < 0) {148printf("Input Error: non-positive edge weight(s).\n");149return 0;150}151}152}153154return 1;155}156157158/*************************************************************************/159/*! This function creates a graph whose topology is consistent with160Metis' requirements that:161- There are no self-edges.162- It is undirected; i.e., (u,v) and (v,u) should be present and of the163same weight.164- The adjacency list should not contain multiple edges to the same165other vertex.166167Any of the above errors are fixed by performing the following operations:168- Self-edges are removed.169- The undirected graph is formed by the union of edges.170- One of the duplicate edges is selected.171172The routine does not change the provided vertex weights.173*/174/*************************************************************************/175graph_t *FixGraph(graph_t *graph)176{177idx_t i, j, k, l, nvtxs, nedges;178idx_t *xadj, *adjncy, *adjwgt;179idx_t *nxadj, *nadjncy, *nadjwgt;180graph_t *ngraph;181uvw_t *edges;182183184nvtxs = graph->nvtxs;185xadj = graph->xadj;186adjncy = graph->adjncy;187adjwgt = graph->adjwgt;188ASSERT(adjwgt != NULL);189190ngraph = CreateGraph();191192ngraph->nvtxs = nvtxs;193194/* deal with vertex weights/sizes */195ngraph->ncon = graph->ncon;196ngraph->vwgt = icopy(nvtxs*graph->ncon, graph->vwgt,197imalloc(nvtxs*graph->ncon, "FixGraph: vwgt"));198199ngraph->vsize = ismalloc(nvtxs, 1, "FixGraph: vsize");200if (graph->vsize)201icopy(nvtxs, graph->vsize, ngraph->vsize);202203/* fix graph by sorting the "superset" of edges */204edges = (uvw_t *)gk_malloc(sizeof(uvw_t)*2*xadj[nvtxs], "FixGraph: edges");205206for (nedges=0, i=0; i<nvtxs; i++) {207for (j=xadj[i]; j<xadj[i+1]; j++) {208/* keep only the upper-trianglular part of the adjacency matrix */209if (i < adjncy[j]) {210edges[nedges].u = i;211edges[nedges].v = adjncy[j];212edges[nedges].w = adjwgt[j];213nedges++;214}215else if (i > adjncy[j]) {216edges[nedges].u = adjncy[j];217edges[nedges].v = i;218edges[nedges].w = adjwgt[j];219nedges++;220}221}222}223224uvwsorti(nedges, edges);225226227/* keep the unique subset */228for (k=0, i=1; i<nedges; i++) {229if (edges[k].v != edges[i].v || edges[k].u != edges[i].u) {230edges[++k] = edges[i];231}232}233nedges = k+1;234235/* allocate memory for the fixed graph */236nxadj = ngraph->xadj = ismalloc(nvtxs+1, 0, "FixGraph: nxadj");237nadjncy = ngraph->adjncy = imalloc(2*nedges, "FixGraph: nadjncy");238nadjwgt = ngraph->adjwgt = imalloc(2*nedges, "FixGraph: nadjwgt");239240/* create the adjacency list of the fixed graph from the upper-triangular241part of the adjacency matrix */242for (k=0; k<nedges; k++) {243nxadj[edges[k].u]++;244nxadj[edges[k].v]++;245}246MAKECSR(i, nvtxs, nxadj);247248for (k=0; k<nedges; k++) {249nadjncy[nxadj[edges[k].u]] = edges[k].v;250nadjncy[nxadj[edges[k].v]] = edges[k].u;251nadjwgt[nxadj[edges[k].u]] = edges[k].w;252nadjwgt[nxadj[edges[k].v]] = edges[k].w;253nxadj[edges[k].u]++;254nxadj[edges[k].v]++;255}256SHIFTCSR(i, nvtxs, nxadj);257258gk_free((void **)&edges, LTERM);259260return ngraph;261}262263264265