Skip to content

Commit

Permalink
fix: update compiler/rules to use circuit.wire_names
Browse files Browse the repository at this point in the history
  • Loading branch information
changsookim committed Oct 28, 2024
1 parent 801dced commit 17a7780
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 34 deletions.
15 changes: 8 additions & 7 deletions src/qibolab/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,9 @@ def execute_circuit(self, circuit, initial_state=None, nshots=1000):
"Hardware backend only supports circuits as initial states.",
)

# This should be done in qibo side
# Temporary fix: overwrite the wire names
if not all(q in circuit.wire_names for q in self.platform.qubits):
# This should be done in qibo side
# raise_error(
# ValueError,
# "Circuit qubits do not match the platform qubits.",
# )

# Temporary fix: overwrite the wire names
circuit._wire_names = self.qubits

self.platform.wire_names = circuit.wire_names
Expand Down Expand Up @@ -179,6 +174,12 @@ def execute_circuits(self, circuits, initial_states=None, nshots=1000):
"Hardware backend only supports circuits as initial states.",
)

# This should be done in qibo side
# Temporary fix: overwrite the wire names
for circuit in circuits:
if not all(q in circuit.wire_names for q in self.platform.qubits):
circuit._wire_names = self.qubits

# TODO: Maybe these loops can be parallelized
sequences, measurement_maps = zip(
*(self.compiler.compile(circuit, self.platform) for circuit in circuits)
Expand Down
24 changes: 21 additions & 3 deletions src/qibolab/compilers/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,24 @@ def inner(func):
return inner

def _compile_gate(
self, gate, platform, sequence, virtual_z_phases, moment_start, delays
self,
gate,
platform,
sequence,
virtual_z_phases,
moment_start,
delays,
wire_names,
):
"""Adds a single gate to the pulse sequence."""
rule = self[gate.__class__]

# get local sequence and phases for the current gate
gate_sequence, gate_phases = rule(gate, platform)
qubits_ids = (
[wire_names[qubit] for qubit in gate.control_qubits],
[wire_names[qubit] for qubit in gate.target_qubits],
)
gate_sequence, gate_phases = rule(qubits_ids, platform, gate.parameters)

# update global pulse sequence
# determine the right start time based on the availability of the qubits involved
Expand Down Expand Up @@ -154,7 +166,13 @@ def compile(self, circuit, platform):
delays[qubit] += gate.delay
continue
gate_sequence, gate_phases = self._compile_gate(
gate, platform, sequence, virtual_z_phases, moment_start, delays
gate,
platform,
sequence,
virtual_z_phases,
moment_start,
delays,
circuit.wire_names,
)
for qubit in gate.qubits:
delays[qubit] = 0
Expand Down
46 changes: 22 additions & 24 deletions src/qibolab/compilers/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,48 @@
from qibolab.pulses import PulseSequence


def identity_rule(gate, platform):
def identity_rule(qubits_ids, platform, parameters=None):
"""Identity gate skipped."""
return PulseSequence(), {}


def z_rule(gate, platform):
def z_rule(qubits_ids, platform, parameters=None):
"""Z gate applied virtually."""
qubit = platform.get_qubit(gate.target_qubits[0])
return PulseSequence(), {qubit: math.pi}
return PulseSequence(), {qubits_ids[1][0]: math.pi}


def rz_rule(gate, platform):
def rz_rule(qubits_ids, platform, parameters=None):
"""RZ gate applied virtually."""
qubit = platform.get_qubit(gate.target_qubits[0])
return PulseSequence(), {qubit: -gate.parameters[0]}
return PulseSequence(), {qubits_ids[1][0]: -parameters[0]}


def gpi2_rule(gate, platform):
def gpi2_rule(qubits_ids, platform, parameters=None):
"""Rule for GPI2."""
qubit = platform.get_qubit(gate.target_qubits[0])
theta = gate.parameters[0]
theta = parameters[0]
sequence = PulseSequence()
pulse = platform.create_RX90_pulse(qubit, start=0, relative_phase=theta)
pulse = platform.create_RX90_pulse(qubits_ids[1][0], start=0, relative_phase=theta)
sequence.add(pulse)
return sequence, {}


def gpi_rule(gate, platform):
def gpi_rule(qubits_ids, platform, parameters=None):
"""Rule for GPI."""
qubit = platform.get_qubit(gate.target_qubits[0])
theta = gate.parameters[0]
theta = parameters[0]
sequence = PulseSequence()
# the following definition has a global phase difference compare to
# to the matrix representation. See
# https://github.com/qiboteam/qibolab/pull/804#pullrequestreview-1890205509
# for more detail.
pulse = platform.create_RX_pulse(qubit, start=0, relative_phase=theta)
pulse = platform.create_RX_pulse(qubits_ids[1][0], start=0, relative_phase=theta)
sequence.add(pulse)
return sequence, {}


def u3_rule(gate, platform):
def u3_rule(qubits_ids, platform, parameters=None):
"""U3 applied as RZ-RX90-RZ-RX90-RZ."""
qubit = platform.get_qubit(gate.target_qubits[0])
qubit = qubits_ids[1][0]
# Transform gate to U3 and add pi/2-pulses
theta, phi, lam = gate.parameters
theta, phi, lam = parameters
# apply RZ(lam)
virtual_z_phases = {qubit: lam}
sequence = PulseSequence()
Expand All @@ -79,24 +75,26 @@ def u3_rule(gate, platform):
return sequence, virtual_z_phases


def cz_rule(gate, platform):
def cz_rule(qubits_ids, platform, parameters=None):
"""CZ applied as defined in the platform runcard.
Applying the CZ gate may involve sending pulses on qubits that the
gate is not directly acting on.
"""
return platform.create_CZ_pulse_sequence(gate.qubits)
qubits = qubits_ids[0] + qubits_ids[1]
return platform.create_CZ_pulse_sequence(qubits)


def cnot_rule(gate, platform):
def cnot_rule(qubits_ids, platform, parameters=None):
"""CNOT applied as defined in the platform runcard."""
return platform.create_CNOT_pulse_sequence(gate.qubits)
qubits = qubits_ids[0] + qubits_ids[1]
return platform.create_CNOT_pulse_sequence(qubits)


def measurement_rule(gate, platform):
def measurement_rule(qubits_ids, platform, parameters=None):
"""Measurement gate applied using the platform readout pulse."""
sequence = PulseSequence()
for qubit in gate.target_qubits:
for qubit in qubits_ids[1]:
MZ_pulse = platform.create_MZ_pulse(qubit, start=0)
sequence.add(MZ_pulse)
return sequence, {}
2 changes: 2 additions & 0 deletions tests/test_compilers_default.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ def test_u3_sim_agreement():
def compile_circuit(circuit, platform):
"""Compile a circuit to a pulse sequence."""
compiler = Compiler.default()
# Temporary fix: overwrite the wire names
circuit._wire_names = list(platform.qubits)
sequence, _ = compiler.compile(circuit, platform)
return sequence

Expand Down

0 comments on commit 17a7780

Please sign in to comment.