Skip to content

Commit

Permalink
Merge pull request #1284 from qiboteam/to_qasm_fix
Browse files Browse the repository at this point in the history
Fix to classical registers in to_qasm
  • Loading branch information
scarrazza committed Apr 5, 2024
2 parents d6209f4 + 78c8056 commit 9c0eb21
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 26 deletions.
30 changes: 22 additions & 8 deletions src/qibo/models/_openqasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,7 @@ def to_circuit(
density_matrix,
wire_names=self._construct_wire_names(),
)
for gate in gates:
circ.add(gate)
self._reorder_registers(circ.measurements)
circ.add(self._merge_measurements(gates))
return circ

def _get_measurement(self, measurement):
Expand Down Expand Up @@ -267,11 +265,27 @@ def _def_gate(self, definition):
gates = [self._get_gate(gate) for gate in definition.body]
self.defined_gates.update({name: CustomQASMGate(name, gates, qubits, args)})

def _reorder_registers(self, measurements):
"""Reorders the registers of the provided :class:`qibo.gates.measurements.M`
gates according to the classical registers order defined in the QASM program."""
for meas in measurements:
meas.target_qubits = [self.c_registers[meas.register_name].pop(0)]
def _merge_measurements(self, gates):
"""Merges separated measurements of a same register into a single one.
This is needed because qibo doesn't allow to separetely define two measurements in a same register:
# not allowed
c.add(gates.M(0, register="m0"))
c.add(gates.M(1, register="m0"))
"""
updated_queue = []
for gate in gates:
if isinstance(gate, qibo.gates.M):
if gate.register_name in self.c_registers:
updated_queue.append(
qibo.gates.M(
*self.c_registers.pop(gate.register_name),
register_name=gate.register_name,
)
)
else:
updated_queue.append(gate)
return updated_queue

def _construct_wire_names(self):
"""Builds the wires names from the declared quantum registers."""
Expand Down
27 changes: 11 additions & 16 deletions src/qibo/models/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -667,13 +667,11 @@ def add(self, gate):
nreg = self.queue.nmeasurements - 1
gate.register_name = f"register{nreg}"
else:
registers = self.measurement_tuples
for register, qubits in registers.items():
intersection = set(qubits).intersection(set(gate.target_qubits))
if len(intersection) > 0:
name = gate.register_name
for mgate in self.measurements:
if name == mgate.register_name:
raise_error(
KeyError,
f"Qubits {tuple(intersection)} already measured in register `{register}`.",
KeyError, f"Register {name} already exists in circuit."
)

gate.result.circuit = self
Expand Down Expand Up @@ -1156,16 +1154,14 @@ def to_qasm(self):
code += [f"qreg q[{self.nqubits}];"]

# Set measurements
for measurement in self.measurements:
reg_name = measurement.register_name
reg_qubits = measurement.target_qubits
if not reg_name.islower():
for register, qubits in self.measurement_tuples.items():
if not register.islower():
raise_error(
NameError,
"OpenQASM does not support capital letters in "
+ f"register names but {reg_name} was used",
+ f"register names but {register} was used",
)
code.append(f"creg {reg_name}[{len(reg_qubits)}];")
code.append(f"creg {register}[{len(qubits)}];")

# Add gates
for gate in self.queue:
Expand All @@ -1186,10 +1182,9 @@ def to_qasm(self):
code.append(f"{name} {qubits};")

# Add measurements
for measurement in self.measurements:
reg_name = measurement.register_name
for i, q in enumerate(measurement.target_qubits):
code.append(f"measure q[{q}] -> {reg_name}[{i}];")
for register, qubits in self.measurement_tuples.items():
for i, q in enumerate(qubits):
code.append(f"measure q[{q}] -> {register}[{i}];")

return "\n".join(code)

Expand Down
11 changes: 9 additions & 2 deletions tests/test_models_circuit_qasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,18 @@ def test_crotations():
target = c.to_qasm()


def test_measurements():
@pytest.mark.parametrize(
"measurements",
[
[gates.M(0, 1)],
],
)
def test_measurements(measurements):
c = Circuit(2)
c.add(gates.X(0))
c.add(gates.Y(1))
c.add(gates.M(0, 1))
for m in measurements:
c.add(m)
target = f"""// Generated by QIBO {__version__}
OPENQASM 2.0;
include "qelib1.inc";
Expand Down

0 comments on commit 9c0eb21

Please sign in to comment.