diff --git a/src/qibo/models/_openqasm.py b/src/qibo/models/_openqasm.py index 5b03470cd3..0ebd1c7acb 100644 --- a/src/qibo/models/_openqasm.py +++ b/src/qibo/models/_openqasm.py @@ -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): @@ -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.""" diff --git a/src/qibo/models/circuit.py b/src/qibo/models/circuit.py index db7e0ea880..67ec3a670b 100644 --- a/src/qibo/models/circuit.py +++ b/src/qibo/models/circuit.py @@ -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 @@ -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: @@ -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) diff --git a/tests/test_models_circuit_qasm.py b/tests/test_models_circuit_qasm.py index 5170b3bd01..39c4e4c44f 100644 --- a/tests/test_models_circuit_qasm.py +++ b/tests/test_models_circuit_qasm.py @@ -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";