Exemple #1
0
int igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t *res,
	       igraph_bool_t use_seed, igraph_integer_t maxiter,
	       igraph_real_t epsilon, igraph_real_t kkconst, 
	       const igraph_vector_t *weights,
	       const igraph_vector_t *minx, const igraph_vector_t *maxx,
	       const igraph_vector_t *miny, const igraph_vector_t *maxy) {
  
  igraph_integer_t no_nodes=igraph_vcount(graph);
  igraph_integer_t no_edges=igraph_ecount(graph);
  igraph_real_t L, L0=sqrt(no_nodes);  
  igraph_matrix_t dij, lij, kij;
  igraph_real_t max_dij;
  igraph_vector_t D1, D2;
  igraph_integer_t i, j, m;

  if (maxiter < 0) {
    IGRAPH_ERROR("Number of iterations must be non-negatice in "
		 "Kamada-Kawai layout", IGRAPH_EINVAL);
  }
  if (kkconst <= 0) {
    IGRAPH_ERROR("`K' constant must be positive in Kamada-Kawai layout",
		 IGRAPH_EINVAL);
  }

  if (use_seed && (igraph_matrix_nrow(res) != no_nodes ||
		   igraph_matrix_ncol(res) != 2)) {
    IGRAPH_ERROR("Invalid start position matrix size in "
		 "Kamada-Kawai layout", IGRAPH_EINVAL);
  }
  if (weights && igraph_vector_size(weights) != no_edges) {
    IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL);
  }

  if (minx && igraph_vector_size(minx) != no_nodes) {
    IGRAPH_ERROR("Invalid minx vector length", IGRAPH_EINVAL);
  }
  if (maxx && igraph_vector_size(maxx) != no_nodes) {
    IGRAPH_ERROR("Invalid maxx vector length", IGRAPH_EINVAL);
  }
  if (minx && maxx && !igraph_vector_all_le(minx, maxx)) {
    IGRAPH_ERROR("minx must not be greater than maxx", IGRAPH_EINVAL);
  }
  if (miny && igraph_vector_size(miny) != no_nodes) {
    IGRAPH_ERROR("Invalid miny vector length", IGRAPH_EINVAL);
  }
  if (maxy && igraph_vector_size(maxy) != no_nodes) {
    IGRAPH_ERROR("Invalid maxy vector length", IGRAPH_EINVAL);
  }
  if (miny && maxy && !igraph_vector_all_le(miny, maxy)) {
    IGRAPH_ERROR("miny must not be greater than maxy", IGRAPH_EINVAL);
  }

  if (!use_seed) {
    if (minx || maxx || miny || maxy) {
      const igraph_real_t width=sqrt(no_nodes), height=width;
      IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 2));
      RNG_BEGIN();
      for (i=0; i<no_nodes; i++) {
	igraph_real_t x1=minx ? VECTOR(*minx)[i] : -width/2;
	igraph_real_t x2=maxx ? VECTOR(*maxx)[i] :  width/2;
	igraph_real_t y1=miny ? VECTOR(*miny)[i] : -height/2;
	igraph_real_t y2=maxy ? VECTOR(*maxy)[i] :  height/2;
	if (!igraph_finite(x1)) { x1 = -width/2; }
	if (!igraph_finite(x2)) { x2 =  width/2; }
	if (!igraph_finite(y1)) { y1 = -height/2; }
	if (!igraph_finite(y2)) { y2 =  height/2; }
	MATRIX(*res, i, 0) = RNG_UNIF(x1, x2);
	MATRIX(*res, i, 1) = RNG_UNIF(y1, y2);
      }
      RNG_END();
    } else {
      igraph_layout_circle(graph, res, /* order= */ igraph_vss_all());
    }
  }

  if (no_nodes <= 1) { return 0; }

  IGRAPH_MATRIX_INIT_FINALLY(&dij, no_nodes, no_nodes);
  IGRAPH_MATRIX_INIT_FINALLY(&kij, no_nodes, no_nodes);
  IGRAPH_MATRIX_INIT_FINALLY(&lij, no_nodes, no_nodes);
  IGRAPH_CHECK(igraph_shortest_paths_dijkstra(graph, &dij, igraph_vss_all(),
					      igraph_vss_all(), weights,
					      IGRAPH_ALL));
  
  max_dij = 0.0;
  for (i=0; i<no_nodes; i++) {
    for (j=i+1; j<no_nodes; j++) {
      if (!igraph_finite(MATRIX(dij, i, j))) { continue; }
      if (MATRIX(dij, i, j) > max_dij) { max_dij = MATRIX(dij, i, j); }
    }
  }
  for (i=0; i<no_nodes; i++) {
    for (j=0; j<no_nodes; j++) {
      if (MATRIX(dij, i, j) > max_dij) { MATRIX(dij, i, j) = max_dij; }
    }
  }

  L = L0 / max_dij;
  for (i=0; i<no_nodes; i++) {
    for (j=0; j<no_nodes; j++) {      
      igraph_real_t tmp=MATRIX(dij, i, j) * MATRIX(dij, i, j);
      if (i==j) { continue; }
      MATRIX(kij, i, j) = kkconst / tmp;
      MATRIX(lij, i, j) = L * MATRIX(dij, i, j);
    }
  }

  /* Initialize delta */
  IGRAPH_VECTOR_INIT_FINALLY(&D1, no_nodes);
  IGRAPH_VECTOR_INIT_FINALLY(&D2, no_nodes);
  for (m=0; m<no_nodes; m++) {
    igraph_real_t myD1=0.0, myD2=0.0;
    for (i=0; i<no_nodes; i++) { 
      if (i==m) { continue; }
      igraph_real_t dx=MATRIX(*res, m, 0) - MATRIX(*res, i, 0);
      igraph_real_t dy=MATRIX(*res, m, 1) - MATRIX(*res, i, 1);
      igraph_real_t mi_dist=sqrt(dx * dx + dy * dy);
      myD1 += MATRIX(kij, m, i) * (dx - MATRIX(lij, m, i) * dx / mi_dist);
      myD2 += MATRIX(kij, m, i) * (dy - MATRIX(lij, m, i) * dy / mi_dist);
    }
    VECTOR(D1)[m] = myD1;
    VECTOR(D2)[m] = myD2;
  }

  for (j=0; j<maxiter; j++) {
    
    igraph_real_t myD1=0.0, myD2=0.0, A=0.0, B=0.0, C=0.0;
    igraph_real_t max_delta, delta_x, delta_y;
    igraph_real_t old_x, old_y, new_x, new_y;

    /* Select maximal delta */
    m=0; max_delta=-1;
    for (i=0; i<no_nodes; i++) {
      igraph_real_t delta=(VECTOR(D1)[i] * VECTOR(D1)[i] + 
			   VECTOR(D2)[i] * VECTOR(D2)[i]);
      if (delta > max_delta) { 
	m=i; max_delta=delta;
      }
    }
    if (max_delta < epsilon) { break; }
    old_x=MATRIX(*res, m, 0);
    old_y=MATRIX(*res, m, 1);
    
    /* Calculate D1 and D2, A, B, C */
    for (i=0; i<no_nodes; i++) {
      if (i==m) { continue; }
      igraph_real_t dx=old_x - MATRIX(*res, i, 0);
      igraph_real_t dy=old_y - MATRIX(*res, i, 1);
      igraph_real_t dist=sqrt(dx * dx + dy * dy);
      igraph_real_t den=dist * (dx * dx + dy * dy);
      A += MATRIX(kij, m, i) * (1 - MATRIX(lij, m, i) * dy * dy / den);
      B += MATRIX(kij, m, i) * MATRIX(lij, m, i) * dx * dy / den;
      C += MATRIX(kij, m, i) * (1 - MATRIX(lij, m, i) * dx * dx / den);
    }
    myD1 = VECTOR(D1)[m];
    myD2 = VECTOR(D2)[m];

    /* Need to solve some linear equations */
    delta_y = (B * myD1 - myD2 * A) / (C * A - B * B);
    delta_x = - (myD1 + B * delta_y) / A;
    
    new_x = old_x + delta_x;
    new_y = old_y + delta_y;

    /* Limits, if given */
    if (minx && new_x < VECTOR(*minx)[m]) { new_x = VECTOR(*minx)[m]; }
    if (maxx && new_x > VECTOR(*maxx)[m]) { new_x = VECTOR(*maxx)[m]; }
    if (miny && new_y < VECTOR(*miny)[m]) { new_y = VECTOR(*miny)[m]; }
    if (maxy && new_y > VECTOR(*maxy)[m]) { new_y = VECTOR(*maxy)[m]; }

    /* Update delta, only with/for the affected node */
    VECTOR(D1)[m] = VECTOR(D2)[m] = 0.0;
    for (i=0; i<no_nodes; i++) {
      if (i==m) { continue; }
      igraph_real_t old_dx=old_x - MATRIX(*res, i, 0);
      igraph_real_t old_dy=old_y - MATRIX(*res, i, 1);
      igraph_real_t old_mi_dist=sqrt(old_dx * old_dx + old_dy * old_dy);
      igraph_real_t new_dx=new_x - MATRIX(*res, i, 0);
      igraph_real_t new_dy=new_y - MATRIX(*res, i, 1);
      igraph_real_t new_mi_dist=sqrt(new_dx * new_dx + new_dy * new_dy);

      VECTOR(D1)[i] -= MATRIX(kij, m, i) * 
	(-old_dx + MATRIX(lij, m, i) * old_dx / old_mi_dist);
      VECTOR(D2)[i] -= MATRIX(kij, m, i) *
	(-old_dy + MATRIX(lij, m, i) * old_dy / old_mi_dist);
      VECTOR(D1)[i] += MATRIX(kij, m, i) *
	(-new_dx + MATRIX(lij, m, i) * new_dx / new_mi_dist);
      VECTOR(D2)[i] += MATRIX(kij, m, i) *
	(-new_dy + MATRIX(lij, m, i) * new_dy / new_mi_dist);

      VECTOR(D1)[m] += MATRIX(kij, m, i) *
	(new_dx - MATRIX(lij, m, i) * new_dx / new_mi_dist);
      VECTOR(D2)[m] += MATRIX(kij, m, i) *
	(new_dy - MATRIX(lij, m, i) * new_dy / new_mi_dist);
    }
      
    /* Update coordinates*/
    MATRIX(*res, m, 0) = new_x;
    MATRIX(*res, m, 1) = new_y;
  }

  igraph_vector_destroy(&D2);
  igraph_vector_destroy(&D1);
  igraph_matrix_destroy(&lij);
  igraph_matrix_destroy(&kij);
  igraph_matrix_destroy(&dij);
  IGRAPH_FINALLY_CLEAN(5);

  return 0;
}
int main() {
  igraph_t g;
  igraph_vector_t tdist;
  igraph_matrix_t pmat;
  igraph_bool_t conn;
  igraph_vector_bool_t bs;
  int i, ret;
  
  /* Symmetric preference game */
  igraph_vector_bool_init(&bs, 0);

  igraph_vector_init_real(&tdist, 3, 1.0, 1.0, 1.0);

  igraph_matrix_init(&pmat, 3, 3);
  for (i=0; i<3; i++) MATRIX(pmat, i, i) = 0.2;

  /* undirected, no loops */
  IGRAPH_CHECK(igraph_preference_game(&g, 1000, 3, &tdist, /*fixed_sizes=*/ 0,
				      &pmat, 0, 0, 0));
  if (igraph_vcount(&g) != 1000) return 18;
  if (igraph_is_directed(&g)) return 2;
  igraph_is_connected(&g, &conn, IGRAPH_STRONG);
  if (conn) return 3;
  igraph_is_loop(&g, &bs, igraph_ess_all(IGRAPH_EDGEORDER_ID));
  if (igraph_vector_bool_sum(&bs)) return 4;
  igraph_is_multiple(&g, &bs, igraph_ess_all(IGRAPH_EDGEORDER_ID));
  if (igraph_vector_bool_sum(&bs)) return 5;
  igraph_destroy(&g);

  for (i=0; i<2; i++) MATRIX(pmat, i, i+1) = 0.1;

  /* directed, no loops */
  IGRAPH_CHECK(igraph_preference_game(&g, 1000, 3, &tdist, /*fixed_sizes=*/0, 
				      &pmat, 0, 1, 0));
  if (igraph_vcount(&g) != 1000) return 17;
  if (!igraph_is_directed(&g)) return 6;
  igraph_is_loop(&g, &bs, igraph_ess_all(IGRAPH_EDGEORDER_ID));
  if (igraph_vector_bool_sum(&bs)) return 7;
  igraph_is_multiple(&g, &bs, igraph_ess_all(IGRAPH_EDGEORDER_ID));
  if (igraph_vector_bool_sum(&bs)) return 8;
  igraph_destroy(&g);

  /* undirected, loops */
  for (i=0; i<3; i++) MATRIX(pmat, i, i) = 1.0;
  IGRAPH_CHECK(igraph_preference_game(&g, 100, 3, &tdist, /*fixed_sizes=*/ 0,
				      &pmat, 0, 0, 1));
  if (igraph_vcount(&g) != 100) return 16;
  if (igraph_ecount(&g) < 1395) return 20;
  if (igraph_is_directed(&g)) return 9;
  igraph_is_loop(&g, &bs, igraph_ess_all(IGRAPH_EDGEORDER_ID));
  if (igraph_vector_bool_sum(&bs) == 0) return 10;
  igraph_is_multiple(&g, &bs, igraph_ess_all(IGRAPH_EDGEORDER_ID));
  if (igraph_vector_bool_sum(&bs)) return 11;
  igraph_destroy(&g);

  /* directed, loops */
  IGRAPH_CHECK(igraph_preference_game(&g, 100, 3, &tdist, /*fixed_sizes=*/ 0,
				      &pmat, 0, 1, 1));
  if (igraph_vcount(&g) != 100) return 15;
  if (igraph_ecount(&g) < 2700) return 19;
  if (!igraph_is_directed(&g)) return 12;
  igraph_is_loop(&g, &bs, igraph_ess_all(IGRAPH_EDGEORDER_ID));
  if (igraph_vector_bool_sum(&bs) == 0) return 13;
  igraph_is_multiple(&g, &bs, igraph_ess_all(IGRAPH_EDGEORDER_ID));
  if (igraph_vector_bool_sum(&bs)) return 14;
  igraph_destroy(&g);

  /* Asymmetric preference game */

  /* directed, no loops */
  igraph_matrix_resize(&pmat, 2, 2);
  MATRIX(pmat, 0, 0) = 1; MATRIX(pmat, 0, 1) = 1;
  MATRIX(pmat, 1, 0) = 1; MATRIX(pmat, 1, 1) = 1;
  IGRAPH_CHECK(igraph_asymmetric_preference_game(&g, 100, 2, 0, &pmat, 0, 0, 0));
  if (igraph_vcount(&g) != 100) return 21;
  if (igraph_ecount(&g) != 9900) return 22;
  if (!igraph_is_directed(&g)) return 23;
  igraph_is_loop(&g, &bs, igraph_ess_all(IGRAPH_EDGEORDER_ID));
  if (igraph_vector_bool_sum(&bs)) return 24;
  igraph_is_multiple(&g, &bs, igraph_ess_all(IGRAPH_EDGEORDER_ID));
  if (igraph_vector_bool_sum(&bs)) return 25;
  igraph_destroy(&g);

  /* directed, loops */
  igraph_matrix_resize(&pmat, 2, 2);
  MATRIX(pmat, 0, 0) = 1; MATRIX(pmat, 0, 1) = 1;
  MATRIX(pmat, 1, 0) = 1; MATRIX(pmat, 1, 1) = 1;
  IGRAPH_CHECK(igraph_asymmetric_preference_game(&g, 100, 2, 0, &pmat, 0, 0, 1));
  if (igraph_vcount(&g) != 100) return 26;
  if (igraph_ecount(&g) != 10000) return 27;
  if (!igraph_is_directed(&g)) return 28;
  igraph_is_loop(&g, &bs, igraph_ess_all(IGRAPH_EDGEORDER_ID));
  if (igraph_vector_bool_sum(&bs) != 100) return 29;
  igraph_is_multiple(&g, &bs, igraph_ess_all(IGRAPH_EDGEORDER_ID));
  if (igraph_vector_bool_sum(&bs)) return 30;
  igraph_destroy(&g);

  igraph_vector_destroy(&tdist);
  igraph_matrix_destroy(&pmat);
  igraph_vector_bool_destroy(&bs);

  assert(IGRAPH_FINALLY_STACK_EMPTY);

  return 0;
}
Exemple #3
0
int igraph_layout_kamada_kawai_3d(const igraph_t *graph, igraph_matrix_t *res,
	       igraph_bool_t use_seed, igraph_integer_t maxiter,
	       igraph_real_t epsilon, igraph_real_t kkconst, 
	       const igraph_vector_t *weights,
	       const igraph_vector_t *minx, const igraph_vector_t *maxx,
	       const igraph_vector_t *miny, const igraph_vector_t *maxy,
	       const igraph_vector_t *minz, const igraph_vector_t *maxz) {
  
  igraph_integer_t no_nodes=igraph_vcount(graph);
  igraph_integer_t no_edges=igraph_ecount(graph);
  igraph_real_t L, L0=sqrt(no_nodes);  
  igraph_matrix_t dij, lij, kij;
  igraph_real_t max_dij;
  igraph_vector_t D1, D2, D3;
  igraph_integer_t i, j, m;

  if (maxiter < 0) {
    IGRAPH_ERROR("Number of iterations must be non-negatice in "
		 "Kamada-Kawai layout", IGRAPH_EINVAL);
  }
  if (kkconst <= 0) {
    IGRAPH_ERROR("`K' constant must be positive in Kamada-Kawai layout",
		 IGRAPH_EINVAL);
  }

  if (use_seed && (igraph_matrix_nrow(res) != no_nodes ||
		   igraph_matrix_ncol(res) != 3)) {
    IGRAPH_ERROR("Invalid start position matrix size in "
		 "3d Kamada-Kawai layout", IGRAPH_EINVAL);
  }
  if (weights && igraph_vector_size(weights) != no_edges) {
    IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL);
  }

  if (minx && igraph_vector_size(minx) != no_nodes) {
    IGRAPH_ERROR("Invalid minx vector length", IGRAPH_EINVAL);
  }
  if (maxx && igraph_vector_size(maxx) != no_nodes) {
    IGRAPH_ERROR("Invalid maxx vector length", IGRAPH_EINVAL);
  }
  if (minx && maxx && !igraph_vector_all_le(minx, maxx)) {
    IGRAPH_ERROR("minx must not be greater than maxx", IGRAPH_EINVAL);
  }
  if (miny && igraph_vector_size(miny) != no_nodes) {
    IGRAPH_ERROR("Invalid miny vector length", IGRAPH_EINVAL);
  }
  if (maxy && igraph_vector_size(maxy) != no_nodes) {
    IGRAPH_ERROR("Invalid maxy vector length", IGRAPH_EINVAL);
  }
  if (miny && maxy && !igraph_vector_all_le(miny, maxy)) {
    IGRAPH_ERROR("miny must not be greater than maxy", IGRAPH_EINVAL);
  }
  if (minz && igraph_vector_size(minz) != no_nodes) {
    IGRAPH_ERROR("Invalid minz vector length", IGRAPH_EINVAL);
  }
  if (maxz && igraph_vector_size(maxz) != no_nodes) {
    IGRAPH_ERROR("Invalid maxz vector length", IGRAPH_EINVAL);
  }
  if (minz && maxz && !igraph_vector_all_le(minz, maxz)) {
    IGRAPH_ERROR("minz must not be greater than maxz", IGRAPH_EINVAL);
  }

  if (!use_seed) {
    if (minx || maxx || miny || maxy || minz || maxz) {
      const igraph_real_t width=sqrt(no_nodes), height=width, depth=width;
      IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 3));
      RNG_BEGIN();
      for (i=0; i<no_nodes; i++) {
	igraph_real_t x1=minx ? VECTOR(*minx)[i] : -width/2;
	igraph_real_t x2=maxx ? VECTOR(*maxx)[i] :  width/2;
	igraph_real_t y1=miny ? VECTOR(*miny)[i] : -height/2;
	igraph_real_t y2=maxy ? VECTOR(*maxy)[i] :  height/2;
	igraph_real_t z1=minz ? VECTOR(*minz)[i] : -depth/2;
	igraph_real_t z2=maxz ? VECTOR(*maxz)[i] :  depth/2;
	if (!igraph_finite(x1)) { x1 = -width/2; }
	if (!igraph_finite(x2)) { x2 =  width/2; }
	if (!igraph_finite(y1)) { y1 = -height/2; }
	if (!igraph_finite(y2)) { y2 =  height/2; }
	if (!igraph_finite(z1)) { z1 = -depth/2; }
	if (!igraph_finite(z2)) { z2 =  depth/2; }
	MATRIX(*res, i, 0) = RNG_UNIF(x1, x2);
	MATRIX(*res, i, 1) = RNG_UNIF(y1, y2);
	MATRIX(*res, i, 2) = RNG_UNIF(z1, z2);
      }
      RNG_END();
    } else {
      igraph_layout_sphere(graph, res);
    }
  }

  if (no_nodes <= 1) { return 0; }

  IGRAPH_MATRIX_INIT_FINALLY(&dij, no_nodes, no_nodes);
  IGRAPH_MATRIX_INIT_FINALLY(&kij, no_nodes, no_nodes);
  IGRAPH_MATRIX_INIT_FINALLY(&lij, no_nodes, no_nodes);
  IGRAPH_CHECK(igraph_shortest_paths_dijkstra(graph, &dij, igraph_vss_all(),
					      igraph_vss_all(), weights,
					      IGRAPH_ALL));
  
  max_dij = 0.0;
  for (i=0; i<no_nodes; i++) {
    for (j=i+1; j<no_nodes; j++) {
      if (!igraph_finite(MATRIX(dij, i, j))) { continue; }
      if (MATRIX(dij, i, j) > max_dij) { max_dij = MATRIX(dij, i, j); }
    }
  }
  for (i=0; i<no_nodes; i++) {
    for (j=0; j<no_nodes; j++) {
      if (MATRIX(dij, i, j) > max_dij) { MATRIX(dij, i, j) = max_dij; }
    }
  }

  L = L0 / max_dij;
  for (i=0; i<no_nodes; i++) {
    for (j=0; j<no_nodes; j++) {      
      igraph_real_t tmp=MATRIX(dij, i, j) * MATRIX(dij, i, j);
      if (i==j) { continue; }
      MATRIX(kij, i, j) = kkconst / tmp;
      MATRIX(lij, i, j) = L * MATRIX(dij, i, j);
    }
  }

  /* Initialize delta */
  IGRAPH_VECTOR_INIT_FINALLY(&D1, no_nodes);
  IGRAPH_VECTOR_INIT_FINALLY(&D2, no_nodes);
  IGRAPH_VECTOR_INIT_FINALLY(&D3, no_nodes);
  for (m=0; m<no_nodes; m++) {
    igraph_real_t myD1=0.0, myD2=0.0, myD3=0.0;
    for (i=0; i<no_nodes; i++) { 
      if (i==m) { continue; }
      igraph_real_t dx=MATRIX(*res, m, 0) - MATRIX(*res, i, 0);
      igraph_real_t dy=MATRIX(*res, m, 1) - MATRIX(*res, i, 1);
      igraph_real_t dz=MATRIX(*res, m, 2) - MATRIX(*res, i, 2);
      igraph_real_t mi_dist=sqrt(dx * dx + dy * dy + dz * dz);
      myD1 += MATRIX(kij, m, i) * (dx - MATRIX(lij, m, i) * dx / mi_dist);
      myD2 += MATRIX(kij, m, i) * (dy - MATRIX(lij, m, i) * dy / mi_dist);
      myD3 += MATRIX(kij, m, i) * (dz - MATRIX(lij, m, i) * dz / mi_dist);
    }
    VECTOR(D1)[m] = myD1;
    VECTOR(D2)[m] = myD2;
    VECTOR(D3)[m] = myD3;
  }

  for (j=0; j<maxiter; j++) {
    
    igraph_real_t Ax=0.0, Ay=0.0, Az=0.0;
    igraph_real_t Axx=0.0, Axy=0.0, Axz=0.0, Ayy=0.0, Ayz=0.0, Azz=0.0;
    igraph_real_t max_delta, delta_x, delta_y, delta_z;
    igraph_real_t old_x, old_y, old_z, new_x, new_y, new_z;
    igraph_real_t detnum;

    /* Select maximal delta */
    m=0; max_delta=-1;
    for (i=0; i<no_nodes; i++) {
      igraph_real_t delta=(VECTOR(D1)[i] * VECTOR(D1)[i] + 
			   VECTOR(D2)[i] * VECTOR(D2)[i] +
			   VECTOR(D3)[i] * VECTOR(D3)[i]);
      if (delta > max_delta) { 
	m=i; max_delta=delta;
      }
    }
    if (max_delta < epsilon) { break; }
    old_x=MATRIX(*res, m, 0);
    old_y=MATRIX(*res, m, 1);
    old_z=MATRIX(*res, m, 2);
    
    /* Calculate D1, D2 and D3, and other coefficients */
    for (i=0; i<no_nodes; i++) {
      if (i==m) { continue; }
      igraph_real_t dx=old_x - MATRIX(*res, i, 0);
      igraph_real_t dy=old_y - MATRIX(*res, i, 1);
      igraph_real_t dz=old_z - MATRIX(*res, i, 2);
      igraph_real_t dist=sqrt(dx * dx + dy * dy + dz *dz);
      igraph_real_t den=dist * (dx * dx + dy * dy + dz * dz);
      igraph_real_t k_mi=MATRIX(kij, m, i);
      igraph_real_t l_mi=MATRIX(lij, m, i);
      Axx += k_mi * (1 - l_mi * (dy*dy + dz*dz) / den);
      Ayy += k_mi * (1 - l_mi * (dx*dx + dz*dz) / den);
      Azz += k_mi * (1 - l_mi * (dx*dx + dy*dy) / den);
      Axy += k_mi * l_mi * dx * dy / den;
      Axz += k_mi * l_mi * dx * dz / den;
      Ayz += k_mi * l_mi * dy * dz / den;
    }
    Ax = -VECTOR(D1)[m];
    Ay = -VECTOR(D2)[m];
    Az = -VECTOR(D3)[m];

    /* Need to solve some linear equations, we just use Cramer's rule */
#define DET(a,b,c,d,e,f,g,h,i) ((a*e*i+b*f*g+c*d*h)-(c*e*g+b*d*i+a*f*h))
    
    detnum  = DET(Axx,Axy,Axz, Axy,Ayy,Ayz, Axz,Ayz,Azz);
    delta_x = DET(Ax ,Ay ,Az , Axy,Ayy,Ayz, Axz,Ayz,Azz) / detnum;
    delta_y = DET(Axx,Axy,Axz, Ax ,Ay ,Az , Axz,Ayz,Azz) / detnum;
    delta_z = DET(Axx,Axy,Axz, Axy,Ayy,Ayz, Ax ,Ay ,Az ) / detnum;
    
    new_x = old_x + delta_x;
    new_y = old_y + delta_y;
    new_z = old_z + delta_z;

    /* Limits, if given */
    if (minx && new_x < VECTOR(*minx)[m]) { new_x = VECTOR(*minx)[m]; }
    if (maxx && new_x > VECTOR(*maxx)[m]) { new_x = VECTOR(*maxx)[m]; }
    if (miny && new_y < VECTOR(*miny)[m]) { new_y = VECTOR(*miny)[m]; }
    if (maxy && new_y > VECTOR(*maxy)[m]) { new_y = VECTOR(*maxy)[m]; }
    if (minz && new_z < VECTOR(*minz)[m]) { new_z = VECTOR(*minz)[m]; }
    if (maxz && new_z > VECTOR(*maxz)[m]) { new_z = VECTOR(*maxz)[m]; }

    /* Update delta, only with/for the affected node */
    VECTOR(D1)[m] = VECTOR(D2)[m] = VECTOR(D3)[m] = 0.0;
    for (i=0; i<no_nodes; i++) {
      if (i==m) { continue; }
      igraph_real_t old_dx=old_x - MATRIX(*res, i, 0);
      igraph_real_t old_dy=old_y - MATRIX(*res, i, 1);
      igraph_real_t old_dz=old_z - MATRIX(*res, i, 2);
      igraph_real_t old_mi_dist=sqrt(old_dx * old_dx + old_dy * old_dy + 
				     old_dz * old_dz);
      igraph_real_t new_dx=new_x - MATRIX(*res, i, 0);
      igraph_real_t new_dy=new_y - MATRIX(*res, i, 1);
      igraph_real_t new_dz=new_z - MATRIX(*res, i, 2);
      igraph_real_t new_mi_dist=sqrt(new_dx * new_dx + new_dy * new_dy +
				     new_dz * new_dz);

      VECTOR(D1)[i] -= MATRIX(kij, m, i) * 
	(-old_dx + MATRIX(lij, m, i) * old_dx / old_mi_dist);
      VECTOR(D2)[i] -= MATRIX(kij, m, i) *
	(-old_dy + MATRIX(lij, m, i) * old_dy / old_mi_dist);
      VECTOR(D3)[i] -= MATRIX(kij, m, i) *
	(-old_dz + MATRIX(lij, m, i) * old_dz / old_mi_dist);

      VECTOR(D1)[i] += MATRIX(kij, m, i) *
	(-new_dx + MATRIX(lij, m, i) * new_dx / new_mi_dist);
      VECTOR(D2)[i] += MATRIX(kij, m, i) *
	(-new_dy + MATRIX(lij, m, i) * new_dy / new_mi_dist);
      VECTOR(D3)[i] += MATRIX(kij, m, i) *
	(-new_dz + MATRIX(lij, m, i) * new_dz / new_mi_dist);

      VECTOR(D1)[m] += MATRIX(kij, m, i) *
	(new_dx - MATRIX(lij, m, i) * new_dx / new_mi_dist);
      VECTOR(D2)[m] += MATRIX(kij, m, i) *
	(new_dy - MATRIX(lij, m, i) * new_dy / new_mi_dist);
      VECTOR(D3)[m] += MATRIX(kij, m, i) *
	(new_dz - MATRIX(lij, m, i) * new_dz / new_mi_dist);
    }
      
    /* Update coordinates*/
    MATRIX(*res, m, 0) = new_x;
    MATRIX(*res, m, 1) = new_y;
    MATRIX(*res, m, 2) = new_z;
  }

  igraph_vector_destroy(&D3);
  igraph_vector_destroy(&D2);
  igraph_vector_destroy(&D1);
  igraph_matrix_destroy(&lij);
  igraph_matrix_destroy(&kij);
  igraph_matrix_destroy(&dij);
  IGRAPH_FINALLY_CLEAN(6);

  return 0;
}
// Orthnormalization using the Gram-Schmidt algorithm
void MATRIX(_gramschmidt)(T *          _x,
                          unsigned int _rx,
                          unsigned int _cx,
                          T *          _v)
{
    // validate input
    if (_rx == 0 || _cx == 0) {
        fprintf(stderr,"error: matrix_gramschmidt(), input matrix cannot have zero-length dimensions\n");
        exit(1);
    }

    unsigned int i;
    unsigned int j;
    unsigned int k;

    // copy _x to _u
    memmove(_v, _x, _rx * _cx * sizeof(T));

    unsigned int n = _rx;   // dimensionality of each vector
    T proj_ij[n];
    for (j=0; j<_cx; j++) {
        for (i=0; i<j; i++) {
            // v_j  <-  v_j - proj(v_i, v_j)

#if DEBUG_MATRIX_GRAMSCHMIDT
            printf("computing proj(v_%u, v_%u)\n", i, j);
#endif

            // compute proj(v_i, v_j)
            T vij = 0.;     // dotprod(v_i, v_j)
            T vii = 0.;     // dotprod(v_i, v_i)
            T ti;
            T tj;
            for (k=0; k<n; k++) {
                ti = matrix_access(_v, _rx, _cx, k, i);
                tj = matrix_access(_v, _rx, _cx, k, j);

                T prodij = ti * conj(tj);
                vij += prodij;

                T prodii = ti * conj(ti);
                vii += prodii;
            }
            // TODO : vii should be 1.0 from normalization step below
            T g = vij / vii;

            // complete projection
            for (k=0; k<n; k++)
                proj_ij[k] = matrix_access(_v, _rx, _cx, k, i) * g;

            // subtract projection from v_j
            for (k=0; k<n; k++)
                matrix_access(_v, _rx, _cx, k, j) -= proj_ij[k];
        }

        // normalize v_j
        T vjj = 0.;     // dotprod(v_j, v_j)
        T tj  = 0.;
        for (k=0; k<n; k++) {
            tj = matrix_access(_v, _rx, _cx, k, j);
            T prodjj = tj * conj(tj);
            vjj += prodjj;
        }
        // TODO : check magnitude of vjj
        T g = 1. / sqrt( creal(vjj) );
        for (k=0; k<n; k++)
            matrix_access(_v, _rx, _cx, k, j) *= g;

#if DEBUG_MATRIX_GRAMSCHMIDT
        MATRIX(_print)(_v, _rx, _cx);
#endif
    }
}
Exemple #5
0
void Matrix_transpose(Matrix * matrix) {
    *matrix = MATRIX(matrix->m[0],  matrix->m[1],  matrix->m[2],  matrix->m[3],
                     matrix->m[4],  matrix->m[5],  matrix->m[6],  matrix->m[7],
                     matrix->m[8],  matrix->m[9],  matrix->m[10], matrix->m[11],
                     matrix->m[12], matrix->m[13], matrix->m[14], matrix->m[15]);
}
Exemple #6
0
/* zeroHMM - Sets all of the transition probabilities to 0.0. */
void zeroHMM(Hmm *m)
{ int u, v;
  for (u = 0; u<m->uu; u++)
  { VECTOR(m->logB)[u] = NEGATIVE_INFINITY;
    for (v = 0; v<m->uu; v++)
    { MATRIX(m->logA)[u][v] = NEGATIVE_INFINITY;}}}
Exemple #7
0
void LayoutBuilder::produce(AbstractPetriNetBuilder *builder){
	if(!attrTableAttached){
		igraph_i_set_attribute_table(&igraph_cattribute_table);
		attrTableAttached = true;
	}
	size_t V = places.size() + transitions.size();
	size_t E = inArcs.size() + outArcs.size();
	igraph_t graph;
	// Create a directed graph
	igraph_empty(&graph, V, true);

	// Create vector with all edges
	igraph_vector_t edges;
	igraph_vector_init(&edges, E * 2);

	// Add edges to vector
	int i = 0;
	for(ArcIter it = inArcs.begin(); it != inArcs.end(); it++){
		VECTOR(edges)[i++] = numberFromName(it->start);
		VECTOR(edges)[i++] = numberFromName(it->end);
	}
	for(ArcIter it = outArcs.begin(); it != outArcs.end(); it++){
		VECTOR(edges)[i++] = numberFromName(it->start);
		VECTOR(edges)[i++] = numberFromName(it->end);
	}

	// Add the edges to graph
	igraph_add_edges(&graph, &edges, 0);

	// Delete the vector with edges
	igraph_vector_destroy(&edges);

	// Arrays to store result in
	double posx[V];
	double posy[V];

	// Provide current positions, if they're used at all
	if(startFromCurrentPositions){
		int i = 0;
		for(PlaceIter it = places.begin(); it != places.end(); it++){
			posx[i] = it->x;
			posy[i] = it->y;
			igraph_cattribute_VAN_set(&graph, "id", i, i);
			i++;
		}
		for(TransitionIter it = transitions.begin(); it != transitions.end(); it++){
			posx[i] = it->x;
			posy[i] = it->y;
			igraph_cattribute_VAN_set(&graph, "id", i, i);
			i++;
		}
	}

	// Decompose the graph, and layout subgraphs induvidually
	igraph_vector_ptr_t subgraphs;
	igraph_vector_ptr_init(&subgraphs, 0);
	igraph_decompose(&graph, &subgraphs, IGRAPH_WEAK, -1, 0);

	// Offset for places subgraphs
	double offsetx = 0;
	double offsety = 0;

	// Layout, translate and extract results for each subgraph
	for(int i = 0; i < igraph_vector_ptr_size(&subgraphs); i++){
		//Get the subgraph
		igraph_t* subgraph = (igraph_t*)VECTOR(subgraphs)[i];

		// Allocate result matrix
		igraph_matrix_t sublayout;
		igraph_matrix_init(&sublayout, 0, 0);

		// Vertex selector and iterator
		igraph_vs_t vs;
		igraph_vit_t vit;
		// Select all and create iterator
		igraph_vs_all(&vs);
		igraph_vit_create(subgraph, vs, &vit);

		// Initialize sublayout, using original positions
		if(startFromCurrentPositions){
			// Count vertices
			int vertices = 0;
			// Iterator over vertices to count them, hacked but it works
			while(!IGRAPH_VIT_END(vit)){
				vertices++;
				IGRAPH_VIT_NEXT(vit);
			}
			//Reset vertex iterator
			IGRAPH_VIT_RESET(vit);
			// Resize sublayout
			igraph_matrix_resize(&sublayout, vertices, 2);
			// Iterator over vertices
			while(!IGRAPH_VIT_END(vit)){
				int subindex = (int)IGRAPH_VIT_GET(vit);
				int index = (int)igraph_cattribute_VAN(subgraph, "id", subindex);
				MATRIX(sublayout, subindex, 0) = posx[index];
				MATRIX(sublayout, subindex, 1) = posy[index];
				IGRAPH_VIT_NEXT(vit);
			}
			//Reset vertex iterator
			IGRAPH_VIT_RESET(vit);
		}

		igraph_layout_kamada_kawai(subgraph, &sublayout, 1000, ((double)V)/4.0, 10, 0.99, V*V, startFromCurrentPositions);
		// Other layout algorithms with reasonable parameters
		//igraph_layout_kamada_kawai(subgraph, &sublayout, 1000, ((double)V)/4.0, 10, 0.99, V*V, startFromCurrentPositions);
		//igraph_layout_grid_fruchterman_reingold(subgraph, &sublayout, 500, V, V*V, 1.5, V*V*V, V*V/4, startFromCurrentPositions);
		//igraph_layout_fruchterman_reingold(subgraph, &sublayout, 500, V, V*V, 1.5, V*V*V, startFromCurrentPositions, NULL);
		//igraph_layout_lgl(subgraph, &sublayout, 150, V, V*V, 1.5, V*V*V, sqrt(V), -1);

		//Find min and max values:
		double minx = DBL_MAX,
			   miny = DBL_MAX,
			   maxx = -DBL_MAX,
			   maxy = -DBL_MAX;
		//Iterator over all vertices
		while(!IGRAPH_VIT_END(vit)){
			int subindex = (int)IGRAPH_VIT_GET(vit);
			double x = MATRIX(sublayout, subindex, 0) * factor;
			double y = MATRIX(sublayout, subindex, 1) * factor;
			minx = minx < x ? minx : x;
			miny = miny < y ? miny : y;
			maxx = maxx > x ? maxx : x;
			maxy = maxy > y ? maxy : y;
			IGRAPH_VIT_NEXT(vit);
		}
		//Reset vertex iterator
		IGRAPH_VIT_RESET(vit);

		// Compute translation
		double tx = margin - minx;
		double ty = margin - miny;
		// Decide whether to put it below or left of current content
		if(maxx - minx + offsetx < maxy - miny + offsety){
			tx += offsetx;
			offsetx += maxx - minx + margin;
			if(offsety < maxy - miny + margin)
				offsety = maxy - miny + margin;
		}else{
			ty += offsety;
			offsety += maxy - miny + margin;
			if(offsetx < maxx - minx + margin)
				offsetx = maxx - minx + margin;
		}
		// Translate and extract results
		while(!IGRAPH_VIT_END(vit)){
			int subindex = (int)IGRAPH_VIT_GET(vit);
			int index = (int)igraph_cattribute_VAN(subgraph, "id", subindex);
			double x = MATRIX(sublayout, subindex, 0) * factor;
			double y = MATRIX(sublayout, subindex, 1) * factor;
			posx[index] = x + tx;
			posy[index] = y + ty;
			IGRAPH_VIT_NEXT(vit);
		}
		// Destroy iterator and selector
		igraph_vit_destroy(&vit);
		igraph_vs_destroy(&vs);

		// Destroy the sublayout
		igraph_matrix_destroy(&sublayout);

		// Destroy subgraph
		igraph_destroy(subgraph);
		free(VECTOR(subgraphs)[i]);
	}

	// Remove the attributes
	igraph_cattribute_remove_v(&graph, "id");

	// Destroy the graph
	igraph_destroy(&graph);

	// Insert results
	i = 0;
	for(PlaceIter it = places.begin(); it != places.end(); it++){
		it->x = posx[i];
		it->y = posy[i];
		i++;
	}
	for(TransitionIter it = transitions.begin(); it != transitions.end(); it++){
		it->x = posx[i];
		it->y = posy[i];
		i++;
	}

	// Produce variables
	for(VarIter it = vars.begin(); it != vars.end(); it++)
		builder->addVariable(it->name, it->initialValue, it->range);

	for(BoolVarIter it = boolVars.begin(); it != boolVars.end(); it++)
		builder->addBoolVariable(it->name, it->initialValue);

	for(PlaceIter it = places.begin(); it != places.end(); it++)
		builder->addPlace(it->name, it->tokens, it->x, it->y);

	for(TransitionIter it = transitions.begin(); it != transitions.end(); it++)
		builder->addTransition(it->name, it->conditions, it->assignments, it->x, it->y);

	for(ArcIter it = inArcs.begin(); it != inArcs.end(); it++)
		builder->addInputArc(it->start, it->end, it->weight);

	for(ArcIter it = outArcs.begin(); it != outArcs.end(); it++)
		builder->addInputArc(it->start, it->end, it->weight);

	//Reset builder state (just in case some idoit decides to reuse it!
	vars.clear();
	boolVars.clear();
	places.clear();
	transitions.clear();
	inArcs.clear();
	outArcs.clear();
}
int main() {
  float dist[8][8] = {
	  {0.00, 4.69, 6.79, 3.50, 3.11, 4.46, 5.57, 3.00},
	  {4.69, 0.00, 2.10, 2.27, 2.65, 2.36, 1.99, 1.74},
	  {6.79, 2.10, 0.00, 3.78, 4.53, 2.83, 2.44, 3.79},
	  {3.50, 2.27, 3.78, 0.00, 1.98, 4.35, 2.07, 0.53},
	  {3.11, 2.65, 4.53, 1.98, 0.00, 3.80, 3.31, 1.47},
	  {4.46, 2.36, 2.83, 4.35, 3.80, 0.00, 4.35, 3.82},
	  {5.57, 1.99, 2.44, 2.07, 3.31, 4.35, 0.00, 2.57},
	  {3.00, 1.74, 3.79, 0.53, 1.47, 3.82, 2.57, 0.00},
  };
  igraph_t g;
  igraph_matrix_t coords, dist_mat;
  igraph_real_t vc;
  igraph_arpack_options_t options;
  int i, j;
  srand(time(0));

  igraph_arpack_options_init(&options);

  igraph_tree(&g, 10, 2, IGRAPH_TREE_UNDIRECTED);
  igraph_matrix_init(&coords, 0, 0);
  igraph_layout_mds(&g, &coords, 0, 2, &options);
  if (MATRIX(coords, 0, 0) > 0) {
    for (i = 0; i < igraph_matrix_nrow(&coords); i++)
      MATRIX(coords, i, 0) *= -1;
  }
  if (MATRIX(coords, 0, 1) < 0) {
    for (i = 0; i < igraph_matrix_nrow(&coords); i++)
      MATRIX(coords, i, 1) *= -1;
  }
  igraph_matrix_print(&coords);
  igraph_matrix_destroy(&coords);
  igraph_destroy(&g);

  igraph_full(&g, 8, IGRAPH_UNDIRECTED, 0);
  igraph_matrix_init(&coords, 8, 2);
  igraph_matrix_init(&dist_mat, 8, 8);
  for (i = 0; i < 8; i++)
    for (j = 0; j < 2; j++)
      MATRIX(coords, i, j) = rand() % 1000;
  for (i = 0; i < 8; i++)
    for (j = i+1; j < 8; j++) {
      double dist_sq = 0.0;
      dist_sq += sqr(MATRIX(coords, i, 0)-MATRIX(coords, j, 0));
      dist_sq += sqr(MATRIX(coords, i, 1)-MATRIX(coords, j, 1));
      MATRIX(dist_mat, i, j) = sqrt(dist_sq);
      MATRIX(dist_mat, j, i) = sqrt(dist_sq);
	}
  igraph_layout_mds(&g, &coords, &dist_mat, 2, &options);
  for (i = 0; i < 8; i++)
    for (j = i+1; j < 8; j++) {
      double dist_sq = 0.0;
      dist_sq += sqr(MATRIX(coords, i, 0)-MATRIX(coords, j, 0));
      dist_sq += sqr(MATRIX(coords, i, 1)-MATRIX(coords, j, 1));
      if (fabs(sqrt(dist_sq) - MATRIX(dist_mat, i, j)) > 1e-2) {
        printf("dist(%d,%d) should be %.4f, but it is %.4f\n",
				i, j, MATRIX(dist_mat, i, j), sqrt(dist_sq));
        return 1;
      }
    }
  igraph_matrix_destroy(&dist_mat);
  igraph_matrix_destroy(&coords);
  igraph_destroy(&g);

  return 0;
}
Exemple #9
0
static double mdet(double *ap, int dimen, int rowa)
/*  double  *ap;          input matrix */
/*  int     dimen;        Dimension of linre and row, those must be equal,
                          that is square matrix.       */
/*  int     rowa;         ROW Dimension of matrix A    */
{
    double det = 1.0;
    double work;
    int    is = 0;
    int    mmax;
    int    i, j, k;

    for(k = 0; k < dimen - 1; k++) {
        mmax = k;
        for(i = k + 1; i < dimen; i++)
            if (fabs(MATRIX(ap, i, k, rowa)) > fabs(MATRIX(ap, mmax, k, rowa)))
                mmax = i;
        if(mmax != k) {
            for (j = k; j < dimen; j++) {
                work = MATRIX(ap, k, j, rowa);
                MATRIX(ap, k, j, rowa) = MATRIX(ap, mmax, j, rowa);
                MATRIX(ap, mmax, j, rowa) = work;
            }
            is++;
        }
        for(i = k + 1; i < dimen; i++) {
            work = MATRIX(ap, i, k, rowa) / MATRIX(ap, k, k, rowa);
            for (j = k + 1; j < dimen; j++)
                MATRIX(ap, i, j, rowa) -= work * MATRIX(ap, k, j, rowa);
        }
    }
    for(i = 0; i < dimen; i++)
        det *= MATRIX(ap, i, i, rowa);
    for(i = 0; i < is; i++) 
        det *= -1.0;
    return(det);
}
Exemple #10
0
int igraph_i_kleinberg(const igraph_t *graph, igraph_vector_t *vector,
		       igraph_real_t *value, igraph_bool_t scale,
		       igraph_arpack_options_t *options, int inout) {
  
  igraph_adjlist_t myinadjlist, myoutadjlist;
  igraph_adjlist_t *inadjlist, *outadjlist;
  igraph_vector_t tmp;
  igraph_vector_t values;
  igraph_matrix_t vectors;
  igraph_i_kleinberg_data_t extra;
  long int i;
  
  options->n=igraph_vcount(graph);
  options->start=1;
  
  IGRAPH_VECTOR_INIT_FINALLY(&values, 0);
  IGRAPH_MATRIX_INIT_FINALLY(&vectors, options->n, 1);
  IGRAPH_VECTOR_INIT_FINALLY(&tmp, options->n);
  
  if (inout==0) {
    inadjlist=&myinadjlist; 
    outadjlist=&myoutadjlist;
  } else if (inout==1) {
    inadjlist=&myoutadjlist;
    outadjlist=&myinadjlist;
  } else {
    /* This should not happen */
    IGRAPH_ERROR("Invalid 'inout' argument, plese do not call "
		 "this funtion directly", IGRAPH_FAILURE);
  }

  IGRAPH_CHECK(igraph_adjlist_init(graph, &myinadjlist, IGRAPH_IN));
  IGRAPH_FINALLY(igraph_adjlist_destroy, &myinadjlist);
  IGRAPH_CHECK(igraph_adjlist_init(graph, &myoutadjlist, IGRAPH_OUT));
  IGRAPH_FINALLY(igraph_adjlist_destroy, &myoutadjlist);

  IGRAPH_CHECK(igraph_degree(graph, &tmp, igraph_vss_all(), IGRAPH_ALL, 0));
  for (i=0; i<options->n; i++) {
    if (VECTOR(tmp)[i] != 0) { 
      MATRIX(vectors, i, 0) = VECTOR(tmp)[i];
    } else {
      MATRIX(vectors, i, 0) = 1.0;
    }
  }
	
  extra.in=inadjlist; extra.out=outadjlist; extra.tmp=&tmp;

  options->n = igraph_vcount(graph);
  options->nev = 1;
  options->ncv = 3;
  options->which[0]='L'; options->which[1]='M';
  options->start=1;		/* no random start vector */

  IGRAPH_CHECK(igraph_arpack_rssolve(igraph_i_kleinberg2, &extra,
				     options, 0, &values, &vectors));

  igraph_adjlist_destroy(&myoutadjlist);
  igraph_adjlist_destroy(&myinadjlist);
  igraph_vector_destroy(&tmp);
  IGRAPH_FINALLY_CLEAN(3);

  if (value) { 
    *value = VECTOR(values)[0];
  }

  if (vector) {
    igraph_real_t amax=0;
    long int which=0;
    long int i;
    IGRAPH_CHECK(igraph_vector_resize(vector, options->n));
    for (i=0; i<options->n; i++) {
      igraph_real_t tmp;
      VECTOR(*vector)[i] = MATRIX(vectors, i, 0);
      tmp=fabs(VECTOR(*vector)[i]);
      if (tmp>amax) { amax=tmp; which=i; }
    }
    if (scale && amax!=0) { igraph_vector_scale(vector, 1/VECTOR(*vector)[which]); }
  }
  
  if (options->info) {
    IGRAPH_WARNING("Non-zero return code from ARPACK routine!");
  }
  igraph_matrix_destroy(&vectors);
  igraph_vector_destroy(&values);
  IGRAPH_FINALLY_CLEAN(2);
  
  return 0;
}
Exemple #11
0
int igraph_pagerank(const igraph_t *graph, igraph_vector_t *vector,
		    igraph_real_t *value, const igraph_vs_t vids,
		    igraph_bool_t directed, igraph_real_t damping, 
		    const igraph_vector_t *weights,
		    igraph_arpack_options_t *options) {

  igraph_matrix_t values;
  igraph_matrix_t vectors;
  igraph_integer_t dirmode;
  igraph_vector_t outdegree;
  igraph_vector_t tmp;
  long int i;
  long int no_of_nodes=igraph_vcount(graph);
  long int no_of_edges=igraph_ecount(graph);

  options->n = igraph_vcount(graph);
  options->nev = 1;
  options->ncv = 3;
  options->which[0]='L'; options->which[1]='M';
  options->start=1;		/* no random start vector */

  directed = directed && igraph_is_directed(graph);

  if (weights && igraph_vector_size(weights) != igraph_ecount(graph))
  {
    IGRAPH_ERROR("Invalid length of weights vector when calculating "
		 "PageRank scores", IGRAPH_EINVAL);
  }
  
  IGRAPH_MATRIX_INIT_FINALLY(&values, 0, 0);
  IGRAPH_MATRIX_INIT_FINALLY(&vectors, options->n, 1);

  if (directed) { dirmode=IGRAPH_IN; } else { dirmode=IGRAPH_ALL; }

  IGRAPH_VECTOR_INIT_FINALLY(&outdegree, options->n);
  IGRAPH_VECTOR_INIT_FINALLY(&tmp, options->n);

  RNG_BEGIN();

  if (!weights) {
    
    igraph_adjlist_t adjlist;
    igraph_i_pagerank_data_t data = { graph, &adjlist, damping,
				      &outdegree, &tmp };

    IGRAPH_CHECK(igraph_degree(graph, &outdegree, igraph_vss_all(),
			       directed ? IGRAPH_OUT : IGRAPH_ALL, /*loops=*/ 0));
    /* Avoid division by zero */
    for (i=0; i<options->n; i++) {
      if (VECTOR(outdegree)[i]==0) {
	VECTOR(outdegree)[i]=1;
      }
      MATRIX(vectors, i, 0) = VECTOR(outdegree)[i];
    } 

    IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, dirmode));
    IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist);
    
    IGRAPH_CHECK(igraph_arpack_rnsolve(igraph_i_pagerank,
				       &data, options, 0, &values, &vectors));

    igraph_adjlist_destroy(&adjlist);
    IGRAPH_FINALLY_CLEAN(1);
    
  } else {
    
    igraph_adjedgelist_t adjedgelist;
    igraph_i_pagerank_data2_t data = { graph, &adjedgelist, weights,
				       damping, &outdegree, &tmp };    

    IGRAPH_CHECK(igraph_adjedgelist_init(graph, &adjedgelist, dirmode));
    IGRAPH_FINALLY(igraph_adjedgelist_destroy, &adjedgelist);

    /* Weighted degree */
    for (i=0; i<no_of_edges; i++) {
      long int from=IGRAPH_FROM(graph, i);
      long int to=IGRAPH_TO(graph, i);
      igraph_real_t weight=VECTOR(*weights)[i];
      VECTOR(outdegree)[from] += weight;
      if (!directed) { 
	VECTOR(outdegree)[to]   += weight;
      }
    }
    /* Avoid division by zero */
    for (i=0; i<options->n; i++) {
      if (VECTOR(outdegree)[i]==0) {
	VECTOR(outdegree)[i]=1;
      }
      MATRIX(vectors, i, 0) = VECTOR(outdegree)[i];
    }     
    
    IGRAPH_CHECK(igraph_arpack_rnsolve(igraph_i_pagerank2,
				       &data, options, 0, &values, &vectors));
    
    igraph_adjedgelist_destroy(&adjedgelist);
    IGRAPH_FINALLY_CLEAN(1);
  }

  RNG_END();

  igraph_vector_destroy(&tmp);
  igraph_vector_destroy(&outdegree);
  IGRAPH_FINALLY_CLEAN(2);

  if (value) {
    *value=MATRIX(values, 0, 0);
  }
  
  if (vector) {
    long int i;
    igraph_vit_t vit;
    long int nodes_to_calc;
    igraph_real_t sum=0;
    
    for (i=0; i<no_of_nodes; i++) { 
      sum += MATRIX(vectors, i, 0);
    }

    IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
    IGRAPH_FINALLY(igraph_vit_destroy, &vit);
    nodes_to_calc=IGRAPH_VIT_SIZE(vit);

    IGRAPH_CHECK(igraph_vector_resize(vector, nodes_to_calc));
    for (IGRAPH_VIT_RESET(vit), i=0; !IGRAPH_VIT_END(vit);
	 IGRAPH_VIT_NEXT(vit), i++) {
      VECTOR(*vector)[i] = MATRIX(vectors, (long int)IGRAPH_VIT_GET(vit), 0);
      VECTOR(*vector)[i] /= sum;
    }
    
    igraph_vit_destroy(&vit);
    IGRAPH_FINALLY_CLEAN(1);
  }

  if (options->info) {
    IGRAPH_WARNING("Non-zero return code from ARPACK routine!");
  }
  
  igraph_matrix_destroy(&vectors);
  igraph_matrix_destroy(&values);
  IGRAPH_FINALLY_CLEAN(2);
  return 0;
}
Exemple #12
0
int igraph_eigenvector_centrality(const igraph_t *graph, igraph_vector_t *vector,
				  igraph_real_t *value, igraph_bool_t scale,
				  const igraph_vector_t *weights,
				  igraph_arpack_options_t *options) {
  
  igraph_vector_t values;
  igraph_matrix_t vectors;
  igraph_vector_t degree;
  long int i;
  
  options->n=igraph_vcount(graph);
  options->start=1;		/* no random start vector */

  if (weights && igraph_vector_size(weights) != igraph_ecount(graph)) {
    IGRAPH_ERROR("Invalid length of weights vector when calculating "
		 "eigenvector centrality", IGRAPH_EINVAL);
  }

  if (weights && igraph_is_directed(graph)) {
    IGRAPH_WARNING("Weighted directed graph in eigenvector centrality");
  }

  IGRAPH_VECTOR_INIT_FINALLY(&values, 0);
  IGRAPH_MATRIX_INIT_FINALLY(&vectors, options->n, 1);

  IGRAPH_VECTOR_INIT_FINALLY(&degree, options->n);
  IGRAPH_CHECK(igraph_degree(graph, &degree, igraph_vss_all(), 
			     IGRAPH_ALL, /*loops=*/ 0));
  for (i=0; i<options->n; i++) {
    if (VECTOR(degree)[i]) {
      MATRIX(vectors, i, 0) = VECTOR(degree)[i];
    } else {
      MATRIX(vectors, i, 0) = 1.0;
    }
  }
  igraph_vector_destroy(&degree);
  IGRAPH_FINALLY_CLEAN(1);
  
  options->n = igraph_vcount(graph);
  options->nev = 1;
  options->ncv = 3;
  options->which[0]='L'; options->which[1]='A';
  options->start=1;		/* no random start vector */

  if (!weights) {
    
    igraph_adjlist_t adjlist;

    IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, IGRAPH_ALL));
    IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist);
    
    IGRAPH_CHECK(igraph_arpack_rssolve(igraph_i_eigenvector_centrality,
				       &adjlist, options, 0, &values, &vectors));

    igraph_adjlist_destroy(&adjlist);
    IGRAPH_FINALLY_CLEAN(1);
    
  } else {
    
    igraph_adjedgelist_t adjedgelist;
    igraph_i_eigenvector_centrality_t data = { graph, &adjedgelist, weights };
    
    IGRAPH_CHECK(igraph_adjedgelist_init(graph, &adjedgelist, IGRAPH_ALL));
    IGRAPH_FINALLY(igraph_adjedgelist_destroy, &adjedgelist);
    
    IGRAPH_CHECK(igraph_arpack_rssolve(igraph_i_eigenvector_centrality2,
				       &data, options, 0, &values, &vectors));
    
    igraph_adjedgelist_destroy(&adjedgelist);
    IGRAPH_FINALLY_CLEAN(1);
  }

  if (value) {
    *value=VECTOR(values)[0];
  }
  
  if (vector) {
    igraph_real_t amax=0;
    long int which=0;
    long int i;
    IGRAPH_CHECK(igraph_vector_resize(vector, options->n));
    for (i=0; i<options->n; i++) {
      igraph_real_t tmp;
      VECTOR(*vector)[i] = MATRIX(vectors, i, 0);
      tmp=fabs(VECTOR(*vector)[i]);
      if (tmp>amax) { amax=tmp; which=i; }
    }
    if (scale && amax!=0) { igraph_vector_scale(vector, 1/VECTOR(*vector)[which]); }
  }

  if (options->info) {
    IGRAPH_WARNING("Non-zero return code from ARPACK routine!");
  }
  
  igraph_matrix_destroy(&vectors);
  igraph_vector_destroy(&values);
  IGRAPH_FINALLY_CLEAN(2);
  return 0;
}
Exemple #13
0
/* HMM_updateModel -
 *  Given an HMM and a vector of log likelihoods for states in the sequences,
 *  calculates the responsibilities of each state in the HMM for each symbol
 *  in the sequences, and maximises the model parameters based on the
 *  assigned log likelihoods.
*/
Real HMM_updateModel(Hmm *m, Hmm *new_m, RVec *logL, RVec *gamma, Real log_D,
		     Real postpC, int c, int c_ls,
		     enum training_mode training_mode) {
  int t, u, v, tt = VLENGTH(logL[0]);
  Real **a = MATRIX(m->logA), *b = VECTOR(m->logB), **al, **be, ***ps;
  Real logD = 0, like, dtf;
  int Sc = (c==c_ls);
  switch (training_mode) {
  case HMM_ML:
    assert(postpC==0.0);
    logD = NEGATIVE_INFINITY;
    break;
  case HMM_DT:
    assert(c>=0&&c_ls>=0);
    logD = log_D;
    break;
  default: panic("unrecognized training mode");
  }
  assert(VLENGTH(logL[0])==VLENGTH(gamma[0]));
  HMM_initGlobals(m->uu, tt);
  al = MATRIX(g_alpha);
  be = MATRIX(g_beta);
  ps = MATRIX(g_psi);
  /* calculate alpha's */
  HMM_calcAlphas(m, logL);
  /* calculate beta's -
   * beta[u][tt] = 1
   * beta[u][t] = sum(v = 1 ... m->uu, a[u][v]*beta[v][t+1]*logL[v][t+1])
   */
  for (u = 0; u<m->uu; u++) be[u][tt-1] = 0.0;
  for (t = tt-2; t>=0; t--)
  { for (u = 0; u<m->uu; u++)
    { be[u][t] = NEGATIVE_INFINITY;
      for (v = 0; v<m->uu; v++)
      { be[u][t] =
	add_exp(be[u][t], a[u][v]+be[v][t+1]+VECTOR(logL[v])[t+1]);}}}

  /* calculate logL of sequence -
   * P(sequence|m) = sum(u = 1 ... m->uu, alpha[u][tt])
   */
  like = NEGATIVE_INFINITY;
  for (u = 0; u<m->uu; u++)
    like = add_exp(like, al[u][tt-1]);

  /* A sample that can NEVER belong to this category */
  if(like == NEGATIVE_INFINITY){
    assert(postpC == 0.0);
    assert(Sc==0);
  }

  /* calculate responsibilities
   *               alpha[u][t]*beta[u][t]
   * gamma[u][t] = ----------------------
   *                    P(data|model)
   */
  for (t = 0; t<tt; t++){
     for (u = 0; u<m->uu; u++){
       if(like!=NEGATIVE_INFINITY)
	 VECTOR(gamma[u])[t] = al[u][t]+be[u][t]-like;
       else
	 VECTOR(gamma[u])[t] = NEGATIVE_INFINITY;
     }
  }
  /* calculate time-indexed transition probabilities
   *                alpha[u][t]*a[u][v]*logL[v][t+1]*beta[v][t+1]
   * psi[u][v][t] = ---------------------------------------------
   *                               P(data|model)
   */
  for (u = 0; u<m->uu; u++){
    for (v = 0; v<m->uu; v++){
      for (t = 0; t<tt-1; t++){
	if(like!=NEGATIVE_INFINITY)
	  ps[u][v][t] = al[u][t]+a[u][v]+VECTOR(logL[v])[t+1]+be[v][t+1]-like;
	else
	  ps[u][v][t] = NEGATIVE_INFINITY;
      }
    }
  }
  /* Update new model. The model may have been partly updated by some training
     samples. */
  a = MATRIX(new_m->logA);
  b = VECTOR(new_m->logB);
  /* calculate B
     b[u] = gamma[u][1]
     - added scaling by sum of gammas to catch any numerical accuracy problems
     not log space here
   */
  for (u = 0; u<m->uu; u++) {
    /* This may be negative */
    b[u] += (Sc-postpC)*my_exp(VECTOR(gamma[u])[0])
      +my_exp(logD+VECTOR(m->logB)[u]);
  }
  /* calculate A matrix
   *                    sum(t = 1 ... tt-1, psi[u][v][t])
   * a[u][v] = -------------------------------------------------------
   *           sum(t = 1 ... tt-1, sum(w = 1 ... m->uu, psi[u][w][t]))
   * see note above about log space
   */
  for (u = 0; u<m->uu; u++) {
    for (v = 0; v<m->uu; v++) {
      /* This may be negative */
      dtf = 0.0;
      for(t = 0; t<tt-1; t++)
	dtf += my_exp(ps[u][v][t])*(Sc-postpC) + my_exp(logD+MATRIX(m->logA)[u][v]);
      a[u][v] += dtf;
    }
  }
  for (t = 0; t<tt; t++) {
    for (u = 0; u<m->uu; u++) VECTOR(gamma[u])[t] = my_exp(VECTOR(gamma[u])[t]);
  }
  return like;
}
Exemple #14
0
/* zeroHMMlinear - Sets all of the transition probabilities to 0.0 in the
   orginal space. This function is needed in dt training because during update a
   negative value may occur. */
void zeroHMMlinear(Hmm *m)
{ int u, v;
  for (u = 0; u<m->uu; u++)
  { VECTOR(m->logB)[u] = 0.0;
    for (v = 0; v<m->uu; v++)
    { MATRIX(m->logA)[u][v] = 0.0;}}}
float LevenshteinDistance(const Py_UNICODE * s1, int len1,
	                      const Py_UNICODE * s2, int len2)
{
	/* Step 1 */
	/* Check string lengths */

	if (len1 == 0)
		return 0.0f;

	if (len2 == 0)
		return 0.0f;

	/* Step 2 */
	/* Allocate matrix for algorithm and fill it with default values */

	int *matrix = new int[(len1 + 1) * (len2 + 1)];

	for (int index1 = 0; index1 <= len1; index1++)
	    MATRIX(index1, 0) = index1;

	for (int index2 = 0; index2 <= len2; index2++)
	    MATRIX(0, index2) = index2;

	/* Step 3 */
	/* Loop through first string */

	for (int index1 = 1; index1 <= len1; index1++)
	{
		Py_UNICODE s1_current = s1[index1 - 1];

		/* Step 4 */
		/* Loop through second string */

		for (int index2 = 1; index2 <= len2; index2++)
		{
			Py_UNICODE s2_current = s2[index2 - 1];

			/* Step 5 */
			/* Calculate cost of this iteration
			   (handles deletion, insertion, and substitution) */

			int cost = (s1_current == s2_current) ? 0 : 1;

			/* Step 6 */
			/* Calculate the total cost up to this point */

			int above = MATRIX(index1 - 1, index2);
			int left = MATRIX(index1, index2 - 1);
			int diagonal = MATRIX(index1 - 1, index2 - 1);
			int cell = min(min(above + 1, left + 1), diagonal + cost);

			/* Step 6a */
			/* Also cover transposition. This step is taken from:
			   Berghel, Hal ; Roach, David : "An Extension of Ukkonen's 
			   Enhanced Dynamic Programming ASM Algorithm"
			   (http://berghel.net/publications/asm/asm.php) */
			
			if (index1 > 2 && index2 > 2)
			{
				int trans = MATRIX(index1 - 2, index2 - 2) + 1;
				if (s1[index1 - 2] != s2_current)
					trans++;
				if (s1_current != s2[index2 - 2])
					trans++;
				if (cell > trans)
					cell = trans;
			}

			MATRIX(index1, index2) = cell;
		}
	}


	/* Step 7 */
	/* Return result */

    float result = ((float)1 - ((float)MATRIX(len1, len2) / (float)max(len1, len2)));

    delete [] matrix;

	return result;
}
Exemple #16
0
void schur(Matrix M, Matrix V, Matrix W, int nb)
{
     Matrix M00, M01, M10, M11;
     Matrix V00, V01, V10, V11;
     Matrix W00, W01, W10, W11;
     int hnb;

     /* Check base case. */
     if (nb == 1) {
	  block_schur(*M, *V, *W);
	  return;
     }
     /* Break matrices into 4 pieces. */
     hnb = nb / 2;
     M00 = &MATRIX(M, 0, 0);
     M01 = &MATRIX(M, 0, hnb);
     M10 = &MATRIX(M, hnb, 0);
     M11 = &MATRIX(M, hnb, hnb);
     V00 = &MATRIX(V, 0, 0);
     V01 = &MATRIX(V, 0, hnb);
     V10 = &MATRIX(V, hnb, 0);
     V11 = &MATRIX(V, hnb, hnb);
     W00 = &MATRIX(W, 0, 0);
     W01 = &MATRIX(W, 0, hnb);
     W10 = &MATRIX(W, hnb, 0);
     W11 = &MATRIX(W, hnb, hnb);

     /* Form Schur complement with recursive calls. */
     cilk_spawn schur(M00, V00, W00, hnb);
     cilk_spawn schur(M01, V00, W01, hnb);
     cilk_spawn schur(M10, V10, W00, hnb);
     cilk_spawn schur(M11, V10, W01, hnb);
     cilk_sync;

     cilk_spawn schur(M00, V01, W10, hnb);
     cilk_spawn schur(M01, V01, W11, hnb);
     cilk_spawn schur(M10, V11, W10, hnb);
     cilk_spawn schur(M11, V11, W11, hnb);
     cilk_sync;

     return;
}
Exemple #17
0
void multi_burg(int *pn, double *x, int *pomax, int *pnser, double *coef,
	double *pacf, double *var, double *aic, int *porder, int *useaic,
	int *vmethod)
{
    int i, j, m, omax = *pomax, n = *pn, nser=*pnser, order=*porder;
    int dim1[3];
    double aicmin;
    Array xarr, resid_f, resid_b, resid_f_tmp;
    Array *A, *B, P, V;

    dim1[0] = omax+1; dim1[1] = dim1[2] = nser;
    A = (Array *) R_alloc(omax+1, sizeof(Array));
    B = (Array *) R_alloc(omax+1, sizeof(Array));
    for (i = 0; i <= omax; i++) {
	A[i] = make_zero_array(dim1, 3);
	B[i] = make_zero_array(dim1, 3);
    }
    P = make_array(pacf, dim1, 3);
    V = make_array(var, dim1, 3);

    xarr = make_matrix(x, nser, n);
    resid_f = make_zero_matrix(nser, n);
    resid_b = make_zero_matrix(nser, n);
    set_array_to_zero(resid_b);
    copy_array(xarr, resid_f);
    copy_array(xarr, resid_b);
    resid_f_tmp = make_zero_matrix(nser, n);

    burg0(omax, resid_f, resid_b, A, B, P, V, *vmethod);

    /* Model order selection */

    for (i = 0; i <= omax; i++) {
	aic[i] = n * ldet(subarray(V,i)) + 2 * i * nser * nser;
    }
    if (*useaic) {
	order = 0;
	aicmin = aic[0];
	for (i = 1; i <= omax; i++) {
	    if (aic[i] < aicmin) {
		aicmin = aic[i];
		order = i;
	    }
	}
    }
    else order = omax;
    *porder = order;

    for(i = 0; i < vector_length(A[order]); i++)
	coef[i] = VECTOR(A[order])[i];

    if (*useaic) {
	/* Recalculate residuals for chosen model */
	set_array_to_zero(resid_f);
	set_array_to_zero(resid_f_tmp);
	for (m = 0; m <= order; m++) {
	    for (i = 0; i < NROW(resid_f_tmp); i++) {
		for (j = 0; j < NCOL(resid_f_tmp) - order; j++) {
		    MATRIX(resid_f_tmp)[i][j + order] = MATRIX(xarr)[i][j + order - m];
		}
	    }
	    matrix_prod(subarray(A[order],m), resid_f_tmp, 0, 0, resid_f_tmp);
	    array_op(resid_f_tmp, resid_f, '+', resid_f);
	}
    }
    copy_array(resid_f, xarr);

}
Exemple #18
0
/* normaliseHMMlinear -
    Normalises an HMM in the original space so that transition probabilites
    sum to 1. After this, convert all the values from the original space to
    log space.
 */
int normaliseHMMlinear(Hmm *m, int upper_triangular, enum training_mode train_mode, int *xu)
{ int u, v, w;
  Real sum, corrected_sum;
  int flag;
  sum = 0.0;
  for (u = 0; u < m->uu; u++)
    sum += VECTOR(m->logB)[u];

  assert(fabs(sum)>0.0);
  flag = 0;
  corrected_sum = NEGATIVE_INFINITY;
  for (u = 0; u<m->uu; u++) {
    if(VECTOR(m->logB)[u]/sum < -1e-50){
      printf("normaliseHMMlinear: b error\n");
      return FALSE;
    }
    VECTOR(m->logB)[u] = my_log(VECTOR(m->logB)[u]/sum);
    /* Clip the value to zero if it is smaller than CORRECTION_EPS */
    if(train_mode == HMM_DT
       && VECTOR(m->logB)[u] != NEGATIVE_INFINITY
       && VECTOR(m->logB)[u] < my_log(CORRECTION_EPS)){
      printf("normaliseHMMlinear: clip zero\n");
      VECTOR(m->logB)[u] = NEGATIVE_INFINITY;
      flag = 1;
    }
    corrected_sum = add_exp(corrected_sum, VECTOR(m->logB)[u]);
  }
  assert(corrected_sum != NEGATIVE_INFINITY);
  if(flag){
    for(u = 0; u < m->uu; u ++)
      VECTOR(m->logB)[u] -= corrected_sum;
  }
  for (u = 0; u<m->uu; u++)
  { sum = 0.0;
    w = (upper_triangular?u:0);
    for (v = w; v<m->uu; v++) sum += MATRIX(m->logA)[u][v];
    if (sum==0.0) {
      /* A state never jumps to another state (include itself)
	 This is not the unreachable state. It may be a final state or a useless state.
	 An unreachable state is finally to be a useless state.
         We can just keep all the outward transition probabilities zero. */
      // Do NOTHING. We don't want a corrected uniform distribution.
      for(v = 0; v < m->uu; v ++)
	MATRIX(m->logA)[u][v] = NEGATIVE_INFINITY;
      continue;
    }
    flag = 0;
    corrected_sum = NEGATIVE_INFINITY;
    for (v = 0; v<m->uu; v ++) {
      if(MATRIX(m->logA)[u][v]/sum < -1e-50){
	printf("normaliseHMMlinear: a error\n");
	return FALSE;
      }
      MATRIX(m->logA)[u][v] = my_log(MATRIX(m->logA)[u][v]/sum);
      /* Clip the value to zero if it is smaller than CORRECTION_EPS */
      if(train_mode == HMM_DT
	 && MATRIX(m->logA)[u][v] != NEGATIVE_INFINITY
      	 && MATRIX(m->logA)[u][v] < my_log(CORRECTION_EPS)){
	printf("normaliseHMMlinear: clip zero\n");
      	MATRIX(m->logA)[u][v] = NEGATIVE_INFINITY;
      	flag = 1;
      }
      corrected_sum = add_exp(corrected_sum, MATRIX(m->logA)[u][v]);
    }
    assert(corrected_sum != NEGATIVE_INFINITY);
    if(flag){
      for(v = 0; v < m->uu; v ++)
    	MATRIX(m->logA)[u][v] -= corrected_sum;
    }
  }
  /* Check whether any column in logA has entries that are all NEGATIVE_INFINITY,
     which is an unreachable state. */
  if (xu != NULL){
    memset(xu, 0, sizeof(int) * m->uu);
    for(u = 0; u < m->uu; u ++){
      flag = 0;
      /* 1. The entry of initial probability is 0 */
      if(VECTOR(m->logB)[u] == NEGATIVE_INFINITY) flag ++;
      /* 2. No other state (include itself) can reach this state */
      for(v = 0; v < m->uu; v ++)
	if(MATRIX(m->logA)[v][u] != NEGATIVE_INFINITY) break;
      if(v == m->uu) flag ++;
      if(flag == 2){
	printf("AN UNREACHABLE STATE IS REMOVED! State_#: %d Total state_#: %d\n", u, m->uu);
	xu[u] = 1;
      }
    }
  }
  return TRUE;
}