From cd67b0da7c42e1f27e11c44c6a4de6ecf250bde3 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 1 Jul 2024 18:46:05 +0200 Subject: [PATCH] Add untested linspace implementation --- qupulse/program/linspace.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/qupulse/program/linspace.py b/qupulse/program/linspace.py index 600a6f82..cb6d26d4 100644 --- a/qupulse/program/linspace.py +++ b/qupulse/program/linspace.py @@ -44,6 +44,9 @@ class LinSpaceNode: def dependencies(self) -> Mapping[int, set]: raise NotImplementedError + def reversed(self, level: int): + raise NotImplementedError + @dataclass class LinSpaceHold(LinSpaceNode): @@ -60,6 +63,21 @@ def dependencies(self) -> Mapping[int, set]: for idx, factors in enumerate(self.factors) if factors} + def reversed(self, level: int): + factors = [] + for ch_factors in self.factors: + if ch_factors is None or len(ch_factors) <= level: + factors.append(ch_factors) + else: + reversed_factors = ch_factors[:level] + tuple(-f for f in ch_factors[level:]) + factors.append(reversed_factors) + + if self.duration_factors is not None and len(self.duration_factors) <= level: + duration_factors = self.duration_factors + else: + duration_factors = self.duration_factors[:level] + tuple(-f for f in self.duration_factors[level:]) + return LinSpaceHold(self.bases, factors, duration_base=self.duration_base, duration_factors=duration_factors) + @dataclass class LinSpaceArbitraryWaveform(LinSpaceNode): @@ -67,6 +85,12 @@ class LinSpaceArbitraryWaveform(LinSpaceNode): waveform: Waveform channels: Tuple[ChannelID, ...] + def reversed(self, level: int): + return LinSpaceArbitraryWaveform( + waveform=self.waveform.reversed(), + channels=self.channels, + ) + @dataclass class LinSpaceRepeat(LinSpaceNode): @@ -81,6 +105,9 @@ def dependencies(self): dependencies.setdefault(idx, set()).update(deps) return dependencies + def reversed(self, level: int): + return LinSpaceRepeat(tuple(node.reversed(level) for node in reversed(self.body)), self.count) + @dataclass class LinSpaceIter(LinSpaceNode): @@ -100,6 +127,9 @@ def dependencies(self): dependencies.setdefault(idx, set()).update(shortened) return dependencies + def reversed(self, level: int): + return LinSpaceIter(tuple(node.reversed() for node in reversed(self.body)), self.length) + class LinSpaceBuilder(ProgramBuilder): """This program builder supports efficient translation of pulse templates that use symbolic linearly @@ -214,6 +244,13 @@ def with_iteration(self, index_name: str, rng: range, if cmds: self._stack[-1].append(LinSpaceIter(body=tuple(cmds), length=len(rng))) + def time_reversed(self) -> ContextManager['LinSpaceBuilder']: + self._stack.append([]) + yield self + inner = self._stack.pop() + level = len(self._ranges) + self._stack[-1].extend(node.reversed(level) for node in reversed(inner)) + def to_program(self) -> Optional[Sequence[LinSpaceNode]]: if self._root(): return self._root()