Source code for qugradlab.pulses.composition

 1"""A collection of methods for composing functions and tensors."""
 2
 3import typing
 4from typing import Callable
 5
 6import numpy as np
 7import tensorflow as tf
 8
[docs] 9def pad(x: np.ndarray[complex], 10 value: complex = 0, 11 left: bool = True, 12 right: bool = True 13 ) -> typing.Any: 14 """Adds padding to a tensor. 15 16 Parameters 17 ---------- 18 x: NDArray[Shape[s := Any_Shape]] 19 The tensor to pad 20 value: number 21 The value to pad the tensor with, by default ``0`` 22 left: bool 23 Whether to prepend padding, by default ``True`` 24 right: bool 25 Whether to append padding, by default ``True`` 26 27 Returns 28 ------- 29 NDArray[Shape[``s[0]+left+right``, ``s[1:]``]] 30 Padded tensor 31 """ 32 if not left and not right: 33 return x 34 padding = value*tf.ones_like(x[0:1]) 35 if left and right: 36 return tf.concat([padding, x, padding], axis=0) 37 elif left and not right: 38 return tf.concat([padding, x], axis=0) 39 return tf.concat([x, padding], axis=0)
40
[docs] 41def concatenate_functions(functions: list[Callable]) -> Callable: 42 """Generates a function that executes the listed functions and concatenates 43 the outputs. 44 45 Parameters 46 ---------- 47 functions : list[Callable] 48 A list of Callables that return concatenatable outputs. 49 50 Returns 51 ------- 52 Callable 53 A function that executes the listed functions and concatenates the 54 outputs. 55 56 Example 57 ------- 58 >>> def f1(x): 59 ... return [x + 1] 60 >>> def f2(x): 61 ... return [x - 1] 62 >>> a = f1(1) 63 >>> b = f2(2) 64 >>> c = tf.concat([a, b], axis=-1) 65 >>> f3 = concatenate_functions([f1, f2]) 66 >>> d = f3([[1], [2]]) 67 >>> assert all(c == d) 68 """ 69 def execute_and_concatenate(function_arguments): 70 return tf.concat([d(*a) for d, a in zip(functions, 71 function_arguments)], 72 axis=-1) 73 return execute_and_concatenate