"""Graph state simulator implemented with networkx."""from__future__importannotationsfromtypingimportTYPE_CHECKINGimportnetworkxasnxfromgraphix.graphsim.basegraphstateimportBaseGraphStateifTYPE_CHECKING:fromcollections.abcimportIteratorfromnetworkx.classes.reportviewsimportEdgeView,NodeView
[docs]classNXGraphState(BaseGraphState):"""Graph state simulator implemented with networkx. See :class:`~graphix.graphsim.basegraphstate.BaseGraphState` for more details. """
[docs]def__init__(self,nodes:list[int]|None=None,edges:list[tuple[int,int]]|None=None,vops:dict[int,int]|None=None,):"""Instantiate a graph simulator. Parameters ---------- nodes : list[int] A container of nodes (list, dict, etc) edges : list[tuple[int, int]] list of tuples (i,j) for pairs to be entangled. vops : dict[int, int] dict of local Clifford gates with keys for node indices and values for Clifford index (see graphix.clifford.CLIFFORD) """super().__init__()self._graph=nx.Graph()ifnodesisnotNone:self.add_nodes_from(nodes)ifedgesisnotNone:self.add_edges_from(edges)ifvopsisnotNone:self.apply_vops(vops)
@propertydefnodes(self)->NodeView:"""Return the set of nodes."""returnself._graph.nodes@propertydefedges(self)->EdgeView:"""Return the set of edges."""returnself._graph.edges@propertydefgraph(self)->nx.Graph:"""Return the graph itself."""returnself._graph
[docs]defdegree(self)->Iterator[tuple[int,int]]:"""Return an iterator for (node, degree) tuples, where degree is the number of edges adjacent to the node."""returniter(self._graph.degree())
[docs]defadd_nodes_from(self,nodes)->None:"""Add nodes and initialize node properties. See :meth:`BaseGraphState.add_nodes_from`. """self._graph.add_nodes_from(nodes,loop=False,sign=False,hollow=False)
[docs]defadd_edges_from(self,edges)->None:"""Add edges and initialize node properties of newly added nodes. See :meth:`BaseGraphState.add_edges_from`. """self._graph.add_edges_from(edges)# adding edges may add new nodesforu,vinedges:ifunotinself._graph.nodes:self._graph.nodes[u]["loop"]=Falseself._graph.nodes[u]["sign"]=Falseself._graph.nodes[u]["hollow"]=Falseifvnotinself._graph.nodes:self._graph.nodes[v]["loop"]=Falseself._graph.nodes[v]["sign"]=Falseself._graph.nodes[v]["hollow"]=False
[docs]defnumber_of_edges(self,u:int|None=None,v:int|None=None)->int:"""Return the number of edges between two nodes. See :meth:`BaseGraphState.number_of_edges`. """ifuisNoneandvisNone:returnlen(self.edges)elifuisNoneorvisNone:raiseValueError("u and v must be specified together")returnself._graph.number_of_edges(u,v)
[docs]defneighbors(self,node)->Iterator:"""Return an iterator over all neighbors of node n. See :meth:`BaseGraphState.neighbors`. """returnself._graph.neighbors(node)
[docs]defsubgraph(self,nodes:list)->nx.Graph:"""Return a subgraph of the graph. See :meth:`BaseGraphState.subgraph`. """returnself._graph.subgraph(nodes)
[docs]defremove_node(self,node:int)->None:"""Remove a node from the graph. See :meth:`BaseGraphState.remove_node`. """self._graph.remove_node(node)
[docs]defremove_nodes_from(self,nodes:list[int])->None:"""Remove all nodes specified in the list. See :meth:`BaseGraphState.remove_nodes_from`. """self._graph.remove_nodes_from(nodes)
[docs]defremove_edge(self,u:int,v:int)->None:"""Remove an edge from the graph. See :meth:`BaseGraphState.remove_edge`. """self._graph.remove_edge(u,v)
[docs]defremove_edges_from(self,edges:list[tuple[int,int]])->None:"""Remove all edges specified in the list. See :meth:`BaseGraphState.remove_edges_from`. """self._graph.remove_edges_from(edges)
[docs]defadjacency(self)->Iterator:"""Return an iterator over (node, adjacency dict) tuples for all nodes. See :meth:`BaseGraphState.adjacency`. """returnself._graph.adjacency()
[docs]deflocal_complement(self,node):"""Perform local complementation of a graph. See :meth:`BaseGraphState.local_complement`. """g=self.subgraph(list(self.neighbors(node)))g_new=nx.complement(g)self.remove_edges_from(g.edges)self.add_edges_from(g_new.edges)
[docs]defget_isolates(self)->list[int]:"""Return a list of isolated nodes (nodes with no edges). See :meth:`BaseGraphState.get_isolates`. """returnlist(nx.isolates(self.graph))