# wiki

name: GraphModification
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Graph Modifications ==

  There's a couple of options which change the internally kept graph.

  === Removing Properties ===
  [[T(Complexity|'''O(1)''')]]

  Vertex and edge properties can be removed from the graph with the options "{{{--remove-vertex-property}}}" and "{{{--remove-edge-property}}}", which take the name of the property to be removed as parameter.

  === Vertex and Edge Indexes ===
  [[T(Complexity|'''O(1)''')]]

  Vertices and Edges are identified internally by indexes. Those can be inserted as properties with the options "{{{--insert-vertex-index-property}}}" and "{{{--insert-edge-index-property}}}", which take as argument the name by which the property will be called.

  === Creating and modifying properties ===
  [[T(Complexity|'''O(V)''' or '''O(E)''')]]

  New properties can be created and old ones modified (replaced) the the following options:

  {{{
  --edit-vertex-property=PROPERTY|EXPRESSION                                   edit the selected vertex property
  --edit-edge-property=PROPERTY|EXPRESSION                                     edit the selected edge property
  }}}

  The PROPERTY parameter takes the name of the property which will be created or modified. The EXPRESSION parameter is a python expression which will be evaluated to a "double" value, and assigned to the property. The variables available are the same as with [wiki:GraphFiltering#GenericFiltering Generic Filtering] described above.

  Example:
  {{{
  $ graph-tool --load example.xml --edit-edge-property="sqrt_weight|weight()**0.5" --average-edge-property="weight|-" --average-edge-property="sqrt_weight|-" 
  # average edge property (weight):
  2.550000        1.163373

  # average edge property (sqrt_weight):
  1.299736        0.328003
  }}}

  == Parallel edges removal ==
  [[T(Complexity|'''O(E log(<k>))''')]]

  A multigraph can be converted into a simple graph by labeling the parallel edges with an edge property and then filtering them out. The edges can be labeled with the following option:

  {{{
  --label-parallel-edges=PROPERTY                                     label parallel edges to PROPERTY
  }}}

  This will create (or replace) a property map with name given by PROPERTY, which will have integer values. The parallel edges will be labeled increasingly starting from zero, in a non-specified order. The graph can thus be reduced to a simple graph by filtering out edges with values > 0. See GraphFiltering above.


name: MixingPatterns
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Mixing Patterns ==

  === Assortativity Coefficient ===
  [[Complexity(Complexity: <b>O(E)</b>)]]

  The assortativity coefficient tells in a concise fashion how vertices of different types are preferentially connected amongst themselves, and is defined by

  [[Equation(\[r = \frac{\sum_i e_{ii} - \sum_i a_i b_i}{1-\sum_i a_i b_i}\])]] where [[Equation(\[a_i=\sum_je_{ij}\])]] and [[Equation(\[b_j=\sum_ie_{ij}\])]], and [[Equation($e_{ij}$)]] is the fraction of edges from a vertex of type [[Equation($i$)]] to a vertex of type [[Equation($j$)]].

  It is obtained by the option `--assortativity-coefficient`", which takes two arguments: the property used to identify different types and a file name, separated by "|". The property may be any scalar vertex property in the graph, as well a "`in-degree`", "`out-degree`" and "`total-degree`".

  Example:

  {{{
  $ graph-tool --load example.xml --assortativity-coefficient="total-degree|-"
  assortativity coefficient:      0.492063        0.252221
  }}}

  The first value is the assortativity coefficient, and the second is the variance, obtained with the [http://en.wikipedia.org/wiki/Resampling_%28statistics%29#Jackknife jackknife method].

  === Scalar Assortativity Coefficient ===
  [[Complexity(Complexity: <b>O(E)</b>)]]

  If the types of vertices are scalar properties, the following coefficient may be more useful:

  [[Equation(\[r = \frac{\sum_{xy} xy(e_{xy} - a_x b_y)}{\sigma_a\sigma_b}\])]] where [[Equation(\[a_x=\sum_ye_{xy}\])]] and [[Equation(\[b_y=\sum_xe_{xy}\])]], and [[Equation($e_{xy}$)]] is the fraction of edges from a vertex of type [[Equation($x$)]] to a vertex of type [[Equation($y$)]]. It can be obtained with the "`--scalar-assortativity-coefficient`" option, which takes the same parameters as the [[ref(Assortativity Coefficient)]]. Example:

  {{{
  $ graph-tool --load example.xml --scalar-assortativity-coefficient="total-degree|-"
  scalar assortativity coefficient:       -0.241202       0.292476
  }}}

  The first value is the scalar assortativity coefficient, and the second is the variance, obtained with the [http://en.wikipedia.org/wiki/Resampling_%28statistics%29#Jackknife jackknife method].


name: GraphClustering
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Clustering ==

  === Local Clustering ===
  [[Complexity(Complexity: <b>O(V&lt;k&gt;<sup>3</sup>)</b>)]]

  The local (vertex) clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(1)}_v = \frac{2N_c}{k(k-1)}\])]], where [[Equation($k$)]] is the number of neighbours of the vertex, and [[Equation($N_c$)]] is the number of edges between the neighbours of the vertex. This value can be calculated and set to a vertex property with the command "`--set-local-clustering-to-property`", which takes the property name as parameter. Example:

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --vertex-histogram="clustering|clust"
  $ cat clust
  0.0     4
  0.333333333333  3
  }}}

  It is possible to obtain the clustering coefficient for the whole graph by using the `--average-vertex-property` option :

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --average-vertex-property="clustering|-"
  average vertex property:        0.142857        0.062348
  }}}

  The first value is the clustering coefficient, and the second is the standard deviation.

  === Global Clustering ===
  [[Complexity(Complexity: <b>O(V&lt;k&gt;<sup>3</sup>)</b>)]]

  The global clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(2)} = \frac{3N_t}{N_c}\])]], where [[Equation($N_t$)]] is the number of triangles in the graph and [[Equation($N_c$)]] is the number of connected triplets. It can be obtained with the "`--global-clustering-coefficient`" option, which takes a file name as a parameter, or "`-`" for terminal output. Example:

  {{{
  $ graph-tool --load example.xml --global-clustering-coefficient=- 
  global clustering coefficient:  0.230769        0.030769
  }}}

  The first value is the global clustering coefficient, and the second value is the variance using the [http://en.wikipedia.org/wiki/Resampling_(statistics)#Jackknife jackknife method] on the vertices.


name: GraphLayout
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Layout ==

  graph-tool includes also a couple of layout algorithms, which saves vertex position coordinates into a vertex property, which later can be used by [http://www.graphviz.org/ graphviz] to draw the graph.

  === Spring-Block ===

  This implements the [http://www.boost.org/libs/graph/doc/fruchterman_reingold.html Fruchterman-Reingold] spring-block layout algorithm. It is available through the "`--compute-spring-block-layout`" option, which takes two arguments: the maximum number of iterations and an optional seed value (which will be taken from the computer clock if not supplied). The positions will be recorded in the "pos" property.

  === Gursoy-Atun ===

  This implements the [http://www.boost.org/libs/graph/doc/gursoy_atun_layout.html Gursoy-Atun] layout algorithm, which can provide for an interesting alternative to force-directed layouts. It is called with the "`--compute-gursoy-atun-layout`" option, and takes the same parameters as the spring-block layout above.


name: GraphReciprocity
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Reciprocity ==

  {{{
      --reciprocity=FILE                                                  get the edge reciprocity
      --minimum-spanning-tree=[WEIGHT|]PROPERTY                           mark the minimum spanning tree edges in PROPERTY
      --line-graph=FILE[|FORMAT]             
  }}}


name: RandomGraphGeneration
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  = Random graph generation =

  graph-tool supports generation of random directed graphs with arbitrary degree distributions, based on the [http://arxiv.org/abs/cond-mat/0007235/ configurational model], with the addition of arbitrary degree correlations. The graph is generated with the "`--correlated-configurational-model`" option, which can take several parameters separated by commas. See the end of this page for a [[ref(Parameter Summary)]].

  == Tutorial & examples ==

  === Uncorrelated graphs ===

  It will be described here how to generate uncorrelated directed graphs. For undirected graphs, all that is necessary is to generate a directed graph and then operate on it after calling the "`--undirected`" option. For more details see the [[ref(Generating undirected graphs)]] section.

  ==== Independent and equal in-out distributions ====

  Let's start with a simple uncorrelated graph with Poisson degree distribution, to get our feet wet. There are only two required parameters to generate a graph: The number of vertices and the joint degree distribution. These are specified through the "`N`" and "`inv_pjk_ceil`" options. The "`inv_pjk_ceil`" option takes as parameter, in fact, the __inverse of the cumulative degree distribution__, given a probability "`p`" and an extra random variable "`r`", both in the [0,1[ range. Its syntax is a pair in the form "`(j,k)`", corresponding to the sampled (j,k) pair. Any valid [http://www.python.org python] expression is allowed to generate the pair. If the desired sampling function is too elaborate to be written in a single expression, it can be specified in a file. See [[ref(More elaborate distributions)]] for more details and an example. There are a couple of predefined function inverses for convenience: "`inv_poisson(p,m)`", "`inv_exponential(p,m)`" and "`inv_power_law(p,b)`", where "`m`" is the average of the distribution and "`b`" is the modulus of the power-law exponent.

  So, our example is a degree distribution where both the in- and out-degrees are distributed independently according to a Poisson:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(inv_poisson(p,5),inv_poisson(r,5))\",progress" \
  --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 99744 of 99744 (100%)
  }}}


  The "`progress`" option is used to show the progress of the graph generation on the terminal. The generated graph is then saved in "`graph.xml.bz2`". We can get some measurements out of it to see if things make sense or not:

  {{{
  $ graph-tool --load graph.xml.bz2 --vertex-histogram="in-degree|in-degree-histogram" \
  --vertex-histogram="out-degree|out-degree-histogram" --vertex-histogram="total-degree|total-degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        99744
  scalar assortativity coefficient:       -0.000422       0.003175
  }}}

  Below are plotted the degree distributions and degree correlation obtained with the above command.

  [[Image(degree-poisson.png, nolink)]] [[Image(degree-uncorrelation.png, nolink)]]

  So, things seem to make sense so far.  Let's try with something a little bit less trivial...

  ==== Independent but different in-out distributions ====

  Suppose you want different in- and out-degree distributions, like one exponential, and the other a Poisson:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(inv_exponential(p,5),inv_poisson(r,5))\",progress" \
  --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 99731 of 99731 (100%)
  }}}

  Getting the same measurements...

  {{{
  $ graph-tool --load graph.xml.bz2 --vertex-histogram="in-degree|in-degree-histogram" \
  --vertex-histogram="out-degree|out-degree-histogram" --vertex-histogram="total-degree|total-degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        99731
  scalar assortativity coefficient:       0.003840        0.003188
  }}}

  Below are plotted the degree distributions and degree correlation obtained with the above command.

  [[Image(degree-exp-poisson.png, nolink)]] [[Image(degree-uncorrelation2.png, nolink)]]

  That wasn't really all that complicated. See the following section for something a little bit more interesting.

  ==== More elaborate distributions ====

  Suppose we want some other expression for the degree distribution that we want to specify ourselves, i.e., not a Poisson, an exponential or a power-law. If the expression is very complicated, perhaps the best approach is to use [[ref(Rejection sampling)]]. But you can still sample it "the normal way", if you can obtain the inverse of the cumulative distribution. As a simple example of this, suppose our in-degree distribution is composed of two Poisson distributions with different averages, and the out-degree distribution is an exponential. Our in-degree distribution can be written as such:

  [[Equation(\[p(j)=\frac{e^{-m_1}m_1^j+e^{-m_2}m_2^j}{2j!}\])]]. The cumulative distribution is then [[Equation(\[P(j)=\frac{\Gamma(j+1,m_1) + \Gamma(j+1,m_2)}{2j!}\])]].

  The inverse of the cumulative distribution is the solution of [[Equation(\[\frac{\Gamma(j+1,m_1) + \Gamma(j+1,m_2)}{2j!}-P=0\])]] for [[Equation($j$)]]. We can use "`fsolve`" function from the [http://www.scipy.org scipy] package (which is included automatically if available) to write it as such:
  {{{
  fsolve(lambda j: (gammaincc(j,m1)+gammaincc(j,m2))/2-p, (m1+m2)/2.0)
  }}}

  We can generate the graph with the following command:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000, \
  inv_pjk_ceil=\"(fsolve(lambda j: (gammaincc(j,4)+gammaincc(j,20))/2-p,(12)/2.0)-0.5+1e-11, \
                  inv_exponential(r,12))\",progress" \
  --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 241062 of 241062 (100%)
  }}}

  The "`-0.5+1e-11`" term added above is just to make up for a rounding effect. We can get the same measurements as before,

  {{{
  $ graph-tool --load graph.xml.bz2 --vertex-histogram="in-degree|in-degree-histogram" \
  --vertex-histogram="out-degree|out-degree-histogram" --vertex-histogram="total-degree|total-degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        241062
  scalar assortativity coefficient:       -0.000600       0.002038
  }}}

  [[Image(degree-2poissons.png, nolink)]] [[Image(degree-uncorrelation3.png, nolink)]]

  ==== Combined in- and out-degree distributions ====

  Generating combined, i.e. not independent, in- and out-degree distributions is a little bit more complicated. Here it is described a relatively simple example. Suppose we want to generate the following joint degree distribution, which is the combination of two independent Poisson distributions,

  [[Equation(\[ p(j,k) = \frac{1}{2}\frac{e^{-m_1}m_1^j}{j!}\frac{e^{-m_1}m_1^k}{k!} + \frac{1}{2}\frac{e^{-m_2}m_2^j}{j!}\frac{e^{-m_2}m_2^k}{k!}\])]].

  The cumulative degree distribution is the following,

  [[Equation(\[ P(j,k) = \frac{1}{2}\frac{\Gamma(j+1,m_1)\Gamma(k+1,m_1)}{j!k!} + \frac{1}{2}\frac{\Gamma(j+1,m_2)\Gamma(k+1,m_2)}{j!k!} \])]], which is already complicated to find the inverse (which will be some sort of curve in the jk-plane).

  So in order to sample from this distribution, it will be necessary to write something more complicated than an expression which can be squeezed in the "`inv_pjk_ceil`" option as a single expression. For this reason, it is possible to define the sampling function in a file first, and then tell graph-tool to load it. Here's the definition of "`inv_pjk_ceil`" which will sample from the above distribution, defined in a file called "`joint_poissons.py`":

  {{{
  #!python
  from random import *

  def inv_pjk_ceil(p,r):
      if random() > 0.5:
          return (int(round(inv_poisson(p,4))),int(round(inv_poisson(r,4))))
      else:
          return (int(round(inv_poisson(p,20))),int(round(inv_poisson(r,20))))
  }}}

  This can be any valid python program that defines the function "`inv_pjk_ceil(p,r)`". This way it is possible to implement just about any sampling routine. With this file in place, the graph can be generated with the following command

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"file:joint_poissons.py\",progress" \
  --save graph4.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 240456 of 240456 (100%)
  }}}

  When the "`inv_pjk_ceil`" parameter begins with "file:", it instructs the program to load it from the specified file. We can then check if everything is correct:
  {{{
  $ graph-tool --load graph4.xml.bz2 --combined-vertex-histogram="in-degree|out-degree|combined-degree-histogram" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-" 
  number of vertices:     20000
  number of edges:        240456
  scalar assortativity coefficient:       0.000398        0.002032
  }}}

  Below are plotted the theoretical and generated joint degree histograms,

  [[Image(joint-poissons-theoretical.png, nolink)]] [[Image(joint-poissons-generated.png, nolink)]]

  Not so bad...

  ==== Generating undirected graphs ====

  Suppose that in the end you just want some undirected graph to work with, and don't want to bother with the in- and out-degrees separately. If you have your desired degree distribution P(k), you just have to generate the graph with a "`inv_pjk_ceil`" as "`(r*inv_p(p), (1-r)*inv_p(p))`", where "`inv_p(p)`" is the inverse of the cumulative degree distribution. This will generate vertices for which the total degree is sampled from P(k) but the in- and out-degrees are uniformly distributed within the constraints of P(k).

  -------

  === Correlated graphs ===

  graph-tool can also generate arbitrarily correlated graphs, as an extension to the [http://arxiv.org/abs/cond-mat/0007235/ configurational model]. 

  {{{
  #!html
  <div class="note">
  }}}
  ==== Important note ====
  Degree correlations are dependent on the degree distribution. That means that not all degree correlations are always possible, given a specific degree distribution. Therefore you must make sure that the degree correlation you're asking the program to generate is actually possible with the given distribution. If it's not, the obtained correlation is obviously not going to match what you asked. And also it must be taken int account that for some types of correlations, even if the correlation itself is possible, it may be required to make averages over several graphs, or very large graphs, in order to obtain the expected correlation more precisely.
  {{{
  #!html
  </div>
  }}}

  ==== Undirected graphs ====

  Let's take the simplest example, when all that is wanted in the end is an undirected graph with some degree correlation. In this case, when all that matters is the total degree of the vertices when it comes to degree correlations, the parameter "`undirected`" should be passed to the "`--correlated-configurational-model`" option.

  Since the degree distribution dictates what kind of correlations are possible, let's try here an homogeneous degree distribution [[Equation(\[P(k)=\frac{1}{100}[k<100]\])]], where all degrees up to 100 are equaly probable. That should give us some room to work with the degree correlation.

  ===== Assortative degree mixing =====

  So, here we'll generate a degree correlation so that vertices of a given type are connected to other vertices of similar type. We must define exactly what correlation we want, and we do this with the correlation function P(j',k'|j,k) which gives the probability that a random edge leaving a vertex with degrees j and k will connect to a vertex with degrees j' and k'. Here we'll define the following,

  [[Equation(\[P(j',k'|j,k)=\frac{e^{-(j+k)}(j+k)^{j'+k'}}{(j'+k')!}\])]], which is a Poisson distribution with average j+k, so that on average vertices will connect with other vertices of the same degree, leading to perfect assortative graph.

  The correlation is passed to the program through the "`inv_corr_ceil`" option, which, similarly to the "`inv_pjk_ceil`" option, it is the inverse of the cumulative of the function defined above. The sintax is also the same as the "`inv_pjk_ceil`" option. We can then generate the graph described above with the following command:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(r*p*100,(1-r)*p*100)\", \
  inv_corr_ceil=\"(r*inv_poisson(p,j+k),(1-r)*inv_poisson(p,j+k))\",undirected,progress" \
  --save graph.xml.bz2 
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 498225 of 498225 (100%)
  }}}

  And now we can check what was generated:

  {{{
  $ graph-tool --load graph.xml.bz2 --undirected --vertex-histogram="total-degree|degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        498225
  scalar assortativity coefficient:       0.926743        0.005064
  }}}

  The assortativity coefficient looks good. Here's the degree histogram and nearest neighbour correlation

  [[Image(uniform-degree-histogram.png, nolink)]] [[Image(degree-correlation-linear.png, nolink)]]

  Looks like it makes sense...

  ===== Disassortative degree mixing =====

  Let's try the other way, i.e., vertices of a given type connecting with the ones which are the most different. Let's define it the following way:

  [[Equation(\[P(j',k'|j,k)=\frac{e^{-(101-(j+k))}(101-(j+k))^{j'+k'}}{(j'+k')!}\])]], which, like above, is a Poisson distribution, but the average degree this time is 101-(j+k), which means that, for instance, on average vertices of degree 100 will connect to vertices of degree 1, and vice versa. So let's try it:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(r*p*100,(1-r)*p*100)\", \
  inv_corr_ceil=\"(r*inv_poisson(p,101-(j+k)),(1-r)*inv_poisson(p,101-(j+k)))\",undirected,progress" \
  --save graph.xml.bz2 
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 503958 of 503958 (100%)
  }}}

  Checking the graph...

  {{{
  $ graph-tool --load graph.xml.bz2 --undirected --vertex-histogram="total-degree|degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        503958
  scalar assortativity coefficient:       -0.284408       0.005967
  }}}

  The assortativity coefficient is negative, which makes sense, but otherwise its absolute value is a little lower than expected with the specified correlation. Below are the degree histogram and neighbour correlation.

  [[Image(uniform-degree-histogram2.png, nolink)]] [[Image(degree-correlation-not-linear.png, nolink)]]

  Oops. What's wrong with the neighbour correlation? Wasn't it supposed to be linear? Well if you remember the [[ref(Important note)]] above, you'll realize that in this case the correlation we asked for is simply not possible. For instance, if all the vertices with degree 100 were connected mostly with vertices of degree 1, it would be necessary to have 100 times more vertices of degree 1 than of degree 100. Since the degree distribution is homogeneous, this is not possible. Let's try again, but this time with a more convenient degree distribution:

  [[Equation(\[P(k)=\frac{2}{100^2}(100-k)[k<100]\])]]

  Generating the graph:
  {{{
  $ graph-tool --correlated-configurational-model="N=20000,\
  inv_pjk_ceil=\"(r*(199-sqrt(199**2 -4*100**2*0.99*p))/2,(1-r)*(199-sqrt(199**2 -4*100**2*0.99*p))/2)\",\
  inv_corr_ceil=\"(r*inv_poisson(p,101-(j+k)),(1-r)*inv_poisson(p,101-(j+k)))\",undirected,progress" \
  --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 330393 of 330393 (100%)
  }}}

  Checking it:
  {{{
  $ graph-tool --load graph.xml.bz2 --undirected --vertex-histogram="total-degree|degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        330393
  scalar assortativity coefficient:       -0.928880       0.005233
  }}}

  The assortativity coefficient is telling a good story. Let's check the rest:

  [[Image(decreasing-degree-histogram.png, nolink)]] [[Image(degree-correlation-linear2.png, nolink)]]

  Looks better.

  --------

  ==== Directed graphs ====

  When dealing with directed graphs, the degree correlations can be more elaborate, since in- and out-degrees can not only be correlated amongst themselves, but also with each other. Here it is shown an example where the in- and out-degrees are homogeneously distributed in the [0,100] range, the in->out correlation is "disassortative", the out->in correlation is "assortative", and everything else is uncorrelated:

  [[Equation(\[P(j',k'|j,k)=\frac{e^{-k}k^{j'}}{j'!} \frac{e^{-(100-j)}(100-j)^{k'}}{k'!}\])]].

  This can be generated with
  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(p*100,r*100)\", \
  inv_corr_ceil=\"(inv_poisson(p,k),inv_poisson(r,100-j+0.001))\",progress"  --save graph.xml.bz2 
  adding vertices: 20000 of 20000 (100%) 
  fixing average degrees: 0 
  adding edges: 1002047 of 1002047 (100%)
  }}}

  The "`0.001`" above is just a little ''ad hoc'' "correction" for a problem when calculating the inverse of a Poisson with average zero. We can then, as usual, measure the correlations:

  {{{
  $ graph-tool --load graph.xml.bz2 --vertex-histogram="in-degree|in-degree-histogram" \
  --vertex-histogram="out-degree|out-degree-histogram"  \
  --average-nearest-neighbours-correlation="in-degree|in-degree|in-degree-correlation"  \
  --average-nearest-neighbours-correlation="out-degree|out-degree|out-degree-correlation" \
  --average-nearest-neighbours-correlation="in-degree|out-degree|in-out-degree-correlation"  \
  --average-nearest-neighbours-correlation="out-degree|in-degree|out-in-degree-correlation" \
  --number-of-vertices=- --number-of-edges=-
  }}}

  Below are the degree distributions and correlation plots.

  [[Image(degree-hist-directed.png, nolink)]] [[Image(correlation-directed.png, nolink)]]

  The deviations above from the straight line are due to fluctuations of the chosen correlation distribution.

  -------

  == Rejection sampling ==

  If the desired degree distribution or correlation is some very complicated function for which the inverse cannot be easily computed, it is still possible to sample from it using [http://en.wikipedia.org/wiki/Rejection_sampling rejection sampling], which uses an envelope distribution, from which it is easy to obtain a sample. In total, graph-tool needs four parameters: the inverse of the envelope distribution, the envelope distribution g(x), the target distribution f(x), and the upper boundary M for the ratio f(x)/g(x).

  As an illustration, it will be shown here how to generate an uncorrelated undirected graph with a degree distribution which is obtained with rejection sampling. The degree distribution we want to obtain is 

  [[Equation(\[P(k)=\frac{sin\left(\frac{2\pi k}{100}\right)+1}{101} [k\leq 100]\])]].

  For that, we'll use an homogeneous envelope distribution: [[Equation(\[E(k)=\frac{1}{101}[k\leq 100]\])]]. In this case we have that M=2.

  The inverse of envelope distribution, the envelope distribution, the target distribution and the ratio M must be set with the "`inv_pjk_ceil`" (hence the name), "`pjk_ceil`", "`pjk`" and "`pjk_m`" options, respectively. In our case, we can generate the graph with the following command:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(p*r*100,p*(1-r)*100)\",\
  pjk_ceil=\"step(100-(j+k))/(101**2)\", \
  pjk=\"(sin(2*pi*(j+k)/100)+1)/(101**2)\", \
  pjk_m=2,undirected,progress" --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 342247 of 342247 (100%)
  }}}

  We can then obtain the degree histogram and correlation,

  {{{
  $ graph-tool --load graph.xml.bz2 --undirected --vertex-histogram="total-degree|total-degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- 
  number of vertices:     20000
  number of edges:        342247
  }}}

  And the obtained graph looks like the following:

  [[Image(degree-hist-sine.png, nolink)]] [[Image(degree-correlation-sine.png, nolink)]]

  Degree correlations can also be obtained in an analogous fashion, with the "`inv_corr_ceil`", "`corr_ceil`", "`corr`" and "`corr_m`" options.

  --------

  == Parameter Summary ==
   '''`N`'''::
     The number of vertices in the network. This paramenter is mandatory.
   '''pjk'''::
     The joint degree distribution P(j,k). This parameter is only used when doing [[ref(Rejection sampling)]].
   '''pjk_ceil'''::
     This is the ceil function for the '''pjk''' parameter. This parameter is only used when doing [[ref(Rejection sampling)]].
   '''pjk_m'''::
     This is the maximum ratio '''pjk_ceil/pjk'''. Defaults to 1.0. This parameter is only used when doing [[ref(Rejection sampling)]].
   '''inv_pjk_ceil''':: 
     This is the inverse of the cumulative ceil joint degree distribution (or the distribution itself when not doing [[ref(Rejection sampling)]]). This is the parameter which will be more frequently used when setting the joint degree distribution, and is a required parameter. It should be defined as a [http://www.python.org python] expression, defining a tuple of size 2 for the sampled (j,k) degrees. The parameters are two random variables `p` and `r`, uniformly distributed in the range [0,1[.  Some predefined functions which can be used include "`inv_poisson(p,m)`" for an inverse Poisson function with average "`m`", "`inv_exponential(p,m)`" for an inverse exponential distribution with average "`m`", and "`inv_power_law(p,b)`" for an inverse power-law distribution with exponent "`-b`". See above for various examples of how to use this parameter.
   '''corr'''::
     This is the correlation distribution, P(j',k'|j,k), which is the probability that a randomly chosen edge leaving a (j,k) vertex will be connected to a (j',k') vertex. This parameter is only used when doing [[ref(Rejection sampling)]].
    '''corr_ceil'''::
     This is the ceil function for the '''corr''' parameter. This parameter is only used when doing [[ref(Rejection sampling)]].
   '''corr_m'''::
     This is the maximum ratio '''corr_ceil/corr'''. Defaults to 1.0. This parameter is only used when doing [[ref(Rejection sampling)]].
   '''inv_corr_ceil'''::
     This is the inverse of the cumulative ceil correlation distribution (or the distribution itself if not doing [[ref(Rejection sampling)]]). The available variables are `j` and `k`, for the in- and out-degree of the origin vertex, and two random variables `p` and `r`. This defaults to the uncorrelated case "`ceil=pjk(j,k)`". See above for examples.
   '''undirected'''::
     This option controls how edge targets are chosen in respect to their in- and out-degrees. If an edge is supposed to connect to a vertex with (j,k), but no such vertex exists, this options says it should connect randomly to one of the vertices with the closest total degree j+k.
   '''directed'''::
     This option controls how edge targets are chosen in respect to their in and out degrees. If an edge is supposed to connect to a vertex with (j,k), but no such vertex exists, this options says it should connect randomly to one of the vertices which is closest in the jk-plane. This is the default.
   '''progress'''::
     This option displays useful progress information in the terminal.
   '''seed'''::
     This options sets the seed value for the random number generator. It is taken from the computer clock if unspecified.


name: GraphHistory
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Graph History ==

  Graphs sometimes have dynamical properties related to them. Sometimes they grow or change somehow during time. It is often interesting to see how its various properties also change with time. In graph tool this is possible through the usage of properties, filtering, and the "`--history`" option. The history option takes three parameters, which function just like a "`for` loop": the initial statement, a condition to be checked every iteration, and a step statement. The variables defined and modified in the parameters of this option are available to be used by the other options that follow it. Using graph properties and filtering, snapshots of the graph can be generated. It all becomes clearer with an example. Consider the following graph, called "`example-time.xml`":

  {{{
  #!html
  <div style="float: right;">
  }}}
  {{{
  #!graphviz
  digraph G {
  start="12";
  1->2 [label = "  1  ", len=0.6];
  2->3 [label = "  2  ", len=0.6];
  3->7 [label = "  3  ", len=0.6];
  4->5 [label = "  4  ", len=0.6];
  5->6 [label = "  5  ", len=0.6];
  5->3 [label = "  6  ", len=0.6];
  6->7 [label = "  7  ", len=0.6];
  7->2 [label = "  8  ", len=0.6];
  }
  }}}
  {{{
  #!html
  </div>
  }}}


  {{{
  #!xml
  <?xml version="1.0" encoding="UTF-8"?>
  <graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://graphml.graphdrawing\.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
    <key id="d1" for="edge" attr.name="time" attr.type="int"/>
    <graph id="G" edgedefault="directed">
      <node id="n0"/>
      <node id="n1"/>
      <node id="n2"/>
      <node id="n3"/>
      <node id="n4"/>
      <node id="n5"/>
      <node id="n6"/>
      <edge id="e0" source="n0" target="n1">
        <data key="d1">1</data>
      </edge>
      <edge id="e1" source="n1" target="n2">
        <data key="d1">2</data>
      </edge>
      <edge id="e2" source="n2" target="n6">
        <data key="d1">3</data>
      </edge>
      <edge id="e3" source="n3" target="n4">
        <data key="d1">4</data>
      </edge>
      <edge id="e4" source="n4" target="n5">
        <data key="d1">5</data>
      </edge>
      <edge id="e5" source="n4" target="n2">
        <data key="d1">6</data>
      </edge>
      <edge id="e6" source="n5" target="n6">
        <data key="d1">7</data>
      </edge>
      <edge id="e7" source="n6" target="n1">
        <data key="d1">8</data>
      </edge>
    </graph>
  </graphml>
  }}}

  There's an edge property called time which goes from 1 to 8. So in order to calculate, for instance, the number of edges and the degree distribution over time, one could do the following:

  {{{
  $ graph-tool --load example-time.xml --history="t=1|t<9|t+=1" --edge-range-filter="time|1 %t" \
  --vertex-histogram="total-degree|deg-history" --number-of-edges="num-edges-history"
  $ cat num-edges-history 
  0       1
  1       2
  2       3
  3       4
  4       5
  5       6
  6       7
  7       8
  $ cat deg-history
  0       0.0     5
  0       1.0     2
  1       0.0     4
  1       1.0     2
  1       2.0     1
  2       0.0     3
  2       1.0     2
  2       2.0     2
  3       0.0     1
  3       1.0     4
  3       2.0     2
  4       1.0     4
  4       2.0     3
  5       1.0     4
  5       2.0     1
  5       3.0     2
  6       1.0     2
  6       2.0     3
  6       3.0     2
  7       1.0     2
  7       2.0     1
  7       3.0     4
  }}}

  The variables defined in the "`--history`" option are reachable in the options that follow it by prefixing them with "`%`". Each saved file contains the history of the measured property, with each line prefixed by the history iteration number (or with the variable "`prefix`" defined in the history specification, as shown below). In the case above, "`num-edges-history`" contains the number of edges in each iteration and "`deg-history`" contains the degree distribution with each iteration. It should be clear with the above example that this feature is reasonably general, since combined with generic filtering, it is possible to obtain quite arbitrary "histories" of the graph. The syntax of the history specification is any valid [http://www.python.org python] statement.

  ==== Specifying the history prefix ====

  Using the history counter as a prefix is sometimes not the most confortable way of labeling points in history. Luckily, this can easily be changed by defining the "`prefix`" variable, as shown in the example below:

  {{{
  $ graph-tool --load example-time.xml --history="t=1; prefix=t+10 | t<9 | t+=1; prefix=t+10" \
   --edge-range-filter="time|1 %t" --number-of-edges="num-edges-history"
  $ cat num-edges-history 
  11      1
  12      2
  13      3
  14      4
  15      5
  16      6
  17      7
  18      8
  }}}

  The prefix can be entirely suppressed by setting it to an empty string: "`prefix=""`". This can be useful when each history step is being saved to a different file.

  === Resuming history computations ===

  For large graphs history computations can take quite a long time. During this time things in general can go wrong, such as a power outage. For this reason graph-tool supports resuming of history computations, where partial results already contained in the history files are automatically skipped and not recalculated. Therefore, if you change the history rules or the graph, you must remember to delete the old history files or to save to new ones, otherwise they'll still contain old information.

  Before data is saved to the history files, partial history results are kept in temporary files, which get periodically copied over to the final files. The frequency of this update can be changed with the "`--history-rate`" option, which takes a number as a parameter followed by "`s`","`m`","`h`" or "`d`" to indicate seconds, minutes, hours or days, respectively. The default value is "`1h`".


name: GraphToolDownload
author: count0
ipnr: 201.81.194.239
text:
  = graph-tool Download =

  graph-tool is released under the [http://www.gnu.org/copyleft/gpl.html GPL]. For installation instructions, see the included INSTALL file.

  [[T(Note|Warning: Memory requirements for compilation|graph-tool requires large amounts of RAM (~1 GB) during compilation, because it uses lots of [http://en.wikipedia.org/wiki/Template_metaprogramming template metaprogramming]. The supported compiler, [http://gcc.gnu.org/ GCC], is still not very well optimized for this, which means that even though the program is relatively small (the compiled binary, as of version 0.9, is only around 10 MB in size), it will still use up lots of RAM during compilation, specially if optimizations are used (and you do want to use them). See, for instance, GCC bugs [http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29433 29433] and [http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12850 12850]. For this reason, pre-compiled binaries are also provided, so that if you don't have that much RAM, you can still use the program (but you'll still need all the [[ref(Requirements)]] mentioned below).)]]

  == Requirements ==

  You'll need the following in order to build and use graph-tool:

   * [http://gcc.gnu.org/ GCC] 4.1 or above
   * The [http://www.boost.org/ boost] libraries.
   * [http://www.python.org Python] 2.4 or above
   * The [http://expat.sourceforge.net/ expat] library

  graph-tool was tested only on [http://www.gnu.org GNU/Linux] systems, but should also be usable on other systems where the above requirements are available.

  === Optional packages ===
  The following packages, if available, will be used automatically by graph-tool, but are not required:
   * [http://www.scipy.org/ SciPy], for useful mathematical functions
   * [http://psyco.sourceforge.net/ Psyco], for improved performace of python code

  == Stable Releases ==

  [[T(Note|Try the SVN version first|Please consider first downloading the [wiki:GraphToolDownload#LatestDevelopmentSourceCode latest development source code] below, as it will usually be in a usable state, and will contain most bugfixes and new features)]]

  === Latest stable release - 0.9 ===
  0.9 is the first public release.

  ==== Tar source package ====
   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-0.9.tar.bz2 graph-tool-0.9.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-0.9.tar.bz2 graph-tool-0.9.tar.bz2]

  '''Note:''' After compilation, "`make install`" must be run before graph-tool can be used. If you just want to run the program without installing it, you must make sure that the "`libgraph_tool.so`" file (available after compilation in "`src/graph/.libs`") is in the same directory as the "`grap-tool`" executable (or, alternatively, somewhere in the python module path).

  ==== Pre-compiled binaries (i686 only) ====

  This package includes the "`graph-tool`" python executable and the "`libgraph_tool.so`" library, which should be either in the same directory as "`graph-tool`", or in the python module path, for graph-tool to work properly.

   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-0.9-precompiled-i686.tar.bz2 graph-tool-0.9-precompiled-i686.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-0.9-precompiled-i686.tar.bz2 graph-tool-0.9-precompiled-i686.tar.bz2]

  === Previous stable release - none ===

  ----

  == Latest Development Source Code ==

  We use [http://subversion.tigris.org/ Subversion] for source revision control and code sharing.

  The Subversion repository URL for the graph-tool project is at:

    http://svn.forked.de/graph-tool/

  The latest revision can be checked out with the following command:

  {{{
  svn co http://svn.forked.de/graph-tool/trunk graph-tool
  }}}

  Or with encryption:

  {{{
  svn co https://svn.forked.de/graph-tool/trunk graph-tool
  }}}

  For further instructions on how to use Subversion, see [http://svnbook.red-bean.com/book.html The Subversion Book]


name: GraphToolDownload
author: count0
ipnr: 201.81.194.239
text:
  = graph-tool Download =

  graph-tool is released under the [http://www.gnu.org/copyleft/gpl.html GPL]. For installation instructions, see the included INSTALL file.

  [[T(Note|Warning: Memory requirements for compilation|graph-tool requires large amounts of RAM (~1 GB) during compilation, because it uses lots of [http://en.wikipedia.org/wiki/Template_metaprogramming template metaprogramming]. The supported compiler, [http://gcc.gnu.org/ GCC], is still not very well optimized for this, which means that even though the program is relatively small (the compiled binary, as of version 0.9, is only around 10 MB in size), it will still use up lots of RAM during compilation, specially if optimizations are used (and you do want to use them). See, for instance, GCC bugs [http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29433 29433] and [http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12850 12850]. For this reason, pre-compiled binaries are also provided, so that if you don't have that much RAM, you can still use the program (but you'll still need all the [[ref(Requirements)]] mentioned below).)]]

  == Requirements ==

  You'll need the following in order to build and use graph-tool:

   * [http://gcc.gnu.org/ GCC] 4.1 or above
   * The [http://www.boost.org/ boost] libraries.
   * [http://www.python.org Python] 2.4 or above
   * The [http://expat.sourceforge.net/ expat] library

  graph-tool was tested only on [http://www.gnu.org GNU/Linux] systems, but should also be usable on other systems where the above requirements are available.

  === Optional packages ===
  The following packages, if available, will be used automatically by graph-tool, but are not required:
   * [http://www.scipy.org/ SciPy], for useful mathematical functions
   * [http://psyco.sourceforge.net/ Psyco], for improved performace of python code

  == Stable Releases ==

  [[T(Note|Try the SVN version first|Please consider first downloading the [wiki:GraphToolDownload#LatestDevelopmentSourceCode latest development source code] below, as it will usually be in an usable state, and will contain most bugfixes and new features)]]

  === Latest stable release - 0.9 ===
  0.9 is the first public release.

  ==== Tar source package ====
   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-0.9.tar.bz2 graph-tool-0.9.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-0.9.tar.bz2 graph-tool-0.9.tar.bz2]

  '''Note:''' After compilation, "`make install`" must be run before graph-tool can be used. If you just want to run the program without installing it, you must make sure that the "`libgraph_tool.so`" file (available after compilation in "`src/graph/.libs`") is in the same directory as the "`grap-tool`" executable (or, alternatively, somewhere in the python module path).

  ==== Pre-compiled binaries (i686 only) ====

  This package includes the "`graph-tool`" python executable and the "`libgraph_tool.so`" library, which should be either in the same directory as "`graph-tool`", or in the python module path, for graph-tool to work properly.

   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-0.9-precompiled-i686.tar.bz2 graph-tool-0.9-precompiled-i686.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-0.9-precompiled-i686.tar.bz2 graph-tool-0.9-precompiled-i686.tar.bz2]

  === Previous stable release - none ===

  ----

  == Latest Development Source Code ==

  We use [http://subversion.tigris.org/ Subversion] for source revision control and code sharing.

  The Subversion repository URL for the graph-tool project is at:

    http://svn.forked.de/graph-tool/

  The latest revision can be checked out with the following command:

  {{{
  svn co http://svn.forked.de/graph-tool/trunk graph-tool
  }}}

  Or with encryption:

  {{{
  svn co https://svn.forked.de/graph-tool/trunk graph-tool
  }}}

  For further instructions on how to use Subversion, see [http://svnbook.red-bean.com/book.html The Subversion Book]


name: GraphToolDownload
author: count0
ipnr: 201.81.194.239
text:
  = graph-tool Download =

  graph-tool is released under the [http://www.gnu.org/copyleft/gpl.html GPL]. For installation instructions, see the included INSTALL file.

  [[T(Note|Warning: Memory requirements for compilation|graph-tool requires large amounts of RAM (~1 GB) during compilation, because it uses lots of [http://en.wikipedia.org/wiki/Template_metaprogramming template metaprogramming]. The supported compiler, [http://gcc.gnu.org/ GCC], is still not very well optimized for this, which means that even though the program is relatively small (the compiled binary, as of version 0.9, is only around 10 MB in size), it will still use up lots of RAM during compilation, specially if optimizations are used (and you do want to use them). See, for instance, GCC bugs [http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29433 29433] and [http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12850 12850]. For this reason, pre-compiled binaries are also provided, so that if you don't have that much RAM, you can still use the program (but you'll still need all the [wiki:GraphToolDownload#Requirements requirements] below).)]]

  == Requirements ==

  You'll need the following in order to build and use graph-tool:

   * [http://gcc.gnu.org/ GCC] 4.1 or above
   * The [http://www.boost.org/ boost] libraries.
   * [http://www.python.org Python] 2.4 or above
   * The [http://expat.sourceforge.net/ expat] library

  graph-tool was tested only on [http://www.gnu.org GNU/Linux] systems, but should also be usable on other systems where the above requirements are available.

  === Optional packages ===
  The following packages, if available, will be used automatically by graph-tool, but are not required:
   * [http://www.scipy.org/ SciPy], for useful mathematical functions
   * [http://psyco.sourceforge.net/ Psyco], for improved performace of python code

  == Stable Releases ==

  [[T(Note|Try the SVN version first|Please consider first downloading the [wiki:GraphToolDownload#LatestDevelopmentSourceCode latest development source code] below, as it will usually be in an usable state, and will contain most bugfixes and new features)]]

  === Latest stable release - 0.9 ===
  0.9 is the first public release.

  ==== Tar source package ====
   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-0.9.tar.bz2 graph-tool-0.9.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-0.9.tar.bz2 graph-tool-0.9.tar.bz2]

  '''Note:''' After compilation, "`make install`" must be run before graph-tool can be used. If you just want to run the program without installing it, you must make sure that the "`libgraph_tool.so`" file (available after compilation in "`src/graph/.libs`") is in the same directory as the "`grap-tool`" executable (or, alternatively, somewhere in the python module path).

  ==== Pre-compiled binaries (i686 only) ====

  This package includes the "`graph-tool`" python executable and the "`libgraph_tool.so`" library, which should be either in the same directory as "`graph-tool`", or in the python module path, for graph-tool to work properly.

   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-0.9-precompiled-i686.tar.bz2 graph-tool-0.9-precompiled-i686.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-0.9-precompiled-i686.tar.bz2 graph-tool-0.9-precompiled-i686.tar.bz2]

  === Previous stable release - none ===

  ----

  == Latest Development Source Code ==

  We use [http://subversion.tigris.org/ Subversion] for source revision control and code sharing.

  The Subversion repository URL for the graph-tool project is at:

    http://svn.forked.de/graph-tool/

  The latest revision can be checked out with the following command:

  {{{
  svn co http://svn.forked.de/graph-tool/trunk graph-tool
  }}}

  Or with encryption:

  {{{
  svn co https://svn.forked.de/graph-tool/trunk graph-tool
  }}}

  For further instructions on how to use Subversion, see [http://svnbook.red-bean.com/book.html The Subversion Book]


name: DocToc
author: count0
ipnr: 201.81.194.239
text:
  [[TOC(GraphToolGuide,BasicStatistics,GraphFiltering,GraphModification,GraphCorrelations,MixingPatterns,GraphClustering,GraphLayout,GraphReciprocity,RandomGraphGeneration,GraphHistory)]]


name: GraphCorrelations
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Correlations ==

  === Combined Vertex Correlation ===
  [[T(Complexity|'''O(V)''')]]

  Option summary:
  {{{
  --average-combined-vertex-correlation=DEGREE1|DEGREE2|FILE
                                      get the average of DEGREE2 in function of
                                      DEGREE1. Scalar properties are also
                                      accepted as DEGREE1 or DEGREE2
  }}}


  === Vertex Correlation ===
  [[T(Complexity|'''O(E)''')]]

  Option summary:
  {{{
  --vertex-correlation-histogram=DEGREE1|DEGREE2[|WEIGHT]|FILE
                                      get the degree correlation histogram.
                                      Scalar properties are also accepted in
                                      place of DEGREE. An optional edge weight
                                      property can be passed by WEIGHT
  --average-nearest-neighbours-correlation=ORIGIN-DEGREE|DEGREE[|WEIGHT]|FILE
                                      get the average nearest neighbours
                                      correlation. An optional edge weight
                                      property can be passed by WEIGHT
  }}}

  The vertex correlation histogram is a bidimensional histogram defined as

  [[Equation(\[C(k,k')=\sum_{u,v}A_{uv}W_{uv}[k_u=k][k_v=k']\])]], where [[Equation($\mathbf{A}$)]] is the adjacency matrix, and [[Equation($\mathbf{W}$)]] is an optional weight matrix. It is obtainable with the "{{{--vertex-correlation-histogram}}}" option, which takes three or four parameters separated by "|": First degree type ([[Equation($k_u$)]]), second degree type ([[Equation($k_v$)]]), an optional weight property, and a file name. The degree types can be `in-degree`, `out-degree` and `total-degree`. It can also be the name of any scalar vertex property available.

  Example:

  {{{
  $ graph-tool --load example.xml --vertex-correlation="in-degree|out-degree|deg-corr"
  $ cat deg-corr
  0.0     1.0     1
  0.0     2.0     1
  1.0     1.0     3
  2.0     1.0     3
  }}}

  It is also possible to obtain the correlation in an alternative fashion, which a lot of times is more convenient, which is the average nearest neighbours degree, given by

  [[Equation(\[ \bar{k}(k)=\frac{\sum_{u,v}A_{uv}W_{uv}k_v[k_u=k]}{\sum_{u,v}A_{uv}[k_u=k]}\])]].

  It is obtainable with the "`--average-nearest-neighbours-correlation`" option, which takes three or four parameters separated by "|": degree type of the origin vertex, degree type of the neighbours, the optional weight property, and a file name. Origin and neighbour degree type can be "`in-degree`", "`out-degree`" and "`total-degree`", as well as the name of any scalar vertex property available.

  Example:

  {{{
  $ graph-tool --load example.xml --average-nearest-neighbours-correlation="total-degree|in-degree|deg-corr"
  $ cat deg-corr
  1.0     1.5     0.5
  2.0     2.0     0.0
  3.0     1.8     0.2
  }}}

  The third column above is the standard deviation of the average in the second column.

  === Edge Correlation ===
  [[T(Complexity|'''O(E)''')]]

  Option summary:
  {{{
  --edge-vertex-correlation-histogram=DEGREE1|EDGE-PROP|DEGREE2|FILE
                                                             get the source degree vs. edge scalar vs. target degree
                                                             correlation histogram. Scalar properties are also accepted in
                                                             place of DEGREE-TYPE
  }}}


  When edges have scalar properties, it is possible to generate a 3-dimensional correlation histogram defined as:

  [[Equation(\[ P(k,m,k')=\sum_{e}[k_{s(e)}=k][k_{t(e)}=k'][p(e)=m]}\])]], where [[Equation($e$)]] are the edges of the graph, [[Equation(\[s(e)\])]] and [[Equation(\[t(e)\])]] are the source and target vertex of edge [[Equation($e$)]], and [[Equation(\[p(e)\])]] is some property of the edge.

  This can be obtained with the "`--edge-vertex-correlation-histogram`" option which takes four arguments separated by "|": Source degree type, edge property and target degree type. The source and target degree types can be "`in-degree`", "`out-degree`" and "`total-degree`", as well as the name of any scalar vertex property available.

  Example:
  {{{
  $ graph-tool --load example.xml --edge-vertex-correlation-histogram="in-degree|weight|out-degree|edge-corr"
  $ cat edge-corr
  0.0     0.2     2.0     1
  0.0     1.2     1.0     1
  1.0     2.0     1.0     1
  1.0     5.5     1.0     1
  1.0     10.1    1.0     1
  2.0     0.1     1.0     1
  2.0     0.5     1.0     1
  2.0     0.8     1.0     1
  }}}


name: GraphCorrelations
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Correlations ==

  === Combined Vertex Correlation ===
  [[T(Complexity|'''O(V)''')]]

  Option summary:
  {{{
  --average-combined-vertex-correlation=DEGREE1|DEGREE2|FILE
                                      get the average of DEGREE2 in function of
                                      DEGREE1. Scalar properties are also
                                      accepted as DEGREE1 or DEGREE2
  }}}

  The average combined vertex correlation is defined as

  [[Equation(\[\left<k_2\right>(k_1)=\frac{\sum_{v}{k_2}_v[{k_1}_v=k_1]}{\sum_{v}[{k_1}_v=k_1]}\])]], where [[Equation($k_1$)]] is the first degree type and [[Equation($k_2$)]] is the second. It is obtainable with the "{{{--average-combined-vertex-correlation}}}" option, which takes three parameters separated by "|": First degree type ([[Equation($k_1$)]]), second degree type ([[Equation($k_2$)]]), and a file name. The degree types can be `in-degree`, `out-degree` and `total-degree`. It can also be the name of any scalar vertex property available.

  Example:

  {{{
  $ ./graph-tool --load example.xml --average-combined-vertex-correlation="in-degree|out-degree|-"
  # average combined vertex correlation (in-degree, out-degree):
  0.0     1.0     0.0
  1.0     1.5     0.5
  2.0     1.0     0.0
  }}}

  The first column is DEGREE1, the second is the average of DEGREE2, and the third column is the standard deviation of the average.

  === Vertex-Vertex Correlation ===
  [[T(Complexity|'''O(E)''')]]

  Option summary:
  {{{
  --vertex-correlation-histogram=DEGREE1|DEGREE2[|WEIGHT]|FILE
                                      get the degree correlation histogram.
                                      Scalar properties are also accepted in
                                      place of DEGREE. An optional edge weight
                                      property can be passed by WEIGHT
  --average-nearest-neighbours-correlation=ORIGIN-DEGREE|DEGREE[|WEIGHT]|FILE
                                      get the average nearest neighbours
                                      correlation. An optional edge weight
                                      property can be passed by WEIGHT
  }}}

  The vertex correlation histogram is a bidimensional histogram defined as

  [[Equation(\[C(k,k')=\sum_{u,v}A_{uv}W_{uv}[k_u=k][k_v=k']\])]], where [[Equation($\mathbf{A}$)]] is the adjacency matrix, and [[Equation($\mathbf{W}$)]] is an optional weight matrix. It is obtainable with the "{{{--vertex-correlation-histogram}}}" option, which takes three or four parameters separated by "|": First degree type ([[Equation($k_u$)]]), second degree type ([[Equation($k_v$)]]), an optional weight property, and a file name. The degree types can be `in-degree`, `out-degree` and `total-degree`. It can also be the name of any scalar vertex property available.

  Example:

  {{{
  $ graph-tool --load example.xml --vertex-correlation="in-degree|out-degree|deg-corr"
  $ cat deg-corr
  0.0     1.0     1
  0.0     2.0     1
  1.0     1.0     3
  2.0     1.0     3
  }}}

  It is also possible to obtain the correlation in an alternative fashion, which a lot of times is more convenient, which is the average nearest neighbours degree, given by

  [[Equation(\[ \bar{k}(k)=\frac{\sum_{u,v}A_{uv}W_{uv}k_v[k_u=k]}{\sum_{u,v}A_{uv}[k_u=k]}\])]].

  It is obtainable with the "`--average-nearest-neighbours-correlation`" option, which takes three or four parameters separated by "|": degree type of the origin vertex, degree type of the neighbours, the optional weight property, and a file name. Origin and neighbour degree type can be "`in-degree`", "`out-degree`" and "`total-degree`", as well as the name of any scalar vertex property available.

  Example:

  {{{
  $ graph-tool --load example.xml --average-nearest-neighbours-correlation="total-degree|in-degree|deg-corr"
  $ cat deg-corr
  1.0     1.5     0.5
  2.0     2.0     0.0
  3.0     1.8     0.2
  }}}

  The third column above is the standard deviation of the average in the second column.

  === Edge Correlation ===
  [[T(Complexity|'''O(E)''')]]

  Option summary:
  {{{
  --edge-vertex-correlation-histogram=DEGREE1|EDGE-PROP|DEGREE2|FILE
                                                             get the source degree vs. edge scalar vs. target degree
                                                             correlation histogram. Scalar properties are also accepted in
                                                             place of DEGREE-TYPE
  }}}


  When edges have scalar properties, it is possible to generate a 3-dimensional correlation histogram defined as:

  [[Equation(\[ P(k,m,k')=\sum_{e}[k_{s(e)}=k][k_{t(e)}=k'][p(e)=m]}\])]], where [[Equation($e$)]] are the edges of the graph, [[Equation(\[s(e)\])]] and [[Equation(\[t(e)\])]] are the source and target vertex of edge [[Equation($e$)]], and [[Equation(\[p(e)\])]] is some property of the edge.

  This can be obtained with the "`--edge-vertex-correlation-histogram`" option which takes four arguments separated by "|": Source degree type, edge property and target degree type. The source and target degree types can be "`in-degree`", "`out-degree`" and "`total-degree`", as well as the name of any scalar vertex property available.

  Example:
  {{{
  $ graph-tool --load example.xml --edge-vertex-correlation-histogram="in-degree|weight|out-degree|edge-corr"
  $ cat edge-corr
  0.0     0.2     2.0     1
  0.0     1.2     1.0     1
  1.0     2.0     1.0     1
  1.0     5.5     1.0     1
  1.0     10.1    1.0     1
  2.0     0.1     1.0     1
  2.0     0.5     1.0     1
  2.0     0.8     1.0     1
  }}}


name: GraphCorrelations
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Correlations ==

  === Combined Vertex Correlation ===
  [[T(Complexity|'''O(V)''')]]

  Option summary:
  {{{
  --average-combined-vertex-correlation=DEGREE1|DEGREE2|FILE
                                      get the average of DEGREE2 in function of
                                      DEGREE1. Scalar properties are also
                                      accepted as DEGREE1 or DEGREE2
  }}}

  The average combined vertex correlation is defined as

  [[Equation(\[\left<k_2\right>(k_1)=\frac{\sum_{v}{k_2}_v[{k_1}_v=k_1]}{\sum_{v}[{k_1}_v=k_1]}\])]], where [[Equation($k_1$)]] is the first degree type and [[Equation($k_2$)]] is the second. It is obtainable with the "{{{--average-combined-vertex-correlation}}}" option, which takes three parameters separated by "|": First degree type ([[Equation($k_1$)]]), second degree type ([[Equation($k_2$)]]), and a file name. The degree types can be `in-degree`, `out-degree` and `total-degree`. It can also be the name of any scalar vertex property available.

  Example:

  {{{
  $ ./graph-tool --load example.xml \
    --average-combined-vertex-correlation="in-degree|out-degree|-"
  # average combined vertex correlation (in-degree, out-degree):
  0.0     1.0     0.0
  1.0     1.5     0.5
  2.0     1.0     0.0
  }}}

  The first column is DEGREE1, the second is the average of DEGREE2, and the third column is the standard deviation of the average.

  === Vertex-Vertex Correlation ===
  [[T(Complexity|'''O(E)''')]]

  Option summary:
  {{{
  --vertex-correlation-histogram=DEGREE1|DEGREE2[|WEIGHT]|FILE
                                      get the degree correlation histogram.
                                      Scalar properties are also accepted in
                                      place of DEGREE. An optional edge weight
                                      property can be passed by WEIGHT
  --average-nearest-neighbours-correlation=ORIGIN-DEGREE|DEGREE[|WEIGHT]|FILE
                                      get the average nearest neighbours
                                      correlation. An optional edge weight
                                      property can be passed by WEIGHT
  }}}

  The vertex correlation histogram is a bidimensional histogram defined as

  [[Equation(\[C(k,k')=\sum_{u,v}A_{uv}W_{uv}[k_u=k][k_v=k']\])]], where [[Equation($\mathbf{A}$)]] is the adjacency matrix, and [[Equation($\mathbf{W}$)]] is an optional weight matrix. It is obtainable with the "{{{--vertex-correlation-histogram}}}" option, which takes three or four parameters separated by "|": First degree type ([[Equation($k_u$)]]), second degree type ([[Equation($k_v$)]]), an optional weight property, and a file name. The degree types can be `in-degree`, `out-degree` and `total-degree`. It can also be the name of any scalar vertex property available.

  Example:

  {{{
  $ graph-tool --load example.xml --vertex-correlation="in-degree|out-degree|deg-corr"
  $ cat deg-corr
  0.0     1.0     1
  0.0     2.0     1
  1.0     1.0     3
  2.0     1.0     3
  }}}

  It is also possible to obtain the correlation in an alternative fashion, which a lot of times is more convenient, which is the average nearest neighbours degree, given by

  [[Equation(\[ \bar{k}(k)=\frac{\sum_{u,v}A_{uv}W_{uv}k_v[k_u=k]}{\sum_{u,v}A_{uv}[k_u=k]}\])]].

  It is obtainable with the "`--average-nearest-neighbours-correlation`" option, which takes three or four parameters separated by "|": degree type of the origin vertex, degree type of the neighbours, the optional weight property, and a file name. Origin and neighbour degree type can be "`in-degree`", "`out-degree`" and "`total-degree`", as well as the name of any scalar vertex property available.

  Example:

  {{{
  $ graph-tool --load example.xml --average-nearest-neighbours-correlation="total-degree|in-degree|deg-corr"
  $ cat deg-corr
  1.0     1.5     0.5
  2.0     2.0     0.0
  3.0     1.8     0.2
  }}}

  The third column above is the standard deviation of the average in the second column.

  === Edge Correlation ===
  [[T(Complexity|'''O(E)''')]]

  Option summary:
  {{{
  --edge-vertex-correlation-histogram=DEGREE1|EDGE-PROP|DEGREE2|FILE
                                                             get the source degree vs. edge scalar vs. target degree
                                                             correlation histogram. Scalar properties are also accepted in
                                                             place of DEGREE-TYPE
  }}}


  When edges have scalar properties, it is possible to generate a 3-dimensional correlation histogram defined as:

  [[Equation(\[ P(k,m,k')=\sum_{e}[k_{s(e)}=k][k_{t(e)}=k'][p(e)=m]}\])]], where [[Equation($e$)]] are the edges of the graph, [[Equation(\[s(e)\])]] and [[Equation(\[t(e)\])]] are the source and target vertex of edge [[Equation($e$)]], and [[Equation(\[p(e)\])]] is some property of the edge.

  This can be obtained with the "`--edge-vertex-correlation-histogram`" option which takes four arguments separated by "|": Source degree type, edge property and target degree type. The source and target degree types can be "`in-degree`", "`out-degree`" and "`total-degree`", as well as the name of any scalar vertex property available.

  Example:
  {{{
  $ graph-tool --load example.xml --edge-vertex-correlation-histogram="in-degree|weight|out-degree|edge-corr"
  $ cat edge-corr
  0.0     0.2     2.0     1
  0.0     1.2     1.0     1
  1.0     2.0     1.0     1
  1.0     5.5     1.0     1
  1.0     10.1    1.0     1
  2.0     0.1     1.0     1
  2.0     0.5     1.0     1
  2.0     0.8     1.0     1
  }}}


name: GraphCorrelations
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Correlations ==

  === Combined Vertex Correlation ===
  [[T(Complexity|'''O(V)''')]]

  Option summary:
  {{{
  --average-combined-vertex-correlation=DEGREE1|DEGREE2|FILE
                                      get the average of DEGREE2 in function of
                                      DEGREE1. Scalar properties are also
                                      accepted as DEGREE1 or DEGREE2
  }}}

  The average combined vertex correlation is defined as

  [[Equation(\[\bar{k_2}(k_1)=\frac{\sum_{v}{k_2}_v[{k_1}_v=k_1]}{\sum_{v}[{k_1}_v=k_1]}\])]], where [[Equation($k_1$)]] is the first degree type and [[Equation($k_2$)]] is the second. It is obtainable with the "{{{--average-combined-vertex-correlation}}}" option, which takes three parameters separated by "|": First degree type ([[Equation($k_1$)]]), second degree type ([[Equation($k_2$)]]), and a file name. The degree types can be `in-degree`, `out-degree` and `total-degree`. It can also be the name of any scalar vertex property available.

  Example:

  {{{
  $ ./graph-tool --load example.xml \
    --average-combined-vertex-correlation="in-degree|out-degree|-"
  # average combined vertex correlation (in-degree, out-degree):
  0.0     1.0     0.0
  1.0     1.5     0.5
  2.0     1.0     0.0
  }}}

  The first column is DEGREE1, the second is the average of DEGREE2, and the third column is the standard deviation of the average.

  === Vertex-Vertex Correlation ===
  [[T(Complexity|'''O(E)''')]]

  Option summary:
  {{{
  --vertex-correlation-histogram=DEGREE1|DEGREE2[|WEIGHT]|FILE
                                      get the degree correlation histogram.
                                      Scalar properties are also accepted in
                                      place of DEGREE. An optional edge weight
                                      property can be passed by WEIGHT
  --average-nearest-neighbours-correlation=ORIGIN-DEGREE|DEGREE[|WEIGHT]|FILE
                                      get the average nearest neighbours
                                      correlation. An optional edge weight
                                      property can be passed by WEIGHT
  }}}

  The vertex correlation histogram is a bidimensional histogram defined as

  [[Equation(\[C(k,k')=\sum_{u,v}A_{uv}W_{uv}[k_u=k][k_v=k']\])]], where [[Equation($\mathbf{A}$)]] is the adjacency matrix, and [[Equation($\mathbf{W}$)]] is an optional weight matrix. It is obtainable with the "{{{--vertex-correlation-histogram}}}" option, which takes three or four parameters separated by "|": First degree type ([[Equation($k_u$)]]), second degree type ([[Equation($k_v$)]]), an optional weight property, and a file name. The degree types can be `in-degree`, `out-degree` and `total-degree`. It can also be the name of any scalar vertex property available.

  Example:

  {{{
  $ graph-tool --load example.xml --vertex-correlation="in-degree|out-degree|deg-corr"
  $ cat deg-corr
  0.0     1.0     1
  0.0     2.0     1
  1.0     1.0     3
  2.0     1.0     3
  }}}

  It is also possible to obtain the correlation in an alternative fashion, which a lot of times is more convenient, which is the average nearest neighbours degree, given by

  [[Equation(\[ \bar{k}(k)=\frac{\sum_{u,v}A_{uv}W_{uv}k_v[k_u=k]}{\sum_{u,v}A_{uv}[k_u=k]}\])]].

  It is obtainable with the "`--average-nearest-neighbours-correlation`" option, which takes three or four parameters separated by "|": degree type of the origin vertex, degree type of the neighbours, the optional weight property, and a file name. Origin and neighbour degree type can be "`in-degree`", "`out-degree`" and "`total-degree`", as well as the name of any scalar vertex property available.

  Example:

  {{{
  $ graph-tool --load example.xml --average-nearest-neighbours-correlation="total-degree|in-degree|deg-corr"
  $ cat deg-corr
  1.0     1.5     0.5
  2.0     2.0     0.0
  3.0     1.8     0.2
  }}}

  The third column above is the standard deviation of the average in the second column.

  === Edge Correlation ===
  [[T(Complexity|'''O(E)''')]]

  Option summary:
  {{{
  --edge-vertex-correlation-histogram=DEGREE1|EDGE-PROP|DEGREE2|FILE
                                                             get the source degree vs. edge scalar vs. target degree
                                                             correlation histogram. Scalar properties are also accepted in
                                                             place of DEGREE-TYPE
  }}}


  When edges have scalar properties, it is possible to generate a 3-dimensional correlation histogram defined as:

  [[Equation(\[ P(k,m,k')=\sum_{e}[k_{s(e)}=k][k_{t(e)}=k'][p(e)=m]}\])]], where [[Equation($e$)]] are the edges of the graph, [[Equation(\[s(e)\])]] and [[Equation(\[t(e)\])]] are the source and target vertex of edge [[Equation($e$)]], and [[Equation(\[p(e)\])]] is some property of the edge.

  This can be obtained with the "`--edge-vertex-correlation-histogram`" option which takes four arguments separated by "|": Source degree type, edge property and target degree type. The source and target degree types can be "`in-degree`", "`out-degree`" and "`total-degree`", as well as the name of any scalar vertex property available.

  Example:
  {{{
  $ graph-tool --load example.xml --edge-vertex-correlation-histogram="in-degree|weight|out-degree|edge-corr"
  $ cat edge-corr
  0.0     0.2     2.0     1
  0.0     1.2     1.0     1
  1.0     2.0     1.0     1
  1.0     5.5     1.0     1
  1.0     10.1    1.0     1
  2.0     0.1     1.0     1
  2.0     0.5     1.0     1
  2.0     0.8     1.0     1
  }}}


name: DocToc
author: count0
ipnr: 201.81.194.239
text:
  [[TOC(GraphToolGuide,BasicStatistics,GraphFiltering,GraphModification,GraphCorrelations,MixingPatterns,GraphClustering,GraphLayout,GraphReciprocity,RandomGraphGeneration,CommunityDetection,GraphHistory)]]


name: MixingPatterns
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Mixing Patterns ==

  === Assortativity Coefficient ===
  [[T(Complexity| '''O(E)''')]]

  The assortativity coefficient tells in a concise fashion how vertices of different types are preferentially connected amongst themselves, and is defined by

  [[Equation(\[r = \frac{\sum_i e_{ii} - \sum_i a_i b_i}{1-\sum_i a_i b_i}\])]] where [[Equation(\[a_i=\sum_je_{ij}\])]] and [[Equation(\[b_j=\sum_ie_{ij}\])]], and [[Equation($e_{ij}$)]] is the fraction of edges from a vertex of type [[Equation($i$)]] to a vertex of type [[Equation($j$)]].

  It is obtained by the option `--assortativity-coefficient`", which takes two arguments: the property used to identify different types and a file name, separated by "|". The property may be any scalar vertex property in the graph, as well a "`in-degree`", "`out-degree`" and "`total-degree`".

  Example:

  {{{
  $ graph-tool --load example.xml --assortativity-coefficient="total-degree|-"
  assortativity coefficient:      0.492063        0.252221
  }}}

  The first value is the assortativity coefficient, and the second is the variance, obtained with the [http://en.wikipedia.org/wiki/Resampling_%28statistics%29#Jackknife jackknife method].

  === Scalar Assortativity Coefficient ===
  [[T(Complexity| '''O(E)''')]]

  If the types of vertices are scalar properties, the following coefficient may be more useful:

  [[Equation(\[r = \frac{\sum_{xy} xy(e_{xy} - a_x b_y)}{\sigma_a\sigma_b}\])]] where [[Equation(\[a_x=\sum_ye_{xy}\])]] and [[Equation(\[b_y=\sum_xe_{xy}\])]], and [[Equation($e_{xy}$)]] is the fraction of edges from a vertex of type [[Equation($x$)]] to a vertex of type [[Equation($y$)]]. It can be obtained with the "`--scalar-assortativity-coefficient`" option, which takes the same parameters as the [[ref(Assortativity Coefficient)]]. Example:

  {{{
  $ graph-tool --load example.xml --scalar-assortativity-coefficient="total-degree|-"
  scalar assortativity coefficient:       -0.241202       0.292476
  }}}

  The first value is the scalar assortativity coefficient, and the second is the variance, obtained with the [http://en.wikipedia.org/wiki/Resampling_%28statistics%29#Jackknife jackknife method].


name: GraphClustering
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Clustering ==

  === Local Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The local (vertex) clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(1)}_v = \frac{2N_c}{k(k-1)}\])]], where [[Equation($k$)]] is the number of neighbours of the vertex, and [[Equation($N_c$)]] is the number of edges between the neighbours of the vertex. This value can be calculated and set to a vertex property with the command "`--set-local-clustering-to-property`", which takes the property name as parameter. Example:

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --vertex-histogram="clustering|clust"
  $ cat clust
  0.0     4
  0.333333333333  3
  }}}

  It is possible to obtain the clustering coefficient for the whole graph by using the `--average-vertex-property` option :

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --average-vertex-property="clustering|-"
  average vertex property:        0.142857        0.062348
  }}}

  The first value is the clustering coefficient, and the second is the standard deviation.

  [[T(Note|Performance note|Please consider using the [wiki:GraphClustering#ExtendedClustering extented clustering] algorithm below, which is implemented differently and seems to be faster.)]]

  === Global Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The global clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(2)} = \frac{3N_t}{N_c}\])]], where [[Equation($N_t$)]] is the number of triangles in the graph and [[Equation($N_c$)]] is the number of connected triplets. It can be obtained with the "`--global-clustering-coefficient`" option, which takes a file name as a parameter, or "`-`" for terminal output. Example:

  {{{
  $ graph-tool --load example.xml --global-clustering-coefficient=- 
  global clustering coefficient:  0.230769        0.030769
  }}}

  The first value is the global clustering coefficient, and the second value is the variance using the [http://en.wikipedia.org/wiki/Resampling_(statistics)#Jackknife jackknife method] on the vertices.

  === Extended Clustering ===
  [[T(Complexity|'''O(V<k>^2^*N(MAX))''', where '''N(d)''' is the average number of vertices and edges visited during a BFS of maximal depth $d$.)

  Option summary:
  {{{
  --set-extended-clustering-to-property=PREFIX|MAX
                                      set the extended clustering coefficients
                                      c1 to cMAX to vertex properties PREFIX1
                                      to PREFIXMAX
  }}}


name: GraphClustering
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Clustering ==

  === Local Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The local (vertex) clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(1)}_v = \frac{2N_c}{k(k-1)}\])]], where [[Equation($k$)]] is the number of neighbours of the vertex, and [[Equation($N_c$)]] is the number of edges between the neighbours of the vertex. This value can be calculated and set to a vertex property with the command "`--set-local-clustering-to-property`", which takes the property name as parameter. Example:

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --vertex-histogram="clustering|clust"
  $ cat clust
  0.0     4
  0.333333333333  3
  }}}

  It is possible to obtain the clustering coefficient for the whole graph by using the `--average-vertex-property` option :

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --average-vertex-property="clustering|-"
  average vertex property:        0.142857        0.062348
  }}}

  The first value is the clustering coefficient, and the second is the standard deviation.

  [[T(Note|Performance note|Please consider using the [wiki:GraphClustering#ExtendedClustering extented clustering] algorithm below, which is implemented differently and seems to be faster.)]]

  === Global Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The global clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(2)} = \frac{3N_t}{N_c}\])]], where [[Equation($N_t$)]] is the number of triangles in the graph and [[Equation($N_c$)]] is the number of connected triplets. It can be obtained with the "`--global-clustering-coefficient`" option, which takes a file name as a parameter, or "`-`" for terminal output. Example:

  {{{
  $ graph-tool --load example.xml --global-clustering-coefficient=- 
  global clustering coefficient:  0.230769        0.030769
  }}}

  The first value is the global clustering coefficient, and the second value is the variance using the [http://en.wikipedia.org/wiki/Resampling_(statistics)#Jackknife jackknife method] on the vertices.

  === Extended Clustering ===
  [[T(Complexity|'''O(V<k>^2+MAX^))''' (worst case))]]

  Option summary:
  {{{
  --set-extended-clustering-to-property=PREFIX|MAX
                                      set the extended clustering coefficients
                                      c1 to cMAX to vertex properties PREFIX1
                                      to PREFIXMAX
  }}}


name: GraphClustering
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Clustering ==

  === Local Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The local (vertex) clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(1)}_v = \frac{2N_c}{k(k-1)}\])]], where [[Equation($k$)]] is the number of neighbours of the vertex, and [[Equation($N_c$)]] is the number of edges between the neighbours of the vertex. This value can be calculated and set to a vertex property with the command "`--set-local-clustering-to-property`", which takes the property name as parameter. Example:

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --vertex-histogram="clustering|clust"
  $ cat clust
  0.0     4
  0.333333333333  3
  }}}

  It is possible to obtain the clustering coefficient for the whole graph by using the `--average-vertex-property` option :

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --average-vertex-property="clustering|-"
  average vertex property:        0.142857        0.062348
  }}}

  The first value is the clustering coefficient, and the second is the standard deviation.

  [[T(Note|Performance note|Please consider using the [wiki:GraphClustering#ExtendedClustering extented clustering] algorithm below, which is implemented differently and seems to be faster.)]]

  === Global Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The global clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(2)} = \frac{3N_t}{N_c}\])]], where [[Equation($N_t$)]] is the number of triangles in the graph and [[Equation($N_c$)]] is the number of connected triplets. It can be obtained with the "`--global-clustering-coefficient`" option, which takes a file name as a parameter, or "`-`" for terminal output. Example:

  {{{
  $ graph-tool --load example.xml --global-clustering-coefficient=- 
  global clustering coefficient:  0.230769        0.030769
  }}}

  The first value is the global clustering coefficient, and the second value is the variance using the [http://en.wikipedia.org/wiki/Resampling_(statistics)#Jackknife jackknife method] on the vertices.

  === Extended Clustering ===
  [[T(Complexity|'''O(V<k>^2+MAX^))''' (worst case))]]

  Option summary:
  {{{
  --set-extended-clustering-to-property=PREFIX|MAX
                                      set the extended clustering coefficients
                                      c1 to cMAX to vertex properties PREFIX1
                                      to PREFIXMAX
  }}}

  An interesting generalization of the local clustering coefficient was proposed by [http://arxiv.org/abs/physics/0605235 Abdo et al] which allows for clusterings of larger order, while conceptual and numerical compatibility with the traditional coefficient is maintained. The definition of the extended clustering coefficient is as follows:


name: GraphClustering
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Clustering ==

  === Local Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The local (vertex) clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(1)}_v = \frac{2N_c}{k(k-1)}\])]], where [[Equation($k$)]] is the number of neighbours of the vertex, and [[Equation($N_c$)]] is the number of edges between the neighbours of the vertex. This value can be calculated and set to a vertex property with the command "`--set-local-clustering-to-property`", which takes the property name as parameter. Example:

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --vertex-histogram="clustering|clust"
  $ cat clust
  0.0     4
  0.333333333333  3
  }}}

  It is possible to obtain the clustering coefficient for the whole graph by using the `--average-vertex-property` option :

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --average-vertex-property="clustering|-"
  average vertex property:        0.142857        0.062348
  }}}

  The first value is the clustering coefficient, and the second is the standard deviation.

  [[T(Note|Performance note|Please consider using the [wiki:GraphClustering#ExtendedClustering extented clustering] algorithm below, which is implemented differently and seems to be faster.)]]

  === Global Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The global clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(2)} = \frac{3N_t}{N_c}\])]], where [[Equation($N_t$)]] is the number of triangles in the graph and [[Equation($N_c$)]] is the number of connected triplets. It can be obtained with the "`--global-clustering-coefficient`" option, which takes a file name as a parameter, or "`-`" for terminal output. Example:

  {{{
  $ graph-tool --load example.xml --global-clustering-coefficient=- 
  global clustering coefficient:  0.230769        0.030769
  }}}

  The first value is the global clustering coefficient, and the second value is the variance using the [http://en.wikipedia.org/wiki/Resampling_(statistics)#Jackknife jackknife method] on the vertices.

  === Extended Clustering ===
  [[T(Complexity|'''O(V<k>^2+MAX^))''' (worst case))]]

  Option summary:
  {{{
  --set-extended-clustering-to-property=PREFIX|MAX
                                      set the extended clustering coefficients
                                      c1 to cMAX to vertex properties PREFIX1
                                      to PREFIXMAX
  }}}

  An interesting generalization of the local clustering coefficient was proposed by [http://arxiv.org/abs/physics/0605235 Abdo et al] which allows for clusterings of larger order, while conceptual and numerical compatibility with the traditional coefficient is maintained. The definition of the extended clustering coefficient is as follows:

  [[Equation(\[C^d(u) = \frac{\left|\right\{ \{v,w\}; v,w \in N(u) | d_{G(V\diagdown \{u\})} (v,w) = d \left\}\right|}{\binom{\left|N(u)\right|}{2}} \])]]


name: GraphClustering
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Clustering ==

  === Local Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The local (vertex) clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(1)}_v = \frac{2N_c}{k(k-1)}\])]], where [[Equation($k$)]] is the number of neighbours of the vertex, and [[Equation($N_c$)]] is the number of edges between the neighbours of the vertex. This value can be calculated and set to a vertex property with the command "`--set-local-clustering-to-property`", which takes the property name as parameter. Example:

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --vertex-histogram="clustering|clust"
  $ cat clust
  0.0     4
  0.333333333333  3
  }}}

  It is possible to obtain the clustering coefficient for the whole graph by using the `--average-vertex-property` option :

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --average-vertex-property="clustering|-"
  average vertex property:        0.142857        0.062348
  }}}

  The first value is the clustering coefficient, and the second is the standard deviation.

  [[T(Note|Performance note|Please consider using the [wiki:GraphClustering#ExtendedClustering extented clustering] algorithm below, which is implemented differently and seems to be faster.)]]

  === Global Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The global clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(2)} = \frac{3N_t}{N_c}\])]], where [[Equation($N_t$)]] is the number of triangles in the graph and [[Equation($N_c$)]] is the number of connected triplets. It can be obtained with the "`--global-clustering-coefficient`" option, which takes a file name as a parameter, or "`-`" for terminal output. Example:

  {{{
  $ graph-tool --load example.xml --global-clustering-coefficient=- 
  global clustering coefficient:  0.230769        0.030769
  }}}

  The first value is the global clustering coefficient, and the second value is the variance using the [http://en.wikipedia.org/wiki/Resampling_(statistics)#Jackknife jackknife method] on the vertices.

  === Extended Clustering ===
  [[T(Complexity|'''O(V<k>^2+MAX^))''' (worst case))]]

  Option summary:
  {{{
  --set-extended-clustering-to-property=PREFIX|MAX
                                      set the extended clustering coefficients
                                      c1 to cMAX to vertex properties PREFIX1
                                      to PREFIXMAX
  }}}

  An interesting generalization of the local clustering coefficient was proposed by [http://arxiv.org/abs/physics/0605235 Abdo et al] which allows for clusterings of larger order, while conceptual and numerical compatibility with the traditional coefficient is maintained. The definition of the extended clustering coefficient is as follows:

  [[Equation(\[C^d(u) = \frac{\left|\right\{ \{v,w\}; v,w \in N(u) | d_{G(V\diagdown \{u\})} (v,w) = d \left\}\right|}{\binom{\left|N(u)\right|}{2}} \])]],

  where [[Equation($N(u)$)] is the set of neighbours of [[Equation($N(u)$)]. According to the above definition, we have that the traditional clustering coefficient is recovered for [Equation($d=1$)].

  The extended clustering coefficients can be calculated and set to a vertex property with the command "`--set-extended-clustering-to-property`", which takes the prefix of property name as parameter, and the maximum value of "d". The properties from PREFIX1 to PREFIXMAX will contain the coefficients C^1^ to C^MAX^. Example:

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --vertex-histogram="clustering|clust"
  $ cat clust
  0.0     4
  0.333333333333  3
  }}}


name: GraphClustering
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Clustering ==

  === Local Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The local (vertex) clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(1)}_v = \frac{2N_c}{k(k-1)}\])]], where [[Equation($k$)]] is the number of neighbours of the vertex, and [[Equation($N_c$)]] is the number of edges between the neighbours of the vertex. This value can be calculated and set to a vertex property with the command "`--set-local-clustering-to-property`", which takes the property name as parameter. Example:

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --vertex-histogram="clustering|clust"
  $ cat clust
  0.0     4
  0.333333333333  3
  }}}

  It is possible to obtain the clustering coefficient for the whole graph by using the `--average-vertex-property` option :

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --average-vertex-property="clustering|-"
  average vertex property:        0.142857        0.062348
  }}}

  The first value is the clustering coefficient, and the second is the standard deviation.

  [[T(Note|Performance note|Please consider using the [wiki:GraphClustering#ExtendedClustering extented clustering] algorithm below, which is implemented differently and seems to be faster.)]]

  === Global Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The global clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(2)} = \frac{3N_t}{N_c}\])]], where [[Equation($N_t$)]] is the number of triangles in the graph and [[Equation($N_c$)]] is the number of connected triplets. It can be obtained with the "`--global-clustering-coefficient`" option, which takes a file name as a parameter, or "`-`" for terminal output. Example:

  {{{
  $ graph-tool --load example.xml --global-clustering-coefficient=- 
  global clustering coefficient:  0.230769        0.030769
  }}}

  The first value is the global clustering coefficient, and the second value is the variance using the [http://en.wikipedia.org/wiki/Resampling_(statistics)#Jackknife jackknife method] on the vertices.

  === Extended Clustering ===
  [[T(Complexity|'''O(V<k>^2+MAX^))''' (worst case))]]

  Option summary:
  {{{
  --set-extended-clustering-to-property=PREFIX|MAX
                                      set the extended clustering coefficients
                                      c1 to cMAX to vertex properties PREFIX1
                                      to PREFIXMAX
  }}}

  An interesting generalization of the local clustering coefficient was proposed by [http://arxiv.org/abs/physics/0605235 Abdo et al] which allows for clusterings of larger order, while conceptual and numerical compatibility with the traditional coefficient is maintained. The definition of the extended clustering coefficient is as follows:

  [[Equation(\[C^d(u) = \frac{\left|\right\{ \{v,w\}; v,w \in N(u) | d_{G(V\diagdown \{u\})} (v,w) = d \left\}\right|}{\binom{\left|N(u)\right|}{2}} \])]],

  where [[Equation($N(u)$)] is the set of neighbours of [[Equation($N(u)$)]. According to the above definition, we have that the traditional clustering coefficient is recovered for [Equation($d=1$)].

  The extended clustering coefficients can be calculated and set to a vertex property with the command "`--set-extended-clustering-to-property`", which takes the prefix of property name as parameter, and the maximum value of "d". The properties from PREFIX1 to PREFIXMAX will contain the coefficients C^1^ to C^MAX^. 

  Example:
  {{{
  $ graph-tool --load example.xml --set-extended-clustering-to-property="c|3" --vertex-histogram="c2|-"
  # vertex histogram (c2):
  0.0     3
  0.333333333333  3
  1.0     1
  }}}


name: GraphClustering
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Clustering ==

  === Local Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The local (vertex) clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(1)}_v = \frac{2N_c}{k(k-1)}\])]], where [[Equation($k$)]] is the number of neighbours of the vertex, and [[Equation($N_c$)]] is the number of edges between the neighbours of the vertex. This value can be calculated and set to a vertex property with the command "`--set-local-clustering-to-property`", which takes the property name as parameter. Example:

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --vertex-histogram="clustering|clust"
  $ cat clust
  0.0     4
  0.333333333333  3
  }}}

  It is possible to obtain the clustering coefficient for the whole graph by using the `--average-vertex-property` option :

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --average-vertex-property="clustering|-"
  average vertex property:        0.142857        0.062348
  }}}

  The first value is the clustering coefficient, and the second is the standard deviation.

  [[T(Note|Performance note|Please consider using the [wiki:GraphClustering#ExtendedClustering extented clustering] algorithm below, which is implemented differently and seems to be faster.)]]

  === Global Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The global clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(2)} = \frac{3N_t}{N_c}\])]], where [[Equation($N_t$)]] is the number of triangles in the graph and [[Equation($N_c$)]] is the number of connected triplets. It can be obtained with the "`--global-clustering-coefficient`" option, which takes a file name as a parameter, or "`-`" for terminal output. Example:

  {{{
  $ graph-tool --load example.xml --global-clustering-coefficient=- 
  global clustering coefficient:  0.230769        0.030769
  }}}

  The first value is the global clustering coefficient, and the second value is the variance using the [http://en.wikipedia.org/wiki/Resampling_(statistics)#Jackknife jackknife method] on the vertices.

  === Extended Clustering ===
  [[T(Complexity|'''O(V<k>^2+MAX^))''' (worst case))]]

  Option summary:
  {{{
  --set-extended-clustering-to-property=PREFIX|MAX
                                      set the extended clustering coefficients
                                      c1 to cMAX to vertex properties PREFIX1
                                      to PREFIXMAX
  }}}

  An interesting generalization of the local clustering coefficient was proposed by [http://arxiv.org/abs/physics/0605235 Abdo et al] which allows for clusterings of larger order, while conceptual and numerical compatibility with the traditional coefficient is maintained. The definition of the extended clustering coefficient is as follows:

  [[Equation(\[C^d(u) = \frac{\left|\right\{ \{v,w\}; v,w \in N(u) | d_{G(V\diagdown \{u\})} (v,w) = d \left\}\right|}{\binom{\left|N(u)\right|}{2}} \])]],

  where [[Equation($N(u)$)]] is the set of neighbours of [[Equation($N(u)$)]]. According to the above definition, we have that the traditional clustering coefficient is recovered for [[Equation($d=1$)]].

  The extended clustering coefficients can be calculated and set to a vertex property with the command "`--set-extended-clustering-to-property`", which takes the prefix of property name as parameter, and the maximum value of "d". The properties from PREFIX1 to PREFIXMAX will contain the coefficients C^1^ to C^MAX^. 

  Example:
  {{{
  $ graph-tool --load example.xml --set-extended-clustering-to-property="c|3" --vertex-histogram="c2|-"
  # vertex histogram (c2):
  0.0     3
  0.333333333333  3
  1.0     1
  }}}


name: GraphClustering
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Clustering ==

  === Local Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The local (vertex) clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(1)}_v = \frac{2N_c}{k(k-1)}\])]], where [[Equation($k$)]] is the number of neighbours of the vertex, and [[Equation($N_c$)]] is the number of edges between the neighbours of the vertex. This value can be calculated and set to a vertex property with the command "`--set-local-clustering-to-property`", which takes the property name as parameter. Example:

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --vertex-histogram="clustering|clust"
  $ cat clust
  0.0     4
  0.333333333333  3
  }}}

  It is possible to obtain the clustering coefficient for the whole graph by using the `--average-vertex-property` option :

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --average-vertex-property="clustering|-"
  average vertex property:        0.142857        0.062348
  }}}

  The first value is the clustering coefficient, and the second is the standard deviation.

  [[T(Note|Performance note|Please consider using the [wiki:GraphClustering#ExtendedClustering extented clustering] algorithm below, which is implemented differently and seems to be faster.)]]

  === Global Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The global clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(2)} = \frac{3N_t}{N_c}\])]], where [[Equation($N_t$)]] is the number of triangles in the graph and [[Equation($N_c$)]] is the number of connected triplets. It can be obtained with the "`--global-clustering-coefficient`" option, which takes a file name as a parameter, or "`-`" for terminal output. Example:

  {{{
  $ graph-tool --load example.xml --global-clustering-coefficient=- 
  global clustering coefficient:  0.230769        0.030769
  }}}

  The first value is the global clustering coefficient, and the second value is the variance using the [http://en.wikipedia.org/wiki/Resampling_(statistics)#Jackknife jackknife method] on the vertices.

  === Extended Clustering ===
  [[T(Complexity|'''O(V<k>^2+MAX^))''' (worst case))]]

  Option summary:
  {{{
  --set-extended-clustering-to-property=PREFIX|MAX
                                      set the extended clustering coefficients
                                      c1 to cMAX to vertex properties PREFIX1
                                      to PREFIXMAX
  }}}

  An interesting generalization of the local clustering coefficient was proposed by [http://arxiv.org/abs/physics/0605235 Abdo et al] which allows for clusterings of larger order, while conceptual and numerical compatibility with the traditional coefficient is maintained. The definition of the extended clustering coefficient is as follows:

  [[Equation(\[C^d(u) = \frac{\left|\right\{ \{v,w\}; v,w \in N(u) | d_{G(V\diagdown \{u\})} (v,w) = d \left\}\right|}{\binom{\left|N(u)\right|}{2}} \])]],

  where '''N(u)''' is the set of neighbours of '''u'''. According to the above definition, we have that the traditional clustering coefficient is recovered for '''d=1'''.

  The extended clustering coefficients can be calculated and set to a vertex property with the command "`--set-extended-clustering-to-property`", which takes the prefix of property name as parameter, and the maximum value of "d". The properties from PREFIX1 to PREFIXMAX will contain the coefficients C^1^ to C^MAX^. 

  Example:
  {{{
  $ graph-tool --load example.xml --set-extended-clustering-to-property="c|3" --vertex-histogram="c2|-"
  # vertex histogram (c2):
  0.0     3
  0.333333333333  3
  1.0     1
  }}}


name: GraphReciprocity
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Reciprocity ==

  Option summary:
  {{{
  --reciprocity=FILE                                                  get the edge reciprocity
  }}}

  This option calculated the reciprocity of the directed graph, defined as

  [[Equation(\[\rho=\frac{L_{bd}/L-\bar{a}}{1-\bar{a}}\])]], where [[Equation(\[\bar{a}=\frac{L}{N(N-1)}\])]] and '''L,,bd,,''' is the number of bidirectional edges.


  {{{
      --minimum-spanning-tree=[WEIGHT|]PROPERTY                           mark the minimum spanning tree edges in PROPERTY
      --line-graph=FILE[|FORMAT]             
  }}}


name: GraphReciprocity
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Reciprocity ==

  Option summary:
  {{{
  --reciprocity=FILE                    get the edge reciprocity
  }}}

  This option calculates the reciprocity of the directed graph, defined as

  [[Equation(\[\rho=\frac{L_{bd}/L-\bar{a}}{1-\bar{a}}\])]], where [[Equation(\[\bar{a}=\frac{L}{N(N-1)}\])]] and '''L,,bd,,''' is the number of bidirectional edges.

  As an example consider the following graph saved as "reciprocity.dot":

  {{{
  #!graphviz
  digraph G {
  start="12";
  1->2 [len=0.6];
  2->3 [len=0.6];
  3->7 [len=0.6];
  4->5 [len=0.6];
  5->4 [len=0.6];
  5->6 [len=0.6];
  5->3 [len=0.6];
  6->7 [len=0.6];
  7->6 [len=0.6];
  7->2 [len=0.6];
  }
  }}}

  {{{
  $ graph-tool --load reciprocity.dot --reciprocity=-
  # reciprocity:
  0.2125
  }}}


name: DocToc
author: count0
ipnr: 201.81.194.239
text:
  [[TOC(GraphToolGuide,BasicStatistics, GraphFiltering, GraphModification, GraphCorrelations, MixingPatterns, GraphClustering, GraphLayout, GraphReciprocity, DerivedGraphs, RandomGraphGeneration, CommunityDetection, GraphHistory)]]


name: DerivedGraphs
author: count0
ipnr: 201.81.194.239
text:
  == Derived Graphs ==

  === Minimum Spanning Tree ===

  {{{
      --minimum-spanning-tree=[WEIGHT|]PROPERTY                           mark the minimum spanning tree edges in PROPERTY
      --line-graph=FILE[|FORMAT]             
  }}


name: DerivedGraphs
author: count0
ipnr: 201.81.194.239
text:
  == Derived Graphs ==

  === Minimum Spanning Tree ===
  [[T(Complexity|'''O(E log(E))''')]]

  Options summary:
  {{{
  --minimum-spanning-tree=[WEIGHT|]PROPERTY      mark the minimum spanning tree edges in PROPERTY
  }}}

  This options marks the edges belonging to the (one of the many) [http://en.wikipedia.org/wiki/Minimum_spanning_tree minimum spanning tree] of the graph (as if it were undirected) in a boolean property map specified by PROPERTY (value 1 (True) if it belongs, 0 (False) otherwise). The vertices can later be filtered out, if necessary.

  Example, consider the following "example.dot":

  {{{
  #! graphviz
  digraph G 
  start=12;
  {
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}

  {{{
  $ graph-tool --load example.xml --minimum-spanning-tree="weight|tree" --number-of-edges=- \
               --edge-range-filter="tree|1 1"  --number-of-edges=- --save=spanning-tree.dot
  # number of edges:
  8

  # number of edges:
  6
  }}}

  === Line Graph ===
  {{{
      --line-graph=FILE[|FORMAT]             
  }}}


name: DerivedGraphs
author: count0
ipnr: 201.81.194.239
text:
  == Derived Graphs ==

  === Minimum Spanning Tree ===
  [[T(Complexity|'''O(E log(E))''')]]

  Options summary:
  {{{
  --minimum-spanning-tree=[WEIGHT|]PROPERTY      mark the minimum spanning tree edges in PROPERTY
  }}}

  This options marks the edges belonging to the (one of the many) [http://en.wikipedia.org/wiki/Minimum_spanning_tree minimum spanning tree] of the graph (as if it were undirected) in a boolean property map specified by PROPERTY (value 1 (True) if it belongs, 0 (False) otherwise). The vertices can later be filtered out, if necessary.

  Example, consider the following "example.dot":

  {{{
  #!graphviz
  digraph G 
  {
  start="12";
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}

  {{{
  $ graph-tool --load example.xml --minimum-spanning-tree="weight|tree" --number-of-edges=- \
               --edge-range-filter="tree|1 1"  --number-of-edges=- --save=spanning-tree.dot
  # number of edges:
  8

  # number of edges:
  6
  }}}

  The saved "spanning-tree.dot" file is the following:

  {{{
  #!graphviz
  digraph G {
  0->1  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }

  }}}

  === Line Graph ===

  Option summary:
  {{{
  --line-graph=FILE[|FORMAT]          save the corresponding line graph to FILE
  }}}

  This option calculates the [http://en.wikipedia.org/wiki/Line_graph line graph] of the graph as if it were undirected and outputs it to FILE. The default format is either guessed by the filename, or obtained by the FORMAT option. If unspecified, it defaults to graphml. The vertex properties are converted to edge properties and vice-versa.


  As an example, consider the following "example.dot":

  {{{
  #!graphviz
  digraph G 
  {
  start="12";
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}


  {{{
  $ graph-tool --load example.xml --line-graph="line-graph.dot"
  }}}

  The graph "line-graph.dot" looks like this:

  {{{
  #!graphviz
  graph G {
  0;
  1;
  2;
  3;
  4;
  5;
  6;
  7;
  1--0 ;
  1--7 ;
  0--7 ;
  2--1 ;
  2--5 ;
  1--5 ;
  4--5 ;
  4--3 ;
  5--3 ;
  6--4 ;
  7--2 ;
  7--6 ;
  2--6 ;
  }
  }}}


name: DerivedGraphs
author: count0
ipnr: 201.81.194.239
text:
  == Derived Graphs ==

  === Minimum Spanning Tree ===
  [[T(Complexity|'''O(E log(E))''')]]

  Options summary:
  {{{
  --minimum-spanning-tree=[WEIGHT|]PROPERTY      mark the minimum spanning tree edges in PROPERTY
  }}}

  This options marks the edges belonging to the (one of the many) [http://en.wikipedia.org/wiki/Minimum_spanning_tree minimum spanning tree] of the graph (as if it were undirected) in a boolean property map specified by PROPERTY (value 1 (True) if it belongs, 0 (False) otherwise). The vertices can later be filtered out, if necessary. It also accepts a weight property defined by WEIGHT. The algorithm used is described [http://www.boost.org/libs/graph/doc/kruskal_min_spanning_tree.html here].

  Example, consider the following "example.dot":

  {{{
  #!graphviz
  digraph G 
  {
  start="12";
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}

  {{{
  $ graph-tool --load example.xml --minimum-spanning-tree="weight|tree" --number-of-edges=- \
               --edge-range-filter="tree|1 1"  --number-of-edges=- --save=spanning-tree.dot
  # number of edges:
  8

  # number of edges:
  6
  }}}

  The saved "spanning-tree.dot" file is the following:

  {{{
  #!graphviz
  digraph G {
  0->1  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }

  }}}

  === Line Graph ===

  Option summary:
  {{{
  --line-graph=FILE[|FORMAT]          save the corresponding line graph to FILE
  }}}

  This option calculates the [http://en.wikipedia.org/wiki/Line_graph line graph] of the graph as if it were undirected and outputs it to FILE. The default format is either guessed by the filename, or obtained by the FORMAT option. If unspecified, it defaults to graphml. The vertex properties are converted to edge properties and vice-versa.


  As an example, consider the following "example.dot":

  {{{
  #!graphviz
  digraph G 
  {
  start="12";
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}


  {{{
  $ graph-tool --load example.xml --line-graph="line-graph.dot"
  }}}

  The graph "line-graph.dot" looks like this:

  {{{
  #!graphviz
  graph G {
  0;
  1;
  2;
  3;
  4;
  5;
  6;
  7;
  1--0 ;
  1--7 ;
  0--7 ;
  2--1 ;
  2--5 ;
  1--5 ;
  4--5 ;
  4--3 ;
  5--3 ;
  6--4 ;
  7--2 ;
  7--6 ;
  2--6 ;
  }
  }}}


name: DerivedGraphs
author: count0
ipnr: 201.81.194.239
text:
  == Derived Graphs ==

  === Minimum Spanning Tree ===
  [[T(Complexity|'''O(E log(E))''')]]

  Options summary:
  {{{
  --minimum-spanning-tree=[WEIGHT|]PROPERTY      mark the minimum spanning tree edges in PROPERTY
  }}}

  This options marks the edges belonging to the (one of the many) [http://en.wikipedia.org/wiki/Minimum_spanning_tree minimum spanning tree] of the graph (as if it were undirected) in a boolean property map specified by PROPERTY (value 1 (True) if it belongs, 0 (False) otherwise). The vertices can later be filtered out, if necessary. It also accepts a weight property defined by WEIGHT. The algorithm used is described [http://www.boost.org/libs/graph/doc/kruskal_min_spanning_tree.html here].

  Example, consider the following "example.dot":

  {{{
  #!graphviz
  digraph G 
  {
  start="12";
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}

  {{{
  $ graph-tool --load example.xml --minimum-spanning-tree="weight|tree" --number-of-edges=- \
               --edge-range-filter="tree|1 1"  --number-of-edges=- --save=spanning-tree.dot
  # number of edges:
  8

  # number of edges:
  6
  }}}

  The saved "spanning-tree.dot" file is the following:

  {{{
  #!graphviz
  digraph G {
  0->1  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }

  }}}

  === Line Graph ===
  [[T(Complexity|'''O(E+V<k>^^2^^)''')]]

  Option summary:
  {{{
  --line-graph=FILE[|FORMAT]          save the corresponding line graph to FILE
  }}}

  This option calculates the [http://en.wikipedia.org/wiki/Line_graph line graph] of the graph as if it were undirected and outputs it to FILE. The default format is either guessed by the filename, or obtained by the FORMAT option. If unspecified, it defaults to graphml. The vertex properties are converted to edge properties and vice-versa.


  As an example, consider the following "example.dot":

  {{{
  #!graphviz
  digraph G 
  {
  start="12";
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}


  {{{
  $ graph-tool --load example.xml --line-graph="line-graph.dot"
  }}}

  The graph "line-graph.dot" looks like this:

  {{{
  #!graphviz
  graph G {
  0;
  1;
  2;
  3;
  4;
  5;
  6;
  7;
  1--0 ;
  1--7 ;
  0--7 ;
  2--1 ;
  2--5 ;
  1--5 ;
  4--5 ;
  4--3 ;
  5--3 ;
  6--4 ;
  7--2 ;
  7--6 ;
  2--6 ;
  }
  }}}


name: DerivedGraphs
author: count0
ipnr: 201.81.194.239
text:
  == Derived Graphs ==

  === Minimum Spanning Tree ===
  [[T(Complexity|'''O(E log(E))''')]]

  Options summary:
  {{{
  --minimum-spanning-tree=[WEIGHT|]PROPERTY      mark the minimum spanning tree edges in PROPERTY
  }}}

  This options marks the edges belonging to the (one of the many) [http://en.wikipedia.org/wiki/Minimum_spanning_tree minimum spanning tree] of the graph (as if it were undirected) in a boolean property map specified by PROPERTY (value 1 (True) if it belongs, 0 (False) otherwise). The vertices can later be filtered out, if necessary. It also accepts a weight property defined by WEIGHT. The algorithm used is described [http://www.boost.org/libs/graph/doc/kruskal_min_spanning_tree.html here].

  Example, consider the following "example.dot":

  {{{
  #!graphviz
  digraph G 
  {
  start="12";
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}

  {{{
  $ graph-tool --load example.xml --minimum-spanning-tree="weight|tree" --number-of-edges=- \
               --edge-range-filter="tree|1 1"  --number-of-edges=- --save=spanning-tree.dot
  # number of edges:
  8

  # number of edges:
  6
  }}}

  The saved "spanning-tree.dot" file is the following:

  {{{
  #!graphviz
  digraph G {
  0->1  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }

  }}}

  === Line Graph ===
  [[T(Complexity|'''O(E+V<k>^2^)''')]]

  Option summary:
  {{{
  --line-graph=FILE[|FORMAT]          save the corresponding line graph to FILE
  }}}

  This option calculates the [http://en.wikipedia.org/wiki/Line_graph line graph] of the graph as if it were undirected and outputs it to FILE. The default format is either guessed by the filename, or obtained by the FORMAT option. If unspecified, it defaults to graphml. The vertex properties are converted to edge properties and vice-versa.


  As an example, consider the following "example.dot":

  {{{
  #!graphviz
  digraph G 
  {
  start="12";
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}


  {{{
  $ graph-tool --load example.xml --line-graph="line-graph.dot"
  }}}

  The graph "line-graph.dot" looks like this:

  {{{
  #!graphviz
  graph G {
  0;
  1;
  2;
  3;
  4;
  5;
  6;
  7;
  1--0 ;
  1--7 ;
  0--7 ;
  2--1 ;
  2--5 ;
  1--5 ;
  4--5 ;
  4--3 ;
  5--3 ;
  6--4 ;
  7--2 ;
  7--6 ;
  2--6 ;
  }
  }}}


name: DerivedGraphs
author: count0
ipnr: 201.81.194.239
text:
  == Derived Graphs ==

  === Minimum Spanning Tree ===
  [[T(Complexity|'''O(E log(E))''')]]

  Options summary:
  {{{
  --minimum-spanning-tree=[WEIGHT|]PROPERTY      mark the minimum spanning tree edges in PROPERTY
  }}}

  This options marks the edges belonging to the (one of the many) [http://en.wikipedia.org/wiki/Minimum_spanning_tree minimum spanning tree] of the graph (as if it were undirected) in a boolean property map specified by PROPERTY (value 1 (True) if it belongs, 0 (False) otherwise). The vertices can later be filtered out, if necessary. It also accepts a weight property defined by WEIGHT. The algorithm used is described [http://www.boost.org/libs/graph/doc/kruskal_min_spanning_tree.html here].

  Example, consider the following "example.dot":

  {{{
  #!graphviz
  digraph G 
  {
  start="12";
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}

  {{{
  $ graph-tool --load example.xml --minimum-spanning-tree="weight|tree" --number-of-edges=- \
               --edge-range-filter="tree|1 1"  --number-of-edges=- --save=spanning-tree.dot
  # number of edges:
  8

  # number of edges:
  6
  }}}

  The saved "spanning-tree.dot" file is the following:

  {{{
  #!graphviz
  digraph G {
  0->1  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }

  }}}

  -----

  === Line Graph ===
  [[T(Complexity|'''O(E+V<k>^2^)''')]]

  Option summary:
  {{{
  --line-graph=FILE[|FORMAT]          save the corresponding line graph to FILE
  }}}

  This option calculates the [http://en.wikipedia.org/wiki/Line_graph line graph] of the graph as if it were undirected and outputs it to FILE. The default format is either guessed by the filename, or obtained by the FORMAT option. If unspecified, it defaults to graphml. The vertex properties are converted to edge properties and vice-versa.


  As an example, consider the following "example.dot":

  {{{
  #!graphviz
  digraph G 
  {
  start="12";
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}


  {{{
  $ graph-tool --load example.xml --line-graph="line-graph.dot"
  }}}

  The graph "line-graph.dot" looks like this:

  {{{
  #!graphviz
  graph G {
  0;
  1;
  2;
  3;
  4;
  5;
  6;
  7;
  1--0 ;
  1--7 ;
  0--7 ;
  2--1 ;
  2--5 ;
  1--5 ;
  4--5 ;
  4--3 ;
  5--3 ;
  6--4 ;
  7--2 ;
  7--6 ;
  2--6 ;
  }
  }}}


name: GraphHistory
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Graph History ==

  Option Summary:

  {{{
  --for=INIT|CONDITION|STEP                            simplified scripting
  --history=INIT|CONDITION|STEP                        simplified scripting (does not overwrite previous results)
  --refresh-rate=TIME                                  for/history files refresh rate
  }}}

  Graphs sometimes have dynamical properties related to them. Sometimes they grow or change somehow during time. It is often interesting to see how its various properties also change with time. In graph tool this is possible through the usage of properties, filtering, and the "`--history`" or "`--for`" option. The history/for option takes three parameters, which function just like a "`for` loop": the initial statement, a condition to be checked every iteration, and a step statement. The variables defined and modified in the parameters of this option are available to be used by the other options that follow it. __The difference between the `for` and `history` options is that the `history` option does not overwrite existing files, and only appends to them.__ Using graph properties and filtering, snapshots of the graph can be generated. It all becomes clearer with an example. Consider the following graph, called "`example-time.xml`":

  {{{
  #!html
  <div style="float: right;">
  }}}
  {{{
  #!graphviz
  digraph G {
  start="12";
  1->2 [label = "  1  ", len=0.6];
  2->3 [label = "  2  ", len=0.6];
  3->7 [label = "  3  ", len=0.6];
  4->5 [label = "  4  ", len=0.6];
  5->6 [label = "  5  ", len=0.6];
  5->3 [label = "  6  ", len=0.6];
  6->7 [label = "  7  ", len=0.6];
  7->2 [label = "  8  ", len=0.6];
  }
  }}}
  {{{
  #!html
  </div>
  }}}


  {{{
  #!xml
  <?xml version="1.0" encoding="UTF-8"?>
  <graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://graphml.graphdrawing\.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
    <key id="d1" for="edge" attr.name="time" attr.type="int"/>
    <graph id="G" edgedefault="directed">
      <node id="n0"/>
      <node id="n1"/>
      <node id="n2"/>
      <node id="n3"/>
      <node id="n4"/>
      <node id="n5"/>
      <node id="n6"/>
      <edge id="e0" source="n0" target="n1">
        <data key="d1">1</data>
      </edge>
      <edge id="e1" source="n1" target="n2">
        <data key="d1">2</data>
      </edge>
      <edge id="e2" source="n2" target="n6">
        <data key="d1">3</data>
      </edge>
      <edge id="e3" source="n3" target="n4">
        <data key="d1">4</data>
      </edge>
      <edge id="e4" source="n4" target="n5">
        <data key="d1">5</data>
      </edge>
      <edge id="e5" source="n4" target="n2">
        <data key="d1">6</data>
      </edge>
      <edge id="e6" source="n5" target="n6">
        <data key="d1">7</data>
      </edge>
      <edge id="e7" source="n6" target="n1">
        <data key="d1">8</data>
      </edge>
    </graph>
  </graphml>
  }}}

  There's an edge property called time which goes from 1 to 8. So in order to calculate, for instance, the number of edges and the degree distribution over time, one could do the following:

  {{{
  $ graph-tool --load example-time.xml --history="t=1|t<9|t+=1" --edge-range-filter="time|1 %t" \
  --vertex-histogram="total-degree|deg-history" --number-of-edges="num-edges-history"
  $ cat num-edges-history 
  0       1
  1       2
  2       3
  3       4
  4       5
  5       6
  6       7
  7       8
  $ cat deg-history
  0       0.0     5
  0       1.0     2
  1       0.0     4
  1       1.0     2
  1       2.0     1
  2       0.0     3
  2       1.0     2
  2       2.0     2
  3       0.0     1
  3       1.0     4
  3       2.0     2
  4       1.0     4
  4       2.0     3
  5       1.0     4
  5       2.0     1
  5       3.0     2
  6       1.0     2
  6       2.0     3
  6       3.0     2
  7       1.0     2
  7       2.0     1
  7       3.0     4
  }}}

  The variables defined in the "`--history`" option are reachable in the options that follow it by prefixing them with "`%`". Each saved file contains the history of the measured property, with each line prefixed by the history iteration number (or with the variable "`prefix`" defined in the history specification, as shown below). In the case above, "`num-edges-history`" contains the number of edges in each iteration and "`deg-history`" contains the degree distribution with each iteration. It should be clear with the above example that this feature is reasonably general, since combined with generic filtering, it is possible to obtain quite arbitrary "histories" of the graph. The syntax of the history specification is any valid [http://www.python.org python] statement.

  ==== Specifying the history prefix ====

  Using the history counter as a prefix is sometimes not the most comfortable way of labeling points in history. Luckily, this can easily be changed by defining the "`prefix`" variable, as shown in the example below:

  {{{
  $ graph-tool --load example-time.xml --history="t=1; prefix=t+10 | t<9 | t+=1; prefix=t+10" \
   --edge-range-filter="time|1 %t" --number-of-edges="num-edges-history"
  $ cat num-edges-history 
  11      1
  12      2
  13      3
  14      4
  15      5
  16      6
  17      7
  18      8
  }}}

  The prefix can be entirely suppressed by setting it to an empty string: "`prefix=""`". This can be useful when each history step is being saved to a different file.

  === Resuming history computations ===

  For large graphs history computations can take quite a long time. During this time things in general can go wrong, such as a power outage. For this reason graph-tool supports resuming of history computations, where partial results already contained in the history files are automatically skipped and not recalculated. Therefore, if you change the history rules or the graph, you must remember to delete the old history files or to save to new ones, otherwise they'll still contain old information.

  Before data is saved to the history files, partial history results are kept in temporary files, which get periodically copied over to the final files. The frequency of this update can be changed with the "`--history-rate`" option, which takes a number as a parameter followed by "`s`","`m`","`h`" or "`d`" to indicate seconds, minutes, hours or days, respectively. The default value is "`1h`".


name: GraphHistory
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Graph History ==

  Option Summary:

  {{{
  --for=INIT|CONDITION|STEP          simplified scripting
  --history=INIT|CONDITION|STEP      simplified scripting (does not overwrite previous results)
  --refresh-rate=TIME                for/history files refresh rate
  }}}

  Graphs sometimes have dynamical properties related to them. Sometimes they grow or change somehow during time. It is often interesting to see how its various properties also change with time. In graph tool this is possible through the usage of properties, filtering, and the "`--history`" or "`--for`" option. The history/for option takes three parameters, which function just like a "`for` loop": the initial statement, a condition to be checked every iteration, and a step statement. The variables defined and modified in the parameters of this option are available to be used by the other options that follow it. __The difference between the `for` and `history` options is that the `history` option does not overwrite existing files, and only appends to them.__ Using graph properties and filtering, snapshots of the graph can be generated. It all becomes clearer with an example. Consider the following graph, called "`example-time.xml`":

  {{{
  #!html
  <div style="float: right;">
  }}}
  {{{
  #!graphviz
  digraph G {
  start="12";
  1->2 [label = "  1  ", len=0.6];
  2->3 [label = "  2  ", len=0.6];
  3->7 [label = "  3  ", len=0.6];
  4->5 [label = "  4  ", len=0.6];
  5->6 [label = "  5  ", len=0.6];
  5->3 [label = "  6  ", len=0.6];
  6->7 [label = "  7  ", len=0.6];
  7->2 [label = "  8  ", len=0.6];
  }
  }}}
  {{{
  #!html
  </div>
  }}}


  {{{
  #!xml
  <?xml version="1.0" encoding="UTF-8"?>
  <graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://graphml.graphdrawing\.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
    <key id="d1" for="edge" attr.name="time" attr.type="int"/>
    <graph id="G" edgedefault="directed">
      <node id="n0"/>
      <node id="n1"/>
      <node id="n2"/>
      <node id="n3"/>
      <node id="n4"/>
      <node id="n5"/>
      <node id="n6"/>
      <edge id="e0" source="n0" target="n1">
        <data key="d1">1</data>
      </edge>
      <edge id="e1" source="n1" target="n2">
        <data key="d1">2</data>
      </edge>
      <edge id="e2" source="n2" target="n6">
        <data key="d1">3</data>
      </edge>
      <edge id="e3" source="n3" target="n4">
        <data key="d1">4</data>
      </edge>
      <edge id="e4" source="n4" target="n5">
        <data key="d1">5</data>
      </edge>
      <edge id="e5" source="n4" target="n2">
        <data key="d1">6</data>
      </edge>
      <edge id="e6" source="n5" target="n6">
        <data key="d1">7</data>
      </edge>
      <edge id="e7" source="n6" target="n1">
        <data key="d1">8</data>
      </edge>
    </graph>
  </graphml>
  }}}

  There's an edge property called time which goes from 1 to 8. So in order to calculate, for instance, the number of edges and the degree distribution over time, one could do the following:

  {{{
  $ graph-tool --load example-time.xml --history="t=1|t<9|t+=1" --edge-range-filter="time|1 %t" \
  --vertex-histogram="total-degree|deg-history" --number-of-edges="num-edges-history"
  $ cat num-edges-history 
  0       1
  1       2
  2       3
  3       4
  4       5
  5       6
  6       7
  7       8
  $ cat deg-history
  0       0.0     5
  0       1.0     2
  1       0.0     4
  1       1.0     2
  1       2.0     1
  2       0.0     3
  2       1.0     2
  2       2.0     2
  3       0.0     1
  3       1.0     4
  3       2.0     2
  4       1.0     4
  4       2.0     3
  5       1.0     4
  5       2.0     1
  5       3.0     2
  6       1.0     2
  6       2.0     3
  6       3.0     2
  7       1.0     2
  7       2.0     1
  7       3.0     4
  }}}

  The variables defined in the "`--history`" option are reachable in the options that follow it by prefixing them with "`%`". Each saved file contains the history of the measured property, with each line prefixed by the history iteration number (or with the variable "`prefix`" defined in the history specification, as shown below). In the case above, "`num-edges-history`" contains the number of edges in each iteration and "`deg-history`" contains the degree distribution with each iteration. It should be clear with the above example that this feature is reasonably general, since combined with generic filtering, it is possible to obtain quite arbitrary "histories" of the graph. The syntax of the history specification is any valid [http://www.python.org python] statement.

  ==== Specifying the history prefix ====

  Using the history counter as a prefix is sometimes not the most comfortable way of labeling points in history. Luckily, this can easily be changed by defining the "`prefix`" variable, as shown in the example below:

  {{{
  $ graph-tool --load example-time.xml --history="t=1; prefix=t+10 | t<9 | t+=1; prefix=t+10" \
   --edge-range-filter="time|1 %t" --number-of-edges="num-edges-history"
  $ cat num-edges-history 
  11      1
  12      2
  13      3
  14      4
  15      5
  16      6
  17      7
  18      8
  }}}

  The prefix can be entirely suppressed by setting it to an empty string: "`prefix=""`". This can be useful when each history step is being saved to a different file.

  === Resuming history computations ===

  For large graphs history computations can take quite a long time. During this time things in general can go wrong, such as a power outage. For this reason graph-tool supports resuming of history computations, where partial results already contained in the history files are automatically skipped and not recalculated. Therefore, if you change the history rules or the graph, you must remember to delete the old history files or to save to new ones, otherwise they'll still contain old information.

  Before data is saved to the history files, partial history results are kept in temporary files, which get periodically copied over to the final files. The frequency of this update can be changed with the "`--history-rate`" option, which takes a number as a parameter followed by "`s`","`m`","`h`" or "`d`" to indicate seconds, minutes, hours or days, respectively. The default value is "`1h`".


name: GraphHistory
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Graph History ==

  Option Summary:

  {{{
  --for=INIT|CONDITION|STEP          simplified scripting
  --history=INIT|CONDITION|STEP      simplified scripting (does not overwrite previous results)
  --refresh-rate=TIME                for/history files refresh rate
  }}}

  Graphs sometimes have dynamical properties related to them. Sometimes they grow or change somehow during time. It is often interesting to see how its various properties also change with time. In graph-tool this is possible through the usage of properties, filtering, and the "`--history`" or "`--for`" option. The history/for option takes three parameters, which function just like a "`for` loop": the initial statement, a condition to be checked every iteration, and a step statement. The variables defined and modified in the parameters of this option are available to be used by the other options that follow it. __The difference between the `for` and `history` options is that the `history` option does not overwrite existing files, and only appends to them.__ Using graph properties and filtering, snapshots of the graph can be generated. It all becomes clearer with an example. Consider the following graph, called "`example-time.xml`":

  {{{
  #!html
  <div style="float: right;">
  }}}
  {{{
  #!graphviz
  digraph G {
  start="12";
  1->2 [label = "  1  ", len=0.6];
  2->3 [label = "  2  ", len=0.6];
  3->7 [label = "  3  ", len=0.6];
  4->5 [label = "  4  ", len=0.6];
  5->6 [label = "  5  ", len=0.6];
  5->3 [label = "  6  ", len=0.6];
  6->7 [label = "  7  ", len=0.6];
  7->2 [label = "  8  ", len=0.6];
  }
  }}}
  {{{
  #!html
  </div>
  }}}


  {{{
  #!xml
  <?xml version="1.0" encoding="UTF-8"?>
  <graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://graphml.graphdrawing\.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
    <key id="d1" for="edge" attr.name="time" attr.type="int"/>
    <graph id="G" edgedefault="directed">
      <node id="n0"/>
      <node id="n1"/>
      <node id="n2"/>
      <node id="n3"/>
      <node id="n4"/>
      <node id="n5"/>
      <node id="n6"/>
      <edge id="e0" source="n0" target="n1">
        <data key="d1">1</data>
      </edge>
      <edge id="e1" source="n1" target="n2">
        <data key="d1">2</data>
      </edge>
      <edge id="e2" source="n2" target="n6">
        <data key="d1">3</data>
      </edge>
      <edge id="e3" source="n3" target="n4">
        <data key="d1">4</data>
      </edge>
      <edge id="e4" source="n4" target="n5">
        <data key="d1">5</data>
      </edge>
      <edge id="e5" source="n4" target="n2">
        <data key="d1">6</data>
      </edge>
      <edge id="e6" source="n5" target="n6">
        <data key="d1">7</data>
      </edge>
      <edge id="e7" source="n6" target="n1">
        <data key="d1">8</data>
      </edge>
    </graph>
  </graphml>
  }}}

  There's an edge property called time which goes from 1 to 8. So in order to calculate, for instance, the number of edges and the degree distribution over time, one could do the following:

  {{{
  $ graph-tool --load example-time.xml --history="t=1|t<9|t+=1" --edge-range-filter="time|1 %t" \
  --vertex-histogram="total-degree|deg-history" --number-of-edges="num-edges-history"
  $ cat num-edges-history 
  0       1
  1       2
  2       3
  3       4
  4       5
  5       6
  6       7
  7       8
  $ cat deg-history
  0       0.0     5
  0       1.0     2
  1       0.0     4
  1       1.0     2
  1       2.0     1
  2       0.0     3
  2       1.0     2
  2       2.0     2
  3       0.0     1
  3       1.0     4
  3       2.0     2
  4       1.0     4
  4       2.0     3
  5       1.0     4
  5       2.0     1
  5       3.0     2
  6       1.0     2
  6       2.0     3
  6       3.0     2
  7       1.0     2
  7       2.0     1
  7       3.0     4
  }}}

  The variables defined in the "`--history`" option are reachable in the options that follow it by prefixing them with "`%`". Each saved file contains the history of the measured property, with each line prefixed by the history iteration number (or with the variable "`prefix`" defined in the history specification, as shown below). In the case above, "`num-edges-history`" contains the number of edges in each iteration and "`deg-history`" contains the degree distribution with each iteration. It should be clear with the above example that this feature is reasonably general, since combined with generic filtering, it is possible to obtain quite arbitrary "histories" of the graph. The syntax of the history specification is any valid [http://www.python.org python] statement.

  ==== Specifying the history prefix ====

  Using the history counter as a prefix is sometimes not the most comfortable way of labeling points in history. Luckily, this can easily be changed by defining the "`prefix`" variable, as shown in the example below:

  {{{
  $ graph-tool --load example-time.xml --history="t=1; prefix=t+10 | t<9 | t+=1; prefix=t+10" \
   --edge-range-filter="time|1 %t" --number-of-edges="num-edges-history"
  $ cat num-edges-history 
  11      1
  12      2
  13      3
  14      4
  15      5
  16      6
  17      7
  18      8
  }}}

  The prefix can be entirely suppressed by setting it to an empty string: "`prefix=""`". This can be useful when each history step is being saved to a different file.

  === Resuming history computations ===

  For large graphs history computations can take quite a long time. During this time things in general can go wrong, such as a power outage. For this reason graph-tool supports resuming of history computations, where partial results already contained in the history files are automatically skipped and not recalculated. Therefore, if you change the history rules or the graph, you must remember to delete the old history files or to save to new ones, otherwise they'll still contain old information.

  Before data is saved to the history files, partial history results are kept in temporary files, which get periodically copied over to the final files. The frequency of this update can be changed with the "`--history-rate`" option, which takes a number as a parameter followed by "`s`","`m`","`h`" or "`d`" to indicate seconds, minutes, hours or days, respectively. The default value is "`1h`".


name: DerivedGraphs
author: count0
ipnr: 201.81.194.239
text:
  == Derived Graphs ==

  === Minimum Spanning Tree ===
  [[T(Complexity|'''O(E log(E))''')]]

  Options summary:
  {{{
  --minimum-spanning-tree=[WEIGHT|]PROPERTY      mark the minimum spanning tree edges in PROPERTY
  }}}

  This options marks the edges belonging to the (one of the many) [http://en.wikipedia.org/wiki/Minimum_spanning_tree minimum spanning tree] of the graph (as if it were undirected) in a boolean property map specified by PROPERTY (value 1 (True) if it belongs, 0 (False) otherwise). The vertices can later be filtered out, if necessary. It also accepts a weight property defined by WEIGHT. The algorithm used is described [http://www.boost.org/libs/graph/doc/kruskal_min_spanning_tree.html here].

  Example, consider the following "example.dot":

  {{{
  #!graphviz
  digraph G 
  {
  start="12";
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}

  {{{
  $ graph-tool --load example.xml --minimum-spanning-tree="weight|tree" --number-of-edges=- \
               --edge-range-filter="tree|1 1"  --number-of-edges=- --save=spanning-tree.dot
  # number of edges:
  8

  # number of edges:
  6
  }}}

  The saved "spanning-tree.dot" file is the following:

  {{{
  #!graphviz
  digraph G {
  0->1  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }

  }}}

  -----

  === Line Graph ===
  [[T(Complexity|'''O(E+V<k>^2^)''')]]

  Option summary:
  {{{
  --line-graph=FILE[|FORMAT]          save the corresponding line graph to FILE
  }}}

  This option calculates the [http://en.wikipedia.org/wiki/Line_graph line graph] of the graph as if it were undirected and outputs it to FILE. The default format is either guessed by the filename, or obtained by the FORMAT option. If unspecified, it defaults to graphml. The vertex properties are converted to edge properties and vice-versa.


  As an example, consider the following "example.dot":

  {{{
  #!graphviz
  digraph G 
  {
  start="12";
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}


  {{{
  $ graph-tool --load example.xml --line-graph="line-graph.dot"
  }}}

  The graph "line-graph.dot" looks like this:

  {{{
  #!graphviz
  graph G {
  0;
  1;
  2;
  3;
  4;
  5;
  6;
  7;
  1--0 ;
  1--7 ;
  0--7 ;
  2--1 ;
  2--5 ;
  1--5 ;
  4--5 ;
  4--3 ;
  5--3 ;
  6--4 ;
  7--2 ;
  7--6 ;
  2--6 ;
  }
  }}}

  === Community Graph ===

  See CommunityDetection.


name: DerivedGraphs
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Derived Graphs ==

  === Minimum Spanning Tree ===
  [[T(Complexity|'''O(E log(E))''')]]

  Options summary:
  {{{
  --minimum-spanning-tree=[WEIGHT|]PROPERTY      mark the minimum spanning tree edges in PROPERTY
  }}}

  This options marks the edges belonging to the (one of the many) [http://en.wikipedia.org/wiki/Minimum_spanning_tree minimum spanning tree] of the graph (as if it were undirected) in a boolean property map specified by PROPERTY (value 1 (True) if it belongs, 0 (False) otherwise). The vertices can later be filtered out, if necessary. It also accepts a weight property defined by WEIGHT. The algorithm used is described [http://www.boost.org/libs/graph/doc/kruskal_min_spanning_tree.html here].

  Example, consider the following "example.dot":

  {{{
  #!graphviz
  digraph G 
  {
  start="12";
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}

  {{{
  $ graph-tool --load example.xml --minimum-spanning-tree="weight|tree" --number-of-edges=- \
               --edge-range-filter="tree|1 1"  --number-of-edges=- --save=spanning-tree.dot
  # number of edges:
  8

  # number of edges:
  6
  }}}

  The saved "spanning-tree.dot" file is the following:

  {{{
  #!graphviz
  digraph G {
  0->1  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }

  }}}

  -----

  === Line Graph ===
  [[T(Complexity|'''O(E+V<k>^2^)''')]]

  Option summary:
  {{{
  --line-graph=FILE[|FORMAT]          save the corresponding line graph to FILE
  }}}

  This option calculates the [http://en.wikipedia.org/wiki/Line_graph line graph] of the graph as if it were undirected and outputs it to FILE. The default format is either guessed by the filename, or obtained by the FORMAT option. If unspecified, it defaults to graphml. The vertex properties are converted to edge properties and vice-versa.


  As an example, consider the following "example.dot":

  {{{
  #!graphviz
  digraph G 
  {
  start="12";
  0->1  [len="0.6"];
  1->2  [len="0.6"];
  2->6  [len="0.6"];
  3->4  [len="0.6"];
  4->5  [len="0.6"];
  4->2  [len="0.6"];
  5->6  [len="0.6"];
  6->1  [len="0.6"];
  }
  }}}


  {{{
  $ graph-tool --load example.xml --line-graph="line-graph.dot"
  }}}

  The graph "line-graph.dot" looks like this:

  {{{
  #!graphviz
  graph G {
  0;
  1;
  2;
  3;
  4;
  5;
  6;
  7;
  1--0 ;
  1--7 ;
  0--7 ;
  2--1 ;
  2--5 ;
  1--5 ;
  4--5 ;
  4--3 ;
  5--3 ;
  6--4 ;
  7--2 ;
  7--6 ;
  2--6 ;
  }
  }}}

  === Community Graph ===

  See CommunityDetection.


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  = Community Detection =

  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  == Community Detection ==

  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a simulated annealing algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  which reduces the problem of community detection to finding the ground states of a Potts spin-glass model.

  == Modularity ==

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  == Community Detection ==

  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma$=1)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" takes a random graph with average correlation taken from the loaded graph itself.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged.

  == Modularity ==

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  == Community Detection ==

  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  Consider the following example. Attached is a file...

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}



  == Modularity ==

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  == Community Detection ==

  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[P(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file...

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}



  == Modularity ==

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  == Community Detection ==

  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file...

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}



  == Modularity ==

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  == Community Detection ==

  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}



  == Modularity ==

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  == Community Detection ==

  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.

  [[Image(original-community.png)]]

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}



  == Modularity ==

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  == Community Detection ==

  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.


  [[Image(original-community.png, align=center)]]


  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}



  [[Image(comm-history-iter.png, align=center)]] [[Image(comm-history-temp.png, align=center)]]


  == Modularity ==

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  == Community Detection ==

  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.

  {{{
  #!html
  <center>
  }}}
  [[Image(original-community.png)]]
  {{{
  #!html
  </center>
  }}}

  So, we'll try to recover this structure with the following command:

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}

  So, with those parameters the algorithm converged to 4 spins (communities). Below are the histories of the number of spins by iteration and temperature.

  {{{
  #!html
  <center>
  }}}
  [[Image(comm-history-iter.png)]] [[Image(comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And below is how the detected community structure looks like:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-community.png)]]
  {{{
  #!html
  </center>
  }}}

  === Sub-communities ===

  == Modularity ==

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  == Community Detection ==

  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.

  {{{
  #!html
  <center>
  }}}
  [[Image(original-community.png)]]
  {{{
  #!html
  </center>
  }}}

  So, we'll try to recover this structure with the following command:

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}

  So, with those parameters the algorithm converged to 4 spins (communities). Below are the histories of the number of spins by iteration and temperature.

  {{{
  #!html
  <center>
  }}}
  [[Image(comm-history-iter.png)]] [[Image(comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And below is how the detected community structure looks like:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-community.png)]]
  {{{
  #!html
  </center>
  }}}

  === Sub-communities ===

  To find sub-communities we must vary the parameter [[Equation($\gamma$)]]. Below are the results with [[Equation($\gamma=2.22$)]].

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|g=2.22,N=5000,Tmin=0.5,Tmax=1.5,corr_type=uncorrelated,seed=43,verbose,history=sub-comm-history-uncorr" \
    --save found-sub-community.xml
  4999 of 5000 (100%) temperature:            0.5 spins: 16 energy levels:  512
  }}}

  The histories:

  {{{
  #!html
  <center>
  }}}
  [[Image(sub-comm-history-iter.png)]] [[Image(sub-comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And the detected structure:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-sub-community.png)]]
  {{{
  #!html
  </center>
  }}}

  One vertex was apparently wrongly detected. However, this is more likely due to random deviations in the graph construction process. For denser graphs, it should be more robust.

  == Modularity ==

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  = Community Detection =
  [[T(Complexity| '''unknown''' (topology determined)]]


  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.

  {{{
  #!html
  <center>
  }}}
  [[Image(original-community.png)]]
  {{{
  #!html
  </center>
  }}}

  So, we'll try to recover this structure with the following command:

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}

  So, with those parameters the algorithm converged to 4 spins (communities). Below are the histories of the number of spins by iteration and temperature.

  {{{
  #!html
  <center>
  }}}
  [[Image(comm-history-iter.png)]] [[Image(comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And below is how the detected community structure looks like:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-community.png)]]
  {{{
  #!html
  </center>
  }}}

  === Sub-communities ===

  To find sub-communities we must vary the parameter [[Equation($\gamma$)]]. Below are the results with [[Equation($\gamma=2.22$)]].

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|g=2.22,N=5000,Tmin=0.5,Tmax=1.5,corr_type=uncorrelated,seed=43,verbose,history=sub-comm-history-uncorr" \
    --save found-sub-community.xml
  4999 of 5000 (100%) temperature:            0.5 spins: 16 energy levels:  512
  }}}

  The histories:

  {{{
  #!html
  <center>
  }}}
  [[Image(sub-comm-history-iter.png)]] [[Image(sub-comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And the detected structure:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-sub-community.png)]]
  {{{
  #!html
  </center>
  }}}

  One vertex was apparently wrongly detected. However, this is more likely due to random deviations in the graph construction process. For denser graphs, it should be more robust.

  == Modularity ==
  [[T(Modularity|'''O(V+E)''')]]

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  Given a specific graph partition specified by PROPERTY, [http://www-personal.umich.edu/~mejn/papers/epjb.pdf Newman's modularity], defined by

  [[Equation(\[  Q = \sum_s e_{ss} - \left(\sum_r e_{rs}\right) \])]], where [[Equation(\[e_{rs}\])]] is the fraction of edges which fall between vertices with spin '''s''' and '''r''', can be obtained by the above option (with the possibility of selection edge weights by the WEIGHT property).

  Example (consider the found-community.xml above):
  {{{
  $ graph-tool --undirected --load found-community.xml --modularity="spin|-"
  # modularity (spin):
  0.535314188562
  }}}




  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  = Community Detection =
  [[T(Complexity| '''unknown''' (topology determined)]]


  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.

  {{{
  #!html
  <center>
  }}}
  [[Image(original-community.png)]]
  {{{
  #!html
  </center>
  }}}

  So, we'll try to recover this structure with the following command:

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}

  So, with those parameters the algorithm converged to 4 spins (communities). Below are the histories of the number of spins by iteration and temperature.

  {{{
  #!html
  <center>
  }}}
  [[Image(comm-history-iter.png)]] [[Image(comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And below is how the detected community structure looks like:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-community.png)]]
  {{{
  #!html
  </center>
  }}}

  === Sub-communities ===

  To find sub-communities we must vary the parameter [[Equation($\gamma$)]]. Below are the results with [[Equation($\gamma=2.22$)]].

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|g=2.22,N=5000,Tmin=0.5,Tmax=1.5,corr_type=uncorrelated,seed=43,verbose,history=sub-comm-history-uncorr" \
    --save found-sub-community.xml
  4999 of 5000 (100%) temperature:            0.5 spins: 16 energy levels:  512
  }}}

  The histories:

  {{{
  #!html
  <center>
  }}}
  [[Image(sub-comm-history-iter.png)]] [[Image(sub-comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And the detected structure:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-sub-community.png)]]
  {{{
  #!html
  </center>
  }}}

  One vertex was apparently wrongly detected. However, this is more likely due to random deviations in the graph construction process. For denser graphs, it should be more robust.

  == Modularity ==
  [[T(Modularity|'''O(<k>V+E)''')]]

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  Given a specific graph partition specified by PROPERTY, [http://www-personal.umich.edu/~mejn/papers/epjb.pdf Newman's modularity], defined by

  [[Equation(\[  Q = \sum_s e_{ss} - \left(\sum_r e_{rs}\right) \])]], where [[Equation(\[e_{rs}\])]] is the fraction of edges which fall between vertices with spin '''s''' and '''r''', can be obtained by the above option (with the possibility of selection edge weights by the WEIGHT property).

  Example (consider the found-community.xml above):
  {{{
  $ graph-tool --undirected --load found-community.xml --modularity="spin|-"
  # modularity (spin):
  0.535314188562
  }}}




  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  = Community Detection =
  [[T(Complexity| '''unknown''' (topology determined)]]


  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.

  {{{
  #!html
  <center>
  }}}
  [[Image(original-community.png)]]
  {{{
  #!html
  </center>
  }}}

  So, we'll try to recover this structure with the following command:

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}

  So, with those parameters the algorithm converged to 4 spins (communities). Below are the histories of the number of spins by iteration and temperature.

  {{{
  #!html
  <center>
  }}}
  [[Image(comm-history-iter.png)]] [[Image(comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And below is how the detected community structure looks like:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-community.png)]]
  {{{
  #!html
  </center>
  }}}

  === Sub-communities ===

  To find sub-communities we must vary the parameter [[Equation($\gamma$)]]. Below are the results with [[Equation($\gamma=2.22$)]].

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|g=2.22,N=5000,Tmin=0.5,Tmax=1.5,corr_type=uncorrelated,seed=43,verbose,history=sub-comm-history-uncorr" \
    --save found-sub-community.xml
  4999 of 5000 (100%) temperature:            0.5 spins: 16 energy levels:  512
  }}}

  The histories:

  {{{
  #!html
  <center>
  }}}
  [[Image(sub-comm-history-iter.png)]] [[Image(sub-comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And the detected structure:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-sub-community.png)]]
  {{{
  #!html
  </center>
  }}}

  One vertex was apparently wrongly detected. However, this is more likely due to random deviations in the graph construction process. For denser graphs, it should be more robust.

  == Modularity ==
  [[T(Complexity|'''O(<k>V+E)''')]]

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  Given a specific graph partition specified by PROPERTY, [http://www-personal.umich.edu/~mejn/papers/epjb.pdf Newman's modularity], defined by

  [[Equation(\[  Q = \sum_s e_{ss} - \left(\sum_r e_{rs}\right)^2 \])]], where [[Equation(\[e_{rs}\])]] is the fraction of edges which fall between vertices with spin '''s''' and '''r''', can be obtained by the above option (with the possibility of selection edge weights by the WEIGHT property).

  Example (consider the found-community.xml above):
  {{{
  $ graph-tool --undirected --load found-community.xml --modularity="spin|-"
  # modularity (spin):
  0.535314188562
  }}}




  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  = Community Detection =
  [[T(Complexity| '''unknown''', determined by topology]]


  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.

  {{{
  #!html
  <center>
  }}}
  [[Image(original-community.png)]]
  {{{
  #!html
  </center>
  }}}

  So, we'll try to recover this structure with the following command:

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}

  So, with those parameters the algorithm converged to 4 spins (communities). Below are the histories of the number of spins by iteration and temperature.

  {{{
  #!html
  <center>
  }}}
  [[Image(comm-history-iter.png)]] [[Image(comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And below is how the detected community structure looks like:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-community.png)]]
  {{{
  #!html
  </center>
  }}}

  === Sub-communities ===

  To find sub-communities we must vary the parameter [[Equation($\gamma$)]]. Below are the results with [[Equation($\gamma=2.22$)]].

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|g=2.22,N=5000,Tmin=0.5,Tmax=1.5,corr_type=uncorrelated,seed=43,verbose,history=sub-comm-history-uncorr" \
    --save found-sub-community.xml
  4999 of 5000 (100%) temperature:            0.5 spins: 16 energy levels:  512
  }}}

  The histories:

  {{{
  #!html
  <center>
  }}}
  [[Image(sub-comm-history-iter.png)]] [[Image(sub-comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And the detected structure:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-sub-community.png)]]
  {{{
  #!html
  </center>
  }}}

  One vertex was apparently wrongly detected. However, this is more likely due to random deviations in the graph construction process. For denser graphs, it should be more robust.

  == Modularity ==
  [[T(Complexity|'''O(<k>V+E)''')]]

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  Given a specific graph partition specified by PROPERTY, [http://www-personal.umich.edu/~mejn/papers/epjb.pdf Newman's modularity], defined by [[Equation($Q = \sum_s e_{ss} - \left(\sum_r e_{rs}\right)^2 $)]], where [[Equation($e_{rs}$)]] is the fraction of edges which fall between vertices with spin '''s''' and '''r''', can be obtained by the above option (with the possibility of selection of edge weights by the WEIGHT property).

  Example (consider the found-community.xml above):
  {{{
  $ graph-tool --undirected --load found-community.xml --modularity="spin|-"
  # modularity (spin):
  0.535314188562
  }}}


  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  The community graph is obtained by considering all vertices in the same communities as a single vertex, and preserving the connections between them. Example:

  {{{
  $ graph-tool --undirected --load found-sub-community.xml --community-graph="spin|sub-community-graph.dot"
  $ graph-tool --load sub-community-graph.dot --number-of-vertices=- --number-of-edges=-
  # number of vertices:
  16

  # number of edges:
  5888
  }}}

  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  = Community Detection =
  [[T(Complexity| '''unknown''', determined by topology]]


  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.

  {{{
  #!html
  <center>
  }}}
  [[Image(original-community.png)]]
  {{{
  #!html
  </center>
  }}}

  So, we'll try to recover this structure with the following command:

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}

  So, with those parameters the algorithm converged to 4 spins (communities). Below are the histories of the number of spins by iteration and temperature.

  {{{
  #!html
  <center>
  }}}
  [[Image(comm-history-iter.png)]] [[Image(comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And below is how the detected community structure looks like:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-community.png)]]
  {{{
  #!html
  </center>
  }}}

  === Sub-communities ===

  To find sub-communities we must vary the parameter [[Equation($\gamma$)]]. Below are the results with [[Equation($\gamma=2.22$)]].

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|g=2.22,N=5000,Tmin=0.5,Tmax=1.5,corr_type=uncorrelated,seed=43,verbose,history=sub-comm-history-uncorr" \
    --save found-sub-community.xml
  4999 of 5000 (100%) temperature:            0.5 spins: 16 energy levels:  512
  }}}

  The histories:

  {{{
  #!html
  <center>
  }}}
  [[Image(sub-comm-history-iter.png)]] [[Image(sub-comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And the detected structure:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-sub-community.png)]]
  {{{
  #!html
  </center>
  }}}

  One vertex was apparently wrongly detected. However, this is more likely due to random deviations in the graph construction process. For denser graphs, it should be more robust.

  == Modularity ==
  [[T(Complexity|'''O(<k>V+E)''')]]

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  Given a specific graph partition specified by PROPERTY, [http://www-personal.umich.edu/~mejn/papers/epjb.pdf Newman's modularity], defined by [[Equation($Q = \sum_s e_{ss} - \left(\sum_r e_{rs}\right)^2 $)]], where [[Equation($e_{rs}$)]] is the fraction of edges which fall between vertices with spin '''s''' and '''r''', can be obtained by the above option (with the possibility of selection of edge weights by the WEIGHT property).

  Example (consider the found-community.xml above):
  {{{
  $ graph-tool --undirected --load found-community.xml --modularity="spin|-"
  # modularity (spin):
  0.535314188562
  }}}


  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  The community graph is obtained by considering all vertices in the same communities as a single vertex, and preserving the connections between them. Example:

  {{{
  $ graph-tool --undirected --load found-sub-community.xml --community-graph="spin|sub-community-graph.dot"
  $ graph-tool --load sub-community-graph.dot --number-of-vertices=- --number-of-edges=-
  # number of vertices:
  16

  # number of edges:
  5888
  }}}

  With parallel edges removed, the community graph looks like this:


  {{{
  #!html
  <center>
  }}}
  [[Image(sub-community-graph.png)]]
  {{{
  #!html
  </center>
  }}}


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  = Community Detection =
  [[T(Complexity| '''unknown''', determined by topology)]]


  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.

  {{{
  #!html
  <center>
  }}}
  [[Image(original-community.png)]]
  {{{
  #!html
  </center>
  }}}

  So, we'll try to recover this structure with the following command:

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}

  So, with those parameters the algorithm converged to 4 spins (communities). Below are the histories of the number of spins by iteration and temperature.

  {{{
  #!html
  <center>
  }}}
  [[Image(comm-history-iter.png)]] [[Image(comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And below is how the detected community structure looks like:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-community.png)]]
  {{{
  #!html
  </center>
  }}}

  === Sub-communities ===

  To find sub-communities we must vary the parameter [[Equation($\gamma$)]]. Below are the results with [[Equation($\gamma=2.22$)]].

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|g=2.22,N=5000,Tmin=0.5,Tmax=1.5,corr_type=uncorrelated,seed=43,verbose,history=sub-comm-history-uncorr" \
    --save found-sub-community.xml
  4999 of 5000 (100%) temperature:            0.5 spins: 16 energy levels:  512
  }}}

  The histories:

  {{{
  #!html
  <center>
  }}}
  [[Image(sub-comm-history-iter.png)]] [[Image(sub-comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And the detected structure:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-sub-community.png)]]
  {{{
  #!html
  </center>
  }}}

  One vertex was apparently wrongly detected. However, this is more likely due to random deviations in the graph construction process. For denser graphs, it should be more robust.

  == Modularity ==
  [[T(Complexity|'''O(<k>V+E)''')]]

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  Given a specific graph partition specified by PROPERTY, [http://www-personal.umich.edu/~mejn/papers/epjb.pdf Newman's modularity], defined by [[Equation($Q = \sum_s e_{ss}-\left(\sum_r e_{rs}\right)^2$)]], where [[Equation($e_{rs}$)]] is the fraction of edges which fall between vertices with spin '''s''' and '''r''', can be obtained by the above option (with the possibility of selection of edge weights by the WEIGHT property).

  Example (consider the found-community.xml above):
  {{{
  $ graph-tool --undirected --load found-community.xml --modularity="spin|-"
  # modularity (spin):
  0.535314188562
  }}}


  == Community Graph ==

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  The community graph is obtained by considering all vertices in the same communities as a single vertex, and preserving the connections between them. Example:

  {{{
  $ graph-tool --undirected --load found-sub-community.xml --community-graph="spin|sub-community-graph.dot"
  $ graph-tool --load sub-community-graph.dot --number-of-vertices=- --number-of-edges=-
  # number of vertices:
  16

  # number of edges:
  5888
  }}}

  With parallel edges removed, the community graph looks like this:


  {{{
  #!html
  <center>
  }}}
  [[Image(sub-community-graph.png)]]
  {{{
  #!html
  </center>
  }}}

  It's close to a complete graph, and no further community structure can be seen.


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  = Community Detection =
  [[T(Complexity| '''unknown''', determined by topology)]]


  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.

  {{{
  #!html
  <center>
  }}}
  [[Image(original-community.png)]]
  {{{
  #!html
  </center>
  }}}

  So, we'll try to recover this structure with the following command:

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}

  So, with those parameters the algorithm converged to 4 spins (communities). Below are the histories of the number of spins by iteration and temperature.

  {{{
  #!html
  <center>
  }}}
  [[Image(comm-history-iter.png)]] [[Image(comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And below is how the detected community structure looks like:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-community.png)]]
  {{{
  #!html
  </center>
  }}}

  === Sub-communities ===

  To find sub-communities we must vary the parameter [[Equation($\gamma$)]]. Below are the results with [[Equation($\gamma=2.22$)]].

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|g=2.22,N=5000,Tmin=0.5,Tmax=1.5,corr_type=uncorrelated,seed=43,verbose,history=sub-comm-history-uncorr" \
    --save found-sub-community.xml
  4999 of 5000 (100%) temperature:            0.5 spins: 16 energy levels:  512
  }}}

  The histories:

  {{{
  #!html
  <center>
  }}}
  [[Image(sub-comm-history-iter.png)]] [[Image(sub-comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And the detected structure:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-sub-community.png)]]
  {{{
  #!html
  </center>
  }}}

  One vertex was apparently wrongly detected. However, this is more likely due to random deviations in the graph construction process. For denser graphs, it should be more robust.

  == Modularity ==
  [[T(Complexity|'''O(<k>V+E)''')]]

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  Given a specific graph partition specified by PROPERTY, [http://www-personal.umich.edu/~mejn/papers/epjb.pdf Newman's modularity], defined by [[Equation($Q = \sum_s e_{ss}-\left(\sum_r e_{rs}\right)^2$)]], where [[Equation($e_{rs}$)]] is the fraction of edges which fall between vertices with spin '''s''' and '''r''', can be obtained by the above option (with the possibility of selection of edge weights by the WEIGHT property).

  Example (consider the found-community.xml above):
  {{{
  $ graph-tool --undirected --load found-community.xml --modularity="spin|-"
  # modularity (spin):
  0.535314188562
  }}}


  == Community Graph ==
  [[P(Complexity|'''O(V+E)''')]]

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  The community graph is obtained by considering all vertices in the same communities as a single vertex, and preserving the connections between them. Example:

  {{{
  $ graph-tool --undirected --load found-sub-community.xml --community-graph="spin|sub-community-graph.dot"
  $ graph-tool --load sub-community-graph.dot --number-of-vertices=- --number-of-edges=-
  # number of vertices:
  16

  # number of edges:
  5888
  }}}

  With parallel edges removed, the community graph looks like this:


  {{{
  #!html
  <center>
  }}}
  [[Image(sub-community-graph.png)]]
  {{{
  #!html
  </center>
  }}}

  It's close to a complete graph, and no further community structure can be seen.


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  = Community Detection =
  [[T(Complexity| '''unknown''', determined by topology)]]


  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.

  {{{
  #!html
  <center>
  }}}
  [[Image(original-community.png)]]
  {{{
  #!html
  </center>
  }}}

  So, we'll try to recover this structure with the following command:

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}

  So, with those parameters the algorithm converged to 4 spins (communities). Below are the histories of the number of spins by iteration and temperature.

  {{{
  #!html
  <center>
  }}}
  [[Image(comm-history-iter.png)]] [[Image(comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And below is how the detected community structure looks like:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-community.png)]]
  {{{
  #!html
  </center>
  }}}

  === Sub-communities ===

  To find sub-communities we must vary the parameter [[Equation($\gamma$)]]. Below are the results with [[Equation($\gamma=2.22$)]].

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|g=2.22,N=5000,Tmin=0.5,Tmax=1.5,corr_type=uncorrelated,seed=43,verbose,history=sub-comm-history-uncorr" \
    --save found-sub-community.xml
  4999 of 5000 (100%) temperature:            0.5 spins: 16 energy levels:  512
  }}}

  The histories:

  {{{
  #!html
  <center>
  }}}
  [[Image(sub-comm-history-iter.png)]] [[Image(sub-comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And the detected structure:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-sub-community.png)]]
  {{{
  #!html
  </center>
  }}}

  One vertex was apparently wrongly detected. However, this is more likely due to random deviations in the graph construction process. For denser graphs, it should be more robust.

  == Modularity ==
  [[T(Complexity|'''O(<k>V+E)''')]]

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  Given a specific graph partition specified by PROPERTY, [http://www-personal.umich.edu/~mejn/papers/epjb.pdf Newman's modularity], defined by [[Equation($Q = \sum_s e_{ss}-\left(\sum_r e_{rs}\right)^2$)]], where [[Equation($e_{rs}$)]] is the fraction of edges which fall between vertices with spin '''s''' and '''r''', can be obtained by the above option (with the possibility of selection of edge weights by the WEIGHT property).

  Example (consider the found-community.xml above):
  {{{
  $ graph-tool --undirected --load found-community.xml --modularity="spin|-"
  # modularity (spin):
  0.535314188562
  }}}


  == Community Graph ==
  [[T(Complexity|'''O(V+E)''')]]

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  The community graph is obtained by considering all vertices in the same communities as a single vertex, and preserving the connections between them. Example:

  {{{
  $ graph-tool --undirected --load found-sub-community.xml --community-graph="spin|sub-community-graph.dot"
  $ graph-tool --load sub-community-graph.dot --number-of-vertices=- --number-of-edges=-
  # number of vertices:
  16

  # number of edges:
  5888
  }}}

  With parallel edges removed, the community graph looks like this:


  {{{
  #!html
  <center>
  }}}
  [[Image(sub-community-graph.png)]]
  {{{
  #!html
  </center>
  }}}

  It's close to a complete graph, and no further community structure can be seen.


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  = Community Detection =
  [[T(Complexity| '''unknown''', determined by topology)]]


  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.

  {{{
  #!html
  <center>
  }}}
  [[Image(original-community.png)]]
  {{{
  #!html
  </center>
  }}}

  So, we'll try to recover this structure with the following command:

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}

  So, with those parameters the algorithm converged to 4 spins (communities). Below are the histories of the number of spins by iteration and temperature.

  {{{
  #!html
  <center>
  }}}
  [[Image(comm-history-iter.png)]] [[Image(comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And below is how the detected community structure looks like:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-community.png)]]
  {{{
  #!html
  </center>
  }}}

  === Sub-communities ===

  To find sub-communities we must vary the parameter [[Equation($\gamma$)]]. Below are the results with [[Equation($\gamma=2.22$)]].

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|g=2.22,N=5000,Tmin=0.5,Tmax=1.5,corr_type=uncorrelated,seed=43,verbose,history=sub-comm-history-uncorr" \
    --save found-sub-community.xml
  4999 of 5000 (100%) temperature:            0.5 spins: 16 energy levels:  512
  }}}

  The histories:

  {{{
  #!html
  <center>
  }}}
  [[Image(sub-comm-history-iter.png)]] [[Image(sub-comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And the detected structure:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-sub-community.png)]]
  {{{
  #!html
  </center>
  }}}

  One vertex was apparently wrongly detected. However, this is more likely due to random deviations in the graph construction process. For denser graphs, it should be more robust.

  == Modularity ==
  [[T(Complexity|'''O(<k>V+E)''')]]

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  Given a specific graph partition specified by PROPERTY, [http://www-personal.umich.edu/~mejn/papers/epjb.pdf Newman's modularity], defined by [[Equation($Q = \sum_s e_{ss}-\left(\sum_r e_{rs}\right)^2$)]], where [[Equation($e_{rs}$)]] is the fraction of edges which fall between vertices with spin '''s''' and '''r''', can be obtained by the above option (with the possibility of selection of edge weights by the WEIGHT property).

  Example (consider the found-community.xml above):
  {{{
  $ graph-tool --undirected --load found-community.xml --modularity="spin|-"
  # modularity (spin):
  0.535314188562
  }}}


  == Community Graph ==
  [[T(Complexity|'''O(V+E)''')]]

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  The community graph is obtained by considering all vertices in the same community as a single vertex, and preserving the connections between them. Example:

  {{{
  $ graph-tool --undirected --load found-sub-community.xml --community-graph="spin|sub-community-graph.dot"
  $ graph-tool --load sub-community-graph.dot --number-of-vertices=- --number-of-edges=-
  # number of vertices:
  16

  # number of edges:
  5888
  }}}

  With parallel edges removed, the community graph looks like this:


  {{{
  #!html
  <center>
  }}}
  [[Image(sub-community-graph.png)]]
  {{{
  #!html
  </center>
  }}}

  It's close to a complete graph, and no further community structure can be seen.


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  = Community Detection =
  [[T(Complexity| '''unknown''', determined by topology)]]


  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.

  {{{
  #!html
  <center>
  }}}
  [[Image(original-community.png)]]
  {{{
  #!html
  </center>
  }}}

  So, we'll try to recover this structure with the following command:

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}

  So, with those parameters the algorithm converged to 4 spins (communities). Below are the histories of the number of spins by iteration and temperature.

  {{{
  #!html
  <center>
  }}}
  [[Image(comm-history-iter.png)]] [[Image(comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And below is how the detected community structure looks like:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-community.png)]]
  {{{
  #!html
  </center>
  }}}

  === Sub-communities ===

  To find sub-communities we must vary the parameter [[Equation($\gamma$)]]. Below are the results with [[Equation($\gamma=2.22$)]].

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|g=2.22,N=5000,Tmin=0.5,Tmax=1.5,corr_type=uncorrelated,seed=43,verbose,history=sub-comm-history-uncorr" \
    --save found-sub-community.xml
  4999 of 5000 (100%) temperature:            0.5 spins: 16 energy levels:  512
  }}}

  The histories:

  {{{
  #!html
  <center>
  }}}
  [[Image(sub-comm-history-iter.png)]] [[Image(sub-comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And the detected structure:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-sub-community.png)]]
  {{{
  #!html
  </center>
  }}}

  One vertex was apparently wrongly detected. However, this is more likely due to random deviations in the graph construction process. For denser graphs, it should be more robust.

  -----

  == Modularity ==
  [[T(Complexity|'''O(<k>V+E)''')]]

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  Given a specific graph partition specified by PROPERTY, [http://www-personal.umich.edu/~mejn/papers/epjb.pdf Newman's modularity], defined by [[Equation($Q = \sum_s e_{ss}-\left(\sum_r e_{rs}\right)^2$)]], where [[Equation($e_{rs}$)]] is the fraction of edges which fall between vertices with spin '''s''' and '''r''', can be obtained by the above option (with the possibility of selection of edge weights by the WEIGHT property).

  Example (consider the found-community.xml above):
  {{{
  $ graph-tool --undirected --load found-community.xml --modularity="spin|-"
  # modularity (spin):
  0.535314188562
  }}}

  -------
  == Community Graph ==
  [[T(Complexity|'''O(V+E)''')]]

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  The community graph is obtained by considering all vertices in the same community as a single vertex, and preserving the connections between them. Example:

  {{{
  $ graph-tool --undirected --load found-sub-community.xml --community-graph="spin|sub-community-graph.dot"
  $ graph-tool --load sub-community-graph.dot --number-of-vertices=- --number-of-edges=-
  # number of vertices:
  16

  # number of edges:
  5888
  }}}

  With parallel edges removed, the community graph looks like this:


  {{{
  #!html
  <center>
  }}}
  [[Image(sub-community-graph.png)]]
  {{{
  #!html
  </center>
  }}}

  It's close to a complete graph, and no further community structure can be seen.


name: RandomGraphGeneration
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Random graph generation ==

  graph-tool supports generation of random directed graphs with arbitrary degree distributions, based on the [http://arxiv.org/abs/cond-mat/0007235/ configurational model], with the addition of arbitrary degree correlations. The graph is generated with the "`--correlated-configurational-model`" option, which can take several parameters separated by commas. See the end of this page for a [[ref(Parameter Summary)]].

  === Uncorrelated graphs ===

  It will be described here how to generate uncorrelated directed graphs. For undirected graphs, all that is necessary is to generate a directed graph and then operate on it after calling the "`--undirected`" option. For more details see the [[ref(Generating undirected graphs)]] section.

  ==== Independent and equal in-out distributions ====

  Let's start with a simple uncorrelated graph with Poisson degree distribution, to get our feet wet. There are only two required parameters to generate a graph: The number of vertices and the joint degree distribution. These are specified through the "`N`" and "`inv_pjk_ceil`" options. The "`inv_pjk_ceil`" option takes as parameter, in fact, the __inverse of the cumulative degree distribution__, given a probability "`p`" and an extra random variable "`r`", both in the [0,1[ range. Its syntax is a pair in the form "`(j,k)`", corresponding to the sampled (j,k) pair. Any valid [http://www.python.org python] expression is allowed to generate the pair. If the desired sampling function is too elaborate to be written in a single expression, it can be specified in a file. See [[ref(More elaborate distributions)]] for more details and an example. There are a couple of predefined function inverses for convenience: "`inv_poisson(p,m)`", "`inv_exponential(p,m)`" and "`inv_power_law(p,b)`", where "`m`" is the average of the distribution and "`b`" is the modulus of the power-law exponent.

  So, our example is a degree distribution where both the in- and out-degrees are distributed independently according to a Poisson:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(inv_poisson(p,5),inv_poisson(r,5))\",progress" \
  --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 99744 of 99744 (100%)
  }}}


  The "`progress`" option is used to show the progress of the graph generation on the terminal. The generated graph is then saved in "`graph.xml.bz2`". We can get some measurements out of it to see if things make sense or not:

  {{{
  $ graph-tool --load graph.xml.bz2 --vertex-histogram="in-degree|in-degree-histogram" \
  --vertex-histogram="out-degree|out-degree-histogram" --vertex-histogram="total-degree|total-degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        99744
  scalar assortativity coefficient:       -0.000422       0.003175
  }}}

  Below are plotted the degree distributions and degree correlation obtained with the above command.

  [[Image(degree-poisson.png, nolink)]] [[Image(degree-uncorrelation.png, nolink)]]

  So, things seem to make sense so far.  Let's try with something a little bit less trivial...

  ==== Independent but different in-out distributions ====

  Suppose you want different in- and out-degree distributions, like one exponential, and the other a Poisson:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(inv_exponential(p,5),inv_poisson(r,5))\",progress" \
  --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 99731 of 99731 (100%)
  }}}

  Getting the same measurements...

  {{{
  $ graph-tool --load graph.xml.bz2 --vertex-histogram="in-degree|in-degree-histogram" \
  --vertex-histogram="out-degree|out-degree-histogram" --vertex-histogram="total-degree|total-degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        99731
  scalar assortativity coefficient:       0.003840        0.003188
  }}}

  Below are plotted the degree distributions and degree correlation obtained with the above command.

  [[Image(degree-exp-poisson.png, nolink)]] [[Image(degree-uncorrelation2.png, nolink)]]

  That wasn't really all that complicated. See the following section for something a little bit more interesting.

  ==== More elaborate distributions ====

  Suppose we want some other expression for the degree distribution that we want to specify ourselves, i.e., not a Poisson, an exponential or a power-law. If the expression is very complicated, perhaps the best approach is to use [[ref(Rejection sampling)]]. But you can still sample it "the normal way", if you can obtain the inverse of the cumulative distribution. As a simple example of this, suppose our in-degree distribution is composed of two Poisson distributions with different averages, and the out-degree distribution is an exponential. Our in-degree distribution can be written as such:

  [[Equation(\[p(j)=\frac{e^{-m_1}m_1^j+e^{-m_2}m_2^j}{2j!}\])]]. The cumulative distribution is then [[Equation(\[P(j)=\frac{\Gamma(j+1,m_1) + \Gamma(j+1,m_2)}{2j!}\])]].

  The inverse of the cumulative distribution is the solution of [[Equation(\[\frac{\Gamma(j+1,m_1) + \Gamma(j+1,m_2)}{2j!}-P=0\])]] for [[Equation($j$)]]. We can use "`fsolve`" function from the [http://www.scipy.org scipy] package (which is included automatically if available) to write it as such:
  {{{
  fsolve(lambda j: (gammaincc(j,m1)+gammaincc(j,m2))/2-p, (m1+m2)/2.0)
  }}}

  We can generate the graph with the following command:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000, \
  inv_pjk_ceil=\"(fsolve(lambda j: (gammaincc(j,4)+gammaincc(j,20))/2-p,(12)/2.0)-0.5+1e-11, \
                  inv_exponential(r,12))\",progress" \
  --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 241062 of 241062 (100%)
  }}}

  The "`-0.5+1e-11`" term added above is just to make up for a rounding effect. We can get the same measurements as before,

  {{{
  $ graph-tool --load graph.xml.bz2 --vertex-histogram="in-degree|in-degree-histogram" \
  --vertex-histogram="out-degree|out-degree-histogram" --vertex-histogram="total-degree|total-degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        241062
  scalar assortativity coefficient:       -0.000600       0.002038
  }}}

  [[Image(degree-2poissons.png, nolink)]] [[Image(degree-uncorrelation3.png, nolink)]]

  ==== Combined in- and out-degree distributions ====

  Generating combined, i.e. not independent, in- and out-degree distributions is a little bit more complicated. Here it is described a relatively simple example. Suppose we want to generate the following joint degree distribution, which is the combination of two independent Poisson distributions,

  [[Equation(\[ p(j,k) = \frac{1}{2}\frac{e^{-m_1}m_1^j}{j!}\frac{e^{-m_1}m_1^k}{k!} + \frac{1}{2}\frac{e^{-m_2}m_2^j}{j!}\frac{e^{-m_2}m_2^k}{k!}\])]].

  The cumulative degree distribution is the following,

  [[Equation(\[ P(j,k) = \frac{1}{2}\frac{\Gamma(j+1,m_1)\Gamma(k+1,m_1)}{j!k!} + \frac{1}{2}\frac{\Gamma(j+1,m_2)\Gamma(k+1,m_2)}{j!k!} \])]], which is already complicated to find the inverse (which will be some sort of curve in the jk-plane).

  So in order to sample from this distribution, it will be necessary to write something more complicated than an expression which can be squeezed in the "`inv_pjk_ceil`" option as a single expression. For this reason, it is possible to define the sampling function in a file first, and then tell graph-tool to load it. Here's the definition of "`inv_pjk_ceil`" which will sample from the above distribution, defined in a file called "`joint_poissons.py`":

  {{{
  #!python
  from random import *

  def inv_pjk_ceil(p,r):
      if random() > 0.5:
          return (int(round(inv_poisson(p,4))),int(round(inv_poisson(r,4))))
      else:
          return (int(round(inv_poisson(p,20))),int(round(inv_poisson(r,20))))
  }}}

  This can be any valid python program that defines the function "`inv_pjk_ceil(p,r)`". This way it is possible to implement just about any sampling routine. With this file in place, the graph can be generated with the following command

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"file:joint_poissons.py\",progress" \
  --save graph4.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 240456 of 240456 (100%)
  }}}

  When the "`inv_pjk_ceil`" parameter begins with "file:", it instructs the program to load it from the specified file. We can then check if everything is correct:
  {{{
  $ graph-tool --load graph4.xml.bz2 --combined-vertex-histogram="in-degree|out-degree|combined-degree-histogram" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-" 
  number of vertices:     20000
  number of edges:        240456
  scalar assortativity coefficient:       0.000398        0.002032
  }}}

  Below are plotted the theoretical and generated joint degree histograms,

  [[Image(joint-poissons-theoretical.png, nolink)]] [[Image(joint-poissons-generated.png, nolink)]]

  Not so bad...

  ==== Generating undirected graphs ====

  Suppose that in the end you just want some undirected graph to work with, and don't want to bother with the in- and out-degrees separately. If you have your desired degree distribution P(k), you just have to generate the graph with a "`inv_pjk_ceil`" as "`(r*inv_p(p), (1-r)*inv_p(p))`", where "`inv_p(p)`" is the inverse of the cumulative degree distribution. This will generate vertices for which the total degree is sampled from P(k) but the in- and out-degrees are uniformly distributed within the constraints of P(k).

  -------

  === Correlated graphs ===

  graph-tool can also generate arbitrarily correlated graphs, as an extension to the [http://arxiv.org/abs/cond-mat/0007235/ configurational model]. 

  {{{
  #!html
  <div class="note">
  }}}
  ==== Important note ====
  Degree correlations are dependent on the degree distribution. That means that not all degree correlations are always possible, given a specific degree distribution. Therefore you must make sure that the degree correlation you're asking the program to generate is actually possible with the given distribution. If it's not, the obtained correlation is obviously not going to match what you asked. And also it must be taken int account that for some types of correlations, even if the correlation itself is possible, it may be required to make averages over several graphs, or very large graphs, in order to obtain the expected correlation more precisely.
  {{{
  #!html
  </div>
  }}}

  ==== Undirected graphs ====

  Let's take the simplest example, when all that is wanted in the end is an undirected graph with some degree correlation. In this case, when all that matters is the total degree of the vertices when it comes to degree correlations, the parameter "`undirected`" should be passed to the "`--correlated-configurational-model`" option.

  Since the degree distribution dictates what kind of correlations are possible, let's try here an homogeneous degree distribution [[Equation(\[P(k)=\frac{1}{100}[k<100]\])]], where all degrees up to 100 are equaly probable. That should give us some room to work with the degree correlation.

  ===== Assortative degree mixing =====

  So, here we'll generate a degree correlation so that vertices of a given type are connected to other vertices of similar type. We must define exactly what correlation we want, and we do this with the correlation function P(j',k'|j,k) which gives the probability that a random edge leaving a vertex with degrees j and k will connect to a vertex with degrees j' and k'. Here we'll define the following,

  [[Equation(\[P(j',k'|j,k)=\frac{e^{-(j+k)}(j+k)^{j'+k'}}{(j'+k')!}\])]], which is a Poisson distribution with average j+k, so that on average vertices will connect with other vertices of the same degree, leading to perfect assortative graph.

  The correlation is passed to the program through the "`inv_corr_ceil`" option, which, similarly to the "`inv_pjk_ceil`" option, it is the inverse of the cumulative of the function defined above. The sintax is also the same as the "`inv_pjk_ceil`" option. We can then generate the graph described above with the following command:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(r*p*100,(1-r)*p*100)\", \
  inv_corr_ceil=\"(r*inv_poisson(p,j+k),(1-r)*inv_poisson(p,j+k))\",undirected,progress" \
  --save graph.xml.bz2 
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 498225 of 498225 (100%)
  }}}

  And now we can check what was generated:

  {{{
  $ graph-tool --load graph.xml.bz2 --undirected --vertex-histogram="total-degree|degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        498225
  scalar assortativity coefficient:       0.926743        0.005064
  }}}

  The assortativity coefficient looks good. Here's the degree histogram and nearest neighbour correlation

  [[Image(uniform-degree-histogram.png, nolink)]] [[Image(degree-correlation-linear.png, nolink)]]

  Looks like it makes sense...

  ===== Disassortative degree mixing =====

  Let's try the other way, i.e., vertices of a given type connecting with the ones which are the most different. Let's define it the following way:

  [[Equation(\[P(j',k'|j,k)=\frac{e^{-(101-(j+k))}(101-(j+k))^{j'+k'}}{(j'+k')!}\])]], which, like above, is a Poisson distribution, but the average degree this time is 101-(j+k), which means that, for instance, on average vertices of degree 100 will connect to vertices of degree 1, and vice versa. So let's try it:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(r*p*100,(1-r)*p*100)\", \
  inv_corr_ceil=\"(r*inv_poisson(p,101-(j+k)),(1-r)*inv_poisson(p,101-(j+k)))\",undirected,progress" \
  --save graph.xml.bz2 
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 503958 of 503958 (100%)
  }}}

  Checking the graph...

  {{{
  $ graph-tool --load graph.xml.bz2 --undirected --vertex-histogram="total-degree|degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        503958
  scalar assortativity coefficient:       -0.284408       0.005967
  }}}

  The assortativity coefficient is negative, which makes sense, but otherwise its absolute value is a little lower than expected with the specified correlation. Below are the degree histogram and neighbour correlation.

  [[Image(uniform-degree-histogram2.png, nolink)]] [[Image(degree-correlation-not-linear.png, nolink)]]

  Oops. What's wrong with the neighbour correlation? Wasn't it supposed to be linear? Well if you remember the [[ref(Important note)]] above, you'll realize that in this case the correlation we asked for is simply not possible. For instance, if all the vertices with degree 100 were connected mostly with vertices of degree 1, it would be necessary to have 100 times more vertices of degree 1 than of degree 100. Since the degree distribution is homogeneous, this is not possible. Let's try again, but this time with a more convenient degree distribution:

  [[Equation(\[P(k)=\frac{2}{100^2}(100-k)[k<100]\])]]

  Generating the graph:
  {{{
  $ graph-tool --correlated-configurational-model="N=20000,\
  inv_pjk_ceil=\"(r*(199-sqrt(199**2 -4*100**2*0.99*p))/2,(1-r)*(199-sqrt(199**2 -4*100**2*0.99*p))/2)\",\
  inv_corr_ceil=\"(r*inv_poisson(p,101-(j+k)),(1-r)*inv_poisson(p,101-(j+k)))\",undirected,progress" \
  --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 330393 of 330393 (100%)
  }}}

  Checking it:
  {{{
  $ graph-tool --load graph.xml.bz2 --undirected --vertex-histogram="total-degree|degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        330393
  scalar assortativity coefficient:       -0.928880       0.005233
  }}}

  The assortativity coefficient is telling a good story. Let's check the rest:

  [[Image(decreasing-degree-histogram.png, nolink)]] [[Image(degree-correlation-linear2.png, nolink)]]

  Looks better.

  --------

  ==== Directed graphs ====

  When dealing with directed graphs, the degree correlations can be more elaborate, since in- and out-degrees can not only be correlated amongst themselves, but also with each other. Here it is shown an example where the in- and out-degrees are homogeneously distributed in the [0,100] range, the in->out correlation is "disassortative", the out->in correlation is "assortative", and everything else is uncorrelated:

  [[Equation(\[P(j',k'|j,k)=\frac{e^{-k}k^{j'}}{j'!} \frac{e^{-(100-j)}(100-j)^{k'}}{k'!}\])]].

  This can be generated with
  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(p*100,r*100)\", \
  inv_corr_ceil=\"(inv_poisson(p,k),inv_poisson(r,100-j+0.001))\",progress"  --save graph.xml.bz2 
  adding vertices: 20000 of 20000 (100%) 
  fixing average degrees: 0 
  adding edges: 1002047 of 1002047 (100%)
  }}}

  The "`0.001`" above is just a little ''ad hoc'' "correction" for a problem when calculating the inverse of a Poisson with average zero. We can then, as usual, measure the correlations:

  {{{
  $ graph-tool --load graph.xml.bz2 --vertex-histogram="in-degree|in-degree-histogram" \
  --vertex-histogram="out-degree|out-degree-histogram"  \
  --average-nearest-neighbours-correlation="in-degree|in-degree|in-degree-correlation"  \
  --average-nearest-neighbours-correlation="out-degree|out-degree|out-degree-correlation" \
  --average-nearest-neighbours-correlation="in-degree|out-degree|in-out-degree-correlation"  \
  --average-nearest-neighbours-correlation="out-degree|in-degree|out-in-degree-correlation" \
  --number-of-vertices=- --number-of-edges=-
  }}}

  Below are the degree distributions and correlation plots.

  [[Image(degree-hist-directed.png, nolink)]] [[Image(correlation-directed.png, nolink)]]

  The deviations above from the straight line are due to fluctuations of the chosen correlation distribution.

  -------

  == Rejection sampling ==

  If the desired degree distribution or correlation is some very complicated function for which the inverse cannot be easily computed, it is still possible to sample from it using [http://en.wikipedia.org/wiki/Rejection_sampling rejection sampling], which uses an envelope distribution, from which it is easy to obtain a sample. In total, graph-tool needs four parameters: the inverse of the envelope distribution, the envelope distribution g(x), the target distribution f(x), and the upper boundary M for the ratio f(x)/g(x).

  As an illustration, it will be shown here how to generate an uncorrelated undirected graph with a degree distribution which is obtained with rejection sampling. The degree distribution we want to obtain is 

  [[Equation(\[P(k)=\frac{sin\left(\frac{2\pi k}{100}\right)+1}{101} [k\leq 100]\])]].

  For that, we'll use an homogeneous envelope distribution: [[Equation(\[E(k)=\frac{1}{101}[k\leq 100]\])]]. In this case we have that M=2.

  The inverse of envelope distribution, the envelope distribution, the target distribution and the ratio M must be set with the "`inv_pjk_ceil`" (hence the name), "`pjk_ceil`", "`pjk`" and "`pjk_m`" options, respectively. In our case, we can generate the graph with the following command:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(p*r*100,p*(1-r)*100)\",\
  pjk_ceil=\"step(100-(j+k))/(101**2)\", \
  pjk=\"(sin(2*pi*(j+k)/100)+1)/(101**2)\", \
  pjk_m=2,undirected,progress" --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 342247 of 342247 (100%)
  }}}

  We can then obtain the degree histogram and correlation,

  {{{
  $ graph-tool --load graph.xml.bz2 --undirected --vertex-histogram="total-degree|total-degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- 
  number of vertices:     20000
  number of edges:        342247
  }}}

  And the obtained graph looks like the following:

  [[Image(degree-hist-sine.png, nolink)]] [[Image(degree-correlation-sine.png, nolink)]]

  Degree correlations can also be obtained in an analogous fashion, with the "`inv_corr_ceil`", "`corr_ceil`", "`corr`" and "`corr_m`" options.

  --------

  == Parameter Summary ==
   '''`N`'''::
     The number of vertices in the network. This paramenter is mandatory.
   '''pjk'''::
     The joint degree distribution P(j,k). This parameter is only used when doing [[ref(Rejection sampling)]].
   '''pjk_ceil'''::
     This is the ceil function for the '''pjk''' parameter. This parameter is only used when doing [[ref(Rejection sampling)]].
   '''pjk_m'''::
     This is the maximum ratio '''pjk_ceil/pjk'''. Defaults to 1.0. This parameter is only used when doing [[ref(Rejection sampling)]].
   '''inv_pjk_ceil''':: 
     This is the inverse of the cumulative ceil joint degree distribution (or the distribution itself when not doing [[ref(Rejection sampling)]]). This is the parameter which will be more frequently used when setting the joint degree distribution, and is a required parameter. It should be defined as a [http://www.python.org python] expression, defining a tuple of size 2 for the sampled (j,k) degrees. The parameters are two random variables `p` and `r`, uniformly distributed in the range [0,1[.  Some predefined functions which can be used include "`inv_poisson(p,m)`" for an inverse Poisson function with average "`m`", "`inv_exponential(p,m)`" for an inverse exponential distribution with average "`m`", and "`inv_power_law(p,b)`" for an inverse power-law distribution with exponent "`-b`". See above for various examples of how to use this parameter.
   '''corr'''::
     This is the correlation distribution, P(j',k'|j,k), which is the probability that a randomly chosen edge leaving a (j,k) vertex will be connected to a (j',k') vertex. This parameter is only used when doing [[ref(Rejection sampling)]].
    '''corr_ceil'''::
     This is the ceil function for the '''corr''' parameter. This parameter is only used when doing [[ref(Rejection sampling)]].
   '''corr_m'''::
     This is the maximum ratio '''corr_ceil/corr'''. Defaults to 1.0. This parameter is only used when doing [[ref(Rejection sampling)]].
   '''inv_corr_ceil'''::
     This is the inverse of the cumulative ceil correlation distribution (or the distribution itself if not doing [[ref(Rejection sampling)]]). The available variables are `j` and `k`, for the in- and out-degree of the origin vertex, and two random variables `p` and `r`. This defaults to the uncorrelated case "`ceil=pjk(j,k)`". See above for examples.
   '''undirected'''::
     This option controls how edge targets are chosen in respect to their in- and out-degrees. If an edge is supposed to connect to a vertex with (j,k), but no such vertex exists, this options says it should connect randomly to one of the vertices with the closest total degree j+k.
   '''directed'''::
     This option controls how edge targets are chosen in respect to their in and out degrees. If an edge is supposed to connect to a vertex with (j,k), but no such vertex exists, this options says it should connect randomly to one of the vertices which is closest in the jk-plane. This is the default.
   '''progress'''::
     This option displays useful progress information in the terminal.
   '''seed'''::
     This options sets the seed value for the random number generator. It is taken from the computer clock if unspecified.


name: RandomGraphGeneration
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Random graph generation ==

  graph-tool supports generation of random directed graphs with arbitrary degree distributions, based on the [http://arxiv.org/abs/cond-mat/0007235/ configurational model], with the addition of arbitrary degree correlations. The graph is generated with the "`--correlated-configurational-model`" option, which can take several parameters separated by commas. See the end of this page for a [[ref(Parameter Summary)]].

  === Uncorrelated graphs ===

  It will be described here how to generate uncorrelated directed graphs. For undirected graphs, all that is necessary is to generate a directed graph and then operate on it after calling the "`--undirected`" option. For more details see the [[ref(Generating undirected graphs)]] section.

  ==== Independent and equal in-out distributions ====

  Let's start with a simple uncorrelated graph with Poisson degree distribution, to get our feet wet. There are only two required parameters to generate a graph: The number of vertices and the joint degree distribution. These are specified through the "`N`" and "`inv_pjk_ceil`" options. The "`inv_pjk_ceil`" option takes as parameter, in fact, the __inverse of the cumulative degree distribution__, given a probability "`p`" and an extra random variable "`r`", both in the [0,1[ range. Its syntax is a pair in the form "`(j,k)`", corresponding to the sampled (j,k) pair. Any valid [http://www.python.org python] expression is allowed to generate the pair. If the desired sampling function is too elaborate to be written in a single expression, it can be specified in a file. See [[ref(More elaborate distributions)]] for more details and an example. There are a couple of predefined function inverses for convenience: "`inv_poisson(p,m)`", "`inv_exponential(p,m)`" and "`inv_power_law(p,b)`", where "`m`" is the average of the distribution and "`b`" is the modulus of the power-law exponent.

  So, our example is a degree distribution where both the in- and out-degrees are distributed independently according to a Poisson:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(inv_poisson(p,5),inv_poisson(r,5))\",progress" \
  --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 99744 of 99744 (100%)
  }}}


  The "`progress`" option is used to show the progress of the graph generation on the terminal. The generated graph is then saved in "`graph.xml.bz2`". We can get some measurements out of it to see if things make sense or not:

  {{{
  $ graph-tool --load graph.xml.bz2 --vertex-histogram="in-degree|in-degree-histogram" \
  --vertex-histogram="out-degree|out-degree-histogram" --vertex-histogram="total-degree|total-degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        99744
  scalar assortativity coefficient:       -0.000422       0.003175
  }}}

  Below are plotted the degree distributions and degree correlation obtained with the above command.

  [[Image(degree-poisson.png, nolink)]] [[Image(degree-uncorrelation.png, nolink)]]

  So, things seem to make sense so far.  Let's try with something a little bit less trivial...

  ==== Independent but different in-out distributions ====

  Suppose you want different in- and out-degree distributions, like one exponential, and the other a Poisson:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(inv_exponential(p,5),inv_poisson(r,5))\",progress" \
  --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 99731 of 99731 (100%)
  }}}

  Getting the same measurements...

  {{{
  $ graph-tool --load graph.xml.bz2 --vertex-histogram="in-degree|in-degree-histogram" \
  --vertex-histogram="out-degree|out-degree-histogram" --vertex-histogram="total-degree|total-degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        99731
  scalar assortativity coefficient:       0.003840        0.003188
  }}}

  Below are plotted the degree distributions and degree correlation obtained with the above command.

  [[Image(degree-exp-poisson.png, nolink)]] [[Image(degree-uncorrelation2.png, nolink)]]

  That wasn't really all that complicated. See the following section for something a little bit more interesting.

  ==== More elaborate distributions ====

  Suppose we want some other expression for the degree distribution that we want to specify ourselves, i.e., not a Poisson, an exponential or a power-law. If the expression is very complicated, perhaps the best approach is to use [[ref(Rejection sampling)]]. But you can still sample it "the normal way", if you can obtain the inverse of the cumulative distribution. As a simple example of this, suppose our in-degree distribution is composed of two Poisson distributions with different averages, and the out-degree distribution is an exponential. Our in-degree distribution can be written as such:

  [[Equation(\[p(j)=\frac{e^{-m_1}m_1^j+e^{-m_2}m_2^j}{2j!}\])]]. The cumulative distribution is then [[Equation(\[P(j)=\frac{\Gamma(j+1,m_1) + \Gamma(j+1,m_2)}{2j!}\])]].

  The inverse of the cumulative distribution is the solution of [[Equation(\[\frac{\Gamma(j+1,m_1) + \Gamma(j+1,m_2)}{2j!}-P=0\])]] for [[Equation($j$)]]. We can use "`fsolve`" function from the [http://www.scipy.org scipy] package (which is included automatically if available) to write it as such:
  {{{
  fsolve(lambda j: (gammaincc(j,m1)+gammaincc(j,m2))/2-p, (m1+m2)/2.0)
  }}}

  We can generate the graph with the following command:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000, \
  inv_pjk_ceil=\"(fsolve(lambda j: (gammaincc(j,4)+gammaincc(j,20))/2-p,(12)/2.0)-0.5+1e-11, \
                  inv_exponential(r,12))\",progress" \
  --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 241062 of 241062 (100%)
  }}}

  The "`-0.5+1e-11`" term added above is just to make up for a rounding effect. We can get the same measurements as before,

  {{{
  $ graph-tool --load graph.xml.bz2 --vertex-histogram="in-degree|in-degree-histogram" \
  --vertex-histogram="out-degree|out-degree-histogram" --vertex-histogram="total-degree|total-degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        241062
  scalar assortativity coefficient:       -0.000600       0.002038
  }}}

  [[Image(degree-2poissons.png, nolink)]] [[Image(degree-uncorrelation3.png, nolink)]]

  ==== Combined in- and out-degree distributions ====

  Generating combined, i.e. not independent, in- and out-degree distributions is a little bit more complicated. Here it is described a relatively simple example. Suppose we want to generate the following joint degree distribution, which is the combination of two independent Poisson distributions,

  [[Equation(\[ p(j,k) = \frac{1}{2}\frac{e^{-m_1}m_1^j}{j!}\frac{e^{-m_1}m_1^k}{k!} + \frac{1}{2}\frac{e^{-m_2}m_2^j}{j!}\frac{e^{-m_2}m_2^k}{k!}\])]].

  The cumulative degree distribution is the following,

  [[Equation(\[ P(j,k) = \frac{1}{2}\frac{\Gamma(j+1,m_1)\Gamma(k+1,m_1)}{j!k!} + \frac{1}{2}\frac{\Gamma(j+1,m_2)\Gamma(k+1,m_2)}{j!k!} \])]], which is already complicated to find the inverse (which will be some sort of curve in the jk-plane).

  So in order to sample from this distribution, it will be necessary to write something more complicated than an expression which can be squeezed in the "`inv_pjk_ceil`" option as a single expression. For this reason, it is possible to define the sampling function in a file first, and then tell graph-tool to load it. Here's the definition of "`inv_pjk_ceil`" which will sample from the above distribution, defined in a file called "`joint_poissons.py`":

  {{{
  #!python
  from random import *

  def inv_pjk_ceil(p,r):
      if random() > 0.5:
          return (int(round(inv_poisson(p,4))),int(round(inv_poisson(r,4))))
      else:
          return (int(round(inv_poisson(p,20))),int(round(inv_poisson(r,20))))
  }}}

  This can be any valid python program that defines the function "`inv_pjk_ceil(p,r)`". This way it is possible to implement just about any sampling routine. With this file in place, the graph can be generated with the following command

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"file:joint_poissons.py\",progress" \
  --save graph4.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 240456 of 240456 (100%)
  }}}

  When the "`inv_pjk_ceil`" parameter begins with "file:", it instructs the program to load it from the specified file. We can then check if everything is correct:
  {{{
  $ graph-tool --load graph4.xml.bz2 --combined-vertex-histogram="in-degree|out-degree|combined-degree-histogram" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-" 
  number of vertices:     20000
  number of edges:        240456
  scalar assortativity coefficient:       0.000398        0.002032
  }}}

  Below are plotted the theoretical and generated joint degree histograms,

  [[Image(joint-poissons-theoretical.png, nolink)]] [[Image(joint-poissons-generated.png, nolink)]]

  Not so bad...

  ==== Generating undirected graphs ====

  Suppose that in the end you just want some undirected graph to work with, and don't want to bother with the in- and out-degrees separately. If you have your desired degree distribution P(k), you just have to generate the graph with a "`inv_pjk_ceil`" as "`(r*inv_p(p), (1-r)*inv_p(p))`", where "`inv_p(p)`" is the inverse of the cumulative degree distribution. This will generate vertices for which the total degree is sampled from P(k) but the in- and out-degrees are uniformly distributed within the constraints of P(k).

  -------

  === Correlated graphs ===

  graph-tool can also generate arbitrarily correlated graphs, as an extension to the [http://arxiv.org/abs/cond-mat/0007235/ configurational model]. 

  {{{
  #!html
  <div class="note">
  }}}
  ==== Important note ====
  Degree correlations are dependent on the degree distribution. That means that not all degree correlations are always possible, given a specific degree distribution. Therefore you must make sure that the degree correlation you're asking the program to generate is actually possible with the given distribution. If it's not, the obtained correlation is obviously not going to match what you asked. And also it must be taken int account that for some types of correlations, even if the correlation itself is possible, it may be required to make averages over several graphs, or very large graphs, in order to obtain the expected correlation more precisely.
  {{{
  #!html
  </div>
  }}}

  ==== Undirected graphs ====

  Let's take the simplest example, when all that is wanted in the end is an undirected graph with some degree correlation. In this case, when all that matters is the total degree of the vertices when it comes to degree correlations, the parameter "`undirected`" should be passed to the "`--correlated-configurational-model`" option.

  Since the degree distribution dictates what kind of correlations are possible, let's try here an homogeneous degree distribution [[Equation(\[P(k)=\frac{1}{100}[k<100]\])]], where all degrees up to 100 are equaly probable. That should give us some room to work with the degree correlation.

  ===== Assortative degree mixing =====

  So, here we'll generate a degree correlation so that vertices of a given type are connected to other vertices of similar type. We must define exactly what correlation we want, and we do this with the correlation function P(j',k'|j,k) which gives the probability that a random edge leaving a vertex with degrees j and k will connect to a vertex with degrees j' and k'. Here we'll define the following,

  [[Equation(\[P(j',k'|j,k)=\frac{e^{-(j+k)}(j+k)^{j'+k'}}{(j'+k')!}\])]], which is a Poisson distribution with average j+k, so that on average vertices will connect with other vertices of the same degree, leading to perfect assortative graph.

  The correlation is passed to the program through the "`inv_corr_ceil`" option, which, similarly to the "`inv_pjk_ceil`" option, it is the inverse of the cumulative of the function defined above. The sintax is also the same as the "`inv_pjk_ceil`" option. We can then generate the graph described above with the following command:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(r*p*100,(1-r)*p*100)\", \
  inv_corr_ceil=\"(r*inv_poisson(p,j+k),(1-r)*inv_poisson(p,j+k))\",undirected,progress" \
  --save graph.xml.bz2 
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 498225 of 498225 (100%)
  }}}

  And now we can check what was generated:

  {{{
  $ graph-tool --load graph.xml.bz2 --undirected --vertex-histogram="total-degree|degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        498225
  scalar assortativity coefficient:       0.926743        0.005064
  }}}

  The assortativity coefficient looks good. Here's the degree histogram and nearest neighbour correlation

  [[Image(uniform-degree-histogram.png, nolink)]] [[Image(degree-correlation-linear.png, nolink)]]

  Looks like it makes sense...

  ===== Disassortative degree mixing =====

  Let's try the other way, i.e., vertices of a given type connecting with the ones which are the most different. Let's define it the following way:

  [[Equation(\[P(j',k'|j,k)=\frac{e^{-(101-(j+k))}(101-(j+k))^{j'+k'}}{(j'+k')!}\])]], which, like above, is a Poisson distribution, but the average degree this time is 101-(j+k), which means that, for instance, on average vertices of degree 100 will connect to vertices of degree 1, and vice versa. So let's try it:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(r*p*100,(1-r)*p*100)\", \
  inv_corr_ceil=\"(r*inv_poisson(p,101-(j+k)),(1-r)*inv_poisson(p,101-(j+k)))\",undirected,progress" \
  --save graph.xml.bz2 
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 503958 of 503958 (100%)
  }}}

  Checking the graph...

  {{{
  $ graph-tool --load graph.xml.bz2 --undirected --vertex-histogram="total-degree|degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        503958
  scalar assortativity coefficient:       -0.284408       0.005967
  }}}

  The assortativity coefficient is negative, which makes sense, but otherwise its absolute value is a little lower than expected with the specified correlation. Below are the degree histogram and neighbour correlation.

  [[Image(uniform-degree-histogram2.png, nolink)]] [[Image(degree-correlation-not-linear.png, nolink)]]

  Oops. What's wrong with the neighbour correlation? Wasn't it supposed to be linear? Well if you remember the [[ref(Important note)]] above, you'll realize that in this case the correlation we asked for is simply not possible. For instance, if all the vertices with degree 100 were connected mostly with vertices of degree 1, it would be necessary to have 100 times more vertices of degree 1 than of degree 100. Since the degree distribution is homogeneous, this is not possible. Let's try again, but this time with a more convenient degree distribution:

  [[Equation(\[P(k)=\frac{2}{100^2}(100-k)[k<100]\])]]

  Generating the graph:
  {{{
  $ graph-tool --correlated-configurational-model="N=20000,\
  inv_pjk_ceil=\"(r*(199-sqrt(199**2 -4*100**2*0.99*p))/2,(1-r)*(199-sqrt(199**2 -4*100**2*0.99*p))/2)\",\
  inv_corr_ceil=\"(r*inv_poisson(p,101-(j+k)),(1-r)*inv_poisson(p,101-(j+k)))\",undirected,progress" \
  --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 330393 of 330393 (100%)
  }}}

  Checking it:
  {{{
  $ graph-tool --load graph.xml.bz2 --undirected --vertex-histogram="total-degree|degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- --scalar-assortativity-coefficient="total-degree|-"
  number of vertices:     20000
  number of edges:        330393
  scalar assortativity coefficient:       -0.928880       0.005233
  }}}

  The assortativity coefficient is telling a good story. Let's check the rest:

  [[Image(decreasing-degree-histogram.png, nolink)]] [[Image(degree-correlation-linear2.png, nolink)]]

  Looks better.

  --------

  ==== Directed graphs ====

  When dealing with directed graphs, the degree correlations can be more elaborate, since in- and out-degrees can not only be correlated amongst themselves, but also with each other. Here it is shown an example where the in- and out-degrees are homogeneously distributed in the [0,100] range, the in->out correlation is "disassortative", the out->in correlation is "assortative", and everything else is uncorrelated:

  [[Equation(\[P(j',k'|j,k)=\frac{e^{-k}k^{j'}}{j'!} \frac{e^{-(100-j)}(100-j)^{k'}}{k'!}\])]].

  This can be generated with
  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(p*100,r*100)\", \
  inv_corr_ceil=\"(inv_poisson(p,k),inv_poisson(r,100-j+0.001))\",progress"  --save graph.xml.bz2 
  adding vertices: 20000 of 20000 (100%) 
  fixing average degrees: 0 
  adding edges: 1002047 of 1002047 (100%)
  }}}

  The "`0.001`" above is just a little ''ad hoc'' "correction" for a problem when calculating the inverse of a Poisson with average zero. We can then, as usual, measure the correlations:

  {{{
  $ graph-tool --load graph.xml.bz2 --vertex-histogram="in-degree|in-degree-histogram" \
  --vertex-histogram="out-degree|out-degree-histogram"  \
  --average-nearest-neighbours-correlation="in-degree|in-degree|in-degree-correlation"  \
  --average-nearest-neighbours-correlation="out-degree|out-degree|out-degree-correlation" \
  --average-nearest-neighbours-correlation="in-degree|out-degree|in-out-degree-correlation"  \
  --average-nearest-neighbours-correlation="out-degree|in-degree|out-in-degree-correlation" \
  --number-of-vertices=- --number-of-edges=-
  }}}

  Below are the degree distributions and correlation plots.

  [[Image(degree-hist-directed.png, nolink)]] [[Image(correlation-directed.png, nolink)]]

  The deviations above from the straight line are due to fluctuations of the chosen correlation distribution.

  -------

  === Rejection sampling ===

  If the desired degree distribution or correlation is some very complicated function for which the inverse cannot be easily computed, it is still possible to sample from it using [http://en.wikipedia.org/wiki/Rejection_sampling rejection sampling], which uses an envelope distribution, from which it is easy to obtain a sample. In total, graph-tool needs four parameters: the inverse of the envelope distribution, the envelope distribution g(x), the target distribution f(x), and the upper boundary M for the ratio f(x)/g(x).

  As an illustration, it will be shown here how to generate an uncorrelated undirected graph with a degree distribution which is obtained with rejection sampling. The degree distribution we want to obtain is 

  [[Equation(\[P(k)=\frac{sin\left(\frac{2\pi k}{100}\right)+1}{101} [k\leq 100]\])]].

  For that, we'll use an homogeneous envelope distribution: [[Equation(\[E(k)=\frac{1}{101}[k\leq 100]\])]]. In this case we have that M=2.

  The inverse of envelope distribution, the envelope distribution, the target distribution and the ratio M must be set with the "`inv_pjk_ceil`" (hence the name), "`pjk_ceil`", "`pjk`" and "`pjk_m`" options, respectively. In our case, we can generate the graph with the following command:

  {{{
  $ graph-tool --correlated-configurational-model="N=20000,inv_pjk_ceil=\"(p*r*100,p*(1-r)*100)\",\
  pjk_ceil=\"step(100-(j+k))/(101**2)\", \
  pjk=\"(sin(2*pi*(j+k)/100)+1)/(101**2)\", \
  pjk_m=2,undirected,progress" --save graph.xml.bz2
  adding vertices: 20000 of 20000 (100%)
  fixing average degrees: 0
  adding edges: 342247 of 342247 (100%)
  }}}

  We can then obtain the degree histogram and correlation,

  {{{
  $ graph-tool --load graph.xml.bz2 --undirected --vertex-histogram="total-degree|total-degree-histogram" \
  --average-nearest-neighbours-correlation="total-degree|total-degree|total-degree-correlation" \
  --number-of-vertices=- --number-of-edges=- 
  number of vertices:     20000
  number of edges:        342247
  }}}

  And the obtained graph looks like the following:

  [[Image(degree-hist-sine.png, nolink)]] [[Image(degree-correlation-sine.png, nolink)]]

  Degree correlations can also be obtained in an analogous fashion, with the "`inv_corr_ceil`", "`corr_ceil`", "`corr`" and "`corr_m`" options.

  --------

  === Parameter Summary ===
   '''`N`'''::
     The number of vertices in the network. This paramenter is mandatory.
   '''pjk'''::
     The joint degree distribution P(j,k). This parameter is only used when doing [[ref(Rejection sampling)]].
   '''pjk_ceil'''::
     This is the ceil function for the '''pjk''' parameter. This parameter is only used when doing [[ref(Rejection sampling)]].
   '''pjk_m'''::
     This is the maximum ratio '''pjk_ceil/pjk'''. Defaults to 1.0. This parameter is only used when doing [[ref(Rejection sampling)]].
   '''inv_pjk_ceil''':: 
     This is the inverse of the cumulative ceil joint degree distribution (or the distribution itself when not doing [[ref(Rejection sampling)]]). This is the parameter which will be more frequently used when setting the joint degree distribution, and is a required parameter. It should be defined as a [http://www.python.org python] expression, defining a tuple of size 2 for the sampled (j,k) degrees. The parameters are two random variables `p` and `r`, uniformly distributed in the range [0,1[.  Some predefined functions which can be used include "`inv_poisson(p,m)`" for an inverse Poisson function with average "`m`", "`inv_exponential(p,m)`" for an inverse exponential distribution with average "`m`", and "`inv_power_law(p,b)`" for an inverse power-law distribution with exponent "`-b`". See above for various examples of how to use this parameter.
   '''corr'''::
     This is the correlation distribution, P(j',k'|j,k), which is the probability that a randomly chosen edge leaving a (j,k) vertex will be connected to a (j',k') vertex. This parameter is only used when doing [[ref(Rejection sampling)]].
    '''corr_ceil'''::
     This is the ceil function for the '''corr''' parameter. This parameter is only used when doing [[ref(Rejection sampling)]].
   '''corr_m'''::
     This is the maximum ratio '''corr_ceil/corr'''. Defaults to 1.0. This parameter is only used when doing [[ref(Rejection sampling)]].
   '''inv_corr_ceil'''::
     This is the inverse of the cumulative ceil correlation distribution (or the distribution itself if not doing [[ref(Rejection sampling)]]). The available variables are `j` and `k`, for the in- and out-degree of the origin vertex, and two random variables `p` and `r`. This defaults to the uncorrelated case "`ceil=pjk(j,k)`". See above for examples.
   '''undirected'''::
     This option controls how edge targets are chosen in respect to their in- and out-degrees. If an edge is supposed to connect to a vertex with (j,k), but no such vertex exists, this options says it should connect randomly to one of the vertices with the closest total degree j+k.
   '''directed'''::
     This option controls how edge targets are chosen in respect to their in and out degrees. If an edge is supposed to connect to a vertex with (j,k), but no such vertex exists, this options says it should connect randomly to one of the vertices which is closest in the jk-plane. This is the default.
   '''progress'''::
     This option displays useful progress information in the terminal.
   '''seed'''::
     This options sets the seed value for the random number generator. It is taken from the computer clock if unspecified.


name: CommunityDetection
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]

  == Community Detection ==
  [[T(Complexity| '''unknown''', determined by topology)]]


  Option summary:

  {{{
  --community-structure=PROPERTY|OPTIONS
                                      calculate the community structure and
                                      assign it to PROPERTY. Options are: g
                                      (default: 1.0), N (default: 1000), Tmin
                                      (default: 0.01), Tmax (default: 1.0),
                                      spins (default: number of vertices),
                                      corr_type (default: uncorrelated),
                                      weight, seed (default: from clock),
                                      verbose, history.  The value of
                                      corr_type can be 'random',
                                      'uncorrelated' or 'correlated'.
  }}}

  The method of community detection covered here is an implementation of what was proposed in http://arxiv.org/abs/cond-mat/0603718 by Reichardt et al. It consists of a [http://en.wikipedia.org/wiki/Simulated_annealing simulated annealing] algorithm which tries to minimize the following hamiltonian

  [[Equation(\[ \mathcal{H}(\{\sigma\}) = - \sum_{i \noteq j} \left(A_{ij} - \gamma p_{ij}\right) \delta(\sigma_i,\sigma_j) \right) \])]],

  where '''p,,ij,,''' is the probability of vertices '''i''' and '''j''' being connected, which reduces the problem of community detection to finding the ground states of a Potts spin-glass model. It can be [http://arxiv.org/abs/cond-mat/0603718 shown] that minimizing this hamiltonan, with [[Equation($\gamma=1$)]], is equivalent to maximizing Newman's [[ref(Modularity)]]. By increasing the parameter [[Equation($\gamma$)]], it's possible also to find sub-communities. It is possible to select three policies for choosing '''p,,ij,,''' and thus choosing the null model: "random" selects a Erdős-Reyni random graph, "uncorrelated" selects an arbitrary random graph with no vertex-vertex correlations, and "correlated" selects a random graph with average correlation taken from the loaded graph itself. Optionally a weight property can be given by the "weight" option.

  The most important parameters for the algorithm are the initial and final temperatures ("Tmin" and "Tmax"), and total number of iterations ("N"). It normally takes some trial and error to determine the best values for a specific graph. To help with this, the "history" option can be used, which saves to a chosen file the temperature and number of spins per iteration, which can be used to determined whether or not the algorithm converged. Also, the "verbose" option prints the computation status on the terminal.  

  [[T(Note|Previously existing spins|If the spin property already exists before the computation starts, it's not re-sampled at the beginning. This means that it's possible to continue a previous run, if you saved the graph, by setting "Tmax" to the previous "Tmin" value, and using the same spin property.)]]

  Consider the following example. Attached is a file attachment:community.dot, shown below, which is an undirected graph with 256 vertices, divided into 4 communities, each of which is further divided into 4 sub-communities. Each vertex has, on average, 3.75 random connections to the same main community, 3.75 random connection with other vertices which don't belong to the same community, and, in addition, 4 random connections to members of the same sub-community.

  {{{
  #!html
  <center>
  }}}
  [[Image(original-community.png)]]
  {{{
  #!html
  </center>
  }}}

  So, we'll try to recover this structure with the following command:

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|N=2000,Tmin=1.0,Tmax=1.4,corr_type=uncorrelated,seed=42,verbose,history=comm-history" \
    --save found-community.xml
  1999 of 2000 (100%) temperature:              1 spins: 4 energy levels:  1604
  }}}

  So, with those parameters the algorithm converged to 4 spins (communities). Below are the histories of the number of spins by iteration and temperature.

  {{{
  #!html
  <center>
  }}}
  [[Image(comm-history-iter.png)]] [[Image(comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And below is how the detected community structure looks like:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-community.png)]]
  {{{
  #!html
  </center>
  }}}

  ==== Sub-communities ====

  To find sub-communities we must vary the parameter [[Equation($\gamma$)]]. Below are the results with [[Equation($\gamma=2.22$)]].

  {{{
  $ graph-tool --undirected --load community.dot \
    --community-structure="spin|g=2.22,N=5000,Tmin=0.5,Tmax=1.5,corr_type=uncorrelated,seed=43,verbose,history=sub-comm-history-uncorr" \
    --save found-sub-community.xml
  4999 of 5000 (100%) temperature:            0.5 spins: 16 energy levels:  512
  }}}

  The histories:

  {{{
  #!html
  <center>
  }}}
  [[Image(sub-comm-history-iter.png)]] [[Image(sub-comm-history-temp.png)]]
  {{{
  #!html
  </center>
  }}}

  And the detected structure:

  {{{
  #!html
  <center>
  }}}
  [[Image(found-sub-community.png)]]
  {{{
  #!html
  </center>
  }}}

  One vertex was apparently wrongly detected. However, this is more likely due to random deviations in the graph construction process. For denser graphs, it should be more robust.

  -----

  === Modularity ===
  [[T(Complexity|'''O(<k>V+E)''')]]

  {{{
  --modularity=PROPERTY[|WEIGHT]|FILE
                                      calculate the modularity, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  Given a specific graph partition specified by PROPERTY, [http://www-personal.umich.edu/~mejn/papers/epjb.pdf Newman's modularity], defined by [[Equation($Q = \sum_s e_{ss}-\left(\sum_r e_{rs}\right)^2$)]], where [[Equation($e_{rs}$)]] is the fraction of edges which fall between vertices with spin '''s''' and '''r''', can be obtained by the above option (with the possibility of selection of edge weights by the WEIGHT property).

  Example (consider the found-community.xml above):
  {{{
  $ graph-tool --undirected --load found-community.xml --modularity="spin|-"
  # modularity (spin):
  0.535314188562
  }}}

  -------
  === Community Graph ===
  [[T(Complexity|'''O(V+E)''')]]

  {{{
  --community-graph=PROPERTY|FILE[|FORMAT]
                                      obtain the graph of communities, given a
                                      community partition specified by
                                      PROPERTY
  }}}

  The community graph is obtained by considering all vertices in the same community as a single vertex, and preserving the connections between them. Example:

  {{{
  $ graph-tool --undirected --load found-sub-community.xml --community-graph="spin|sub-community-graph.dot"
  $ graph-tool --load sub-community-graph.dot --number-of-vertices=- --number-of-edges=-
  # number of vertices:
  16

  # number of edges:
  5888
  }}}

  With parallel edges removed, the community graph looks like this:


  {{{
  #!html
  <center>
  }}}
  [[Image(sub-community-graph.png)]]
  {{{
  #!html
  </center>
  }}}

  It's close to a complete graph, and no further community structure can be seen.


name: GraphModification
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Graph Modifications ==

  There's a couple of options which change the internally kept graph.

  === Removing Properties ===
  [[T(Complexity|'''O(1)''')]]

  Vertex and edge properties can be removed from the graph with the options "{{{--remove-vertex-property}}}" and "{{{--remove-edge-property}}}", which take the name of the property to be removed as parameter.

  === Vertex and Edge Indexes ===
  [[T(Complexity|'''O(1)''')]]

  Vertices and Edges are identified internally by indexes. Those can be inserted as properties with the options "{{{--insert-vertex-index-property}}}" and "{{{--insert-edge-index-property}}}", which take as argument the name by which the property will be called.

  === Creating and modifying properties ===
  [[T(Complexity|'''O(V)''' or '''O(E)''')]]

  New properties can be created and old ones modified (replaced) the the following options:

  {{{
  --edit-vertex-property=PROPERTY|EXPRESSION                                   edit the selected vertex property
  --edit-edge-property=PROPERTY|EXPRESSION                                     edit the selected edge property
  }}}

  The PROPERTY parameter takes the name of the property which will be created or modified. The EXPRESSION parameter is a python expression which will be evaluated to a "double" value, and assigned to the property. The variables available are the same as with [wiki:GraphFiltering#GenericFiltering Generic Filtering] described above.

  Example:
  {{{
  $ graph-tool --load example.xml --edit-edge-property="sqrt_weight|weight()**0.5" --average-edge-property="weight|-" --average-edge-property="sqrt_weight|-" 
  # average edge property (weight):
  2.550000        1.163373

  # average edge property (sqrt_weight):
  1.299736        0.328003
  }}}

  === Parallel edges removal ===
  [[T(Complexity|'''O(E log(<k>))''')]]

  A multigraph can be converted into a simple graph by labeling the parallel edges with an edge property and then filtering them out. The edges can be labeled with the following option:

  {{{
  --label-parallel-edges=PROPERTY                                     label parallel edges to PROPERTY
  }}}

  This will create (or replace) a property map with name given by PROPERTY, which will have integer values. The parallel edges will be labeled increasingly starting from zero, in a non-specified order. The graph can thus be reduced to a simple graph by filtering out edges with values > 0. See GraphFiltering above.


name: WikiStart
author: count0
ipnr: 201.81.194.239
text:
  = What is graph-tool? =
  [[Image(WikiStartAttachments:small.png, class=floatright, nolink)]] 

  graph-tool is a program to help with statistical analysis of [http://en.wikipedia.org/wiki/Graph_%28mathematics%29 graphs]. Its feature set includes:

   * support for directed and undirected graphs
   * support for arbitrary vertex or edge properties
   * [wiki:GraphFiltering generic filtering] of edges and vertices
   * several statistical measurements:
     * degree (or scalar property) histogram
     * combined degree (or scalar property) histogram
     * vertex-vertex degree (or scalar property) correlation
     * average nearest neighbours degree (or scalar property)
     * vertex-edge-vertex correlation
     * clustering coefficients
     * [wiki:GraphClustering#ExtendedClustering extended clustering coefficient]
     * assortativity coefficient
     * average distance
     * component statistics
     * reciprocity
   * [wiki:CommunityDetection community detection]
   * [wiki:RandomGraphGeneration generation of random graphs] with arbitrary degree distribution and degree correlation
   * [wiki:GraphToolGuide#GraphHistory graph history] measurement based on filtering
   * support for [http://graphml.graphdrawing.org/ graphml] and [http://www.graphviz.org/ dot] file formats
   * and lots more!

  The core algorithms are written in C++, making use of the [http://www.boost.org/libs/graph/doc/ Boost Graph Library], and [http://en.wikipedia.org/wiki/Template_metaprogramming template metaprogramming] techniques, with performace in mind. The command line interface and other outlying code are written in [http://www.python.org python].

  See GraphToolGuide for instructions and examples of how to use the program.

  graph-tool was written by [https://forked.de/bin/view/Main/TiagoPeixoto Tiago de Paula Peixoto] and is [http://www.gnu.org/philosophy/free-sw.html free software], released under the [http://www.gnu.org/copyleft/gpl.html GPL].


name: WikiStart
author: count0
ipnr: 201.81.194.239
text:
  = What is graph-tool? =
  [[Image(WikiStartAttachments:small.png, class=floatright, nolink)]] 

  graph-tool is a program to help with statistical analysis of [http://en.wikipedia.org/wiki/Graph_%28mathematics%29 graphs]. Its feature set includes:

   * support for directed and undirected graphs
   * support for arbitrary vertex or edge properties
   * [wiki:GraphFiltering generic filtering] of edges and vertices
   * several statistical measurements:
     * degree (or scalar property) histogram
     * combined degree (or scalar property) histogram
     * vertex-vertex degree (or scalar property) correlation
     * average nearest neighbours degree (or scalar property)
     * vertex-edge-vertex correlation
     * clustering coefficients
     * [wiki:GraphClustering#ExtendedClustering extended clustering coefficient]
     * assortativity coefficient
     * average distance
     * component statistics
     * reciprocity
   * [wiki:CommunityDetection community detection]
   * [wiki:RandomGraphGeneration generation of random graphs] with arbitrary degree distribution and degree correlation
   * [wiki:GraphToolGuide#GraphHistory graph history] measurement based on filtering
   * support for [http://graphml.graphdrawing.org/ graphml] and [http://www.graphviz.org/ dot] file formats
   * and lots more!

  The core algorithms are written in C++, making use of the [http://www.boost.org/libs/graph/doc/ Boost Graph Library], and [http://en.wikipedia.org/wiki/Template_metaprogramming template metaprogramming] techniques, with performance in mind. The command line interface and other outlying code are written in [http://www.python.org python].

  See GraphToolGuide for instructions and examples of how to use the program.

  graph-tool was written by [https://forked.de/bin/view/Main/TiagoPeixoto Tiago de Paula Peixoto] and is [http://www.gnu.org/philosophy/free-sw.html free software], released under the [http://www.gnu.org/copyleft/gpl.html GPL].


name: WikiStart
author: count0
ipnr: 201.81.194.239
text:
  = What is graph-tool? =
  [[Image(WikiStartAttachments:small.png, class=floatright, nolink)]] 

  graph-tool is a program to help with statistical analysis of [http://en.wikipedia.org/wiki/Graph_%28mathematics%29 graphs]. Its feature set includes:

   * support for directed and undirected graphs
   * support for arbitrary vertex or edge properties
   * [wiki:GraphFiltering generic filtering] of edges and vertices
   * several statistical measurements:
     * degree (or scalar property) histogram
     * combined degree (or scalar property) histogram
     * vertex-vertex degree (or scalar property) correlation
     * average nearest neighbours degree (or scalar property)
     * vertex-edge-vertex correlation
     * clustering coefficients
     * [wiki:GraphClustering#ExtendedClustering extended clustering coefficient]
     * assortativity coefficient
     * average distance
     * component statistics
     * reciprocity
   * [wiki:CommunityDetection community detection]
   * [wiki:RandomGraphGeneration generation of random graphs] with arbitrary degree distribution and degree correlation
   * [wiki:GraphHistory graph history] measurement based on filtering
   * support for [http://graphml.graphdrawing.org/ graphml] and [http://www.graphviz.org/ dot] file formats
   * and lots more!

  The core algorithms are written in C++, making use of the [http://www.boost.org/libs/graph/doc/ Boost Graph Library], and [http://en.wikipedia.org/wiki/Template_metaprogramming template metaprogramming] techniques, with performance in mind. The command line interface and other outlying code are written in [http://www.python.org python].

  See GraphToolGuide for instructions and examples of how to use the program.

  graph-tool was written by [https://forked.de/bin/view/Main/TiagoPeixoto Tiago de Paula Peixoto] and is [http://www.gnu.org/philosophy/free-sw.html free software], released under the [http://www.gnu.org/copyleft/gpl.html GPL].


name: GraphToolDownload
author: count0
ipnr: 201.81.194.239
text:
  = graph-tool Download =

  graph-tool is released under the [http://www.gnu.org/copyleft/gpl.html GPL]. For installation instructions, see the included INSTALL file.

  [[T(Note|Warning: Memory requirements for compilation|graph-tool requires large amounts of RAM (~1 GB) during compilation, because it uses lots of [http://en.wikipedia.org/wiki/Template_metaprogramming template metaprogramming]. The supported compiler, [http://gcc.gnu.org/ GCC], is still not very well optimized for this, which means that even though the program is relatively small (the compiled binary, as of version 1.0, is around 20 MB in size), it will still use up lots of RAM during compilation, specially if optimizations are used (and you do want to use them). See, for instance, GCC bugs [http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29433 29433] and [http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12850 12850]. For this reason, pre-compiled binaries are also provided, so that if you don't have that much RAM, you can still use the program (but you'll still need all the [wiki:GraphToolDownload#Requirements requirements] below).)]]

  == Requirements ==

  You'll need the following in order to build and use graph-tool:

   * [http://gcc.gnu.org/ GCC] 4.1 or above
   * The [http://www.boost.org/ boost] libraries.
   * [http://www.python.org Python] 2.4 or above
   * The [http://expat.sourceforge.net/ expat] library

  graph-tool was tested only on [http://www.gnu.org GNU/Linux] systems, but should also be usable on other systems where the above requirements are available.

  === Optional packages ===
  The following packages, if available, will be used automatically by graph-tool, but are not required:
   * [http://www.scipy.org/ SciPy], for useful mathematical functions
   * [http://psyco.sourceforge.net/ Psyco], for improved performace of python code

  == Stable Releases ==

  [[T(Note|Try the SVN version first|Please consider first downloading the [wiki:GraphToolDownload#LatestDevelopmentSourceCode latest development source code] below, as it will usually be in an usable state, and will contain most bugfixes and new features)]]

  === Latest stable release - 1.0 ===

  ==== Tar source package ====
   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-1.0.tar.bz2 graph-tool-1.0.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-1.0.tar.bz2 graph-tool-1.0.tar.bz2]

  '''Note:''' After compilation, "`make install`" must be run before graph-tool can be used. If you just want to run the program without installing it, you must make sure that the "`libgraph_tool.so`" file (available after compilation in "`src/graph/.libs`") is in the same directory as the "`grap-tool`" executable (or, alternatively, somewhere in the python module path).

  ==== Pre-compiled binaries (i686 only) ====

  This package includes the "`graph-tool`" python executable and the "`libgraph_tool.so`" library, which should be either in the same directory as "`graph-tool`", or in the python module path, for graph-tool to work properly.

   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-1.0-precompiled-i686.tar.bz2 graph-tool-1.0-precompiled-i686.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-1.0-precompiled-i686.tar.bz2 graph-tool-1.0-precompiled-i686.tar.bz2]

  === Previous stable release - 0.9 ===
  0.9 is the first public release. '''Warning:''' This version is considered deprecated.

  ==== Tar source package ====
   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-0.9.tar.bz2 graph-tool-0.9.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-0.9.tar.bz2 graph-tool-0.9.tar.bz2]

  '''Note:''' After compilation, "`make install`" must be run before graph-tool can be used. If you just want to run the program without installing it, you must make sure that the "`libgraph_tool.so`" file (available after compilation in "`src/graph/.libs`") is in the same directory as the "`grap-tool`" executable (or, alternatively, somewhere in the python module path).

  ==== Pre-compiled binaries (i686 only) ====

  This package includes the "`graph-tool`" python executable and the "`libgraph_tool.so`" library, which should be either in the same directory as "`graph-tool`", or in the python module path, for graph-tool to work properly.

   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-0.9-precompiled-i686.tar.bz2 graph-tool-0.9-precompiled-i686.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-0.9-precompiled-i686.tar.bz2 graph-tool-0.9-precompiled-i686.tar.bz2]

  ----

  == Latest Development Source Code ==

  We use [http://subversion.tigris.org/ Subversion] for source revision control and code sharing.

  The Subversion repository URL for the graph-tool project is at:

    http://svn.forked.de/graph-tool/

  The latest revision can be checked out with the following command:

  {{{
  svn co http://svn.forked.de/graph-tool/trunk graph-tool
  }}}

  Or with encryption:

  {{{
  svn co https://svn.forked.de/graph-tool/trunk graph-tool
  }}}

  For further instructions on how to use Subversion, see [http://svnbook.red-bean.com/book.html The Subversion Book]


name: GraphToolDownload
author: count0
ipnr: 201.81.194.239
text:
  = graph-tool Download =

  graph-tool is released under the [http://www.gnu.org/copyleft/gpl.html GPL]. For installation instructions, see the included INSTALL file.

  [[T(Note|Warning: Memory requirements for compilation|graph-tool requires large amounts of RAM (~1 GB) during compilation, because it uses lots of [http://en.wikipedia.org/wiki/Template_metaprogramming template metaprogramming]. The supported compiler, [http://gcc.gnu.org/ GCC], is still not very well optimized for this, which means that even though the program is relatively small (the compiled binary, as of version 1.0, is around 20 MB in size), it will still use up lots of RAM during compilation, specially if optimizations are used (and you do want to use them). See, for instance, GCC bugs [http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29433 29433] and [http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12850 12850]. For this reason, pre-compiled binaries are also provided, so that if you don't have that much RAM, you can still use the program (but you'll still need all the [wiki:GraphToolDownload#Requirements requirements] below). Also, if you still want to compile your own version, but don't have enough memory, try passing the "`--disable-filtering`" option to the configure script. This will disable some of the filtering functionality of graph-tool, and will save some memory during compilation.)]]

  == Requirements ==

  You'll need the following in order to build and use graph-tool:

   * [http://gcc.gnu.org/ GCC] 4.1 or above
   * The [http://www.boost.org/ boost] libraries.
   * [http://www.python.org Python] 2.4 or above
   * The [http://expat.sourceforge.net/ expat] library

  graph-tool was tested only on [http://www.gnu.org GNU/Linux] systems, but should also be usable on other systems where the above requirements are available.

  === Optional packages ===
  The following packages, if available, will be used automatically by graph-tool, but are not required:
   * [http://www.scipy.org/ SciPy], for useful mathematical functions
   * [http://psyco.sourceforge.net/ Psyco], for improved performace of python code

  == Stable Releases ==

  [[T(Note|Try the SVN version first|Please consider first downloading the [wiki:GraphToolDownload#LatestDevelopmentSourceCode latest development source code] below, as it will usually be in an usable state, and will contain most bugfixes and new features)]]

  === Latest stable release - 1.0 ===

  ==== Tar source package ====
   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-1.0.tar.bz2 graph-tool-1.0.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-1.0.tar.bz2 graph-tool-1.0.tar.bz2]

  '''Note:''' After compilation, "`make install`" must be run before graph-tool can be used. If you just want to run the program without installing it, you must make sure that the "`libgraph_tool.so`" file (available after compilation in "`src/graph/.libs`") is in the same directory as the "`grap-tool`" executable (or, alternatively, somewhere in the python module path).

  ==== Pre-compiled binaries (i686 only) ====

  This package includes the "`graph-tool`" python executable and the "`libgraph_tool.so`" library, which should be either in the same directory as "`graph-tool`", or in the python module path, for graph-tool to work properly.

   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-1.0-precompiled-i686.tar.bz2 graph-tool-1.0-precompiled-i686.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-1.0-precompiled-i686.tar.bz2 graph-tool-1.0-precompiled-i686.tar.bz2]

  === Previous stable release - 0.9 ===
  0.9 was the first public release. '''Warning:''' This version is considered deprecated!

  ==== Tar source package ====
   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-0.9.tar.bz2 graph-tool-0.9.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-0.9.tar.bz2 graph-tool-0.9.tar.bz2]

  '''Note:''' After compilation, "`make install`" must be run before graph-tool can be used. If you just want to run the program without installing it, you must make sure that the "`libgraph_tool.so`" file (available after compilation in "`src/graph/.libs`") is in the same directory as the "`grap-tool`" executable (or, alternatively, somewhere in the python module path).

  ==== Pre-compiled binaries (i686 only) ====

  This package includes the "`graph-tool`" python executable and the "`libgraph_tool.so`" library, which should be either in the same directory as "`graph-tool`", or in the python module path, for graph-tool to work properly.

   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-0.9-precompiled-i686.tar.bz2 graph-tool-0.9-precompiled-i686.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-0.9-precompiled-i686.tar.bz2 graph-tool-0.9-precompiled-i686.tar.bz2]

  ----

  == Latest Development Source Code ==

  We use [http://subversion.tigris.org/ Subversion] for source revision control and code sharing.

  The Subversion repository URL for the graph-tool project is at:

    http://svn.forked.de/graph-tool/

  The latest revision can be checked out with the following command:

  {{{
  svn co http://svn.forked.de/graph-tool/trunk graph-tool
  }}}

  Or with encryption:

  {{{
  svn co https://svn.forked.de/graph-tool/trunk graph-tool
  }}}

  For further instructions on how to use Subversion, see [http://svnbook.red-bean.com/book.html The Subversion Book]


name: GraphFiltering
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Filtering ==

  Graphs can be filtered in several ways. None of them actually modify the internally kept graph, and are of complexity O(1).

  === Directedness ===
  [[T(Complexity| '''O(1)''')]]

  Internally, all graphs in `graph-tool` are directed graphs. But it is possible to treat them easily as undirected with the "{{{--undirected}}}" option. All options after that will operate on a undirected filter of the internal directed graph. The "{{{--directed}}}" option reverts back to the default mode. If you want to load an undirected graph with graph-tool, just use the "{{{--undirected}}}" option before the "{{{--load}}}" option.

  === Edge direction ===
  [[T(Complexity| '''O(1)''')]]

  Directed graphs can have the the edge direction reversed with the "{{{--reverse}}}" option. A second "{{{--reverse}}}" reverts back to the original state.

  === Filtering of vertices or edges ===

  ==== Range filtering ====
  [[T(Complexity| '''O(1)''')]]

  Edges and vertices can be filtered out of the graph based on their properties. The most basic and fastest way of filtering is called "range filtering" and filters out vertices with a scalar property which lays outside a given range. The filtering is controlled with the "{{{--vertex-range-filter}}}" and "{{{--edge-range-filter}}}" options, which takes two parameters separated by "|": the property to be used as filter and the range (two values separated by space). Here's an example using the graph defined in the [wiki:GraphToolGuideDev#Fileformatdescription file format description] section:

  {{{
  $ graph-tool --load example.xml --number-of-edges=-
  number of edges:        8
  $ graph-tool --load example.xml --edge-range-filter="weight|0.6 6.0" --number-of-edges=- --save filtered.dot
  number of edges:        4
  }}}

  The file "{{{filtered.dot}}}" contains (graphical representation on the side):

  {{{
  #!html
  <div style="float: right;">
  }}}
  {{{
  #!graphviz
  digraph G {
  1;
  2;
  3;
  7;
  4;
  5;
  6;
  1->2  [label="1.2"];
  2->3  [label="0.8"];
  5->3  [label="5.5"];
  6->7  [label="2.0"];
  }
  }}}
  {{{
  #!html
  </div>
  }}}

  {{{
  digraph G {
  1;
  2;
  3;
  7;
  4;
  5;
  6;
  1->2  [weight="1.2"];
  2->3  [weight="0.8"];
  5->3  [weight="5.5"];
  6->7  [weight="2"];
  }
  }}}

  A second vertex filtering rule will always replace the former vertex filtering rule, and the same is valid for edge filters. For this effect, the generic vertex/edge filters below count as vertex/edge filters, but {{{--undirected}}} and {{{--reverse}}} filters do not.

  ==== Generic Filtering ====
  [[T(Complexity| '''O(1)''')]]

  Graphs can be filtered in a more versatile way than above (at a performance cost). This is done through the "{{{--vertex-filter}}}" and "{{{--edge-filter}}}" options, which take a generic [http://www.python.org python] expression as a parameter, which may contain vertex and edge properties respectively, and if it evaluates to "{{{True}}}" the vertex or edge is removed.

  Example:

  {{{
  #!html
  <div style="float: right;">
  }}}
  {{{
  #!graphviz
  digraph G {
  0;
  1;
  2;
  3;
  4;
  1->4  [label="0.5"];
  2->3  [label="10.1"];
  2->1  [label="5.5"];
  3->4  [label="2"];
  4->0  [label="0.1"];
  }
  }}}
  {{{
  #!html
  </div>
  }}}
  {{{
  $ graph-tool --load example.xml --edge-filter="weight()==0.8" --vertex-filter="in_degree()==0" \
  --save filtered.dot
  $ cat filtered.dot
  digraph G {
  0;
  1;
  2;
  3;
  4;
  1->4  [weight="0.5"];
  2->3  [weight="10.1"];
  2->1  [weight="5.5"];
  3->4  [weight="2"];
  4->0  [weight="0.1"];
  }
  }}}

  Filtering expressions may also contain some built-in C++ functions provided by {{{graph-tool}}}:

  ===== Edge functions =====
   is_self()::
    Checks if an edge is a self-edge (if its source is also its target).
   source_PROP()::
    Gets property PROP for the source of an edge.
   target_PROP()::
    Gets property PROP for the target of an edge.

  ===== Vertex Functions =====
   orig_DEG()::
     Returns the original degree of the unfiltered graph (if filtering is on). DEG can be any of "in_degree", "out_degree", or "total_degree".
   out_PROP()::
     Returns a list of edge properties PROP for each out-edge.
   in_PROP()::
     Returns a list of edge properties PROP for each in-edge.


  [[T(Note|Performance note | When generic filtering is turned on, algorithms in general will run much slower, since the python interpreter will be involved in the computations. Therefore, if some expensive computation is being considered, it is in general better to save the graph to a file after the filtering, and load it as an unfiltered graph to perform the computation.)]]

  ==== Removing filtering ====

  The graph can be returned to its unfiltered state by calling "{{{--reset-vertex-filter}}}" and "{{{--reset-edge-filter}}}".


name: GraphFiltering
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Filtering ==

  Graphs can be filtered in several ways. None of them actually modify the internally kept graph, and are of complexity O(1).

  === Directedness ===
  [[T(Complexity| '''O(1)''')]]

  Internally, all graphs in `graph-tool` are directed graphs. But it is possible to treat them easily as undirected with the "{{{--undirected}}}" option. All options after that will operate on a undirected filter of the internal directed graph. The "{{{--directed}}}" option reverts back to the default mode. If you want to load an undirected graph with graph-tool, just use the "{{{--undirected}}}" option before the "{{{--load}}}" option.

  === Edge direction ===
  [[T(Complexity| '''O(1)''')]]

  Directed graphs can have the the edge direction reversed with the "{{{--reverse}}}" option. A second "{{{--reverse}}}" reverts back to the original state.

  === Filtering of vertices or edges ===

  ==== Range filtering ====
  [[T(Complexity| '''O(1)''')]]

  [[T(Note|Note|Since revision [71] of the svn repository, this function can be disabled at compile-time through the "`--disable-range-filtering`" option passed to the configure script.)]]

  Edges and vertices can be filtered out of the graph based on their properties. The most basic and fastest way of filtering is called "range filtering" and filters out vertices with a scalar property which lays outside a given range. The filtering is controlled with the "{{{--vertex-range-filter}}}" and "{{{--edge-range-filter}}}" options, which takes two parameters separated by "|": the property to be used as filter and the range (two values separated by space). Here's an example using the graph defined in the [wiki:GraphToolGuideDev#Fileformatdescription file format description] section:

  {{{
  $ graph-tool --load example.xml --number-of-edges=-
  number of edges:        8
  $ graph-tool --load example.xml --edge-range-filter="weight|0.6 6.0" --number-of-edges=- --save filtered.dot
  number of edges:        4
  }}}

  The file "{{{filtered.dot}}}" contains (graphical representation on the side):

  {{{
  #!html
  <div style="float: right;">
  }}}
  {{{
  #!graphviz
  digraph G {
  1;
  2;
  3;
  7;
  4;
  5;
  6;
  1->2  [label="1.2"];
  2->3  [label="0.8"];
  5->3  [label="5.5"];
  6->7  [label="2.0"];
  }
  }}}
  {{{
  #!html
  </div>
  }}}

  {{{
  digraph G {
  1;
  2;
  3;
  7;
  4;
  5;
  6;
  1->2  [weight="1.2"];
  2->3  [weight="0.8"];
  5->3  [weight="5.5"];
  6->7  [weight="2"];
  }
  }}}

  A second vertex filtering rule will always replace the former vertex filtering rule, and the same is valid for edge filters. For this effect, the generic vertex/edge filters below count as vertex/edge filters, but {{{--undirected}}} and {{{--reverse}}} filters do not.

  ==== Generic Filtering ====
  [[T(Complexity| '''O(1)''')]]

  [[T(Note|Warning|Since revision [71] of the svn repository, this function is disabled by default. It must be enabled at compile-time through the "`--enable-python-filtering`" option passed to the configure script. The functionality here can be reproduced by creating a new vertex/edge property, which accepts python expressions, and then using range filtering above.)]]

  Graphs can be filtered in a more versatile way than above (at a performance cost). This is done through the "{{{--vertex-filter}}}" and "{{{--edge-filter}}}" options, which take a generic [http://www.python.org python] expression as a parameter, which may contain vertex and edge properties respectively, and if it evaluates to "{{{True}}}" the vertex or edge is removed.

  Example:

  {{{
  #!html
  <div style="float: right;">
  }}}
  {{{
  #!graphviz
  digraph G {
  0;
  1;
  2;
  3;
  4;
  1->4  [label="0.5"];
  2->3  [label="10.1"];
  2->1  [label="5.5"];
  3->4  [label="2"];
  4->0  [label="0.1"];
  }
  }}}
  {{{
  #!html
  </div>
  }}}
  {{{
  $ graph-tool --load example.xml --edge-filter="weight()==0.8" --vertex-filter="in_degree()==0" \
  --save filtered.dot
  $ cat filtered.dot
  digraph G {
  0;
  1;
  2;
  3;
  4;
  1->4  [weight="0.5"];
  2->3  [weight="10.1"];
  2->1  [weight="5.5"];
  3->4  [weight="2"];
  4->0  [weight="0.1"];
  }
  }}}

  Filtering expressions may also contain some built-in C++ functions provided by {{{graph-tool}}}:

  ===== Edge functions =====
   is_self()::
    Checks if an edge is a self-edge (if its source is also its target).
   source_PROP()::
    Gets property PROP for the source of an edge.
   target_PROP()::
    Gets property PROP for the target of an edge.

  ===== Vertex Functions =====
   orig_DEG()::
     Returns the original degree of the unfiltered graph (if filtering is on). DEG can be any of "in_degree", "out_degree", or "total_degree".
   out_PROP()::
     Returns a list of edge properties PROP for each out-edge.
   in_PROP()::
     Returns a list of edge properties PROP for each in-edge.


  [[T(Note|Performance note | When generic filtering is turned on, algorithms in general will run much slower, since the python interpreter will be involved in the computations. Therefore, if some expensive computation is being considered, it is in general better to save the graph to a file after the filtering, and load it as an unfiltered graph to perform the computation.)]]

  ==== Removing filtering ====

  The graph can be returned to its unfiltered state by calling "{{{--reset-vertex-filter}}}" and "{{{--reset-edge-filter}}}".


name: GraphToolDownload
author: count0
ipnr: 201.81.194.239
text:
  = graph-tool Download =

  graph-tool is released under the [http://www.gnu.org/copyleft/gpl.html GPL]. For installation instructions, see the included INSTALL file.

  [[T(Note|Warning: Memory requirements for compilation|graph-tool requires large amounts of RAM (~1 GB) during compilation, because it uses lots of [http://en.wikipedia.org/wiki/Template_metaprogramming template metaprogramming]. The supported compiler, [http://gcc.gnu.org/ GCC], is still not very well optimized for this, which means that even though the program is relatively small (the compiled binary, as of version 1.0, is around 20 MB in size), it will still use up lots of RAM during compilation, specially if optimizations are used (and you do want to use them). See, for instance, GCC bugs [http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29433 29433] and [http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12850 12850]. For this reason, pre-compiled binaries are also provided, so that if you don't have that much RAM, you can still use the program (but you'll still need all the [wiki:GraphToolDownload#Requirements requirements] below). Also, if you still want to compile your own version, but don't have enough memory, try passing the "`--disable-filtering`" option to the configure script. This will disable some of the filtering functionality of graph-tool, and will save some memory during compilation.)]]

  [[T(Note|Update|Since revision [71] in the svn, graph-tool does not enable python filtering by default, and it must be enabled, if wanted, by passing "`--enable-python-filtering`" to the configure script during compilation. This reduces the memory requirements to ~500 MB (in my i686 machine). There is also an "`--disable-range-filtering`" option, which disables range filtering, and reduces the memory requirements to ~300MB.)]]

  == Requirements ==

  You'll need the following in order to build and use graph-tool:

   * [http://gcc.gnu.org/ GCC] 4.1 or above
   * The [http://www.boost.org/ boost] libraries.
   * [http://www.python.org Python] 2.4 or above
   * The [http://expat.sourceforge.net/ expat] library

  graph-tool was tested only on [http://www.gnu.org GNU/Linux] systems, but should also be usable on other systems where the above requirements are available.

  === Optional packages ===
  The following packages, if available, will be used automatically by graph-tool, but are not required:
   * [http://www.scipy.org/ SciPy], for useful mathematical functions
   * [http://psyco.sourceforge.net/ Psyco], for improved performace of python code

  == Stable Releases ==

  [[T(Note|Try the SVN version first|Please consider first downloading the [wiki:GraphToolDownload#LatestDevelopmentSourceCode latest development source code] below, as it will usually be in an usable state, and will contain most bugfixes and new features)]]

  === Latest stable release - 1.0 ===

  ==== Tar source package ====
   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-1.0.tar.bz2 graph-tool-1.0.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-1.0.tar.bz2 graph-tool-1.0.tar.bz2]

  '''Note:''' After compilation, "`make install`" must be run before graph-tool can be used. If you just want to run the program without installing it, you must make sure that the "`libgraph_tool.so`" file (available after compilation in "`src/graph/.libs`") is in the same directory as the "`grap-tool`" executable (or, alternatively, somewhere in the python module path).

  ==== Pre-compiled binaries (i686 only) ====

  This package includes the "`graph-tool`" python executable and the "`libgraph_tool.so`" library, which should be either in the same directory as "`graph-tool`", or in the python module path, for graph-tool to work properly.

   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-1.0-precompiled-i686.tar.bz2 graph-tool-1.0-precompiled-i686.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-1.0-precompiled-i686.tar.bz2 graph-tool-1.0-precompiled-i686.tar.bz2]

  === Previous stable release - 0.9 ===
  0.9 was the first public release. '''Warning:''' This version is considered deprecated!

  ==== Tar source package ====
   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-0.9.tar.bz2 graph-tool-0.9.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-0.9.tar.bz2 graph-tool-0.9.tar.bz2]

  '''Note:''' After compilation, "`make install`" must be run before graph-tool can be used. If you just want to run the program without installing it, you must make sure that the "`libgraph_tool.so`" file (available after compilation in "`src/graph/.libs`") is in the same directory as the "`grap-tool`" executable (or, alternatively, somewhere in the python module path).

  ==== Pre-compiled binaries (i686 only) ====

  This package includes the "`graph-tool`" python executable and the "`libgraph_tool.so`" library, which should be either in the same directory as "`graph-tool`", or in the python module path, for graph-tool to work properly.

   * '''HTTP:''' [http://ftp.forked.de/pub/graph-tool/graph-tool-0.9-precompiled-i686.tar.bz2 graph-tool-0.9-precompiled-i686.tar.bz2]
   * '''FTP:''' [ftp://ftp.forked.de/pub/graph-tool/graph-tool-0.9-precompiled-i686.tar.bz2 graph-tool-0.9-precompiled-i686.tar.bz2]

  ----

  == Latest Development Source Code ==

  We use [http://subversion.tigris.org/ Subversion] for source revision control and code sharing.

  The Subversion repository URL for the graph-tool project is at:

    http://svn.forked.de/graph-tool/

  The latest revision can be checked out with the following command:

  {{{
  svn co http://svn.forked.de/graph-tool/trunk graph-tool
  }}}

  Or with encryption:

  {{{
  svn co https://svn.forked.de/graph-tool/trunk graph-tool
  }}}

  For further instructions on how to use Subversion, see [http://svnbook.red-bean.com/book.html The Subversion Book]


name: GraphFiltering
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Filtering ==

  Graphs can be filtered in several ways. None of them actually modify the internally kept graph, and are of complexity O(1).

  === Directedness ===
  [[T(Complexity| '''O(1)''')]]

  Internally, all graphs in `graph-tool` are directed graphs. But it is possible to treat them easily as undirected with the "{{{--undirected}}}" option. All options after that will operate on a undirected filter of the internal directed graph. The "{{{--directed}}}" option reverts back to the default mode. If you want to load an undirected graph with graph-tool, just use the "{{{--undirected}}}" option before the "{{{--load}}}" option.

  === Edge direction ===
  [[T(Complexity| '''O(1)''')]]

  Directed graphs can have the the edge direction reversed with the "{{{--reverse}}}" option. A second "{{{--reverse}}}" reverts back to the original state.

  === Filtering of vertices or edges ===

  ==== Range filtering ====
  [[T(Complexity| '''O(1)''')]]

  [[T(Note|Note|Since revision [71] of the svn repository, this function can be disabled at compile-time through the "`--disable-range-filtering`" option passed to the configure script.)]]

  Edges and vertices can be filtered out of the graph based on their properties. The most basic and fastest way of filtering is called "range filtering" and filters out vertices with a scalar property which lays outside a given range. The filtering is controlled with the "{{{--vertex-range-filter}}}" and "{{{--edge-range-filter}}}" options, which takes two parameters separated by "|": the property to be used as filter and the range (two values separated by space). Here's an example using the graph defined in the [wiki:GraphToolGuideDev#Fileformatdescription file format description] section:

  {{{
  $ graph-tool --load example.xml --number-of-edges=-
  number of edges:        8
  $ graph-tool --load example.xml --edge-range-filter="weight|0.6 6.0" --number-of-edges=- --save filtered.dot
  number of edges:        4
  }}}

  The file "{{{filtered.dot}}}" contains (graphical representation on the side):

  {{{
  #!html
  <div style="float: right;">
  }}}
  {{{
  #!graphviz
  digraph G {
  1;
  2;
  3;
  7;
  4;
  5;
  6;
  1->2  [label="1.2"];
  2->3  [label="0.8"];
  5->3  [label="5.5"];
  6->7  [label="2.0"];
  }
  }}}
  {{{
  #!html
  </div>
  }}}

  {{{
  digraph G {
  1;
  2;
  3;
  7;
  4;
  5;
  6;
  1->2  [weight="1.2"];
  2->3  [weight="0.8"];
  5->3  [weight="5.5"];
  6->7  [weight="2"];
  }
  }}}

  A second vertex filtering rule will always replace the former vertex filtering rule, and the same is valid for edge filters. For this effect, the generic vertex/edge filters below count as vertex/edge filters, but {{{--undirected}}} and {{{--reverse}}} filters do not.

  ==== Generic Filtering ====
  [[T(Complexity| '''O(1)''')]]

  [[T(Note|Warning|Since revision [71] this function is disabled by default. It must be enabled at compile-time through the "`--enable-python-filtering`" option passed to the configure script. The functionality here can be reproduced by creating a new vertex/edge property, which accepts python expressions, and then using range filtering above.)]]

  [[T(Note|Warning|Since revision [72] this functionality has been greatly modified, and is now much more general. The this page's history for the old documentation.)]]

  Graphs can be filtered in a more versatile way than above (at a performance cost). This is done through the "{{{--vertex-filter}}}" and "{{{--edge-filter}}}" options, which take a generic [http://www.python.org python] expression as a parameter, and if it evaluates to "{{{True}}}" the vertex or edge is removed.

  The expression syntax is as follows: For vertex filters a variable "`v`" is defined and for edge filters, a variable "`e`", corresponding to the current vertex or edge, respectively. Those variables are a instantiation of the "`Vertex`" and "`Edge`" python classes, respectively, which have the following member funcions:

  ===== Vertex =====
    '''in_degree()'''::
      Returns the in-degree of the vertex
    '''out_degree()'''::
      Returns the out-degree of the vertex
    '''get_property(name)::
      Returns the value of the property specified by "name"
    '''in_edges()'''::
      Returns a list of Edges corresponding to the in-edges of the vertex
    '''out_edges()'''::
      Returns a list of Edges corresponding to the out-edges of the vertex

  ===== Edge =====
    '''source()'''::
      Returns the source Vertex
    '''target()'''::
      Returns target Vertex
    '''get_property(name)::
      Returns the value of the property specified by "name"
    '''n_parallel()'''::
      Return the number of parallel edges

  This syntax is specially useful when [wiki:GraphModification#Creatingandmodifyingproperties editing properties].

  Example:

  {{{
  #!html
  <div style="float: right;">
  }}}
  {{{
  #!graphviz
  digraph G {
  0;
  1;
  2;
  3;
  4;
  1->4  [label="0.5"];
  2->3  [label="10.1"];
  2->1  [label="5.5"];
  3->4  [label="2"];
  4->0  [label="0.1"];
  }
  }}}
  {{{
  #!html
  </div>
  }}}
  {{{
  $ graph-tool --load example.xml --edge-filter="e.get_property('weight')==0.8" --vertex-filter="v.in_degree()==0" \
  --save filtered.dot
  $ cat filtered.dot
  digraph G {
  0;
  1;
  2;
  3;
  4;
  1->4  [weight="0.5"];
  2->3  [weight="10.1"];
  2->1  [weight="5.5"];
  3->4  [weight="2"];
  4->0  [weight="0.1"];
  }
  }}}

  Filtering expressions may also contain some built-in C++ functions provided by {{{graph-tool}}}:

  ===== Edge functions =====
   is_self()::
    Checks if an edge is a self-edge (if its source is also its target).
   source_PROP()::
    Gets property PROP for the source of an edge.
   target_PROP()::
    Gets property PROP for the target of an edge.

  ===== Vertex Functions =====
   orig_DEG()::
     Returns the original degree of the unfiltered graph (if filtering is on). DEG can be any of "in_degree", "out_degree", or "total_degree".
   out_PROP()::
     Returns a list of edge properties PROP for each out-edge.
   in_PROP()::
     Returns a list of edge properties PROP for each in-edge.


  [[T(Note|Performance note | When generic filtering is turned on, algorithms in general will run much slower, since the python interpreter will be involved in the computations. Therefore, if some expensive computation is being considered, it is in general better to save the graph to a file after the filtering, and load it as an unfiltered graph to perform the computation. [wiki:GraphModification#Creatingandmodifyingproperties Editing properties] and then using range filtering, as above, can also be a viable alternative.)]]

  ==== Removing filtering ====

  The graph can be returned to its unfiltered state by calling "{{{--reset-vertex-filter}}}" and "{{{--reset-edge-filter}}}".


name: GraphModification
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Graph Modifications ==

  There's a couple of options which change the internally kept graph.

  === Removing Properties ===
  [[T(Complexity|'''O(1)''')]]

  Vertex and edge properties can be removed from the graph with the options "{{{--remove-vertex-property}}}" and "{{{--remove-edge-property}}}", which take the name of the property to be removed as parameter.

  === Vertex and Edge Indexes ===
  [[T(Complexity|'''O(1)''')]]

  Vertices and Edges are identified internally by indexes. Those can be inserted as properties with the options "{{{--insert-vertex-index-property}}}" and "{{{--insert-edge-index-property}}}", which take as argument the name by which the property will be called.

  === Creating and modifying properties ===
  [[T(Complexity|'''O(V)''' or '''O(E)''')]]

  New properties can be created and old ones modified (replaced) the the following options:

  {{{
  --edit-vertex-property=PROPERTY|EXPRESSION     edit the selected vertex property
  --edit-edge-property=PROPERTY|EXPRESSION       edit the selected edge property
  }}}

  The PROPERTY parameter takes the name of the property which will be created or modified. The EXPRESSION parameter is a python expression which will be evaluated to a "double" value, and assigned to the property. The variables available are the same as with [wiki:GraphFiltering#GenericFiltering Generic Filtering] described above. Additionally, the editing expression may be defined in a file. For that, the value of EXPRESSION must be in the format "`file:FILE`" where FILE is a python program which contain the fuction "`edit_function`" whose return value will define the property. 

  Example:
  {{{
  $ graph-tool --load example.xml \
    --edit-edge-property="sqrt_weight|e.get_property('weight')**0.5" \
    --average-edge-property="weight|-" \
    --average-edge-property="sqrt_weight|-" 
  # average edge property (weight):
  2.550000        1.163373

  # average edge property (sqrt_weight):
  1.299736        0.328003
  }}}

  Suppose you want to get the distribution of the number of neighbours at a distance 2 from a vertex. You have just to define the editing routine, here called  `second-neighbours.py`:

  {{{
  #!python
  def edit_function():
      first_neighbours = set()
      second_neighbours = set()
      for n in v.out_edges() + v.in_edges():
          first_neighbours.add(n.target())
      for n in first_neighbours:
          for n2 in n.out_edges() + n.in_edges():
              if n2.target() not in first_neighbours:
                  second_neighbours.add(n2)
      return len(second_neighbours)
  }}}

  And then,

  {{{
  $ graph-tool --load example.xml \
    --edit-vertex-property="second|file:second-neighbours.py" \
    --vertex-histogram="second|-"
  # vertex histogram (second):
  1.0     5
  2.0     2
  }}}

  === Parallel edges removal ===
  [[T(Complexity|'''O(E log(<k>))''')]]

  A multigraph can be converted into a simple graph by labeling the parallel edges with an edge property and then filtering them out. The edges can be labeled with the following option:

  {{{
  --label-parallel-edges=PROPERTY       label parallel edges to PROPERTY
  }}}

  This will create (or replace) a property map with name given by PROPERTY, which will have integer values. The parallel edges will be labeled increasingly starting from zero, in a non-specified order. The graph can thus be reduced to a simple graph by filtering out edges with values > 0. See GraphFiltering above.


name: GraphFiltering
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Filtering ==

  Graphs can be filtered in several ways. None of them actually modify the internally kept graph, and are of complexity O(1).

  === Directedness ===
  [[T(Complexity| '''O(1)''')]]

  Internally, all graphs in `graph-tool` are directed graphs. But it is possible to treat them easily as undirected with the "{{{--undirected}}}" option. All options after that will operate on a undirected filter of the internal directed graph. The "{{{--directed}}}" option reverts back to the default mode. If you want to load an undirected graph with graph-tool, just use the "{{{--undirected}}}" option before the "{{{--load}}}" option.

  === Edge direction ===
  [[T(Complexity| '''O(1)''')]]

  Directed graphs can have the the edge direction reversed with the "{{{--reverse}}}" option. A second "{{{--reverse}}}" reverts back to the original state.

  === Filtering of vertices or edges ===

  ==== Range filtering ====
  [[T(Complexity| '''O(1)''')]]

  [[T(Note|Note|Since revision [71] of the svn repository, this function can be disabled at compile-time through the "`--disable-range-filtering`" option passed to the configure script.)]]

  Edges and vertices can be filtered out of the graph based on their properties. The most basic and fastest way of filtering is called "range filtering" and filters out vertices with a scalar property which lays outside a given range. The filtering is controlled with the "{{{--vertex-range-filter}}}" and "{{{--edge-range-filter}}}" options, which takes two parameters separated by "|": the property to be used as filter and the range (two values separated by space). Here's an example using the graph defined in the [wiki:GraphToolGuideDev#Fileformatdescription file format description] section:

  {{{
  $ graph-tool --load example.xml --number-of-edges=-
  number of edges:        8
  $ graph-tool --load example.xml --edge-range-filter="weight|0.6 6.0" --number-of-edges=- --save filtered.dot
  number of edges:        4
  }}}

  The file "{{{filtered.dot}}}" contains (graphical representation on the side):

  {{{
  #!html
  <div style="float: right;">
  }}}
  {{{
  #!graphviz
  digraph G {
  1;
  2;
  3;
  7;
  4;
  5;
  6;
  1->2  [label="1.2"];
  2->3  [label="0.8"];
  5->3  [label="5.5"];
  6->7  [label="2.0"];
  }
  }}}
  {{{
  #!html
  </div>
  }}}

  {{{
  digraph G {
  1;
  2;
  3;
  7;
  4;
  5;
  6;
  1->2  [weight="1.2"];
  2->3  [weight="0.8"];
  5->3  [weight="5.5"];
  6->7  [weight="2"];
  }
  }}}

  A second vertex filtering rule will always replace the former vertex filtering rule, and the same is valid for edge filters. For this effect, the generic vertex/edge filters below count as vertex/edge filters, but {{{--undirected}}} and {{{--reverse}}} filters do not.

  ==== Generic Filtering ====
  [[T(Complexity| '''O(1)''')]]

  [[T(Note|Warning|Since revision [71] this function is disabled by default. It must be enabled at compile-time through the "`--enable-python-filtering`" option passed to the configure script. The functionality here can be reproduced by creating a new vertex/edge property, which accepts python expressions, and then using range filtering above.)]]

  [[T(Note|Warning|Since revision [72] this functionality has been greatly modified, and is now much more general. The this page's history for the old documentation.)]]

  Graphs can be filtered in a more versatile way than above (at a performance cost). This is done through the "{{{--vertex-filter}}}" and "{{{--edge-filter}}}" options, which take a generic [http://www.python.org python] expression as a parameter, and if it evaluates to "{{{True}}}" the vertex or edge is removed. The expression syntax is the same as defined in [wiki:GraphModification#Creatingandmodifyingproperties Creating and Modifying Properties].

  Example:

  {{{
  #!html
  <div style="float: right;">
  }}}
  {{{
  #!graphviz
  digraph G {
  0;
  1;
  2;
  3;
  4;
  1->4  [label="0.5"];
  2->3  [label="10.1"];
  2->1  [label="5.5"];
  3->4  [label="2"];
  4->0  [label="0.1"];
  }
  }}}
  {{{
  #!html
  </div>
  }}}
  {{{
  $ graph-tool --load example.xml --edge-filter="e.get_property('weight')==0.8" --vertex-filter="v.in_degree()==0" \
  --save filtered.dot
  $ cat filtered.dot
  digraph G {
  0;
  1;
  2;
  3;
  4;
  1->4  [weight="0.5"];
  2->3  [weight="10.1"];
  2->1  [weight="5.5"];
  3->4  [weight="2"];
  4->0  [weight="0.1"];
  }
  }}}


  [[T(Note|Performance note | When generic filtering is turned on, algorithms in general will run much slower, since the python interpreter will be involved in the computations. Therefore, if some expensive computation is being considered, it is in general better to save the graph to a file after the filtering, and load it as an unfiltered graph to perform the computation. [wiki:GraphModification#Creatingandmodifyingproperties Editing properties] and then using range filtering, as above, can also be a viable alternative.)]]

  ==== Removing filtering ====

  The graph can be returned to its unfiltered state by calling "{{{--reset-vertex-filter}}}" and "{{{--reset-edge-filter}}}".


name: GraphModification
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Graph Modifications ==

  There's a couple of options which change the internally kept graph.

  === Removing Properties ===
  [[T(Complexity|'''O(1)''')]]

  Vertex and edge properties can be removed from the graph with the options "{{{--remove-vertex-property}}}" and "{{{--remove-edge-property}}}", which take the name of the property to be removed as parameter.

  === Vertex and Edge Indexes ===
  [[T(Complexity|'''O(1)''')]]

  Vertices and Edges are identified internally by indexes. Those can be inserted as properties with the options "{{{--insert-vertex-index-property}}}" and "{{{--insert-edge-index-property}}}", which take as argument the name by which the property will be called.

  === Creating and modifying properties ===
  [[T(Complexity|'''O(V)''' or '''O(E)''')]]

  New properties can be created and old ones modified (replaced) the the following options:

  {{{
  --edit-vertex-property=PROPERTY|EXPRESSION     edit the selected vertex property
  --edit-edge-property=PROPERTY|EXPRESSION       edit the selected edge property
  }}}

  The PROPERTY parameter takes the name of the property which will be created or modified. The EXPRESSION parameter is a python expression which will be evaluated to a "double" value, and assigned to the property. Additionally, the editing expression may be defined in a file. For that, the value of EXPRESSION must be in the format "`file:FILE`" where FILE is a python program which contain the fuction "`edit_function`" whose return value will define the property. 

  The expression syntax is as follows: For vertex filters a variable "`v`" is defined and for edge filters, a variable "`e`", corresponding to the current vertex or edge, respectively. Those variables are a instantiation of the "`Vertex`" and "`Edge`" python classes, respectively, which have the following member funcions:

  ===== Vertex =====
    '''in_degree()'''::
      Returns the in-degree of the vertex
    '''out_degree()'''::
      Returns the out-degree of the vertex
    '''get_property(name)::
      Returns the value of the property specified by "name"
    '''in_edges()'''::
      Returns a list of Edges corresponding to the in-edges of the vertex
    '''out_edges()'''::
      Returns a list of Edges corresponding to the out-edges of the vertex

  ===== Edge =====
    '''source()'''::
      Returns the source Vertex
    '''target()'''::
      Returns target Vertex
    '''get_property(name)::
      Returns the value of the property specified by "name"
    '''n_parallel()'''::
      Return the number of parallel edges

  Example:
  {{{
  $ graph-tool --load example.xml \
    --edit-edge-property="sqrt_weight|e.get_property('weight')**0.5" \
    --average-edge-property="weight|-" \
    --average-edge-property="sqrt_weight|-" 
  # average edge property (weight):
  2.550000        1.163373

  # average edge property (sqrt_weight):
  1.299736        0.328003
  }}}

  Suppose you want to get the distribution of the number of neighbours at a distance 2 from a vertex. You have just to define the editing routine, here called  `second-neighbours.py`:

  {{{
  #!python
  def edit_function():
      first_neighbours = set()
      second_neighbours = set()
      for n in v.out_edges() + v.in_edges():
          first_neighbours.add(n.target())
      for n in first_neighbours:
          for n2 in n.out_edges() + n.in_edges():
              if n2.target() not in first_neighbours:
                  second_neighbours.add(n2)
      return len(second_neighbours)
  }}}

  And then,

  {{{
  $ graph-tool --load example.xml \
    --edit-vertex-property="second|file:second-neighbours.py" \
    --vertex-histogram="second|-"
  # vertex histogram (second):
  1.0     5
  2.0     2
  }}}

  === Parallel edges removal ===
  [[T(Complexity|'''O(E log(<k>))''')]]

  A multigraph can be converted into a simple graph by labeling the parallel edges with an edge property and then filtering them out. The edges can be labeled with the following option:

  {{{
  --label-parallel-edges=PROPERTY       label parallel edges to PROPERTY
  }}}

  This will create (or replace) a property map with name given by PROPERTY, which will have integer values. The parallel edges will be labeled increasingly starting from zero, in a non-specified order. The graph can thus be reduced to a simple graph by filtering out edges with values > 0. See GraphFiltering above.


name: GraphModification
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Graph Modifications ==

  There's a couple of options which change the internally kept graph.

  === Removing Properties ===
  [[T(Complexity|'''O(1)''')]]

  Vertex and edge properties can be removed from the graph with the options "{{{--remove-vertex-property}}}" and "{{{--remove-edge-property}}}", which take the name of the property to be removed as parameter.

  === Vertex and Edge Indexes ===
  [[T(Complexity|'''O(1)''')]]

  Vertices and Edges are identified internally by indexes. Those can be inserted as properties with the options "{{{--insert-vertex-index-property}}}" and "{{{--insert-edge-index-property}}}", which take as argument the name by which the property will be called.

  === Creating and modifying properties ===
  [[T(Complexity|'''O(V)''' or '''O(E)''')]]

  New properties can be created and old ones modified (replaced) the the following options:

  {{{
  --edit-vertex-property=PROPERTY|EXPRESSION     edit the selected vertex property
  --edit-edge-property=PROPERTY|EXPRESSION       edit the selected edge property
  }}}

  The PROPERTY parameter takes the name of the property which will be created or modified. The EXPRESSION parameter is a python expression which will be evaluated to a "double" value, and assigned to the property. Additionally, the editing expression may be defined in a file. For that, the value of EXPRESSION must be in the format "`file:FILE`" where FILE is a python program which contain the fuction "`edit_function`" whose return value will define the property. 

  The expression syntax is as follows: For vertex filters a variable "`v`" is defined and for edge filters, a variable "`e`", corresponding to the current vertex or edge, respectively. Those variables are a instantiation of the "`Vertex`" and "`Edge`" python classes, respectively, which have the following member funcions:

  ===== Vertex =====
    '''in_degree()'''::
      Returns the in-degree of the vertex
    '''out_degree()'''::
      Returns the out-degree of the vertex
    '''get_property(name)::
      Returns the value of the property specified by "name"
    '''in_edges()'''::
      Returns a list of Edges corresponding to the in-edges of the vertex
    '''out_edges()'''::
      Returns a list of Edges corresponding to the out-edges of the vertex

  ===== Edge =====
    '''source()'''::
      Returns the source Vertex
    '''target()'''::
      Returns target Vertex
    '''get_property(name)::
      Returns the value of the property specified by "name"
    '''n_parallel()'''::
      Return the number of parallel edges

  Example:
  {{{
  $ graph-tool --load example.xml \
    --edit-edge-property="sqrt_weight|e.get_property('weight')**0.5" \
    --average-edge-property="weight|-" \
    --average-edge-property="sqrt_weight|-" 
  # average edge property (weight):
  2.550000        1.163373

  # average edge property (sqrt_weight):
  1.299736        0.328003
  }}}

  Suppose you want to get the distribution of the number of neighbours at a distance 2 from a vertex. You have just to define the editing routine, here called  `second-neighbours.py`:

  {{{
  #!python
  def edit_function():
      first_neighbours = set()
      second_neighbours = set()
      for n in v.out_edges():
          first_neighbours.add(n.target())
      for n in first_neighbours:
          for n2 in n.out_edges():
              if n2.target() not in first_neighbours:
                  second_neighbours.add(n2)
      return len(second_neighbours)
  }}}

  And then,

  {{{
  $ graph-tool --load example.xml \
    --edit-vertex-property="second|file:second-neighbours.py" \
    --vertex-histogram="second|-"
  # vertex histogram (second):
  1.0     5
  2.0     2
  }}}

  === Parallel edges removal ===
  [[T(Complexity|'''O(E log(<k>))''')]]

  A multigraph can be converted into a simple graph by labeling the parallel edges with an edge property and then filtering them out. The edges can be labeled with the following option:

  {{{
  --label-parallel-edges=PROPERTY       label parallel edges to PROPERTY
  }}}

  This will create (or replace) a property map with name given by PROPERTY, which will have integer values. The parallel edges will be labeled increasingly starting from zero, in a non-specified order. The graph can thus be reduced to a simple graph by filtering out edges with values > 0. See GraphFiltering above.


name: GraphModification
author: anonymous
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Graph Modifications ==

  There's a couple of options which change the internally kept graph.

  === Removing Properties ===
  [[T(Complexity|'''O(1)''')]]

  Vertex and edge properties can be removed from the graph with the options "{{{--remove-vertex-property}}}" and "{{{--remove-edge-property}}}", which take the name of the property to be removed as parameter.

  === Vertex and Edge Indexes ===
  [[T(Complexity|'''O(1)''')]]

  Vertices and Edges are identified internally by indexes. Those can be inserted as properties with the options "{{{--insert-vertex-index-property}}}" and "{{{--insert-edge-index-property}}}", which take as argument the name by which the property will be called.

  === Creating and modifying properties ===
  [[T(Complexity|'''O(V)''' or '''O(E)''')]]

  New properties can be created and old ones modified (replaced) the the following options:

  {{{
  --edit-vertex-property=PROPERTY|EXPRESSION     edit the selected vertex property
  --edit-edge-property=PROPERTY|EXPRESSION       edit the selected edge property
  }}}

  The PROPERTY parameter takes the name of the property which will be created or modified. The EXPRESSION parameter is a python expression which will be evaluated to a "double" value, and assigned to the property. Additionally, the editing expression may be defined in a file. For that, the value of EXPRESSION must be in the format "`file:FILE`" where FILE is a python program which contain the fuction "`edit_function`" whose return value will define the property. 

  The expression syntax is as follows: For vertex filters a variable "`v`" is defined and for edge filters, a variable "`e`", corresponding to the current vertex or edge, respectively. Those variables are a instantiation of the "`Vertex`" and "`Edge`" python classes, respectively, which have the following member funcions:

  ===== Vertex =====
    '''in_degree()'''::
      Returns the in-degree of the vertex
    '''out_degree()'''::
      Returns the out-degree of the vertex
    '''get_property(name)::
      Returns the value of the property specified by "name"
    '''in_edges()'''::
      Returns a list of Edges corresponding to the in-edges of the vertex
    '''out_edges()'''::
      Returns a list of Edges corresponding to the out-edges of the vertex

  ===== Edge =====
    '''source()'''::
      Returns the source Vertex
    '''target()'''::
      Returns target Vertex
    '''get_property(name)::
      Returns the value of the property specified by "name"
    '''n_parallel()'''::
      Return the number of parallel edges

  Example:
  {{{
  $ graph-tool --load example.xml \
    --edit-edge-property="sqrt_weight|e.get_property('weight')**0.5" \
    --average-edge-property="weight|-" \
    --average-edge-property="sqrt_weight|-" 
  # average edge property (weight):
  2.550000        1.163373

  # average edge property (sqrt_weight):
  1.299736        0.328003
  }}}

  Suppose you want to get the distribution of the number of neighbours at a distance 2 from a vertex. You have just to define the editing routine, here called  `second-neighbours.py`:

  {{{
  #!python
  def edit_function():
      first_neighbours = set()
      second_neighbours = set()
      for n in v.out_edges():
          first_neighbours.add(n.target())
      for n in first_neighbours:
          for n2 in n.out_edges():
              if n2.target() not in first_neighbours:
                  second_neighbours.add(n2.target())
      return len(second_neighbours)
  }}}

  And then,

  {{{
  $ graph-tool --load example.xml \
    --edit-vertex-property="second|file:second-neighbours.py" \
    --vertex-histogram="second|-"
  # vertex histogram (second):
  1.0     6
  2.0     1
  }}}

  === Parallel edges removal ===
  [[T(Complexity|'''O(E log(<k>))''')]]

  A multigraph can be converted into a simple graph by labeling the parallel edges with an edge property and then filtering them out. The edges can be labeled with the following option:

  {{{
  --label-parallel-edges=PROPERTY       label parallel edges to PROPERTY
  }}}

  This will create (or replace) a property map with name given by PROPERTY, which will have integer values. The parallel edges will be labeled increasingly starting from zero, in a non-specified order. The graph can thus be reduced to a simple graph by filtering out edges with values > 0. See GraphFiltering above.


name: GraphClustering
author: count0
ipnr: 201.81.194.239
text:
  [[Include(DocToc)]]
  == Clustering ==

  === Local Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The local (vertex) clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(1)}_v = \frac{2N_c}{k(k-1)}\])]], where [[Equation($k$)]] is the number of neighbours of the vertex, and [[Equation($N_c$)]] is the number of edges between the neighbours of the vertex. This value can be calculated and set to a vertex property with the command "`--set-local-clustering-to-property`", which takes the property name as parameter. Example:

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --vertex-histogram="clustering|clust"
  $ cat clust
  0.0     4
  0.333333333333  3
  }}}

  It is possible to obtain the clustering coefficient for the whole graph by using the `--average-vertex-property` option :

  {{{
  $ graph-tool --load example.xml --set-local-clustering-to-property=clustering --average-vertex-property="clustering|-"
  average vertex property:        0.142857        0.062348
  }}}

  The first value is the clustering coefficient, and the second is the standard deviation.

  [[T(Note|Performance note|Please consider using the [wiki:GraphClustering#ExtendedClustering extented clustering] algorithm below, which is implemented differently and seems to be faster.)]]

  === Global Clustering ===
  [[T(Complexity| '''O(V<k>^3^)''')]]

  The global clustering coefficient is defined on an undirected graph as 

  [[Equation(\[C^{(2)} = \frac{3N_t}{N_c}\])]], where [[Equation($N_t$)]] is the number of triangles in the graph and [[Equation($N_c$)]] is the number of connected triplets. It can be obtained with the "`--global-clustering-coefficient`" option, which takes a file name as a parameter, or "`-`" for terminal output. Example:

  {{{
  $ graph-tool --load example.xml --global-clustering-coefficient=- 
  global clustering coefficient:  0.230769        0.030769
  }}}

  The first value is the global clustering coefficient, and the second value is the variance using the [http://en.wikipedia.org/wiki/Resampling_(statistics)#Jackknife jackknife method] on the vertices.

  === Extended Clustering ===
  [[T(Complexity|'''O(V<k>^2+MAX^)''' (worst case))]]

  Option summary:
  {{{
  --set-extended-clustering-to-property=PREFIX|MAX
                                      set the extended clustering coefficients
                                      c1 to cMAX to vertex properties PREFIX1
                                      to PREFIXMAX
  }}}

  An interesting generalization of the local clustering coefficient was proposed by [http://arxiv.org/abs/physics/0605235 Abdo et al] which allows for clusterings of larger order, while conceptual and numerical compatibility with the traditional coefficient is maintained. The definition of the extended clustering coefficient is as follows:

  [[Equation(\[C^d(u) = \frac{\left|\right\{ \{v,w\}; v,w \in N(u) | d_{G(V\diagdown \{u\})} (v,w) = d \left\}\right|}{\binom{\left|N(u)\right|}{2}} \])]],

  where '''N(u)''' is the set of neighbours of '''u'''. According to the above definition, we have that the traditional clustering coefficient is recovered for '''d=1'''.

  The extended clustering coefficients can be calculated and set to a vertex property with the command "`--set-extended-clustering-to-property`", which takes the prefix of property name as parameter, and the maximum value of "d". The properties from PREFIX1 to PREFIXMAX will contain the coefficients C^1^ to C^MAX^. 

  Example:
  {{{
  $ graph-tool --load example.xml --set-extended-clustering-to-property="c|3" --vertex-histogram="c2|-"
  # vertex histogram (c2):
  0.0     3
  0.333333333333  3
  1.0     1
  }}}


name: GraphHistory
author: abdo@member.fsf.org
ipnr: 201.6.37.145
comment: updating prefix suppression syntax
text:
  [[Include(DocToc)]]
  == Graph History ==

  Option Summary:

  {{{
  --for=INIT|CONDITION|STEP          simplified scripting
  --history=INIT|CONDITION|STEP      simplified scripting (does not overwrite previous results)
  --refresh-rate=TIME                for/history files refresh rate
  }}}

  Graphs sometimes have dynamical properties related to them. Sometimes they grow or change somehow during time. It is often interesting to see how its various properties also change with time. In graph-tool this is possible through the usage of properties, filtering, and the "`--history`" or "`--for`" option. The history/for option takes three parameters, which function just like a "`for` loop": the initial statement, a condition to be checked every iteration, and a step statement. The variables defined and modified in the parameters of this option are available to be used by the other options that follow it. __The difference between the `for` and `history` options is that the `history` option does not overwrite existing files, and only appends to them.__ Using graph properties and filtering, snapshots of the graph can be generated. It all becomes clearer with an example. Consider the following graph, called "`example-time.xml`":

  {{{
  #!html
  <div style="float: right;">
  }}}
  {{{
  #!graphviz
  digraph G {
  start="12";
  1->2 [label = "  1  ", len=0.6];
  2->3 [label = "  2  ", len=0.6];
  3->7 [label = "  3  ", len=0.6];
  4->5 [label = "  4  ", len=0.6];
  5->6 [label = "  5  ", len=0.6];
  5->3 [label = "  6  ", len=0.6];
  6->7 [label = "  7  ", len=0.6];
  7->2 [label = "  8  ", len=0.6];
  }
  }}}
  {{{
  #!html
  </div>
  }}}


  {{{
  #!xml
  <?xml version="1.0" encoding="UTF-8"?>
  <graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://graphml.graphdrawing\.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
    <key id="d1" for="edge" attr.name="time" attr.type="int"/>
    <graph id="G" edgedefault="directed">
      <node id="n0"/>
      <node id="n1"/>
      <node id="n2"/>
      <node id="n3"/>
      <node id="n4"/>
      <node id="n5"/>
      <node id="n6"/>
      <edge id="e0" source="n0" target="n1">
        <data key="d1">1</data>
      </edge>
      <edge id="e1" source="n1" target="n2">
        <data key="d1">2</data>
      </edge>
      <edge id="e2" source="n2" target="n6">
        <data key="d1">3</data>
      </edge>
      <edge id="e3" source="n3" target="n4">
        <data key="d1">4</data>
      </edge>
      <edge id="e4" source="n4" target="n5">
        <data key="d1">5</data>
      </edge>
      <edge id="e5" source="n4" target="n2">
        <data key="d1">6</data>
      </edge>
      <edge id="e6" source="n5" target="n6">
        <data key="d1">7</data>
      </edge>
      <edge id="e7" source="n6" target="n1">
        <data key="d1">8</data>
      </edge>
    </graph>
  </graphml>
  }}}

  There's an edge property called time which goes from 1 to 8. So in order to calculate, for instance, the number of edges and the degree distribution over time, one could do the following:

  {{{
  $ graph-tool --load example-time.xml --history="t=1|t<9|t+=1" --edge-range-filter="time|1 %t" \
  --vertex-histogram="total-degree|deg-history" --number-of-edges="num-edges-history"
  $ cat num-edges-history 
  0       1
  1       2
  2       3
  3       4
  4       5
  5       6
  6       7
  7       8
  $ cat deg-history
  0       0.0     5
  0       1.0     2
  1       0.0     4
  1       1.0     2
  1       2.0     1
  2       0.0     3
  2       1.0     2
  2       2.0     2
  3       0.0     1
  3       1.0     4
  3       2.0     2
  4       1.0     4
  4       2.0     3
  5       1.0     4
  5       2.0     1
  5       3.0     2
  6       1.0     2
  6       2.0     3
  6       3.0     2
  7       1.0     2
  7       2.0     1
  7       3.0     4
  }}}

  The variables defined in the "`--history`" option are reachable in the options that follow it by prefixing them with "`%`". Each saved file contains the history of the measured property, with each line prefixed by the history iteration number (or with the variable "`prefix`" defined in the history specification, as shown below). In the case above, "`num-edges-history`" contains the number of edges in each iteration and "`deg-history`" contains the degree distribution with each iteration. It should be clear with the above example that this feature is reasonably general, since combined with generic filtering, it is possible to obtain quite arbitrary "histories" of the graph. The syntax of the history specification is any valid [http://www.python.org python] statement.

  ==== Specifying the history prefix ====

  Using the history counter as a prefix is sometimes not the most comfortable way of labeling points in history. Luckily, this can easily be changed by defining the "`prefix`" variable, as shown in the example below:

  {{{
  $ graph-tool --load example-time.xml --history="t=1; prefix=t+10 | t<9 | t+=1; prefix=t+10" \
   --edge-range-filter="time|1 %t" --number-of-edges="num-edges-history"
  $ cat num-edges-history 
  11      1
  12      2
  13      3
  14      4
  15      5
  16      6
  17      7
  18      8
  }}}

  The prefix can be entirely suppressed by setting it to None: "`prefix=None`". This can be useful when each history step is being saved to a different file.

  === Resuming history computations ===

  For large graphs history computations can take quite a long time. During this time things in general can go wrong, such as a power outage. For this reason graph-tool supports resuming of history computations, where partial results already contained in the history files are automatically skipped and not recalculated. Therefore, if you change the history rules or the graph, you must remember to delete the old history files or to save to new ones, otherwise they'll still contain old information.

  Before data is saved to the history files, partial history results are kept in temporary files, which get periodically copied over to the final files. The frequency of this update can be changed with the "`--history-rate`" option, which takes a number as a parameter followed by "`s`","`m`","`h`" or "`d`" to indicate seconds, minutes, hours or days, respectively. The default value is "`1h`".


name: GraphModification
author: count0
ipnr: 201.81.210.76
text:
  [[Include(DocToc)]]
  == Graph Modifications ==

  There's a couple of options which change the internally kept graph.

  === Listing Properties ===
  [[T(Complexity|'''O(1)''')]]

  This doesn't really modify the graph, but it is useful for the options below. All graph properties can be listed with the "{{{--list-properties}}}" option.
  Example (see below for more details):

  {{{
  $ graph-tool --load example.xml --list-properties
  weight          (edge)    type: double

  $ graph-tool --load example.xml  \
    --edit-graph-property="name|string|'foo'" \
    --edit-vertex-property="indeg_over_2|float|v.in_degree()/2.0" \
    --edit-edge-property="weight_tresh|boolean|e.get_property('weight') > 1.0" \
    --list-properties 
  indeg_over_2    (vertex)  type: float
  name            (graph)   type: string
  weight          (edge)    type: double
  weight_tresh    (edge)    type: boolean
  }}}


  === Removing Properties ===
  [[T(Complexity|'''O(1)''')]]

  Vertex, edge and graph properties can be removed from the graph with the options "{{{--remove-vertex-property}}}", "{{{--remove-edge-property}}}" and "{{{--remove-graph-property}}}", which take the name of the property to be removed as parameter.

  === Vertex and Edge Indexes ===
  [[T(Complexity|'''O(1)''')]]

  Vertices and Edges are identified internally by indexes. Those can be inserted as properties with the options "{{{--insert-vertex-index-property}}}" and "{{{--insert-edge-index-property}}}", which take as argument the name by which the property will be called.

  === Creating and modifying properties ===
  [[T(Complexity|'''O(V)''' or '''O(E)''' (or O(1) for graph)]]

  New properties can be created and old ones modified (replaced) the the following options:

  {{{
  --edit-vertex-property=PROPERTY[|TYPE]|EXPRESSION     edit the selected vertex property
  --edit-edge-property=PROPERTY[|TYPE]|EXPRESSION       edit the selected edge property
  --edit-graph-property=PROPERTY[|TYPE]|EXPRESSION      edit the selected graph property
  }}}

  The PROPERTY parameter takes the name of the property which will be created or modified. The EXPRESSION parameter is a python expression which will be evaluated to a value of type TYPE, which can be any of `boolean`, `int`, `long`, `float`, `double`, `string` ("`double`" when ommited), and assigned to the property. Additionally, the editing expression may be defined in a file. For that, the value of EXPRESSION must be in the format "`file:FILE`" where FILE is a python program which contain the fuction "`edit_function`" whose return value will define the property. 

  The expression syntax is as follows: For vertex filters a variable "`v`" is defined and for edge filters, a variable "`e`", corresponding to the current vertex or edge, respectively. For all filters a variable "`g`" also is defined. Those variables are a instantiation of the "`Vertex`", "`Edge`" and "`Graph`"  python classes, respectively, which have the following member funcions:

  ===== Vertex =====
    '''in_degree()'''::
      Returns the in-degree of the vertex
    '''out_degree()'''::
      Returns the out-degree of the vertex
    '''get_property(name)::
      Returns the value of the property specified by "name"
    '''put_property(name, value)::
      Modifies the value of the property specified by "name"
    '''in_edges()'''::
      Returns the in-edge iterator of the vertex
    '''out_edges()'''::
      Returns the out-edge iterator of the vertex

  ===== Edge =====
    '''source()'''::
      Returns the source Vertex
    '''target()'''::
      Returns target Vertex
    '''get_property(name)::
      Returns the value of the property specified by "name"
    '''set_property(name)::
      Modifies the value of the property specified by "name"
    '''n_parallel()'''::
      Return the number of parallel edges

  ===== Graph =====
    '''get_property(name)::
      Returns the value of the property specified by "name"
    '''set_property(name)::
      Modifies the value of the property specified by "name"
    '''edges()'''::
      Returns the edge iterator of the graph
    '''vertices()'''::
      Returns the vertex iterator of the graph

  Example:
  {{{
  $ graph-tool --load example.xml \
    --edit-edge-property="sqrt_weight|double|e.get_property('weight')**0.5" \
    --average-edge-property="weight|-" \
    --average-edge-property="sqrt_weight|-" 
  # average edge property (weight):
  2.550000        1.163373

  # average edge property (sqrt_weight):
  1.299736        0.328003
  }}}

  Suppose you want to get the distribution of the number of neighbours at a distance 2 from a vertex. You have just to define the editing routine, here called  `second-neighbours.py`:

  {{{
  #!python
  def edit_function():
      first_neighbours = set()
      second_neighbours = set()
      for n in v.out_edges():
          first_neighbours.add(n.target())
      for n in first_neighbours:
          for n2 in n.out_edges():
              if n2.target() not in first_neighbours:
                  second_neighbours.add(n2.target())
      return len(second_neighbours)
  }}}

  And then,

  {{{
  $ graph-tool --load example.xml \
    --edit-vertex-property="second|file:second-neighbours.py" \
    --vertex-histogram="second|-"
  # vertex histogram (second):
  1.0     6
  2.0     1
  }}}

  === Parallel edges removal ===
  [[T(Complexity|'''O(E log(<k>))''')]]

  A multigraph can be converted into a simple graph by labeling the parallel edges with an edge property and then filtering them out. The edges can be labeled with the following option:

  {{{
  --label-parallel-edges=PROPERTY       label parallel edges to PROPERTY
  }}}

  This will create (or replace) a property map with name given by PROPERTY, which will have integer values. The parallel edges will be labeled increasingly starting from zero, in a non-specified order. The graph can thus be reduced to a simple graph by filtering out edges with values > 0. See GraphFiltering above.


name: GraphModification
author: count0
ipnr: 201.81.210.76
text:
  [[Include(DocToc)]]
  == Graph Modifications ==

  There's a couple of options which change the internally kept graph.

  === Listing Properties ===
  [[T(Complexity|'''O(1)''')]]

  This doesn't really modify the graph, but it is useful for the options below. All graph properties can be listed with the "{{{--list-properties}}}" option.
  Example (see below for more details):

  {{{
  $ graph-tool --load example.xml --list-properties
  weight          (edge)    type: double

  $ graph-tool --load example.xml  \
    --edit-graph-property="name|string|'foo'" \
    --edit-vertex-property="indeg_over_2|float|v.in_degree()/2.0" \
    --edit-edge-property="weight_tresh|boolean|e.get_property('weight') > 1.0" \
    --list-properties 
  indeg_over_2    (vertex)  type: float
  name            (graph)   type: string
  weight          (edge)    type: double
  weight_tresh    (edge)    type: boolean
  }}}


  === Removing Properties ===
  [[T(Complexity|'''O(1)''')]]

  Vertex, edge and graph properties can be removed from the graph with the options "{{{--remove-vertex-property}}}", "{{{--remove-edge-property}}}" and "{{{--remove-graph-property}}}", which take the name of the property to be removed as parameter.

  === Vertex and Edge Indexes ===
  [[T(Complexity|'''O(1)''')]]

  Vertices and Edges are identified internally by indexes. Those can be inserted as properties with the options "{{{--insert-vertex-index-property}}}" and "{{{--insert-edge-index-property}}}", which take as argument the name by which the property will be called.

  === Creating and modifying properties ===
  [[T(Complexity|'''O(V)''' or '''O(E)''' (or O(1) for graph)]]

  New properties can be created and old ones modified (replaced) the the following options:

  {{{
  --edit-vertex-property=PROPERTY[|TYPE]|EXPRESSION     edit the selected vertex property
  --edit-edge-property=PROPERTY[|TYPE]|EXPRESSION       edit the selected edge property
  --edit-graph-property=PROPERTY[|TYPE]|EXPRESSION      edit the selected graph property
  }}}

  The PROPERTY parameter takes the name of the property which will be created or modified. The EXPRESSION parameter is a python expression which will be evaluated to a value of type TYPE, which can be any of `boolean`, `int`, `long`, `float`, `double`, `string` ("`double`" when ommited), and assigned to the property. Additionally, the editing expression may be defined in a file. For that, the value of EXPRESSION must be in the format "`file:FILE`" where FILE is a python program which contain the fuction "`edit_function`" whose return value will define the property. 

  The expression syntax is as follows: For vertex filters a variable "`v`" is defined and for edge filters, a variable "`e`", corresponding to the current vertex or edge, respectively. For all filters a variable "`g`" also is defined. Those variables are a instantiation of the "`Vertex`", "`Edge`" and "`Graph`"  python classes, respectively, which have the following member funcions:

  ===== Vertex =====
    '''in_degree()'''::
      Returns the in-degree of the vertex
    '''out_degree()'''::
      Returns the out-degree of the vertex
    '''get_property(name)::
      Returns the value of the property specified by "name"
    '''put_property(name, value)::
      Modifies the value of the property specified by "name"
    '''in_edges()'''::
      Returns the in-edge iterator of the vertex
    '''out_edges()'''::
      Returns the out-edge iterator of the vertex

  ===== Edge =====
    '''source()'''::
      Returns the source Vertex
    '''target()'''::
      Returns target Vertex
    '''get_property(name)::
      Returns the value of the property specified by "name"
    '''set_property(name)::
      Modifies the value of the property specified by "name"
    '''n_parallel()'''::
      Return the number of parallel edges

  ===== Graph =====
    '''get_property(name)::
      Returns the value of the property specified by "name"
    '''set_property(name, value)::
      Modifies the value of the property specified by "name"
    '''edges()'''::
      Returns the edge iterator of the graph
    '''vertices()'''::
      Returns the vertex iterator of the graph

  Example:
  {{{
  $ graph-tool --load example.xml \
    --edit-edge-property="sqrt_weight|double|e.get_property('weight')**0.5" \
    --average-edge-property="weight|-" \
    --average-edge-property="sqrt_weight|-" 
  # average edge property (weight):
  2.550000        1.163373

  # average edge property (sqrt_weight):
  1.299736        0.328003
  }}}

  Suppose you want to get the distribution of the number of neighbours at a distance 2 from a vertex. You have just to define the editing routine, here called  `second-neighbours.py`:

  {{{
  #!python
  def edit_function():
      first_neighbours = set()
      second_neighbours = set()
      for n in v.out_edges():
          first_neighbours.add(n.target())
      for n in first_neighbours:
          for n2 in n.out_edges():
              if n2.target() not in first_neighbours:
                  second_neighbours.add(n2.target())
      return len(second_neighbours)
  }}}

  And then,

  {{{
  $ graph-tool --load example.xml \
    --edit-vertex-property="second|file:second-neighbours.py" \
    --vertex-histogram="second|-"
  # vertex histogram (second):
  1.0     6
  2.0     1
  }}}

  === Parallel edges removal ===
  [[T(Complexity|'''O(E log(<k>))''')]]

  A multigraph can be converted into a simple graph by labeling the parallel edges with an edge property and then filtering them out. The edges can be labeled with the following option:

  {{{
  --label-parallel-edges=PROPERTY       label parallel edges to PROPERTY
  }}}

  This will create (or replace) a property map with name given by PROPERTY, which will have integer values. The parallel edges will be labeled increasingly starting from zero, in a non-specified order. The graph can thus be reduced to a simple graph by filtering out edges with values > 0. See GraphFiltering above.


