//-------------------------------------------------------------------------------------------------- //----------------------------------- Message Creators---------------------------------------------- //-------------------------------------------------------------------------------------------------- mvec *SumRowsOrCols(nodes *factornode, nodes *previousnode, char specify) { //Sums rows of columns of a matrix represented as a vector //Specify 'f' for forwardtraverse 'b' for backward traverse //Produces array //Vector is assumed to be Row Major hfactor* fnhfac = (hfactor *)factornode->ndata; hfactor* pnhfac = (hfactor *)previousnode->ndata; mvec *messagein; if(specify=='f') { messagein = fnhfac->messagesin[0]; } else { messagein = fnhfac->bmessagesin[0]; } mvec *message = (mvec *)imalloc(E,1*sizeof(mvec)); int nrow = fnhfac->nrow; int ncol = fnhfac->ncol; double *matrix = fnhfac->probdist; double *result; int i,j; //Determine length of resulting vector if(fnhfac->columnlabel == previousnode->nhash) //If the previousnode is represented in column { //Then the length of vector = to number of rows result = (double *)imalloc(E,nrow*sizeof(double)); message->length = nrow; //Multiply incoming message -- which should only be 1 message as its a factor node //Then sum i=0; for(i;i<nrow;i++) { result[i]=0; j=0; for(j;j<ncol;j++) { result[i]=result[i]+matrix[i*ncol+j]*(messagein->vector[j]); } } } else //If the previousnode is represented in the rows { //Then the length of vector = number of columns result = (double *)imalloc(E,ncol*sizeof(double)); message->length = ncol; //Multiply incoming message -- which should only be 1 message as its a factor node //Then sum j=0; for(j;j<ncol;j++) { result[j]=0; i=0; for(i;i<nrow;i++) { result[j]=result[j]+matrix[i*ncol+j]*(messagein->vector[i]); } } } message->sender = factornode->nhash; message->vector = result; NormaliseMVEC(message); return message; }
void backwardtraverse(nodes *currentnode,nodes *callingnode, hgph *graph) { //--------------------------Go down and update nodes int nbranches = currentnode->nedges; //When further down the tree, every edge except the calling edge is forward int nforwardbranches = nbranches - 1; //If root node, every edge is a forward edge if(currentnode==callingnode) nforwardbranches = nbranches; char type = ((hfactor*)currentnode->ndata)->type; char callingobs = ((hfactor*)callingnode->ndata)->observed; nodes *nextnode; //-----------------------------Find forward branches------------------------------------------------- //Already computed in forward traverse unsigned *forwardedges = ((hfactor*)currentnode->ndata)->fedges; //-----------------------------Calculate & send message first---------------------------------------------------- if (currentnode==callingnode) //If this is the root node --- Message is 1 if only 1 branch, product of messages if not { int msgveclength; mvec *message; int k = 0; if(nforwardbranches == 1) //If only has 1 outgoing connection { message = (mvec *)imalloc(E,1*sizeof(mvec)); //Allocate memory for message nextnode= find_node(forwardedges[0],graph->nnodes,graph->nodelist); //Determine length of message vector if(((hfactor *)nextnode->ndata)->columnlabel == currentnode->nhash) //If prob dist column is for the current node, { msgveclength = ((hfactor *)nextnode->ndata)->ncol; } else { msgveclength = ((hfactor *)nextnode->ndata)->nrow; } //Allocate memory for vector and initialise value to 1 as per theory double *msgvec = (double *)imalloc(E,msgveclength*sizeof(double)); int i; for(i=0;i<msgveclength;i++) { msgvec[i] = 1; } message->vector = msgvec; message->sender = currentnode->nhash; message->length = msgveclength; addmessagetonodeB(message, nextnode); //Attach full message to callingnode } else //If it has multiple outgoing connections { for(k;k<nforwardbranches;k++) // For each nextnode { nextnode = find_node(forwardedges[k],graph->nnodes,graph->nodelist); message = productofmessagesinB(currentnode, nextnode); addmessagetonodeB(message, nextnode); } } } else if (type == 'v') //If this is a variable node --- Product of messages in { mvec *message; int k = 0; for(k;k<nforwardbranches;k++) // For each nextnode { nextnode = find_node(forwardedges[k],graph->nnodes,graph->nodelist); message = productofmessagesinB(currentnode, nextnode); addmessagetonodeB(message, nextnode); } } else //If this is a factor node --- Sum of row/column multiplied by previous messages --- Factor node only connected to 2 nodes { if(((hfactor*)callingnode->ndata)->observed == 'f') //If it is unobserved { nextnode = find_node(forwardedges[0],graph->nnodes,graph->nodelist); mvec *message; if(((hfactor*)nextnode->ndata)->observed == 't') //If the nextnode is observed { message = MsgToObservedNode(currentnode, nextnode); } else //Else if calling node not observed { message = SumRowsOrCols(currentnode, callingnode,'b'); } addmessagetonodeB(message, nextnode); } else //If it is observed { mvec *message; nextnode = find_node(forwardedges[0],graph->nnodes,graph->nodelist); if(((hfactor*)nextnode->ndata)->observed == 't') //If the nextnode is observed { message = MsgToObservedNode(currentnode, nextnode); } else { message = sumobservednode(currentnode, callingnode); } addmessagetonodeB(message, nextnode); } } //-------------------------------Recurse Down------------------------------------------------------- int i=0; for(i; i<nforwardbranches; i++) { nextnode = find_node(forwardedges[i],graph->nnodes,graph->nodelist); backwardtraverse(nextnode,currentnode,graph); } //Return from Recursion return; }
void calculatemarginals(hgph *graph) { //-----------------------Calculate marginals at all the variable nodes //------Done by calculating product of messages nodes **nodelist = graph->nodelist; int nnodes = graph->nnodes; nodes *currentnode; hfactor *currenthfac; mvec *margvec; mvec *currentmessage; double *vec; int length,nmessages,nbmessages; int i = 0; int j,k,m; for(i;i<nnodes;i++) //for every node { margvec = (mvec *)imalloc(E,1*sizeof(mvec)); currentnode = nodelist[i]; currenthfac = (hfactor *)currentnode->ndata; nmessages = currenthfac->nmessages; nbmessages = currenthfac->nbmessages; //Does a check if it is a variable node if(currenthfac->type == 'f') continue; //Length of messages will all be same, must have 1 message either in or out if(nmessages!=0) length = currenthfac->messagesin[0]->length; else if(nbmessages!= 0) length = currenthfac->bmessagesin[0]->length; //Allocate memory vec = (double *)imalloc(E,length*sizeof(double)); margvec->length = length; for(k=0;k<length;k++)//For every element in the vector initialise to 1 { vec[k] = 1; } if(nmessages!=0) //If there is forward message { j = 0; for(j;j<nmessages;j++) //For every messagein (Forward) { currentmessage = currenthfac->messagesin[j]; for(k=0;k<length;k++)//For every element in the vector { vec[k] = vec[k]*currentmessage->vector[k]; } } } if(nbmessages!=0) //If there is backward message { j = 0; for(j;j<nbmessages;j++) //For every messagein (Backward) { currentmessage = currenthfac->bmessagesin[j]; for(k=0;k<length;k++)//For every element in the vector { vec[k] = vec[k]*currentmessage->vector[k]; } } } //Normalise //1. Sum double sumofelements= 0.0; for(m=0;m<length;m++) //For every element - find sum { sumofelements = sumofelements + vec[m]; } //2. Divide by sum for(m=0;m<length;m++) //For every element - find sum { vec[m] = vec[m]/sumofelements; } //Append margvec->vector = vec; currenthfac->marginal = margvec; } return; }
void forwardtraverse(nodes *currentnode,nodes *callingnode, hgph *graph) { //-----------------------Go down to leaf and come up int nbranches = currentnode->nedges; //When further down the tree, every edge except the calling edge is forward int nforwardbranches = nbranches - 1; //If root node, every edge is a forward edge if(currentnode==callingnode) nforwardbranches = nbranches; char type = ((hfactor*)currentnode->ndata)->type; nodes *nextnode; //----If at leaf go up----- //----Leaf is the terminal nodes of the tree, as far as can go. if(nforwardbranches==0) { mvec *message = (mvec *)imalloc(E,1*sizeof(mvec)); //Allocate memory for message //Determine length of message vector int msgveclength; if(((hfactor *)callingnode->ndata)->columnlabel == currentnode->nhash) //If prob dist column is for the current node, { msgveclength = ((hfactor *)callingnode->ndata)->ncol; } else { msgveclength = ((hfactor *)callingnode->ndata)->nrow; } //Allocate memory for vector and initialise value to 1 as per theory double *msgvec = (double *)imalloc(E,msgveclength*sizeof(double)); int i = 0; for(i;i<msgveclength;i++) { msgvec[i] = 1; } message->vector = msgvec; message->sender = currentnode->nhash; message->length = msgveclength; addmessagetonode(message, callingnode); //Attach full message to callingnode return; } //----If not at leaf, go down & come up---------- else { //Copy edge list & remove calling node from the list unsigned *forwardedges = (unsigned *)imalloc(E,nforwardbranches*sizeof(unsigned)); //list of edges to pursue int j = 0; char callingnodefound = 'f'; for( j; j<nbranches; j++) { if(callingnodefound =='f') { if(currentnode->edge[j]==callingnode->nhash) { callingnodefound = 't'; continue; } else forwardedges[j] = currentnode->edge[j]; } else forwardedges[j-1] = currentnode->edge[j]; } ((hfactor *)currentnode->ndata)->fedges = forwardedges; //Saves the list to the structure //RECURSION DOWN int i=0; for(i; i<nforwardbranches; i++) { nextnode = find_node(forwardedges[i],graph->nnodes,graph->nodelist); forwardtraverse(nextnode,currentnode,graph); } //RETURNING FROM RECURSION //What happens on this level before going up //Results are appended to the calling node if(currentnode==callingnode) return; //If this is the root node, forward traverse ends if(type == 'v') //variable -- product of factor messages { mvec *message = productofmessagesin(currentnode,'f'); //Products all the factor messages addmessagetonode(message, callingnode); return; } else if(type == 'f') //factor --- sum marginals { //Previous node is next node and next node is calling node if(((hfactor*)nextnode->ndata)->observed == 'f') //If the previous node was unobserved { mvec *message; if(((hfactor*)callingnode->ndata)->observed == 't') //If the nextnode is observed { message = MsgToObservedNode(currentnode, callingnode); } else //Else if calling node not observed { message = SumRowsOrCols(currentnode, nextnode,'f'); } addmessagetonode(message,callingnode); } else //If the previous node was observed - take only the associated row or column { mvec *message; if(((hfactor*)callingnode->ndata)->observed == 't') //If the next node is observed { message = MsgToObservedNode(currentnode, callingnode); } else { message = sumobservednode(currentnode, nextnode); } addmessagetonode(message,callingnode); } return; } } }
void *sumproduct_setupproblem(void *arglist) { //--------------------------- Creates nodes and sets up model--------------------------------------- void *argptr; nodes *x1, *fa, *x2, *fb, *x3, *fc, *x4; hgph *graph; //Get previous hgph struct if(dynamic_getarg(arglist,"hgph",&argptr)=='f') return NULL; if(!invalidptr(E,argptr)) graph=(hgph *) argptr; //Sets up nodes in their places x1 = createnode(1,5,"x1",graph,'v'); fa = createnode(3,5,"fa",graph,'f'); x2 = createnode(5,5,"x2",graph,'v'); fb = createnode(7,5,"fb",graph,'f'); x3 = createnode(9,5,"x3",graph,'v'); fc = createnode(5,3,"fc",graph,'f'); x4 = createnode(5,1,"x4",graph,'v'); //Adds directed edge between mu and x add_edge(x1,fa); add_edge(fa,x2); add_edge(x2,fb); add_edge(fb,x3); add_edge(x4,fc); add_edge(fc,x2); //Create probability distribution table /*Row Major Ordering EG: {11 12 13 21 22 23 31 32 33} Becomes {11 12 13 21 22 23 31 32 33} */ double *probdist1; //fc probdist1 =(double *)imalloc(E,6*sizeof(double)); /* probdist1[0] = 1.0; probdist1[1] = 0.1; probdist1[2] = 0.1; probdist1[3] = 1.0; */ // probdist1[0] = 0.3; // probdist1[1] = 0.4; // probdist1[2] = 0.3; // probdist1[3] = 0.0; probdist1[0] = 0.3; probdist1[1] = 0.4; probdist1[2] = 0.5; probdist1[3] = 0.3; probdist1[4] = 0.1; probdist1[5] = 0.6; double *probdist2; //fa probdist2 =(double *)imalloc(E,6*sizeof(double)); /* probdist2[0] = 1.0; probdist2[1] = 0.9; probdist2[2] = 0.9; probdist2[3] = 1.0; */ // probdist2[0] = 0.5; // probdist2[1] = 0.2; // probdist2[2] = 0.3; // probdist2[3] = 0.5; probdist2[0] = 0.5; probdist2[1] = 0.2; probdist2[2] = 0.3; probdist2[3] = 0.5; probdist2[4] = 0.1; probdist2[5] = 0.2; double *probdist3; //fb probdist3 =(double *)imalloc(E,6*sizeof(double)); /* probdist3[0] = 0.1; probdist3[1] = 1.0; probdist3[2] = 1.0; probdist3[3] = 0.1; */ // probdist3[0] = 0.7; // probdist3[1] = 0.2; // probdist3[2] = 0.1; // probdist3[3] = 0.3; probdist3[0] = 0.7; probdist3[1] = 0.2; probdist3[2] = 0.3; probdist3[3] = 0.1; probdist3[4] = 0.3; probdist3[5] = 0.5; //Populate factor payloads with probability distribution double *discretevalue = (double *)imalloc(E,2*sizeof(double)); discretevalue[0] = 0.0; discretevalue[1] = 1.0; double *disval = (double *)imalloc(E,3*sizeof(double)); disval[0] = 0.0; disval[1] = 1.0; disval[2] = 2.0; ((hfactor *)fa->ndata)->probdist = probdist2; ((hfactor *)fa->ndata)->columndiscretevalues = discretevalue; ((hfactor *)fa->ndata)->rowdiscretevalues = disval; ((hfactor *)fa->ndata)->columnlabel = str_hash("x1"); ((hfactor *)fa->ndata)->rowlabel = str_hash("x2"); ((hfactor *)fa->ndata)->ncol = 2; ((hfactor *)fa->ndata)->nrow = 3; ((hfactor *)fb->ndata)->probdist = probdist3; ((hfactor *)fb->ndata)->columndiscretevalues = disval; ((hfactor *)fb->ndata)->rowdiscretevalues = discretevalue; ((hfactor *)fb->ndata)->columnlabel = str_hash("x2"); ((hfactor *)fb->ndata)->rowlabel = str_hash("x3"); ((hfactor *)fb->ndata)->ncol = 3; ((hfactor *)fb->ndata)->nrow = 2; ((hfactor *)fc->ndata)->probdist = probdist1; ((hfactor *)fc->ndata)->columndiscretevalues = disval; ((hfactor *)fc->ndata)->rowdiscretevalues = discretevalue; ((hfactor *)fc->ndata)->columnlabel = str_hash("x2"); ((hfactor *)fc->ndata)->rowlabel = str_hash("x4"); ((hfactor *)fc->ndata)->ncol = 3; ((hfactor *)fc->ndata)->nrow = 2; //Test observed node ((hfactor *)x1->ndata)->observed = 't'; ((hfactor *)x1->ndata)->observedvariable = 1.0; //Output to arglist arglist=NULL; dynamic_putarg("graph.hgph","hgph",(void *)graph,SZ,&arglist); return arglist; }
static bool ctl_grow(void) { ctl_arena_stats_t *astats; arena_t **tarenas; /* Allocate extended arena stats and arenas arrays. */ astats = (ctl_arena_stats_t *)imalloc((ctl_stats.narenas + 2) * sizeof(ctl_arena_stats_t)); if (astats == NULL) return (true); tarenas = (arena_t **)imalloc((ctl_stats.narenas + 1) * sizeof(arena_t *)); if (tarenas == NULL) { idalloc(astats); return (true); } /* Initialize the new astats element. */ memcpy(astats, ctl_stats.arenas, (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t)); memset(&astats[ctl_stats.narenas + 1], 0, sizeof(ctl_arena_stats_t)); if (ctl_arena_init(&astats[ctl_stats.narenas + 1])) { idalloc(tarenas); idalloc(astats); return (true); } /* Swap merged stats to their new location. */ { ctl_arena_stats_t tstats; memcpy(&tstats, &astats[ctl_stats.narenas], sizeof(ctl_arena_stats_t)); memcpy(&astats[ctl_stats.narenas], &astats[ctl_stats.narenas + 1], sizeof(ctl_arena_stats_t)); memcpy(&astats[ctl_stats.narenas + 1], &tstats, sizeof(ctl_arena_stats_t)); } /* Initialize the new arenas element. */ tarenas[ctl_stats.narenas] = NULL; { arena_t **arenas_old = arenas; /* * Swap extended arenas array into place. Although ctl_mtx * protects this function from other threads extending the * array, it does not protect from other threads mutating it * (i.e. initializing arenas and setting array elements to * point to them). Therefore, array copying must happen under * the protection of arenas_lock. */ malloc_mutex_lock(&arenas_lock); arenas = tarenas; memcpy(arenas, arenas_old, ctl_stats.narenas * sizeof(arena_t *)); narenas_total++; arenas_extend(narenas_total - 1); malloc_mutex_unlock(&arenas_lock); /* * Deallocate arenas_old only if it came from imalloc() (not * base_alloc()). */ if (ctl_stats.narenas != narenas_auto) idalloc(arenas_old); } ctl_stats.arenas = astats; ctl_stats.narenas++; return (false); }
/************************************************************************* * This function returns the min-cover of a bipartite graph. * The algorithm used is due to Hopcroft and Karp as modified by Duff etal * adj: the adjacency list of the bipartite graph * asize: the number of vertices in the first part of the bipartite graph * bsize-asize: the number of vertices in the second part * 0..(asize-1) > A vertices * asize..bsize > B vertices * * Returns: * cover : the actual cover (array) * csize : the size of the cover **************************************************************************/ void MinCover(idx_t *xadj, idx_t *adjncy, idx_t asize, idx_t bsize, idx_t *cover, idx_t *csize) { idx_t i, j; idx_t *mate, *queue, *flag, *level, *lst; idx_t fptr, rptr, lstptr; idx_t row, maxlevel, col; mate = ismalloc(bsize, -1, "MinCover: mate"); flag = imalloc(bsize, "MinCover: flag"); level = imalloc(bsize, "MinCover: level"); queue = imalloc(bsize, "MinCover: queue"); lst = imalloc(bsize, "MinCover: lst"); /* Get a cheap matching */ for (i = 0; i < asize; i++) { for (j = xadj[i]; j < xadj[i + 1]; j++) { if (mate[adjncy[j]] == -1) { mate[i] = adjncy[j]; mate[adjncy[j]] = i; break; } } } /* Get into the main loop */ while (1) { /* Initialization */ fptr = rptr = 0; /* Empty Queue */ lstptr = 0; /* Empty List */ for (i = 0; i < bsize; i++) { level[i] = -1; flag[i] = 0; } maxlevel = bsize; /* Insert free nodes into the queue */ for (i = 0; i < asize; i++) { if (mate[i] == -1) { queue[rptr++] = i; level[i] = 0; } } /* Perform the BFS */ while (fptr != rptr) { row = queue[fptr++]; if (level[row] < maxlevel) { flag[row] = 1; for (j = xadj[row]; j < xadj[row + 1]; j++) { col = adjncy[j]; if (!flag[col]) { /* If this column has not been accessed yet */ flag[col] = 1; if (mate[col] == -1) { /* Free column node was found */ maxlevel = level[row]; lst[lstptr++] = col; } else { /* This column node is matched */ if (flag[mate[col]]) { printf("\nSomething wrong, flag[%"PRIDX"] is 1", mate[col]); } queue[rptr++] = mate[col]; level[mate[col]] = level[row] + 1; } } } } } if (lstptr == 0) { break; } /* No free columns can be reached */ /* Perform restricted DFS from the free column nodes */ for (i = 0; i < lstptr; i++) MinCover_Augment(xadj, adjncy, lst[i], mate, flag, level, maxlevel); } MinCover_Decompose(xadj, adjncy, asize, bsize, mate, cover, csize); gk_free((void **) &mate, &flag, &level, &queue, &lst, LTERM); }
void CreateGraphNodal(idx_t ne, idx_t nn, idx_t *eptr, idx_t *eind, idx_t **r_xadj, idx_t **r_adjncy) { idx_t i, j, nnbrs; idx_t *nptr, *nind; idx_t *xadj, *adjncy; idx_t *marker, *nbrs; /* construct the node-element list first */ nptr = ismalloc(nn+1, 0, "CreateGraphNodal: nptr"); nind = imalloc(eptr[ne], "CreateGraphNodal: nind"); for (i=0; i<ne; i++) { for (j=eptr[i]; j<eptr[i+1]; j++) nptr[eind[j]]++; } MAKECSR(i, nn, nptr); for (i=0; i<ne; i++) { for (j=eptr[i]; j<eptr[i+1]; j++) nind[nptr[eind[j]]++] = i; } SHIFTCSR(i, nn, nptr); /* Allocate memory for xadj, since you know its size. These are done using standard malloc as they are returned to the calling function */ if ((xadj = (idx_t *)malloc((nn+1)*sizeof(idx_t))) == NULL) gk_errexit(SIGMEM, "***Failed to allocate memory for xadj.\n"); *r_xadj = xadj; iset(nn+1, 0, xadj); /* allocate memory for working arrays used by FindCommonElements */ marker = ismalloc(nn, 0, "CreateGraphNodal: marker"); nbrs = imalloc(nn, "CreateGraphNodal: nbrs"); for (i=0; i<nn; i++) { xadj[i] = FindCommonNodes(i, nptr[i+1]-nptr[i], nind+nptr[i], eptr, eind, marker, nbrs); } MAKECSR(i, nn, xadj); /* Allocate memory for adjncy, since you now know its size. These are done using standard malloc as they are returned to the calling function */ if ((adjncy = (idx_t *)malloc(xadj[nn]*sizeof(idx_t))) == NULL) { free(xadj); *r_xadj = NULL; gk_errexit(SIGMEM, "***Failed to allocate memory for adjncy.\n"); } *r_adjncy = adjncy; for (i=0; i<nn; i++) { nnbrs = FindCommonNodes(i, nptr[i+1]-nptr[i], nind+nptr[i], eptr, eind, marker, nbrs); for (j=0; j<nnbrs; j++) adjncy[xadj[i]++] = nbrs[j]; } SHIFTCSR(i, nn, xadj); gk_free((void **)&nptr, &nind, &marker, &nbrs, LTERM); }
EXPORT void* IAmalloc( size_t size, UINT attr ) { return imalloc(size, SelIMACB(attr)); }
graph_t *FixGraph(graph_t *graph) { idx_t i, j, k, l, nvtxs, nedges; idx_t *xadj, *adjncy, *adjwgt; idx_t *nxadj, *nadjncy, *nadjwgt; graph_t *ngraph; uvw_t *edges; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; ASSERT(adjwgt != NULL); ngraph = CreateGraph(); ngraph->nvtxs = nvtxs; /* deal with vertex weights/sizes */ ngraph->ncon = graph->ncon; ngraph->vwgt = icopy(nvtxs*graph->ncon, graph->vwgt, imalloc(nvtxs*graph->ncon, "FixGraph: vwgt")); ngraph->vsize = ismalloc(nvtxs, 1, "FixGraph: vsize"); if (graph->vsize) icopy(nvtxs, graph->vsize, ngraph->vsize); /* fix graph by sorting the "superset" of edges */ edges = (uvw_t *)gk_malloc(sizeof(uvw_t)*2*xadj[nvtxs], "FixGraph: edges"); for (nedges=0, i=0; i<nvtxs; i++) { for (j=xadj[i]; j<xadj[i+1]; j++) { /* keep only the upper-trianglular part of the adjacency matrix */ if (i < adjncy[j]) { edges[nedges].u = i; edges[nedges].v = adjncy[j]; edges[nedges].w = adjwgt[j]; nedges++; } else if (i > adjncy[j]) { edges[nedges].u = adjncy[j]; edges[nedges].v = i; edges[nedges].w = adjwgt[j]; nedges++; } } } uvwsorti(nedges, edges); /* keep the unique subset */ for (k=0, i=1; i<nedges; i++) { if (edges[k].v != edges[i].v || edges[k].u != edges[i].u) { edges[++k] = edges[i]; } } nedges = k+1; /* allocate memory for the fixed graph */ nxadj = ngraph->xadj = ismalloc(nvtxs+1, 0, "FixGraph: nxadj"); nadjncy = ngraph->adjncy = imalloc(2*nedges, "FixGraph: nadjncy"); nadjwgt = ngraph->adjwgt = imalloc(2*nedges, "FixGraph: nadjwgt"); /* create the adjacency list of the fixed graph from the upper-triangular part of the adjacency matrix */ for (k=0; k<nedges; k++) { nxadj[edges[k].u]++; nxadj[edges[k].v]++; } MAKECSR(i, nvtxs, nxadj); for (k=0; k<nedges; k++) { nadjncy[nxadj[edges[k].u]] = edges[k].v; nadjncy[nxadj[edges[k].v]] = edges[k].u; nadjwgt[nxadj[edges[k].u]] = edges[k].w; nadjwgt[nxadj[edges[k].v]] = edges[k].w; nxadj[edges[k].u]++; nxadj[edges[k].v]++; } SHIFTCSR(i, nvtxs, nxadj); gk_free((void **)&edges, LTERM); return ngraph; }