def test_requires_stop(self): sts = [ DummyPulseTemplate(duration='t1', defined_channels={'A'}, parameter_names={'a', 'b'}, requires_stop=False), DummyPulseTemplate(duration='t1', defined_channels={'B'}, parameter_names={'a', 'c'}, requires_stop=False) ] self.assertFalse( AtomicMultiChannelPulseTemplate(*sts).requires_stop( dict(), dict())) sts = [ DummyPulseTemplate(duration='t1', defined_channels={'A'}, parameter_names={'a', 'b'}, requires_stop=False), DummyPulseTemplate(duration='t1', defined_channels={'B'}, parameter_names={'a', 'c'}, requires_stop=True) ] self.assertTrue( AtomicMultiChannelPulseTemplate(*sts).requires_stop( dict(), dict()))
def test_duration(self): sts = [DummyPulseTemplate(duration='t1', defined_channels={'A'}), DummyPulseTemplate(duration='t1', defined_channels={'B'}), DummyPulseTemplate(duration='t2', defined_channels={'C'})] with self.assertRaises(ValueError): AtomicMultiChannelPulseTemplate(*sts) with self.assertRaises(ValueError): AtomicMultiChannelPulseTemplate(sts[0], sts[2]) template = AtomicMultiChannelPulseTemplate(*sts[:1]) self.assertEqual(template.duration, 't1')
def test_init_empty(self) -> None: with self.assertRaises(ValueError): AtomicMultiChannelPulseTemplate() with self.assertRaises(ValueError): AtomicMultiChannelPulseTemplate(identifier='foo') with self.assertRaises(ValueError): AtomicMultiChannelPulseTemplate() with self.assertRaises(ValueError): AtomicMultiChannelPulseTemplate(identifier='foo') with self.assertRaises(ValueError): AtomicMultiChannelPulseTemplate(identifier='foo', parameter_constraints=[])
def test_non_atomic_subtemplates(self): non_atomic_pt = PulseTemplateStub(duration='t1', defined_channels={'A'}, parameter_names=set()) atomic_pt = DummyPulseTemplate(defined_channels={'B'}, duration='t1') non_atomic_mapping = MappingPulseTemplate(non_atomic_pt) with self.assertRaises(TypeError): AtomicMultiChannelPulseTemplate(non_atomic_pt) with self.assertRaises(TypeError): AtomicMultiChannelPulseTemplate(non_atomic_pt, atomic_pt) with self.assertRaises(TypeError): AtomicMultiChannelPulseTemplate(non_atomic_mapping, atomic_pt) with self.assertRaises(TypeError): AtomicMultiChannelPulseTemplate((non_atomic_pt, {'A': 'C'}), atomic_pt)
def test_get_measurement_windows(self): wfs = [ DummyWaveform(duration=1.1, defined_channels={'A'}), DummyWaveform(duration=1.1, defined_channels={'B'}) ] sts = [ DummyPulseTemplate(duration='t1', defined_channels={'A'}, waveform=wfs[0], measurements=[('m', 0, 1), ('n', 0.3, 0.4)]), DummyPulseTemplate(duration='t1', defined_channels={'B'}, waveform=wfs[1], measurements=[('m', 0.1, .2)]) ] pt = AtomicMultiChannelPulseTemplate(*sts, parameter_constraints=['a < b'], measurements=[('n', .1, .2)]) measurement_mapping = dict(m='foo', n='bar') expected = [('bar', .1, .2), ('foo', 0, 1), ('bar', .3, .4), ('foo', .1, .2)] meas_windows = pt.get_measurement_windows({}, measurement_mapping) self.assertEqual(expected, meas_windows)
def test_plot_with_parameter_value_being_expression_string(self) -> None: """This is currently not supported but probably should be?""" sine_measurements = [('M', 't_duration/2', 't_duration')] sine = FunctionPulseTemplate('a*sin(omega*t)', 't_duration', measurements=sine_measurements) sine_channel_mapping = dict(default='sin_channel') sine_measurement_mapping = dict(M='M_sin') remapped_sine = MappingPulseTemplate( sine, measurement_mapping=sine_measurement_mapping, channel_mapping=sine_channel_mapping) cos_measurements = [('M', 0, 't_duration/2')] cos = FunctionPulseTemplate('a*cos(omega*t)', 't_duration', measurements=cos_measurements) cos_channel_mapping = dict(default='cos_channel') cos_measurement_mapping = dict(M='M_cos') remapped_cos = MappingPulseTemplate( cos, channel_mapping=cos_channel_mapping, measurement_mapping=cos_measurement_mapping) both = AtomicMultiChannelPulseTemplate(remapped_sine, remapped_cos) parameter_values = dict(omega=1.0, a=1.0, t_duration="2*pi") _ = plot(both, parameters=parameter_values, sample_rate=100)
def test_build_waveform_none(self): wfs = [DummyWaveform(duration=1.1, defined_channels={'A'}), DummyWaveform(duration=1.1, defined_channels={'B'})] sts = [DummyPulseTemplate(duration='t1', defined_channels={'A'}, waveform=wfs[0]), DummyPulseTemplate(duration='t1', defined_channels={'B'}, waveform=wfs[1]), DummyPulseTemplate(duration='t1', defined_channels={'C'}, waveform=None)] pt = AtomicMultiChannelPulseTemplate(*sts, parameter_constraints=['a < b']) parameters = dict(a=2.2, b=1.1, c=3.3) channel_mapping = dict(A=6) with self.assertRaises(ParameterConstraintViolation): # parameter constraints are checked before channel mapping is applied pt.build_waveform(parameters, channel_mapping=dict()) parameters['a'] = 0.5 wf = pt.build_waveform(parameters, channel_mapping=channel_mapping) self.assertIs(wf['A'], wfs[0]) self.assertIs(wf['B'], wfs[1]) sts[1].waveform = None wf = pt.build_waveform(parameters, channel_mapping=channel_mapping) self.assertIs(wf, wfs[0]) sts[0].waveform = None wf = pt.build_waveform(parameters, channel_mapping=channel_mapping) self.assertIsNone(wf)
def test_serialize_old(self) -> None: # test for deprecated version during transition period, remove after final switch with self.assertWarnsRegex( DeprecationWarning, "deprecated", msg= "AtomicMultiChannelPT does not issue warning for old serialization routines." ): sts = [ DummyPulseTemplate(duration='t1', defined_channels={'A'}, parameter_names={'a', 'b'}), DummyPulseTemplate(duration='t1', defined_channels={'B'}, parameter_names={'a', 'c'}) ] constraints = ['a < d'] template = AtomicMultiChannelPulseTemplate( *sts, parameter_constraints=constraints) expected_data = dict(subtemplates=['0', '1'], parameter_constraints=['a < d']) def serialize_callback(obj) -> str: self.assertIn(obj, sts) return str(sts.index(obj)) serializer = DummySerializer( serialize_callback=serialize_callback, identifier_callback=serialize_callback) data = template.get_serialization_data(serializer=serializer) self.assertEqual(expected_data, data)
def test_duration(self): sts = [ DummyPulseTemplate(duration='t1', defined_channels={'A'}), DummyPulseTemplate(duration='t1', defined_channels={'B'}), DummyPulseTemplate(duration='t2', defined_channels={'C'}) ] template = AtomicMultiChannelPulseTemplate(*sts[:1]) self.assertEqual(template.duration, 't1')
def test_mapping_template_pure_conversion(self): template = AtomicMultiChannelPulseTemplate( *zip(self.subtemplates, self.param_maps, self.chan_maps)) for st, pm, cm in zip(template.subtemplates, self.param_maps, self.chan_maps): self.assertEqual(st.parameter_names, set(pm.values())) self.assertEqual(st.defined_channels, set(cm.values()))
def test_parameter_names_2(self): template = AtomicMultiChannelPulseTemplate( *zip(self.subtemplates, self.param_maps, self.chan_maps), parameter_constraints={'pp1 > hugo'}, measurements={('meas', 'd', 1)}, duration='my_duration') self.assertEqual({'pp1', 'pp2', 'pp3', 'hugo', 'd', 'my_duration'}, template.parameter_names)
def test_external_parameters_warning(self): with self.assertWarnsRegex( DeprecationWarning, "external_parameters", msg= "AtomicMultiChannelPulseTemplate did not issue a warning for argument external_parameters" ): AtomicMultiChannelPulseTemplate(DummyPulseTemplate(), external_parameters={'a'})
def test_parameter_names(self): sts = [DummyPulseTemplate(duration='t1', defined_channels={'A'}, parameter_names={'a', 'b'}, measurement_names={'A', 'C'}), DummyPulseTemplate(duration='t1', defined_channels={'B'}, parameter_names={'a', 'c'}, measurement_names={'A', 'B'})] pt = AtomicMultiChannelPulseTemplate(*sts, measurements=[('D', 'd', 2)], parameter_constraints=['d < e']) self.assertEqual(pt.parameter_names, {'a', 'b', 'c', 'd', 'e'})
def test_integral(self) -> None: sts = [DummyPulseTemplate(duration='t1', defined_channels={'A'}, integrals={'A': ExpressionScalar('2+k')}), DummyPulseTemplate(duration='t1', defined_channels={'B', 'C'}, integrals={'B': ExpressionScalar('t1-t0*3.1'), 'C': ExpressionScalar('l')})] pulse = AtomicMultiChannelPulseTemplate(*sts) self.assertEqual({'A': ExpressionScalar('2+k'), 'B': ExpressionScalar('t1-t0*3.1'), 'C': ExpressionScalar('l')}, pulse.integral)
def test_as_expression(self): sts = [DummyPulseTemplate(duration='t1', defined_channels={'A'}, integrals={'A': ExpressionScalar('2+k')}), DummyPulseTemplate(duration='t1', defined_channels={'B', 'C'}, integrals={'B': ExpressionScalar('t1-t0*3.1'), 'C': ExpressionScalar('l')})] pulse = AtomicMultiChannelPulseTemplate(*sts) self.assertEqual({'A': ExpressionScalar(sympify('(2+k) / t1') * pulse._AS_EXPRESSION_TIME), 'B': ExpressionScalar(sympify('(t1-t0*3.1)/t1') * pulse._AS_EXPRESSION_TIME), 'C': ExpressionScalar(sympify('l/t1') * pulse._AS_EXPRESSION_TIME)}, pulse._as_expression())
def test_instantiation_duration_check(self): subtemplates = [DummyPulseTemplate(parameter_names={'p1'}, measurement_names={'m1'}, defined_channels={'c1'}, duration='t_1', waveform=DummyWaveform(duration=3, defined_channels={'c1'})), DummyPulseTemplate(parameter_names={'p2'}, measurement_names={'m2'}, defined_channels={'c2'}, duration='t_2', waveform=DummyWaveform(duration=3, defined_channels={'c2'})), DummyPulseTemplate(parameter_names={'p3'}, measurement_names={'m3'}, defined_channels={'c3'}, duration='t_3', waveform=DummyWaveform(duration=4, defined_channels={'c3'}))] with self.assertRaisesRegex(ValueError, 'duration equality'): AtomicMultiChannelPulseTemplate(*subtemplates) amcpt = AtomicMultiChannelPulseTemplate(*subtemplates, duration=True) self.assertIs(amcpt.duration, subtemplates[0].duration) with self.assertRaisesRegex(ValueError, 'duration'): amcpt.build_waveform(parameters=dict(t_1=3, t_2=3, t_3=3), channel_mapping={ch: ch for ch in 'c1 c2 c3'.split()}) subtemplates[2].waveform = None amcpt.build_waveform(parameters=dict(t_1=3, t_2=3, t_3=3), channel_mapping={ch: ch for ch in 'c1 c2 c3'.split()}) amcpt = AtomicMultiChannelPulseTemplate(*subtemplates, duration='t_0') with self.assertRaisesRegex(ValueError, 'duration'): amcpt.build_waveform(parameters=dict(t_1=3, t_2=3, t_3=3, t_0=4), channel_mapping={ch: ch for ch in 'c1 c2 c3'.split()}) with self.assertRaisesRegex(ValueError, 'duration'): amcpt.build_waveform(parameters=dict(t_1=3+1e-9, t_2=3, t_3=3, t_0=4), channel_mapping={ch: ch for ch in 'c1 c2 c3'.split()}) amcpt.build_waveform(parameters=dict(t_1=3, t_2=3, t_3=3, t_0=3), channel_mapping={ch: ch for ch in 'c1 c2 c3'.split()}) amcpt.build_waveform(parameters=dict(t_1=3+1e-11, t_2=3, t_3=3, t_0=3), channel_mapping={ch: ch for ch in 'c1 c2 c3'.split()})
def test_mapping_template_mixed_conversion(self): subtemp_args = [ (self.subtemplates[0], self.param_maps[0], self.chan_maps[0]), MappingPulseTemplate(self.subtemplates[1], parameter_mapping=self.param_maps[1], channel_mapping=self.chan_maps[1]), (self.subtemplates[2], self.param_maps[2], self.chan_maps[2]) ] template = AtomicMultiChannelPulseTemplate(*subtemp_args) for st, pm, cm in zip(template.subtemplates, self.param_maps, self.chan_maps): self.assertEqual(st.parameter_names, set(pm.values())) self.assertEqual(st.defined_channels, set(cm.values()))
def test_plotting_two_channel_function_pulse_after_two_channel_table_pulse_crash( self) -> None: """ successful if no crash -> no asserts """ template = TablePulseTemplate(entries={ 'A': [(0, 0), ('ta', 'va', 'hold'), ('tb', 'vb', 'linear'), ('tend', 0, 'jump')], 'B': [(0, 0), ('ta', '-va', 'hold'), ('tb', '-vb', 'linear'), ('tend', 0, 'jump')] }, measurements=[('m', 0, 'ta'), ('n', 'tb', 'tend-tb')]) parameters = { 'ta': 2, 'va': 2, 'tb': 4, 'vb': 3, 'tc': 5, 'td': 11, 'tend': 6 } _ = plot(template, parameters, sample_rate=100, show=False, plot_measurements={'m', 'n'}) repeated_template = RepetitionPulseTemplate(template, 'n_rep') sine_template = FunctionPulseTemplate('sin_a*sin(t)', '2*3.1415') two_channel_sine_template = AtomicMultiChannelPulseTemplate( (sine_template, { 'default': 'A' }), (sine_template, { 'default': 'B' }, { 'sin_a': 'sin_b' })) sequence_template = SequencePulseTemplate(repeated_template, two_channel_sine_template) #sequence_template = SequencePulseTemplate(two_channel_sine_template, repeated_template) # this was working fine sequence_parameters = dict( parameters) # we just copy our parameter dict from before sequence_parameters[ 'n_rep'] = 4 # and add a few new values for the new params from the sine wave sequence_parameters['sin_a'] = 1 sequence_parameters['sin_b'] = 2 _ = plot(sequence_template, parameters=sequence_parameters, sample_rate=100, show=False)
def test_measurement_names(self): sts = [ DummyPulseTemplate(duration='t1', defined_channels={'A'}, parameter_names={'a', 'b'}, measurement_names={'A', 'C'}), DummyPulseTemplate(duration='t1', defined_channels={'B'}, parameter_names={'a', 'c'}, measurement_names={'A', 'B'}) ] self.assertEqual( AtomicMultiChannelPulseTemplate(*sts, measurements=[ ('D', 1, 2) ]).measurement_names, {'A', 'B', 'C', 'D'})
def test_build_sequence(self): wfs = [ DummyWaveform(duration=1.1, defined_channels={'A'}), DummyWaveform(duration=1.1, defined_channels={'B'}) ] sts = [ DummyPulseTemplate(duration='t1', defined_channels={'A'}, waveform=wfs[0], measurements=[('m', 0, 1)]), DummyPulseTemplate(duration='t1', defined_channels={'B'}, waveform=wfs[1]), DummyPulseTemplate(duration='t1', defined_channels={'C'}, waveform=None) ] pt = AtomicMultiChannelPulseTemplate(*sts, parameter_constraints=['a < b'], measurements=[('n', .1, .2)]) params = dict(a=ConstantParameter(1.0), b=ConstantParameter(1.1)) measurement_mapping = dict(m='foo', n='bar') channel_mapping = {'A': 'A', 'B': 'B', 'C': None} block = InstructionBlock() pt.build_sequence(None, parameters=params, conditions={}, measurement_mapping=measurement_mapping, channel_mapping=channel_mapping, instruction_block=block) expected_waveform = MultiChannelWaveform(wfs) expected_block = InstructionBlock() measurements = [('bar', .1, .2), ('foo', 0, 1)] expected_block.add_instruction_meas(measurements) expected_block.add_instruction_exec(waveform=expected_waveform) self.assertEqual(len(block.instructions), len(expected_block.instructions)) self.assertEqual(block.instructions[0].compare_key, expected_block.instructions[0].compare_key) self.assertEqual(block.instructions[1].compare_key, expected_block.instructions[1].compare_key)
def test_build_waveform(self): wfs = [ DummyWaveform(duration=1.1, defined_channels={'A'}), DummyWaveform(duration=1.1, defined_channels={'B'}) ] sts = [ DummyPulseTemplate(duration='t1', defined_channels={'A'}, parameter_names={'a', 'b'}, measurement_names={'A', 'C'}, waveform=wfs[0]), DummyPulseTemplate(duration='t1', defined_channels={'B'}, parameter_names={'a', 'c'}, measurement_names={'A', 'B'}, waveform=wfs[1]) ] pt = AtomicMultiChannelPulseTemplate(*sts, parameter_constraints=['a < b']) parameters = dict(a=2.2, b=1.1, c=3.3) channel_mapping = dict() with self.assertRaises(ParameterConstraintViolation): pt.build_waveform(parameters, channel_mapping=dict()) parameters['a'] = 0.5 wf = pt.build_waveform(parameters, channel_mapping=channel_mapping) self.assertEqual(wf['A'], wfs[0]) self.assertEqual(wf['B'], wfs[1]) for st in sts: self.assertEqual(st.build_waveform_calls, [(parameters, channel_mapping)]) self.assertIs(parameters, st.build_waveform_calls[0][0]) self.assertIs(channel_mapping, st.build_waveform_calls[0][1])
def test_defined_channels(self): subtemp_args = [ *zip(self.subtemplates, self.param_maps, self.chan_maps) ] template = AtomicMultiChannelPulseTemplate(*subtemp_args) self.assertEqual(template.defined_channels, {'cc1', 'cc2', 'cc3'})
def test_channel_intersection(self): chan_maps = self.chan_maps.copy() chan_maps[-1]['c3'] = 'cc1' with self.assertRaises(ChannelMappingException): AtomicMultiChannelPulseTemplate( *zip(self.subtemplates, self.param_maps, chan_maps))