def test_init_empty(self) -> None: template = MultiChannelPulseTemplate([], {}, identifier='foo') self.assertEqual('foo', template.identifier) self.assertFalse(template.parameter_names) self.assertFalse(template.parameter_declarations) self.assertTrue(template.is_interruptable) self.assertFalse(template.requires_stop(dict(), dict())) self.assertEqual(0, template.num_channels)
def test_requires_stop_true_mapped_parameters(self) -> None: dummy = DummyPulseTemplate(parameter_names={'foo'}, requires_stop=True) pulse = MultiChannelPulseTemplate([(dummy, dict(foo='2*bar'), [0]), (dummy, dict(foo='rab-5'), [1])], {'bar', 'rab'}) self.assertEqual({'bar', 'rab'}, pulse.parameter_names) self.assertEqual( {ParameterDeclaration('bar'), ParameterDeclaration('rab')}, pulse.parameter_declarations) parameters = dict(bar=ConstantParameter(-3.6), rab=ConstantParameter(35.26)) self.assertTrue(pulse.requires_stop(parameters, dict()))
def test_init_single_subtemplate_invalid_channel_mapping(self) -> None: subtemplate = DummyPulseTemplate(parameter_names={'foo'}, num_channels=2, duration=1.3) with self.assertRaises(ValueError): MultiChannelPulseTemplate([(subtemplate, { 'foo': "2.3" }, [3, 0])], {}) with self.assertRaises(ValueError): MultiChannelPulseTemplate([(subtemplate, { 'foo': "2.3" }, [-1, 0])], {})
def test_init_single_subtemplate_no_external_params(self) -> None: subtemplate = DummyPulseTemplate(parameter_names={'foo'}, num_channels=2, duration=1.3) template = MultiChannelPulseTemplate([(subtemplate, { 'foo': "2.3" }, [1, 0])], {}) self.assertFalse(template.parameter_names) self.assertFalse(template.parameter_declarations) self.assertFalse(template.is_interruptable) self.assertFalse(template.requires_stop(dict(), dict())) self.assertEqual(2, template.num_channels)
def test_deserialize(self) -> None: dummy1 = DummyPulseTemplate(parameter_names={'foo'}, num_channels=2) dummy2 = DummyPulseTemplate(parameter_names={}, num_channels=1) exp = Expression("bar - 35") data = dict(external_parameters=['bar'], subtemplates=[ dict(template=str(id(dummy1)), parameter_mappings=dict(foo=str(exp)), channel_mappings=[0, 2]), dict(template=str(id(dummy2)), parameter_mappings=dict(), channel_mappings=[1]) ]) serializer = DummySerializer(serialize_callback=lambda x: str(x) if isinstance(x, Expression) else str(id(x))) serializer.subelements[str(id(dummy1))] = dummy1 serializer.subelements[str(id(dummy2))] = dummy2 serializer.subelements[str(exp)] = exp template = MultiChannelPulseTemplate.deserialize(serializer, **data) self.assertEqual(set(data['external_parameters']), template.parameter_names) self.assertEqual({ParameterDeclaration('bar')}, template.parameter_declarations) recovered_data = template.get_serialization_data(serializer) self.assertEqual(data, recovered_data)
def test_init_single_subtemplate_requires_stop_external_params( self) -> None: subtemplate = DummyPulseTemplate(parameter_names={'foo'}, requires_stop=True, num_channels=2, duration=1.3) template = MultiChannelPulseTemplate([(subtemplate, { 'foo': "2.3 ** bar" }, [1, 0])], {'bar'}) self.assertEqual({'bar'}, template.parameter_names) self.assertEqual({ParameterDeclaration('bar')}, template.parameter_declarations) self.assertFalse(template.is_interruptable) self.assertTrue( template.requires_stop(dict(bar=ConstantParameter(3.5)), dict())) self.assertEqual(2, template.num_channels)
def test_integration_table_and_function_template(self) -> None: from qctoolkit.pulses import TablePulseTemplate, FunctionPulseTemplate, Sequencer, EXECInstruction, STOPInstruction table_template = TablePulseTemplate(channels=2) table_template.add_entry(1, 4, channel=0) table_template.add_entry('foo', 'bar', channel=0) table_template.add_entry(10, 0, channel=0) table_template.add_entry('foo', 2.7, interpolation='linear', channel=1) table_template.add_entry(9, 'bar', interpolation='linear', channel=1) function_template = FunctionPulseTemplate('sin(t)', '10') template = MultiChannelPulseTemplate( [(function_template, dict(), [1]), (table_template, dict(foo='5', bar='2 * hugo'), [2, 0])], {'hugo'}) sample_times = numpy.linspace(98.5, 103.5, num=11) function_template_samples = function_template.build_waveform( dict()).sample(sample_times) table_template_samples = table_template.build_waveform( dict(foo=ConstantParameter(5), bar=ConstantParameter(2 * (-1.3)))).sample(sample_times) template_waveform = template.build_waveform( dict(hugo=ConstantParameter(-1.3))) template_samples = template_waveform.sample(sample_times) self.assertTrue( numpy.all(table_template_samples[0] == template_samples[2])) self.assertTrue( numpy.all(table_template_samples[1] == template_samples[0])) self.assertTrue( numpy.all(function_template_samples[0] == template_samples[1])) sequencer = Sequencer() sequencer.push(template, parameters=dict(hugo=-1.3), conditions=dict()) instructions = sequencer.build() self.assertEqual(2, len(instructions)) self.assertIsInstance(instructions[0], EXECInstruction) self.assertIsInstance(instructions[1], STOPInstruction)
def test_get_serialization_data(self) -> None: serializer = DummySerializer(serialize_callback=lambda x: str(x) if isinstance(x, Expression) else str(id(x))) dummy1 = DummyPulseTemplate(parameter_names={'foo'}, num_channels=2) dummy2 = DummyPulseTemplate(parameter_names={}, num_channels=1) template = MultiChannelPulseTemplate([(dummy1, { 'foo': "bar+3" }, [0, 2]), (dummy2, {}, [1])], {'bar'}, identifier='herbert') expected_data = dict( external_parameters=['bar'], subtemplates=[ dict(template=str(id(dummy1)), parameter_mappings=dict(foo=str(Expression("bar+3"))), channel_mappings=[0, 2]), dict(template=str(id(dummy2)), parameter_mappings=dict(), channel_mappings=[1]) ]) data = template.get_serialization_data(serializer) self.assertEqual(expected_data, data)
def test_init_multi_subtemplates_interruptable_no_requires_stop( self) -> None: st1 = DummyPulseTemplate(parameter_names={'foo'}, is_interruptable=True, num_channels=2, duration=1.3) st2 = DummyPulseTemplate(parameter_names={'bar'}, is_interruptable=True, num_channels=1, duration=6.34) template = MultiChannelPulseTemplate([(st1, { 'foo': "2.3 ** bar" }, [0, 2]), (st2, { 'bar': "bar" }, [1])], {'bar'}) self.assertEqual({'bar'}, template.parameter_names) self.assertEqual({ParameterDeclaration('bar')}, template.parameter_declarations) self.assertTrue(template.is_interruptable) self.assertFalse( template.requires_stop(dict(bar=ConstantParameter(4.1)), dict())) self.assertEqual(3, template.num_channels)
def test_build_sequence(self) -> None: dummy_wf1 = DummyWaveform(duration=2.3, num_channels=2) dummy_wf2 = DummyWaveform(duration=2.3, num_channels=1) dummy1 = DummyPulseTemplate(parameter_names={'foo'}, num_channels=2, waveform=dummy_wf1) dummy2 = DummyPulseTemplate(parameter_names={}, num_channels=1, waveform=dummy_wf2) pulse = MultiChannelPulseTemplate([(dummy1, { 'foo': '2*bar' }, [2, 1]), (dummy2, {}, [0])], {'bar'}) result = pulse.build_waveform({'bar': ConstantParameter(3)}) expected = MultiChannelWaveform([(dummy_wf1, [2, 1]), (dummy_wf2, [0])]) self.assertEqual(expected, result) self.assertEqual([{ 'foo': MappedParameter(Expression("2*bar"), {'bar': ConstantParameter(3)}) }], dummy1.build_waveform_calls) self.assertEqual([{}], dummy2.build_waveform_calls)
def test_init_broken_mappings(self) -> None: st1 = DummyPulseTemplate(parameter_names={'foo'}, is_interruptable=True, num_channels=2, duration=1.3) st2 = DummyPulseTemplate(parameter_names={'bar'}, is_interruptable=True, num_channels=1, duration=6.34) with self.assertRaises(MissingMappingException): MultiChannelPulseTemplate([(st1, { 'foo': "bar" }, [0, 2]), (st2, {}, [1])], {'bar'}) with self.assertRaises(MissingMappingException): MultiChannelPulseTemplate([(st1, {}, [0, 2]), (st2, { 'bar': "bar" }, [1])], {'bar'}) with self.assertRaises(MissingParameterDeclarationException): MultiChannelPulseTemplate([(st1, { 'foo': "2.3 ** bar" }, [0, 2]), (st2, { 'bar': "bar" }, [1])], {})
def test_init_multi_subtemplates_wrong_channel_mapping(self) -> None: st1 = DummyPulseTemplate(parameter_names={'foo'}, is_interruptable=True, num_channels=2, duration=1.3) st2 = DummyPulseTemplate(parameter_names={'bar'}, is_interruptable=True, num_channels=1, duration=6.34) with self.assertRaises(ValueError): MultiChannelPulseTemplate([(st1, { 'foo': "2.3 ** bar" }, [0, 3]), (st2, { 'bar': "bar" }, [1])], {'bar'}) with self.assertRaises(ValueError): MultiChannelPulseTemplate([(st1, { 'foo': "2.3 ** bar" }, [0, -1]), (st2, { 'bar': "bar" }, [1])], {'bar'}) with self.assertRaises(ValueError): MultiChannelPulseTemplate([(st1, { 'foo': "2.3 ** bar" }, [0, 2]), (st2, { 'bar': "bar" }, [-1])], {'bar'}) with self.assertRaises(ValueError): MultiChannelPulseTemplate([(st1, { 'foo': "2.3 ** bar" }, [0, 2]), (st2, { 'bar': "bar" }, [3])], {'bar'}) with self.assertRaises(ValueError): MultiChannelPulseTemplate([(st1, { 'foo': "2.3 ** bar" }, [0, 0]), (st2, { 'bar': "bar" }, [1])], {'bar'}) with self.assertRaises(ValueError): MultiChannelPulseTemplate([(st1, { 'foo': "2.3 ** bar" }, [0, 2]), (st2, { 'bar': "bar" }, [2])], {'bar'})
def test_build_sequence_no_params(self) -> None: dummy1 = DummyPulseTemplate(parameter_names={'foo'}) pulse = MultiChannelPulseTemplate([(dummy1, { 'foo': '2*bar' }, [1]), (dummy1, { 'foo': '3' }, [0])], {'bar'}) self.assertEqual({'bar'}, pulse.parameter_names) self.assertEqual({ParameterDeclaration('bar')}, pulse.parameter_declarations) with self.assertRaises(ParameterNotProvidedException): pulse.build_waveform({}) with self.assertRaises(ParameterNotProvidedException): pulse.build_sequence(DummySequencer(), dict(), dict(), DummyInstructionBlock())