示例#1
0
int igraph_i_eigen_matrix_lapack_common(const igraph_matrix_t *A,
					const igraph_eigen_which_t *which, 
					igraph_vector_complex_t *values,
					igraph_matrix_complex_t *vectors) {

  igraph_vector_t valuesreal, valuesimag;
  igraph_matrix_t vectorsright, *myvectors= vectors ? &vectorsright : 0;
  int n=(int) igraph_matrix_nrow(A);
  int info=1;

  IGRAPH_VECTOR_INIT_FINALLY(&valuesreal, n);
  IGRAPH_VECTOR_INIT_FINALLY(&valuesimag, n);
  if (vectors) { IGRAPH_MATRIX_INIT_FINALLY(&vectorsright, n, n); }
  IGRAPH_CHECK(igraph_lapack_dgeev(A, &valuesreal, &valuesimag, 
				   /*vectorsleft=*/ 0, myvectors, &info));

  IGRAPH_CHECK(igraph_i_eigen_matrix_lapack_reorder(&valuesreal, 
						    &valuesimag, 
						    myvectors, which, values,
						    vectors));
  
  if (vectors) { 
    igraph_matrix_destroy(&vectorsright);
    IGRAPH_FINALLY_CLEAN(1);
  }
  
  igraph_vector_destroy(&valuesimag);
  igraph_vector_destroy(&valuesreal);
  IGRAPH_FINALLY_CLEAN(2);

  return 0;
  
}
示例#2
0
int igraph_i_eigen_matrix_symmetric_arpack_be(const igraph_matrix_t *A, 
			   const igraph_sparsemat_t *sA, 
			   igraph_arpack_function_t *fun, 
			   int n, void *extra,
			   const igraph_eigen_which_t *which, 
			   igraph_arpack_options_t *options,
			   igraph_arpack_storage_t *storage,
			   igraph_vector_t *values, 
			   igraph_matrix_t *vectors) {
  
  igraph_vector_t tmpvalues, tmpvalues2;
  igraph_matrix_t tmpvectors, tmpvectors2;
  igraph_i_eigen_matrix_sym_arpack_data_t myextra = { A, sA };  
  int low=(int) floor(which->howmany/2.0), high=(int) ceil(which->howmany/2.0);
  int l1, l2, w;

  if (low + high >= n) {
    IGRAPH_ERROR("Requested too many eigenvalues/vectors", IGRAPH_EINVAL);
  }

  if (!fun) { 
    fun=igraph_i_eigen_matrix_sym_arpack_cb;
    extra=(void*) &myextra;
  }
  
  IGRAPH_VECTOR_INIT_FINALLY(&tmpvalues, high);
  IGRAPH_MATRIX_INIT_FINALLY(&tmpvectors, n, high);
  IGRAPH_VECTOR_INIT_FINALLY(&tmpvalues2, low);
  IGRAPH_MATRIX_INIT_FINALLY(&tmpvectors2, n, low);

  options->n=n;
  options->nev=high;
  options->ncv= 2*options->nev < n ? 2*options->nev : n;
  options->which[0]='L'; options->which[1]='A';
  
  IGRAPH_CHECK(igraph_arpack_rssolve(fun, extra, options, storage, 
				     &tmpvalues, &tmpvectors));

  options->nev=low;
  options->ncv= 2*options->nev < n ? 2*options->nev : n;
  options->which[0]='S'; options->which[1]='A';

  IGRAPH_CHECK(igraph_arpack_rssolve(fun, extra, options, storage,
				     &tmpvalues2, &tmpvectors2));

  IGRAPH_CHECK(igraph_vector_resize(values, low+high));
  IGRAPH_CHECK(igraph_matrix_resize(vectors, n, low+high));
  
  l1=0; l2=0; w=0;
  while (w < which->howmany) {
    VECTOR(*values)[w] = VECTOR(tmpvalues)[l1];
    memcpy(&MATRIX(*vectors, 0, w), &MATRIX(tmpvectors, 0, l1), 
	   (size_t) n * sizeof(igraph_real_t));
    w++; l1++;
    if (w < which->howmany) {
      VECTOR(*values)[w] = VECTOR(tmpvalues2)[l2];
      memcpy(&MATRIX(*vectors, 0, w), &MATRIX(tmpvectors2, 0, l2), 
	     (size_t) n * sizeof(igraph_real_t));
      w++; l2++;
    }
  }

  igraph_matrix_destroy(&tmpvectors2);
  igraph_vector_destroy(&tmpvalues2);
  igraph_matrix_destroy(&tmpvectors);
  igraph_vector_destroy(&tmpvalues);
  IGRAPH_FINALLY_CLEAN(4);
    
  return 0;
}
示例#3
0
int igraph_i_community_spinglass_negative(const igraph_t *graph,
					  const igraph_vector_t *weights,
					  igraph_real_t *modularity,
					  igraph_real_t *temperature,
					  igraph_vector_t *membership, 
					  igraph_vector_t *csize,
					  igraph_integer_t spins,
					  igraph_bool_t parupdate,
					  igraph_real_t starttemp,
					  igraph_real_t stoptemp,
					  igraph_real_t coolfact,
					  igraph_spincomm_update_t update_rule,
					  igraph_real_t gamma,
/* 					  igraph_matrix_t *adhesion, */
/* 					  igraph_matrix_t *normalised_adhesion, */
/* 					  igraph_real_t *polarization, */
					  igraph_real_t gamma_minus) {

  unsigned long changes, runs;
  igraph_bool_t use_weights=0;
  bool zeroT;
  double kT, acc;
  ClusterList<NNode*> *cl_cur;
  network *net;
  PottsModelN *pm;
  igraph_real_t d_n;
  igraph_real_t d_p;

  /* Check arguments */

  if (parupdate) {
    IGRAPH_ERROR("Parallel spin update not implemented with "
		 "negative gamma", IGRAPH_UNIMPLEMENTED);
  }

  if (spins < 2 || spins > 500) {
    IGRAPH_ERROR("Invalid number of spins", IGRAPH_EINVAL);
  }
  if (update_rule != IGRAPH_SPINCOMM_UPDATE_SIMPLE &&
      update_rule != IGRAPH_SPINCOMM_UPDATE_CONFIG) {
    IGRAPH_ERROR("Invalid update rule", IGRAPH_EINVAL);
  }
  if (weights) {
    if (igraph_vector_size(weights) != igraph_ecount(graph)) {
      IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL);
    }
    use_weights=1;
  }
  if (coolfact < 0 || coolfact>=1.0) {
    IGRAPH_ERROR("Invalid cooling factor", IGRAPH_EINVAL);
  }
  if (gamma < 0.0) {
    IGRAPH_ERROR("Invalid gamma value", IGRAPH_EINVAL);
  }
  if (starttemp/stoptemp<1.0) {
    IGRAPH_ERROR("starttemp should be larger in absolute value than stoptemp",
		 IGRAPH_EINVAL);
  }
  
  /* Check whether we have a single component */
  igraph_bool_t conn;
  IGRAPH_CHECK(igraph_is_connected(graph, &conn, IGRAPH_WEAK));
  if (!conn) {
    IGRAPH_ERROR("Cannot work with unconnected graph", IGRAPH_EINVAL);
  }
  
  igraph_vector_minmax(weights, &d_n, &d_p);
  if (d_n > 0) { d_n=0; }
  if (d_p < 0) { d_p=0; }
  d_n = -d_n;

  net = new network;
  net->node_list   =new DL_Indexed_List<NNode*>();
  net->link_list   =new DL_Indexed_List<NLink*>();
  net->cluster_list=new DL_Indexed_List<ClusterList<NNode*>*>();

  /* Transform the igraph_t */
  IGRAPH_CHECK(igraph_i_read_network(graph, weights,
				     net, use_weights, 0));
	
  bool directed = igraph_is_directed(graph);
  
  pm=new PottsModelN(net,(unsigned int)spins, directed);

  /* initialize the random number generator */
  RNG_BEGIN();
  
  if ((stoptemp==0.0) && (starttemp==0.0)) zeroT=true; else zeroT=false;

  //Begin at a high enough temperature
  kT=pm->FindStartTemp(gamma, gamma_minus, starttemp);

  /* assign random initial configuration */
  pm->assign_initial_conf(true);

  runs=0;
  changes=1;
  acc = 0;
	while (changes>0 && (kT/stoptemp>1.0 || (zeroT && runs<150))) 
	{
		
		IGRAPH_ALLOW_INTERRUPTION(); /* This is not clean.... */
		
		runs++;
		kT = kT*coolfact; 
		acc=pm->HeatBathLookup(gamma, gamma_minus, kT, 50);
		if (acc<(1.0-1.0/double(spins))*0.001)
			changes=0; 
		else 
			changes=1;
		
	} /* while loop */

  /* These are needed, otherwise 'modularity' is not calculated */
  igraph_matrix_t adhesion, normalized_adhesion;
  igraph_real_t polarization;
  IGRAPH_MATRIX_INIT_FINALLY(&adhesion, 0, 0);
  IGRAPH_MATRIX_INIT_FINALLY(&normalized_adhesion, 0, 0);
  pm->WriteClusters(modularity, temperature, csize, membership, 
		    &adhesion, &normalized_adhesion, &polarization, 
		    kT, d_p, d_n, gamma, gamma_minus);
  igraph_matrix_destroy(&normalized_adhesion);
  igraph_matrix_destroy(&adhesion);
  IGRAPH_FINALLY_CLEAN(2);

  while (net->link_list->Size()) delete net->link_list->Pop();
  while (net->node_list->Size()) delete net->node_list->Pop();
  while (net->cluster_list->Size())
    {
      cl_cur=net->cluster_list->Pop();
      while (cl_cur->Size()) cl_cur->Pop();
      delete cl_cur;
    }
  
  RNG_END();

  return 0;
}
示例#4
0
int igraph_i_eigen_matrix_symmetric_lapack_sm(const igraph_matrix_t *A,
			      const igraph_eigen_which_t *which,
			      igraph_vector_t *values,
			      igraph_matrix_t *vectors) {
  
  igraph_vector_t val;
  igraph_matrix_t vec;
  int i, w=0, n=(int) igraph_matrix_nrow(A);
  igraph_real_t small;
  int p1, p2, pr=0;

  IGRAPH_VECTOR_INIT_FINALLY(&val, 0);
  
  if (vectors) {
    IGRAPH_MATRIX_INIT_FINALLY(&vec, 0, 0);
  }
  
  IGRAPH_CHECK(igraph_lapack_dsyevr(A, IGRAPH_LAPACK_DSYEV_ALL, /*vl=*/ 0, 
				    /*vu=*/ 0, /*vestimate=*/ 0, 
				    /*il=*/ 0, /*iu=*/ 0, 
				    /*abstol=*/ 1e-14, &val, 
				    vectors ? &vec : 0,
				    /*support=*/ 0));

  /* Look for smallest value */
  small=fabs(VECTOR(val)[0]);
  for (i=1; i<n; i++) {
    igraph_real_t v=fabs(VECTOR(val)[i]);
    if (v < small) { 
      small=v;
      w=i;
    }
  }
  p1=w-1; p2=w;
  
  if (values) { IGRAPH_CHECK(igraph_vector_resize(values, which->howmany)); }
  if (vectors) { 
    IGRAPH_CHECK(igraph_matrix_resize(vectors, n, which->howmany));
  }

  while (pr < which->howmany) {
    if (p2 == n-1 || fabs(VECTOR(val)[p1]) < fabs(VECTOR(val)[p2])) {
      if (values) { 
	VECTOR(*values)[pr]=VECTOR(val)[p1];
      }
      if (vectors) {
	memcpy(&MATRIX(*vectors,0,pr), &MATRIX(vec,0,p1), 
	       sizeof(igraph_real_t) * (size_t) n);
      }
      p1--;
      pr++;
    } else {
      if (values) { 
	VECTOR(*values)[pr]=VECTOR(val)[p2];
      }
      if (vectors) {
	memcpy(&MATRIX(*vectors,0,pr), &MATRIX(vec,0,p2), 
	       sizeof(igraph_real_t) * (size_t) n);
      }
      p2++;
      pr++;
    }
  }

  if (vectors) {
    igraph_matrix_destroy(&vec);
    IGRAPH_FINALLY_CLEAN(1);
  }
  igraph_vector_destroy(&val);
  IGRAPH_FINALLY_CLEAN(1);

  return 0;
}
示例#5
0
int igraph_revolver_mes_d_d(const igraph_t *graph,
                            igraph_lazy_inclist_t *inclist,
                            igraph_matrix_t *kernel,
                            igraph_matrix_t *sd,
                            igraph_matrix_t *norm,
                            igraph_matrix_t *cites,
                            const igraph_matrix_t *debug,
                            igraph_vector_ptr_t *debugres,
                            const igraph_vector_t *st,
                            const igraph_vector_t *vtime,
                            const igraph_vector_t *vtimeidx,
                            const igraph_vector_t *etime,
                            const igraph_vector_t *etimeidx,
                            igraph_integer_t pno_of_events,
                            igraph_integer_t pmaxdegree) {

    long int no_of_nodes=igraph_vcount(graph);
    long int no_of_edges=igraph_ecount(graph);
    long int no_of_events=pno_of_events;
    long int maxdegree=pmaxdegree;

    igraph_vector_long_t degree;
    igraph_vector_char_t added;	/* is this edge already in the network? */

    igraph_matrix_t v_normfact, *normfact, v_notnull, *notnull;
    igraph_matrix_t ch;

    igraph_vector_long_t ntk;	/* # of type x vertices */
    igraph_matrix_t ntkk;	        /* # of connections between type x1, x2 vert. */

    igraph_vector_t *adjedges;

    long int timestep, i;
    long int nptr=0, eptr=0;
    long int nptr_save, eptr_save, eptr_new;

    IGRAPH_CHECK(igraph_vector_long_init(&degree, no_of_nodes));
    IGRAPH_FINALLY(&igraph_vector_long_destroy, &degree);

    IGRAPH_CHECK(igraph_vector_char_init(&added, no_of_edges));
    IGRAPH_FINALLY(igraph_vector_char_destroy, &added);

    IGRAPH_CHECK(igraph_vector_long_init(&ntk, maxdegree+1));
    IGRAPH_FINALLY(igraph_vector_long_destroy, &ntk);
    IGRAPH_MATRIX_INIT_FINALLY(&ntkk, maxdegree+1, maxdegree+1);
    IGRAPH_MATRIX_INIT_FINALLY(&ch, maxdegree+1, maxdegree+1);

    if (norm) {
        normfact=norm;
        IGRAPH_CHECK(igraph_matrix_resize(normfact, maxdegree+1, maxdegree+1));
        igraph_matrix_null(normfact);
    } else {
        normfact=&v_normfact;
        IGRAPH_MATRIX_INIT_FINALLY(normfact, maxdegree+1, maxdegree+1);
    }

    if (cites) {
        notnull=cites;
        IGRAPH_CHECK(igraph_matrix_resize(notnull, maxdegree+1, maxdegree+1));
        igraph_matrix_null(notnull);
    } else {
        notnull=&v_notnull;
        IGRAPH_MATRIX_INIT_FINALLY(notnull, maxdegree+1, maxdegree+1);
    }

    IGRAPH_CHECK(igraph_matrix_resize(kernel, maxdegree+1, maxdegree+1));
    igraph_matrix_null(kernel);
    if (sd) {
        IGRAPH_CHECK(igraph_matrix_resize(sd, maxdegree+1, maxdegree+1));
        igraph_matrix_null(sd);
    }

    for (timestep=0; timestep<no_of_events; timestep++) {

        IGRAPH_ALLOW_INTERRUPTION();

        /* Add the vertices in the first */
        nptr_save=nptr;
        while (nptr < no_of_nodes &&
                VECTOR(*vtime)[(long int)VECTOR(*vtimeidx)[nptr]]==timestep) {
            nptr++;
        }
        VECTOR(ntk)[0] += (nptr-nptr_save);

        /* Update ch accordingly, could be done later as well */
        if (VECTOR(ntk)[0] == nptr-nptr_save && nptr!=nptr_save) {
            if (nptr-nptr_save >= 2) {
                MATRIX(ch, 0, 0) = eptr;
            }
            for (i=1; i<maxdegree+1; i++) {
                if (NTKK(0,i) == (nptr-nptr_save)*VECTOR(ntk)[i]) {
                    MATRIX(ch, 0, i) = MATRIX(ch, i, 0) = eptr;
                }
            }
        }

        /* Estimate Akk */
        eptr_save=eptr;
        while (eptr < no_of_edges &&
                VECTOR(*etime)[(long int)VECTOR(*etimeidx)[eptr] ] == timestep) {
            long int edge=(long int) VECTOR(*etimeidx)[eptr];
            long int from=IGRAPH_FROM(graph, edge), to=IGRAPH_TO(graph, edge);
            long int xidx=VECTOR(degree)[from];
            long int yidx=VECTOR(degree)[to];
            double xk, oldakk;

            MATRIX(*notnull, xidx, yidx) += 1;
            MATRIX(*notnull, yidx, xidx) = MATRIX(*notnull, xidx, yidx);

            xk=VECTOR(*st)[timestep]/NTKK(xidx, yidx);
            oldakk=MATRIX(*kernel, xidx, yidx);
            MATRIX(*kernel, xidx, yidx) +=  (xk-oldakk)/MATRIX(*notnull, xidx, yidx);
            MATRIX(*kernel, yidx, xidx) = MATRIX(*kernel, xidx, yidx);
            if (sd) {
                MATRIX(*sd, xidx, yidx) += (xk-oldakk)*(xk-MATRIX(*kernel, xidx, yidx));
                MATRIX(*sd, yidx, xidx) = MATRIX(*sd, xidx, yidx);
            }
            /* TODO: debug */

            eptr++;
        }

        /* Update ntkk, ntk, ch, normfact, add the edges */
        eptr_new=eptr;
        eptr=eptr_save;
        while (eptr < no_of_edges &&
                VECTOR(*etime)[(long int) VECTOR(*etimeidx)[eptr] ] == timestep) {
            long int edge=(long int) VECTOR(*etimeidx)[eptr];
            long int from=IGRAPH_FROM(graph, edge);
            long int to=IGRAPH_TO(graph, edge);
            long int xidx=VECTOR(degree)[from];
            long int yidx=VECTOR(degree)[to];
            long int n;

            adjedges=igraph_lazy_inclist_get(inclist, (igraph_integer_t) from);
            n=igraph_vector_size(adjedges);
            for (i=0; i<n; i++) {
                long int edge=(long int) VECTOR(*adjedges)[i];
                if (VECTOR(added)[edge]) {
                    long int otherv=IGRAPH_OTHER(graph, edge, from); /* other than from */
                    long int deg=VECTOR(degree)[otherv];
                    MATRIX(ntkk, xidx, deg) -= 1;
                    MATRIX(ntkk, deg, xidx) = MATRIX(ntkk, xidx, deg);
                    if (NTKK(xidx, deg)==1) {
                        MATRIX(ch, deg, xidx) = eptr_new;
                        MATRIX(ch, xidx, deg) = MATRIX(ch, deg, xidx);
                    }
                    MATRIX(ntkk, xidx+1, deg) += 1;
                    MATRIX(ntkk, deg, xidx+1) = MATRIX(ntkk, xidx+1, deg);
                    if (NTKK(xidx+1, deg)==0) {
                        MATRIX(*normfact, xidx+1, deg) += eptr_new-MATRIX(ch, xidx+1, deg);
                        MATRIX(*normfact, deg, xidx+1) = MATRIX(*normfact, xidx+1, deg);
                    }
                }
            }
            adjedges=igraph_lazy_inclist_get(inclist, (igraph_integer_t) to);
            n=igraph_vector_size(adjedges);
            for (i=0; i<n; i++) {
                long int edge=(long int) VECTOR(*adjedges)[i];
                if (VECTOR(added)[edge]) {
                    long int otherv=IGRAPH_OTHER(graph, edge, to); /* other than to */
                    long int deg=VECTOR(degree)[otherv];
                    MATRIX(ntkk, yidx, deg) -= 1;
                    MATRIX(ntkk, deg, yidx) = MATRIX(ntkk, yidx, deg);
                    if (NTKK(yidx, deg)==1) {
                        MATRIX(ch, deg, yidx) = eptr_new;
                        MATRIX(ch, yidx, deg) = MATRIX(ch, deg, yidx);
                    }
                    MATRIX(ntkk, yidx+1, deg) += 1;
                    MATRIX(ntkk, deg, yidx+1) = MATRIX(ntkk, yidx+1, deg);
                    if (NTKK(yidx+1, deg)==0) {
                        MATRIX(*normfact, yidx+1, deg) += eptr_new-MATRIX(ch, yidx+1, deg);
                        MATRIX(*normfact, deg, yidx+1) = MATRIX(*normfact, yidx+1, deg);
                    }
                }
            }

            VECTOR(added)[edge]=1;

            MATRIX(ntkk, xidx+1, yidx+1) += 1;
            MATRIX(ntkk, yidx+1, xidx+1) = MATRIX(ntkk, xidx+1, yidx+1);
            if (NTKK(xidx+1, yidx+1)==0) {
                MATRIX(*normfact, xidx+1, yidx+1) = eptr_new-MATRIX(ch, xidx+1, yidx+1);
                MATRIX(*normfact, yidx+1, xidx+1) = MATRIX(*normfact, xidx+1, yidx+1);
            }

            for (i=0; i<maxdegree+1; i++) {
                long int before, after;
                before=(long int) NTKK(xidx,i);
                VECTOR(ntk)[xidx] -= 1;
                after=(long int) NTKK(xidx,i);
                VECTOR(ntk)[xidx] += 1;
                if (before > 0 && after==0) {
                    MATRIX(*normfact, xidx, i) += eptr_new-MATRIX(ch, xidx, i);
                    MATRIX(*normfact, i, xidx) = MATRIX(*normfact, xidx, i);
                }
            }
            VECTOR(ntk)[xidx]--;

            for (i=0; i<maxdegree+1; i++) {
                long int before, after;
                before=(long int) NTKK(yidx, i);
                VECTOR(ntk)[yidx] -= 1;
                after=(long int) NTKK(yidx, i);
                VECTOR(ntk)[yidx] += 1;
                if (before > 0 && after==0) {
                    MATRIX(*normfact, yidx, i) += eptr_new-MATRIX(ch, yidx, i);
                    MATRIX(*normfact, i, yidx) = MATRIX(*normfact, yidx, i);
                }
            }
            VECTOR(ntk)[yidx]--;

            for (i=0; i<maxdegree+1; i++) {
                long int before, after;
                before=(long int) NTKK(xidx+1, i);
                VECTOR(ntk)[xidx+1] += 1;
                after=(long int) NTKK(xidx+1, i);
                VECTOR(ntk)[xidx+1] -= 1;
                if (before==0 && after > 0) {
                    MATRIX(ch, xidx+1, i) = eptr_new;
                    MATRIX(ch, i, xidx+1) = MATRIX(ch, xidx+1, i);
                }
            }
            VECTOR(ntk)[xidx+1]++;

            for (i=0; i<maxdegree+1; i++) {
                long int before, after;
                before=(long int) NTKK(yidx+1, i);
                VECTOR(ntk)[yidx+1] += 1;
                after=(long int) NTKK(yidx+1, i);
                VECTOR(ntk)[yidx+1] -= 1;
                if (before == 0 && after == 0) {
                    MATRIX(ch, yidx+1, i) = eptr_new;
                    MATRIX(ch, i, yidx+1) = MATRIX(ch, yidx+1, i);
                }
            }
            VECTOR(ntk)[yidx+1]++;

            VECTOR(degree)[from]++;
            VECTOR(degree)[to]++;

            eptr++;
        }

    }

    for (i=0; i<maxdegree+1; i++) {
        igraph_real_t oldakk;
        long int j;
        for (j=0; j<=i; j++) {
            if (NTKK(i, j) != 0) {
                MATRIX(*normfact, i, j) += (eptr-MATRIX(ch, i, j));
                MATRIX(*normfact, j, i) = MATRIX(*normfact, i, j);
            }
            if (MATRIX(*normfact, i, j)==0) {
                MATRIX(*kernel, i, j)=MATRIX(*kernel, j, i)=0;
                MATRIX(*normfact, i, j)=MATRIX(*normfact, j, i)=1;
            }
            oldakk=MATRIX(*kernel, i, j);
            MATRIX(*kernel, i, j) *= MATRIX(*notnull, i, j)/MATRIX(*normfact, i, j);
            MATRIX(*kernel, j, i) = MATRIX(*kernel, i, j);
            if (sd) {
                MATRIX(*sd, i, j) += oldakk * oldakk * MATRIX(*notnull, i, j) *
                                     (1-MATRIX(*notnull, i, j)/MATRIX(*normfact, i, j));
                MATRIX(*sd, i, j) = sqrt(MATRIX(*sd, i, j)/(MATRIX(*normfact, i, j)-1));
                MATRIX(*sd, j, i) = MATRIX(*sd, i, j);
            }
        }
    }

    if (!cites) {
        igraph_matrix_destroy(notnull);
        IGRAPH_FINALLY_CLEAN(1);
    }
    if (!norm) {
        igraph_matrix_destroy(normfact);
        IGRAPH_FINALLY_CLEAN(1);
    }

    igraph_matrix_destroy(&ch);
    igraph_matrix_destroy(&ntkk);
    igraph_vector_long_destroy(&ntk);
    igraph_vector_char_destroy(&added);
    igraph_vector_long_destroy(&degree);
    IGRAPH_FINALLY_CLEAN(5);

    return 0;
}
示例#6
0
int igraph_revolver_mes_p_p(const igraph_t *graph,
                            igraph_lazy_inclist_t *inclist,
                            igraph_matrix_t *kernel,
                            igraph_matrix_t *sd,
                            igraph_matrix_t *norm,
                            igraph_matrix_t *cites,
                            const igraph_matrix_t *debug,
                            igraph_vector_ptr_t *debugres,
                            const igraph_vector_t *st,
                            const igraph_vector_t *vtime,
                            const igraph_vector_t *vtimeidx,
                            const igraph_vector_t *etime,
                            const igraph_vector_t *etimeidx,
                            igraph_integer_t pno_of_events,
                            const igraph_vector_t *authors,
                            const igraph_vector_t *eventsizes,
                            igraph_integer_t pmaxpapers) {

    long int no_of_nodes=igraph_vcount(graph);
    long int no_of_edges=igraph_ecount(graph);
    long int no_of_events=pno_of_events;
    long int maxpapers=pmaxpapers;

    igraph_vector_long_t papers;
    igraph_vector_char_t added;

    igraph_matrix_t v_normfact, *normfact, v_notnull, *notnull;
    igraph_matrix_t ch;

    igraph_vector_long_t ntk;
    igraph_matrix_t ntkk;

    igraph_vector_t *adjedges;

    long int timestep, i;
    long int nptr=0, eptr=0, aptr=0;
    long int nptr_save, eptr_save, eptr_new;

    IGRAPH_CHECK(igraph_vector_long_init(&papers, no_of_nodes));
    IGRAPH_FINALLY(&igraph_vector_long_destroy, &papers);

    IGRAPH_CHECK(igraph_vector_char_init(&added, no_of_edges));
    IGRAPH_FINALLY(igraph_vector_char_destroy, &added);

    IGRAPH_CHECK(igraph_vector_long_init(&ntk, maxpapers+1));
    IGRAPH_FINALLY(igraph_vector_long_destroy, &ntk);
    IGRAPH_MATRIX_INIT_FINALLY(&ntkk, maxpapers+1, maxpapers+1);
    IGRAPH_MATRIX_INIT_FINALLY(&ch, maxpapers+1, maxpapers+1);

    if (norm) {
        normfact=norm;
        IGRAPH_CHECK(igraph_matrix_resize(normfact, maxpapers+1, maxpapers+1));
        igraph_matrix_null(normfact);
    } else {
        normfact=&v_normfact;
        IGRAPH_MATRIX_INIT_FINALLY(normfact, maxpapers+1, maxpapers+1);
    }

    if (cites) {
        notnull=cites;
        IGRAPH_CHECK(igraph_matrix_resize(notnull, maxpapers+1, maxpapers+1));
        igraph_matrix_null(notnull);
    } else {
        notnull=&v_notnull;
        IGRAPH_MATRIX_INIT_FINALLY(notnull, maxpapers+1, maxpapers+1);
    }

    IGRAPH_CHECK(igraph_matrix_resize(kernel, maxpapers+1, maxpapers+1));
    igraph_matrix_null(kernel);
    if (sd) {
        IGRAPH_CHECK(igraph_matrix_resize(sd, maxpapers+1, maxpapers+1));
        igraph_matrix_null(sd);
    }

    for (timestep=0; timestep<no_of_events; timestep++) {

        IGRAPH_ALLOW_INTERRUPTION();

        nptr_save=nptr;
        while (nptr < no_of_nodes &&
                VECTOR(*vtime)[(long int)VECTOR(*vtimeidx)[nptr]]==timestep) {
            nptr++;
        }
        /* If it is a new author then she has no papers yet */
        VECTOR(ntk)[0] += (nptr-nptr_save);

        /* Update ch accordingly, could be done later as well */
        if (VECTOR(ntk)[0] == nptr-nptr_save && nptr!=nptr_save) {
            if (nptr-nptr_save >= 2) {
                MATRIX(ch, 0, 0) = eptr;
            }
            for (i=1; i<maxpapers+1; i++) {
                if (NTKK(0,i) == (nptr-nptr_save)*VECTOR(ntk)[i]) {
                    MATRIX(ch, 0, i) = MATRIX(ch, i, 0) = eptr;
                }
            }
        }

        /*     print_ntkk(&ntkk, &ntk); */

        /* Estimate Akk */
        eptr_save=eptr;
        while (eptr < no_of_edges &&
                VECTOR(*etime)[(long int)VECTOR(*etimeidx)[eptr] ] == timestep) {
            long int edge=(long int) VECTOR(*etimeidx)[eptr];
            long int from=IGRAPH_FROM(graph, edge), to=IGRAPH_TO(graph, edge);
            long int xidx=VECTOR(papers)[from];
            long int yidx=VECTOR(papers)[to];
            double xk, oldakk;

            MATRIX(*notnull, xidx, yidx) += 1;
            MATRIX(*notnull, yidx, xidx) = MATRIX(*notnull, xidx, yidx);

            xk=VECTOR(*st)[timestep]/NTKK(xidx, yidx);
            oldakk=MATRIX(*kernel, xidx, yidx);
            MATRIX(*kernel, xidx, yidx) +=  (xk-oldakk)/MATRIX(*notnull, xidx, yidx);
            MATRIX(*kernel, yidx, xidx) = MATRIX(*kernel, xidx, yidx);
            if (sd) {
                MATRIX(*sd, xidx, yidx) += (xk-oldakk)*(xk-MATRIX(*kernel, xidx, yidx));
                MATRIX(*sd, yidx, xidx) = MATRIX(*sd, xidx, yidx);
            }
            /* TODO: debug */

            eptr++;
        }

        /* update ntkk, the new papers change the type of their authors */
        eptr_new=eptr;
        for (i=aptr; i<aptr+VECTOR(*eventsizes)[timestep]; i++) {
            long int aut=(long int) VECTOR(*authors)[i];
            long int pap=VECTOR(papers)[aut];
            long int j, n;

            adjedges=igraph_lazy_inclist_get(inclist, (igraph_integer_t) aut);
            n=igraph_vector_size(adjedges);
            for (j=0; j<n; j++) {
                long int edge=(long int) VECTOR(*adjedges)[j];
                if (VECTOR(added)[edge]) {
                    long int otherv=IGRAPH_OTHER(graph, edge, aut);
                    long int otherpap=VECTOR(papers)[otherv];
                    MATRIX(ntkk, pap, otherpap) -= 1;
                    MATRIX(ntkk, otherpap, pap) = MATRIX(ntkk, pap, otherpap);
                    if (NTKK(pap, otherpap)==1) {
                        MATRIX(ch, pap, otherpap) = eptr_new;
                        MATRIX(ch, otherpap, pap) = MATRIX(ch, pap, otherpap);
                    }
                    MATRIX(ntkk, pap+1, otherpap) += 1;
                    MATRIX(ntkk, otherpap, pap+1) = MATRIX(ntkk, pap+1, otherpap);
                    if (NTKK(pap+1, otherpap)==0) {
                        MATRIX(*normfact, pap+1, otherpap) +=
                            eptr_new-MATRIX(ch, pap+1, otherpap);
                        MATRIX(*normfact, otherpap, pap+1) =
                            MATRIX(*normfact, pap+1, otherpap);
                    }
                }
            }

            /* update ntk too */
            for (j=0; j<maxpapers+1; j++) {
                long int before, after;
                before=(long int) NTKK(pap, j);
                VECTOR(ntk)[pap]-=1;
                after=(long int) NTKK(pap, j);
                VECTOR(ntk)[pap]+=1;
                if (before > 0 && after==0) {
                    MATRIX(*normfact, pap, j) += eptr_new-MATRIX(ch, pap, j);
                    MATRIX(*normfact, j, pap) = MATRIX(*normfact, pap, j);
                }
            }
            VECTOR(ntk)[pap]-=1;

            for (j=0; j<maxpapers+1; j++) {
                long int before, after;
                before=(long int) NTKK(pap+1, j);
                VECTOR(ntk)[pap+1] += 1;
                after=(long int) NTKK(pap+1, j);
                VECTOR(ntk)[pap+1] -= 1;
                if (before == 0 && after > 0) {
                    MATRIX(ch, pap+1, j) = eptr_new;
                    MATRIX(ch, j, pap+1) = MATRIX(ch, pap+1, j);
                }
            }
            VECTOR(ntk)[pap+1]+=1;

            VECTOR(papers)[aut] += 1;
        }
        aptr += VECTOR(*eventsizes)[timestep];

        /* For every new edge, we lose one connection possibility, also add the edges*/
        eptr=eptr_save;
        while (eptr < no_of_edges &&
                VECTOR(*etime)[(long int) VECTOR(*etimeidx)[eptr] ] == timestep) {
            long int edge=(long int) VECTOR(*etimeidx)[eptr];
            long int from=IGRAPH_FROM(graph, edge), to=IGRAPH_TO(graph, edge);
            long int xidx=VECTOR(papers)[from];
            long int yidx=VECTOR(papers)[to];

            MATRIX(ntkk, xidx, yidx) += 1;
            MATRIX(ntkk, yidx, xidx) = MATRIX(ntkk, xidx, yidx);
            if (NTKK(xidx, yidx)==0) {
                MATRIX(*normfact, xidx, yidx) += eptr_new-MATRIX(ch, xidx, yidx);
                MATRIX(*normfact, yidx, xidx) = MATRIX(*normfact, xidx, yidx);
            }

            VECTOR(added)[edge]=1;
            eptr++;
        }
    }

    for (i=0; i<maxpapers+1; i++) {
        igraph_real_t oldakk;
        long int j;
        for (j=0; j<=i; j++) {
            if (NTKK(i, j) != 0) {
                MATRIX(*normfact, i, j) += (eptr-MATRIX(ch, i, j));
                MATRIX(*normfact, j, i) = MATRIX(*normfact, i, j);
            }
            if (MATRIX(*normfact, i, j)==0) {
                MATRIX(*kernel, i, j)=MATRIX(*kernel, j, i)=0;
                MATRIX(*normfact, i, j)=MATRIX(*normfact, j, i)=1;
            }
            oldakk=MATRIX(*kernel, i, j);
            MATRIX(*kernel, i, j) *= MATRIX(*notnull, i, j)/MATRIX(*normfact, i, j);
            MATRIX(*kernel, j, i) = MATRIX(*kernel, i, j);
            if (sd) {
                MATRIX(*sd, i, j) += oldakk * oldakk * MATRIX(*notnull, i, j) *
                                     (1-MATRIX(*notnull, i, j)/MATRIX(*normfact, i, j));
                MATRIX(*sd, i, j) = sqrt(MATRIX(*sd, i, j)/(MATRIX(*normfact, i, j)-1));
                MATRIX(*sd, j, i) = MATRIX(*sd, i, j);
            }
        }
    }

    if (!cites) {
        igraph_matrix_destroy(notnull);
        IGRAPH_FINALLY_CLEAN(1);
    }
    if (!norm) {
        igraph_matrix_destroy(normfact);
        IGRAPH_FINALLY_CLEAN(1);
    }

    igraph_matrix_destroy(&ch);
    igraph_matrix_destroy(&ntkk);
    igraph_vector_long_destroy(&ntk);
    igraph_vector_char_destroy(&added);
    igraph_vector_long_destroy(&papers);
    IGRAPH_FINALLY_CLEAN(5);

    return 0;
}
示例#7
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;
}
示例#8
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;
}
示例#9
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;
}
示例#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;
}
示例#11
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;
}