• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

ne_per_lib.c

00001 /*===========================================================================
00002  NetEvo Foundation Library
00003  Copyright (C) 2009, 2010 Thomas E. Gorochowski <tgorochowski@me.com>
00004  Bristol Centre for Complexity Sciences, University of Bristol, Bristol, UK
00005  ---------------------------------------------------------------------------- 
00006  NetEvo is a computing framework designed to allow researchers to investigate 
00007  evolutionary aspects of dynamical complex networks. By providing tools to 
00008  easily integrate each of these factors in a coherent way, it is hoped a 
00009  greater understanding can be gained of key attributes and features displayed 
00010  by complex systems.
00011  
00012  NetEvo is open-source software released under the Open Source Initiative 
00013  (OSI) approved Non-Profit Open Software License ("Non-Profit OSL") 3.0. 
00014  Detailed information about this licence can be found in the COPYING file 
00015  included as part of the source distribution.
00016  
00017  This library is distributed in the hope that it will be useful, but
00018  WITHOUT ANY WARRANTY; without even the implied warranty of
00019  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00020  ============================================================================*/
00021 
00022 
00023 #include "ne_per_lib.h"
00024 #include <math.h>
00025 #include <igraph.h>
00026 #include <gsl/gsl_eigen.h>
00027 #include <gsl/gsl_vector.h>
00028 #include <gsl/gsl_sort_vector.h>
00029 
00030 
00031 ne_per_t * ne_per_top_eigenratio_alloc (void)
00032 {
00033    /* No parameters */
00034    ne_per_t *per;
00035    
00036    if ((per = (ne_per_t *)malloc(sizeof(ne_per_t))) == NULL) {
00037       ne_error("ne_per_top_eigenratio_alloc: Could not allocate memory.");
00038       return NULL;
00039    }
00040    
00041    /* Configure the strucutre */
00042    per->type = NE_PER_TOP;
00043    per->fn = &ne_per_top_eigenratio;
00044    per->params = NULL;
00045    
00046    return per;
00047 }
00048 
00049 
00050 double ne_per_top_eigenratio (ne_sys_t *sys, ne_dyn_vec_t *dyn, ne_real_t *params)
00051 {
00052    double r = 0.0;
00053    gsl_matrix* gLocal = NULL;
00054    gsl_eigen_symm_workspace* w = NULL;
00055    gsl_vector* v = NULL;
00056    
00057    /* Generate a GSL Laplacian Matrix as easier to work with */
00058    gLocal = ne_sys_laplacian_to_gsl_matrix_alloc(sys);
00059    
00060    /* Setup the eigensystem space and calculate the ordered eigenvalues */
00061    w = gsl_eigen_symm_alloc(gLocal->size1);
00062    v = gsl_vector_alloc(gLocal->size1);
00063    gsl_eigen_symm(gLocal, v, w);
00064    gsl_sort_vector(v);
00065    
00066    /* Calculate the eigen ratio lambda_N/lambda_2 */
00067    r = (double)gsl_vector_get(v, gLocal->size1-1)/(double)gsl_vector_get(v, 1);
00068    
00069    gsl_eigen_symm_free(w);
00070    gsl_vector_free(v);
00071    gsl_matrix_free(gLocal);
00072    
00073    return r;
00074 }
00075 
00076 
00077 ne_per_t * ne_per_dyn_orderparam_alloc (ne_real_t delta)
00078 {
00079    /* 0 - delta */
00080    ne_real_t *newParams;
00081    ne_per_t *per;
00082    
00083    if ((per = (ne_per_t *)malloc(sizeof(ne_per_t))) == NULL) {
00084       ne_error("ne_per_top_eigenratio_alloc: Could not allocate memory.");
00085       return NULL;
00086    }
00087    
00088    if ((newParams = (ne_real_t *)malloc(sizeof(ne_real_t))) == NULL) {
00089       ne_error("ne_per_top_eigenratio_alloc: Could not allocate memory.");
00090       free(per);
00091       return NULL;
00092    }
00093    newParams[0] = delta;
00094    
00095    /* Configure the parameter strucutre */
00096    per->type = NE_PER_DYN;
00097    per->fn = &ne_per_dyn_orderparam;
00098    per->params = newParams;
00099    
00100    return per;
00101 }
00102 
00103 
00104 double ne_per_dyn_orderparam (ne_sys_t *sys, ne_dyn_vec_t *dyn, ne_real_t *params)
00105 {
00106    /* 0 - delta (acceptable synchronisation error) */
00107    
00108    return ne_per_dyn_orderparam_calc_mu(sys, dyn, dyn->curSize-1, params[0]);
00109 }
00110 
00111 
00112 double ne_per_dyn_orderparam_integral (ne_sys_t *sys, ne_dyn_vec_t *dyn, ne_real_t *params)
00113 {
00114    /* 0 - delta (acceptable synchronisation error) */
00115    
00116    int t;
00117    double y1, y2, tDiff, curSec, outSum;
00118    
00119    outSum = 0;
00120    
00121    for ( t=0; t<dyn->curSize; t++ ) {
00122       
00123       y1 = ne_per_dyn_orderparam_calc_mu(sys, dyn, t, params[0]);
00124       y2 = ne_per_dyn_orderparam_calc_mu(sys, dyn, t+1, params[0]);
00125       
00126       tDiff = dyn->data[t+1][0] - dyn->data[t][0];
00127       
00128       if ( y1 > y2 ) 
00129          curSec = (y1 * tDiff) - (((y1 - y2) * tDiff) / 2.0);
00130       else
00131          curSec = (y2 * tDiff) - (((y2 - y1) * tDiff) / 2.0);
00132       
00133       outSum += curSec;
00134    }
00135    
00136    return outSum;
00137 }
00138 
00139 
00140 double ne_per_dyn_orderparam_calc_mu (ne_sys_t *sys, ne_dyn_vec_t *dyn, int t, double delta)
00141 {
00142    int i, j, e, N;
00143    double mu, d;
00144    
00145    mu = 0;
00146    N  = igraph_vcount(sys->graph);
00147    
00148    for ( i=0; i<N; i++ ) {
00149       for ( j=0; j<N; j++ ) {
00150          
00151          if ( i != j ) {
00152             
00153             /* Calculate the euclidean distance between the two nodes */
00154             d = 0;
00155             for ( e=0; e<sys->nodeStates; e++ ) {
00156                
00157                if ( isnan(dyn->data[t][(i*sys->nodeStates)+e+1]) || 
00158                    isnan(dyn->data[t][(j*sys->nodeStates)+e+1]) ) {
00159                   return 1.0;
00160                }
00161                
00162                d += pow(dyn->data[t][(i*sys->nodeStates)+e+1] - dyn->data[t][(j*sys->nodeStates)+e+1], 2.0);
00163             }
00164             d = sqrt(d);
00165             
00166             /* Calculate the heavyside function with delta error range */
00167             if ( d - delta >= 0 )
00168                mu += 100;
00169             else
00170                mu += 0;
00171          }
00172       }
00173    }
00174    
00175    /* Normalise */
00176    mu = mu * (1.0 / (N * (N - 1)));
00177    
00178    return mu;
00179 }
00180 
00181 
00182 ne_per_t * ne_per_dyn_bounded_alloc (ne_real_t tEnd)
00183 {
00184    /* 0 - end period length to calculate bound using */
00185    ne_real_t *newParams;
00186    ne_per_t *per;
00187    
00188    if ((per = (ne_per_t *)malloc(sizeof(ne_per_t))) == NULL) {
00189       ne_error("ne_per_top_eigenratio_alloc: Could not allocate memory.");
00190       return NULL;
00191    }
00192    
00193    if ((newParams = (ne_real_t *)malloc(sizeof(ne_real_t))) == NULL) {
00194       ne_error("ne_per_top_eigenratio_alloc: Could not allocate memory.");
00195       return NULL;
00196    }
00197    newParams[0] = tEnd;
00198    
00199    /* Configure the parameter strucutre */
00200    per->type = NE_PER_DYN;
00201    per->fn = &ne_per_dyn_bounded;
00202    per->params = newParams;
00203    
00204    return per;
00205 }
00206 
00207 
00208 double ne_per_dyn_bounded (ne_sys_t *sys, ne_dyn_vec_t *dyn, ne_real_t *params)
00209 {
00210    long int t, i, j, e;
00211    double d = 0, curBound = -1, tStart, indStart;
00212    
00213    curBound = 0.0;
00214    
00215    /* Find the start time in the dynamics output */
00216    tStart = dyn->data[dyn->curSize-1][0] - params[0];
00217    
00218    /* Search for the index at which this time corrisponds */
00219    indStart = -1;
00220    for (i=0; i<dyn->curSize; i++) {
00221       
00222       if (dyn->data[i][0] > tStart) {
00223          indStart = i-1;
00224          break;
00225       }
00226    }
00227    
00228    /* Check that an index was found */
00229    if (indStart == -1) {
00230       
00231       /* Error occured */
00232       ne_error("ne_per_dyn_bounded - Could not find start index.\n");
00233       return NE_HUGE_NUMBER;
00234    }
00235    
00236    /* For each time point calculate the largest bound */
00237    for (t=indStart; t<dyn->curSize; t++) {
00238       
00239       
00240       /* For each pair of vertices (i, j) where (i != j) */
00241       for (i=0; i<igraph_vcount(sys->graph); i++) {
00242          for (j=0; j<igraph_vcount(sys->graph); j++) {
00243             
00244             /* Check that a distance will exist */
00245             if (i != j) {
00246                
00247                /* Calculate the euclidean distance between the two nodes */
00248                d = 0;
00249                for (e=0; e<sys->nodeStates; e++) {
00250                   
00251                   if (isnan(dyn->data[t][(i*sys->nodeStates)+e+1]) || 
00252                       isnan(dyn->data[t][(j*sys->nodeStates)+e+1]) ) {
00253                      return NE_HUGE_NUMBER;
00254                   }
00255                   
00256                   d += pow(dyn->data[t][(i*sys->nodeStates)+e+1] - dyn->data[t][(j*sys->nodeStates)+e+1], 2.0);
00257                }
00258                d = sqrt(d);
00259                
00260                if (d > curBound) {
00261                   curBound = d;
00262                }
00263             }
00264          }
00265       }
00266    }
00267    
00268    return curBound;
00269 }

Generated on Thu Aug 26 2010 11:04:24 for NetEvo by  doxygen 1.7.1