예제 #1
0
    def test_duration(self):
        dt = DummyPulseTemplate(parameter_names={'idx', 'd'},
                                duration=Expression('d+idx*2'))

        flt = ForLoopPulseTemplate(body=dt, loop_index='idx', loop_range='n')
        self.assertEqual(flt.duration.evaluate_numeric(n=4, d=100),
                         4 * 100 + 2 * (1 + 2 + 3))

        flt = ForLoopPulseTemplate(body=dt,
                                   loop_index='idx',
                                   loop_range=(3, 'n', 2))
        self.assertEqual(flt.duration.evaluate_numeric(n=9, d=100),
                         3 * 100 + 2 * (3 + 5 + 7))
        self.assertEqual(flt.duration.evaluate_numeric(n=8, d=100),
                         3 * 100 + 2 * (3 + 5 + 7))

        flt = ForLoopPulseTemplate(body=dt,
                                   loop_index='idx',
                                   loop_range=('m', 'n', -2))
        self.assertEqual(flt.duration.evaluate_numeric(n=9, d=100, m=14),
                         3 * 100 + 2 * (14 + 12 + 10))

        flt = ForLoopPulseTemplate(body=dt,
                                   loop_index='idx',
                                   loop_range=('m', 'n', -2))
        self.assertEqual(flt.duration.evaluate_numeric(n=9, d=100, m=14),
                         3 * 100 + 2 * (14 + 12 + 10))
예제 #2
0
    def test_create_program_append(self) -> None:
        dt = DummyPulseTemplate(parameter_names={'i'}, waveform=DummyWaveform(duration=4.0), duration=4,
                                measurements=[('b', 2, 1)])
        flt = ForLoopPulseTemplate(body=dt, loop_index='i', loop_range=('a', 'b', 'c'),
                                   measurements=[('A', 0, 1)], parameter_constraints=['c > 1'])

        scope = DictScope.from_kwargs(a=1, b=4, c=2, volatile={'inner'})
        measurement_mapping = dict(A='B', b='b')
        channel_mapping = dict(C='D')

        children = [Loop(waveform=DummyWaveform(duration=2.0))]
        program = Loop(children=children)
        flt._internal_create_program(scope=scope,
                                     measurement_mapping=measurement_mapping,
                                     channel_mapping=channel_mapping,
                                     parent_loop=program,
                                     to_single_waveform=set(),
                                     global_transformation=None)

        self.assertEqual(3, len(program.children))
        self.assertIs(children[0], program.children[0])
        self.assertEqual(dt.waveform, program.children[1].waveform)
        self.assertEqual(dt.waveform, program.children[2].waveform)
        self.assertEqual(1, program.children[1].repetition_count)
        self.assertEqual(1, program.children[2].repetition_count)
        self.assertEqual(1, program.repetition_count)
        self.assert_measurement_windows_equal({'b': ([4, 8], [1, 1]), 'B': ([2], [1])}, program.get_measurement_windows())
예제 #3
0
    def test_body_scope_generator(self):
        dt = DummyPulseTemplate(parameter_names={'i', 'k'})
        flt = ForLoopPulseTemplate(body=dt,
                                   loop_index='i',
                                   loop_range=('a', 'b', 'c'))

        expected_range = range(2, 17, 3)
        outer_scope = DictScope.from_kwargs(k=5,
                                            a=expected_range.start,
                                            b=expected_range.stop,
                                            c=expected_range.step,
                                            volatile={'i', 'j'})

        forward_scopes = list(
            flt._body_scope_generator(outer_scope, forward=True))
        backward_scopes = list(
            flt._body_scope_generator(outer_scope, forward=False))
        volatile_dict = FrozenDict(j=ExpressionScalar('j'))

        self.assertEqual(forward_scopes, list(reversed(backward_scopes)))

        for scope, i in zip(forward_scopes, expected_range):
            self.assertEqual(volatile_dict, scope.get_volatile_parameters())

            expected_dict_equivalent = dict(k=5,
                                            i=i,
                                            a=expected_range.start,
                                            b=expected_range.stop,
                                            c=expected_range.step)
            self.assertEqual(expected_dict_equivalent, dict(scope.items()))
예제 #4
0
 def test_loop_index(self):
     loop_index = 'i'
     dt = DummyPulseTemplate(parameter_names={'i', 'k'})
     flt = ForLoopPulseTemplate(body=dt,
                                loop_index=loop_index,
                                loop_range=('a', 'b', 'c'))
     self.assertIs(loop_index, flt.loop_index)
예제 #5
0
    def test_create_program_invalid_params(self) -> None:
        dt = DummyPulseTemplate(parameter_names={'i'},
                                waveform=DummyWaveform(duration=4.0),
                                duration=4,
                                measurements=[('b', 2, 1)])
        flt = ForLoopPulseTemplate(body=dt,
                                   loop_index='i',
                                   loop_range=('a', 'b', 'c'),
                                   measurements=[('A', 0, 1)],
                                   parameter_constraints=['c > 1'])

        invalid_scope = DictScope.from_kwargs(a=0, b=2, c=1)
        measurement_mapping = dict(A='B')
        channel_mapping = dict(C='D')

        children = [Loop(waveform=DummyWaveform(duration=2.0))]
        program = Loop(children=children)
        with self.assertRaises(ParameterConstraintViolation):
            flt._internal_create_program(
                scope=invalid_scope,
                measurement_mapping=measurement_mapping,
                channel_mapping=channel_mapping,
                parent_loop=program,
                to_single_waveform=set(),
                global_transformation=None)

        self.assertEqual(children, list(program.children))
        self.assertEqual(1, program.repetition_count)
        self.assertIsNone(program._measurements)
        self.assert_measurement_windows_equal(
            {}, program.get_measurement_windows())
예제 #6
0
    def test_create_program_body_none(self) -> None:
        dt = DummyPulseTemplate(parameter_names={'i'},
                                waveform=None,
                                duration=0,
                                measurements=[('b', 2, 1)])
        flt = ForLoopPulseTemplate(body=dt,
                                   loop_index='i',
                                   loop_range=('a', 'b', 'c'),
                                   measurements=[('A', 0, 1)],
                                   parameter_constraints=['c > 1'])

        scope = DictScope.from_kwargs(a=1, b=4, c=2)
        measurement_mapping = dict(A='B', b='b')
        channel_mapping = dict(C='D')

        program = Loop()
        flt._internal_create_program(scope=scope,
                                     measurement_mapping=measurement_mapping,
                                     channel_mapping=channel_mapping,
                                     parent_loop=program,
                                     to_single_waveform=set(),
                                     global_transformation=None)

        self.assertEqual(0, len(program.children))
        self.assertEqual(1, program.repetition_count)
        self.assertEqual([], list(program.children))
예제 #7
0
    def test_get_serialization_data_all_features_old(self) -> None:
        # test for deprecated version during transition period, remove after final switch
        with self.assertWarnsRegex(
                DeprecationWarning,
                "deprecated",
                msg=
                "ForLoopPT does not issue warning for old serialization routines."
        ):
            measurements = [('a', 0, 1), ('b', 1, 1)]
            parameter_constraints = ['foo < 3']

            dt = DummyPulseTemplate(parameter_names={'i'})
            flt = ForLoopPulseTemplate(
                body=dt,
                loop_index='i',
                loop_range=('A', 'B'),
                measurements=measurements,
                parameter_constraints=parameter_constraints)

            def check_dt(to_dictify) -> str:
                self.assertIs(to_dictify, dt)
                return 'dt'

            serializer = DummySerializer(serialize_callback=check_dt)

            data = flt.get_serialization_data(serializer)
            expected_data = dict(body='dt',
                                 loop_range=('A', 'B', 1),
                                 loop_index='i',
                                 measurements=measurements,
                                 parameter_constraints=parameter_constraints)
            self.assertEqual(data, expected_data)
예제 #8
0
    def test_create_program_constraint_on_loop_var_exception(self):
        """This test is to assure the status-quo behavior of ForLoopPT handling parameter constraints affecting the loop index
        variable. Please see https://github.com/qutech/qupulse/issues/232 ."""

        with self.assertWarnsRegex(UserWarning, "constraint on a variable shadowing the loop index",
                                   msg="ForLoopPT did not issue a warning when constraining the loop index"):
            flt = ForLoopPulseTemplate(body=DummyPulseTemplate(parameter_names={'k', 'i'}), loop_index='i',
                                       loop_range=('a', 'b', 'c',), parameter_constraints=['k<=f', 'k>i'])

        # loop index showing up in parameter_names because it appears in consraints
        self.assertEqual(flt.parameter_names, {'f', 'k', 'a', 'b', 'c', 'i'})

        scope = DictScope.from_kwargs(k=1, a=0, b=2, c=1, f=2)

        # loop index not accessible in current build_sequence -> Exception
        children = [Loop(waveform=DummyWaveform(duration=2.0))]
        program = Loop(children=children)

        with self.assertRaises(ParameterNotProvidedException):
            flt._internal_create_program(scope=scope,
                                         measurement_mapping=dict(),
                                         channel_mapping=dict(),
                                         parent_loop=program,
                                         to_single_waveform=set(),
                                         global_transformation=None)
        self.assertEqual(children, list(program.children))
        self.assertEqual(1, program.repetition_count)
        self.assertIsNone(program._measurements)
        self.assert_measurement_windows_equal({}, program.get_measurement_windows())
예제 #9
0
 def test_issue_612_for_loop_duration(self):
     fpt = FunctionPulseTemplate('sin(2*pi*i*t*f)', '1/f')
     pt = ForLoopPulseTemplate(fpt, 'i', 'floor(total_time*f)')
     self.assertEqual((500 + 501) // 2,
                      pt.duration.evaluate_in_scope({
                          'f': 1.,
                          'total_time': 500
                      }))
예제 #10
0
 def test_parameter_names(self):
     dt = DummyPulseTemplate(parameter_names={'i', 'k'})
     flt = ForLoopPulseTemplate(body=dt,
                                loop_index='i',
                                loop_range=('a', 'b', 'c'),
                                parameter_constraints={'c > hugo'},
                                measurements=[('meas', 'd', 1)])
     self.assertEqual({'k', 'a', 'b', 'c', 'd', 'hugo'},
                      flt.parameter_names)
예제 #11
0
    def test_integral(self) -> None:
        dummy = DummyPulseTemplate(defined_channels={'A', 'B'},
                                   parameter_names={'t1', 'i'},
                                   integrals={'A': ExpressionScalar('t1-i*3.1'), 'B': ExpressionScalar('i')})

        pulse = ForLoopPulseTemplate(dummy, 'i', (1, 8, 2))

        expected = {'A': ExpressionScalar('Sum(t1-3.1*(1+2*i), (i, 0, 3))'),
                    'B': ExpressionScalar('Sum((1+2*i), (i, 0, 3))') }
        self.assertEqual(expected, pulse.integral)
예제 #12
0
 def test_parameter_names_param_only_in_constraint(self) -> None:
     flt = ForLoopPulseTemplate(
         body=DummyPulseTemplate(parameter_names={'k', 'i'}),
         loop_index='i',
         loop_range=(
             'a',
             'b',
             'c',
         ),
         parameter_constraints=['k<=f'])
     self.assertEqual(flt.parameter_names, {'k', 'a', 'b', 'c', 'f'})
예제 #13
0
    def test_requires_stop(self):
        parameters = dict(A=DummyParameter(requires_stop=False),
                          B=DummyParameter(requires_stop=False))

        dt = DummyPulseTemplate(parameter_names={'i'})
        flt = ForLoopPulseTemplate(body=dt,
                                   loop_index='i',
                                   loop_range=('A', 'B'))

        self.assertFalse(flt.requires_stop(parameters, dict()))

        parameters['A'] = DummyParameter(requires_stop=True)
        self.assertTrue(flt.requires_stop(parameters, dict()))
예제 #14
0
    def test_create_program_invalid_measurement_mapping(self) -> None:
        dt = DummyPulseTemplate(parameter_names={'i'},
                                waveform=DummyWaveform(duration=4.0),
                                duration=4,
                                measurements=[('b', 2, 1)])
        flt = ForLoopPulseTemplate(body=dt,
                                   loop_index='i',
                                   loop_range=('a', 'b', 'c'),
                                   measurements=[('A', 0, 1)],
                                   parameter_constraints=['c > 1'])

        invalid_parameters = {
            'a': ConstantParameter(1),
            'b': ConstantParameter(4),
            'c': ConstantParameter(2)
        }
        measurement_mapping = dict()
        channel_mapping = dict(C='D')

        children = [Loop(waveform=DummyWaveform(duration=2.0))]
        program = Loop(children=children)
        with self.assertRaises(KeyError):
            flt._internal_create_program(
                parameters=invalid_parameters,
                measurement_mapping=measurement_mapping,
                channel_mapping=channel_mapping,
                parent_loop=program,
                to_single_waveform=set(),
                global_transformation=None)

        self.assertEqual(children, program.children)
        self.assertEqual(1, program.repetition_count)
        self.assertIsNone(program._measurements)
        self.assert_measurement_windows_equal(
            {}, program.get_measurement_windows())

        # test for broken mapping on child level. no guarantee that parent_loop is not changed, only check for exception
        measurement_mapping = dict(A='B')
        with self.assertRaises(KeyError):
            flt._internal_create_program(
                parameters=invalid_parameters,
                measurement_mapping=measurement_mapping,
                channel_mapping=channel_mapping,
                parent_loop=program,
                to_single_waveform=set(),
                global_transformation=None)
예제 #15
0
    def test_create_program(self) -> None:
        dt = DummyPulseTemplate(parameter_names={'i'},
                                waveform=DummyWaveform(duration=4.0, defined_channels={'A'}),
                                duration=4,
                                measurements=[('b', .2, .3)])
        flt = ForLoopPulseTemplate(body=dt, loop_index='i', loop_range=('a', 'b', 'c'),
                                   measurements=[('A', 'meas_param', 1)], parameter_constraints=['c > 1'])

        scope = DictScope.from_kwargs(a=1, b=4, c=2, meas_param=.1, volatile={'inner'})
        measurement_mapping = dict(A='B', b='b')
        channel_mapping = dict(C='D')

        to_single_waveform = {'tom', 'jerry'}
        global_transformation = TransformationStub()

        program = Loop()

        # inner _create_program does nothing
        expected_program = Loop(measurements=[('B', .1, 1)])

        expected_create_program_kwargs = dict(measurement_mapping=measurement_mapping,
                                              channel_mapping=channel_mapping,
                                              global_transformation=global_transformation,
                                              to_single_waveform=to_single_waveform,
                                              parent_loop=program)
        expected_create_program_calls = [mock.call(**expected_create_program_kwargs,
                                                   scope=scope.overwrite(dict(i=i)))
                                         for i in (1, 3)]

        with mock.patch.object(flt, 'validate_scope') as validate_scope:
            with mock.patch.object(dt, '_create_program') as body_create_program:
                with mock.patch.object(flt, 'get_measurement_windows',
                                       wraps=flt.get_measurement_windows) as get_measurement_windows:
                    flt._internal_create_program(scope=scope,
                                                 measurement_mapping=measurement_mapping,
                                                 channel_mapping=channel_mapping,
                                                 parent_loop=program,
                                                 to_single_waveform=to_single_waveform,
                                                 global_transformation=global_transformation)

                    validate_scope.assert_called_once_with(scope=scope)
                    get_measurement_windows.assert_called_once_with(scope, measurement_mapping)
                    self.assertEqual(body_create_program.call_args_list, expected_create_program_calls)

        self.assertEqual(expected_program, program)
예제 #16
0
    def test_create_program_body_none(self) -> None:
        dt = DummyPulseTemplate(parameter_names={'i'},
                                waveform=None,
                                duration=0,
                                measurements=[('b', 2, 1)])
        flt = ForLoopPulseTemplate(body=dt,
                                   loop_index='i',
                                   loop_range=('a', 'b', 'c'),
                                   measurements=[('A', 0, 1)],
                                   parameter_constraints=['c > 1'])

        parameters = {
            'a': ConstantParameter(1),
            'b': ConstantParameter(4),
            'c': ConstantParameter(2)
        }
        measurement_mapping = dict(A='B', b='b')
        channel_mapping = dict(C='D')

        program = Loop()
        flt._internal_create_program(parameters=parameters,
                                     measurement_mapping=measurement_mapping,
                                     channel_mapping=channel_mapping,
                                     parent_loop=program,
                                     to_single_waveform=set(),
                                     global_transformation=None)

        self.assertEqual(0, len(program.children))
        self.assertEqual(1, program.repetition_count)
        self.assertEqual([], program.children)

        # ensure same result as from Sequencer
        sequencer = Sequencer()
        sequencer.push(flt,
                       parameters=parameters,
                       conditions={},
                       window_mapping=measurement_mapping,
                       channel_mapping=channel_mapping)
        block = sequencer.build()
        program_old = MultiChannelProgram(
            block, channels={'A'}).programs[frozenset({'A'})]
        self.assertEqual(program_old.repetition_count,
                         program.repetition_count)
        self.assertEqual(program_old.children, program.children)
        self.assertEqual(program_old.waveform, program.waveform)
예제 #17
0
    def test_build_sequence(self):
        dt = DummyPulseTemplate(parameter_names={'i'})
        flt = ForLoopPulseTemplate(body=dt,
                                   loop_index='i',
                                   loop_range=('a', 'b', 'c'),
                                   measurements=[('A', 0, 1)],
                                   parameter_constraints=['c > 1'])

        sequencer = DummySequencer()
        block = DummyInstructionBlock()
        invalid_parameters = {
            'a': ConstantParameter(1),
            'b': ConstantParameter(4),
            'c': ConstantParameter(1)
        }
        parameters = {
            'a': ConstantParameter(1),
            'b': ConstantParameter(4),
            'c': ConstantParameter(2)
        }
        measurement_mapping = dict(A='B')
        channel_mapping = dict(C='D')

        with self.assertRaises(ParameterConstraintViolation):
            flt.build_sequence(sequencer, invalid_parameters, dict(),
                               measurement_mapping, channel_mapping, block)

        self.assertEqual(block.instructions, [])
        self.assertNotIn(block, sequencer.sequencing_stacks)

        flt.build_sequence(sequencer, parameters, dict(), measurement_mapping,
                           channel_mapping, block)

        self.assertEqual(block.instructions,
                         [MEASInstruction(measurements=[('B', 0, 1)])])

        expected_stack = [(dt, {
            'i': ConstantParameter(3)
        }, dict(), measurement_mapping, channel_mapping),
                          (dt, {
                              'i': ConstantParameter(1)
                          }, dict(), measurement_mapping, channel_mapping)]

        self.assertEqual(sequencer.sequencing_stacks[block], expected_stack)
예제 #18
0
    def test_init(self):
        dt = DummyPulseTemplate(parameter_names={'i', 'k'})
        self.assertEqual(
            ForLoopPulseTemplate(body=dt, loop_index='i',
                                 loop_range=5).loop_range.to_tuple(),
            (0, 5, 1))
        self.assertEqual(
            ForLoopPulseTemplate(body=dt, loop_index='i',
                                 loop_range='s').loop_range.to_tuple(),
            (0, 's', 1))
        self.assertEqual(
            ForLoopPulseTemplate(body=dt, loop_index='i',
                                 loop_range=(2, 5)).loop_range.to_tuple(),
            (2, 5, 1))
        self.assertEqual(
            ForLoopPulseTemplate(body=dt,
                                 loop_index='i',
                                 loop_range=range(1, 2,
                                                  5)).loop_range.to_tuple(),
            (1, 2, 5))
        self.assertEqual(
            ForLoopPulseTemplate(body=dt,
                                 loop_index='i',
                                 loop_range=ParametrizedRange(
                                     'a', 'b', 'c')).loop_range.to_tuple(),
            ('a', 'b', 'c'))

        with self.assertRaises(InvalidParameterNameException):
            ForLoopPulseTemplate(body=dt, loop_index='1i', loop_range=6)

        with self.assertRaises(ValueError):
            ForLoopPulseTemplate(body=dt,
                                 loop_index='i',
                                 loop_range=slice(None))

        with self.assertRaises(LoopIndexNotUsedException):
            ForLoopPulseTemplate(body=DummyPulseTemplate(),
                                 loop_index='i',
                                 loop_range=1)
예제 #19
0
    def test_body_parameter_generator(self):
        dt = DummyPulseTemplate(parameter_names={'i', 'k'})
        flt = ForLoopPulseTemplate(body=dt,
                                   loop_index='i',
                                   loop_range=('a', 'b', 'c'))

        expected_range = range(2, 17, 3)

        outer_params = dict(k=ConstantParameter(5),
                            a=ConstantParameter(expected_range.start),
                            b=ConstantParameter(expected_range.stop),
                            c=ConstantParameter(expected_range.step))
        forward_parameter_dicts = list(
            flt._body_parameter_generator(outer_params, forward=True))
        backward_parameter_dicts = list(
            flt._body_parameter_generator(outer_params, forward=False))

        self.assertEqual(forward_parameter_dicts,
                         list(reversed(backward_parameter_dicts)))
        for local_params, i in zip(forward_parameter_dicts, expected_range):
            expected_local_params = dict(k=ConstantParameter(5),
                                         i=ConstantParameter(i))
            self.assertEqual(expected_local_params, local_params)
예제 #20
0
    def test_build_sequence_constraint_on_loop_var_exception(self):
        """This test is to assure the status-quo behavior of ForLoopPT handling parameter constraints affecting the loop index
        variable. Please see https://github.com/qutech/qupulse/issues/232 ."""

        with self.assertWarnsRegex(
                UserWarning,
                "constraint on a variable shadowing the loop index",
                msg=
                "ForLoopPT did not issue a warning when constraining the loop index"
        ):
            flt = ForLoopPulseTemplate(
                body=DummyPulseTemplate(parameter_names={'k', 'i'}),
                loop_index='i',
                loop_range=(
                    'a',
                    'b',
                    'c',
                ),
                parameter_constraints=['k<=f', 'k>i'])

        # loop index showing up in parameter_names because it appears in consraints
        self.assertEqual(flt.parameter_names, {'f', 'k', 'a', 'b', 'c', 'i'})

        parameters = {
            'k': ConstantParameter(1),
            'a': ConstantParameter(0),
            'b': ConstantParameter(2),
            'c': ConstantParameter(1),
            'f': ConstantParameter(2)
        }
        sequencer = DummySequencer()
        block = DummyInstructionBlock()

        # loop index not accessible in current build_sequence -> Exception
        self.assertRaises(ParameterNotProvidedException, flt.build_sequence,
                          sequencer, parameters, dict(), dict(), dict(), block)
예제 #21
0
    def test_create_program_missing_params(self) -> None:
        dt = DummyPulseTemplate(parameter_names={'i'},
                                waveform=DummyWaveform(duration=4.0),
                                duration='t',
                                measurements=[('b', 2, 1)])
        flt = ForLoopPulseTemplate(body=dt,
                                   loop_index='i',
                                   loop_range=('a', 'b', 'c'),
                                   measurements=[('A', 'alph', 1)],
                                   parameter_constraints=['c > 1'])

        parameters = {'a': ConstantParameter(1), 'b': ConstantParameter(4)}
        measurement_mapping = dict(A='B')
        channel_mapping = dict(C='D')

        children = [Loop(waveform=DummyWaveform(duration=2.0))]
        program = Loop(children=children)

        # test parameter in constraints
        with self.assertRaises(ParameterNotProvidedException):
            flt._internal_create_program(
                parameters=parameters,
                measurement_mapping=measurement_mapping,
                channel_mapping=channel_mapping,
                parent_loop=program,
                to_single_waveform=set(),
                global_transformation=None)

        # test parameter in measurement mappings
        parameters = {
            'a': ConstantParameter(1),
            'b': ConstantParameter(4),
            'c': ConstantParameter(2)
        }
        with self.assertRaises(ParameterNotProvidedException):
            flt._internal_create_program(
                parameters=parameters,
                measurement_mapping=measurement_mapping,
                channel_mapping=channel_mapping,
                parent_loop=program,
                to_single_waveform=set(),
                global_transformation=None)

        # test parameter in duration
        parameters = {
            'a': ConstantParameter(1),
            'b': ConstantParameter(4),
            'c': ConstantParameter(2),
            'alph': ConstantParameter(0)
        }
        with self.assertRaises(ParameterNotProvidedException):
            flt._internal_create_program(
                parameters=parameters,
                measurement_mapping=measurement_mapping,
                channel_mapping=channel_mapping,
                parent_loop=program,
                to_single_waveform=set(),
                global_transformation=None)

        self.assertEqual(children, program.children)
        self.assertEqual(1, program.repetition_count)
        self.assertIsNone(program._measurements)
        self.assert_measurement_windows_equal(
            {}, program.get_measurement_windows())
예제 #22
0
    def test_create_program(self) -> None:
        dt = DummyPulseTemplate(parameter_names={'i'},
                                waveform=DummyWaveform(duration=4.0,
                                                       defined_channels={'A'}),
                                duration=4,
                                measurements=[('b', .2, .3)])
        flt = ForLoopPulseTemplate(body=dt,
                                   loop_index='i',
                                   loop_range=('a', 'b', 'c'),
                                   measurements=[('A', 'meas_param', 1)],
                                   parameter_constraints=['c > 1'])

        parameters = {
            'a': ConstantParameter(1),
            'b': ConstantParameter(4),
            'c': ConstantParameter(2),
            'meas_param': ConstantParameter(.1)
        }
        measurement_mapping = dict(A='B', b='b')
        channel_mapping = dict(C='D')

        to_single_waveform = {'tom', 'jerry'}
        global_transformation = TransformationStub()

        expected_meas_params = {'meas_param': .1}

        program = Loop()

        # inner _create_program does nothing
        expected_program = Loop(measurements=[('B', .1, 1)])

        expected_create_program_kwargs = dict(
            measurement_mapping=measurement_mapping,
            channel_mapping=channel_mapping,
            global_transformation=global_transformation,
            to_single_waveform=to_single_waveform,
            parent_loop=program)
        expected_create_program_calls = [
            mock.call(**expected_create_program_kwargs,
                      parameters=dict(i=ConstantParameter(i))) for i in (1, 3)
        ]

        with mock.patch.object(flt, 'validate_parameter_constraints'
                               ) as validate_parameter_constraints:
            with mock.patch.object(dt,
                                   '_create_program') as body_create_program:
                with mock.patch.object(flt,
                                       'get_measurement_windows',
                                       wraps=flt.get_measurement_windows
                                       ) as get_measurement_windows:
                    flt._internal_create_program(
                        parameters=parameters,
                        measurement_mapping=measurement_mapping,
                        channel_mapping=channel_mapping,
                        parent_loop=program,
                        to_single_waveform=to_single_waveform,
                        global_transformation=global_transformation)

                    validate_parameter_constraints.assert_called_once_with(
                        parameters=parameters)
                    get_measurement_windows.assert_called_once_with(
                        expected_meas_params, measurement_mapping)
                    self.assertEqual(body_create_program.call_args_list,
                                     expected_create_program_calls)

        self.assertEqual(expected_program, program)