Esempio n. 1
0
    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)
Esempio n. 2
0
    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)
Esempio n. 3
0
        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],
                 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'}))