Skip to content

Commit

Permalink
Merge 01faf3d into eb3d72e
Browse files Browse the repository at this point in the history
  • Loading branch information
damiansteiger committed Jul 18, 2018
2 parents eb3d72e + 01faf3d commit 7c756dd
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 5 deletions.
1 change: 1 addition & 0 deletions docs/projectq.ops.rst
Expand Up @@ -46,6 +46,7 @@ The operations collection consists of various default gates and is a work-in-pro
projectq.ops.QubitOperator
projectq.ops.CRz
projectq.ops.CNOT
projectq.ops.CZ
projectq.ops.Toffoli
projectq.ops.TimeEvolution

Expand Down
2 changes: 1 addition & 1 deletion projectq/cengines/_twodmapper_test.py
Expand Up @@ -90,7 +90,7 @@ def test_return_swaps_random(num_rows, num_columns, seed, none_old, none_new):
new_mapping.pop(logical_id)

mapper = two_d.GridMapper(num_rows=num_rows,
num_columns=num_columns)
num_columns=num_columns)
swaps = mapper.return_swaps(old_mapping, new_mapping)
# Check that Swaps are allowed
all_allowed_swaps = set()
Expand Down
5 changes: 4 additions & 1 deletion projectq/ops/_shortcuts.py
Expand Up @@ -20,7 +20,7 @@
"""

from ._metagates import C
from ._gates import Rz, NOT
from ._gates import NOT, Rz, Z


def CRz(angle):
Expand All @@ -33,4 +33,7 @@ def CRz(angle):
CNOT = CX = C(NOT)


CZ = C(Z)


Toffoli = C(CNOT)
2 changes: 2 additions & 0 deletions projectq/setups/decompositions/__init__.py
Expand Up @@ -16,6 +16,7 @@
barrier,
carb1qubit2cnotrzandry,
crz2cxandrz,
cnot2cz,
cnu2toffoliandcu,
entangle,
globalphase,
Expand All @@ -34,6 +35,7 @@
barrier,
carb1qubit2cnotrzandry,
crz2cxandrz,
cnot2cz,
cnu2toffoliandcu,
entangle,
globalphase,
Expand Down
41 changes: 41 additions & 0 deletions projectq/setups/decompositions/cnot2cz.py
@@ -0,0 +1,41 @@
# 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 to for a CNOT gate in terms of CZ and Hadamard.
"""

from projectq.cengines import DecompositionRule
from projectq.meta import Compute, get_control_count, Uncompute
from projectq.ops import CZ, H, X


def _decompose_cnot(cmd):
""" Decompose CNOT gates. """
ctrl = cmd.control_qubits
eng = cmd.engine
with Compute(eng):
H | cmd.qubits[0]
CZ | (ctrl[0], cmd.qubits[0][0])
Uncompute(eng)


def _recognize_cnot(cmd):
return get_control_count(cmd) == 1


#: Decomposition rules
all_defined_decomposition_rules = [
DecompositionRule(X.__class__, _decompose_cnot, _recognize_cnot)
]
104 changes: 104 additions & 0 deletions projectq/setups/decompositions/cnot2cz_test.py
@@ -0,0 +1,104 @@
# 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.

"Tests for projectq.setups.decompositions.cnot2cz.py."

import pytest

import projectq
from projectq import MainEngine
from projectq.backends import Simulator
from projectq.cengines import (AutoReplacer, DecompositionRuleSet, DummyEngine,
InstructionFilter)
from projectq.meta import Control
from projectq.ops import All, CNOT, CZ, Measure, X, Z

from projectq.setups.decompositions import cnot2cz


def test_recognize_gates():
saving_backend = DummyEngine(save_commands=True)
eng = MainEngine(backend=saving_backend, verbose=True)
qubit1 = eng.allocate_qubit()
qubit2 = eng.allocate_qubit()
qubit3 = eng.allocate_qubit()
eng.flush()
CZ | (qubit1, qubit2)
with Control(eng, qubit2):
Z | qubit1
X | qubit1
with Control(eng, qubit2 + qubit3):
Z | qubit1
eng.flush() # To make sure gates arrive before deallocate gates
eng.flush(deallocate_qubits=True)
# Don't test initial 4 allocate and flush
for cmd in saving_backend.received_commands[5:7]:
assert cnot2cz._recognize_cnot(cmd)
for cmd in saving_backend.received_commands[7:9]:
assert not cnot2cz._recognize_cnot(cmd)


def _decomp_gates(eng, cmd):
g = cmd.gate
if len(cmd.control_qubits) == 1 and isinstance(cmd.gate, X.__class__):
return False
return True


def test_cnot_decomposition():
for basis_state_index in range(0, 4):
basis_state = [0] * 4
basis_state[basis_state_index] = 1.
correct_dummy_eng = DummyEngine(save_commands=True)
correct_eng = MainEngine(backend=Simulator(),
engine_list=[correct_dummy_eng])
rule_set = DecompositionRuleSet(modules=[cnot2cz])
test_dummy_eng = DummyEngine(save_commands=True)
test_eng = MainEngine(backend=Simulator(),
engine_list=[AutoReplacer(rule_set),
InstructionFilter(_decomp_gates),
test_dummy_eng])
test_sim = test_eng.backend
correct_sim = correct_eng.backend
correct_qb = correct_eng.allocate_qubit()
correct_ctrl_qb = correct_eng.allocate_qubit()
correct_eng.flush()
test_qb = test_eng.allocate_qubit()
test_ctrl_qb = test_eng.allocate_qubit()
test_eng.flush()

correct_sim.set_wavefunction(basis_state, correct_qb +
correct_ctrl_qb)
test_sim.set_wavefunction(basis_state, test_qb + test_ctrl_qb)
CNOT | (test_ctrl_qb, test_qb)
CNOT | (correct_ctrl_qb, correct_qb)

test_eng.flush()
correct_eng.flush()

assert len(correct_dummy_eng.received_commands) == 5
assert len(test_dummy_eng.received_commands) == 7

for fstate in range(4):
binary_state = format(fstate, '02b')
test = test_sim.get_amplitude(binary_state,
test_qb + test_ctrl_qb)
correct = correct_sim.get_amplitude(binary_state, correct_qb +
correct_ctrl_qb)
assert correct == pytest.approx(test, rel=1e-12, abs=1e-12)

All(Measure) | test_qb + test_ctrl_qb
All(Measure) | correct_qb + correct_ctrl_qb
test_eng.flush(deallocate_qubits=True)
correct_eng.flush(deallocate_qubits=True)
2 changes: 1 addition & 1 deletion projectq/setups/grid.py
Expand Up @@ -71,7 +71,7 @@ def get_engine_list(num_rows, num_columns, one_qubit_gates="any",
to double check and potentially extend the decomposition rules.
This implemention currently requires that the one qubit gates must
contain Rz and at least one of {Ry(best), Rx, H} and the two qubit gate
must contain CNOT.
must contain CNOT (recommended) or CZ.
Note:
Classical instructions gates such as e.g. Flush and Measure are
Expand Down
2 changes: 1 addition & 1 deletion projectq/setups/linear.py
Expand Up @@ -71,7 +71,7 @@ def get_engine_list(num_qubits, cyclic=False, one_qubit_gates="any",
to double check and potentially extend the decomposition rules.
This implemention currently requires that the one qubit gates must
contain Rz and at least one of {Ry(best), Rx, H} and the two qubit gate
must contain CNOT.
must contain CNOT (recommended) or CZ.
Note:
Classical instructions gates such as e.g. Flush and Measure are
Expand Down
2 changes: 1 addition & 1 deletion projectq/setups/restrictedgateset.py
Expand Up @@ -74,7 +74,7 @@ def get_engine_list(one_qubit_gates="any",
to double check and potentially extend the decomposition rules.
This implemention currently requires that the one qubit gates must
contain Rz and at least one of {Ry(best), Rx, H} and the two qubit gate
must contain CNOT.
must contain CNOT (recommended) or CZ.
Note:
Classical instructions gates such as e.g. Flush and Measure are
Expand Down

0 comments on commit 7c756dd

Please sign in to comment.