<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>复杂网络 on Zeqiang Fang | 方泽强</title><link>https://zeqiang.fun/categories/%E5%A4%8D%E6%9D%82%E7%BD%91%E7%BB%9C/</link><description>Recent content in 复杂网络 on Zeqiang Fang | 方泽强</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Fri, 01 Jan 2021 00:00:00 +0000</lastBuildDate><atom:link href="https://zeqiang.fun/categories/%E5%A4%8D%E6%9D%82%E7%BD%91%E7%BB%9C/" rel="self" type="application/rss+xml"/><item><title>图存储与计算（Network Storage &amp; Computing)</title><link>https://zeqiang.fun/cn/2021/01/network-storage-and-computing/</link><pubDate>Fri, 01 Jan 2021 00:00:00 +0000</pubDate><guid>https://zeqiang.fun/cn/2021/01/network-storage-and-computing/</guid><description><![CDATA[
        <blockquote>
<p>本文为<a href="/categories/%E5%A4%8D%E6%9D%82%E7%BD%91%E7%BB%9C/">《复杂网络系列》</a>文章</p>
</blockquote>
<h2 id="图存储">图存储</h2>
<h3 id="语义网络与-rdf-存储">语义网络与 RDF 存储</h3>
<p>1968 年 Ross Quillian 在其博士论文中最先提出<strong>语义网络</strong>（Semantic Web），把它作为人类联想记忆的一个显式心理学模型，并在他设计的可教式语言理解器 TLC（Teachable Language Comprehenden）中用作知识表示方法。</p>
<p>语义网络的基本思想是在网络中，用“节点”代替概念，用节点间的“连接弧”（称为联想弧）代替概念之间的关系，因此，语义网络又称联想网络。它在形式上是一个带标识的有向图。由于所有的概念节点均通过联想弧彼此相连知识推导。</p>
<p>一个语义网络的基本构成如下：</p>
<ul>
<li>语义网络中的节点：表示各种事物、概念、情况、属性、动作、状态等，每个节点可以带有若干属性，一般用框架或元组表示。此外，节点还可以是一个语义子网络，形成一个多层次的嵌套结构。</li>
<li>语义网络中的弧：表示各种语义联系，指明它所连接的节点间某种语义关系。</li>
<li>节点和弧都必须带有标识，以便区分各种不同对象以及对象间各种不同的语义联系。</li>
</ul>
<p>之后 Tim Berners-Lee 又提出了<strong>语义网堆栈</strong>（Semantic Web Stack）的概念。语义网堆栈利用图示解释是不同层面的语言所构成的层级结构，其中，每一层面都将利用下游层面的能力，语义网堆栈如下图所示：</p>
<img src="/images/cn/2021-01-01-network-storage-and-computing/sweb-stack-zh.png" width="60%" />
<p><strong>资源描述框架</strong>（Resource Description Framework，RDF）是用于描述网络资源的 W3C 标准，比如网页的标题、作者、修改日期、内容以及版权信息。</p>
<p>RDF 使用 Web 标识符来标识事物，并通过属性和属性值来描述资源。</p>
<p>对资源、属性和属性值的解释：</p>
<ul>
<li>资源是可拥有 URI 的任何事物，比如 <code>http://www.w3school.com.cn/rdf</code></li>
<li>属性是拥有名称的资源，比如 <code>author</code> 或 <code>homepage</code></li>
<li>属性值是某个属性的值，比如 <code>David</code> 或 <code>http://www.w3school.com.cn</code>（请注意一个属性值可以是另外一个资源)</li>
</ul>
<p>下面是一个 RDF 示例文档（这是一个简化的例子，命名空间被忽略了）：</p>
<pre><code class="language-xml">&lt;?xml version=&quot;1.0&quot;?&gt;

&lt;RDF&gt;
  &lt;Description about=&quot;http://www.w3school.com.cn/RDF&quot;&gt;
    &lt;author&gt;David&lt;/author&gt;
    &lt;homepage&gt;http://www.w3school.com.cn&lt;/homepage&gt;
  &lt;/Description&gt;
&lt;/RDF&gt;
</code></pre>
<p><strong>资源</strong>、<strong>属性</strong>和<strong>属性值</strong>的组合可形成一个陈述（被称为陈述的主体、谓语和客体)。上述的 RDF 文档包含了如下两个陈述：</p>
<ul>
<li>陈述：The <code>author</code> of <code>http://www.w3school.com.cn/rdf</code> is <code>David</code>
<ul>
<li>陈述的主体是：<code>http://www.w3school.com.cn/rdf</code></li>
<li>谓语是：<code>author</code></li>
<li>客体是：<code>David</code></li>
</ul>
</li>
<li>陈述：The <code>homepage</code> of <code>http://www.w3school.com.cn/rdf</code> is <code>http://www.w3school.com.cn</code>
<ul>
<li>陈述的主体是：<code>http://www.w3school.com.cn/rdf</code></li>
<li>谓语是：<code>homepage</code></li>
<li>客体是：<code>http://www.w3school.com.cn</code></li>
</ul>
</li>
</ul>
<p>更多 RDF 介绍请参见：https://www.w3school.com.cn/rdf/index.asp 。</p>
<p><a href="https://jena.apache.org/">Apache Jena</a> 是一个用于构建<strong>语义网络</strong>（Semantic Web）和<strong>链接数据</strong>（Linked Data）应用的开源 Java 框架。Jena 提供了 3 大部分功能：</p>
<ol>
<li>RDF
<ul>
<li>RDF API：提供构建和读取 RDF 图的核心 API，并利用 <a href="https://en.wikipedia.org/wiki/RDF/XML">RDF/XML</a> 或 <a href="https://en.wikipedia.org/wiki/Turtle_(syntax)">Turtle</a> 等数据类型序列化数据。</li>
<li>ARQ（SPARQL)：提供一种 SPARQL 1.1 的编译引擎 ARQ 用于查询 RDF。</li>
</ul>
</li>
<li>Triple store
<ul>
<li>TDB：提供一种原生高效的 Triple 存储 TDB，全面支持 Jena APIs。</li>
<li>Fuseki：提供 REST 风格的 RDF 数据交互方式。</li>
</ul>
</li>
<li>OWL
<ul>
<li>Ontology API：通过 RDFS，OWL 等为 RDF 数据添加更多语义信息。</li>
<li>Inference API：通过内置的 OWL 和 RDFS <a href="https://en.wikipedia.org/wiki/Semantic_reasoner">语义推理器</a> 构建个性化的推理规则。</li>
</ul>
</li>
</ol>
<p>下面以 <strong>Graph of The Gods</strong> 的关系图对 Jena 的基本功能进行说明。<strong>Graph of The Gods</strong> 是一张描述希腊神话相关事物之间关系的图，其中顶点的类型有：titan（泰坦，希腊神话中曾经统治师姐的古老神族)，god（神)，demigod（半神)，human（人)，monster（怪物)，location（地点)；关系的类型有：father（父亲)，brother（兄弟)，mother（母亲)，battled（战斗)，lives（居住)。</p>
<p><img src="/images/cn/2021-01-01-network-storage-and-computing/graph-of-the-gods.svg" alt=""></p>
<p>以 Apache Tomcat 作为容器来安装 Apache Jena Fuseki，下载最新版的 Apache Jena Fuseki 并解压，将其中的 fuseki.war 复制到已经安装并运行的 Apache Tomcat 的 webapps 路径下。安装完毕后，进入 http://127.0.0.1:8080/fuseki 即可使用 Apache Jena Fuseki。</p>
<p><img src="/images/cn/2021-01-01-network-storage-and-computing/apache-jena-fuseki.png" alt=""></p>
<p>在导入 Graph of The Gods 数据后，执行如下查询语句可以获得 <code>jupiter</code> 的所有兄弟：</p>
<pre><code class="language-sparql">PREFIX gods: &lt;http://leovan.me/gods/&gt;

SELECT DISTINCT ?god
WHERE {
  ?god gods:brother gods:jupiter
}
</code></pre>
<p>查询结果为：</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th>god</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1</td>
          <td>gods:pluto</td>
      </tr>
      <tr>
          <td>2</td>
          <td>gods:neptune</td>
      </tr>
  </tbody>
</table>
<h3 id="图数据库">图数据库</h3>
<p><strong>图数据库</strong>是一个使用图结构进行语义查询的数据库，它使用节点、边和属性来表示和存储数据。不同于关系型数据库，图数据库为 NoSQL（Not Only SQL）的一种，属于联机事务处理（OLTP）的范畴，可以解决现有关系数据库的局限性。</p>
<p>下图展示了近年来不同类型数据库的流行度趋势，不难看出近年来越来越多的人开始关注图数据库。</p>
<figure>
  <img data-src="/images/cn/2021-01-01-network-storage-and-computing/db-engines-database-categories-trend.png" class="lazyload"/>
  <figcaption><p class="figcaption">数据库流行度趋势 <a href="https://db-engines.com/en/ranking_categories">https://db-engines.com/en/ranking_categories</a></p></figcaption>
</figure>
<p>截止到 2020 年 12 月，图数据库的排名如下图所示：</p>
<figure>
  <img data-src="/images/cn/2021-01-01-network-storage-and-computing/db-engines-graph-database-ranking.png" class="lazyload"/>
  <figcaption><p class="figcaption">图数据库排名 <a href="https://db-engines.com/en/ranking/graph+dbms">https://db-engines.com/en/ranking/graph+dbms</a></p></figcaption>
</figure>
<p>其中，<a href="https://neo4j.com/">Neo4j</a>、<a href="https://janusgraph.org/">JanusGraph</a>、<a href="https://dgraph.io/">Dgraph</a>、<a href="https://www.tigergraph.com/">TigerGraph</a>、<a href="https://nebula-graph.io/">Nebula Graph</a> 均为时下常用的图数据库。从下图的流行度趋势角度来看，JanusGraph、Dgraph、TigerGraph 和 Nebula Graph 等后起之秀发展迅速。</p>
<figure>
  <img data-src="/images/cn/2021-01-01-network-storage-and-computing/db-engines-graph-database-trend.png" class="lazyload"/>
  <figcaption><p class="figcaption">图数据库流行度趋势 <a href="https://db-engines.com/en/ranking_trend/graph+dbms">https://db-engines.com/en/ranking_trend/graph+dbms</a></p></figcaption>
</figure>
<p>不同的图数据库有着不同的优劣势，用户可以根据实际业务场景选择合适的图数据库。下面给到一些较新的图数据库对比和评测：</p>
<ol>
<li><a href="https://nebula-graph.com.cn/posts/benchmarking-mainstraim-graph-databases-dgraph-nebula-graph-janusgraph/">主流开源分布式图数据库 Benchmark</a></li>
<li><a href="https://nebula-graph.com.cn/posts/performance-comparison-neo4j-janusgraph-nebula-graph/">图数据库对比：Neo4j vs Nebula Graph vs HugeGraph</a></li>
<li><a href="https://www.tigergraph.com.cn/wp-content/uploads/2018/10/TigerGraph-Benchmark-Report-2018-1.pdf">图分析系统基准测试报告</a></li>
<li><a href="https://fma-ai.cn/pdf/FMA_benchmark.pdf">图数据平台产品测试报告</a></li>
</ol>
<h3 id="查询语言">查询语言</h3>
<p><strong>图查询语言</strong>（Graph Query Language，GQL）是一种用于图数据库的查询语言，类比于关系型数据库的查询语言 SQL。2019 年 9 月，GQL 被提议为一种新的数据库查询语言（<a href="https://www.iso.org/standard/76120.html">ISO/IEC WD 39075</a>），目前仍处于开发当中，因此市面上还没有统一的图查询语言标准。</p>
<h4 id="gremlin">Gremlin</h4>
<p><a href="https://tinkerpop.apache.org/gremlin.html">Gremlin</a> 是 <a href="https://tinkerpop.apache.org/">Apache TinkerPop</a> 框架下的图遍历语言。Gremlin 适用于基于 OLTP 的图数据库以及基于 OLAP 的图分析引擎，支持命令式和声明式查询。支持 Gremlin 的图数据库有：Neo4j、JanusGraph 等。</p>
<h4 id="cypher">Cypher</h4>
<p><a href="http://www.opencypher.org/">Cypher</a> 是一种声明式图查询语言，这使得在不必编写遍历逻辑的情况下可以实现高效的查询。支持 Cypher 的图数据库有：Neo4j、RedisGraph、Nebula Graph 等。</p>
<h4 id="ngql">nGQL</h4>
<p><a href="https://docs.nebula-graph.com.cn/manual-CN/1.overview/1.concepts/2.nGQL-overview/">nGQL</a> 是一种声明式的图查询语言，支持图遍历、模式匹配、聚合运算和图计算等特性。支持 nGQL 的图数据库有：Nebula Graph。</p>
<h4 id="比较">比较</h4>
<p>针对 3 种不同的查询语言，对于图中相关概念的表示也略有不同，如下表所示：</p>
<table>
  <thead>
      <tr>
          <th style="text-align: left">术语</th>
          <th style="text-align: left">Gremlin</th>
          <th style="text-align: left">Cypher</th>
          <th style="text-align: left">nGQL</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td style="text-align: left">点</td>
          <td style="text-align: left">Vertex</td>
          <td style="text-align: left">Node</td>
          <td style="text-align: left">Vertex</td>
      </tr>
      <tr>
          <td style="text-align: left">边</td>
          <td style="text-align: left">Edge</td>
          <td style="text-align: left">Relationship</td>
          <td style="text-align: left">Edge</td>
      </tr>
      <tr>
          <td style="text-align: left">点类型</td>
          <td style="text-align: left">Label</td>
          <td style="text-align: left">Label</td>
          <td style="text-align: left">Tag</td>
      </tr>
      <tr>
          <td style="text-align: left">边类型</td>
          <td style="text-align: left">label</td>
          <td style="text-align: left">RelationshipType</td>
          <td style="text-align: left">edge type</td>
      </tr>
      <tr>
          <td style="text-align: left">点 ID</td>
          <td style="text-align: left">vid</td>
          <td style="text-align: left">id(n)</td>
          <td style="text-align: left">vid</td>
      </tr>
      <tr>
          <td style="text-align: left">边 ID</td>
          <td style="text-align: left">eid</td>
          <td style="text-align: left">id(r)</td>
          <td style="text-align: left">无</td>
      </tr>
      <tr>
          <td style="text-align: left">插入</td>
          <td style="text-align: left">add</td>
          <td style="text-align: left">create</td>
          <td style="text-align: left">insert</td>
      </tr>
      <tr>
          <td style="text-align: left">删除</td>
          <td style="text-align: left">drop</td>
          <td style="text-align: left">delete</td>
          <td style="text-align: left">delete / drop</td>
      </tr>
      <tr>
          <td style="text-align: left">更新属性</td>
          <td style="text-align: left">setProperty</td>
          <td style="text-align: left">set</td>
          <td style="text-align: left">update</td>
      </tr>
  </tbody>
</table>
<p>更多不同查询语言之间的详细对比可以参见如下资料：</p>
<ol>
<li><a href="https://nebula-graph.com.cn/posts/graph-query-language-comparison-cypher-gremlin-ngql/">一文了解各大图数据库查询语言 | 操作入门篇</a></li>
<li><a href="https://nebula-graph.com.cn/posts/sql-vs-ngql-comparison/">文档解读 ｜ SQL vs. nGQL</a></li>
</ol>
<h2 id="图计算">图计算</h2>
<h3 id="图计算框架">图计算框架</h3>
<h4 id="graphx">GraphX</h4>
<p><a href="https://spark.apache.org/graphx/">GraphX</a> 是一个基于 <a href="https://spark.apache.org/">Spark</a> 大规模图计算框架。GraphX 通过引入一个包含带有属性的顶点和变的有向图对 Spark 的 RDD 进行了扩展。通过 subgraph、joinVertices 和 aggregateMessages 等算子实现了 PageRank、连通子图、LPA 等图算法。</p>
<h4 id="plato">Plato</h4>
<p><a href="https://github.com/Tencent/plato">Plato</a> 是由腾讯开源的高性能图计算框架。Plato 主要提供两方面的能力：离线图计算和图表示学习，目前支持的图算法如下：</p>
<table>
  <thead>
      <tr>
          <th>算法分类</th>
          <th>算法</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>图特征</td>
          <td>树深度/宽度；节点数/边数/密度/节点度分布；N-阶度；HyperANF</td>
      </tr>
      <tr>
          <td>节点中心性指标</td>
          <td>KCore；Pagerank；Closeness；Betweenness</td>
      </tr>
      <tr>
          <td>连通图 &amp; 社团识别</td>
          <td>Connected-Component；LPA；HANP</td>
      </tr>
      <tr>
          <td>图表示学习</td>
          <td>Node2Vec-Randomwalk；Metapath-Randomwalk</td>
      </tr>
      <tr>
          <td>聚类/分圈算法</td>
          <td>FastUnfolding</td>
      </tr>
      <tr>
          <td>其他图相关算法</td>
          <td>BFS；共同类计算</td>
      </tr>
      <tr>
          <td>待开源算法</td>
          <td>Word2Vec；Line；GraphVite；GCN</td>
      </tr>
  </tbody>
</table>
<p>在计算性能上，Plato 与 Spark GraphX 在 PageRank 和 LPA 两个算法上的计算耗时与内存消耗对比如下图所示：</p>
<p><img src="/images/cn/2021-01-01-network-storage-and-computing/plaot-spark-graphx-benchmark.png" alt="Plato &amp; Spark GraphX Benchmark"></p>
<h4 id="graphscope">GraphScope</h4>
<p><a href="https://github.com/alibaba/GraphScope">GraphScope</a> 由有阿里巴巴开源的一个统一的分布式图计算平台。GraphScope 提供了一个一站式环境，可以通过用户友好的 Python 接口在集群内对图进行操作。GraphScope 利用一系列开源技术使得集群上的大规模图数据的多阶段处理变得简单，这些技术包括：用于分析的 <a href="https://github.com/alibaba/libgrape-lite">GRAPE</a>、用于查询的 <a href="https://github.com/alibaba/GraphScope/blob/master/interactive_engine">MaxGraph</a> 、用于图神经网络计算的 <a href="https://github.com/alibaba/graph-learn">Graph-Learn</a> 和用于提供高效内存数据交换的 <a href="https://github.com/alibaba/libvineyard">vineyard</a>。GraphScope 的整体架构如下图所示：</p>
<p><img src="/images/cn/2021-01-01-network-storage-and-computing/architecture-of-graphscope.png" alt="Architecture of GraphScope"></p>
<p>GraphScope Interactive Engine（GIE）是一个用于探索性分析大规模复杂图结构数据的引擎，它通过 Gremlin 提供高级别的图查询语言，同时提供自动并行执行功能。</p>
<p>GraphScope Analytical Engine（GAE）是一个基于 GRAPE <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> 提供并行图算法的分析引擎。除了提供基础的内置算法以外，GAE 允许用户利用 Python 基于 PIE <sup id="fnref1:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> 编程模型编写自定义算法，PIE 编程模型的运行方式如下图所示：</p>
<p><img src="/images/cn/2021-01-01-network-storage-and-computing/execution-model-in-gae.png" alt="Execution Model in GAE"></p>
<p>GraphScope 还提供以顶点为中心的 Pregel 模型 <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>，用户可以使用 Pregel 模型来实现自定义算法。</p>
<p>GraphScope Learning Engine（GLE）是一个用于开发和训练大规模图神经网络的分布式框架。GLE 提供基于全量图（用于 GCN、GAT 等算法）和采样子图（用于 GraphSAGE，FastGCN、GraphSAINT 等算法）两种不同方式训练图模型。整体架构如下图所示：</p>
<p><img src="/images/cn/2021-01-01-network-storage-and-computing/gle.png" alt="GLE"></p>
<h4 id="galileo">Galileo</h4>
<p>Galileo 是由京东零售研发的图计算平台，提供离线和在线图计算和图数据服务能力。目前 Galileo 暂未开源，待开源后补充相关信息。</p>
<h3 id="图神经网络">图神经网络</h3>
<p>关于图神经网络内容，请参见之前的博客 <a href="/cn/2020/04/graph-embedding-and-gnn/">图嵌入 (Graph Embedding) 和图神经网络 (Graph Neural Network)</a>。</p>
<h2>:tada::tada::tada: Happe New Year! :tada::tada::tada:</h2>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Fan, W., Yu, W., Xu, J., Zhou, J., Luo, X., Yin, Q., &hellip; &amp; Xu, R. (2018). Parallelizing sequential graph computations. <em>ACM Transactions on Database Systems (TODS)</em>, 43(4), 1-39.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Malewicz, G., Austern, M. H., Bik, A. J., Dehnert, J. C., Horn, I., Leiser, N., &amp; Czajkowski, G. (2010, June). Pregel: a system for large-scale graph processing. In <em>Proceedings of the 2010 ACM SIGMOD International Conference on Management of data</em> (pp. 135-146).&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>

        ]]></description></item><item><title>网络算法 (Network Algorithms)</title><link>https://zeqiang.fun/cn/2020/12/network-algorithms/</link><pubDate>Sat, 12 Dec 2020 00:00:00 +0000</pubDate><guid>https://zeqiang.fun/cn/2020/12/network-algorithms/</guid><description><![CDATA[
        <blockquote>
<p>本文为<a href="/categories/%E5%A4%8D%E6%9D%82%E7%BD%91%E7%BB%9C/">《复杂网络系列》</a>文章<br>
本文内容主要参考自：《网络科学引论》<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
</blockquote>
<h2 id="网络基础算法">网络基础算法</h2>
<h3 id="最短路径">最短路径</h3>
<p><strong>最短路径</strong>（shortest path）算法是寻找两个顶点之间的最短路径，寻找网络中最短路径的标准算法称为<strong>广度优先搜索</strong>（breadth-first search）。算法的基本思想如下图所示：</p>
<p><img src="/images/cn/2020-12-12-network-algorithms/bfs.png" alt=""></p>
<p>根据广度优先搜索的基本思想，不难证明距 <code>$s$</code> 最短距离为 <code>$d$</code> 的每个顶点都有一个到 <code>$s$</code> 的最短距离为 <code>$d - 1$</code> 的邻居顶点。一个简单的实现方式是，创建一个有 <code>$n$</code> 个元素的数组存储从源顶点 <code>$s$</code> 到其他所有顶点的距离，同时创建一个距离变量 <code>$d$</code> 来记录当前在搜索过程中所处的层数，算法的具体流程如下：</p>
<ol>
<li>遍历距离数组，查找到 <code>$s$</code> 的距离为 <code>$d$</code> 的所有顶点。</li>
<li>查找上述顶点的所有邻居顶点，如果同 <code>$s$</code> 的距离未知，则距离置为 <code>$d + 1$</code>。</li>
<li>如果距离未知的邻居顶点数量为零，则停止算法，否则将 <code>$d$</code> 的值加一并重复上述过程。</li>
</ol>
<p>这种方法在最坏的情况下时间复杂度为 <code>$O \left(m + n^2\right)$</code>，考虑多数网络的直径只随 <code>$\log n$</code> 增长，算法运行的时间复杂度为 <code>$O \left(m + n \log n\right)$</code>。</p>
<p>上述算法中步骤 1 是最耗时的部分，通过使用<strong>队列</strong>的数据结构我们可以避免每次都遍历列表来找到距离源顶点 <code>$s$</code> 距离为 <code>$d$</code> 的顶点。构造一个队列，一个指针指向下一个要读取的元素，另一个指针指向要填充的空位，这样距离为 <code>$d + 1$</code> 的顶点就会紧跟在距离为 <code>$d$</code> 的顶点后面，队列如下图所示：</p>
<p><img src="/images/cn/2020-12-12-network-algorithms/bfs-queue.png" alt=""></p>
<p>通过队列可以将算法的时间复杂度降至 <code>$O \left(m + n\right)$</code>，对于 <code>$m \propto n$</code> 的稀疏网络而言，<code>$O \left(m + n\right)$</code> 相当于 <code>$O \left(n\right)$</code>，所以算法的时间复杂度同顶点数量成正比。</p>
<p>通过对算法进行进一步修改则可以得到源顶点 <code>$s$</code> 到其他任何顶点的最短路径。方法是在原来的网络上构建一个新的有向网络，该网络代表最短路径，称为<strong>最短路径树</strong>（shortest path tree），通常情况下，该网络是一个有向非循环网络，而不是树。</p>
<p>对于加权网络，利用广度优先搜索无法找到最短路径，这里需要用到 Dijkstra 算法 <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> 进行求解。算法将图中的顶点分成两组 <code>$S$</code> 和 <code>$U$</code>，整个算法过程如下：</p>
<ol>
<li>初始状态，<code>$S$</code> 仅包含源顶点，即 <code>$S = \left\{v\right\}$</code>，<code>$U$</code> 包含其余顶点。如果 <code>$v$</code> 与 <code>$U$</code> 中的顶点 <code>$u$</code> 为邻居，则距离为边的权重，否则为无穷大。</li>
<li>从 <code>$U$</code> 中选择一个距离 <code>$v$</code> 最短的顶点 <code>$k$</code>，并把 <code>$k$</code> 加入到 <code>$S$</code> 中。</li>
<li>若从源点 <code>$v$</code> 经过顶点 <code>$k$</code> 到达 <code>$u$</code> 的距离比之前 <code>$v$</code> 到 <code>$u$</code> 的距离短，则将距离修改为这个更短的距离。</li>
<li>重复步骤 2 和 3，直至所有顶点都包含在 <code>$S$</code> 中。</li>
</ol>
<p>整个算法过程的可视化效果如下图所示：</p>
<p><img src="/images/cn/2020-12-12-network-algorithms/dijkstras-progress.gif" alt=""></p>
<p>Dijkstra 算法的时间复杂度为 <code>$O \left(m + n^2\right)$</code>，通过二叉堆的数据结构可以将时间复杂度优化至 <code>$O \left(\left(m + n\right) \log n\right)$</code>。</p>
<p>Dijkstra 算法虽然能够处理加权网络，但不能处理存在负权重的网络，需要利用 Floyd-Warshall 算法 <sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> 进行求解。更多 Floyd-Warshall 算法的细节请参见之前的博客<a href="/cn/2018/11/computational-complexity-and-dynamic-programming/">计算复杂性 (Computational Complexity) 与动态规划 (Dynamic Programming)</a>。</p>
<h3 id="最大流和最小割">最大流和最小割</h3>
<p>对于连接给定顶点 <code>$s$</code> 和 <code>$t$</code> 的两条路径，若没有共享边，则这两条路径是<strong>边独立</strong>的；若除 <code>$s$</code> 和 <code>$t$</code> 外不共享任何其他顶点，则这两条路径是<strong>顶点独立</strong>的。顶点之间的<strong>边连通度</strong>和<strong>顶点连通度</strong>分别是顶点之间边独立路径数和顶点独立路径数。连通度是度量顶点之间连通鲁棒性的简单参数。假设一个网络是一个管线网络，其中每个管线的容量均为单位流量，那么边连通度等于从 <code>$s$</code> 流向 <code>$t$</code> 的<strong>最大流</strong>。</p>
<p><strong>增广路径算法</strong>（Ford-Fulkerson Algorithm，FFA）是计算最大流最简单的算法。基本思想是：首先利用广度优先搜索算法找到一条从源 <code>$s$</code> 到目标 <code>$t$</code> 的路径。该步骤“消耗”了网络中的一些边，将这些边的容量填充满后，它们不再承载更多流量。之后在剩余边中找到从 <code>$s$</code> 到 <code>$t$</code> 的另一条路径，重复该过程直到找不到更多的路径为止。</p>
<p>但这还不是一个有效的算法，如下图中的 (a) 所示，如果在 <code>$s$</code> 和 <code>$t$</code> 之间运用广度优先搜索，可以发现黑色标记的路径。一旦这些边的容量被填充满，就不能在剩余边中找到从 <code>$s$</code> 到 <code>$t$</code> 的更多路径，但很明显，从 <code>$s$</code> 到 <code>$t$</code> 有两条边独立路径（上下各一条）。</p>
<p><img src="/images/cn/2020-12-12-network-algorithms/augmenting-path-algorithm.png" alt=""></p>
<p>解决该问题的一个简单修正方法是允许网络流量在一条边中能够同时在两个方向流动。更一般地，因为一条边容许承载的最大流是在任意方向的单位流量，那么一条边可以有多个单位流量，只要保证他们能够相互抵消，并且最终每条边承载不超过一个单位流量。</p>
<p>增广路径算法的实现利用了<strong>剩余图</strong>（residual graph），这是一个有向网络，该网络中的有向边连接原网络中相应的顶点对，并在指定方向承载一个或多个单位流量。例如上图中 (c) 和 (d) 就是对应 (a) 和 (b) 的流量状态的剩余图。算法的正确性在这里就不过多展开说明，该算法在计算两个顶点之间的最大流的平均时间复杂度为 <code>$O \left(\left(m + n\right) m / n\right)$</code>。</p>
<p>在图论中，去掉其中所有边使一张网络不再连通的边集为图的<strong>割</strong>，一张图上最小的割为<strong>最小割</strong>。通过对增广路径算法进行改动即可以寻找到边独立路径、最小边割集和顶点独立路径。</p>
<h2 id="图划分和社团发现">图划分和社团发现</h2>
<p><strong>图划分</strong>（graph partitioning）和<strong>社团发现</strong>（community detection）都是指根据网络中的边的连接模式，把网络顶点划分成群组、簇或社团。将网络顶点划分成群组后最常见的属性是，同一群组内部的顶点之间通过边紧密连接，而不同群组之间只有少数边。</p>
<h3 id="图划分">图划分</h3>
<p>最简单的图划分问题是把网络划分成两部分，有时也称其为<strong>图对分</strong>（graph bisection）。图对分是把一个网络中的顶点划分成为两个指定规模的非重叠群组，使得不同群组之间相互连接的边数最小。群组之间的边数称为<strong>割集规模</strong>（cut size）。 利用穷举搜索解决该问题是极为耗时的，通过启发式算法我们可以找到较好的网络划分。</p>
<h4 id="kernighan-lin-算法">Kernighan-Lin 算法</h4>
<p>Kernighan-Lin 算法是由 Brian Kernighan 和 Shen Lin 在 1970 年提出的 <sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>，是图对分问题中最简单、最知名的启发式算法之一，如下图所示。</p>
<p><img src="/images/cn/2020-12-12-network-algorithms/kernighan%E2%80%93lin-algorithm.png" alt=""></p>
<p>先以任意方式将网络顶点按指定规模划分成两个群组，对于任何由分属不同群组的顶点 <code>$i$</code> 和顶点 <code>$j$</code> 组成的顶点对 <code>$\left(i, j\right)$</code>，交换 <code>$i$</code> 和 <code>$j$</code> 的位置，并计算交换前后两个群组之间割集规模的变化量。在所有顶点对中找到使割集规模减小最多的顶点对，或者若没有使割集规模减小的顶点对，则找到使割集规模增加最小的顶点对，交换这两个顶点。重复这个过程，同时保证网络中的每个顶点只能移动一次。</p>
<p>继续算法，每一步都交换最大程度减少或最小程度增加群组之间边数的顶点对，直到没有可以变换的顶点对，此时本轮算法停止。在完成所有交换后，检查网络在此过程中经过的每一个状态，然后选择割集规模最小的状态。最后，重复执行上述整个过程，每次始于上次发现的最优网络划分，直到割集规模不在出现改善。</p>
<p>Kernighan-Lin 算法的主要缺点是运算速度缓慢，采用一些技巧来改善算法也只能使时间复杂度降至 <code>$O \left(n^3\right)$</code>，因此该算法仅适用于有几百或几千个顶点的网络，而不适用于更大规模的网络。</p>
<h4 id="谱划分">谱划分</h4>
<blockquote>
<p>请先了解<a href="#%E9%99%84%E5%BD%95">附录</a>中的拉普拉斯算子和拉普拉斯矩阵等相关概念。</p>
</blockquote>
<p>考虑具有 <code>$n$</code> 个顶点 <code>$m$</code> 条边的网络，将其划分为两个群组，称为群组 1 和群组 2。可以把该划分的割集规模，也就是两个群组之间的边数表示为：</p>
<p><code>$$ \label{eq:r_1} R = \dfrac{1}{2} \sum_{i, j \text{ 属于不同群组}} A_{ij} $$</code></p>
<p>对于每个网络划分，定义有参数 <code>$s_i$</code> 组成的集合，集合中每个元素对应于一个顶点 <code>$i$</code>，则有：</p>
<p><code>$$ s_i = \left\{\begin{array}{ll} +1 &amp; \text{顶点 } i \text{ 在群组 1 中} \\ -1 &amp; \text{顶点 } i \text{ 在群组 2 中} \end{array}\right. $$</code></p>
<p>那么：</p>
<p><code>$$ \dfrac{1}{2} \left(1 - s_i s_j\right) = \left\{\begin{array}{ll} 1 &amp; \text{顶点 } i \text{ 和 } j \text{ 在不同的群组中} \\ 0 &amp; \text{顶点 } i \text{ 和 } j \text{ 在相同的群组中} \end{array}\right. $$</code></p>
<p>则式 \ref{eq:r_1} 可以改写为：</p>
<p><code>$$ \begin{aligned} R &amp; = \dfrac{1}{4} \sum_{ij} A_{ij} \left(1 - s_i s_j\right) \\ &amp; = \dfrac{1}{4} \left(k_i \delta_{ij} - A_{ij}\right) s_i s_j \\ &amp; = \dfrac{1}{4} \sum_{ij} L_{ij} s_i s_j \end{aligned} $$</code></p>
<p>其中，<code>$\delta_{ij}$</code> 是克罗内克函数，<code>$L_{ij}$</code> 是图拉普拉斯矩阵的第 <code>$ij$</code> 个元素。写成矩阵的形式有：</p>
<p><code>$$ R = \dfrac{1}{4} \mathbf{s}^{\top} \mathbf{L} \mathbf{s} $$</code></p>
<p>由于每个 <code>$s_i$</code> 的取值只能是 <code>$\left\{+1, -1\right\}$</code>，所以在给定 <code>$\mathbf{L}$</code> 时求解 <code>$\mathbf{s}$</code> 使其割集规模最小时并不容易。具体求解方法的推导在此不再展开说明，最终谱划分算法的过程如下所示：</p>
<ol>
<li>计算图拉普拉斯矩阵的第二小特征值 <code>$\lambda_2$</code>，称为网络的<strong>代数连通度</strong>（algebraic connectivity），及其对应的特征向量 <code>$\mathbf{v}_2$</code>。</li>
<li>按从大到小的顺序对特征向量的元素进行排序。</li>
<li>把前 <code>$n_1$</code> 个最大元素对应的顶点放入群组 1，其余放入群组 2，计算割集规模。</li>
<li>把前 <code>$n_1$</code> 个最小（注意：中文译本中有错误）元素对应的顶点放入群组 2，其余放入群组 1，并重新计算割集规模。</li>
<li>在两种网络划分中，选择割集规模较小的那个划分。</li>
</ol>
<p>谱划分方法在稀疏网络上的时间复杂度为 <code>$O \left(n^2\right)$</code>，这比 Kernighan-Lin 算法时间复杂度少了一个因子 <code>$n$</code>，从而使该算法能应用于更大规模的网络。</p>
<h3 id="社团发现">社团发现</h3>
<p><strong>社团发现</strong>（社区发现，社群发现，Community Detection）的基本目的与图划分类似，即把网络分成几个节点点群组，并使节点群组之间的连接较少。主要的差别就是群组的数量和规模是不确定的。社团发现的算法分类和具体实现很多，本文仅介绍几个常用的算法，更多方法及其细节请参见如下开放资源：</p>
<ol>
<li>Community Detection in Graphs <sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup></li>
<li>Deep Learning for Community Detection: Progress, Challenges and Opportunities <sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup></li>
<li>复杂网络社团发现算法研究新进展 <sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup></li>
<li><a href="https://github.com/benedekrozemberczki/awesome-community-detection">benedekrozemberczki/awesome-community-detection</a></li>
</ol>
<h4 id="fast-unfolding-louvain">Fast Unfolding (Louvain)</h4>
<p><strong>Fast Unfolding (Louvain)</strong> <sup id="fnref:8"><a href="#fn:8" class="footnote-ref" role="doc-noteref">8</a></sup> 是一种基于模块度的社团发现算法，通过模块度来衡量一个社团的紧密程度。算法包含两个阶段：</p>
<ol>
<li>历遍网络中所有的节点，通过比较将节点给每个邻居社团带来的模块度变化，将这个节点加入到使模块度增加最大的社团中。</li>
<li>对于步骤 1 的结果，将属于同一个社团的节点合并成为一个大的节点，进而重型构造网络。新的节点之间边的权重是所包含的之前所有节点之间相连的边权重之和，然后重复步骤 1。</li>
</ol>
<p>算法的两个步骤如下图所示：</p>
<p><img src="/images/cn/2020-12-12-network-algorithms/louvain.png" alt=""></p>
<h4 id="label-propagation-algorithm-lpa">Label Propagation Algorithm (LPA)</h4>
<p><strong>标签传播算法</strong>（Label Propagation Algorithm，LPA）是一种基于半监督学习的社团发现算法。对于每个节点都有对应的标签（即节点所隶属的社团），在算法迭代过程中，节点根据其邻居节点更新自身的标签。更新的规则是选择邻居节点中最多的标签作为自身的标签。</p>
<p>标签传播的过程中，节点的标签更新方式分为<strong>同步更新</strong>和<strong>异步更新</strong>两种方式。同步更新是指对于节点 <code>$x$</code>，在第 <code>$t$</code> 步时，根据其所有邻居节点在 <code>$t - 1$</code> 步时的标签对其进行更新，即：</p>
<p><code>$$ C_{x}(t)=f\left(C_{x_{1}}(t-1), C_{x_{2}}(t-1), \cdots, C_{x_{k}}(t-1)\right) $$</code></p>
<p>同步更新对于一个二分或者近似二分的网络来说可能会出现标签震荡的现象。对于异步更新方式，更新公式为：</p>
<p><code>$$ C_{x}(t)=f\left(C_{x_{i 1}}(t), \cdots, C_{x_{i m}}(t), C_{x_{i(m+1)}}(t-1), \cdots, C_{x_{i k}}(t-1)\right) $$</code></p>
<p>其中，邻居节点 <code>$x_{i1}, \cdots, x_{im}$</code> 的标签在第 <code>$t$</code> 步时已经更新过，而 <code>$x_{i(m+1)}, \cdots, x_{ik}$</code> 的标签还未更新。</p>
<h2 id="附录">附录</h2>
<p><strong>拉普拉斯算子</strong>（Laplace operator，Laplacian）是由欧式空间中的一个函数的梯度的散度给出的微分算子，通常写作 <code>$\Delta$</code>，<code>$\nabla^2$</code> 或 <code>$\nabla \cdot \nabla$</code>。</p>
<p><strong>梯度</strong>（gradient）是对多元导数的概括，函数沿着梯度的方向变化最快，变化率则为梯度的模。假设二元函数 <code>$f \left(x, y\right)$</code> 在区域 <code>$G$</code> 内具有一阶连续偏导数，点 <code>$P \left(x, y\right) \in G$</code>，则称向量：</p>
<p><code>$$ \nabla f = \left(\dfrac{\partial f}{\partial x}, \dfrac{\partial f}{\partial y} \right) = \dfrac{\partial f}{\partial x} \mathbf{i} + \dfrac{\partial f}{\partial y} \mathbf{j} $$</code></p>
<p>为函数 <code>$f$</code> 在点 <code>$P$</code> 处的梯度，其中 <code>$\mathbf{i}$</code> 和 <code>$\mathbf{j}$</code> 为单位向量，分别指向 <code>$x$</code> 和 <code>$y$</code> 坐标方向。</p>
<p><strong>散度</strong>（divergence）将向量空间上的一个向量场对应到一个标量场上，记为 <code>$\nabla \cdot$</code>。散度的意义是场的有源性，当 <code>$\nabla \cdot F &gt; 0$</code> 时，表示该点是发源点；当 <code>$\nabla \cdot F &lt; 0$</code> 时，表示该点是汇聚点；当 <code>$\nabla \cdot F = 0$</code> 时，表示该点无源，如下图所示。</p>
<p><img src="/images/cn/2020-12-12-network-algorithms/divergence.png" alt=""></p>
<p>拉普拉斯离散化后即为<strong>拉普拉斯矩阵</strong>（laplacian matrix），也称为<strong>调和矩阵</strong>（harmonic matrix）。离散化的拉普拉斯算子形式如下：</p>
<p><code>$$ \begin{aligned} \Delta f &amp; = \dfrac{\partial^2 f}{\partial x^2} + \dfrac{\partial^2 f}{\partial y^2} \\ &amp; = f \left(x + 1, y\right) + f \left(x - 1, y\right) - 2 f \left(x, y\right) + f \left(x, y + 1\right) + f \left(x, y - 1\right) - 2 f \left(x, y\right) \\ &amp; = f \left(x + 1, y\right) + f \left(x - 1, y\right) + f \left(x, y + 1\right) + f \left(x, y - 1\right) - 4 f \left(x, y\right) \end{aligned} $$</code></p>
<p>从上述离散化后的拉普拉斯算子形式可以看出，拉普拉斯矩阵表示的是对矩阵进行微小扰动后获得的收益。</p>
<p>设图 <code>$G$</code> 有 <code>$n$</code> 个节点，节点的邻域为 <code>$N$</code>，图上的函数 <code>$f = \left(f_1, f_2, \cdots, f_n\right)$</code>，其中 <code>$f_i$</code> 表示节点 <code>$i$</code> 处的函数值。对 <code>$i$</code> 进行扰动，其可能变为邻域内的任意一个节点 <code>$j \in N_i$</code>：</p>
<p><code>$$ \Delta f_{i}=\sum_{j \in N_{i}}\left(f_{i}-f_{j}\right) $$</code></p>
<p>设每一条边 <code>$e_{ij}$</code> 的权重为 <code>$w_{ij}$</code>，<code>$w_{ij} = 0$</code> 表示节点 <code>$i$</code> 和节点 <code>$j$</code> 不相邻，则有：</p>
<p><code>$$ \begin{aligned} \Delta f_i &amp; = \sum_{j \in N} w_{ij} \left(f_i - f_j\right) \\ &amp; = \sum_{j \in N} w_{ij} f_i - \sum_{j \in N} w_{ij} f_i \\ &amp; = d_i f_i - W_{i:} f  \end{aligned} $$</code></p>
<p>对于所有节点有：</p>
<p><code>$$ \begin{aligned} \Delta f &amp; = \left(\begin{array}{c} \Delta f_{1} \\ \vdots \\ \Delta f_{N} \end{array}\right)=\left(\begin{array}{c} d_{1} f_{1}-W_{1:} f \\ \vdots \\ d_{N} f_{N}-W_{N:} f \end{array}\right) \\ &amp; = \left(\begin{array}{ccc} d_{1} &amp; \cdots &amp; 0 \\ \vdots &amp; \ddots &amp; \vdots \\ 0 &amp; \cdots &amp; d_{N} \end{array}\right) f-\left(\begin{array}{c} W_{1:} \\ \vdots \\ W_{N:} \end{array}\right) f \\ &amp; = diag \left(d_i\right) f - W f \\ &amp; = \left(D - W\right) f \\ &amp; = L f \end{aligned} $$</code></p>
<p>令图 <code>$G$</code> 的邻接矩阵为 <code>$W$</code>，度矩阵为 <code>$D$</code>，从上式可知拉普拉斯矩阵 <code>$L = D - W$</code>，其中：</p>
<p><code>$$ L_{ij} = \left\{\begin{array}{ll} \deg \left(v_i\right) &amp; \text{如果 } i = j \\ -1 &amp; \text{如果 } i \neq j \text{ 且 } v_i \text{ 与 } v_j \text{ 相邻} \\ 0 &amp; \text{其他情况} \end{array}\right. $$</code></p>
<p>以下面的图为例：</p>
<p><img src="/images/cn/2020-12-12-network-algorithms/laplacian-matrix-demo-graph.png" alt=""></p>
<p>邻接矩阵为：</p>
<p><code>$$ \left(\begin{array}{llllll} 0 &amp; 1 &amp; 0 &amp; 0 &amp; 1 &amp; 0 \\ 1 &amp; 0 &amp; 1 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 1 &amp; 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; 1 &amp; 0 &amp; 1 &amp; 1 \\ 1 &amp; 1 &amp; 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 &amp; 0 \end{array}\right) $$</code></p>
<p>度矩阵为：</p>
<p><code>$$ \left(\begin{array}{cccccc} 2 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 3 &amp; 0 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; 2 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 3 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 0 &amp; 3 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1 \end{array}\right) $$</code></p>
<p>拉普拉斯矩阵为：</p>
<p><code>$$ \left(\begin{array}{rrrrrr} 2 &amp; -1 &amp; 0 &amp; 0 &amp; -1 &amp; 0 \\ -1 &amp; 3 &amp; -1 &amp; 0 &amp; -1 &amp; 0 \\ 0 &amp; -1 &amp; 2 &amp; -1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; -1 &amp; 3 &amp; -1 &amp; -1 \\ -1 &amp; -1 &amp; 0 &amp; -1 &amp; 3 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1 &amp; 0 &amp; 1 \end{array}\right) $$</code></p>
<h2 id="开放资源">开放资源</h2>
<h3 id="常用网络算法包">常用网络算法包</h3>
<table>
  <thead>
      <tr>
          <th>名称</th>
          <th>语言</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="https://networkx.org/">NetworkX</a></td>
          <td><i class="icon icon-python">Python</i></td>
      </tr>
      <tr>
          <td><a href="https://graph-tool.skewed.de/">graph-tool</a></td>
          <td><i class="icon icon-python">Python</i></td>
      </tr>
      <tr>
          <td><a href="https://snap.stanford.edu/index.html">SNAP</a></td>
          <td><i class="icon icon-cpp">C++</i>, <i class="icon icon-python">Python</i></td>
      </tr>
      <tr>
          <td><a href="https://github.com/networkit/networkit">NetworKit</a></td>
          <td><i class="icon icon-cpp">C++</i>, <i class="icon icon-python">Python</i></td>
      </tr>
      <tr>
          <td><a href="https://igraph.org/">igraph</a></td>
          <td><i class="icon icon-c">C</i>, <i class="icon icon-cpp">C++</i>, <i class="icon icon-python">Python</i>, <i class="icon icon-r">R</i></td>
      </tr>
      <tr>
          <td><a href="https://github.com/JuliaGraphs/LightGraphs.jl">lightgraphs</a></td>
          <td><i class="icon icon-julia">Julia</i></td>
      </tr>
  </tbody>
</table>
<p>不同扩展包之间的性能比较如下表所示 <sup id="fnref:9"><a href="#fn:9" class="footnote-ref" role="doc-noteref">9</a></sup>：</p>
<table>
  <thead>
      <tr>
          <th>数据集</th>
          <th>算法</th>
          <th>graph-tool</th>
          <th>igraph</th>
          <th>LightGraphs</th>
          <th>NetworKit</th>
          <th>NetworkX</th>
          <th>SNAP</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Amazon</td>
          <td>CC</td>
          <td>0.08</td>
          <td>0.22</td>
          <td>0.07</td>
          <td>0.09</td>
          <td>2.22</td>
          <td>0.31</td>
      </tr>
      <tr>
          <td>Amazon</td>
          <td>k-core</td>
          <td>0.08</td>
          <td>0.15</td>
          <td>0.04</td>
          <td>0.15</td>
          <td>3.63</td>
          <td>0.37</td>
      </tr>
      <tr>
          <td>Amazon</td>
          <td>loading</td>
          <td>2.61</td>
          <td>0.57</td>
          <td>4.66</td>
          <td>0.98</td>
          <td>4.72</td>
          <td>1.61</td>
      </tr>
      <tr>
          <td>Amazon</td>
          <td>page rank</td>
          <td>0.04</td>
          <td>0.57</td>
          <td>0.02</td>
          <td>0.02</td>
          <td>8.59</td>
          <td>0.58</td>
      </tr>
      <tr>
          <td>Amazon</td>
          <td>shortest path</td>
          <td>0.03</td>
          <td>0.05</td>
          <td>0.01</td>
          <td>0.04</td>
          <td>1.37</td>
          <td>0.12</td>
      </tr>
      <tr>
          <td>Google</td>
          <td>CC</td>
          <td>0.28</td>
          <td>1.38</td>
          <td>0.29</td>
          <td>0.37</td>
          <td>7.77</td>
          <td>1.56</td>
      </tr>
      <tr>
          <td>Google</td>
          <td>k-core</td>
          <td>0.39</td>
          <td>0.92</td>
          <td>0.16</td>
          <td>0.83</td>
          <td>42.6</td>
          <td>1.31</td>
      </tr>
      <tr>
          <td>Google</td>
          <td>loading</td>
          <td>11.02</td>
          <td>3.87</td>
          <td>16.75</td>
          <td>4.38</td>
          <td>19.24</td>
          <td>7.56</td>
      </tr>
      <tr>
          <td>Google</td>
          <td>page rank</td>
          <td>0.36</td>
          <td>2.42</td>
          <td>0.06</td>
          <td>0.1</td>
          <td>33.5</td>
          <td>2.31</td>
      </tr>
      <tr>
          <td>Google</td>
          <td>shortest path</td>
          <td>0.08</td>
          <td>0.41</td>
          <td>0.01</td>
          <td>0.14</td>
          <td>3.41</td>
          <td>0.26</td>
      </tr>
      <tr>
          <td>Pokec</td>
          <td>CC</td>
          <td>1.83</td>
          <td>3.96</td>
          <td>1.5</td>
          <td>1.75</td>
          <td>61.74</td>
          <td>9.75</td>
      </tr>
      <tr>
          <td>Pokec</td>
          <td>k-core</td>
          <td>3.6</td>
          <td>5.99</td>
          <td>0.95</td>
          <td>5.05</td>
          <td>296.26</td>
          <td>6.91</td>
      </tr>
      <tr>
          <td>Pokec</td>
          <td>loading</td>
          <td>71.46</td>
          <td>25.75</td>
          <td>170.63</td>
          <td>26.77</td>
          <td>140.19</td>
          <td>52.73</td>
      </tr>
      <tr>
          <td>Pokec</td>
          <td>page rank</td>
          <td>1.1</td>
          <td>23.39</td>
          <td>0.21</td>
          <td>0.24</td>
          <td>239.75</td>
          <td>8.62</td>
      </tr>
      <tr>
          <td>Pokec</td>
          <td>shortest path</td>
          <td>0.48</td>
          <td>0.6</td>
          <td>0.05</td>
          <td>0.56</td>
          <td>5.65</td>
          <td>2.3</td>
      </tr>
  </tbody>
</table>
<h3 id="常用网络可视化软件">常用网络可视化软件</h3>
<table>
  <thead>
      <tr>
          <th>软件</th>
          <th>平台</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="https://cytoscape.org/">Cytoscape</a></td>
          <td><i class="icon icon-windows">Windows</i>, <i class="icon icon-macos">macOS</i>, <i class="icon icon-linux">Linux</i></td>
      </tr>
      <tr>
          <td><a href="https://gephi.org/">Gephi</a></td>
          <td><i class="icon icon-windows">Windows</i>, <i class="icon icon-macos">macOS</i>, <i class="icon icon-linux">Linux</i></td>
      </tr>
      <tr>
          <td><a href="https://tulip.labri.fr/TulipDrupal/">Tulip</a></td>
          <td><i class="icon icon-windows">Windows</i>, <i class="icon icon-macos">macOS</i>, <i class="icon icon-linux">Linux</i></td>
      </tr>
      <tr>
          <td><a href="http://mrvar.fdv.uni-lj.si/pajek/">Pajek</a></td>
          <td><i class="icon icon-windows">Windows</i></td>
      </tr>
  </tbody>
</table>
<p>不同可视化软件之间的比较如下表所示 <sup id="fnref:10"><a href="#fn:10" class="footnote-ref" role="doc-noteref">10</a></sup>：</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th>Cytoscape</th>
          <th>Tulip</th>
          <th>Gephi</th>
          <th>Pajek</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Scalability</td>
          <td>⭑⭑</td>
          <td>⭑</td>
          <td>⭑⭑⭑</td>
          <td>⭑⭑⭑⭑</td>
      </tr>
      <tr>
          <td>User friendliness</td>
          <td>⭑⭑</td>
          <td>⭑⭑⭑⭑</td>
          <td>⭑⭑⭑</td>
          <td>⭑</td>
      </tr>
      <tr>
          <td>Visual styles</td>
          <td>⭑⭑⭑⭑</td>
          <td>⭑⭑</td>
          <td>⭑⭑⭑</td>
          <td>⭑</td>
      </tr>
      <tr>
          <td>Edge bundling</td>
          <td>⭑⭑⭑</td>
          <td>⭑⭑⭑⭑</td>
          <td>⭑⭑</td>
          <td>-</td>
      </tr>
      <tr>
          <td>Relevance to biology</td>
          <td>⭑⭑⭑⭑</td>
          <td>⭑⭑</td>
          <td>⭑⭑⭑</td>
          <td>⭑</td>
      </tr>
      <tr>
          <td>Memory efficiency</td>
          <td>⭑</td>
          <td>⭑⭑</td>
          <td>⭑⭑⭑</td>
          <td>⭑⭑⭑⭑</td>
      </tr>
      <tr>
          <td>Clustering</td>
          <td>⭑⭑⭑⭑</td>
          <td>⭑⭑⭑</td>
          <td>⭑</td>
          <td>⭑⭑</td>
      </tr>
      <tr>
          <td>Manual node/edge editing</td>
          <td>⭑⭑⭑</td>
          <td>⭑⭑⭑⭑</td>
          <td>⭑⭑⭑</td>
          <td>⭑</td>
      </tr>
      <tr>
          <td>Layouts</td>
          <td>⭑⭑⭑</td>
          <td>⭑⭑</td>
          <td>⭑⭑⭑⭑</td>
          <td>⭑</td>
      </tr>
      <tr>
          <td>Network profiling</td>
          <td>⭑⭑⭑⭑</td>
          <td>⭑⭑</td>
          <td>⭑⭑⭑</td>
          <td>⭑</td>
      </tr>
      <tr>
          <td>File formats</td>
          <td>⭑⭑</td>
          <td>⭑⭑⭑</td>
          <td>⭑⭑⭑⭑</td>
          <td>⭑</td>
      </tr>
      <tr>
          <td>Plugins</td>
          <td>⭑⭑⭑⭑</td>
          <td>⭑⭑</td>
          <td>⭑⭑⭑</td>
          <td>⭑</td>
      </tr>
      <tr>
          <td>Stability</td>
          <td>⭑⭑⭑</td>
          <td>⭑</td>
          <td>⭑⭑⭑⭑</td>
          <td>⭑⭑⭑</td>
      </tr>
      <tr>
          <td>Speed</td>
          <td>⭑⭑</td>
          <td>⭑</td>
          <td>⭑⭑⭑</td>
          <td>⭑⭑⭑⭑</td>
      </tr>
      <tr>
          <td>Documentation</td>
          <td>⭑⭑⭑⭑</td>
          <td>⭑</td>
          <td>⭑⭑</td>
          <td>⭑⭑⭑</td>
      </tr>
  </tbody>
</table>
<p>其中，⭑ 表示较弱、⭑⭑ 表示中等、⭑⭑⭑ 表示较好、⭑⭑⭑⭑ 表示优秀。</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Newman, M. E. J. (2014) <em>网络科学引论</em>. 电子工业出版社.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://zh.wikipedia.org/wiki/%E6%88%B4%E5%85%8B%E6%96%AF%E7%89%B9%E6%8B%89%E7%AE%97%E6%B3%95">https://zh.wikipedia.org/wiki/戴克斯特拉算法</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://zh.wikipedia.org/zh-hans/Floyd-Warshall%E7%AE%97%E6%B3%95">https://zh.wikipedia.org/zh-hans/Floyd-Warshall算法</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>Kernighan, B. W., &amp; Lin, S. (1970). An efficient heuristic procedure for partitioning graphs. <em>The Bell system technical journal</em>, 49(2), 291-307.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>Fortunato, S. (2010). Community detection in graphs. <em>Physics reports</em>, 486(3-5), 75-174.&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p>Liu, F., Xue, S., Wu, J., Zhou, C., Hu, W., Paris, C., &hellip; &amp; Yu, P. S. (2020). Deep Learning for Community Detection: Progress, Challenges and Opportunities. <em>arXiv preprint arXiv:2005.08225</em>.&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:7">
<p>骆志刚, 丁凡, 蒋晓舟, &amp; 石金龙. (2011). 复杂网络社团发现算法研究新进展. <em>国防科技大学学报</em>, (1), 12.&#160;<a href="#fnref:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:8">
<p>Blondel, V. D., Guillaume, J. L., Lambiotte, R., &amp; Lefebvre, E. (2008). Fast unfolding of communities in large networks. <em>Journal of statistical mechanics: theory and experiment</em>, 2008(10), P10008.&#160;<a href="#fnref:8" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:9">
<p><a href="https://www.timlrx.com/2020/05/10/benchmark-of-popular-graph-network-packages-v2/">Benchmark of popular graph/network packages v2</a>&#160;<a href="#fnref:9" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:10">
<p>Pavlopoulos, G. A., Paez-Espino, D., Kyrpides, N. C., &amp; Iliopoulos, I. (2017). Empirical comparison of visualization tools for larger-scale network analysis. <em>Advances in bioinformatics</em>, 2017.&#160;<a href="#fnref:10" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>

        ]]></description></item><item><title>真实世界网络结构 (Structure of Real-World Network)</title><link>https://zeqiang.fun/cn/2020/11/structure-of-real-world-network/</link><pubDate>Sat, 28 Nov 2020 00:00:00 +0000</pubDate><guid>https://zeqiang.fun/cn/2020/11/structure-of-real-world-network/</guid><description><![CDATA[
        <blockquote>
<p>本文为<a href="/categories/%E5%A4%8D%E6%9D%82%E7%BD%91%E7%BB%9C/">《复杂网络系列》</a>文章<br>
本文内容主要参考自：《网络科学引论》<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
</blockquote>
<h2 id="分支">分支</h2>
<p>在无向网络中，一个典型的现象是很多网络都有一个分支，该分支占据了网络的绝大部分，而剩余部分则被划分为大量的小分支，这些小分支之间彼此并不相连。如下图所示：</p>
<p><img src="/images/cn/2020-11-28-structure-of-real-world-network/components-in-an-undirected-network.png" alt=""></p>
<p>一个网络通常不能有两个或更多占据网络大部分的大分支。如果将一个 <code>$n$</code> 个顶点的网络分解为两个分支，每个分支约为 <code>$\dfrac{1}{2} n$</code> 个顶点，则两个分支的顶点之间会有 <code>$\dfrac{1}{4} n^2$</code> 个顶点对，这些顶点对有可能一个顶点在一个大分支中，而另一个顶点在另外一个大分支中。如果在任何一个顶点对之间有一条边，那么这两个分支就会合并为一个分支。</p>
<p>有向图中分支分为两种：<strong>弱连通分支</strong>和<strong>强连通分支</strong>。弱连通分支的定义与无向网络的分支定义类似，强连通分支是指网络顶点的一个最大子集，该子集中的顶点能够通过有向路径到达其余所有顶点，同时也能够通过有向路径从其余所有顶点到达。</p>
<p>每个连通分支拥有<strong>外向分支</strong>（即从强连通分支中的任意顶点出发，沿着有向路径能够到达的所有顶点的集合）和<strong>内向分支</strong>（即沿着有向路径能够到达强连通分支的所有顶点的集合）。利用**“领结”图**可以很好地刻画有向网络的总体情况，万维网的“领结”图如下所示：</p>
<p><img src="/images/cn/2020-11-28-structure-of-real-world-network/components-in-a-directed-network.png" alt=""></p>
<h2 id="小世界效应">小世界效应</h2>
<p><strong>小世界效应</strong>（small-world effect）是指对于大多数网络而言，网络顶点之间的测地距离都惊人的小，例如：<a href="https://zh.wikipedia.org/wiki/%E5%85%AD%E5%BA%A6%E5%88%86%E9%9A%94%E7%90%86%E8%AE%BA">六度分隔理论</a>。网络的数学模型显示出网络测地路径长度的数量级通常与网络定点数 <code>$n$</code> 成对数关系 ，即 <code>$\log n$</code>。</p>
<h2 id="度分布">度分布</h2>
<p>顶点的度是指连接到它的边的数量。<strong>度分布</strong>（degree distribution）<code>$p_k$</code> 是指网络中节点度的概率分布，也可以理解为从网络中随机选择一个顶点，其度为 <code>$k$</code> 的概率。<strong>度序列</strong>（degree sequence）是指所有顶点度的集合。</p>
<p>根据度 <code>$k$</code> 描述出大型网络的度分布有着非常重要的作用，下图给出了 Internet 的度分布：</p>
<p><img src="/images/cn/2020-11-28-structure-of-real-world-network/degree-distribution-of-the-internet.png" alt=""></p>
<p>现实世界中，几乎所有网络的度分布都有类似的由度较大的核心顶点构成的尾部，统计上称为<strong>右偏</strong>（right-skewed）的。</p>
<h2 id="幂律和无标度网络">幂律和无标度网络</h2>
<p>以 Internet 为例，下图给出了度分布的一个有趣特征，下图使用了对数标度重新绘制了上图的直方图：</p>
<p><img src="/images/cn/2020-11-28-structure-of-real-world-network/power-law-degree-distribution-of-the-internet.png" alt=""></p>
<p>如上图所示，对数处理后，分布大致遵循一条直线。度分布 <code>$p_k$</code> 的对数与度 <code>$k$</code> 的对数之间具有线性函数关系：</p>
<p><code>$$ \ln p_k = - \alpha \ln k + c $$</code></p>
<p>对两侧同时做指数运算，有：</p>
<p><code>$$ p_k = C k^{- \alpha} $$</code></p>
<p>其中，<code>$C = e^c$</code> 是一个常数。这种形式的分布，即按照 <code>$k$</code> 的幂变化，称为<strong>幂律</strong>（power law）。在不同类型的网络中，幂律度分布是普遍存在的，常数 <code>$\alpha$</code> 是幂律的指数，该值的典型取值区间为 <code>$2 \leq \alpha \leq 3$</code>。通常，度分布并非在整个区间都遵循幂律分布，当 <code>$k$</code> 较小时，度分布并不是单调的。具有幂律度分布的网络也称为<strong>无标度网络</strong>（scale-free network）。</p>
<p>观察幂律分布的另外一种方式是构建<strong>累积分布函数</strong>，定义如下：</p>
<p><code>$$ P_k = \sum_{k' = k}^{\infty} p_{k'} $$</code></p>
<p>假设度分布 <code>$p_k$</code> 在尾部服从幂律，确切地讲，对于某个 <code>$k_{\min}$</code>，当 <code>$k \geq k_{\min}$</code> 时有 <code>$p_k = C k^{- \alpha}$</code>，则对于 <code>$k \geq k_{\min}$</code>，有：</p>
<p><code>$$ P_{k}=C \sum_{k^{\prime}=k}^{\infty} k^{\prime-\alpha} \simeq C \int_{k}^{\infty} k^{\prime-\alpha} \mathrm{d} k^{\prime}=\frac{C}{\alpha-1} k^{-(\alpha-1)} $$</code></p>
<p>这里通过积分来近似求和是合理的，因为当 <code>$k$</code> 值较大时，幂律函数的变化率较小。所以，如果度分布 <code>$p_k$</code> 服从幂律，那么 <code>$p_k$</code> 的累积分布函数也服从幂律。</p>
<h2 id="聚类系数">聚类系数</h2>
<p>聚类系数是度量某个顶点的两个邻居顶点也互为邻居的平均概率。该测度计算值与随机条件下得到的期望值之间有较大的差异，这种巨大差异可能也显示出了真正发挥作用的社会效应。在合作网络中，与随机选择合作者相比，实际的合作网络中包含更多的三角形结构。这种现象背后有很多原因，其中一个原因可能是人们会介绍其合作者认识，而这些合作者两两之间也开始进行合作。</p>
<p>随着度的增加，局部聚类系数不断减少，这种现象的一个可能的解释是顶点分成紧密的群组或社团，同一个群组内部的顶点之间连接较多。在表现出此类行为的网络中，属于小型群组的顶点的度较小，因为这种群组的成员也相对较少，但在较大的群组中的顶点的度较大。同时，小型群组中的顶点的局部聚类系数较高。出现这种情况是因为将每个群组与网络的其余部分隔离开之后，每个群组大体上相当于一个小型网络，较小的网络会有更大的聚类系数。当对不同规模的网络取平均之后，会发现度小的顶点具有较高的聚类系数，如下图所示：</p>
<p><img src="/images/cn/2020-11-28-structure-of-real-world-network/local-clustering-as-a-function-of-degree-on-the-internet.png" alt=""></p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Newman, M. E. J. (2014) <em>网络科学引论</em>. 电子工业出版社.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>

        ]]></description></item><item><title>网络表示，测度和度量 (Network Representation, Measures &amp; Metrics)</title><link>https://zeqiang.fun/cn/2020/11/graph-theory/</link><pubDate>Sat, 21 Nov 2020 00:00:00 +0000</pubDate><guid>https://zeqiang.fun/cn/2020/11/graph-theory/</guid><description><![CDATA[
        <blockquote>
<p>本文为<a href="/categories/%E5%A4%8D%E6%9D%82%E7%BD%91%E7%BB%9C/">《复杂网络系列》</a>文章<br>
本文内容主要参考自：《网络科学引论》<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
</blockquote>
<p><strong>网络</strong>（network）也称为<strong>图</strong>（graph），是一个由多个<strong>顶点</strong>（vertex）及连接顶点的<strong>边</strong>（edge）组成的集合。在网络中，我们通常用 <code>$n$</code> 表示顶点的数目，用 <code>$m$</code> 表示边的数目。在大多数网络中两个顶点之间都只有一条边，极少数情况下，两个顶点之间有多条边，称之为<strong>重边</strong>（multiedge）。在极特殊情况下，还会存在连接到顶点自身的边，称之为<strong>自边</strong>（self-edge）。既没有自边也没有重边的图称之为<strong>简单网络</strong>（simple network）或<strong>简单图</strong>（simple graph），存在重边的网络称之为<strong>重图</strong>（multigraph）。相关概念示例如下：</p>
<p><img src="/images/cn/2020-11-21-network-representation-measures-and-metrics/graph.png" alt=""></p>
<h2 id="网络表示">网络表示</h2>
<h3 id="无向网络">无向网络</h3>
<p>对于一个包含 <code>$n$</code> 个顶点的无向图，可以用整数 <code>$1$</code> 到 <code>$n$</code> 对各个顶点进行标注。如果用 <code>$\left(i, j\right)$</code> 表示顶点 <code>$i$</code> 和顶点 <code>$j$</code> 之间的边，那么通过给定 <code>$n$</code> 的值及所有边的列表就能表示一个完整的网络，这种表示方法称之为<strong>边列表</strong>（edge list）。</p>
<p>相比于边列表，<strong>邻接矩阵</strong>（adjacency matrix）可以更好地表示网络。一个简单图的邻接矩阵 <code>$\mathbf{A}$</code> 中元素 <code>$A_{ij}$</code> 的含义如下：</p>
<p><code>$$ A_{ij}=\left\{\begin{array}{ll} 1 &amp; \text{如果顶点 } i \text{ 和顶点 } j \text{ 之间存在一条边} \\ 0 &amp; \text{其他} \end{array}\right. $$</code></p>
<p>对于一个没有自边的网络，其邻接矩阵有两个特点：</p>
<ol>
<li>邻接矩阵对角线上的元素取值均为零。</li>
<li>邻接矩阵是对称的。</li>
</ol>
<h3 id="加权网络">加权网络</h3>
<p>对于<strong>加权网络</strong>（weighted network）和<strong>赋值网络</strong>（valued network）可以将邻接矩阵中对应元素的值设定为相应的权重的方式来进行表示。</p>
<h3 id="有向网络">有向网络</h3>
<p><strong>有向网络</strong>（directed network）或<strong>有向图</strong>（directed graph）有时简称为 digraph，在这类网络中，每条边都有方向，从一个顶点指向另一个顶点，称之为<strong>有向边</strong>（directed edge）。</p>
<div class="blockquote" style='border-left: 4px solid #369BE5;'><strong>注意：</strong> 有向网络的邻接矩阵中元素 <code>$A_{ij} = 1$</code> 时表示存在从顶点 <code>$j$</code> 到顶点 <code>$i$</code> 的边。虽然表示方法有些出人意料，但在数据计算上会带来极大的方便。</div>
<h3 id="超图">超图</h3>
<p>在某些类型的网络中，一些边会同时连接多个顶点。例如：创建一个社会网络，用来表示一个大规模社区中的各个家庭。每个家庭都可能会有两名或多名成员，因此表示这些家庭之间关系的做好方法就是使用一种广义边来同时连接多个顶点。这样的边称之为<strong>超边</strong>（hyperedge），含有超边的网络称之为<strong>超图</strong>（hypergraph）。下图 (a) 表示一个小型超图，其中超边用环的形式表示。</p>
<p><img src="/images/cn/2020-11-21-network-representation-measures-and-metrics/hypergraph.png" alt=""></p>
<p>当一个网络中的顶点因为某种群组之间的关系被连接在一起时，可以使用超图来表示这个网络，在社会学中，这样的网络称之为<strong>隶属网络</strong>。对于超图，可于采用<strong>二分图</strong>的方式进行表示，通过引入 4 个新的顶点代表 4 个群组，在顶点及其所属群组之间通过边连接，如上图 (b) 所示。</p>
<h3 id="二分网络">二分网络</h3>
<p>群组内成员之间的关系可以用超图中的超边表示，也可以等价地用更方便的<strong>二分图</strong>（bipartite network）表示。这种网络中有两类顶点，一类顶点代表原始顶点，另一类顶点则表示原始顶点所属的群组。</p>
<p>二分网络中，与邻接矩阵等价的是一个矩形矩阵，称之为<strong>关联矩阵</strong>（incidence matrix）。如果 <code>$n$</code> 代表人数或网络中的成员数目，<code>$g$</code> 是群组的数目，那么关联矩阵 <code>$\mathbf{B}$</code> 是一个 <code>$g \times n$</code> 的矩阵，其元素 <code>$B_{ij}$</code> 的取值含义如下：</p>
<p><code>$$ B_{ij}=\left\{\begin{array}{ll} 1 &amp; \text{如果顶点 } j  \text{ 属于群组 } i \\ 0 &amp; \text{其他} \end{array}\right. $$</code></p>
<p>研究统一类型顶点之间的直接联系可以通过对二分网络进行<strong>单模投影</strong>（one-mode projection），推导出同类顶点之间的直接联系，如下图所示。</p>
<p><img src="/images/cn/2020-11-21-network-representation-measures-and-metrics/one-mode-projection.png" alt=""></p>
<h3 id="树">树</h3>
<p>**树（tree）**是连通的、无向的且不包含闭合循环的网络，如下图所示。</p>
<p><img src="/images/cn/2020-11-21-network-representation-measures-and-metrics/tree.png" alt=""></p>
<p><strong>连通</strong>是指任意两个顶点之间都存在一条相互可达的路径。一个网络可能有两个或多个部分组成，每个部分相互之间不连通，如果任意单独的部分都为树，则称这个网络为<strong>森林</strong>（forest）。</p>
<p>由于树没有闭合循环，因此任意两个顶点之间有且只有一条相连的路径。如果一个树有 <code>$n$</code> 个顶点，那么它有且仅有 <code>$n - 1$</code> 条边。</p>
<h3 id="度">度</h3>
<p>图中顶点的<strong>度</strong>（degree）是指与其直接相连的边数目。将顶点 <code>$i$</code> 的度表示为 <code>$k_i$</code>，对于有 <code>$n$</code> 个顶点构成的无向图，可利用邻接矩阵将度表示为：</p>
<p><code>$$ k_i = \sum_{j=1}^{n} A_{ij} $$</code></p>
<p>在无向图中，每个边都有两端，如果一共有 <code>$m$</code> 条边，那么就有 <code>$2m$</code> 个边的端点。同时，边的端点数与所有顶点度的总和相等：</p>
<p><code>$$ 2m = \sum_{j=1}^{n} k_i $$</code></p>
<p>即</p>
<p><code>$$ m = \dfrac{1}{2} \sum_{i=1}^{n} k_i = \dfrac{1}{2} \sum_{ij} A_{ij} $$</code></p>
<p>无向图中顶点度的均值 <code>$c$</code> 为：</p>
<p><code>$$ c = \dfrac{1}{n} \sum_{i=1}^{n} k_i $$</code></p>
<p>综上可得：</p>
<p><code>$$ c = \dfrac{2m}{n} $$</code></p>
<p>在一个简单图中，可能的边数的最大值是 <code>$\dbinom{n}{2} = \dfrac{1}{2} n \left(n - 1\right)$</code> 个。图的<strong>连通度</strong>（connectance）或<strong>密度</strong>（density）<code>$\rho$</code> 是所有图中实际出现的边的数目与边数最大值之间的比值：</p>
<p><code>$$ \rho = \dfrac{m}{\dbinom{n}{2}} = \dfrac{2m}{n \left(n - 1\right)} = \dfrac{c}{n - 1} $$</code></p>
<p>在有向图中，每个顶点有两个度：<strong>入度</strong>（in-degree）是连接到该顶点的入边的数目，<strong>出度</strong>（out-degree）是出边数目。当从顶点 <code>$j$</code> 到 <code>$i$</code> 有一条边时，邻接矩阵中对应的元素 <code>$A_{ij} = 1$</code>，则入度和出度记为：</p>
<p><code>$$ k_i^{\text{in}} = \sum_{j=1}^{n} A_{ij}, k_j^{\text{out}} = \sum_{i=1}^{n} A_{ij} $$</code></p>
<p>在有向图中，边的数目 <code>$m$</code> 等于入边的端点数总和，也等于出边的端点数总和，有：</p>
<p><code>$$ m=\sum_{i=1}^{n} k_{i}^{\mathrm{in}}=\sum_{j=1}^{n} k_{j}^{\mathrm{out}}=\sum_{i j} A_{i j} $$</code></p>
<p>每个有向图的入度的均值 <code>$c_{\text{in}}$</code> 和出度的均值 <code>$c_{\text{out}}$</code> 是相等的：</p>
<p><code>$$ c_{\text {in }}=\frac{1}{n} \sum_{i=1}^{n} k_{i}^{\text {in }}=\frac{1}{n} \sum_{j=1}^{n} k_{j}^{\text {out }}=c_{\text {out }} $$</code></p>
<p>简化后有：</p>
<p><code>$$ c = \dfrac{m}{n} $$</code></p>
<h3 id="路径">路径</h3>
<p>网络中的<strong>路径</strong>是指由一组顶点构成的序列，序列中每两个连续顶点都通过网络中的边连接在一起，路径长度等于该路径经过的边的数目（而非顶点的数目）。从顶点 <code>$j$</code> 到顶点 <code>$i$</code> 存在长度为 <code>$r$</code> 的路径总数为：</p>
<p><code>$$ N_{ij}^{\left(r\right)} = \left[\mathbf{A}^r\right]_{ij} $$</code></p>
<p>其中，<code>$\left[\cdots\right]_{ij}$</code> 表示矩阵中的第 <code>$i$</code> 行、第 <code>$j$</code> 列的元素。</p>
<p><strong>测地路径</strong>（geodesic path），简称为<strong>最短路径</strong>（shortest path），即两个顶点间不存在更短路径的路径。图的<strong>直径</strong>（diameter）是指图中任意一对相互连接的顶点之间的最长测地路径长度。<strong>欧拉路径</strong>（Eulerian path）是经过网络中的所有边且每条边只经过一次的路径。<strong>哈密顿路径</strong>（Hamiltonian path）是访问网络的所有顶点且每个顶点只访问一次的路径。</p>
<h3 id="分支">分支</h3>
<p>如果一个网络中两个顶点之间不存在路径，则称这个网络是<strong>非连通</strong>（disconnected）的，如果网络中任意两个顶点之间都能找到一条路径，则称这个网络是<strong>连通</strong>（connected）的。</p>
<p>网络中的子群称为<strong>分支</strong>（component）。分支是网络中顶点的子集，该子集中任何两个顶点之间至少存在一条路径，在保证该性质的前提下，网络中其他顶点都不能被添加到这个子集中。在保证一个给定性质的前提下，不能再向它添加其他顶点，就称其为<strong>最大子集</strong>（maximal subset）。</p>
<h3 id="连通度">连通度</h3>
<p>如果两条路经除了起点和终点外，不共享其他任何顶点，那么这两条路径是<strong>顶点独立</strong>（vertex-independent）的。如果两条路径是顶点独立的，那么也是边独立的，反之则不成立。</p>
<p>两个顶点之间的独立路径数称为顶点之间的<strong>连通度</strong>（connectivity），如果明确考虑边还是顶点，则需利用<strong>边连通度</strong>（edge connectivity）及<strong>顶点连通度</strong>（vertex connectivity）的概念。</p>
<h3 id="子图">子图</h3>
<p>令原图表示为 <code>$G = \left(V, E\right)$</code>，其中，<code>$V$</code> 是图中所有顶点的集合，<code>$E$</code> 是图中所有边的集合，有：</p>
<ol>
<li><strong>子图</strong>（subgraph）：<code>$G'$</code> 中所有顶点和边均包含于原图 <code>$G$</code> 中，即 <code>$E' \in E, V' \in V$</code>。</li>
<li><strong>生成子图</strong>（spanning subgraph）：<code>$G'$</code> 中顶点同原图 <code>$G$</code> 相同，且 <code>$E' \in E$</code>。</li>
<li><strong>导出子图</strong>（induced subgraph）：<code>$G'$</code> 中，<code>$V' \in V$</code>，同时对于 <code>$V'$</code> 中任意一个顶点，只要在原图 <code>$G$</code> 中有对应的边，则也应包含在 <code>$E'$</code> 中。</li>
</ol>
<p><img src="/images/cn/2020-11-21-network-representation-measures-and-metrics/subgraph.png" alt=""></p>
<h3 id="motif">Motif</h3>
<p>Motif <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> 被定义为反复出现的重要连接模式。这些模式在真实的网络中要比随机网络中出现的更加频繁，如下图所示：</p>
<p><img src="/images/cn/2020-11-21-network-representation-measures-and-metrics/motifs-real-randomized-networks.png" alt=""></p>
<p>Motif 的显著性定义为：</p>
<p><code>$$ Z_i = \dfrac{N_i^{\text{real}} - \bar{N}_i^{\text{rand}}}{\text{std} \left(N_i^{\text{rand}}\right)} $$</code></p>
<p>其中，<code>$N_i^{\text{real}}$</code> 为模式在真实图中出现的次数，<code>$N_i^{\text{rand}}$</code> 为模式在随机图中出现的次数。</p>
<h3 id="graphlets">Graphlets</h3>
<p>Graphlets 是对 Motif 的扩展，Motif 是从全局的角度发现模式，而 Graphlets 是从局部角度出发。Graphlets 是连接的非同构子图，这里要求子图为导出子图。下图展示了节点数为 2 至 5 的所有 Graphlets：</p>
<p><img src="/images/cn/2020-11-21-network-representation-measures-and-metrics/graphlets.png" alt=""></p>
<p>更多关于 Motif 和 Graphlets 的细节请参见 <sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> <sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> 。</p>
<h2 id="测度和度量">测度和度量</h2>
<h3 id="中心性">中心性</h3>
<h4 id="度中心性">度中心性</h4>
<p><strong>中心性</strong>（centrality）是研究“网络中哪些顶点是最重要或最核心的？”这个问题的一个概念。网络中心性的最简单的测度是顶点的度，即与顶点相连的边的数量。有时为了强调度作为中心性测度的用途，在社会学中也称之为<strong>度中心性</strong>（degree centrality）。</p>
<h4 id="特征向量中心性">特征向量中心性</h4>
<p>度中心性可自然地扩展为<strong>特征向量中心性</strong>（eigenvector centrality）。可以将度中心性理解为给某顶点所有邻居顶点赋予一个“中心性值”，但并非所有连接顶点的值都是相同的。很多情况下，一个顶点会由于连接到一些本身很重要的点，而使自身的重要性得到提升，这就是特征向量中心性的本质。</p>
<p>对于每个顶点 <code>$i$</code>，假设其中心性为 <code>$x_i$</code>。对于所有 <code>$i$</code>，可以设其初始值 <code>$x_i = 1$</code>，利用该值可以计算出另一个更能体现中心性的值 <code>$x'_i$</code>，将 <code>$x'_i$</code> 定义为 <code>$i$</code> 所有邻居顶点的中心性之和：</p>
<p><code>$$ x'_i = \sum_{j} A_{ij} x_j $$</code></p>
<p>重复该过程可以得到更好的估计值，重复 <code>$t$</code> 步后，中心性 <code>$\mathbf{x} \left(t\right)$</code> 的计算公式如下：</p>
<p><code>$$ \mathbf{x} \left(t\right) = \mathbf{A}^t \mathbf{x} \left(0\right) $$</code></p>
<p>当 <code>$t \to \infty$</code> 时，中心性向量的极限与邻接矩阵中的主特征向量成正比。因此，可以等价地认为中心性 <code>$\mathbf{x}$</code> 满足：</p>
<p><code>$$ \mathbf{A} \mathbf{x} = \kappa_1 \mathbf{x} $$</code></p>
<p>其中，<code>$\kappa_1$</code> 为矩阵 <code>$\mathbf{A}$</code> 的特征值中的最大值。</p>
<p>特征向量中心性对于有向图和无向图都适用。在有向图中，邻接矩阵是非对称的，因此网络有两类特征向量，通常情况下我们选择右特征向量来定义中心性。因为在有向网络中，中心性主要是由指向顶点的顶点，而不是由顶点指向的顶点赋予的。</p>
<h4 id="katz-中心性">Katz 中心性</h4>
<p><strong>Katz 中心性</strong>解决了特征向量中心性中节点中心性可能为零的问题。通过为网络中每个顶点赋予少量的“免费”中心性，可以定义：</p>
<p><code>$$ x_i = \alpha \sum_{j} A_{ij} x_j + \beta $$</code></p>
<p>其中，<code>$\alpha$</code> 和 <code>$\beta$</code> 是正常数。使用矩阵表示可以写成：</p>
<p><code>$$ \mathbf{x} = \alpha \mathbf{A} \mathbf{x} + \beta \mathbf{1} $$</code></p>
<p>其中，<code>$\mathbf{1}$</code> 代表向量 <code>$\left(1, 1, 1, \cdots\right)$</code>。重新整理有 <code>$\mathbf{x} = \beta \left(\mathbf{I} - \alpha \mathbf{A}\right)^{-1} \mathbf{1}$</code>，由于只关心相对值，通常可以设置 <code>$\beta = 1$</code>，则有：</p>
<p><code>$$ \mathbf{x} = \left(\mathbf{I} - \alpha \mathbf{A}\right)^{-1} \mathbf{1} $$</code></p>
<h4 id="pagerank">PageRank</h4>
<p>Katz 中心性有一个不足，被一个 Katz 中心性较高的顶点指向的顶点具有较高的 Katz 中心性，但如果这个中心性较高的顶点指向大量顶点，那么这些大量被指向的顶点也会拥有较高的中心性，但这种估计并非总是恰当的。在新的中心性中，那些指向很多其他顶点的顶点，即使本身的中心性很高，但也只能传递给它指向的每个顶点少量的中心性，定义为：</p>
<p><code>$$ x_{i}=\alpha \sum_{j} A_{i j} \frac{x_{j}}{k_{j}^{\text {out }}}+\beta $$</code></p>
<p>其中，<code>$k_j^{\text{out}}$</code> 为顶点的出度，当 <code>$k_j^{\text{out}} = 0$</code> 时可以将其设定为任何一个非零值，都不会影响计算结果。利用矩阵的形式，可以表示为：</p>
<p><code>$$ \mathbf{x}=\alpha \mathbf{AD}^{-1} \mathbf{x}+\beta \mathbf{1} $$</code></p>
<p>其中，<code>$\mathbf{D}$</code> 为对角矩阵，<code>$D_{ii} = \max \left(k_j^{\text{out}}, 1\right)$</code>。同之前一样，<code>$\beta$</code> 只是整个公式的因子，设置 <code>$\beta = 1$</code>，有：</p>
<p><code>$$ \mathbf{x}=\left(\mathbf{I}-\alpha \mathbf{A} \mathbf{D}^{-1}\right)^{-1} \mathbf{1} $$</code></p>
<p>该中心性即为 <strong>PageRank</strong>。</p>
<p>上述 4 种中心性的区别和联系如下表所示：</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th>带有常数项</th>
          <th>不带常数项</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>除以出度</td>
          <td><code>$\mathbf{x} = \left(\mathbf{I}-\alpha \mathbf{A} \mathbf{D}^{-1}\right)^{-1} \mathbf{1}$</code><br/>PageRank</td>
          <td><code>$\mathbf{x} = \mathbf{A} \mathbf{D}^{-1} \mathbf{x}$</code><br/>度中心性</td>
      </tr>
      <tr>
          <td>不除出度</td>
          <td><code>$\mathbf{x} = \left(\mathbf{I} - \alpha \mathbf{A}\right)^{-1} \mathbf{1}$</code><br/>Katz 中心性</td>
          <td><code>$\mathbf{x} = \kappa_1^{-1} \mathbf{A} \mathbf{x}$</code><br/>特征向量中心性</td>
      </tr>
  </tbody>
</table>
<h4 id="接近度中心性">接近度中心性</h4>
<p><strong>接近度中心性</strong>（closeness centrality）用于度量一个顶点到其他顶点的平均距离。</p>
<p><code>$$ C_{i}=\frac{1}{\ell_{i}}=\frac{n}{\sum_{j} d_{i j}} $$</code></p>
<p>其中，<code>$d_{i j}$</code> 表示从顶点 <code>$i$</code> 到 <code>$j$</code> 的测地路径长度，即路径中边的总数，<code>$\ell_{i}$</code> 表示从 <code>$i$</code> 到 <code>$j$</code> 的平均测地距离。在大多数网络中，顶点之间的测地距离一般都较小，并且随着网络规模的增长，该值只是以对数级别速度缓慢增长。</p>
<p>在不同分支中的两个顶点之间的测地距离定义为无穷大，则 <code>$C_i$</code> 为零。为了解决这个问题，最常见的方法是只计算同一分支内部的顶点的平均测地距离。新的定义使用顶点之间的调和平均测地距离：</p>
<p><code>$$ C_{i}^{\prime}=\frac{1}{n-1} \sum_{j(\neq i)} \frac{1}{d_{i j}} $$</code></p>
<p>公式中排除了 <code>$j = i$</code> 的情况，因为 <code>$d_{ii} = 0$</code>。结果也称之为<strong>调和中心性</strong>（harmonic centrality）。</p>
<h4 id="介数中心性">介数中心性</h4>
<p><strong>介数中心性</strong>（betweenness centrality）描述了一个顶点在其他顶点之间路径上的分布程度。假设在网络中每两个顶点之间，在每个单位时间内以相等的概率交换信息，信息总是沿着网络中最短测地路径传播，如果有多条最短测地路径则随机选择。由于消息是沿着最短路径以相同的速率传播，因此经过某个顶点的消息数与经过该顶点的测地路径数成正比。测地路径数就是所谓的介数中心性，简称<strong>介数</strong>。</p>
<p>定义 <code>$n_{st}^i$</code> 为从 <code>$s$</code> 到 <code>$t$</code> 经过 <code>$i$</code> 的测地路径数量，定义 <code>$g_{st}$</code> 为从 <code>$s$</code> 到 <code>$t$</code> 的测地路径总数，那么顶点 <code>$i$</code> 的介数中心性可以表示为：</p>
<p><code>$$ x_{i}=\sum_{s t} \frac{n_{s t}^{i}}{g_{s t}} $$</code></p>
<p>高介数中心性的顶点由于控制着其他顶点之间的消息传递，在网络中有着很强的影响力。删除介数最高的顶点，也最有可能破坏其他顶点之间的通信。</p>
<p>不同中心性的可视化如下图所示：</p>
<figure>
  <img data-src="/images/cn/2020-11-21-network-representation-measures-and-metrics/centrality-measures.png" class="lazyload"/>
  <figcaption><p class="figcaption">不同中心性可视化 <a href="https://commons.wikimedia.org/w/index.php?curid=39064835">By Tapiocozzo, CC BY-SA 4.0</a></p></figcaption>
</figure>
<p>其中，A：介数中心性；B：接近度中心性；C：特征向量中心性；D：度中心性；E：调和中心性；F：Katz 中心性。</p>
<h3 id="传递性">传递性</h3>
<p><strong>传递性</strong>（transitivity）在社会网络中的重要性要比其他网络中重要得多。在数学上，对于关系“<code>$\circ$</code>”，如果 <code>$a \circ b$</code> 和 <code>$b \circ c$</code>，若能推出 <code>$a \circ c$</code>，则称 <code>$\circ$</code> 具有传递性。</p>
<p>完全传递性值出现在每一个分支都是全连通的子图或团的网络中。<strong>团</strong>（clique）是指无向图网络中的一个最大顶点子集，在该子集中任何两个顶点之间都有一条边直接连接。完全传递性没有太多的实际意义，而部分传递性却很有用。在很多网络中，<code>$u$</code> 认识 <code>$v$</code> 且 <code>$v$</code> 认识 <code>$w$</code>，并不能保证 <code>$u$</code> 认识 <code>$w$</code>，但两者之间相互认识的概率很大。</p>
<p>如果 <code>$u$</code> 也认识 <code>$w$</code>，则称该路径是闭合的。在社会网络术语中，称 <code>$u, v, w$</code> 这 3 个顶点形成一个<strong>闭合三元组</strong>（closed triad）。我们将<strong>聚类系数</strong>（clustering coefficient）定义为网络中所有长度为 2 的路径中闭合路径所占的比例：</p>
<p><code>$$ C = \dfrac{\text{长度为 2 的路径中闭合路径数}}{\text{长度为 2 的路径数}} $$</code></p>
<p>其取值范围在 0 到 1 之间。社会网络的聚类系数比其他网络偏高。</p>
<p>对于顶点 <code>$i$</code>，定地单个顶点的聚类系数为：</p>
<p><code>$$ C_i = \dfrac{\text{顶点 i 的邻居顶点中直接相连的顶点对数}}{\text{顶点 i 的邻居顶点对总数}} $$</code></p>
<p><code>$C_i$</code> 也称为<strong>局部聚类系数</strong>（local clustering coefficient），该值代表了 <code>$i$</code> 的朋友之间互为朋友的平均概率。</p>
<h3 id="相互性">相互性</h3>
<p>聚类系数观察的是长度为 3 的循环，长度为 2 的循环的频率通过<strong>相互性</strong>（reciprocity）来度量，该频率描述了两个顶点之间相互指向的概率。</p>
<h3 id="相似性">相似性</h3>
<p>社会网络分析的另一个核心概念是顶点之间的相似性。构造网络相似性的测度有两种基本方法：<strong>结构等价</strong>（structural equivalence）和<strong>规则等价</strong>（regular equivalence），如下图所示：</p>
<p><img src="/images/cn/2020-11-21-network-representation-measures-and-metrics/structural-and-regular-equivalence.png" alt=""></p>
<h4 id="结构等价">结构等价</h4>
<p>针对无向网络中，最简单和最显而易见的结构等价测度就是计算两个顶点的共享邻居顶点数。在无向网络中，顶点 <code>$i$</code> 和 <code>$j$</code> 的共享邻居顶点数表示为 <code>$n_{ij}$</code>，有：</p>
<p><code>$$ n_{ij} = \sum_{k} A_{ik} A_{kj} $$</code></p>
<p>利用<strong>余弦相似度</strong>可以更好的对其进行度量。将邻接矩阵的第 <code>$i$</code> 和第 <code>$j$</code> 行分别看成两个向量，然后将这两个向量之间的夹角余弦值用于相似性度量，有：</p>
<p><code>$$ \sigma_{i j}=\cos \theta=\frac{\sum_{k} A_{i k} A_{k j}}{\sqrt{\sum_{k} A_{i k}^{2}} \sqrt{\Sigma_{k} A_{j k}^{2}}} $$</code></p>
<p>假设网络是不带权重的简单图，上式可以化简为：</p>
<p><code>$$ \sigma_{i j}=\frac{\sum_{k} A_{i k} A_{k j}}{\sqrt{k_{i}} \sqrt{k_{j}}}=\frac{n_{i j}}{\sqrt{k_{i} k_{j}}} $$</code></p>
<p>其中，<code>$k_i$</code> 是顶点 <code>$i$</code> 的度。余弦相似度的取值范围为从 0 到 1，1 表示两个顶点之间拥有完全相同的邻居节点。</p>
<p><strong>皮尔逊相关系数</strong>通过同随机选择邻居顶点条件下共享邻居顶点数的期望值进行比较的方式进行计算，得到的标准的皮尔逊相关系数为：</p>
<p><code>$$ r_{i j}=\frac{\sum_{k}\left(A_{i k}-\left\langle A_{i}\right\rangle\right)\left(A_{j k}-\left\langle A_{j}\right\rangle\right)}{\sqrt{\sum_{k}\left(A_{i k}-\left\langle A_{i}\right\rangle\right)^{2}} \sqrt{\sum_{k}\left(A_{j k}-\left\langle A_{j}\right\rangle\right)^{2}}} $$</code></p>
<p>上式的取值范围从 -1 到 1，数值越大表明两者之间越相似。</p>
<h4 id="规则等价">规则等价</h4>
<p>规则等价的顶点不必共享邻居顶点，但是两个顶点的邻居顶点本身要具有相似性。一些简单的代数测度思想如下：定义一个相似性值 <code>$\sigma_{ij}$</code>，若顶点 <code>$i$</code> 和 <code>$j$</code> 各自的邻居顶点 <code>$k$</code> 和 <code>$l$</code> 本身具有较高的相似性，则 <code>$i$</code> 和 <code>$j$</code> 的相似性也较高。对于无向网络，有以下公式：</p>
<p><code>$$ \sigma_{i j}=\alpha \sum_{k l} A_{i k} A_{j l} \sigma_{k l} $$</code></p>
<p>或者利用矩阵性质表示为 <code>$\mathbf{\sigma} = \alpha \mathbf{A \sigma A}$</code>。</p>
<h3 id="同质性">同质性</h3>
<p>在社会网络中，人们倾向于选择那些他们认为与其自身在某些方面相似的人作为朋友，这种倾向性称为<strong>同质性</strong>（homophily）或<strong>同配混合</strong>（assortative mixing）。</p>
<h4 id="依据枚举特征的同配混合">依据枚举特征的同配混合</h4>
<p>假设有一个网络，其顶点根据某个<strong>枚举特征</strong>（例如：国籍、种族、性别等）分类，且该特征的取值是一个有限集合。如果网络中连接相同类型顶点之间的边所占比例很大，那么该网络就是同配的。量化同配性简单的方法是观测这部分边占总边数的比例，但这并不是很好的度量方法，因为如果所有顶点都是同一个类型，那么测度值就是 1。</p>
<p>好的测度可以通过首先找出连接同类顶点的边所占的比例，然后减去在不考虑顶点类型时，随机连接的边中，连接两个同类顶点的边所占比例的期望值的方式得到。常用的测度为<strong>模块度</strong>（modularity）：</p>
<p><code>$$ Q=\frac{1}{2 m} \sum_{i j}\left(A_{i j}-\frac{k_{i} k_{j}}{2 m}\right) \delta_{g_{i} g_{i}} $$</code></p>
<p>其中，<code>$k_i$</code> 为顶点 <code>$i$</code> 的度，<code>$g_i$</code> 为顶点 <code>$i$</code> 的类型，<code>$m$</code> 为总边数，<code>$\delta_{ij}$</code> 为<a href="https://zh.wikipedia.org/wiki/%E5%85%8B%E7%BD%97%E5%86%85%E5%85%8B%CE%B4%E5%87%BD%E6%95%B0">克罗内克函数</a>。该值严格小于 1，如果同类顶点之间边数的实际值大于随机条件下的期望值，则该值为正数，否则为负数，值为正说明该网络是同配混合的。</p>
<h4 id="依据标量特征的同配混合">依据标量特征的同配混合</h4>
<p>如果根据<strong>标量特征</strong>（例如：年龄、收入等）来度量网络中的同质性。由于该类特征具有确定的顺序，因此根据标量的数值，不仅可以指出两个顶点在什么情况下是完全相同的，也可以指出它们在真么情况下是近似相同的。</p>
<p>令 <code>$x_i$</code> 为顶点 <code>$i$</code> 的标量值，<code>$\left(x_i, x_j\right)$</code> 为网络中每一条边 <code>$\left(i, j\right)$</code> 的两个端点的值，利用协方差可以得到<strong>同配系数</strong>：</p>
<p><code>$$ r=\frac{\sum_{i j}\left(A_{i j}-k_{i} k_{j} / 2 m\right) x_{i} x_{j}}{\sum_{i j}\left(k_{i} \delta_{i j}-k_{i} k_{j} / 2 m\right) x_{i} x_{j}} $$</code></p>
<p>该系数在全同配混合网络中取最大值 1，在全异配混合网络中取最小值 -1，值 0 意味着边两端的顶点值是非相关的。</p>
<h4 id="依据度的同配混合">依据度的同配混合</h4>
<p>依据度的同配混合是依据标量特征的同配混合的一个特例。依据度的同配混合网络中，高度数顶点倾向于与其他高度数顶点相连，而低度数顶点倾向于与其他低度数顶点相连。</p>
<p>在同配网络中，度大的顶点倾向于聚集在一起的网络中，我们希望得到网络中这些度大的顶点构成的顶点块或核，它们周围是一些度小的顶点构成的低密度<strong>边缘</strong>（periphery）。这种<strong>核心/边缘结构</strong>（core/periphery structure）是社会网络的普遍特征。</p>
<p><img src="/images/cn/2020-11-21-network-representation-measures-and-metrics/core-periphery-structure.png" alt=""></p>
<p>上图 (a) 给出了一个小型的同配混合网络，其核心/边缘结构明显，上图 (b) 给出了一个小型异配混合网络，通常不具备核心/边缘结构，但顶点的分布更加均匀。</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Newman, M. E. J. (2014) <em>网络科学引论</em>. 电子工业出版社.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Milo, R., Shen-Orr, S., Itzkovitz, S., Kashtan, N., Chklovskii, D., &amp; Alon, U. (2002). Network motifs: simple building blocks of complex networks. <em>Science</em>, 298(5594), 824-827.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Jain, D., &amp; Patgiri, R. (2019, April). Network Motifs: A Survey. In <em>International Conference on Advances in Computing and Data Sciences</em> (pp. 80-91). Springer, Singapore.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>Henderson, K., Gallagher, B., Eliassi-Rad, T., Tong, H., Basu, S., Akoglu, L., &hellip; &amp; Li, L. (2012, August). Rolx: structural role extraction &amp; mining in large graphs. In <em>Proceedings of the 18th ACM SIGKDD international conference on Knowledge discovery and data mining</em> (pp. 1231-1239).&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>

        ]]></description></item></channel></rss>