diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9260908 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,2 @@ +## [1.0.0] - 2026-02-10 +### Initial release \ No newline at end of file diff --git a/CITATION.cff b/CITATION.cff index 2074b85..74d9131 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,4 +1,4 @@ -cff-version: 0.0.0 +cff-version: 1.0.0 message: "If you use this software, please cite it as below." authors: - family-names: "Girouard" @@ -7,8 +7,8 @@ authors: - family-names: "Quesada" given-names: "Nicolás" orcid: "https://orcid.org/0000-0002-0175-1688" -title: "Unitary-Decomp" -version: 0.0.0 +title: "UDecomp" +version: 1.0.0 doi: 10.1364/JOSAB.577579 date-released: 2025-08-28 url: "https://github.com/polyquantique/Unitary-Decomp" \ No newline at end of file diff --git a/README.md b/README.md index d53c8aa..d861d55 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![a](https://img.shields.io/static/v1?label=arXiv&message=2508.20010&color=active&style=flat-square)](https://arxiv.org/abs/arXiv:2508.20010) -# Unitary-Decomp +# UDecomp Decomposition and approximation tools for linear optical unitaries. @@ -17,7 +17,7 @@ Decomposition and approximation tools for linear optical unitaries. ## About This Project -`Unitary-Decomp` is a **Python** package for performing various **decompositions** and **approximations** of unitary matrices into planar arrangements of simple optical components. These tools can be used to design and program **universal multiport interferometers** (UMIs), devices capable of implementing arbitrary linear transformations on multiple optical modes. Such devices have numerous applications in communication, imaging, and information processing. +`UDecomp` is a **Python** package for performing various **decompositions** and **approximations** of unitary matrices into planar arrangements of simple optical components. These tools can be used to design and program **universal multiport interferometers** (UMIs), devices capable of implementing arbitrary linear transformations on multiple optical modes. Such devices have numerous applications in communication, imaging, and information processing. The algorithms implemented in this package cover two main classes of planar UMI architectures: - [Networks of two-mode components](#two-mode-component-networks) @@ -47,30 +47,30 @@ Sequence of phase masks interleaved with the discrete Fourier transform mixing l `Unitary-Decomp` provides tools to perform **exact decompositions** and **numerical approximations** of unitary matrices. ### Exact Decompositions -`Unitary-Decomp` includes four main modules to perform exact decompositions of unitary matrices: +`UDecomp` includes four main modules to perform exact decompositions of unitary matrices: -- [`clements_interferometer`](src/unitary_decomp/clements_interferometer.py): Implementation of the algorithm by [Clements *et al.*, 2016](https://doi.org/10.1364/OPTICA.3.001460) to decompose $N \times N$ unitary matrices into a rectangular mesh of $N(N-1)/2$ **asymmetric** Mach–Zehnder interferometers. +- [`clements_interferometer`](src/udecomp/clements_interferometer.py): Implementation of the algorithm by [Clements *et al.*, 2016](https://doi.org/10.1364/OPTICA.3.001460) to decompose $N \times N$ unitary matrices into a rectangular mesh of $N(N-1)/2$ **asymmetric** Mach–Zehnder interferometers. -- [`bell_interferometer`](src/unitary_decomp/bell_interferometer.py): Implementation of the algorithm by [Bell *et al.*, 2021](https://doi.org/10.1063/5.0053421) to decompose $N \times N$ unitary matrices into a rectangular mesh of $N(N-1)/2$ **symmetric** Mach–Zehnder interferometers. +- [`bell_interferometer`](src/udecomp/bell_interferometer.py): Implementation of the algorithm by [Bell *et al.*, 2021](https://doi.org/10.1063/5.0053421) to decompose $N \times N$ unitary matrices into a rectangular mesh of $N(N-1)/2$ **symmetric** Mach–Zehnder interferometers. -- [`lplm_interferometer`](src/unitary_decomp/lplm_interferometer.py): Implementation of the algorithm by [López Pastor *et al.*, 2021](https://doi.org/10.1364/OE.432787) to decompose $N \times N$ unitary matrices into a sequence of $6N+1$ phase masks interleaved with the **DFT** matrix. +- [`lplm_interferometer`](src/udecomp/lplm_interferometer.py): Implementation of the algorithm by [López Pastor *et al.*, 2021](https://doi.org/10.1364/OE.432787) to decompose $N \times N$ unitary matrices into a sequence of $6N+1$ phase masks interleaved with the **DFT** matrix. -- [`fourier_interferometer`](src/unitary_decomp/fourier_interferometer.py): Implementation of the **Fourier decomposition** and the **compact Fourier decomposition** to decompose $N \times N$ unitary matrices into sequences of $4N+1$ and $2N+5$ phase masks interleaved with **DFT** respectively. +- [`fourier_interferometer`](src/udecomp/fourier_interferometer.py): Implementation of the **Fourier decomposition** and the **compact Fourier decomposition** to decompose $N \times N$ unitary matrices into sequences of $4N+1$ and $2N+5$ phase masks interleaved with **DFT** respectively. ### Optimization Tools -In addition to exact decompositions, `Unitary-Decomp` also has an `optimization` subpackage, which contains tools to approximate unitary matrices into a sequence of phase masks interleaved with a chosen mixing layer. The `optimization` subpackage has two modules: +In addition to exact decompositions, `UDecomp` also has an `optimization` subpackage, which contains tools to approximate unitary matrices into a sequence of phase masks interleaved with a chosen mixing layer. The `optimization` subpackage has two modules: -- [`fourier_optimizer`](src/unitary_decomp/optimization/fourier_optimizer.py): Uses the basin-hopping algorithm from `scipy.optimize` to solve a global minimization problem, yielding the sequence of phase masks that minimizes the infidelity with respect to a target unitary. +- [`fourier_optimizer`](src/udecomp/optimization/fourier_optimizer.py): Uses the basin-hopping algorithm from `scipy.optimize` to solve a global minimization problem, yielding the sequence of phase masks that minimizes the infidelity with respect to a target unitary. -- [`jax_optimizer`](src/unitary_decomp/optimization/jax_optimizer.py): Uses `Jax` and `Optax` to perform gradient-based optimization of the phase masks with multiple restarts to minimize the infidelity with respect to a target unitary. This algorithm can run efficiently on CPU or GPU and is significantly faster than the SciPy-based implementation. +- [`jax_optimizer`](src/udecomp/optimization/jax_optimizer.py): Uses `Jax` and `Optax` to perform gradient-based optimization of the phase masks with multiple restarts to minimize the infidelity with respect to a target unitary. This algorithm can run efficiently on CPU or GPU and is significantly faster than the SciPy-based implementation. --- **Note:** For more detailed descriptions and usage examples, see the documentation of the individual modules. ## Installation -You can install `Unitary-Decomp` from source as follows: +You can install `UDecomp` from source as follows: 1. Clone the repository @@ -127,7 +127,7 @@ pytest tests This first example shows how to use the `clements_interferometer` module to decompose a random unitary matrix. ```python ->>> from unitary_decomp import clements_interferometer as ci +>>> from udecomp import clements_interferometer as ci >>> from scipy.stats import unitary_group >>> import numpy as np ``` @@ -168,7 +168,7 @@ True This example shows how to use the `fourier_interferometer` module to decompose a random unitary matrix. ```python ->>> from unitary_decomp import fourier_interferometer as fi +>>> from udecomp import fourier_interferometer as fi >>> from scipy.stats import unitary_group >>> import numpy as np ``` @@ -212,7 +212,7 @@ True This example shows how to use the `jax_optimizer` module found in the `optimization` subpackage to find numerically a sequence of phase masks that approximate a given unitary matrix. ```python ->>> from unitary_decomp.optimize import jax_optimizer as jo +>>> from udecomp.optimize import jax_optimizer as jo >>> from scipy.stats import unitary_group >>> import numpy as np ``` @@ -244,7 +244,7 @@ The final matrix can be reconstructed using the `circuit_reconstruction` functio ## Documentation -The **LPLM algorithm** found in the [`lplm_interferometer`](src/unitary_decomp/lplm_interferometer.py) module was adapted from [López Pastor *et al.*, 2021](https://doi.org/10.1364/OE.432787) and uses a slightly different sequence of phase masks than the original paper. A comprehensive derivation of this new sequence can be found in the following document: +The **LPLM algorithm** found in the [`lplm_interferometer`](src/udecomp/lplm_interferometer.py) module was adapted from [López Pastor *et al.*, 2021](https://doi.org/10.1364/OE.432787) and uses a slightly different sequence of phase masks than the original paper. A comprehensive derivation of this new sequence can be found in the following document: - [Decomposition of Unitary Matrices Using Fourier Transforms and Phase Masks](papers/LPLM_algorithm_derivation.pdf) diff --git a/examples/clements_example.py b/examples/clements_example.py index 50c8178..7bd77d1 100644 --- a/examples/clements_example.py +++ b/examples/clements_example.py @@ -18,7 +18,7 @@ import numpy as np -from unitary_decomp.clements_interferometer import circuit_reconstruction, clements_decomposition +from udecomp.clements_interferometer import circuit_reconstruction, clements_decomposition # Example unitary matrix (U = H \otimes H) U = 1 / 2 * np.array([[1, 1, 1, 1], [1, -1, 1, -1], [1, 1, -1, -1], [1, -1, -1, 1]]) diff --git a/examples/fourier_decomposition.ipynb b/examples/fourier_decomposition.ipynb index d128a6f..de8643e 100644 --- a/examples/fourier_decomposition.ipynb +++ b/examples/fourier_decomposition.ipynb @@ -20,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "c149d137", "metadata": {}, "outputs": [], @@ -28,7 +28,7 @@ "# Import dependencies\n", "import numpy as np\n", "from scipy.stats import unitary_group\n", - "from unitary_decomp.fourier_interferometer import compact_fourier_decomposition, circuit_reconstruction\n", + "from udecomp.fourier_interferometer import compact_fourier_decomposition, circuit_reconstruction\n", "np.set_printoptions(precision=3, suppress=True, linewidth=150)" ] }, @@ -209,14 +209,14 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "179234a9", "metadata": {}, "outputs": [], "source": [ "# Import the plotting function\n", "import matplotlib.pyplot as plt\n", - "from unitary_decomp.plot.phases_plot import plot_phases" + "from udecomp.plot.phases_plot import plot_phases" ] }, { diff --git a/examples/lplm_example.ipynb b/examples/lplm_example.ipynb index 5bfa83e..f5d2e9a 100644 --- a/examples/lplm_example.ipynb +++ b/examples/lplm_example.ipynb @@ -21,13 +21,13 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "7f574ccd", "metadata": {}, "outputs": [], "source": [ "# Import dependencies\n", - "from unitary_decomp import lplm_interferometer as li\n", + "from udecomp import lplm_interferometer as li\n", "\n", "import numpy as np\n", "from scipy.stats import unitary_group" diff --git a/pyproject.toml b/pyproject.toml index ea2887c..17fda6e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["setuptools>=61.0", "wheel"] build-backend = "setuptools.build_meta" [project] -name = "unitary_decomp" +name = "udecomp" dynamic = ["version"] description = "Decompositions and approximations of linear optical unitaries." authors = [ @@ -35,4 +35,4 @@ Homepage = "https://github.com/polyquantique/Unitary-Decomp" where = ["src"] [tool.setuptools.dynamic] -version = {attr = "unitary_decomp.__version__"} +version = {attr = "udecomp.__version__"} diff --git a/src/unitary_decomp/__init__.py b/src/udecomp/__init__.py similarity index 75% rename from src/unitary_decomp/__init__.py rename to src/udecomp/__init__.py index 9b7a33d..0f4a6c4 100644 --- a/src/unitary_decomp/__init__.py +++ b/src/udecomp/__init__.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""# Unitary Decompositions +"""# UDecomp This package provides functions to decompose and approximate linear optical transformations into various interferometer configurations. @@ -31,14 +31,11 @@ `Unitary-Decomp` also includes optimization routines in the `optimization` subpackage to find approximated decompositions using gradient-based methods. """ -__version__ = "0.1.0" - -from unitary_decomp.bell_interferometer import bell_decomposition -from unitary_decomp.clements_interferometer import clements_decomposition, mzi_decomposition -from unitary_decomp.fourier_interferometer import ( - compact_fourier_decomposition, - fourier_decomposition, -) -from unitary_decomp.lplm_interferometer import lplm_decomposition -from unitary_decomp.optimization.fourier_optimizer import mask_optimizer -from unitary_decomp.optimization.jax_optimizer import jax_mask_optimizer +__version__ = "1.0.0" + +from udecomp.bell_interferometer import bell_decomposition +from udecomp.clements_interferometer import clements_decomposition, mzi_decomposition +from udecomp.fourier_interferometer import compact_fourier_decomposition, fourier_decomposition +from udecomp.lplm_interferometer import lplm_decomposition +from udecomp.optimization.fourier_optimizer import mask_optimizer +from udecomp.optimization.jax_optimizer import jax_mask_optimizer diff --git a/src/unitary_decomp/bell_interferometer.py b/src/udecomp/bell_interferometer.py similarity index 100% rename from src/unitary_decomp/bell_interferometer.py rename to src/udecomp/bell_interferometer.py diff --git a/src/unitary_decomp/clements_interferometer.py b/src/udecomp/clements_interferometer.py similarity index 100% rename from src/unitary_decomp/clements_interferometer.py rename to src/udecomp/clements_interferometer.py diff --git a/src/unitary_decomp/fourier_interferometer.py b/src/udecomp/fourier_interferometer.py similarity index 100% rename from src/unitary_decomp/fourier_interferometer.py rename to src/udecomp/fourier_interferometer.py diff --git a/src/unitary_decomp/lplm_interferometer.py b/src/udecomp/lplm_interferometer.py similarity index 100% rename from src/unitary_decomp/lplm_interferometer.py rename to src/udecomp/lplm_interferometer.py diff --git a/src/unitary_decomp/matrix_operations.py b/src/udecomp/matrix_operations.py similarity index 100% rename from src/unitary_decomp/matrix_operations.py rename to src/udecomp/matrix_operations.py diff --git a/src/unitary_decomp/optimization/__init__.py b/src/udecomp/optimization/__init__.py similarity index 87% rename from src/unitary_decomp/optimization/__init__.py rename to src/udecomp/optimization/__init__.py index b543f3a..7bebec9 100644 --- a/src/unitary_decomp/optimization/__init__.py +++ b/src/udecomp/optimization/__init__.py @@ -22,5 +22,5 @@ - `jax_optimizer`: Uses the `Jax` and `Optax` libraries to find the phase masks that minimize the infidelity with a target unitary efficiently. """ -from unitary_decomp.optimization.fourier_optimizer import mask_optimizer -from unitary_decomp.optimization.jax_optimizer import jax_mask_optimizer, scipy_mask_optimizer +from udecomp.optimization.fourier_optimizer import mask_optimizer +from udecomp.optimization.jax_optimizer import jax_mask_optimizer, scipy_mask_optimizer diff --git a/src/unitary_decomp/optimization/fourier_optimizer.py b/src/udecomp/optimization/fourier_optimizer.py similarity index 97% rename from src/unitary_decomp/optimization/fourier_optimizer.py rename to src/udecomp/optimization/fourier_optimizer.py index 73dc555..901af64 100644 --- a/src/unitary_decomp/optimization/fourier_optimizer.py +++ b/src/udecomp/optimization/fourier_optimizer.py @@ -38,8 +38,8 @@ from numpy.typing import NDArray from scipy.optimize import basinhopping -from unitary_decomp import matrix_operations as mo -from unitary_decomp.fourier_interferometer import FourierDecomp +from udecomp import matrix_operations as mo +from udecomp.fourier_interferometer import FourierDecomp def fidelity(U: NDArray, V: NDArray) -> float: @@ -142,8 +142,8 @@ def mask_optimizer( Example: >>> import numpy as np >>> from scipy.stats import unitary_group - >>> from unitary_decomp.fourier_interferometer import circuit_reconstruction - >>> from unitary_decomp.optimization import mask_optimizer + >>> from udecomp.fourier_interferometer import circuit_reconstruction + >>> from udecomp.optimization import mask_optimizer >>> U = unitary_group(dim=6, seed=137).rvs() # Generate a random 6x6 unitary matrix >>> mask_shape = np.array([True, True, True, True, True, False]) # Define the shape of the phase masks with no phase shifter on the last mode diff --git a/src/unitary_decomp/optimization/jax_optimizer.py b/src/udecomp/optimization/jax_optimizer.py similarity index 99% rename from src/unitary_decomp/optimization/jax_optimizer.py rename to src/udecomp/optimization/jax_optimizer.py index 4744f1f..b981257 100644 --- a/src/unitary_decomp/optimization/jax_optimizer.py +++ b/src/udecomp/optimization/jax_optimizer.py @@ -36,7 +36,7 @@ from jax.scipy.optimize import minimize from scipy.linalg import dft -from unitary_decomp.fourier_interferometer import FourierDecomp +from udecomp.fourier_interferometer import FourierDecomp # Enable 64-bit precision for JAX operations jax.config.update("jax_enable_x64", True) diff --git a/src/unitary_decomp/plot/__init__.py b/src/udecomp/plot/__init__.py similarity index 94% rename from src/unitary_decomp/plot/__init__.py rename to src/udecomp/plot/__init__.py index 02f62de..5c25e47 100644 --- a/src/unitary_decomp/plot/__init__.py +++ b/src/udecomp/plot/__init__.py @@ -22,4 +22,4 @@ - `clements_plot`: Module for the characterization of the Clements decomposition. """ -from unitary_decomp.plot.phases_plot import plot_phases +from udecomp.plot.phases_plot import plot_phases diff --git a/src/unitary_decomp/plot/clements_plot.py b/src/udecomp/plot/clements_plot.py similarity index 98% rename from src/unitary_decomp/plot/clements_plot.py rename to src/udecomp/plot/clements_plot.py index 09f50b5..44d41e1 100644 --- a/src/unitary_decomp/plot/clements_plot.py +++ b/src/udecomp/plot/clements_plot.py @@ -27,7 +27,7 @@ import pandas as pd from scipy.stats import linregress, unitary_group -from unitary_decomp.clements_interferometer import circuit_reconstruction, clements_decomposition +from udecomp.clements_interferometer import circuit_reconstruction, clements_decomposition def fidelity(V: np.ndarray, U: np.ndarray) -> float: diff --git a/src/unitary_decomp/plot/phases_plot.py b/src/udecomp/plot/phases_plot.py similarity index 91% rename from src/unitary_decomp/plot/phases_plot.py rename to src/udecomp/plot/phases_plot.py index 4617faf..b103d46 100644 --- a/src/unitary_decomp/plot/phases_plot.py +++ b/src/udecomp/plot/phases_plot.py @@ -24,8 +24,8 @@ >>> import matplotlib.pyplot as plt >>> from scipy.stats import unitary_group - >>> from unitary_decomp.plot.phases_plot import plot_phases - >>> from unitary_decomp import compact_fourier_decomposition + >>> from udecomp.plot.phases_plot import plot_phases + >>> from udecomp import compact_fourier_decomposition >>> # Generate a random unitary matrix >>> U = unitary_group(10, seed=42).rvs() @@ -48,8 +48,8 @@ import matplotlib.pyplot as plt import numpy as np -from unitary_decomp.fourier_interferometer import FourierDecomp -from unitary_decomp.lplm_interferometer import LplmDecomp +from udecomp.fourier_interferometer import FourierDecomp +from udecomp.lplm_interferometer import LplmDecomp def _generate_phase_matrix(decomposition: FourierDecomp | LplmDecomp) -> np.ndarray: @@ -80,8 +80,8 @@ def plot_phases( Args: decomposition (FourierDecomp | LplmDecomp): The decomposition object containing the mask sequence. Can be obtained from - `unitary_decomp.fourier_interferometer.compact_fourier_decomposition` or - `unitary_decomp.lplm_interferometer.lplm_decomposition`. + `udecomp.fourier_interferometer.compact_fourier_decomposition` or + `udecomp.lplm_interferometer.lplm_decomposition`. ax (plt.Axes, optional): The matplotlib Axes object to plot on. If None, a new figure and axes will be created. diff --git a/tests/test_bell_interferometer.py b/tests/test_bell_interferometer.py index f631598..4f86c4e 100644 --- a/tests/test_bell_interferometer.py +++ b/tests/test_bell_interferometer.py @@ -17,7 +17,7 @@ from scipy.linalg import dft from scipy.stats import unitary_group -from unitary_decomp import bell_interferometer as bi +from udecomp import bell_interferometer as bi """Unit tests for the Bell Interferometer module.""" diff --git a/tests/test_clements_interferometer.py b/tests/test_clements_interferometer.py index 049e2ed..5f93cc8 100644 --- a/tests/test_clements_interferometer.py +++ b/tests/test_clements_interferometer.py @@ -17,7 +17,7 @@ from scipy.fft import fft from scipy.stats import unitary_group -from unitary_decomp import clements_interferometer as ci +from udecomp import clements_interferometer as ci """Unit tests for the Clements interferometer module.""" diff --git a/tests/test_fourier_interferometer.py b/tests/test_fourier_interferometer.py index 0990e85..594c59c 100644 --- a/tests/test_fourier_interferometer.py +++ b/tests/test_fourier_interferometer.py @@ -17,8 +17,8 @@ from scipy.linalg import dft from scipy.stats import unitary_group -import unitary_decomp.fourier_interferometer as fi -from unitary_decomp import matrix_operations as mo +import udecomp.fourier_interferometer as fi +from udecomp import matrix_operations as mo """Unit tests for the Fourier Interferometer module.""" diff --git a/tests/test_fourier_optimizer.py b/tests/test_fourier_optimizer.py index 7e6721a..115bc14 100644 --- a/tests/test_fourier_optimizer.py +++ b/tests/test_fourier_optimizer.py @@ -16,9 +16,9 @@ import pytest from scipy.stats import unitary_group -from unitary_decomp.fourier_interferometer import circuit_reconstruction -from unitary_decomp.matrix_operations import matrix_interleave -from unitary_decomp.optimization.fourier_optimizer import fidelity, mask_optimizer +from udecomp.fourier_interferometer import circuit_reconstruction +from udecomp.matrix_operations import matrix_interleave +from udecomp.optimization.fourier_optimizer import fidelity, mask_optimizer """Unit tests for the `fourier_optimizer` module.""" diff --git a/tests/test_jax_optimizer.py b/tests/test_jax_optimizer.py index 2016b4a..b8dda9b 100644 --- a/tests/test_jax_optimizer.py +++ b/tests/test_jax_optimizer.py @@ -17,8 +17,8 @@ from scipy.linalg import dft from scipy.stats import unitary_group -import unitary_decomp.optimization.jax_optimizer as jax_opt -from unitary_decomp.fourier_interferometer import FourierDecomp, circuit_reconstruction +import udecomp.optimization.jax_optimizer as jax_opt +from udecomp.fourier_interferometer import FourierDecomp, circuit_reconstruction np.random.seed(42) diff --git a/tests/test_lplm_interferometer.py b/tests/test_lplm_interferometer.py index 0a1ff4d..eabea2c 100644 --- a/tests/test_lplm_interferometer.py +++ b/tests/test_lplm_interferometer.py @@ -17,7 +17,7 @@ from scipy.linalg import dft from scipy.stats import unitary_group -import unitary_decomp.lplm_interferometer as li +import udecomp.lplm_interferometer as li np.random.seed(42) diff --git a/tests/test_matrix_operations.py b/tests/test_matrix_operations.py index 95f48d8..ba6a945 100644 --- a/tests/test_matrix_operations.py +++ b/tests/test_matrix_operations.py @@ -17,7 +17,7 @@ from scipy.linalg import dft from scipy.stats import unitary_group -from unitary_decomp import matrix_operations as mo +from udecomp import matrix_operations as mo """Unit tests for the matrix operations module."""