Skip to content

Commit

Permalink
Fixes the controlled gate shortcut. (#53)
Browse files Browse the repository at this point in the history
* Added test for controlled gate which fails without this fix.

* Fixed a few pep8 issues.
  • Loading branch information
thomashaener authored and damiansteiger committed Apr 18, 2017
1 parent 7c1f33e commit bd8ef09
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 11 deletions.
1 change: 0 additions & 1 deletion projectq/cengines/_replacer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,3 @@
from ._replacer import (AutoReplacer,
InstructionFilter,
NoGateDecompositionError)

18 changes: 14 additions & 4 deletions projectq/cengines/_replacer/_replacer_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
import pytest

from projectq import MainEngine
from projectq.cengines import DummyEngine, DecompositionRuleSet, DecompositionRule
from projectq.cengines import (DummyEngine,
DecompositionRuleSet,
DecompositionRule)
from projectq.ops import H, X, Command, S, Rx, NotInvertible, Ry, BasicGate

from projectq.cengines._replacer import _replacer
Expand Down Expand Up @@ -59,14 +61,16 @@ def recognize_test(cmd):
return True

result.add_decomposition_rule(
DecompositionRule(TestGate.__class__, decompose_test1, recognize_test))
DecompositionRule(TestGate.__class__, decompose_test1,
recognize_test))

def decompose_test2(cmd):
qb = cmd.qubits
H | qb

result.add_decomposition_rule(
DecompositionRule(TestGate.__class__, decompose_test2, recognize_test))
DecompositionRule(TestGate.__class__, decompose_test2,
recognize_test))

assert len(result.decompositions[TestGate.__class__.__name__]) == 2
return result
Expand Down Expand Up @@ -141,22 +145,28 @@ def test_auto_replacer_use_inverse_decomposition():
# Create test gate and inverse
class NoMagicGate(BasicGate):
pass

class MagicGate(BasicGate):
def get_inverse(self):
return NoMagicGate()

def decompose_no_magic_gate(cmd):
qb = cmd.qubits
Rx(0.6) | qb
H | qb

def recognize_no_magic_gate(cmd):
return True

rule_set.add_decomposition_rule(DecompositionRule(NoMagicGate,
decompose_no_magic_gate,
recognize_no_magic_gate))

def magic_filter(self, cmd):
if cmd.gate == MagicGate():
return False
return True

backend = DummyEngine(save_commands=True)
eng = MainEngine(backend=backend,
engine_list=[_replacer.AutoReplacer(rule_set),
Expand All @@ -181,7 +191,7 @@ def test_auto_replacer_adds_tags(fixture_gate_filter):
assert len(rule_set.decompositions[TestGate.__class__.__name__]) == 2
assert len(backend.received_commands) == 0
qb = eng.allocate_qubit()
cmd = Command(eng, TestGate, (qb,) )
cmd = Command(eng, TestGate, (qb,))
cmd.tags = ["AddedTag"]
eng.send([cmd])
eng.flush()
Expand Down
3 changes: 2 additions & 1 deletion projectq/ops/_basics.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,8 @@ def get_math_function(self, qubits):
gate, given the input to the gate (a tuple of quantum registers).
Args:
qubits (tuple<Qureg>): Qubits to which the math gate is being applied.
qubits (tuple<Qureg>): Qubits to which the math gate is being
applied.
Returns:
math_fun (function): Python function describing the action of this
Expand Down
6 changes: 3 additions & 3 deletions projectq/ops/_metagates.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,9 @@ def __or__(self, qubits):
raise ControlQubitError("Wrong number of control qubits. "
"First qureg(s) need to contain exactly "
"the required number of control qubits.")
cmd = BasicGate.generate_command(self._gate, tuple(gate_quregs))
cmd.add_control_qubits(ctrl)
apply_command(cmd)
import projectq.meta
with projectq.meta.Control(gate_quregs[0][0].engine, ctrl):
self._gate | tuple(gate_quregs)

def __eq__(self, other):
""" Compare two ControlledGate objects (return True if equal). """
Expand Down
19 changes: 17 additions & 2 deletions projectq/ops/_metagates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,27 @@
from projectq import MainEngine
from projectq.cengines import DummyEngine
from projectq.ops import (T, Y, NotInvertible, Entangle, Rx,
FastForwardingGate, Command,
ClassicalInstructionGate)
FastForwardingGate, Command, C,
ClassicalInstructionGate, All)

from projectq.ops import _metagates


def test_tensored_controlled_gate():
saving_backend = DummyEngine(save_commands=True)
main_engine = MainEngine(backend=saving_backend,
engine_list=[DummyEngine()])
gate = Rx(0.6)
qubit0 = Qubit(main_engine, 0)
qubit1 = Qubit(main_engine, 1)
qubit2 = Qubit(main_engine, 2)
target_qubits = [qubit1, qubit2]
C(All(gate)) | (qubit0, target_qubits)

assert saving_backend.received_commands[-1].gate == gate
assert len(saving_backend.received_commands[-1].control_qubits) == 1


def test_daggered_gate_init():
# Choose gate which does not have an inverse gate:
not_invertible_gate = T
Expand Down

0 comments on commit bd8ef09

Please sign in to comment.