def test_map_parameters(self): template = DummyPulseTemplate(parameter_names={'foo', 'bar'}) st = MappingPulseTemplate(template, parameter_mapping={ 'foo': 't*k', 'bar': 't*l' }) parameters = { 't': ConstantParameter(3), 'k': ConstantParameter(2), 'l': ConstantParameter(7) } values = {'foo': 6, 'bar': 21} for k, v in st.map_parameters(parameters).items(): self.assertEqual(v.get_value(), values[k]) parameters.popitem() with self.assertRaises(ParameterNotProvidedException): st.map_parameters(parameters) parameters = dict(t=3, k=2, l=7) values = {'foo': 6, 'bar': 21} for k, v in st.map_parameters(parameters).items(): self.assertEqual(v, values[k]) with self.assertRaisesRegex(ValueError, "type of return value"): st.map_parameters({}) parameters = dict(t=3, k=2, l=ConstantParameter(7)) with self.assertRaisesRegex(TypeError, "neither all Parameter nor Real"): st.map_parameters(parameters)
def test_as_expression(self): from sympy.abc import f, k, b duration = 5 dummy = DummyPulseTemplate(defined_channels={'A', 'B', 'C'}, parameter_names={'k', 'f', 'b'}, integrals={ 'A': Expression(2 * k), 'B': Expression(-3.2 * f + b), 'C': Expression(1) }, duration=duration) t = DummyPulseTemplate._AS_EXPRESSION_TIME dummy_expr = { ch: i * t / duration for ch, i in dummy._integrals.items() } pulse = MappingPulseTemplate(dummy, parameter_mapping={ 'k': 'f', 'b': 2.3 }, channel_mapping={ 'A': 'a', 'C': None }, allow_partial_parameter_mapping=True) expected = { 'a': Expression(2 * f * t / duration), 'B': Expression((-3.2 * f + 2.3) * t / duration), } self.assertEqual(expected, pulse._as_expression())
def test_create_program_invalid_measurement_mapping(self) -> None: measurement_mapping = {'meas1': 'meas2'} parameter_mapping = {'t': 'k'} channel_mapping = {'B': 'default'} template = DummyPulseTemplate(measurements=[('meas1', 0, 1)], measurement_names={'meas1'}, defined_channels={'B'}, waveform=DummyWaveform(duration=2.0), duration=2, parameter_names={'t'}) st = MappingPulseTemplate(template, parameter_mapping=parameter_mapping, measurement_mapping=measurement_mapping, channel_mapping=channel_mapping) pre_scope = DictScope.from_kwargs(k=5) pre_measurement_mapping = {} pre_channel_mapping = {'default': 'A'} program = Loop() with self.assertRaises(KeyError): st._internal_create_program(scope=pre_scope, measurement_mapping=pre_measurement_mapping, channel_mapping=pre_channel_mapping, to_single_waveform=set(), global_transformation=None, parent_loop=program)
def test_create_program_parameter_constraint_violation(self) -> None: measurement_mapping = {'meas1': 'meas2'} parameter_mapping = {'t': 'k'} channel_mapping = {'B': 'default'} template = DummyPulseTemplate(measurements=[('meas1', 0, 1)], measurement_names={'meas1'}, defined_channels={'B'}, waveform=DummyWaveform(duration=2.0), duration=2, parameter_names={'t'}) st = MappingPulseTemplate(template, parameter_mapping=parameter_mapping, measurement_mapping=measurement_mapping, channel_mapping=channel_mapping, parameter_constraints={'k > 6'}) pre_parameters = {'k': ConstantParameter(5)} pre_measurement_mapping = {'meas2': 'meas3'} pre_channel_mapping = {'default': 'A'} program = Loop() with self.assertRaises(ParameterConstraintViolation): st._internal_create_program( parameters=pre_parameters, measurement_mapping=pre_measurement_mapping, channel_mapping=pre_channel_mapping, to_single_waveform=set(), global_transformation=None, parent_loop=program)
def test_get_serialization_data(self) -> None: # test for deprecated version during transition period, remove after final switch with self.assertWarnsRegex(DeprecationWarning, "deprecated", msg="SequencePT does not issue warning for old serialization routines."): dummy_pt = DummyPulseTemplate(defined_channels={'foo'}, measurement_names={'meas'}, parameter_names={'hugo', 'herbert', 'ilse'}) mpt = MappingPulseTemplate( template=dummy_pt, parameter_mapping={'hugo': Expression('2*k+c'), 'herbert': Expression('c-1.5'), 'ilse': Expression('ilse')}, measurement_mapping={'meas': 'seam'}, channel_mapping={'foo': 'default_channel'}, parameter_constraints=[str(ParameterConstraint('c > 0'))] ) serializer = DummySerializer() expected_data = { 'template': serializer.dictify(dummy_pt), 'parameter_mapping': {'hugo': str(Expression('2*k+c')), 'herbert': str(Expression('c-1.5')), 'ilse': str(Expression('ilse'))}, 'measurement_mapping': {'meas': 'seam'}, 'channel_mapping': {'foo': 'default_channel'}, 'parameter_constraints': [str(ParameterConstraint('c > 0'))] } data = mpt.get_serialization_data(serializer=serializer) self.assertEqual(expected_data, data)
def test_nested_mapping_avoidance(self): template = DummyPulseTemplate(parameter_names={'foo', 'bar'}) st_1 = MappingPulseTemplate(template, parameter_mapping={'foo': 't*k'}, allow_partial_parameter_mapping=True) st_2 = MappingPulseTemplate(st_1, parameter_mapping={'bar': 't*l'}, allow_partial_parameter_mapping=True) self.assertIs(st_2.template, template) self.assertEqual(st_2.parameter_mapping, {'foo': 't*k', 'bar': 't*l'}) st_3 = MappingPulseTemplate(template, parameter_mapping={'foo': 't*k'}, allow_partial_parameter_mapping=True, identifier='käse') st_4 = MappingPulseTemplate(st_3, parameter_mapping={'bar': 't*l'}, allow_partial_parameter_mapping=True) self.assertIs(st_4.template, st_3) self.assertEqual(st_4.parameter_mapping, { 't': 't', 'k': 'k', 'bar': 't*l' })
def test_get_updated_measurement_mapping(self): template = DummyPulseTemplate(measurement_names={'foo', 'bar'}) st = MappingPulseTemplate(template, measurement_mapping={'bar': 'kneipe'}) with self.assertRaises(KeyError): st.get_updated_measurement_mapping(dict()) self.assertEqual(st.get_updated_measurement_mapping({'kneipe': 'meas1', 'foo': 'meas2', 'troet': 'meas3'}), {'foo': 'meas2', 'bar': 'meas1'})
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_constrained(self): template = DummyPulseTemplate(parameter_names={'foo', 'bar'}) st = MappingPulseTemplate(template, parameter_mapping={'foo': 't*k', 'bar': 't*l'}, parameter_constraints=['t < m']) external_params = {'t', 'l', 'k', 'm'} self.assertEqual(st.parameter_names, external_params) with self.assertRaises(ParameterConstraintViolation): st.map_parameters(dict(t=1, l=2, k=3, m=0))
def test_get_updated_channel_mapping(self): template = DummyPulseTemplate(defined_channels={'foo', 'bar', 'brotzeit'}) st = MappingPulseTemplate(template, channel_mapping={'bar': 'kneipe', 'brotzeit': None}) with self.assertRaises(KeyError): st.get_updated_channel_mapping(dict()) self.assertEqual(st.get_updated_channel_mapping({'kneipe': 'meas1', 'foo': 'meas2', 'troet': 'meas3'}), {'foo': 'meas2', 'bar': 'meas1', 'brotzeit': None})
def test_init_exceptions(self): template = DummyPulseTemplate(parameter_names={'foo', 'bar'}, defined_channels={'A'}, measurement_names={'B'}) parameter_mapping = {'foo': 't*k', 'bar': 't*l'} with self.assertRaises(MissingMappingException): MappingPulseTemplate(template, parameter_mapping={}, allow_partial_parameter_mapping=False) with self.assertRaises(MissingMappingException): MappingPulseTemplate(template, parameter_mapping={'bar': 'kneipe'}, allow_partial_parameter_mapping=False) with self.assertRaises(UnnecessaryMappingException): MappingPulseTemplate(template, parameter_mapping=dict(**parameter_mapping, foobar='asd')) with self.assertRaises(UnnecessaryMappingException): MappingPulseTemplate(template, parameter_mapping=parameter_mapping, measurement_mapping=dict(a='b')) with self.assertRaises(UnnecessaryMappingException): MappingPulseTemplate(template, parameter_mapping=parameter_mapping, channel_mapping=dict(a='b')) with self.assertRaises(TypeError): MappingPulseTemplate(template, parameter_mapping) MappingPulseTemplate(template, parameter_mapping={'bar': 'kneipe'}) MappingPulseTemplate(template, parameter_mapping=parameter_mapping)
def test_mapping_permutations(template: DummyPulseTemplate, pmap, mmap, cmap): direct = MappingPulseTemplate(template, parameter_mapping=pmap, measurement_mapping=mmap, channel_mapping=cmap) mappings = [m for m in [pmap, mmap, cmap] if m is not None] for current_mapping_order in itertools.permutations(mappings): mapper = MappingPulseTemplate.from_tuple((template, *current_mapping_order)) self.assertEqual(mapper.measurement_mapping, direct.measurement_mapping) self.assertEqual(mapper.channel_mapping, direct.channel_mapping) self.assertEqual(mapper.parameter_mapping, direct.parameter_mapping)
def __init__(self, *subtemplates: Union[AtomicPulseTemplate, MappingTuple, MappingPulseTemplate], identifier: Optional[str] = None, parameter_constraints: Optional[List] = None, measurements: Optional[List[MeasurementDeclaration]] = None, registry: PulseRegistryType = None, duration: Optional[ExpressionLike] = None) -> None: """Parallels multiple AtomicPulseTemplates of the same duration. If the duration keyword argument is given it is enforced that the instantiated pulse template has this duration. If duration is None the duration of the PT is the duration of the first subtemplate. There are probably changes to this behaviour in the future. Args: *subtemplates: Positional arguments are subtemplates to combine. identifier: Forwarded to AtomicPulseTemplate.__init__ parameter_constraints: Forwarded to ParameterConstrainer.__init__ measurements: Forwarded to AtomicPulseTemplate.__init__ duration: Enforced duration of the pulse template on instantiation. build_waveform checks all sub-waveforms have this duration. If True the equality of durations is only checked durtin instantiation not construction. """ AtomicPulseTemplate.__init__(self, identifier=identifier, measurements=measurements) ParameterConstrainer.__init__(self, parameter_constraints=parameter_constraints) self._subtemplates = [st if isinstance(st, PulseTemplate) else MappingPulseTemplate.from_tuple(st) for st in subtemplates] if duration in (True, False): warnings.warn("Boolean duration is deprecated since qupulse 0.6 and interpreted as None", category=DeprecationWarning, stacklevel=2) duration = None for subtemplate in self._subtemplates: if isinstance(subtemplate, AtomicPulseTemplate): continue elif isinstance(subtemplate, MappingPulseTemplate): if isinstance(subtemplate.template, AtomicPulseTemplate): continue else: raise TypeError('Non atomic subtemplate of MappingPulseTemplate: {}'.format(subtemplate.template)) else: raise TypeError('Non atomic subtemplate: {}'.format(subtemplate)) if not self._subtemplates: raise ValueError('Cannot create empty MultiChannelPulseTemplate') defined_channels = [st.defined_channels for st in self._subtemplates] # check there are no intersections between channels for i, channels_i in enumerate(defined_channels): for j, channels_j in enumerate(defined_channels[i + 1:]): if channels_i & channels_j: raise ChannelMappingException('subtemplate {}'.format(i + 1), 'subtemplate {}'.format(i + 2 + j), (channels_i & channels_j).pop()) if duration is None: self._duration = None else: self._duration = ExpressionScalar(duration) self._register(registry=registry)
def test_drop_channel(self): dummy = DummyPulseTemplate(defined_channels={'A', 'B', 'C', 'D'}, parameter_names={'k', 'f', 'b'}) pulse = MappingPulseTemplate(dummy, parameter_mapping={'k': 'f', 'b': 2.3}, channel_mapping={'A': 'a', 'C': None, 'D': None}) self.assertEqual({'a', 'B'}, pulse.defined_channels)
def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) # Setup test data self.square = TablePulseTemplate( { 'default': [(0, 0), ('up', 'v', 'hold'), ('down', 0, 'hold'), ('length', 0)] }, measurements=[('mw1', 'up', 'length-up')]) self.mapping1 = { 'up': 'uptime', 'down': 'uptime + length', 'v': 'voltage', 'length': '0.5 * pulse_length' } self.window_name_mapping = {'mw1': 'test_window'} self.outer_parameters = {'uptime', 'length', 'pulse_length', 'voltage'} self.parameters = dict() self.parameters['uptime'] = ConstantParameter(5) self.parameters['length'] = ConstantParameter(10) self.parameters['pulse_length'] = ConstantParameter(100) self.parameters['voltage'] = ConstantParameter(10) self.sequence = SequencePulseTemplate( MappingPulseTemplate(self.square, parameter_mapping=self.mapping1, measurement_mapping=self.window_name_mapping))
def test_same_channel_error(self): dpt = DummyPulseTemplate(defined_channels={'A', 'B'}) with self.assertRaisesRegex(ValueError, 'multiple channels to the same target'): MappingPulseTemplate(dpt, channel_mapping={'A': 'X', 'B': 'X'})
def test_partial_parameter_mapping(self): template = DummyPulseTemplate(parameter_names={'foo', 'bar'}) st = MappingPulseTemplate(template, parameter_mapping={'foo': 't*k'}, allow_partial_parameter_mapping=True) self.assertEqual(st.parameter_mapping, {'foo': 't*k', 'bar': 'bar'})
def test_measurement_names(self): template = DummyPulseTemplate(measurement_names={'foo', 'bar'}) st = MappingPulseTemplate(template, measurement_mapping={ 'foo': 'froop', 'bar': 'kneipe' }) self.assertEqual(st.measurement_names, {'froop', 'kneipe'})
def test_parameter_names(self) -> None: template = DummyPulseTemplate(parameter_names={'foo'}, measurement_names={'meas1'}) mt = MappingPulseTemplate(template, parameter_mapping={'foo': 't*k'}, parameter_constraints={'t >= m'}, measurement_mapping={'meas1': 'meas2'}) self.assertEqual({'t', 'k', 'm'}, mt.parameter_names)
def test_duration(self): seconds2ns = 1e9 pulse_duration = 1.0765001496284785e-07 dpt = DummyPulseTemplate(duration=Expression('duration'), parameter_names={'duration'}, defined_channels={'A'}) mpt = MappingPulseTemplate(dpt, parameter_mapping={'duration': seconds2ns * pulse_duration}) self.assertEqual(seconds2ns * pulse_duration, mpt.duration)
def test_build_sequence(self): measurement_mapping = {'meas1': 'meas2'} parameter_mapping = {'t': 'k'} template = DummyPulseTemplate( measurement_names=set(measurement_mapping.keys()), parameter_names=set(parameter_mapping.keys())) st = MappingPulseTemplate(template, parameter_mapping=parameter_mapping, measurement_mapping=measurement_mapping) sequencer = DummySequencer() block = DummyInstructionBlock() pre_parameters = {'k': ConstantParameter(5)} pre_measurement_mapping = {'meas2': 'meas3'} pre_channel_mapping = {'default': 'A'} conditions = dict(a=True) st.build_sequence(sequencer, pre_parameters, conditions, pre_measurement_mapping, pre_channel_mapping, block) self.assertEqual(template.build_sequence_calls, 1) forwarded_args = template.build_sequence_arguments[0] self.assertEqual(forwarded_args[0], sequencer) self.assertEqual(forwarded_args[1], st.map_parameters(pre_parameters)) self.assertEqual(forwarded_args[2], conditions) self.assertEqual( forwarded_args[3], st.get_updated_measurement_mapping(pre_measurement_mapping)) self.assertEqual(forwarded_args[4], st.get_updated_channel_mapping(pre_channel_mapping)) self.assertEqual(forwarded_args[5], block)
def test_external_params(self): template = DummyPulseTemplate(parameter_names={'foo', 'bar'}) st = MappingPulseTemplate(template, parameter_mapping={ 'foo': 't*k', 'bar': 't*l' }) external_params = {'t', 'l', 'k'} self.assertEqual(st.parameter_names, external_params)
def test_integral(self) -> None: dummy = DummyPulseTemplate(defined_channels={'A', 'B', 'C'}, parameter_names={'k', 'f', 'b'}, integrals={'A': Expression('2*k'), 'B': Expression('-3.2*f+b'), 'C': Expression(1)}) pulse = MappingPulseTemplate(dummy, parameter_mapping={'k': 'f', 'b': 2.3}, channel_mapping={'A': 'a', 'C': None}, allow_partial_parameter_mapping=True) self.assertEqual({'a': Expression('2*f'), 'B': Expression('-3.2*f+2.3')}, pulse.integral)
def __init__(self, *subtemplates: Union[PulseTemplate, MappingTuple], external_parameters: Optional[Union[Iterable[str], Set[str]]] = None, identifier: Optional[str] = None, parameter_constraints: Optional[List[Union[ str, Expression]]] = None, measurements: Optional[List[MeasurementDeclaration]] = None, registry: PulseRegistryType = None) -> None: """Create a new SequencePulseTemplate instance. Requires a (correctly ordered) list of subtemplates in the form (PulseTemplate, Dict(str -> str)) where the dictionary is a mapping between the external parameters exposed by this SequencePulseTemplate to the parameters declared by the subtemplates, specifying how the latter are derived from the former, i.e., the mapping is subtemplate_parameter_name -> mapping_expression (as str) where the free variables in the mapping_expression are parameters declared by this SequencePulseTemplate. The following requirements must be satisfied: - for each parameter declared by a subtemplate, a mapping expression must be provided - each free variable in a mapping expression must be declared as an external parameter of this SequencePulseTemplate Args: subtemplates (List(Subtemplate)): The list of subtemplates of this SequencePulseTemplate as tuples of the form (PulseTemplate, Dict(str -> str)). external_parameters (List(str)): A set of names for external parameters of this SequencePulseTemplate. Deprecated. identifier (str): A unique identifier for use in serialization. (optional) """ PulseTemplate.__init__(self, identifier=identifier) ParameterConstrainer.__init__( self, parameter_constraints=parameter_constraints) MeasurementDefiner.__init__(self, measurements=measurements) self.__subtemplates = [ MappingPulseTemplate.from_tuple(st) if isinstance(st, tuple) else st for st in subtemplates ] # check that all subtemplates live on the same channels defined_channels = self.__subtemplates[0].defined_channels for subtemplate in self.__subtemplates[1:]: if subtemplate.defined_channels != defined_channels: raise ValueError( 'The subtemplates are defined for different channels') if external_parameters: warnings.warn( "external_parameters is an obsolete argument and will be removed in the future.", category=DeprecationWarning) self._register(registry=registry)
def test_create_program_subtemplate_none(self) -> None: measurement_mapping = {'meas1': 'meas2'} parameter_mapping = {'t': 'k'} channel_mapping = {'B': 'default'} template = DummyPulseTemplate(measurements=[('meas1', 0, 1)], measurement_names={'meas1'}, defined_channels={'B'}, waveform=None, duration=0, parameter_names={'t'}) st = MappingPulseTemplate(template, parameter_mapping=parameter_mapping, measurement_mapping=measurement_mapping, channel_mapping=channel_mapping) pre_parameters = {'k': ConstantParameter(5)} pre_measurement_mapping = {'meas2': 'meas3'} pre_channel_mapping = {'default': 'A'} program = Loop() st._internal_create_program( parameters=pre_parameters, measurement_mapping=pre_measurement_mapping, channel_mapping=pre_channel_mapping, to_single_waveform=set(), global_transformation=None, parent_loop=program) self.assertEqual(1, len(template.create_program_calls)) self.assertEqual( (st.map_parameters(pre_parameters), st.get_updated_measurement_mapping(pre_measurement_mapping), st.get_updated_channel_mapping(pre_channel_mapping), program), template.create_program_calls[-1]) self.assertEqual(1, program.repetition_count) self.assertEqual(0, len(program.children)) self.assertIsNone(program._measurements) # ensure same result as from Sequencer sequencer = Sequencer() sequencer.push(st, parameters=pre_parameters, conditions={}, window_mapping=pre_measurement_mapping, channel_mapping=pre_channel_mapping) block = sequencer.build() program_old = MultiChannelProgram( block, channels={'A'}).programs[frozenset({'A'})] self.assertEqual(program_old, program)
def test_create_program(self) -> None: measurement_mapping = {'meas1': 'meas2'} parameter_mapping = {'t': 'k'} channel_mapping = {'B': 'default'} global_transformation = TransformationStub() to_single_waveform = {'tom', 'jerry'} template = DummyPulseTemplate(measurements=[('meas1', 0, 1)], measurement_names={'meas1'}, defined_channels={'B'}, waveform=DummyWaveform(duration=2.0), duration=2, parameter_names={'t'}) st = MappingPulseTemplate(template, parameter_mapping=parameter_mapping, measurement_mapping=measurement_mapping, channel_mapping=channel_mapping) pre_parameters = {'k': ConstantParameter(5)} pre_measurement_mapping = {'meas2': 'meas3'} pre_channel_mapping = {'default': 'A'} program = Loop() expected_inner_args = dict( parameters=st.map_parameters(pre_parameters), measurement_mapping=st.get_updated_measurement_mapping( pre_measurement_mapping), channel_mapping=st.get_updated_channel_mapping( pre_channel_mapping), to_single_waveform=to_single_waveform, global_transformation=global_transformation, parent_loop=program) with mock.patch.object(template, '_create_program') as inner_create_program: st._internal_create_program( parameters=pre_parameters, measurement_mapping=pre_measurement_mapping, channel_mapping=pre_channel_mapping, to_single_waveform=to_single_waveform, global_transformation=global_transformation, parent_loop=program) inner_create_program.assert_called_once_with(**expected_inner_args) # as we mock the inner function there shouldnt be any changes self.assertEqual(program, Loop())
def test_deserialize(self) -> None: # test for deprecated version during transition period, remove after final switch with self.assertWarnsRegex( DeprecationWarning, "deprecated", msg= "SequencePT does not issue warning for old serialization routines." ): dummy_pt = DummyPulseTemplate( defined_channels={'foo'}, measurement_names={'meas'}, parameter_names={'hugo', 'herbert', 'ilse'}) serializer = DummySerializer() data = { 'template': serializer.dictify(dummy_pt), 'parameter_mapping': { 'hugo': str(Expression('2*k+c')), 'herbert': str(Expression('c-1.5')), 'ilse': str(Expression('ilse')) }, 'measurement_mapping': { 'meas': 'seam' }, 'channel_mapping': { 'foo': 'default_channel' }, 'parameter_constraints': [str(ParameterConstraint('c > 0'))] } deserialized = MappingPulseTemplate.deserialize( serializer=serializer, **data) self.assertIsInstance(deserialized, MappingPulseTemplate) self.assertEqual(data['parameter_mapping'], deserialized.parameter_mapping) self.assertEqual(data['channel_mapping'], deserialized.channel_mapping) self.assertEqual(data['measurement_mapping'], deserialized.measurement_mapping) self.assertEqual( data['parameter_constraints'], [str(pc) for pc in deserialized.parameter_constraints]) self.assertIs(deserialized.template, dummy_pt)
def test_create_program_subtemplate_none(self) -> None: measurement_mapping = {'meas1': 'meas2'} parameter_mapping = {'t': 'k'} channel_mapping = {'B': 'default'} volatile = {'t'} template = DummyPulseTemplate(measurements=[('meas1', 0, 1)], measurement_names={'meas1'}, defined_channels={'B'}, waveform=None, duration=0, parameter_names={'t'}) st = MappingPulseTemplate(template, parameter_mapping=parameter_mapping, measurement_mapping=measurement_mapping, channel_mapping=channel_mapping) pre_scope = DictScope.from_kwargs(k=5, volatile=volatile) pre_measurement_mapping = {'meas2': 'meas3'} pre_channel_mapping = {'default': 'A'} program = Loop() st._internal_create_program( scope=pre_scope, measurement_mapping=pre_measurement_mapping, channel_mapping=pre_channel_mapping, to_single_waveform=set(), global_transformation=None, parent_loop=program) self.assertEqual(1, len(template.create_program_calls)) self.assertEqual( (st.map_scope(pre_scope), st.get_updated_measurement_mapping(pre_measurement_mapping), st.get_updated_channel_mapping(pre_channel_mapping), program), template.create_program_calls[-1]) self.assertEqual(1, program.repetition_count) self.assertEqual(0, len(program.children)) self.assertIsNone(program._measurements)
def __init__(self, *subtemplates: Union[AtomicPulseTemplate, MappingTuple, MappingPulseTemplate], external_parameters: Optional[Set[str]] = None, identifier: Optional[str] = None, parameter_constraints: Optional[List] = None, measurements: Optional[List[MeasurementDeclaration]] = None, registry: PulseRegistryType = None, duration: Union[str, Expression, bool] = False) -> None: """Parallels multiple AtomicPulseTemplates of the same duration. The duration equality check is performed on construction by default. If the duration keyword argument is given the check is performed on instantiation (when build_waveform is called). duration can be a Expression to enforce a certain duration or True for an unspecified duration. Args: *subtemplates: Positional arguments are subtemplates to combine. identifier: Forwarded to AtomicPulseTemplate.__init__ parameter_constraints: Forwarded to ParameterConstrainer.__init__ measurements: Forwarded to AtomicPulseTemplate.__init__ duration: Enforced duration of the pulse template on instantiation. build_waveform checks all sub-waveforms have this duration. If True the equality of durations is only checked durtin instantiation not construction. external_parameters: No functionality. (Deprecated) """ AtomicPulseTemplate.__init__(self, identifier=identifier, measurements=measurements) ParameterConstrainer.__init__( self, parameter_constraints=parameter_constraints) self._subtemplates = [ st if isinstance(st, PulseTemplate) else MappingPulseTemplate.from_tuple(st) for st in subtemplates ] for subtemplate in self._subtemplates: if isinstance(subtemplate, AtomicPulseTemplate): continue elif isinstance(subtemplate, MappingPulseTemplate): if isinstance(subtemplate.template, AtomicPulseTemplate): continue else: raise TypeError( 'Non atomic subtemplate of MappingPulseTemplate: {}'. format(subtemplate.template)) else: raise TypeError( 'Non atomic subtemplate: {}'.format(subtemplate)) if not self._subtemplates: raise ValueError('Cannot create empty MultiChannelPulseTemplate') defined_channels = [st.defined_channels for st in self._subtemplates] # check there are no intersections between channels for i, channels_i in enumerate(defined_channels): for j, channels_j in enumerate(defined_channels[i + 1:]): if channels_i & channels_j: raise ChannelMappingException( 'subtemplate {}'.format(i + 1), 'subtemplate {}'.format(i + 2 + j), (channels_i | channels_j).pop()) if external_parameters is not None: warnings.warn( "external_parameters is an obsolete argument and will be removed in the future.", category=DeprecationWarning) if not duration: duration = self._subtemplates[0].duration for subtemplate in self._subtemplates[1:]: if almost_equal(duration.sympified_expression, subtemplate.duration.sympified_expression): continue else: raise ValueError( 'Could not assert duration equality of {} and {}'. format(duration, subtemplate.duration)) self._duration = None elif duration is True: self._duration = None else: self._duration = ExpressionScalar(duration) self._register(registry=registry)
def test_from_tuple_exceptions(self): template = DummyPulseTemplate(parameter_names={'foo', 'bar'}, measurement_names={'foo', 'foobar'}, defined_channels={'bar', 'foobar'}) with self.assertRaises(ValueError): MappingPulseTemplate.from_tuple((template, {'A': 'B'})) with self.assertRaises(AmbiguousMappingException): MappingPulseTemplate.from_tuple((template, {'foo': 'foo'})) with self.assertRaises(AmbiguousMappingException): MappingPulseTemplate.from_tuple((template, {'bar': 'bar'})) with self.assertRaises(AmbiguousMappingException): MappingPulseTemplate.from_tuple((template, {'foobar': 'foobar'})) template = DummyPulseTemplate(parameter_names={'foo', 'bar'}) with self.assertRaises(MappingCollisionException): MappingPulseTemplate.from_tuple((template, { 'foo': '1', 'bar': 2 }, { 'foo': '1', 'bar': 4 })) template = DummyPulseTemplate(defined_channels={'A'}) with self.assertRaises(MappingCollisionException): MappingPulseTemplate.from_tuple((template, {'A': 'N'}, {'A': 'C'})) template = DummyPulseTemplate(measurement_names={'M'}) with self.assertRaises(MappingCollisionException): MappingPulseTemplate.from_tuple((template, {'M': 'N'}, {'M': 'N'}))