/** * Creates a new node in the graph and returns the node pointer. */ node *graph_add_node(graph *g) { node *n = node_create(); if (!n || NULL == node_array_add(g->nodes, n)) return NULL; return n; }
/** * Computes the union of a pair of node_arrays. * The returned value should be free using node_array_destroy * * Assumption: the nodes are sorted incrementally by node number. * * Returns an allocated node_array struct on success. * NULL on failure. */ node_array *node_array_union(node_array *n1, node_array *n2) { int i, j; node_array *onion; if (NULL == (onion = node_array_create())) return NULL; i = j = 0; while (i < n1->nnodes && j < n2->nnodes) { if (n1->node[i]->number < n2->node[j]->number) { while (i < n1->nnodes && n1->node[i]->number < n2->node[j]->number) { if (NULL == node_array_add(onion, n1->node[i])) return NULL; i++; } } else if (n1->node[i]->number > n2->node[j]->number) { while (j < n2->nnodes && n2->node[j]->number < n1->node[i]->number) { if (NULL == node_array_add(onion, n2->node[j])) return NULL; j++; } } else { if (NULL == node_array_add(onion, n1->node[i])) return NULL; i++; j++; } } while (i < n1->nnodes) { if (NULL == node_array_add(onion, n1->node[i])) return NULL; i++; } while (j < n2->nnodes) { if (NULL == node_array_add(onion, n2->node[j])) return NULL; j++; } return onion; }
/** * Returns a node_array of nodes connected to this node. * The node_array should be deallocated by the caller using * node_array_destroy(). */ node_array *node_neighbours(node *n) { int i; node_array *na = node_array_create(); for (i = 0; i < n->edges->nedges; i++) { edge *e = n->edges->edge[i]; if (!e) continue; node_array_add(na, e->n1 == n ? e->n2 : e->n1); } return na; }
/** * Computes the intersection of a pair of node_arrays. * The returned value should be free using node_array_destroy * * Assumption: the nodes are sorted incrementally by node number. * * Returns an allocated node_array struct on success. * NULL on failure. */ node_array *node_array_intersection(node_array *n1, node_array *n2) { int i, j; node_array *inter; if (NULL == (inter = node_array_create())) return NULL; for (i = j = 0; i < n1->nnodes; i++) { int nnum = n1->node[i]->number; while (j < n2->nnodes && n2->node[j]->number < nnum) j++; if (j < n2->nnodes && n2->node[j]->number == nnum) { if (NULL == node_array_add(inter, n1->node[i])) return NULL; } } return inter; }
/** * Merges the nodes linked to by edge 'e' and sets any neighbouring * edge / link scores to be invalid. */ void merge_node(graph *g, edge *e) { node *n1, *n2; node_array *na1, *na2, *na; int i, j; if (verbosity >= 2) printf("Merging %d / %d (score %8.2f, link %8.2f) %s / %s\n", e->n1->number, e->n2->number, e->edge_score, e->linkage_score, e->n1->tname, e->n2->tname); /* print_matrix_node(g, e->n1); print_matrix_node(g, e->n2); */ /* Find all the nodes linked to either n1 or n2 where n1 and n2 * are the nodes in this edge. */ n1 = e->n1; n2 = e->n2; na1 = node_neighbours(n1); na2 = node_neighbours(n2); na = node_array_union(na1, na2); node_array_destroy(na1); node_array_destroy(na2); /* Attach n2 to the node_array in n1 - allows traceback */ if (!n1->merged) { n1->merged = node_array_create(); } node_array_add(n1->merged, n2); /* * Merge the matrix rows. */ for (i = 0; i < g->nsnps; i++) { for (j = 0; j < 6; j++) n1->matrix[i][j] += n2->matrix[i][j]; } /* * Forall nodes in our set, find the edges between that and n1 * and/or n2. If it links with both then set the edge score to be * the average of the two values, otherwise use the single score. * Set the linkage score to be undefined. * Reset the edge to be between this node and n1 always (as n2 * will then be disconnected and considered to be merged with n1). */ for (i = 0; i < na->nnodes; i++) { node *n = na->node[i]; edge *e1, *e2; if (n == n1 || n == n2) continue; e1 = edge_find(n, n1); e2 = edge_find(n, n2); if (!e1 && !e2) continue; if (e1 && e2) { /* links to both, so remove edge to n2 */ e1->edge_score = (e1->edge_score + e2->edge_score) / 2; edge_unlink(e2); } else if (e2) { /* links only to n2, so relink edge to n1 */ if (e2->n1 == n) e2->n2 = n1; else e2->n1 = n1; edge_array_add(n1->edges, e2); e1 = e2; } e1->linkage_score = UNDEF_SCORE; e1->edge_score = UNDEF_SCORE; } node_array_destroy(na); edge_unlink(e); for (i = 0; i < g->nodes->nnodes; i++) { if (g->nodes->node[i] == n2) { g->nodes->node[i] = NULL; break; } } /* Recompute all undefined edge scores */ for (i = 0; i < g->edges->nedges; i++) { edge *e; if (!(e = g->edges->edge[i])) continue; if (!e->n1 || !e->n2) continue; e->edge_score = calc_edge_score(e->n1->matrix, e->n2->matrix, g->snp_scores, g->nsnps, NULL, g->correlation_offset); } }
void node_stmts_add(node* arr, node* np) { node_array_add(arr, np); }