Skip to content

Commit 5e506c4

Browse files
committed
Fix some issues with measurements and conditional expressions
- Classical register now are initialised to 0 - Fixed bug with measurements of registers with size > 1 - Fixed issue with conditional expressions and registers with size > 1
1 parent b75dfa7 commit 5e506c4

File tree

2 files changed

+75
-8
lines changed

2 files changed

+75
-8
lines changed

projectq/libs/qasm/_parse_qasm_qiskit.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
from projectq.ops import All, Measure, ControlledGate, SwapGate
1717

18-
from qiskit.circuit import QuantumCircuit
18+
from qiskit.circuit import QuantumCircuit, ClassicalRegister, Clbit
1919

2020
from ._qiskit_conv import gates_conv_table
2121

@@ -68,7 +68,8 @@ def apply_op(eng, gate, qubits, bits, bits_map):
6868
eng.flush()
6969

7070
for idx, bit in enumerate(bits):
71-
bits_map[bit.register.name][idx] = bool(qubits[idx])
71+
assert isinstance(bit, Clbit)
72+
bits_map[bit.register.name][bit.index] = bool(qubits[idx])
7273
else:
7374
if gate.name not in gates_conv_table:
7475
if not gate._definition:
@@ -93,9 +94,14 @@ def apply_op(eng, gate, qubits, bits, bits_map):
9394
# OpenQASM 2.0
9495
cbit, value = gate.condition
9596

96-
# Note: apparently, it is illegal to write if (c0[0] == 1)
97-
# so we always assume that index == 0...
98-
if bits_map[cbit.name][0] == value:
97+
if cbit.size == 1:
98+
cbit_value = bits_map[cbit.name][0]
99+
else:
100+
cbit_value = 0
101+
for bit in bits_map[cbit.name]:
102+
cbit_value = (cbit_value << 1) | bit
103+
104+
if cbit_value == value:
99105
apply_gate(gate_projectq, qubits)
100106
else:
101107
apply_gate(gate_projectq, qubits)
@@ -120,7 +126,7 @@ def _convert_qiskit_circuit(eng, qc):
120126
qureg.name: eng.allocate_qureg(qureg.size)
121127
for qureg in qc.qregs
122128
}
123-
bits_map = {bit.name: [None] * bit.size for bit in qc.cregs}
129+
bits_map = {bit.name: [False] * bit.size for bit in qc.cregs}
124130

125131
# Convert all the gates to ProjectQ commands
126132
for gate, quregs, bits in qc.data:
@@ -131,6 +137,7 @@ def _convert_qiskit_circuit(eng, qc):
131137

132138
return qubits_map, bits_map
133139

140+
134141
def read_qasm_str(eng, qasm_str):
135142
"""
136143
Read an OpenQASM (2.0, 3.0 is experimental) string and convert it to

projectq/libs/qasm/_parse_qasm_qiskit_test.py

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ def test_read_qasm2_allocation(eng):
144144

145145
engine = deepcopy(eng)
146146
qubits_map, bits_map = read_qasm_str(engine, qasm_str)
147-
assert bits_map == {'c': [None], 'd': [None, None]}
147+
assert bits_map == {'c': [False], 'd': [False, False]}
148148
assert len(engine.backend.received_commands) == 3
149149
assert all(cmd.gate == Allocate for cmd in engine.backend.received_commands)
150150

@@ -321,6 +321,7 @@ def test_read_qasm2_gate_def(eng):
321321
assert cmd.gate == Rz(0.5)
322322
assert [qubit for qureg in cmd.qubits for qubit in qureg] == [b]
323323

324+
324325
def test_read_qasm2_file(eng):
325326
qasm_str = """
326327
OPENQASM 2.0;
@@ -334,12 +335,71 @@ def test_read_qasm2_file(eng):
334335
fd.seek(0)
335336
engine = deepcopy(eng)
336337
qubits_map, bits_map = read_qasm_file(engine, fd.name)
337-
assert bits_map == {'c0': [None]}
338+
assert bits_map == {'c0': [False]}
338339
assert len(engine.backend.received_commands) == 2
339340
assert engine.backend.received_commands[0].gate == Allocate
340341
assert engine.backend.received_commands[1].gate == Allocate
341342

342343

344+
def test_qasm_qft2(eng):
345+
qasm_str = """
346+
OPENQASM 2.0;
347+
include "qelib1.inc";
348+
qreg a[2];
349+
creg b[2];
350+
measure a -> b;
351+
qreg q[3];
352+
creg c[3];
353+
// optional post-rotation for state tomography
354+
gate post q { }
355+
u3(0.3,0.2,0.1) q[0];
356+
h q[1];
357+
cx q[1],q[2];
358+
barrier q;
359+
cx q[0],q[1];
360+
h q[0];
361+
measure q[0] -> c[0];
362+
measure q[1] -> c[1];
363+
if(c==1) z q[2];
364+
if(c==2) x q[2];
365+
if(c==3) y q[2];
366+
if(c==4) z q[1];
367+
if(c==5) x q[1];
368+
if(c==6) y q[1];
369+
if(c==7) z q[0];
370+
if(c==8) x q[0];
371+
post q[2];
372+
measure q[2] -> c[2];
373+
"""
374+
375+
qubits_map, bits_map = read_qasm_str(eng, qasm_str)
376+
assert {'q', 'a'} == set(qubits_map)
377+
assert len(qubits_map['a']) == 2
378+
assert len(qubits_map['q']) == 3
379+
assert bits_map == {'b': [True, True], 'c': [True, True, True]}
380+
381+
assert len([
382+
cmd for cmd in eng.backend.received_commands if cmd.gate == Allocate
383+
]) == 5
384+
assert len([
385+
cmd for cmd in eng.backend.received_commands
386+
if isinstance(cmd.gate, U3)
387+
]) == 1
388+
assert len([cmd for cmd in eng.backend.received_commands
389+
if cmd.gate == X]) == 2
390+
cmds = [cmd for cmd in eng.backend.received_commands if cmd.gate == Y]
391+
assert len(cmds) == 1
392+
assert ([qubits_map['q'][1]
393+
] == [qubit for qureg in cmds[0].qubits for qubit in qureg])
394+
assert len([cmd for cmd in eng.backend.received_commands
395+
if cmd.gate == Z]) == 0
396+
assert len([cmd for cmd in eng.backend.received_commands
397+
if cmd.gate == H]) == 2
398+
cmds = [cmd for cmd in eng.backend.received_commands if cmd.gate == Barrier]
399+
assert len(cmds) == 1
400+
assert len([qubit for qureg in cmds[0].qubits for qubit in qureg]) == 3
401+
402+
343403
# ==============================================================================
344404
# OpenQASM 3.0 tests (experimental)
345405

0 commit comments

Comments
 (0)