Skip to content

Commit

Permalink
Merge pull request #48 from ChitambarLab/multiqubit-entanglement-ansatz
Browse files Browse the repository at this point in the history
Multiqubit entanglement ansatz
  • Loading branch information
bdoolittle authored Jan 20, 2023
2 parents a695dba + d371217 commit 5cea880
Show file tree
Hide file tree
Showing 9 changed files with 503 additions and 114 deletions.
2 changes: 1 addition & 1 deletion CITATION.bib
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ @misc{qNetVO
title = {qNetVO: the Quantum Network Variational Optimizer},
howpublished = {\url{https://github.com/ChitambarLab/qNetVO}},
url = {https://github.com/ChitambarLab/qNetVO},
version = {v0.4.0},
version = {v0.4.1},
year = {2022},
month = {March},
doi = {10.5281/zenodo.6345834},
Expand Down
10 changes: 10 additions & 0 deletions docs/source/quantum_networks/ansatz_library.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ State Preparations

.. autofunction:: max_entangled_state

.. autofunction:: nonmax_entangled_state

.. autofunction:: graph_state_fn

.. autofunction:: W_state

.. autofunction:: shared_coin_flip_state


Unitary Layers
--------------
Expand All @@ -23,6 +31,8 @@ Unitary Layers

.. autofunction:: local_RXRY

.. autofunction:: local_Rot


Noise Models
------------
Expand Down
4 changes: 4 additions & 0 deletions docs/source/utilities.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ Utilities
Circuit Tomography
------------------

.. autofunction:: state_vec_fn

.. autofunction:: density_mat_fn

.. autofunction:: unitary_matrix

File I/O
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = qNetVO
version = 0.4.0
version = 0.4.1
author = Brian Doolittle and Tom Bromley
author_email = [email protected]
description = The Quantum Network Variational Optimizer
Expand Down
110 changes: 109 additions & 1 deletion src/qnetvo/ansatz_library.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pennylane as qml
from pennylane.operation import Channel
from pennylane import numpy as np
import numpy as np
import math

eps = 1e-7 # constant
Expand All @@ -27,6 +27,25 @@ def max_entangled_state(settings, wires):
qml.Rot(*settings, wires=wires[0])


def nonmax_entangled_state(settings, wires):
"""Initializes a nonmaximally entangled GHZ-like state that has a bias between its two outcomes.
The state takes the form
.. math::
|\\psi_\\theta\\rangle = \\cos(\\frac{\\theta}{2})|0\\dots 0\\rangle + \\sin(\\frac{\\theta}{2})|1 \\dots 1\\rangle
:param settings: A list of length 1 containing paraameter :math:`\\theta`
:type settings: list[float]
:param wires: A list of wires to prepare the nonmaximally entangled GHZ-like state.
:type wires: list[int] or qml.Wires
"""
qml.RY(settings[0], wires=wires[0])
for i in range(1, len(wires)):
qml.CNOT(wires=[wires[0], wires[i]])


def bell_state_copies(settings, wires):
"""Initializes :math:`n` Bell states on :math:`2n` wires.
The first :math:`n` wires represent Alice's half of the entangled
Expand Down Expand Up @@ -60,6 +79,79 @@ def ghz_state(settings, wires):
qml.CNOT(wires=[wires[0], wires[i]])


def W_state(settings, wires):
"""Initializes the three-qubit :math:`W`-state on the specified wires.
.. math::
|\\psi^W\\rangle = \\frac{1}{\\sqrt{3}}(|100\\rangle + |010\\rangle + |001 \\rangle)
:param settings: A placeholder parameter that is not used.
:type settings: list[empty]
:param wires: The wires on which the :math:`W`-state is prepared.
:type wires: qml.Wires
"""
phi = 2 * np.arccos(1 / np.sqrt(3))
qml.RY(phi, wires=wires[0])
qml.CRY(np.pi / 2, wires=wires[0:2])

qml.CNOT(wires=wires[1:3])
qml.CNOT(wires=wires[0:2])
qml.PauliX(wires=wires[0])


def graph_state_fn(edges):
"""Constructs a quantum function that prepares a graph state
where each qubit wire is a vertex and the ``edge`` are tuple pairs
of interacting wires. A graph state takes the form
.. math::
|\\psi^G \\rangle = \\prod_{(a,b) \\in Edges} CZ^{(a,b)} |+\\rangle^{\\otimes N}
where :math:`N` is the number of qubits, :math:`|+\\rangle = \\frac{1}{\\sqrt{2}}(|0\\rangle + |1\\rangle)`, :math:`(a,b)` is a pair of wires defining
an edge, and :math:`CZ^{(a,b)}` is a controlled-phase operation operating upon the qubit
pair :math:`(a,b)`. For more details, see the :meth:`qml.CZ` function in the `PennyLane docs <https://docs.pennylane.ai/en/stable/>`_.
:param edges: A list of qubit pair tuples defining the wires to which controlled-phase
operations are applied.
:type settings: list[tuple[int]]
:returns: A quantum circuit `graph_state(settings, wires)` that prepares the specified
graph state. Note that ``wires`` must contain all qubits specified in ``edges``.
:rtype: Function
"""

def graph_state(settings, wires):
for wire in wires:
qml.Hadamard(wire)

for edge in edges:
qml.CZ(wires=[wires[edge[0]], wires[edge[1]]])

return graph_state


def shared_coin_flip_state(settings, wires):
"""Initializes a state that mirrors a biased coin flip shared amongst the qubits
on ``wires[0:-1]`` where ``wires[-1]`` is an ansatz used to generate shared randomness.
The shared coin flip is represented by the density matrix.
.. math::
\\rho_\\theta = \\cos^2(\\frac{\\theta}{2})|0\\dots 0\\rangle\\langle 0 \\dots 0| + \\sin^2(\\frac{\\theta}{2})|1\\dots 1 \\rangle \\langle 1 \\dots 1|
:param settings: A list of 1 real value.
:type settings: list[float]
:param wires: The wires used to prepare the shaared coin flip state. Note that the last wire is used as an ancilla.
:type wires: qml.Wires
"""
nonmax_entangled_state(settings, wires)


def local_RY(settings, wires):
"""Performs a rotation about :math:`y`-axis on each qubit
specified by ``wires``.
Expand All @@ -73,6 +165,22 @@ def local_RY(settings, wires):
qml.broadcast(qml.RY, wires, "single", settings)


def local_Rot(settings, wires):
"""Performs an arbitrary qubit unitary as defined by :meth:`qml.Rot`
on each qubit specified by ``wires``.
For more details on :meth:`qml.Rot` please refer to the
`PennyLane docs <https://docs.pennylane.ai/en/stable/>`_.
:param settings: A list of ``3 * len(wires)`` real values.
:type settings: list[float]
:param wires: The wires to which the qubit unitaries are applied.
:type wires: qml.Wires
"""
for i in range(len(wires)):
qml.Rot(*settings[3 * i : 3 * i + 3], wires=wires[i])


def local_RXRY(settings, wires):
"""Performs a rotation about the :math:`x` and :math:`y` axes on
each qubit specified by ``wires``.
Expand Down
71 changes: 62 additions & 9 deletions src/qnetvo/utilities.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pennylane as qml
import pennylane.numpy as np
import pennylane.numpy as qnp
import numpy as np
from pennylane import math
import itertools
import copy
Expand All @@ -25,18 +26,70 @@ def unitary_matrix(circuit, num_wires, *circ_args, **circ_kwargs):
:returns: A unitary matrix representing the provided ``circuit``.
:rtype: Numpy Array
"""
dev = qml.device("default.qubit", wires=range(num_wires))
state_vec = state_vec_fn(circuit, num_wires)

bitstrings = [np.array(bitstring) for bitstring in itertools.product([0, 1], repeat=num_wires)]

unitary = [
state_vec(*circ_args, basis_state=bitstring, **circ_kwargs).numpy()
for bitstring in bitstrings
]
return np.array(unitary).T


def state_vec_fn(circuit, num_wires):
"""Constructs a function ``state_vec(*circ_args, basis_state=[0,...,0], **circ_kwargs)``
that returns the state vector representation of the output of ``circuit`` where the input
to the circuit is specified in the computational basis by ``basis_state``.
:param circuit: A quantum function.
:type circuit: Function
:param num_wires: The number of wires to evaluate ``circuit`` on.
:type num_wires: Int
:returns: A vector representing the pure quantum state output from ``circuit(*circ_args, **circ_kwargs)``
when the computational ``basis_state`` is provided as input.
:rtype: np.array
"""
dev_wires = range(num_wires)
dev = qml.device("default.qubit", wires=dev_wires)
zero_state = np.array([0] * len(dev_wires))

@qml.qnode(dev)
def unitary_z(basis_state):
qml.BasisState(basis_state, wires=range(num_wires))
def state_vec(*circ_args, basis_state=zero_state, **circ_kwargs):
qml.BasisState(basis_state, wires=dev_wires)
circuit(*circ_args, **circ_kwargs)
return qml.state()

bitstrings = [np.array(bitstring) for bitstring in itertools.product([0, 1], repeat=num_wires)]
return state_vec


def density_mat_fn(circuit, num_wires):
"""Constructs a function that returns the density matrix of the specified ``circuit``.
:param circuit: A quantum function.
:type circuit: Function
:param num_wires: The number of wires to evaluate ``circuit`` on.
:type num_wires: Int
:returns: A function ``density_mat(wires_out, *circ_args, basis_state=[0,...,0], **circ_kwargs)`` that returns
the density matrix representing the quantum state on ``wires_out`` for the initialized ``basis_state`` where
the quantum circuit is called as ``circuit(*circ_args, **circ_kwargs)``.
:rtype: np.array
"""
dev_wires = range(num_wires)
dev = qml.device("default.qubit", wires=dev_wires)
zero_state = np.array([0] * len(dev_wires))

@qml.qnode(dev)
def density_mat(wires_out, *circ_args, basis_state=zero_state, **circ_kwargs):
qml.BasisState(basis_state, wires=dev_wires)
circuit(*circ_args, **circ_kwargs)
return qml.density_matrix(wires=wires_out)

u = [unitary_z(bitstring).numpy() for bitstring in bitstrings]
return np.array(u).T
return density_mat


def write_optimization_json(opt_dict, filename):
Expand Down Expand Up @@ -109,8 +162,8 @@ def settings_to_np(list_network_settings):
:returns: The same nested array elements and structure using numpy arrays.
"""

np_prep_settings = [np.array(node_settings) for node_settings in list_network_settings[0]]
np_meas_settings = [np.array(node_settings) for node_settings in list_network_settings[1]]
np_prep_settings = [qnp.array(node_settings) for node_settings in list_network_settings[0]]
np_meas_settings = [qnp.array(node_settings) for node_settings in list_network_settings[1]]

return [np_prep_settings, np_meas_settings]

Expand Down
Loading

0 comments on commit 5cea880

Please sign in to comment.