Skip to content

Commit b05ee16

Browse files
committed
Move apply_gate to its own file
1 parent 4c7dd33 commit b05ee16

File tree

3 files changed

+144
-24
lines changed

3 files changed

+144
-24
lines changed

projectq/libs/qasm/_parse_qasm_qiskit.py

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,34 +18,11 @@
1818
from qiskit.circuit import QuantumCircuit, ClassicalRegister, Clbit
1919

2020
from ._qiskit_conv import gates_conv_table
21+
from ._utils import apply_gate, OpaqueGate
2122

2223
# ==============================================================================
2324

2425

25-
def apply_gate(gate, qubits):
26-
"""
27-
Apply a gate to some qubits while separating control and target qubits.
28-
29-
30-
Args:
31-
gate (BasicGate): Instance of a ProjectQ gate
32-
qubits (list): List of ProjectQ qubits the gate applies to.
33-
"""
34-
if isinstance(gate, ControlledGate):
35-
ctrls = qubits[:gate._n]
36-
qubits = qubits[gate._n:]
37-
if isinstance(gate._gate, SwapGate):
38-
assert len(qubits) == 2
39-
gate | (ctrls, qubits[0], qubits[1])
40-
else:
41-
gate | (ctrls, qubits)
42-
elif isinstance(gate, SwapGate):
43-
assert len(qubits) == 2
44-
gate | (qubits[0], qubits[1])
45-
else:
46-
gate | qubits
47-
48-
4926
def apply_op(eng, gate, qubits, bits, bits_map):
5027
"""
5128
Apply a qiskit operation.
@@ -73,6 +50,7 @@ def apply_op(eng, gate, qubits, bits, bits_map):
7350
else:
7451
if gate.name not in gates_conv_table:
7552
if not gate._definition:
53+
# TODO: This will silently discard opaque gates...
7654
return
7755

7856
gate_args = {gate._definition.qregs[0].name: qubits}

projectq/libs/qasm/_utils.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Copyright 2020 ProjectQ-Framework (www.projectq.ch)
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""Some helper utilities."""
15+
16+
from projectq.ops import ControlledGate, SwapGate, BasicGate
17+
18+
# ==============================================================================
19+
20+
21+
class OpaqueGate(BasicGate):
22+
def __init__(self, name, params):
23+
"""
24+
Constructor
25+
26+
Args:
27+
name (str): Name/type of gat
28+
params (list,tuple): Parameter for the gate (may be empty)
29+
"""
30+
31+
super().__init__()
32+
self.name = name
33+
self.params = params
34+
35+
def __str__(self):
36+
"""
37+
String conversion.
38+
"""
39+
# TODO: This is a bit crude...
40+
if self.params:
41+
return 'Opaque({})({})'.format(self.name, ','.join(self.params))
42+
return 'Opaque({})'.format(self.name)
43+
44+
45+
# ==============================================================================
46+
47+
48+
def apply_gate(gate, qubits):
49+
"""
50+
Apply a gate to some qubits while separating control and target qubits.
51+
52+
53+
Args:
54+
gate (BasicGate): Instance of a ProjectQ gate
55+
qubits (list): List of ProjectQ qubits the gate applies to.
56+
"""
57+
# pylint: disable = protected-access,pointless-statement
58+
59+
if isinstance(gate, ControlledGate):
60+
ctrls = qubits[:gate._n]
61+
qubits = qubits[gate._n:]
62+
if isinstance(gate._gate, SwapGate):
63+
assert len(qubits) == 2
64+
gate | (ctrls, qubits[0], qubits[1])
65+
else:
66+
gate | (ctrls, qubits)
67+
elif isinstance(gate, SwapGate):
68+
assert len(qubits) == 2
69+
gate | (qubits[0], qubits[1])
70+
else:
71+
gate | qubits
72+
73+
74+
# ==============================================================================

projectq/libs/qasm/_utils_test.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Copyright 2020 ProjectQ-Framework (www.projectq.ch)
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""Tests for projectq.libs.qasm._utils.py."""
15+
16+
import pytest
17+
18+
from projectq.types import WeakQubitRef
19+
from projectq.cengines import DummyEngine
20+
from projectq.ops import (X, Y, Z, T, Tdagger, S, Sdagger, H, Ph, R, Rx, Ry, Rz,
21+
U2, U3, Swap, Toffoli, Barrier, C)
22+
from ._utils import apply_gate, OpaqueGate
23+
24+
# ==============================================================================
25+
26+
27+
def test_opaque_gate():
28+
gate = OpaqueGate('my_gate', None)
29+
assert gate.name == 'my_gate'
30+
assert not gate.params
31+
assert str(gate) == 'Opaque(my_gate)'
32+
33+
gate = OpaqueGate('my_gate', ('lambda', 'alpha'))
34+
assert gate.name == 'my_gate'
35+
assert gate.params == ('lambda', 'alpha')
36+
37+
assert str(gate) == 'Opaque(my_gate)(lambda,alpha)'
38+
39+
40+
# ==============================================================================
41+
42+
43+
@pytest.mark.parametrize(
44+
'gate, n_qubits', (list(
45+
map(lambda x:
46+
(x, 1), [
47+
X, Y, Z, S, Sdagger, T, Tdagger, H, Barrier,
48+
Ph(1.12),
49+
Rx(1.12),
50+
Ry(1.12),
51+
Rz(1.12),
52+
R(1.12),
53+
U2(1.12, 1.12),
54+
U3(1.12, 1.12, 1.12),
55+
])) + list(map(lambda x:
56+
(x, 2), [C(X), C(Y), C(Z), Swap, Barrier])) +
57+
list(map(lambda x:
58+
(x, 3), [Toffoli, C(Swap), Barrier])) +
59+
list(map(lambda x: (x, 10), [Barrier]))),
60+
ids=str)
61+
def test_apply_gate(gate, n_qubits):
62+
backend = DummyEngine()
63+
backend.is_last_engine = True
64+
65+
gate.engine = backend
66+
qubits = [WeakQubitRef(backend, idx) for idx in range(n_qubits)]
67+
68+
apply_gate(gate, qubits)

0 commit comments

Comments
 (0)