Skip to content

Commit

Permalink
Add quantitative regression tests for exact connectivity allocations.
Browse files Browse the repository at this point in the history
  • Loading branch information
deanpoulos committed Oct 11, 2024
1 parent 26e0068 commit d5afb07
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 46 deletions.
12 changes: 10 additions & 2 deletions tests/wirer/test_add_dummy_line.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from dataclasses import asdict

import pytest
from qualang_tools.wirer import Connectivity, allocate_wiring, visualize
from qualang_tools.wirer.connectivity.element import Element, Reference
Expand All @@ -22,7 +24,13 @@ def test_add_dummy_line(instruments_2lf_2mw):

allocate_wiring(connectivity, instruments_2lf_2mw)

print(connectivity.elements)

if pytest.visualize_flag:
visualize(connectivity.elements, instruments_2lf_2mw.available_channels)

# regression test
test_element = connectivity.elements[Reference('test')]
for i, channel in enumerate(test_element.channels['ch']):
assert asdict(channel) == asdict([
InstrumentChannelLfFemInput(con=1, port=1, slot=1),
InstrumentChannelLfFemOutput(con=1, port=6, slot=1)
][i])
28 changes: 26 additions & 2 deletions tests/wirer/test_wirer_channel_reuse.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
from dataclasses import asdict

import pytest

from qualang_tools.wirer import *
from qualang_tools.wirer.connectivity.element import QubitReference
from qualang_tools.wirer.connectivity.wiring_spec import WiringLineType
from qualang_tools.wirer.instruments.instrument_channel import InstrumentChannelMwFemInput, \
InstrumentChannelMwFemOutput, InstrumentChannelLfFemOutput

visualize_flag = pytest.visualize_flag

Expand All @@ -17,7 +23,25 @@ def test_5q_allocation_with_channel_reuse(instruments_2lf_2mw):

allocate_wiring(connectivity, instruments_2lf_2mw, block_used_channels=False)

print(connectivity.elements)

if visualize_flag:
visualize(connectivity.elements, instruments_2lf_2mw.available_channels)

for qubit in [1, 3]:
# resonator lines re-used for qubits 1 & 3
for i, channel in enumerate(connectivity.elements[QubitReference(index=qubit)].channels[WiringLineType.RESONATOR]):
assert asdict(channel) == asdict([
InstrumentChannelMwFemInput(con=1, port=1, slot=3),
InstrumentChannelMwFemOutput(con=1, port=1, slot=3)
][i])

# drive lines re-used for qubits 1 & 3
for i, channel in enumerate(connectivity.elements[QubitReference(index=qubit)].channels[WiringLineType.DRIVE]):
assert asdict(channel) == asdict([
InstrumentChannelMwFemOutput(con=1, port=2, slot=3)
][i])

# flux lines re-used for qubits 1 & 3
for i, channel in enumerate(connectivity.elements[QubitReference(index=qubit)].channels[WiringLineType.FLUX]):
assert asdict(channel) == asdict([
InstrumentChannelLfFemOutput(con=1, port=1, slot=1),
][i])
20 changes: 20 additions & 0 deletions tests/wirer/test_wirer_constraining.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
from dataclasses import asdict

import pytest

from qualang_tools.wirer import *
from qualang_tools.wirer.connectivity.element import QubitReference
from qualang_tools.wirer.connectivity.wiring_spec import WiringLineType
from qualang_tools.wirer.instruments.instrument_channel import InstrumentChannelOpxPlusInput, \
InstrumentChannelOpxPlusOutput, InstrumentChannelOpxPlusDigitalOutput, InstrumentChannelOctaveInput, \
InstrumentChannelOctaveDigitalInput, InstrumentChannelOctaveOutput

visualize_flag = pytest.visualize_flag

Expand All @@ -23,6 +30,19 @@ def test_opx_plus_resonator_constraining():
if visualize_flag:
visualize(connectivity.elements, instruments.available_channels)

# resonator lines should be hard-coded to I=9, Q=10, rf_out=1
for i, channel in enumerate(connectivity.elements[QubitReference(index=1)].channels[WiringLineType.RESONATOR]):
assert asdict(channel) == asdict([
InstrumentChannelOpxPlusInput(con=1, port=1, slot=None),
InstrumentChannelOpxPlusInput(con=1, port=2, slot=None),
InstrumentChannelOpxPlusOutput(con=1, port=9, slot=None),
InstrumentChannelOpxPlusOutput(con=1, port=10, slot=None),
InstrumentChannelOpxPlusDigitalOutput(con=1, port=1, slot=None),
InstrumentChannelOctaveInput(con=1, port=1, slot=None),
InstrumentChannelOctaveOutput(con=1, port=1, slot=None),
InstrumentChannelOctaveDigitalInput(con=1, port=1, slot=None)
][i])

def test_fix_attribute_equality():
"""
Make sure that channels aren't considered equal just because their attributes
Expand Down
14 changes: 12 additions & 2 deletions tests/wirer/test_wirer_digital.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from dataclasses import asdict

import pytest

from qualang_tools.wirer import *
from qualang_tools.wirer.connectivity.element import QubitReference
from qualang_tools.wirer.connectivity.wiring_spec import WiringLineType
from qualang_tools.wirer.instruments.instrument_channel import InstrumentChannelMwFemDigitalOutput

visualize_flag = pytest.visualize_flag

Expand All @@ -16,7 +21,12 @@ def test_triggered_wiring_spec_generates_digital_channels(instruments_2lf_2mw):

allocate_wiring(connectivity, instruments_2lf_2mw)

print(connectivity.elements)

if visualize_flag:
visualize(connectivity.elements, instruments_2lf_2mw.available_channels)

# assert digital trigger channel is present
for qubit in [1, 2]:
resonator_channels = connectivity.elements[QubitReference(index=qubit)].channels[WiringLineType.RESONATOR]
resonator_channels_as_dicts = [asdict(channel) for channel in resonator_channels]

assert asdict(InstrumentChannelMwFemDigitalOutput(con=1, port=1, slot=3)) in resonator_channels_as_dicts
66 changes: 44 additions & 22 deletions tests/wirer/test_wirer_lf_and_mw.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,56 @@
from dataclasses import asdict

import pytest

from qualang_tools.wirer import *
from qualang_tools.wirer.connectivity.element import QubitReference, QubitPairReference
from qualang_tools.wirer.connectivity.wiring_spec import WiringLineType
from qualang_tools.wirer.instruments.instrument_channel import InstrumentChannelLfFemOutput, \
InstrumentChannelMwFemOutput, InstrumentChannelMwFemInput

visualize_flag = pytest.visualize_flag

def test_5q_allocation(instruments_2lf_2mw):
qubits = [1, 2, 3, 4, 5]
qubit_pairs = [(1, 2), (2, 3), (3, 4), (4, 5)]
def test_6q_allocation(instruments_2lf_2mw):
qubits = [1, 2, 3, 4, 5, 6]
qubit_pairs = [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

connectivity = Connectivity()
connectivity.add_resonator_line(qubits=qubits, constraints=mw_fem_spec(slot=7))
connectivity.add_qubit_drive_lines(qubits=qubits, constraints=mw_fem_spec(slot=7))
connectivity.add_resonator_line(qubits=qubits)
connectivity.add_qubit_drive_lines(qubits=qubits)
connectivity.add_qubit_flux_lines(qubits=qubits)
connectivity.add_qubit_pair_flux_lines(qubit_pairs=qubit_pairs, constraints=lf_fem_spec(out_slot=2))

allocate_wiring(connectivity, instruments_2lf_2mw)

print(connectivity.elements)

if visualize_flag:
visualize(connectivity.elements, instruments_2lf_2mw.available_channels)

for qubit in qubits:
# flux channels should have some port as qubit index since they're allocated sequentially
flux_channels = connectivity.elements[QubitReference(qubit)].channels[WiringLineType.FLUX]
assert [asdict(ch) for ch in flux_channels] == [
asdict(InstrumentChannelLfFemOutput(con=1, port=qubit, slot=1))
]

# resonators all on same feedline, so should be first available input + outputs channels on MW-FEM
resonator_channels = connectivity.elements[QubitReference(qubit)].channels[WiringLineType.RESONATOR]
assert [asdict(ch) for ch in resonator_channels] == [
asdict(InstrumentChannelMwFemInput(con=1, port=1, slot=3)),
asdict(InstrumentChannelMwFemOutput(con=1, port=1, slot=3))
]

# drive channels are on MW-FEM
drive_channels = connectivity.elements[QubitReference(qubit)].channels[WiringLineType.DRIVE]
assert [asdict(ch) for ch in drive_channels] == [
asdict(InstrumentChannelMwFemOutput(con=1, port=qubit+1, slot=3))
]

for i, pair in enumerate(qubit_pairs):
# coupler channels should have some port as pair index since they're allocated sequentially, but on slot 2
coupler_channels = connectivity.elements[QubitPairReference(*pair)].channels[WiringLineType.COUPLER]
assert [asdict(ch) for ch in coupler_channels] == [
asdict(InstrumentChannelLfFemOutput(con=1, port=i+1, slot=2))
]

def test_4rr_allocation(instruments_2lf_2mw):
connectivity = Connectivity()
Expand All @@ -35,19 +65,11 @@ def test_4rr_allocation(instruments_2lf_2mw):
if visualize_flag:
visualize(connectivity.elements, instruments_2lf_2mw.available_channels)

# resonators all on different feedlines, so should fill all 4 inputs of 2x MW-FEM
for i, qubit in enumerate([1, 2, 3, 4]):
resonator_channels = connectivity.elements[QubitReference(qubit)].channels[WiringLineType.RESONATOR]
assert [asdict(ch) for ch in resonator_channels] == [
asdict(InstrumentChannelMwFemInput(con=1, port=[1, 2, 1, 2][i], slot=[3, 3, 7, 7][i])),
asdict(InstrumentChannelMwFemOutput(con=1, port=[1, 2, 1, 2][i], slot=[3, 3, 7, 7][i]))
]

def test_6rr_6xy_6flux_allocation():
instruments = Instruments()
instruments.add_lf_fem(controller=1, slots=1)
instruments.add_mw_fem(controller=1, slots=2)

qubits = [1, 2, 3, 4, 5, 6]
connectivity = Connectivity()
connectivity.add_resonator_line(qubits=qubits)
connectivity.add_qubit_drive_lines(qubits=qubits)
connectivity.add_qubit_flux_lines(qubits=qubits)

allocate_wiring(connectivity, instruments)

if visualize_flag:
visualize(connectivity.elements, instruments.available_channels)
54 changes: 43 additions & 11 deletions tests/wirer/test_wirer_lf_and_octave.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,54 @@
from dataclasses import asdict

import pytest

from qualang_tools.wirer import *
from pprint import pprint

from qualang_tools.wirer.connectivity.element import QubitReference
from qualang_tools.wirer.connectivity.wiring_spec import WiringLineType
from qualang_tools.wirer.instruments.instrument_channel import InstrumentChannelOpxPlusInput, \
InstrumentChannelOpxPlusOutput, InstrumentChannelOpxPlusDigitalOutput, InstrumentChannelOctaveInput, \
InstrumentChannelOctaveDigitalInput, InstrumentChannelOctaveOutput

visualize_flag = pytest.visualize_flag

def test_rf_io_allocation(instruments_1octave):
qubits = [1,2,3,4]
def test_rf_io_allocation(instruments_1OPX1Octave):
qubits = [1, 2, 3, 4]


connectivity = Connectivity()
connectivity.add_resonator_line(qubits=qubits)
connectivity.add_qubit_drive_lines(qubits=qubits)

allocate_wiring(connectivity, instruments_1octave)
allocate_wiring(connectivity, instruments_1OPX1Octave)

pprint(connectivity.elements)
if visualize_flag:
visualize(connectivity.elements, available_channels=instruments_1octave.available_channels)
visualize(connectivity.elements, available_channels=instruments_1OPX1Octave.available_channels)

for qubit in qubits:
# resonator lines should be the same because only 1 feedline
for i, channel in enumerate(connectivity.elements[QubitReference(index=qubit)].channels[WiringLineType.RESONATOR]):
assert asdict(channel) == asdict([
InstrumentChannelOpxPlusInput(con=1, port=1, slot=None),
InstrumentChannelOpxPlusInput(con=1, port=2, slot=None),
InstrumentChannelOpxPlusOutput(con=1, port=1, slot=None),
InstrumentChannelOpxPlusOutput(con=1, port=2, slot=None),
# InstrumentChannelOpxPlusDigitalOutput(con=1, port=1, slot=None),
InstrumentChannelOctaveInput(con=1, port=1, slot=None),
InstrumentChannelOctaveOutput(con=1, port=1, slot=None),
# InstrumentChannelOctaveDigitalInput(con=1, port=1, slot=None)
][i])

# drive lines should be allocated sequentially
for i, channel in enumerate(connectivity.elements[QubitReference(index=qubit)].channels[WiringLineType.DRIVE]):
assert asdict(channel) == asdict([
InstrumentChannelOpxPlusOutput(con=1, port=1+2*qubit, slot=None),
InstrumentChannelOpxPlusOutput(con=1, port=2+2*qubit, slot=None),
InstrumentChannelOctaveOutput(con=1, port=1+qubit, slot=None),
][i])



def test_qw_soprano_allocation(instruments_qw_soprano):
qubits = [1, 2, 3, 4, 5]
Expand All @@ -28,11 +60,11 @@ def test_qw_soprano_allocation(instruments_qw_soprano):

allocate_wiring(connectivity, instruments_qw_soprano)

pprint(connectivity.elements)

if visualize_flag:
visualize(connectivity.elements, available_channels=instruments_qw_soprano.available_channels)

# should run without error

def test_qw_soprano_2qb_allocation(instruments_1OPX1Octave):
active_qubits = [1, 2]

Expand All @@ -44,11 +76,11 @@ def test_qw_soprano_2qb_allocation(instruments_1OPX1Octave):

allocate_wiring(connectivity, instruments_1OPX1Octave)

pprint(connectivity.elements)

if visualize_flag:
visualize(connectivity.elements, available_channels=instruments_1OPX1Octave.available_channels)

# should run without error

def test_qw_soprano_2qb_among_5_allocation(instruments_1OPX1Octave):
all_qubits = [1, 2, 3, 4]
active_qubits = [1, 2]
Expand All @@ -70,7 +102,7 @@ def test_qw_soprano_2qb_among_5_allocation(instruments_1OPX1Octave):

allocate_wiring(connectivity, instruments_1OPX1Octave)

pprint(connectivity.elements)

if visualize_flag:
visualize(connectivity.elements, instruments_1OPX1Octave.available_channels)

# should run without error
22 changes: 15 additions & 7 deletions tests/wirer/test_wirer_lf_charge.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
from dataclasses import asdict

import pytest

from qualang_tools.wirer import *
from qualang_tools.wirer.connectivity.element import QubitReference
from qualang_tools.wirer.connectivity.wiring_spec import WiringLineType
from qualang_tools.wirer.instruments.instrument_channel import InstrumentChannelLfFemOutput

visualize_flag = pytest.visualize_flag

def test_5q_allocation_flux_charge(instruments_2lf_2mw):
def test_1q_allocation_flux_charge(instruments_2lf_2mw):
qubits = [1, 2, 3, 4, 5]
qubit_pairs = [(1, 2), (2, 3), (3, 4), (4, 5)]

connectivity = Connectivity()
connectivity.add_resonator_line(qubits=qubits, constraints=mw_fem_spec(slot=7))
connectivity.add_qubit_flux_lines(qubits=qubits)
connectivity.add_qubit_charge_lines(qubits=qubits)
connectivity.add_qubit_pair_flux_lines(qubit_pairs=qubit_pairs, constraints=lf_fem_spec(out_slot=2))

allocate_wiring(connectivity, instruments_2lf_2mw)

print(connectivity.elements)

if visualize_flag:
visualize(connectivity.elements, instruments_2lf_2mw.available_channels)

for qubit_index in qubits:
charge_channels = connectivity.elements[QubitReference(qubit_index)].channels[WiringLineType.CHARGE]
assert len(charge_channels) == 1

for i, channel in enumerate(charge_channels):
assert asdict(channel) == asdict([
InstrumentChannelLfFemOutput(con=1, port=qubit_index, slot=1)
][i])

0 comments on commit d5afb07

Please sign in to comment.