Browse Source

Better docs

master
Pete Shadbolt 7 years ago
parent
commit
2126ae219f
5 changed files with 103 additions and 26 deletions
  1. +1
    -1
      README.md
  2. +47
    -15
      abp/graphstate.py
  3. +4
    -0
      doc/Makefile
  4. +3
    -3
      doc/conf.py
  5. +48
    -7
      doc/index.rst

+ 1
- 1
README.md View File

@@ -15,7 +15,7 @@ $ pip install --user abp
Or clone and install:

```shell
$ git clone https://github.com/peteshadbolt/abp
$ git clone https://github.com/peteshadbolt/abp.git
$ python setup.py install --user
```



+ 47
- 15
abp/graphstate.py View File

@@ -15,7 +15,7 @@ class GraphState(object):
"""

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

:param nodes: An iterable of nodes used to construct the graph.
: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.
@@ -26,10 +26,18 @@ class GraphState(object):
self.deterministic = deterministic

def add_node(self, node, **kwargs):
""" Add a node
""" Add a node.
:param node: The name of the node, e.g. ``9``, ``start``
:type node: Any hashable type
:param kwargs: Any extra node attributes
Example of using node attributes ::

>>> g.add_node(0, label="fred", position=(1,2,3))
>>> g.node[0]["label"]
fred
"""
assert not node in self.node, "Node {} already exists".format(v)
self.adj[node] = {}
@@ -37,18 +45,16 @@ class GraphState(object):
self.node[node].update(kwargs)

def add_nodes(self, nodes):
""" Add a buncha nodes """
""" Add many nodes in one shot. """
for n in nodes:
self.add_node(n)

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

:param circuit: An iterable containing tuples of the form ``(node, operation)``.
If ``operation`` is a name for a local operation (e.g. ``6``, ``hadamard``) then that operation is performed on ``node``.
If ``operation`` is ``"cz"`` then a CZ is performed on the two nodes in ``node.
:param circuit: An iterable containing tuples of the form ``(node, operation)``. If ``operation`` is a name for a local operation (e.g. ``6``, ``hadamard``) then that operation is performed on ``node``. If ``operation`` is ``cz`` then a CZ is performed on the two nodes in ``node``.

For example::
Example (makes a Bell pair)::
>>> g.act_circuit([(0, "hadamard"), (1, "hadamard"), ((0, 1), "cz")])

@@ -160,7 +166,15 @@ class GraphState(object):
self._toggle_edge(a, b)

def measure(self, node, basis, force=None):
""" Measure in an arbitrary basis """
""" Measure in an arbitrary basis

:param node: The name of the qubit to measure.
:param basis: The basis in which to measure.
:type basis: :math:`\in` ``{"px", "py", "pz"}``
:param force: Measurements in quantum mechanics are probabilistic. If you want to force a particular outcome, use the ``force``.
:type force: boolean
"""
basis = clifford.by_name[basis]
ha = clifford.conjugation_table[self.node[node]["vop"]]
basis, phase = clifford.conjugate(basis, ha)
@@ -287,10 +301,16 @@ class GraphState(object):
return s

def to_json(self, stringify=False):
"""
Convert the graph to JSON form.
JSON keys must be strings, But sometimes it is useful to have
a JSON-like object whose keys are tuples!
""" Convert the graph to JSON-like form.
:param stringify: JSON keys must be strings, But sometimes it is useful to have a JSON-like object whose keys are tuples.

If you want to dump a graph do disk, do something like this::
>>> import json
>>> with open("graph.json") as f:
json.dump(graph.to_json(True), f)

"""
if stringify:
node = {str(key): value for key, value in self.node.items()}
@@ -306,7 +326,18 @@ class GraphState(object):
# TODO

def to_state_vector(self):
""" Get the full state vector """
""" Get the full state vector corresponding to this stabilizer state. Useful for debugging, interface with other simulators.

The output state is represented as a ``abp.qi.CircuitModel``::
>>> print g.to_state_vector()
|00000>: 0.18+0.00j
|00001>: 0.18+0.00j ...
.. warning::
Obviously this method becomes very slow for more than about ten qubits!

"""
if len(self.node) > 15:
raise ValueError("Cannot build state vector: too many qubits")
state = qi.CircuitModel(len(self.node))
@@ -319,7 +350,8 @@ class GraphState(object):
return state

def to_stabilizer(self):
""" Get the stabilizer of this graph """
""" Get the stabilizer tableau. Work in progress!
"""
return
output = {a: {} for a in self.node}
for a, b in it.product(self.node, self.node):


+ 4
- 0
doc/Makefile View File

@@ -190,3 +190,7 @@ pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

deploy:
scp -r ./_build/html/* rpi:abp/


+ 3
- 3
doc/conf.py View File

@@ -173,13 +173,13 @@ html_static_path = ['_static']
#html_split_index = False

# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
html_show_sourcelink = False

# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
html_show_sphinx = False

# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
html_show_copyright = False

# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the


+ 48
- 7
doc/index.rst View File

@@ -16,6 +16,8 @@ This is the documentation for ``abp``. It's a work in progress.
That means that you can make quantum states of thousands of qubits, perform any sequence of Clifford operations, and measure in any of :math:`\{\sigma_x, \sigma_y, \sigma_z\}`.
It should do thousands of qubits without much trouble.

.. image:: ../examples/demo.gif

Installing
----------------------------

@@ -58,9 +60,6 @@ It's pretty easy to build a graph state, act some gates, and do measurements::
2: IA (1,3)
3: IA (2,4)
4: IA (3,)
>>> print g.to_state_vector()
|00000>: 0.18+0.00j
|00001>: 0.18+0.00j ...
>>> g.measure(2, "px")
0
>>> print g
@@ -70,7 +69,7 @@ It's pretty easy to build a graph state, act some gates, and do measurements::
3: ZA (0,1,4)
4: IA (3,)

GraphState
Working with GraphStates
-------------------------

The ``abp.GraphState`` class is your main interface to ``abp``.
@@ -90,15 +89,57 @@ Here follows complete documentation

.. automethod:: abp.GraphState.act_cz

.. automethod:: abp.GraphState.add_edge
.. automethod:: abp.GraphState.act_circuit

.. automethod:: abp.GraphState.measure

.. automethod:: abp.GraphState.to_json

.. automethod:: abp.GraphState.to_state_vector

.. automethod:: abp.GraphState.to_stabilizer

The Clifford group
----------------------

Visualization
----------------------

``abp`` comes with a tool to visualize graph states in a WebGL compatible web browser (Chrome, Firefox, Safari etc). It uses a client-server architecture.

First, run ``abpserver`` in a terminal:

.. code-block:: bash

$ abpserver
Listening on port 5000 for clients..

Then browse to ``http://localhost:5001/`` (in some circumstances ``abp`` will automatically pop a browser window).

Now, in another terminal, use ``abp.fancy.GraphState`` to run a Clifford circuit::

>>> from abp.fancy import GraphState
>>> g = GraphState(10)
>>> g = GraphState(range(10))
>>> for i in range(10):
... g.act_hadamard(i)
...
>>> g.update()
>>> for i in range(9):
... g.act_cz(i, i+1)
...
>>> g.update()
```

.. automethod:: abp.GraphState.add_edges
And you should see a 3D visualization of the state.

.. automethod:: abp.GraphState.del_edge
.. image:: ../examples/viz.png

Reference
----------------------------

More detailed docs are available here:

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`


Loading…
Cancel
Save