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_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'}) st = MappingPulseTemplate(template, channel_mapping={'bar': 'kneipe'}) 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' })
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), external_parameters=self.outer_parameters)
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 __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) -> 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. identifier (str): A unique identifier for use in serialization. (optional) Raises: MissingMappingException, if a parameter of a subtemplate is not mapped to the external parameters of this SequencePulseTemplate. MissingParameterDeclarationException, if a parameter mapping requires a parameter that was not declared in the external parameters of this SequencePulseTemplate. """ 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: external_parameters = set(external_parameters) remaining = external_parameters.copy() for subtemplate in self.__subtemplates: missing = subtemplate.parameter_names - external_parameters if missing: raise MissingParameterDeclarationException(subtemplate, missing.pop()) remaining -= subtemplate.parameter_names if not external_parameters >= self.constrained_parameters: raise MissingParameterDeclarationException(self, (self.constrained_parameters-external_parameters).pop()) remaining -= self.constrained_parameters if remaining: raise MissingMappingException(self, remaining.pop())
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_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_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={}) with self.assertRaises(MissingMappingException): MappingPulseTemplate(template, parameter_mapping={'bar': 'kneipe'}) 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=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 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_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])
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'}))
def test_defined_channels(self): mapping = {'asd': 'A', 'fgh': 'B'} template = DummyPulseTemplate(defined_channels=set(mapping.keys())) st = MappingPulseTemplate(template, channel_mapping=mapping) self.assertEqual(st.defined_channels, set(mapping.values()))
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 ) -> None: 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: remaining = external_parameters.copy() for subtemplate in self._subtemplates: missing = subtemplate.parameter_names - external_parameters if missing: raise MissingParameterDeclarationException( subtemplate, missing.pop()) remaining -= subtemplate.parameter_names missing = self.constrained_parameters - external_parameters if missing: raise MissingParameterDeclarationException(self, missing.pop()) remaining -= self.constrained_parameters if remaining: raise MissingMappingException(self, remaining.pop()) duration = self._subtemplates[0].duration for subtemplate in self._subtemplates[1:]: if (duration == subtemplate.duration) is True: continue else: raise ValueError( 'Could not assert duration equality of {} and {}'.format( duration, subtemplate.duration))