Browse Source

Merge branch 'pete'

Conflicts:
	.bumpversion.cfg
	setup.py
master
Pete Shadbolt 7 years ago
parent
commit
75227a354e
11 changed files with 60 additions and 38 deletions
  1. +1
    -1
      .bumpversion.cfg
  2. +26
    -11
      abp/graphstate.py
  3. +1
    -0
      doc/index
  4. +1
    -3
      doc/index.rst
  5. +1
    -1
      setup.py
  6. +1
    -1
      tests/mock.py
  7. +4
    -4
      tests/test_fancy.py
  8. +11
    -3
      tests/test_graphstate.py
  9. +7
    -7
      tests/test_measurement.py
  10. +5
    -5
      tests/test_mercedes.py
  11. +2
    -2
      tests/test_qi.py

+ 1
- 1
.bumpversion.cfg View File

@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.4.13
current_version = 0.4.14
commit = True
tag = True



+ 26
- 11
abp/graphstate.py View File

@@ -16,19 +16,25 @@ class GraphState(object):
Internally it uses the same dictionary-of-dictionaries data structure as ``networkx``.
"""

def __init__(self, nodes=[], deterministic=False):
def __init__(self, nodes=[], deterministic=False, vop="identity"):
""" Construct a ``GraphState``

:param nodes: An iterable of nodes used to construct the graph.
:param nodes: An iterable of nodes used to construct the graph, or an integer -- the number of nodes.
:param deterministic: If ``True``, the behaviour of the graph is deterministic up to but not including the choice of measurement outcome. This is slightly less efficient, but useful for testing. If ``False``, the specific graph representation will sometimes be random -- of course, all possible representations still map to the same state vector.
:param vop: The default VOP for new qubits. Setting ``vop="identity"`` initializes qubits in :math:`|+\\rangle`. Setting ``vop="hadamard"`` initializes qubits in :math:`|0\\rangle`.
"""

self.adj, self.node = {}, {}
self.add_nodes(nodes)
self.deterministic = deterministic
self.adj, self.node = {}, {}
try:
for n in nodes:
self._add_node(n, vop=vop)
except TypeError:
for n in range(nodes):
self._add_node(n, vop=vop)

def add_node(self, node, **kwargs):
""" Add a node.
def _add_node(self, node, **kwargs):
""" Add a node. By default, nodes are initialized with ``vop=``:math:`I`, i.e. they are in the :math:`|+\\rangle` state.

:param node: The name of the node, e.g. ``9``, ``start``
:type node: Any hashable type
@@ -42,14 +48,23 @@ class GraphState(object):

"""
assert not node in self.node, "Node {} already exists".format(v)
default = kwargs.get("default", "identity")
self.adj[node] = {}
self.node[node] = {"vop": clifford.by_name["hadamard"]}
self.node[node] = {}
kwargs["vop"] = clifford.by_name[str(kwargs.get("vop", "identity"))] #TODO: ugly
self.node[node].update(kwargs)

def add_nodes(self, nodes):
""" Add many nodes in one shot. """
for n in nodes:
self.add_node(n)
def add_qubit(self, name, **kwargs):
""" Add a qubit to the state.

:param name: The name of the node, e.g. ``9``, ``start``.
:type name: Any hashable type
:param kwargs: Any extra node attributes

By default, qubits are initialized in the :math:`|0\\rangle` state. Provide the optional ``vop`` argument to set the initial state.
"""
kwargs["vop"] = clifford.by_name[str(kwargs.get("vop", "hadamard"))] #TODO: ugly
self._add_node(name, **kwargs)

def act_circuit(self, circuit):
""" Run many gates in one call.


+ 1
- 0
doc/index View File

@@ -0,0 +1 @@
_build/html/index.html

+ 1
- 3
doc/index.rst View File

@@ -81,9 +81,7 @@ The ``abp.GraphState`` class is the main interface to ``abp``.

.. automethod:: abp.GraphState.__init__

.. automethod:: abp.GraphState.add_node

.. automethod:: abp.GraphState.add_nodes
.. automethod:: abp.GraphState.add_qubit

.. automethod:: abp.GraphState.act_local_rotation



+ 1
- 1
setup.py View File

@@ -6,7 +6,7 @@ STATIC = glob("abp/static/*.*")+glob("abp/static/img/*.*")+glob("abp/static/scri

setup(
name = "abp",
version = "0.4.13",
version = "0.4.14",
packages = ["abp", "abp.static"],
test_suite = "tests",
author = "Pete Shadbolt",


+ 1
- 1
tests/mock.py View File

@@ -52,7 +52,7 @@ class ABPWrapper(GraphState):
""" A wrapper for abp, just to ensure determinism """

def __init__(self, nodes=[]):
super(ABPWrapper, self).__init__(nodes, deterministic=True)
super(ABPWrapper, self).__init__(nodes, deterministic=True, vop="hadamard")

def print_stabilizer(self):
print self.to_stabilizer()


+ 4
- 4
tests/test_fancy.py View File

@@ -15,16 +15,16 @@ def test_json_basic():
def test_tuple_keys():
""" Test that we can use tuple-ish keys """
g = fancy.GraphState()
g.add_node("string")
g.add_node((1, 2, 3))
g.add_qubit("string")
g.add_qubit((1, 2, 3))
g.add_edge((1, 2, 3), "string")
json.dumps(g.to_json(True))

def networkx_test():
""" Test that fancy graph states really behave like networkx graphs """
g = fancy.GraphState()
g.add_node(0, position = xyz(10, 0, 0))
g.add_node(1, position = xyz(1, 0, 0))
g.add_qubit(0, position = xyz(10, 0, 0))
g.add_qubit(1, position = xyz(1, 0, 0))
g.act_hadamard(0)
g.act_hadamard(1)
g.act_cz(0, 1)


+ 11
- 3
tests/test_graphstate.py View File

@@ -7,6 +7,14 @@ from tqdm import tqdm
REPEATS = 100
DEPTH = 100

def test_initialization():
g = GraphState("abc")
assert g.node["a"]["vop"] == clifford.by_name["identity"]
g = GraphState("abc", vop="hadamard")
assert g.node["c"]["vop"] == clifford.by_name["hadamard"]
g = GraphState(5)
assert len(g.node) == 5


def test_graph_basic():
""" Test that we can construct graphs, delete edges, whatever """
@@ -56,7 +64,7 @@ def test_edgelist():
def test_stress(n=int(1e5)):
""" Testing that making a graph of ten thousand qubits takes less than half a second"""
import time
g = GraphState(range(n + 1))
g = GraphState(range(n + 1), vop="hadamard")
t = time.clock()
for i in xrange(n):
g._add_edge(i, i + 1)
@@ -65,7 +73,7 @@ def test_stress(n=int(1e5)):

def test_cz():
""" Test CZ gate """
g = GraphState([0, 1])
g = GraphState([0, 1], vop="hadamard")
g.act_local_rotation(0, clifford.by_name["hadamard"])
g.act_local_rotation(1, clifford.by_name["hadamard"])
g.act_local_rotation(1, clifford.by_name["py"])
@@ -77,7 +85,7 @@ def test_cz():
def test_local_complementation():
""" Test that local complementation works okay """
pairs = (0, 1), (0, 3), (1, 3), (1, 2),
psi = GraphState(range(4))
psi = GraphState(range(4), vop="hadamard")
psi.act_circuit([(i, "hadamard") for i in psi.node])
psi.act_circuit([(pair, "cz") for pair in pairs])
old_edges = psi.edgelist()


+ 7
- 7
tests/test_measurement.py View File

@@ -10,16 +10,16 @@ def test_single_qubit_measurements():
""" Various simple tests of measurements """

# Test that measuring |0> in Z gives 0
g = GraphState([0])
g = GraphState([0], vop="hadamard")
assert g.measure(0, "pz") == 0, "Measuring |0> in Z gives 0"

# Test that measuring |1> in Z gives 1
g = GraphState([0])
g = GraphState([0], vop="hadamard")
g.act_local_rotation(0, "px")
assert g.measure(0, "pz") == 1, "Measuring |1> in Z gives 1"

# Test that measuring |+> in X gives 0
g = GraphState([0])
g = GraphState([0], vop="hadamard")
g.act_local_rotation(0, "hadamard")
assert g.measure(0, "px") == 0
assert g.measure(0, "px") == 0, "Measuring |+> in X gives 0"
@@ -30,7 +30,7 @@ def test_single_qubit_measurements():
def test_type():
""" Test that the output is always an int """
for r, m, f in it.product(range(24), ("px", "py", "pz"), (0, 1)):
g = GraphState([0])
g = GraphState([0], vop="hadamard")
g.act_local_rotation(0, r)
assert str(g.measure(0, m)) in "01"
assert str(g.measure(0, m, f)) in "01"
@@ -41,7 +41,7 @@ def test_random_outcomes():
""" Testing random behaviour """
ones = 0
for i in range(1000):
g = GraphState([0])
g = GraphState([0], vop="hadamard")
g.act_local_rotation(0, "hadamard")
ones += g.measure(0, "pz")
assert 400 < ones < 600, "This is a probabilistic test!"
@@ -49,13 +49,13 @@ def test_random_outcomes():

def test_projection():
""" Test that projection works correctly """
g = GraphState([0])
g = GraphState([0], vop="hadamard")
g.act_local_rotation(0, "hadamard")
g.measure(0, "pz", 0)
assert np.allclose(g.to_state_vector().state, qi.zero)

# Now project onto |1>
g = GraphState([0])
g = GraphState([0], vop="hadamard")
g.act_local_rotation(0, "hadamard")
g.measure(0, "pz", 1)
assert np.allclose(g.to_state_vector().state, qi.one)

+ 5
- 5
tests/test_mercedes.py View File

@@ -3,7 +3,7 @@ from abp.util import xyz
from mock import simple_graph

def linear_cluster(n):
g = GraphState(range(n))
g = GraphState(range(n), vop="hadamard")
g.act_circuit([(i, "hadamard") for i in range(n)])
g.act_circuit([((i, i+1), "cz") for i in range(n-1)])
return g
@@ -23,16 +23,16 @@ def test_single_qubit_measurements():
""" Various simple tests of measurements """

# Test that measuring |0> in Z gives 0
g = GraphState([0])
g = GraphState([0], vop="hadamard")
assert g.measure_z(0) == 0, "Measuring |0> in Z gives 0"

# Test that measuring |1> in Z gives 1
g = GraphState([0])
g = GraphState([0], vop="hadamard")
g.act_local_rotation(0, "px")
assert g.measure_z(0) == 1, "Measuring |1> in Z gives 1"

# Test that measuring |+> in X gives 0
g = GraphState([0])
g = GraphState([0], vop="hadamard")
g.act_local_rotation(0, "hadamard")
assert g.measure_x(0) == 0
assert g.measure_x(0) == 0, "Measuring |+> in X gives 0"
@@ -44,7 +44,7 @@ def test_single_qubit_measurements():

def test_is_determinate():
""" Test whether asking if an outcome was random or determinate works """
g = GraphState([0])
g = GraphState([0], vop="hadamard")
assert g.measure_z(0, detail=True)["determinate"] == True
assert g.measure_x(0, detail=True)["determinate"] == False



+ 2
- 2
tests/test_qi.py View File

@@ -104,8 +104,8 @@ def test_dumbness():
def test_to_state_vector_single_qubit():
""" Test some single-qubit stuff """
g = GraphState()
g.add_node(0)
g.add_node(1)
g.add_qubit(0)
g.add_qubit(1)
g.act_local_rotation(0, "hadamard")
g.act_local_rotation(1, "hadamard")
g.act_cz(0, 1)


Loading…
Cancel
Save