Skip to content

Commit

Permalink
Merge branch 'master' into issues/148_pulse_template_integral
Browse files Browse the repository at this point in the history
  • Loading branch information
lumip committed Apr 16, 2018
2 parents 3b18c4c + 77a195f commit f8ebd4f
Show file tree
Hide file tree
Showing 11 changed files with 43 additions and 19 deletions.
5 changes: 3 additions & 2 deletions 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


Expand All @@ -15,7 +15,8 @@ class Comparable(metaclass=ABCMeta):
operators based on comparison of this key.
"""

@abstractproperty
@property
@abstractmethod
def compare_key(self) -> Any:
"""Return a unique key used in comparison and hashing operations.
Expand Down
12 changes: 8 additions & 4 deletions qctoolkit/hardware/awgs/base.py
Expand Up @@ -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"""

Expand Down Expand Up @@ -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."""

Expand Down
11 changes: 7 additions & 4 deletions qctoolkit/pulses/instructions.py
Expand Up @@ -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

Expand Down Expand Up @@ -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."""
Expand Down Expand Up @@ -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."""
Expand Down
2 changes: 1 addition & 1 deletion qctoolkit/pulses/loop_pulse_template.py
Expand Up @@ -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())
Expand Down
11 changes: 7 additions & 4 deletions qctoolkit/pulses/pulse_template.py
Expand Up @@ -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
Expand Down Expand Up @@ -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.
"""
Expand Down
2 changes: 1 addition & 1 deletion qctoolkit/pulses/repetition_pulse_template.py
Expand Up @@ -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]:
Expand Down
2 changes: 1 addition & 1 deletion qctoolkit/pulses/sequence_pulse_template.py
Expand Up @@ -170,7 +170,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]:
Expand Down
3 changes: 2 additions & 1 deletion qctoolkit/serialization.py
Expand Up @@ -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.
Expand Down
5 changes: 5 additions & 0 deletions tests/pulses/loop_pulse_template_tests.py
Expand Up @@ -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'),
Expand Down
5 changes: 4 additions & 1 deletion tests/pulses/repetition_pulse_template_tests.py
Expand Up @@ -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))
Expand All @@ -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<c'])
self.assertEqual(pt.parameter_names, {'a','c', 'n'})


class RepetitionPulseTemplateSerializationTests(unittest.TestCase):

Expand Down
4 changes: 4 additions & 0 deletions tests/pulses/sequence_pulse_template_tests.py
Expand Up @@ -127,6 +127,10 @@ def test_duration(self):
DummyPulseTemplate(duration='b'))
self.assertEqual(pt.duration, Expression('a+a+b'))

def test_parameter_names_param_only_in_constraint(self) -> None:
pt = SequencePulseTemplate(DummyPulseTemplate(parameter_names={'a'}), DummyPulseTemplate(parameter_names={'b'}), parameter_constraints=['a==b', 'a<c'])
self.assertEqual(pt.parameter_names, {'a','b','c'})

def test_build_waveform(self):
wfs = [DummyWaveform(), DummyWaveform()]
pts = [DummyPulseTemplate(waveform=wf) for wf in wfs]
Expand Down

0 comments on commit f8ebd4f

Please sign in to comment.