Skip to content

Commit

Permalink
Phase Estimation as a Gate in ops (#260)
Browse files Browse the repository at this point in the history
* First testing version of Phase Estimation with a lot of hardcoding

* Adapt to All(Measure)

* Adding operators for more than 1 quibit, first version

* Adding operators for more than 1 quibit, first versioni: testing

* Work in progress: create a PhaseX gate to tests via class

* Work in progress: create a PhaseX gate to tests via class. Clean garbaje files

* Work in progress: create a PhaseX gate to tests via class. Some enhanement

* Work in progress: create a PhaseX gate to tests via class. PhaseX testing

* Work in progress: Debugging algorithm

* Work in progress: Debugging algorithm

* Adding 2qubit example

* adding 2 qubit Gate

* Initial version

* Create Phase Estimation as a new Gate in operations

* Solving travis checks

* python 2 compatibility + error in StatePreparation normalization

* test coverage includes now the string

* Improve the check test for no eigenvector test

* Start modifying to decomposition

* QPE as decomposition and gate

* QPE as decomposition and gate: correct a detail in the test

* try to get the travis-ci freeze solved

* Solve a name not defined error in the phaseestimation tests

* Solve coverage in tests

* Address comments in review + change how to assert the tests

* Enhance statistis in the tests bi more executions

* Correct bad calculation in tests

* Refine test

* Address Andi comments: add detail in the examples and atributes and removing code in the test that is never executed
  • Loading branch information
fernandodelaiglesia authored and Takishima committed May 6, 2019
1 parent 6db7038 commit 3ac3c2c
Show file tree
Hide file tree
Showing 8 changed files with 357 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/projectq.ops.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ The operations collection consists of various default gates and is a work-in-pro
projectq.ops.UniformlyControlledRy
projectq.ops.UniformlyControlledRz
projectq.ops.StatePreparation
projectq.ops.QPE
projectq.ops.FlipBits


Expand Down
8 changes: 8 additions & 0 deletions docs/projectq.setups.decompositions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ The decomposition package is a collection of gate decomposition / replacement ru
projectq.setups.decompositions.time_evolution
projectq.setups.decompositions.toffoli2cnotandtgate
projectq.setups.decompositions.uniformlycontrolledr2cnot
projectq.setups.decompositions.phaseestimation


Submodules
Expand Down Expand Up @@ -172,6 +173,13 @@ projectq.setups.decompositions.uniformlycontrolledr2cnot module
:members:
:undoc-members:

projectq.setups.decompositions.phaseestimation module
---------------------------------------------------------------

.. automodule:: projectq.setups.decompositions.phaseestimation
:members:
:undoc-members:


Module contents
---------------
Expand Down
1 change: 1 addition & 0 deletions projectq/ops/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@
from ._uniformly_controlled_rotation import (UniformlyControlledRy,
UniformlyControlledRz)
from ._state_prep import StatePreparation
from ._qpegate import QPE
29 changes: 29 additions & 0 deletions projectq/ops/_qpegate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Copyright 2017 ProjectQ-Framework (www.projectq.ch)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from ._basics import BasicGate


class QPE(BasicGate):
"""
Quantum Phase Estimation gate.
See setups.decompositions for the complete implementation
"""
def __init__(self, unitary):
BasicGate.__init__(self)
self.unitary = unitary

def __str__(self):
return 'QPE({})'.format(str(self.unitary))
23 changes: 23 additions & 0 deletions projectq/ops/_qpegate_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2017 ProjectQ-Framework (www.projectq.ch)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Tests for projectq.ops._qpegate."""

from projectq.ops import _qpegate, X


def test_qpe_str():
unitary = X
gate = _qpegate.QPE(unitary)
assert str(gate) == "QPE(X)"
6 changes: 4 additions & 2 deletions projectq/setups/decompositions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
swap2cnot,
toffoli2cnotandtgate,
time_evolution,
uniformlycontrolledr2cnot)
uniformlycontrolledr2cnot,
phaseestimation)

all_defined_decomposition_rules = [
rule
Expand All @@ -54,6 +55,7 @@
swap2cnot,
toffoli2cnotandtgate,
time_evolution,
uniformlycontrolledr2cnot]
uniformlycontrolledr2cnot,
phaseestimation]
for rule in module.all_defined_decomposition_rules
]
129 changes: 129 additions & 0 deletions projectq/setups/decompositions/phaseestimation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Copyright 2018 ProjectQ-Framework (www.projectq.ch)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Registers a decomposition for phase estimation.
(reference https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm)
The Quantum Phase Estimation (QPE) executes the algorithm up to the inverse
QFT included. The following steps measuring the ancillas and computing the
phase should be executed outside of the QPE.
The decomposition uses as ancillas (qpe_ancillas) the first qubit/qureg in
the Command and as system qubits teh second qubit/qureg in the Command.
The unitary operator for which the phase estimation is estimated (unitary)
is the gate in Command
Example:
.. code-block:: python
# Example using a ProjectQ gate
n_qpe_ancillas = 3
qpe_ancillas = eng.allocate_qureg(n_qpe_ancillas)
system_qubits = eng.allocate_qureg(1)
angle = cmath.pi*2.*0.125
U = Ph(angle) # unitary_specfic_to_the_problem()
# Apply Quantum Phase Estimation
QPE(U) | (qpe_ancillas, system_qubits)
All(Measure) | qpe_ancillas
# Compute the phase from the ancilla measurement
#(https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm)
phasebinlist = [int(q) for q in qpe_ancillas]
phase_in_bin = ''.join(str(j) for j in phasebinlist)
phase_int = int(phase_in_bin,2)
phase = phase_int / (2 ** n_qpe_ancillas)
print (phase)
# Example using a function (two_qubit_gate).
# Instead of applying QPE on a gate U one could provide a function
def two_qubit_gate(system_q, time):
CNOT | (system_q[0], system_q[1])
Ph(2.0*cmath.pi*(time * 0.125)) | system_q[1]
CNOT | (system_q[0], system_q[1])
n_qpe_ancillas = 3
qpe_ancillas = eng.allocate_qureg(n_qpe_ancillas)
system_qubits = eng.allocate_qureg(2)
X | system_qubits[0]
# Apply Quantum Phase Estimation
QPE(two_qubit_gate) | (qpe_ancillas, system_qubits)
All(Measure) | qpe_ancillas
# Compute the phase from the ancilla measurement
#(https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm)
phasebinlist = [int(q) for q in qpe_ancillas]
phase_in_bin = ''.join(str(j) for j in phasebinlist)
phase_int = int(phase_in_bin,2)
phase = phase_int / (2 ** n_qpe_ancillas)
print (phase)
Attributes:
unitary (BasicGate): Unitary Operation either a ProjectQ gate or a function f.
Calling the function with the parameters system_qubits(Qureg) and time (integer),
i.e. f(system_qubits, time), applies to the system qubits a unitary defined in f
with parameter time.
"""

import numpy as np

from projectq.cengines import DecompositionRule
from projectq.meta import Control, Loop, get_control_count
from projectq.ops import H, Tensor, get_inverse, QFT

from projectq.ops import QPE


def _decompose_QPE(cmd):
""" Decompose the Quantum Phase Estimation gate. """
eng = cmd.engine

# Ancillas is the first qubit/qureg. System-qubit is the second qubit/qureg
qpe_ancillas = cmd.qubits[0]
system_qubits = cmd.qubits[1]

# Hadamard on the ancillas
Tensor(H) | qpe_ancillas

# The Unitary Operator
U = cmd.gate.unitary

# Control U on the system_qubits
if (callable(U)):
# If U is a function
for i in range(len(qpe_ancillas)):
with Control(eng, qpe_ancillas[i]):
U(system_qubits, time=2**i)
else:
for i in range(len(qpe_ancillas)):
ipower = int(2**i)
with Loop(eng, ipower):
with Control(eng, qpe_ancillas[i]):
U | system_qubits

# Inverse QFT on the ancillas
get_inverse(QFT) | qpe_ancillas

#: Decomposition rules
all_defined_decomposition_rules = [
DecompositionRule(QPE, _decompose_QPE)
]

0 comments on commit 3ac3c2c

Please sign in to comment.