Skip to content

Commit

Permalink
update examples; bump version
Browse files Browse the repository at this point in the history
  • Loading branch information
shinich1 committed Oct 6, 2023
1 parent 04758a5 commit 789ca30
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 128 deletions.
23 changes: 22 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Visualization of graph state with flow or gflow structures (#78)
### Changed

### Fixed

## [0.2.7] - 2023-10-06

### Added

- Visualization tool of resource state for a pattern, with flow or gflow structures (#78)
- Visualize the resource state by calling `Pattern.draw_graph()`
- Tool to extract fusion network from the resource state of a pattern (#87).

### Changed

### Fixed

## [0.2.6] - 2023-09-29

### Added

- `input_nodes` attribute added to the pattern class (#88)
- `leave_input` optional argument to `Pattern.perform_pauli_measurements()` which leaves the input qubits unmeasured during the optimization.

### Changed

- bump networkx version to 3.* (#82)

## [0.2.5] - 2023-08-17

### Added
Expand Down
2 changes: 2 additions & 0 deletions docs/source/modifier.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ Pattern Optimization

.. automethod:: minimize_space

.. automethod:: draw_graph

.. automethod:: max_space

.. automethod:: get_layers
Expand Down
1 change: 1 addition & 0 deletions docs/source/references.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ Module reference
flow
clifford
device_interface
visualization

13 changes: 13 additions & 0 deletions docs/source/visualization.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Visualization tool
==================

:mod:`graphix.visualization` module
++++++++++++++++++++++++++++++++

This provides functions to visualize the resource state of MBQC pattern.
If flow or gflow exist, the tool take them into account and show the information flow as directed edges.

.. currentmodule:: graphix.visualization

.. autoclass:: GraphVisualizer
:members:
21 changes: 6 additions & 15 deletions examples/deutsch-jozsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
First, let us import relevant modules:
"""
#%%
import numpy as np
from graphix import Circuit
import networkx as nx
Expand Down Expand Up @@ -61,13 +62,7 @@

pattern = circuit.transpile()
pattern.print_pattern(lim=15)
nodes, edges = pattern.get_graph()
g = nx.Graph()
g.add_nodes_from(nodes)
g.add_edges_from(edges)
np.random.seed(100)
nx.draw(g)
plt.show()
pattern.draw_graph()

#%%
# this seems to require quite a large graph state.
Expand All @@ -83,19 +78,15 @@

pattern.perform_pauli_measurements()
pattern.print_pattern(lim=16, filter=["N", "M", "C"])
nodes, edges = pattern.get_graph()
g = nx.Graph()
g.add_nodes_from(nodes)
g.add_edges_from(edges)
np.random.seed(100)
nx.draw(g)
plt.show()
pattern.draw_graph()

#%%
# Since all operations are Clifford, all measurements in the measurement pattern are Pauli measurements:
# Since all operations of the original circuit are Clifford, all measurements in the measurement pattern are Pauli measurements:
# So the preprocessing has done all the necessary computations, and all nodes are isolated with no further measurements required.
# Let us make sure the result is correct:

out_state = pattern.simulate_pattern()
state = circuit.simulate_statevector()
print("overlap of states: ", np.abs(np.dot(state.psi.flatten().conjugate(), out_state.psi.flatten())))

# %%
File renamed without changes.
9 changes: 8 additions & 1 deletion examples/qaoa.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"""


#%%
from graphix import Circuit
import networkx as nx
import numpy as np
Expand Down Expand Up @@ -93,6 +93,11 @@ def get_clr_list(pattern):
graph_params = {"with_labels": False, "node_size": 150, "node_color": get_clr_list(pattern), "edgecolors": "k"}
nx.draw(g, pos=pos, **graph_params)

#%%
# Similar visualization can be done by calling our recently added :class:`graphix.visualization.GraphVisualizer` class, accessible through :meth:`graphix.pattern.Pattern.draw_graph()`
pattern.draw_graph()


#%%
# perform Pauli measurements and plot the new (minimal) graph to perform the same quantum computation

Expand Down Expand Up @@ -127,3 +132,5 @@ def get_clr_list(pattern):
state = circuit.simulate_statevector()
print("overlap of states: ", np.abs(np.dot(state.psi.flatten().conjugate(), out_state.psi.flatten())))
# sphinx_gallery_thumbnail_number = 2

# %%
11 changes: 2 additions & 9 deletions examples/qft.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
# %%
import numpy as np
from graphix import Circuit
import networkx as nx
import matplotlib.pyplot as plt


def cp(circuit, theta, control, target):
Expand Down Expand Up @@ -59,13 +57,8 @@ def swap(circuit, a, b):

# transpile and plot the graph
pattern = circuit.transpile()
nodes, edges = pattern.get_graph()
g = nx.Graph()
g.add_nodes_from(nodes)
g.add_edges_from(edges)
np.random.seed(100)
nx.draw(g)
plt.show()
pattern.draw_graph()
nodes, _ = pattern.get_graph()
print(len(nodes))

# %%
Expand Down
93 changes: 4 additions & 89 deletions examples/qnn.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,98 +329,12 @@ def fit(self, x, y, maxiter=5):

#%%
# Plot the resource state. Node positions are determined by the flow-finding algorithm.
nodes, edges = pattern.get_graph()
g = nx.Graph()
g.add_nodes_from(nodes)
g.add_edges_from(edges)

from graphix.gflow import flow

f, l_k = flow(g, set(range(n_qubits)), set(pattern.output_nodes))

flow = [[i] for i in range(n_qubits)]
for i in range(n_qubits):
contd = True
val = i
while contd:
try:
val = f[val]
flow[i].append(val)
except KeyError:
contd = False
longest = np.max([len(flow[i]) for i in range(n_qubits)])

pos = dict()
for i in range(n_qubits):
length = len(flow[i])
fac = longest / (length - 1)
for j in range(len(flow[i])):
pos[flow[i][j]] = (fac * j, -i)

# determine wheher or not a node will be measured in Pauli basis
def get_clr_list(pattern):
nodes, edges = pattern.get_graph()
meas_list = pattern.get_measurement_commands()
g = nx.Graph()
g.add_nodes_from(nodes)
g.add_edges_from(edges)
clr_list = []
for i in g.nodes:
for cmd in meas_list:
if cmd[1] == i:
if cmd[3] in [-1, -0.5, 0, 0.5, 1]:
clr_list.append([0.5, 0.5, 0.5])
else:
clr_list.append([1, 1, 1])
if i in pattern.output_nodes:
clr_list.append([0.8, 0.8, 0.8])
return clr_list

graph_params = {"with_labels": True,
"alpha":0.8,
"node_size": 350,
"node_color": get_clr_list(pattern),
"edgecolors": "k"}

nx.draw(g, pos=pos, **graph_params)
pattern.draw_graph()

#%%
# The resource state after Pauli measurement preprocessing:
pattern.perform_pauli_measurements()
nodes, edges = pattern.get_graph()
g = nx.Graph()
g.add_nodes_from(nodes)
g.add_edges_from(edges)
graph_params = {"with_labels": True,
"alpha":0.8,
"node_size": 350,
"node_color": get_clr_list(pattern),
"edgecolors": "k"}

pos = { # hand-typed for better look
3: (0,0),
4: (1,0),
5: (2,0),
7: (3,0),
11: (0,-1),
12: (3,-1),
13: (4,-1),
15: (5,-1),
20: (4,0),
21: (5,0),
22: (6,0),
23: (7,0),
25: (8,0),
27: (9,0),
28: (6,-1),
29: (7,-1),
30: (8,-1),
31: (9,-1),
33: (10,-1),
35: (11,-1),
}

nx.draw(g, pos=pos, **graph_params)
pattern.draw_graph()

#%%
# Qubit Resource plot
Expand Down Expand Up @@ -457,4 +371,5 @@ def get_clr_list(pattern):
plt.plot(qubits, after_meas, '.-', label='After Pauli Meas')
plt.xlabel("qubits")
plt.ylabel("max space")
plt.show()
plt.show()
# %%
49 changes: 37 additions & 12 deletions examples/rotation.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
"""
Simple example
==============
Simple example & visualizing graphs
===================================
Here, we show a most basic MBQC proramming using graphix library.
In this example, we consider trivial problem of the rotation of two qubits in |0> states.
We show how transpiler (:class:`~graphix.transpiler.Circuit` class) can be used, and show the resulting meausrement pattern.
In the next example, we describe our visualization tool :class:`~graphix.visualization.GraphVisualizer` and how to understand the plot.
First, let us import relevant modules:
"""
#%%
import numpy as np
from graphix import Circuit, Statevec
from graphix.ops import Ops
import networkx as nx
import matplotlib.pyplot as plt

#%%
# Here, :class:`~graphix.sim.statevec.Statevec` is our simple statevector simulator class.
# Next, let us define the problem with a standard quantum circuit.
# Note that in graphix all qubits starts in |+> states. For this example, we use Hadamard gate (:meth:`graphix.transpiler.Circuit.h`) to start with |0>
# Note that in graphix all qubits starts in |+> states. For this example, we use Hadamard gate (:meth:`graphix.transpiler.Circuit.h`) to start with |0> states instead.

circuit = Circuit(2)

Expand All @@ -42,18 +43,22 @@
# We can plot the graph state to run the above pattern.
# Since there's no two-qubit gates applied to the two qubits in the original gate sequence,
# we see decoupled 1D graphs representing the evolution of single qubits.
nodes, edges = pattern.get_graph()
g = nx.Graph()
g.add_nodes_from(nodes)
g.add_edges_from(edges)
np.random.seed(100)
nx.draw(g)
plt.show()
# The arrows are the `information flow <https://journals.aps.org/pra/abstract/10.1103/PhysRevA.74.052310>`_ of the MBQC pattern, obtained using the flow-finding algorithm implemented in :class:`graphix.gflow.flow`.
# Below we list the meaning of the node boundary and face colors.
#
# - Nodes with red boundaries are the *input nodes* where the computation starts.
# - Nodes with gray color is the *output nodes* where the final state end up in.
# - Nodes with blue color is the nodes that are measured in *Pauli basis*, one of *X*, *Y* or *Z* computational bases.
# - Nodes in white are the ones measured in *non-Pauli basis*.
#
pattern.draw_graph()

#%%
# we can directly simulate the measurement pattern, to obtain the output state.
# Internally, we are executing the command sequence we inspected above on a statevector simulator.
# We also have a tensornetwork simulation backend to handle larger MBQC patterns. see other examples for how to use it.

out_state = pattern.simulate_pattern()
out_state = pattern.simulate_pattern(backend='statevector')
print(out_state.flatten())

#%%
Expand All @@ -63,3 +68,23 @@
state.evolve_single(Ops.Rx(theta[0]), 0)
state.evolve_single(Ops.Rx(theta[1]), 1)
print("overlap of states: ", np.abs(np.dot(state.psi.flatten().conjugate(), out_state.psi.flatten())))

#%%
# Now let us compile more complex pattern and inspect the graph using the visualization tool.
# Here, the additional edges with dotted lines are the ones that correspond to CNOT gates, which creates entanglement between the 1D clusters (nodes connected with directed edges) corresponding to the time evolution of a single qubit in the original circuit.
circuit = Circuit(2)

# apply rotation gates
theta = np.random.rand(4)
circuit.rz(0, theta[0])
circuit.rz(1, theta[1])
circuit.cnot(0, 1)
circuit.s(0)
circuit.cnot(1, 0)
circuit.rz(1, theta[2])
circuit.cnot(1, 0)
circuit.rz(0, theta[3])

pattern = circuit.transpile()
pattern.draw_graph()
# %%
2 changes: 1 addition & 1 deletion graphix/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.2.6"
__version__ = "0.2.7"

0 comments on commit 789ca30

Please sign in to comment.