Example #1
0
 def test_defined_channels(self) -> None:
     wf = FunctionWaveform(ExpressionScalar('t'), 4, channel='A')
     self.assertEqual({'A'}, wf.defined_channels)
Example #2
0
 def calculate_duration(self) -> ExpressionScalar:
     duration_expressions = [entries[-1].t for entries in self._entries.values()]
     duration_expression = sympy.Max(*(expr.sympified_expression for expr in duration_expressions))
     return ExpressionScalar(duration_expression)
 def integral(self) -> Dict[ChannelID, ExpressionScalar]:
     return {c: ExpressionScalar('nan') for c in self.body.defined_channels}
Example #4
0
    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)
Example #5
0
 def expression(self) -> ExpressionScalar:
     return ExpressionScalar('v1')
Example #6
0
 def expression(self) -> ExpressionScalar:
     return ExpressionScalar('v0 + (v1-v0) * (t-t0)/(t1-t0)')
Example #7
0
 def test_variables(self) -> None:
     e = ExpressionScalar('4 ** pi + x * foo')
     expected = sorted(['foo', 'x'])
     received = sorted(e.variables)
     self.assertEqual(expected, received)
Example #8
0
    def __init__(self,
                 identifier: str,
                 *,
                 defined_channels: Optional[Set[ChannelID]] = None,
                 parameter_names: Optional[Set[str]] = None,
                 measurement_names: Optional[Set[str]] = None,
                 integral: Optional[Dict[ChannelID, ExpressionScalar]] = None,
                 duration: Optional[ExpressionScalar] = None,
                 registry: Optional[PulseRegistryType] = None):
        """This pulse template can be used as a place holder for a pulse template with a defined interface. Pulse
        template properties like :func:`defined_channels` can be passed on initialization to declare those properties who make
        up the interface. Omitted properties raise an :class:`.NotSpecifiedError` exception if accessed. Properties
        which have been accessed are marked as "frozen".

        The abstract pulse template can be linked to another pulse template by calling the `link_to` member. The target
        has to have the same properties for all properties marked as "frozen". This ensures a property always returns
        the same value.

        Example:
            >>> abstract_readout = AbstractPulseTemplate('readout', defined_channels={'X', 'Y'})
            >>> assert abstract_readout.defined_channels == {'X', 'Y'}
            >>> # This will raise an exception because duration is not specified
            >>> print(abstract_readout.duration)

        Args:
            identifier: Mandatory property
            defined_channels: Optional property
            parameter_names: Optional property
            measurement_names: Optional property
            integral: Optional property
            duration: Optional property
            registry: Instance is registered here if specified
        """
        super().__init__(identifier=identifier)

        self._declared_properties = {}
        self._frozen_properties = set()

        if defined_channels is not None:
            self._declared_properties['defined_channels'] = set(
                defined_channels)

        if parameter_names is not None:
            self._declared_properties['parameter_names'] = set(
                map(str, parameter_names))

        if measurement_names is not None:
            self._declared_properties['measurement_names'] = set(
                map(str, measurement_names))

        if integral is not None:
            if defined_channels is not None and integral.keys(
            ) != defined_channels:
                raise ValueError('Integral does not fit to defined channels',
                                 integral.keys(), defined_channels)
            self._declared_properties['integral'] = {
                channel: ExpressionScalar(value)
                for channel, value in integral.items()
            }

        if duration:
            self._declared_properties['duration'] = ExpressionScalar(duration)

        self._linked_target = None
        self.serialize_linked = False

        self._register(registry=registry)
    def test_integral(self):
        scalar = 'x + y'
        mapping = {'u': 'x + y', 'v': 2.2}
        pt = DummyPulseTemplate(defined_channels={'u', 'v', 'w'},
                                integrals={
                                    'u': ExpressionScalar('ui'),
                                    'v': ExpressionScalar('vi'),
                                    'w': ExpressionScalar('wi')
                                },
                                duration='t_dur')

        # commutative (+ scalar pt)
        expected = dict(u=ExpressionScalar('ui + (x + y) * t_dur'),
                        v=ExpressionScalar('vi + (x + y) * t_dur'),
                        w=ExpressionScalar('wi + (x + y) * t_dur'))
        self.assertEqual(expected,
                         ArithmeticPulseTemplate(scalar, '+', pt).integral)
        self.assertEqual(expected,
                         ArithmeticPulseTemplate(pt, '+', scalar).integral)

        # commutative (+ mapping pt)
        expected = dict(u=ExpressionScalar('ui + (x + y) * t_dur'),
                        v=ExpressionScalar('vi + 2.2 * t_dur'),
                        w=ExpressionScalar('wi'))
        self.assertEqual(expected,
                         ArithmeticPulseTemplate(mapping, '+', pt).integral)
        self.assertEqual(expected,
                         ArithmeticPulseTemplate(pt, '+', mapping).integral)

        # commutative (* scalar pt)
        expected = dict(u=ExpressionScalar('ui * (x + y)'),
                        v=ExpressionScalar('vi * (x + y)'),
                        w=ExpressionScalar('wi * (x + y)'))
        self.assertEqual(expected,
                         ArithmeticPulseTemplate(scalar, '*', pt).integral)
        self.assertEqual(expected,
                         ArithmeticPulseTemplate(pt, '*', scalar).integral)

        # commutative (* mapping pt)
        expected = dict(u=ExpressionScalar('ui * (x + y)'),
                        v=ExpressionScalar('vi * 2.2'),
                        w=ExpressionScalar('wi'))
        self.assertEqual(expected,
                         ArithmeticPulseTemplate(mapping, '*', pt).integral)
        self.assertEqual(expected,
                         ArithmeticPulseTemplate(pt, '*', mapping).integral)

        # (pt - scalar)
        expected = dict(u=ExpressionScalar('ui - (x + y) * t_dur'),
                        v=ExpressionScalar('vi - (x + y) * t_dur'),
                        w=ExpressionScalar('wi - (x + y) * t_dur'))
        self.assertEqual(expected,
                         ArithmeticPulseTemplate(pt, '-', scalar).integral)

        # (scalar - pt)
        expected = dict(u=ExpressionScalar('(x + y) * t_dur - ui'),
                        v=ExpressionScalar('(x + y) * t_dur - vi'),
                        w=ExpressionScalar('(x + y) * t_dur - wi'))
        self.assertEqual(expected,
                         ArithmeticPulseTemplate(scalar, '-', pt).integral)

        # (mapping - pt)
        expected = dict(u=ExpressionScalar('(x + y) * t_dur - ui'),
                        v=ExpressionScalar('2.2 * t_dur - vi'),
                        w=ExpressionScalar('-wi'))
        self.assertEqual(expected,
                         ArithmeticPulseTemplate(mapping, '-', pt).integral)

        # (pt - mapping)
        expected = dict(u=ExpressionScalar('ui - (x + y) * t_dur'),
                        v=ExpressionScalar('vi - 2.2 * t_dur'),
                        w=ExpressionScalar('wi'))
        self.assertEqual(expected,
                         ArithmeticPulseTemplate(pt, '-', mapping).integral)

        # (pt / scalar)
        expected = dict(u=ExpressionScalar('ui / (x + y)'),
                        v=ExpressionScalar('vi / (x + y)'),
                        w=ExpressionScalar('wi / (x + y)'))
        self.assertEqual(expected,
                         ArithmeticPulseTemplate(pt, '/', scalar).integral)

        # (pt / mapping)
        expected = dict(u=ExpressionScalar('ui / (x + y)'),
                        v=ExpressionScalar('vi / 2.2'),
                        w=ExpressionScalar('wi'))
        self.assertEqual(expected,
                         ArithmeticPulseTemplate(pt, '/', mapping).integral)
Example #10
0
 def test_evaluate_symbolic(self):
     e = ExpressionScalar('a * b + c')
     params = {'a': 'd', 'c': -7}
     result = e.evaluate_symbolic(params)
     expected = ExpressionScalar('d*b-7')
     self.assertEqual(result, expected)
Example #11
0
 def test_repr(self):
     wf = FunctionWaveform(ExpressionScalar('sin(2*pi*t) + 3'), 5, channel='A')
     r = repr(wf)
     self.assertEqual(wf, eval(r))
Example #12
0
 def test_unsafe_get_subset_for_channels(self):
     fw = FunctionWaveform(ExpressionScalar('sin(2*pi*t) + 3'), 5, channel='A')
     self.assertIs(fw.unsafe_get_subset_for_channels({'A'}), fw)
Example #13
0
 def test_duration(self) -> None:
     wf = FunctionWaveform(expression=ExpressionScalar('2*t'), duration=4/5,
                           channel='A')
     self.assertEqual(TimeType.from_float(4/5), wf.duration)
Example #14
0
 def _as_expression(self) -> Dict[ChannelID, ExpressionScalar]:
     assert self.duration != 0
     t = self._AS_EXPRESSION_TIME
     duration = self.duration.underlying_expression
     return {ch: ExpressionScalar(integral.underlying_expression*t/duration)
             for ch, integral in self.integral.items()}
Example #15
0
 def test_variables_indexed(self):
     e = ExpressionScalar('a[i] * c')
     expected = sorted(['a', 'i', 'c'])
     received = sorted(e.variables)
     self.assertEqual(expected, received)
Example #16
0
 def test_get_volatile(self):
     volatile = frozenset('ab')
     volatile_dict = FrozenDict(a=ExpressionScalar('a'), b=ExpressionScalar('b'))
     ds = DictScope(FrozenDict({'a': 1, 'b': 2}), volatile=volatile)
     self.assertEqual(volatile_dict, ds.get_volatile_parameters())
Example #17
0
 def test_evaluate_variable_missing(self) -> None:
     e = ExpressionScalar('a * b + c')
     params = {'b': 1.5}
     with self.assertRaises(ExpressionVariableMissingException):
         e.evaluate_numeric(**params)
Example #18
0
 def integral(self) -> ExpressionScalar:
     return ExpressionScalar('v1*(t1-t0)')
Example #19
0
 def test_repr(self):
     s = 'a    *    b'
     e = ExpressionScalar(s)
     self.assertEqual("Expression('a    *    b')", repr(e))
Example #20
0
 def integral(self) -> ExpressionScalar:
     return ExpressionScalar('0.5 * (t1-t0) * (v0 + v1)')
Example #21
0
 def test_str(self):
     s = 'a    *    b'
     e = ExpressionScalar(s)
     self.assertEqual('a*b', str(e))
Example #22
0
 def duration(self) -> ExpressionScalar:
     return ExpressionScalar('nan')
Example #23
0
 def test_original_expression(self):
     s = 'a    *    b'
     self.assertEqual(ExpressionScalar(s).original_expression, s)
Example #24
0
 def duration(self) -> ExpressionScalar:
     """Duration of the lhs operand if it is larger zero. Else duration of the rhs."""
     return ExpressionScalar(sympy.Max(self.lhs.duration, self.rhs.duration))
Example #25
0
    def test_is_nan(self):
        self.assertTrue(ExpressionScalar('nan').is_nan())
        self.assertTrue(ExpressionScalar('0./0.').is_nan())

        self.assertFalse(ExpressionScalar(456).is_nan())
Example #26
0
 def test_partial_evaluation(self) -> None:
     e = ExpressionScalar('a * c')
     params = {'c': 5.5}
     evaluated = e.evaluate_symbolic(params)
     expected = ExpressionScalar('a * 5.5')
     self.assertEqual(expected.underlying_expression, evaluated.underlying_expression)
Example #27
0
    def test_roll_constant_waveforms(self):
        root = Loop(waveform=ConstantWaveform.from_mapping(
            16, {
                'A': 1.,
                'B': 0.5
            }),
                    repetition_count=4)
        expected = copy.deepcopy(root)
        roll_constant_waveforms(root, 1, 16, TimeType.from_fraction(1, 1))
        self.assertEqual(root, expected)

        root = Loop(waveform=ConstantWaveform.from_mapping(
            32, {
                'A': 1.,
                'B': 0.5
            }),
                    repetition_count=4)
        expected = Loop(waveform=ConstantWaveform.from_mapping(
            16, {
                'A': 1.,
                'B': 0.5
            }),
                        repetition_count=8)
        roll_constant_waveforms(root, 1, 16, TimeType.from_fraction(1, 1))
        self.assertEqual(root, expected)

        root = Loop(waveform=ConstantWaveform.from_mapping(
            16 * 3, {
                'A': 1.,
                'B': 0.5
            }),
                    repetition_count=4)
        expected = Loop(waveform=ConstantWaveform.from_mapping(
            16, {
                'A': 1.,
                'B': 0.5
            }),
                        repetition_count=12)
        roll_constant_waveforms(root, 1, 16, TimeType.from_fraction(1, 1))
        self.assertEqual(root, expected)

        root = Loop(waveform=ConstantWaveform.from_mapping(
            16 * 3, {
                'A': 1.,
                'B': 0.5
            }),
                    repetition_count=4)
        expected = copy.deepcopy(root)
        roll_constant_waveforms(root, 2, 16, TimeType.from_fraction(1, 1))
        self.assertEqual(root, expected)

        root = Loop(waveform=ConstantWaveform.from_mapping(
            16 * 5, {
                'A': 1.,
                'B': 0.5
            }),
                    repetition_count=4)
        expected = copy.deepcopy(root)
        roll_constant_waveforms(root, 2, 16, TimeType.from_fraction(1, 1))
        self.assertEqual(root, expected)

        root = Loop(children=[
            Loop(waveform=ConstantWaveform.from_mapping(
                32, {
                    'A': 1.,
                    'B': 0.5
                }),
                 repetition_count=4),
            Loop(waveform=ConstantWaveform.from_mapping(
                16, {
                    'A': 1.,
                    'B': 0.3
                }),
                 repetition_count=4),
            Loop(waveform=ConstantWaveform.from_mapping(
                128, {
                    'A': .1,
                    'B': 0.5
                }),
                 repetition_count=2)
        ])
        expected = Loop(children=[
            Loop(waveform=ConstantWaveform.from_mapping(
                16, {
                    'A': 1.,
                    'B': 0.5
                }),
                 repetition_count=8),
            Loop(waveform=ConstantWaveform.from_mapping(
                16, {
                    'A': 1.,
                    'B': 0.3
                }),
                 repetition_count=4),
            Loop(waveform=ConstantWaveform.from_mapping(
                16, {
                    'A': .1,
                    'B': 0.5
                }),
                 repetition_count=2 * 128 // 16)
        ])
        roll_constant_waveforms(root, 1, 16, TimeType.from_fraction(1, 1))
        self.assertEqual(root, expected)

        not_constant_wf = DummyWaveform(sample_output=np.array([.1, .2, .3]),
                                        duration=TimeType.from_fraction(32, 1),
                                        defined_channels={'A', 'B'})

        root = Loop(waveform=not_constant_wf, repetition_count=4)
        expected = copy.deepcopy(root)
        roll_constant_waveforms(root, 1, 16, TimeType.from_fraction(1, 1))
        self.assertEqual(root, expected)

        scope = DictScope.from_mapping({'a': 4, 'b': 3}, volatile={'a'})
        rep_count = VolatileRepetitionCount(expression=ExpressionScalar('a+b'),
                                            scope=scope)
        root = Loop(waveform=ConstantWaveform.from_mapping(
            32, {
                'A': 1.,
                'B': 0.5
            }),
                    repetition_count=rep_count)
        expected = Loop(waveform=ConstantWaveform.from_mapping(
            16, {
                'A': 1.,
                'B': 0.5
            }),
                        repetition_count=rep_count * 2)
        self.assertNotEqual(root.repetition_count, expected.repetition_count)
        roll_constant_waveforms(root, 1, 16, TimeType.from_fraction(1, 1))
        self.assertEqual(root, expected)