Algorithms for decomposition of CPTP-maps
This code base contains implementations of the algorithm in the paper The Choi-Cholesky algorithm for completely positive maps, in order to empirically verify the correctness of the Choi–Cholesky decomposition of CP- (resp. CPTP-) maps, $\Phi$. Numerical verification occurs by:
Randomly generating a large number of CP- (resp. CPTP-) maps $\Phi$ dually represented by their Choi-matrices $C_{\Phi}$;
Computing the decompositions (the main algorithm)
$$ C_{\Phi} \overset{!}{=} L^{(\Phi)} : (L^{(\Phi)})^{\ast} $$
Verifying that the relative difference
$$ \frac{ | L^{(\Phi)} : (L^{(\Phi)})^{\ast} - C_{\Phi} | }{ | C_{\Phi} | } $$
between the recovered Choi-matrices and the original is below a given tolerance.
References
This code base can be cited[^1] as
@misc{Dahya2026RepoChoiCholesky,
author = {Dahya, Raj},
title = {{Choi--Cholesky}},
subtitle = {{Algorithms for decomposition of CPTP-maps}},
publisher = {Hugging Face},
doi = {10.57967/hf/8114},
url = {https://doi.org/10.57967/hf/8114},
note = {{Code base available under \url{https://doi.org/10.57967/hf/8114}, Release vX.Y.Z}},
year = {2026}}
and the associated paper as
@misc{Dahya2026PreprintChoiCholesky,
author = {Dahya, Raj},
title = {{The Choi-Cholesky algorithm for completely positive maps}},
publisher = {arXiv},
doi = {10.48550/arXiv.2603.19444},
url = {https://doi.org/10.48550/arXiv.2603.19444},
year = {2026}}
Contents
This code base is modularised as follows:
src/algorithms/choi_cholesky contains the algorithm presented in the paper.
src/experiments/choi_cholesky contains a numerical experiment which involves iterative
generation of random CP-/CPTP-maps
execution of the algorithm
raising of errors to mark failure (i.e. no raised errors implies empirical validation).
src/examples.py contains the entry point for the application (see below).
Usage
There are three ways to use the code in this repository:
- as a package;
- as an open source code base;
- as an open source code base using task runners.
We recommend the 1st variant for those who want to dive in. For developers/contributors the 3rd variant is useful.
System requirements
- python3.10--14 (tested on python3.14)
- bash or bash-like terminal
Usage as package
Install the package by setting adding this package as a dependency within your pyproject.toml for example as follows:
[project] name = "example" version = "0.0.0" description = 'Example code base' authors = [ {name="me", email="me@users.noreply.git.com"}, ] urls = {homepage = 'https://git.com/me/example'} maintainers = [ {name="me", email="me@users.noreply.git.com"}, ] license = 'MIT' readme = 'README.md' keywords = [ "python", ] classifiers = [ "Programming Language :: Python :: 3", ] requires-python = ">=3.11,<3.15" dependencies = [ "pip>=26.0.1", # third party package - replace vX.Y.Z by desired version "choi-cholesky @ git+https://hf.co/raj-dahya/choi-cholesky.git@vX.Y.Z#egg=choi-cholesky", # to include Rust backend # "choi-cholesky[rust] @ git+https://hf.co/raj-dahya/choi-cholesky.git@vX.Y.Z#egg=choi-cholesky", ] [dependency-groups] dev = [ "uv>=0.11.2", "ruff>=0.15.8", "pytest>=9.0.2", "maturin>=1.12.6", ] [build-system] requires = [ "setuptools>=82.0.1", "wheel>=0.46.3", "maturin>=1.12.6,<2.0", ] build-backend = "setuptools.build_meta" [tool.pip] extra-index-url = []In your python script use the package as follows
import logging from choi_cholesky.algorithms.generation import * from choi_cholesky.algorithms.choi_cholesky import * from choi_cholesky.experiments.choi_cholesky import * if __name__ == "__main__": # optional seed seed = "1234" # or None # set up logging logging.basicConfig( format="%(asctime)s $\x1b[92;1m%(name)s\x1b[0m [\x1b[1m%(levelname)s\x1b[0m] %(message)s", datefmt=r"%Y-%m-%d %H:%M:%S", encoding="utf-8", ) logging.getLogger().setLevel(logging.INFO) # create Choi matrix of random CP-map C = random_cp(10, 20, seed=seed) logging.info(C.shape) # (10, 10, 20, 20) # create Choi matrix of random CPTP-map C = random_cptp(10, 20, seed=seed) logging.info(C.shape) # (10, 10, 20, 20) # run Choi-Cholesky decomposition: L = algorithm_choi_cholesky(C, tol=1e-6) # algorithm in paper diff = tensor_diff(tensor_multiply(L, tensor_conj(L)), C) print(f"‖L·L^† – C(Φ)‖ = {diff:.4g}") L = algorithm_choi_cholesky_modified(C, tol=1e-6) # equivalent but modified version diff = tensor_diff(tensor_multiply(L, tensor_conj(L)), C) print(f"‖L·L^† – C(Φ)‖ = {diff:.4g}") # run numerical experiment to empirically verify correctness of algorithm verify_choi_cholesky( # d1 = dim(H1), d2 = dim(H2) d1=10, d2=20, # number of iterations in which a CP-map Φ : L^1(H1) - L^1(H2) is defined and decomposed n=100, # generate random CP-maps (or CPTP-maps) in each iteration map="CP", # choices: "CP", "CPTP" # use the Choi-Cholesky algorithm (or the modified one) in each iteration algorithm="CHOI-CHOLESKY", # choices: "CHOI-CHOLESKY", "CHOI-CHOLESKY-MODIFIED" # optional seed seed=seed, )
Usage as open source code base
Clone the repository.
On linux/osx run the following bash commands within the repository
# create and activate virtual environment python3 -m venv .venv . .venv/bin/activate # install and upgrades package manager python3 -m pip install --upgrade pip uv # install depdendencies using the uv package manager python3 -m uv sync --compile-bytecode --no-managed-python --no-python-downloadsor for windows users
# create and activate virtual environment py -3 -m venv .venv . .venv/Scripts/activate # install and upgrades package manager python -m pip install --upgrade pip uv # install depdendencies using the uv package manager python -m uv sync --compile-bytecode --no-managed-python --no-python-downloadsWithin a bash terminal activate the virtual environment
. .venv/bin/activate # for linux/osx . .venv/Scripts/activate # for windowsRun the script[^2]
python3 -m src.examples --help # to display help python3 -m src.examples version # to display version information python3 -m src.examples # runs the numerical experiment with default settings # run the numerical experiment with custom settings python3 -m src.examples --algorithm ... --map ... --num ... --dim1 ... --dim2 ... --seed ...(see below for the flag options).
Usage as open source code base with task runner
For those with the Justfile tool, setup and execution is a lot easier:
Clone the repository
Call
just setupand modify the contents of the newly created .env file (viz. setPYTHON_PATHto the command for your system).Call
just buildto build a virtual environment + dependencies.Now one may call
just run-examples --help # to display help just run-examples version # to display version information just run-examples # runs the numerical experiment with default settings just run-examples --algorithm ... --map ... --num ... --dim1 ... --dim2 ... --seed ...(see below for the flag options).
Cli-Flags
The command line interface flags for the execution of the application are as follows
| Flag | Value | Description |
|---|---|---|
-a / --algorithm |
(default) "CHOI-CHOLESKY" |
uses the Choi–Cholesky decomposition as in the paper |
| " | "CHOI-CHOLESKY-MODIFIED" |
uses a slightly optimised variant of the Choi–Cholesky decomposition to reduce floating point errors |
-m / --map |
(default) "CP" |
during each iteration of the verification generate (the Choi-matrix of) a random CP-map |
| " | "CPTP" | during each iteration of the verification generate (the Choi-matrix of) a random CPTP-map |
-n / --num |
<integer> (default=100) |
number of iterations in experiment |
--dim1 |
<integer> (default=10) |
dimension of the "input" Hilbert space H1 |
--dim2 |
<integer> (default=20) |
dimension of the "output" Hilbert space H2 |
--seed |
<string> (default: null, examples: "1234", "abc", etc.) |
if set, seeds the random number generator for repeatability |
Rust bindings for python
An implementation in rust has been provided, which mirrors the python setup, but has the advantages of a compiled package which includes parallelisation. To use it add the dependency
...
dependencies = [
...
# third party package - replace vX.Y.Z by desired version
"choi-cholesky[rust] @ git+https://hf.co/raj-dahya/choi-cholesky.git@vX.Y.Z#egg=choi-cholesky",
...
]
...
to your pyproject.toml manifest (see above).
One can then use the script as follows:
import logging
# import basic methods
from choi_cholesky.models.linalg.bipartite import tensor_diff
from choi_cholesky.models.linalg.bipartite import tensor_conj
from choi_cholesky.models.linalg.bipartite import tensor_multiply
# import critical methods from rust backend for improved efficiency
from choi_cholesky_rust import random_cp
from choi_cholesky_rust import random_cptp
from choi_cholesky_rust import algorithm_choi_cholesky
from choi_cholesky_rust import algorithm_choi_cholesky_modified
from choi_cholesky_rust import verify_choi_cholesky
if __name__ == "__main__":
seed = "1234"
# set up logging
logging.basicConfig(
format="%(asctime)s $\x1b[92;1m%(name)s\x1b[0m [\x1b[1m%(levelname)s\x1b[0m] %(message)s",
datefmt=r"%Y-%m-%d %H:%M:%S",
encoding="utf-8",
)
logging.getLogger().setLevel(logging.INFO)
# create Choi matrix of random CP-map
# NOTE: underlying linear algebraic operation (computation of operator norm) to ensure C is a contraction is subject to correction.
try:
C = random_cp(10, 20, seed=seed)
logging.info(C.shape) # (10, 10, 20, 20)
except Exception as err:
logging.error(err)
# create Choi matrix of random CPTP-map
C = random_cptp(10, 20, seed=seed)
logging.info(C.shape) # (10, 10, 20, 20)
# run Choi-Cholesky decomposition:
L = algorithm_choi_cholesky(C, tol=1e-6) # algorithm in paper
diff = tensor_diff(tensor_multiply(L, tensor_conj(L)), C)
print(f"‖L·L^† – C(Φ)‖ = {diff:.4g}")
L = algorithm_choi_cholesky_modified(C, tol=1e-6) # equivalent but modified version
diff = tensor_diff(tensor_multiply(L, tensor_conj(L)), C)
print(f"‖L·L^† – C(Φ)‖ = {diff:.4g}")
# run numerical experiment to empirically verify correctness of algorithm
# NOTE: using rust backend, this runs the experiments in parallel
verify_choi_cholesky(
# d1 = dim(H1), d2 = dim(H2)
d1=10,
d2=20,
# number of iterations in which a CP-map Φ : L^1(H1) - L^1(H2) is defined and decomposed
n=1000,
# generate random CP-maps (or CPTP-maps) in each iteration
map="CP", # choices: "CP", "CPTP"
# use the Choi-Cholesky algorithm (or the modified one) in each iteration
algorithm="CHOI-CHOLESKY", # choices: "CHOI-CHOLESKY", "CHOI-CHOLESKY-MODIFIED"
# optional seed
seed=seed,
)
[^1]: the version in note can be replaced by given version or commit id used.
[^2]: On windows within the venv one must use python instead of python3