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))
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())
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()))
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)
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())
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))
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)
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())
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 }))
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)
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)
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'})
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()))
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)
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)
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)
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)
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)
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)
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)
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())
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)