From f2d7038275d532a3ef3dc3fee4efbad65d70d7a4 Mon Sep 17 00:00:00 2001 From: Lukas Prediger Date: Mon, 9 Apr 2018 12:08:31 +0200 Subject: [PATCH 1/3] Fix: ForLoopPulseTemplate, SequencePulseTemplate, RepetitionPulseTemplate now also include all parameters only appearing in constraint expression in parameter_names . --- qctoolkit/pulses/loop_pulse_template.py | 2 +- qctoolkit/pulses/repetition_pulse_template.py | 2 +- qctoolkit/pulses/sequence_pulse_template.py | 2 +- tests/pulses/loop_pulse_template_tests.py | 5 +++++ tests/pulses/repetition_pulse_template_tests.py | 5 ++++- tests/pulses/sequence_pulse_template_tests.py | 4 ++++ 6 files changed, 16 insertions(+), 4 deletions(-) diff --git a/qctoolkit/pulses/loop_pulse_template.py b/qctoolkit/pulses/loop_pulse_template.py index 5828089f6..9a22d97fc 100644 --- a/qctoolkit/pulses/loop_pulse_template.py +++ b/qctoolkit/pulses/loop_pulse_template.py @@ -178,7 +178,7 @@ def duration(self) -> ExpressionScalar: def parameter_names(self) -> Set[str]: parameter_names = self.body.parameter_names.copy() parameter_names.remove(self._loop_index) - return parameter_names | self._loop_range.parameter_names + return parameter_names | self._loop_range.parameter_names | self.constrained_parameters def _body_parameter_generator(self, parameters: Dict[str, Parameter], forward=True) -> Generator: loop_range_parameters = dict((parameter_name, parameters[parameter_name].get_value()) diff --git a/qctoolkit/pulses/repetition_pulse_template.py b/qctoolkit/pulses/repetition_pulse_template.py index 44b531ddb..250cc64db 100644 --- a/qctoolkit/pulses/repetition_pulse_template.py +++ b/qctoolkit/pulses/repetition_pulse_template.py @@ -123,7 +123,7 @@ def __str__(self) -> str: @property def parameter_names(self) -> Set[str]: - return self.body.parameter_names | set(self.repetition_count.variables) + return self.body.parameter_names | set(self.repetition_count.variables) | self.constrained_parameters @property def measurement_names(self) -> Set[str]: diff --git a/qctoolkit/pulses/sequence_pulse_template.py b/qctoolkit/pulses/sequence_pulse_template.py index b22b8ff3f..2a6fa6bbd 100644 --- a/qctoolkit/pulses/sequence_pulse_template.py +++ b/qctoolkit/pulses/sequence_pulse_template.py @@ -169,7 +169,7 @@ def __init__(self, @property def parameter_names(self) -> Set[str]: - return set.union(*(st.parameter_names for st in self.__subtemplates)) + return self.constrained_parameters.union(*(st.parameter_names for st in self.__subtemplates)) @property def subtemplates(self) -> List[MappingPulseTemplate]: diff --git a/tests/pulses/loop_pulse_template_tests.py b/tests/pulses/loop_pulse_template_tests.py index b8e3e16f7..4e3563f7f 100644 --- a/tests/pulses/loop_pulse_template_tests.py +++ b/tests/pulses/loop_pulse_template_tests.py @@ -148,6 +148,11 @@ def test_parameter_names(self): self.assertEqual(flt.parameter_names, {'k', 'a', 'b', 'c'}) + 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_build_sequence(self): dt = DummyPulseTemplate(parameter_names={'i'}) flt = ForLoopPulseTemplate(body=dt, loop_index='i', loop_range=('a', 'b', 'c'), diff --git a/tests/pulses/repetition_pulse_template_tests.py b/tests/pulses/repetition_pulse_template_tests.py index bdfa8b7dd..c67636706 100644 --- a/tests/pulses/repetition_pulse_template_tests.py +++ b/tests/pulses/repetition_pulse_template_tests.py @@ -204,7 +204,6 @@ def test_parameter_not_provided(self): template.build_sequence(self.sequencer, parameters, conditions, measurement_mapping, channel_mapping, self.block) - def test_build_sequence_declaration_exceeds_bounds(self) -> None: parameters = dict(foo=ConstantParameter(9)) conditions = dict(foo=DummyCondition(requires_stop=True)) @@ -226,6 +225,10 @@ def test_build_sequence_declaration_parameter_value_not_whole(self) -> None: self.template.build_sequence(self.sequencer, parameters, conditions, {}, {}, self.block) self.assertFalse(self.sequencer.sequencing_stacks) + def test_parameter_names_param_only_in_constraint(self) -> None: + pt = RepetitionPulseTemplate(DummyPulseTemplate(parameter_names={'a'}), 'n', parameter_constraints=['a None: + pt = SequencePulseTemplate(DummyPulseTemplate(parameter_names={'a'}), DummyPulseTemplate(parameter_names={'b'}), parameter_constraints=['a==b', 'a Date: Mon, 16 Apr 2018 10:59:27 +0200 Subject: [PATCH 2/3] Removed deprecated @abstractproperty and @abstractstaticmethod annotations in the code and replaced it with the correct annotations. --- qctoolkit/comparable.py | 4 ++-- qctoolkit/hardware/awgs/base.py | 12 ++++++++---- qctoolkit/pulses/instructions.py | 11 +++++++---- qctoolkit/pulses/pulse_template.py | 11 +++++++---- qctoolkit/serialization.py | 3 ++- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/qctoolkit/comparable.py b/qctoolkit/comparable.py index 3d3803952..dec7f15a0 100644 --- a/qctoolkit/comparable.py +++ b/qctoolkit/comparable.py @@ -1,5 +1,5 @@ """This module defines the abstract Comparable class.""" -from abc import ABCMeta, abstractproperty +from abc import ABCMeta, abstractmethod from typing import Any @@ -15,7 +15,7 @@ class Comparable(metaclass=ABCMeta): operators based on comparison of this key. """ - @abstractproperty + @abstractmethod def compare_key(self) -> Any: """Return a unique key used in comparison and hashing operations. diff --git a/qctoolkit/hardware/awgs/base.py b/qctoolkit/hardware/awgs/base.py index db0ad61bf..3c3cd0c7e 100644 --- a/qctoolkit/hardware/awgs/base.py +++ b/qctoolkit/hardware/awgs/base.py @@ -38,11 +38,13 @@ def __init__(self, identifier: str): def identifier(self) -> str: return self._identifier - @abstractproperty + @property + @abstractmethod def num_channels(self): """Number of channels""" - @abstractproperty + @property + @abstractmethod def num_markers(self): """Number of marker channels""" @@ -86,11 +88,13 @@ def arm(self, name: Optional[str]) -> None: """Load the program 'name' and arm the device for running it. If name is None the awg will "dearm" its current program.""" - @abstractproperty + @property + @abstractmethod def programs(self) -> Set[str]: """The set of program names that can currently be executed on the hardware AWG.""" - @abstractproperty + @property + @abstractmethod def sample_rate(self) -> float: """The sample rate of the AWG.""" diff --git a/qctoolkit/pulses/instructions.py b/qctoolkit/pulses/instructions.py index 6586fca01..9df04c5ac 100644 --- a/qctoolkit/pulses/instructions.py +++ b/qctoolkit/pulses/instructions.py @@ -16,7 +16,7 @@ - InstructionPointer: References an instruction's location in a sequence. """ -from abc import ABCMeta, abstractmethod, abstractproperty +from abc import ABCMeta, abstractmethod from typing import List, Any, Dict, Iterable, Optional, Sequence, Union, Set, Tuple from weakref import WeakValueDictionary @@ -108,7 +108,8 @@ def get_sampled(self, sample_times=sample_times, output_array=output_array) - @abstractproperty + @property + @abstractmethod def defined_channels(self) -> Set[ChannelID]: """The channels this waveform should played on. Use :func:`~qctoolkit.pulses.instructions.get_measurement_windows` to get a waveform for a subset of these.""" @@ -390,11 +391,13 @@ def __init__(self) -> None: """Create a new AbstractInstructionBlock instance.""" super().__init__() - @abstractproperty + @property + @abstractmethod def instructions(self) -> Sequence[Instruction]: """The instructions contained in this block (excluding a final stop or return goto).""" - @abstractproperty + @property + @abstractmethod def return_ip(self) -> Optional[InstructionPointer]: """The return instruction pointer indicating the instruction to which the control flow shall return after exection of this instruction block has finished.""" diff --git a/qctoolkit/pulses/pulse_template.py b/qctoolkit/pulses/pulse_template.py index 18ab85dae..5d69b158d 100644 --- a/qctoolkit/pulses/pulse_template.py +++ b/qctoolkit/pulses/pulse_template.py @@ -6,7 +6,7 @@ - AtomicPulseTemplate: PulseTemplate that does imply any control flow disruptions and can be directly translated into a waveform. """ -from abc import ABCMeta, abstractmethod, abstractproperty +from abc import abstractmethod from typing import Dict, Tuple, Set, Optional, Union, List import itertools from numbers import Real @@ -45,15 +45,18 @@ def __init__(self, *, identifier: Optional[str]) -> None: super().__init__(identifier) - @abstractproperty + @property + @abstractmethod def parameter_names(self) -> Set[str]: """The set of names of parameters required to instantiate this PulseTemplate.""" - @abstractproperty + @property + @abstractmethod def measurement_names(self) -> Set[str]: """The set of measurement identifiers in this pulse template.""" - @abstractproperty + @property + @abstractmethod def is_interruptable(self) -> bool: """Return true, if this PulseTemplate contains points at which it can halt if interrupted. """ diff --git a/qctoolkit/serialization.py b/qctoolkit/serialization.py index 57dda619a..e0a0ce5ee 100644 --- a/qctoolkit/serialization.py +++ b/qctoolkit/serialization.py @@ -301,7 +301,8 @@ def get_serialization_data(self, serializer: 'Serializer') -> Dict[str, Any]: storing and later reconstruction as a Python object. """ - @abstractstaticmethod + @staticmethod + @abstractmethod def deserialize(serializer: 'Serializer', **kwargs) -> 'Serializable': """Reconstruct the Serializable object from a dictionary. From 77a195f19b51396bea4abded1955ea3997eba310 Mon Sep 17 00:00:00 2001 From: Lukas Prediger Date: Mon, 16 Apr 2018 12:27:10 +0200 Subject: [PATCH 3/3] hotfix for previous commit added missing property annotation to Comparable.compare_key --- qctoolkit/comparable.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qctoolkit/comparable.py b/qctoolkit/comparable.py index dec7f15a0..5e217a857 100644 --- a/qctoolkit/comparable.py +++ b/qctoolkit/comparable.py @@ -15,6 +15,7 @@ class Comparable(metaclass=ABCMeta): operators based on comparison of this key. """ + @property @abstractmethod def compare_key(self) -> Any: """Return a unique key used in comparison and hashing operations.