forked from Qiskit/qiskit
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Qiskit Pulse Benchmarks (Qiskit/qiskit-metapackage#848)
Partially fixes Qiskit/qiskit-metapackage#794. * first commit * Fixed some typos * More fixes * Add benchmark to insert instruction from left to right * Fix Lints * Add hardcorded parametic pulse and sample pulse * reduce params * Fix lint * review suggestions * Instruction to schedule * review suggestions * Rename due to lint restrictions number_of_unique_pulses -> unique_pulses and number_of_channels -> channels * review suggestions * Seperate inst_add and sched.union * Remove unwanted imports * lint * Update code * Fix lint * separate instruction to sched conversion and union of sched * uncomment code * Lint * move benchmark functions with similar setup.py to a different file * lint * Move time_union_of_schedules to schedule construction class * Add Open Pulse backend in backends/ * lint * Add Play * Add Play * Remove union union is deprecated * lint
- Loading branch information
1 parent
6f1e9d4
commit f0118d5
Showing
4 changed files
with
428 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,305 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
# This code is part of Qiskit. | ||
# | ||
# (C) Copyright IBM 2019. | ||
# | ||
# This code is licensed under the Apache License, Version 2.0. You may | ||
# obtain a copy of this license in the LICENSE.txt file in the root directory | ||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. | ||
# | ||
# Any modifications or derivative works of this code must retain this | ||
# copyright notice, and modified files need to carry a notice indicating | ||
# that they have been altered from the originals. | ||
|
||
""" | ||
Fake Open Pulse (2 qubit). | ||
""" | ||
|
||
import datetime | ||
from qiskit.providers.models import (GateConfig, PulseBackendConfiguration, | ||
PulseDefaults, Command, UchannelLO) | ||
from qiskit.providers.models.backendproperties import (Nduv, Gate, | ||
BackendProperties) | ||
from qiskit.qobj import PulseQobjInstruction | ||
from qiskit.test.mock.fake_backend import FakeBackend | ||
|
||
|
||
class FakeOpenPulse2Q(FakeBackend): | ||
"""A fake open pulse backend.""" | ||
|
||
def __init__(self): | ||
configuration = PulseBackendConfiguration( | ||
backend_name='fake_openpulse', | ||
backend_version='0.0.0', | ||
n_qubits=2, | ||
meas_levels=[0, 1, 2], | ||
basis_gates=['u1', 'u2', 'u3', 'cx', 'id'], | ||
simulator=False, | ||
local=True, | ||
conditional=True, | ||
open_pulse=True, | ||
memory=False, | ||
max_shots=65536, | ||
gates=[GateConfig(name='TODO', parameters=[], qasm_def='TODO')], | ||
coupling_map=[[0, 1]], | ||
n_registers=2, | ||
n_uchannels=2, | ||
u_channel_lo=[ | ||
[UchannelLO(q=0, scale=1. + 0.j)], | ||
[UchannelLO(q=0, scale=-1. + 0.j), | ||
UchannelLO(q=1, scale=1. + 0.j)] | ||
], | ||
meas_level=[1, 2], | ||
qubit_lo_range=[[4.5, 5.5], [4.5, 5.5]], | ||
meas_lo_range=[[6.0, 7.0], [6.0, 7.0]], | ||
dt=1.3333, | ||
dtm=10.5, | ||
rep_times=[100, 250, 500, 1000], | ||
meas_map=[[0, 1]], | ||
channel_bandwidth=[ | ||
[-0.2, 0.4], [-0.3, 0.3], [-0.3, 0.3], | ||
[-0.02, 0.02], [-0.02, 0.02], [-0.02, 0.02] | ||
], | ||
meas_kernels=['kernel1'], | ||
discriminators=['max_1Q_fidelity'], | ||
acquisition_latency=[[100, 100], [100, 100]], | ||
conditional_latency=[ | ||
[100, 1000], [1000, 100], [100, 1000], | ||
[1000, 100], [100, 1000], [1000, 100] | ||
], | ||
hamiltonian={ | ||
'h_str': ["np.pi*(2*v0-alpha0)*O0", "np.pi*alpha0*O0*O0", | ||
"2*np.pi*r*X0||D0", "2*np.pi*r*X0||U1", | ||
"2*np.pi*r*X1||U0", "np.pi*(2*v1-alpha1)*O1", | ||
"np.pi*alpha1*O1*O1", "2*np.pi*r*X1||D1", | ||
"2*np.pi*j*(Sp0*Sm1+Sm0*Sp1)"], | ||
'description': "A hamiltonian for a mocked 2Q device, with 1Q\ | ||
and 2Q terms.", | ||
'qub': {'0': 3, '1': 3}, | ||
'vars': {'v0': 5.00, | ||
'v1': 5.1, | ||
'j': 0.01, | ||
'r': 0.02, | ||
'alpha0': -0.33, | ||
'alpha1': -0.33} | ||
}, | ||
channels={ | ||
'acquire0': { | ||
'operates': {'qubits': [0]}, | ||
'purpose': 'acquire', | ||
'type': 'acquire' | ||
}, | ||
'acquire1': { | ||
'operates': {'qubits': [1]}, | ||
'purpose': 'acquire', | ||
'type': 'acquire' | ||
}, | ||
'd0': { | ||
'operates': {'qubits': [0]}, | ||
'purpose': 'drive', | ||
'type': 'drive' | ||
}, | ||
'd1': { | ||
'operates': {'qubits': [1]}, | ||
'purpose': 'drive', | ||
'type': 'drive' | ||
}, | ||
'm0': { | ||
'type': 'measure', | ||
'purpose': 'measure', | ||
'operates': {'qubits': [0]} | ||
}, | ||
'm1': { | ||
'type': 'measure', | ||
'purpose': 'measure', | ||
'operates': {'qubits': [1]} | ||
}, | ||
'u0': { | ||
'operates': {'qubits': [0, 1]}, | ||
'purpose': 'cross-resonance', | ||
'type': 'control' | ||
}, | ||
'u1': { | ||
'operates': {'qubits': [1, 0]}, | ||
'purpose': 'cross-resonance', | ||
'type': 'control' | ||
} | ||
} | ||
) | ||
|
||
self._defaults = PulseDefaults.from_dict({ | ||
'qubit_freq_est': [4.9, 5.0], | ||
'meas_freq_est': [6.5, 6.6], | ||
'buffer': 10, | ||
'pulse_library': [ | ||
{ | ||
'name': 'test_pulse_1', | ||
'samples': [[0.0, 0.0], [0.0, 0.1]] | ||
}, | ||
{ | ||
'name': 'test_pulse_2', | ||
'samples': [[0.0, 0.0], [0.0, 0.1], [0.0, 1.0]] | ||
}, | ||
{ | ||
'name': 'test_pulse_3', | ||
'samples': [[0.0, 0.0], [0.0, 0.1], [0.0, 1.0], [0.5, 0.0]] | ||
}, | ||
{ | ||
'name': 'test_pulse_4', | ||
'samples': 7 * [ | ||
[0.0, 0.0], [0.0, 0.1], [0.0, 1.0], [0.5, 0.0] | ||
] | ||
} | ||
], | ||
'cmd_def': [ | ||
Command.from_dict({ | ||
'name': 'u1', | ||
'qubits': [0], | ||
'sequence': [ | ||
PulseQobjInstruction(name='fc', ch='d0', | ||
t0=0, phase='-P0').to_dict() | ||
]}).to_dict(), | ||
Command.from_dict({ | ||
'name': 'u1', | ||
'qubits': [1], | ||
'sequence': [ | ||
PulseQobjInstruction(name='fc', ch='d1', | ||
t0=0, phase='-P0').to_dict() | ||
]}).to_dict(), | ||
Command.from_dict({ | ||
'name': 'u2', | ||
'qubits': [0], | ||
'sequence': [ | ||
PulseQobjInstruction(name='fc', ch='d0', | ||
t0=0, | ||
phase='-P1').to_dict(), | ||
PulseQobjInstruction(name='test_pulse_4', ch='d0', | ||
t0=0).to_dict(), | ||
PulseQobjInstruction(name='fc', ch='d0', t0=0, | ||
phase='-P0').to_dict() | ||
]}).to_dict(), | ||
Command.from_dict({ | ||
'name': 'u2', | ||
'qubits': [1], | ||
'sequence': [ | ||
PulseQobjInstruction(name='fc', ch='d1', t0=0, | ||
phase='-P1').to_dict(), | ||
PulseQobjInstruction(name='test_pulse_4', | ||
ch='d1', t0=0).to_dict(), | ||
PulseQobjInstruction(name='fc', ch='d1', | ||
t0=0, phase='-P0').to_dict() | ||
]}).to_dict(), | ||
Command.from_dict({ | ||
'name': 'u3', | ||
'qubits': [0], | ||
'sequence': [ | ||
PulseQobjInstruction(name='test_pulse_1', ch='d0', | ||
t0=0).to_dict() | ||
]}).to_dict(), | ||
Command.from_dict({ | ||
'name': 'u3', | ||
'qubits': [1], | ||
'sequence': [ | ||
PulseQobjInstruction(name='test_pulse_3', ch='d1', | ||
t0=0).to_dict() | ||
]}).to_dict(), | ||
Command.from_dict({ | ||
'name': 'cx', | ||
'qubits': [0, 1], | ||
'sequence': [ | ||
PulseQobjInstruction(name='test_pulse_1', ch='d0', | ||
t0=0).to_dict(), | ||
PulseQobjInstruction(name='test_pulse_2', ch='u0', | ||
t0=10).to_dict(), | ||
PulseQobjInstruction(name='test_pulse_1', ch='d1', | ||
t0=20).to_dict(), | ||
PulseQobjInstruction(name='fc', ch='d1', | ||
t0=20, phase=2.1).to_dict() | ||
]}).to_dict(), | ||
Command.from_dict({ | ||
'name': 'ParametrizedGate', | ||
'qubits': [0, 1], | ||
'sequence': [ | ||
PulseQobjInstruction(name='test_pulse_1', ch='d0', | ||
t0=0).to_dict(), | ||
PulseQobjInstruction(name='test_pulse_2', ch='u0', | ||
t0=10).to_dict(), | ||
PulseQobjInstruction(name='pv', ch='d1', | ||
t0=2, val='cos(P2)').to_dict(), | ||
PulseQobjInstruction(name='test_pulse_1', ch='d1', | ||
t0=20).to_dict(), | ||
PulseQobjInstruction(name='fc', ch='d1', | ||
t0=20, phase=2.1).to_dict() | ||
]}).to_dict(), | ||
Command.from_dict({ | ||
'name': 'measure', | ||
'qubits': [0, 1], | ||
'sequence': [ | ||
PulseQobjInstruction(name='test_pulse_1', ch='m0', | ||
t0=0).to_dict(), | ||
PulseQobjInstruction(name='test_pulse_1', ch='m1', | ||
t0=0).to_dict(), | ||
PulseQobjInstruction(name='acquire', duration=10, t0=0, | ||
qubits=[0, 1], | ||
memory_slot=[0, 1]).to_dict() | ||
]}).to_dict() | ||
] | ||
}) | ||
|
||
mock_time = datetime.datetime.now() | ||
dt = 1.3333 # pylint: disable=invalid-name | ||
self._properties = BackendProperties( | ||
backend_name='fake_openpulse_2q', | ||
backend_version='0.0.0', | ||
last_update_date=mock_time, | ||
qubits=[ | ||
[Nduv(date=mock_time, name='T1', unit='µs', | ||
value=71.9500421005539), | ||
Nduv(date=mock_time, name='frequency', unit='MHz', | ||
value=4919.96800692)], | ||
[Nduv(date=mock_time, name='T1', unit='µs', | ||
value=81.9500421005539), | ||
Nduv(date=mock_time, name='frequency', unit='GHz', | ||
value=5.01996800692)] | ||
], | ||
gates=[ | ||
Gate(gate='u1', name='u1_0', qubits=[0], | ||
parameters=[ | ||
Nduv(date=mock_time, name='gate_error', unit='', | ||
value=0.06), | ||
Nduv(date=mock_time, name='gate_length', unit='ns', | ||
value=0.)]), | ||
Gate(gate='u3', name='u3_0', qubits=[0], | ||
parameters=[ | ||
Nduv(date=mock_time, name='gate_error', unit='', | ||
value=0.06), | ||
Nduv(date=mock_time, name='gate_length', unit='ns', | ||
value=2 * dt)]), | ||
Gate(gate='u3', name='u3_1', qubits=[1], | ||
parameters=[ | ||
Nduv(date=mock_time, name='gate_error', unit='', | ||
value=0.06), | ||
Nduv(date=mock_time, name='gate_length', unit='ns', | ||
value=4 * dt)]), | ||
Gate(gate='cx', name='cx0_1', qubits=[0, 1], | ||
parameters=[ | ||
Nduv(date=mock_time, name='gate_error', unit='', | ||
value=1.0), | ||
Nduv(date=mock_time, name='gate_length', unit='ns', | ||
value=22 * dt)]), | ||
], | ||
general=[] | ||
) | ||
|
||
super().__init__(configuration) | ||
|
||
def defaults(self): | ||
"""Return the default pulse-related settings provided by the backend | ||
(such as gate to Schedule mappings). | ||
""" | ||
return self._defaults | ||
|
||
def properties(self): | ||
"""Return the measured characteristics of the backend.""" | ||
return self._properties |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# -*- coding: utf-8 -* | ||
|
||
# This code is part of Qiskit. | ||
# | ||
# (C) Copyright IBM 2020. | ||
# | ||
# This code is licensed under the Apache License, Version 2.0. You may | ||
# obtain a copy of this license in the LICENSE.txt file in the root directory | ||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. | ||
# | ||
# Any modifications or derivative works of this code must retain this | ||
# copyright notice, and modified files need to carry a notice indicating | ||
# that they have been altered from the originals. | ||
|
||
# pylint: disable=missing-docstring,invalid-name,no-member | ||
# pylint: disable=attribute-defined-outside-init | ||
|
||
import numpy as np | ||
from qiskit.pulse import Schedule, Gaussian, DriveChannel, SamplePulse, Play | ||
|
||
|
||
def build_sample_pulse_schedule(number_of_unique_pulses, number_of_channels): | ||
rng = np.random.RandomState(42) | ||
sched = Schedule() | ||
for _ in range(number_of_unique_pulses): | ||
for channel in range(number_of_channels): | ||
sched.append(Play(SamplePulse(rng.random(50)), | ||
DriveChannel(channel))) | ||
return sched | ||
|
||
|
||
def build_parametric_pulse_schedule(number_of_unique_pulses, | ||
number_of_channels): | ||
sched = Schedule() | ||
for _ in range(number_of_unique_pulses): | ||
for channel in range(number_of_channels): | ||
sched.append(Play(Gaussian(duration=25, sigma=4, amp=0.5j), | ||
DriveChannel(channel))) | ||
return sched | ||
|
||
|
||
class ScheduleConstructionBench: | ||
params = ([1, 2, 5], [8, 128, 2048]) | ||
param_names = ['number_of_unique_pulses', 'number_of_channels'] | ||
timeout = 600 | ||
|
||
def setup(self, unique_pulses, channels): | ||
self.sample_sched = build_sample_pulse_schedule(unique_pulses, | ||
channels) | ||
self.parametric_sched = build_parametric_pulse_schedule(unique_pulses, | ||
channels) | ||
|
||
def time_sample_pulse_schedule_construction(self, | ||
unique_pulses, | ||
channels): | ||
build_sample_pulse_schedule(unique_pulses, channels) | ||
|
||
def time_parametric_pulse_schedule_construction(self, | ||
unique_pulses, | ||
channels): | ||
build_parametric_pulse_schedule(unique_pulses, channels) | ||
|
||
def time_append_instruction(self, _, __): | ||
self.sample_sched.append(self.parametric_sched) | ||
|
||
def time_insert_instruction_left_to_right(self, _, __): | ||
sched = self.sample_sched.shift(self.parametric_sched.stop_time) | ||
sched.insert(self.parametric_sched.start_time, | ||
self.parametric_sched) |
Oops, something went wrong.