Source code for qupulse._program.volatile
from typing import NamedTuple, Mapping
import warnings
import numbers
from qupulse.parameter_scope import Scope, MappedScope, JointScope
from qupulse.expressions import Expression, ExpressionScalar
from qupulse.utils.types import FrozenDict
from qupulse.utils import is_integer
VolatileProperty = NamedTuple('VolatileProperty', [('expression', Expression),
('dependencies', FrozenDict[str, Expression])])
VolatileProperty.__doc__ = """Hashable representation of a volatile program property. It does not contain the concrete
value. Using the dependencies attribute to calculate the value might yield unexpected results."""
[docs]class VolatileValue:
"""Not hashable"""
def __init__(self, expression: ExpressionScalar, scope: Scope):
self._expression = expression
self._scope = scope
@property
def volatile_property(self) -> VolatileProperty:
dependencies = self._scope.get_volatile_parameters()
dependencies = FrozenDict({parameter_name: dependencies[parameter_name]
for parameter_name in self._expression.variables
if parameter_name in dependencies})
return VolatileProperty(expression=self._expression, dependencies=dependencies)
[docs] @classmethod
def operation(cls, expression, **operands):
expression = Expression(expression)
assert set(expression.variables) == operands.keys()
scope = JointScope(FrozenDict(
{operand_name: MappedScope(operand._scope, FrozenDict({operand_name: operand._expression}))
for operand_name, operand in operands.items()}
))
return cls(expression, scope)
def __sub__(self, other: int):
return type(self)(self._expression - other, self._scope)
def __mul__(self, other: int):
return type(self)(self._expression * other, self._scope)
[docs]class VolatileRepetitionCount(VolatileValue):
def __int__(self):
value = self._expression.evaluate_in_scope(self._scope)
if not is_integer(value):
warnings.warn("Repetition count is no integer. Rounding might lead to unexpected results.")
value = int(round(value))
if value < 0:
warnings.warn("Repetition count is negative. Clamping lead to unexpected results.")
value = 0
return value
[docs] def update_volatile_dependencies(self, new_constants: Mapping[str, numbers.Number]) -> int:
self._scope = self._scope.change_constants(new_constants)
return int(self)