-
Notifications
You must be signed in to change notification settings - Fork 0
/
Graph_Constructor.py
74 lines (51 loc) · 3.16 KB
/
Graph_Constructor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import numpy as np
import networkx as nx
#This module takes a level unitary and initial state and formats a networkx
#graph object with the required data and then converts this object into a JSON string
class Graph_Wrapper:
def __init__(self, level_operator, input_state):
self.level_operator = level_operator
self.input_StateVector = input_state
self.state_vector = input_state.data
self.unitary = level_operator.data
self.support = self.support(self.unitary)
self.prob_flows = self.probability_flows()
self.graph = nx.DiGraph(self.support) #This defines as Directed Graph object this is structred as a dict of dicts
#self.mapping = {node:"{0:b}".format(node) for node in self.graph.nodes()} #This defines a maps the node lables to there representation in the computational basis
self.values = nx.circular_layout(self.graph,220) #This defines an array of x,y coridinates that will give the graph a circualr structure when drawn
for source, target in self.graph.edges: # assigns the weight of each edge the corresponding value of the flow matrix
self.graph[source][target]['weight'] = self.prob_flows[source,target]
for nodes in self.graph.nodes: #Assigns each node a x position and y position
self.graph.nodes[nodes]['x_pos'] = self.values[nodes][0]
self.graph.nodes[nodes]['y_pos'] = self.values[nodes][1]
#self.graph = nx.relabel_nodes(self.graph,self.mapping,False) #This applies the earlier defined map to the nodes of the graph.
self.data = nx.node_link_data(self.graph,{'link': "edges", 'source': "from", 'target': "to", 'nodes':"nodes", 'id':"id"}) #This assigns the graph data to the variable data
def support(self,Matrix): # This method constructs the support matrix for a given input matrix. This is then used as the adjacency matrix of the graph.
support = np.zeros((Matrix.shape), dtype='int32')
for i in range(Matrix.shape[0]):
for j in range(Matrix.shape[1]):
if Matrix[i,j] != 0:
support[i,j] = 1
else:
support[i,j] = support[i,j]
return support
def probability_flows(self):#This method calculates the probability flows for each edge of the graph.
flow_matrix = np.zeros((self.unitary.shape))
for i in range(self.unitary.shape[0]):
for j in range(self.unitary.shape[1]):
A = 0
for k in range(self.unitary.shape[0]):
A += self.state_vector[k]*self.unitary[i,k]
flow_matrix[i,j] = (((self.state_vector[j]*self.unitary[i,j]).conjugate())*A).real
return flow_matrix
if __name__== '__main__': #Test Code
from Qflow_Level_Builder import stage
from qiskit import QuantumCircuit
qs = QuantumCircuit(2)
qs.h((0,1))
qs.cx(1,0)
qs.x(0)
qs.y(0)
Stage_One = stage(qs)
G_wrapper = Graph_Wrapper(Stage_One.levelOperator(1),Stage_One.levelState(1))
a = G_wrapper.output_JSON()