diff --git a/perceval/components/__init__.py b/perceval/components/__init__.py index d1917b7a..73dd5f16 100644 --- a/perceval/components/__init__.py +++ b/perceval/components/__init__.py @@ -40,7 +40,7 @@ from ._decompose_perms import decompose_perms from .port import APort, Port, Herald, PortLocation, get_basic_state_from_ports from .detector import IDetector, DetectionType, Detector, BSLayeredPPNR, get_detection_type, check_heralds_detectors -from .unitary_components import BSConvention, BS, PS, WP, HWP, QWP, PR, Unitary, PERM, PBS, Barrier +from .unitary_components import BSConvention, BS, PS, WP, HWP, QWP, PR, Unitary, PERM, PBS, Barrier, UFT from .non_unitary_components import TD, LC from .component_catalog import Catalog from ._mode_connector import ModeConnector, UnavailableModeException diff --git a/perceval/components/unitary_components.py b/perceval/components/unitary_components.py index 8bf74e3d..d2989739 100644 --- a/perceval/components/unitary_components.py +++ b/perceval/components/unitary_components.py @@ -618,3 +618,32 @@ def apply(self, r, sv): def inverse(self, v=False, h=False): pass + + +class UFT(Unitary): + """Fourier interferometer + + :param m: Size of Fourier interferometer. + """ + DEFAULT_NAME = "UFT" + + def __init__(self, m: int): + if not isinstance(m, int) or m <= 0: + raise ValueError("UFT requires a positive integer as argument.") + + u = self._construct_matrix(m) + super().__init__(U=u, name="UFT") + + def describe(self): + return f"UFT({self.m})" + + def definition(self): + return self.U + + @staticmethod + def _construct_matrix(m: int) -> Matrix: + factor = 2j * np.pi / m + indices = np.arange(m) + matrix = np.exp(factor * np.outer(indices, indices)) + matrix /= np.sqrt(m) + return Matrix(matrix)