/**
 * 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);
    }
}
Exemple #6
0
void
node_stmts_add(node* arr, node* np)
{
  node_array_add(arr, np);
}