Python 实现简单的超图 Hypergraph


1 超图

在数学中,超图(Hypergraph)是一种广义上的图,是有限集合中最一般的离散结构,在信息科学、生命科学等领域有着广泛的应用。(如果有疑问,可以参看我写的另外一篇超图基础知识的博客。
边(edge)顶点(vertex 或 node) 组成。
超图超边(hyperedge)顶点(vertex) 组成。

类型元素
顶点 + 边
超图顶点 + 超边

普通图,一条边只能连接两个顶点,而超图的一条边可以连接任意数量的顶点。
记超图为 G G G,顶点集合为 V \mathcal{V} V,超边集合为 E \mathcal{E} E,则有
G = ( V , E ) G = (\mathcal{V}, \mathcal{E}) G=(V,E)
如果是加权超图,则:
G = ( V , E , W ) G = (\mathcal{V}, \mathcal{E}, W) G=(V,E,W)
其中 W W W 表示权重。

对于顶点集合 V \mathcal{V} V 中的任意顶点 v v v,可以表示为 v ∈ V v \in \mathcal{V} vV
对于超边集合 E \mathcal{E} E 中的任意超边 e e e,可以表示为 e ∈ E e \in \mathcal{E} eE,且 e ⊂ V e \subset \mathcal{V} eV

2 代码

顶点 v v v 应该包含一些属性:

  • 名称 —— 顶点得有一个专属编码吧,不与其他顶点重复,用于区分不同的顶点;
  • 权重 —— 顶点的权重,这个可有可无,看你的实际需求。
变量:类型含义符号
Vertex: class顶点 v v v
name: str (int)顶点名称
weight: float顶点权重 w ( v ) w(v) w(v)

那么确定好顶点的属性之后,就可以定义顶点类了。

class Vertex:
    def __init__(self, name: str = None, weight: float = None):
        self.name = name
        self.weight = weight

超边 e e e 应该包含一些属性:

  • 名称 —— 超边得有一个专属编码吧,不与其他超边重复,用于区分不同的超边;
  • 顶点集 —— 超边是由特定的顶点集组成的,那么得保存该超边包含的顶点集;
  • 权重 —— 超边的权重,这个可有可无,看你的实际需求。
变量:类型含义符号
Edge: class超边 e e e
name: str (int)超边名称
vertices: List [Vertex]超边包含的顶点集 ⋃ v ∈ e v \bigcup_{v \in e} v vev
weight: float超边权重 w ( e ) w(e) w(e)

那么确定好超边的属性之后,就可以定义超边类了。

from typing import List
import Vertex


class Edge:
    def __init__(self, name: str = None, weight: float = None, vertices: List[Vertex] = None):
        self.name = name
        self.weight = weight
        self.vertices = vertices

超图 G G G 是由顶点集 V V V 和超边集 E E E 组成的。那么定义 G G G 只需要将 V V V E E E 的定义组装起来就可以啦。

超图 G G G 应该包含一些属性:

  • 顶点集 —— 对应 V V V
  • 超边集 —— 对应 E E E
  • 关联矩阵 —— 这个可有可无,看你的实际需求;
  • 顶点度 —— 这个可有可无,看你的实际需求;
  • 超边度 —— 这个可有可无,看你的实际需求;
  • 顶点度矩阵 —— 这个可有可无,看你的实际需求;
  • 超边度矩阵 —— 这个可有可无,看你的实际需求;
变量:类型含义符号
Hypergraph: class超图 G G G
vertices: List [Vertex]顶点集 V V V
edges: List [Edge]超边集 E E E
num_vertices: int顶点的数量 ∣ V ∣ \lvert V \rvert V
num_edges: int超边的数量 ∣ E ∣ \lvert E \rvert E
incident_matrix: np.ndarray关联矩阵 H H H
vertices_degree: np.ndarray所有顶点的度 d d d
edges_degree: np.ndarray所有超边的度 δ \delta δ
vertex_degree_diagonal_matrix: np.ndarray顶点度组成的对角矩阵 D v D_v Dv
edge_degree_diagonal_matrix: np.ndarray超边度组成的对角矩阵 D e D_e De

超图类定义:

from typing import List
import numpy as np

import Edge
import Vertex


class Hypergraph(object):
    def __init__(self, vertices: List[Vertex] = None, edges: List[Edge] = None):
        self.vertices = vertices
        self.edges = edges
        if vertices is None or edges is None:
            self.num_vertices = 0
            self.num_edges = 0
            self.incident_matrix = None
            self.vertices_degree = None
            self.edges_degree = None
            self.vertex_degree_diagonal_matrix = None
            self.edge_degree_diagonal_matrix = None
        else:
            self.num_vertices = len(vertices)
            self.num_edges = len(edges)
            self.incident_matrix = self.calculate_incident_matrix()
            self.vertices_degree = self.calculate_vertex_degree()
            self.edges_degree = self.calculate_edge_degree()
            self.vertex_degree_diagonal_matrix = self.calculate_diagonal_matrix_of_vertex_degree()
            self.edge_degree_diagonal_matrix = self.calculate_diagonal_matrix_of_edge_degree()

    def init_hypergraph_from_files(self, dataset_dir: str):
        self.vertices, self.edges = hypergraph_construction(dataset_dir)
        self.num_vertices = len(self.vertices)
        self.num_edges = len(self.edges)
        self.incident_matrix = self.calculate_incident_matrix()
        self.vertices_degree = self.calculate_vertex_degree()
        self.edges_degree = self.calculate_edge_degree()
        self.vertex_degree_diagonal_matrix = self.calculate_diagonal_matrix_of_vertex_degree()
        self.edge_degree_diagonal_matrix = self.calculate_diagonal_matrix_of_edge_degree()

    def calculate_incident_matrix(self):
        """
        Calculate the incident matrix of the hypergraph.
        :return: The incident matrix of the hypergraph.
        """
        incident_matrix = np.zeros(shape=(self.num_vertices, self.num_edges), dtype=int)
        for i in range(self.num_vertices):
            vertex = self.vertices[i]
            for j in range(self.num_edges):
                edge = self.edges[j]
                if vertex in edge.vertices:
                    incident_matrix[i, j] = 1

        return incident_matrix

    def calculate_vertex_degree(self):
        """
        Calculate the degree of vertices in the hypergraph.
        :return: The degree of vertices in the hypergraph.
        """
        edge_weights = np.zeros(shape=(self.num_edges,), dtype=np.float64)
        for i in range(self.num_edges):
            edge = self.edges[i]
            edge_weights[i] = edge.weight

        edge_weights = edge_weights.reshape(-1, 1)
        vertex_degree_array = np.dot(self.incident_matrix, edge_weights)

        return vertex_degree_array.reshape(vertex_degree_array.size, )

    def calculate_edge_degree(self):
        """
        Calculate the degree of edges in the hypergraph.
        :return: The degree of edges in the hypergraph.
        """
        edges_degree = self.incident_matrix.sum(axis=0)
        return edges_degree

    def calculate_diagonal_matrix_of_vertex_degree(self):
        """
        Create a diagonal matrix with the degrees of vertex as the diagonal elements.
        :return: The diagonal matrix.
        """
        return np.diag(self.vertices_degree)

    def calculate_diagonal_matrix_of_edge_degree(self):
        """
        Create a diagonal matrix with the degrees of edge as the diagonal elements.
        :return: The diagonal matrix.
        """
        return np.diag(self.edges_degree)

3 说明

以上代码注重 “低耦合、高内聚” 的设计理念。在实际中,为了简略和便捷,往往会简化以上代码。请根据需要设计代码。

4 参考

  1. 超图(Hypergraph)基础——论文细品——《Learning with hypergraphs: Clustering, classification, and embedding》
  2. 集智百科
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值