Skip to content

Commit

Permalink
Repo structure (#3)
Browse files Browse the repository at this point in the history
* refactor: create basic folder structure

* meta: add license

* meta: add basic tooling

* ci: add basic Travis CI configuration

* nb: remove imports from notebook

The notebook still has other issues but those can be resolved later.

* lint: format with ruff

* lint: satisfy pydocstyle

This just adds TODO placeholders in the docstrings but at least gets the
basic structure of them into the right shape.

* lint: satisfy mypy

* lint: satisfy pylint

* lint: satisfy nbqa
  • Loading branch information
mrossinek authored and GitHub Enterprise committed Mar 4, 2024
1 parent e87163b commit 6165fcb
Show file tree
Hide file tree
Showing 18 changed files with 532 additions and 175 deletions.
44 changes: 44 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
language: python

jobs:
include:
# Lint tests
- python: 3.10
env: TOXENV=lint
script: tox -e $TOXENV

# Coverage tests
- python: 3.10
env: TOXENV=coverage
script: tox -e $TOXENV

# Unit tests (py39)
- python: 3.9
env: TOXENV=py39
script: tox -e $TOXENV

# Unit tests (py310)
- python: 3.10
env: TOXENV=py310
script: tox -e $TOXENV

# Unit tests (py311)
- python: 3.11
env: TOXENV=py311
script: tox -e $TOXENV

# Unit tests (py312)
- python: 3.12
env: TOXENV=py312
script: tox -e $TOXENV

# Notebook tests
- python: 3.10
before_install:
- sudo apt-get update
env: TOXENV=notebook
script: tox -e $TOXENV

install:
- pip install --upgrade pip
- pip install tox
1 change: 1 addition & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
IBM Restricted
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# IC-POVM
Informationally complete POVM
# POVMs

This is a first try
A module for the implementation of positive operator-valued measures (POVMs).
17 changes: 7 additions & 10 deletions test.ipynb → notebooks/test.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
"from base_povm import Povm\n",
"from single_qubit_povm import SingleQubitPOVM\n",
"from povm_implementation import ProductPVMSimPOVMImplementation\n",
"from test_base_povm import TestBasePovm\n",
"\n",
"from qiskit.quantum_info import random_density_matrix, Operator"
]
},
Expand Down Expand Up @@ -421,11 +419,11 @@
"sqpovm = SingleQubitPOVM.from_vectors()\n",
"print(sqpovm.check_validity())\n",
"\n",
"sum = np.zeros(4, dtype=complex)\n",
"summed = np.zeros(4, dtype=complex)\n",
"for coef in sqpovm.povm_pauli_decomp:\n",
" sum += coef\n",
" summed += coef\n",
"\n",
"sum"
"summed"
]
},
{
Expand Down Expand Up @@ -679,8 +677,6 @@
}
],
"source": [
"import numpy as np\n",
"from povm_implementation import ProductPVMSimPOVMImplementation\n",
"povm_implementation = ProductPVMSimPOVMImplementation(2, np.array([0,0, 1,0.5, 1,1, 1,1, 0,0, 1,0.5, 0.3,0.2, 2,1]))\n",
"povm_implementation._build_qc().draw()"
]
Expand Down Expand Up @@ -1165,6 +1161,7 @@
" return povm\n",
"\n",
"def compare_povms(povm1: Povm, povm2: Povm, tol:float=1e-5) -> bool:\n",
" del tol\n",
" povm1 = clean_povm(povm1)\n",
" povm2 = clean_povm(povm2)\n",
"\n",
Expand Down Expand Up @@ -1379,7 +1376,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
Expand All @@ -1393,9 +1390,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.7"
"version": "3.11.8"
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}
96 changes: 0 additions & 96 deletions povm_implementation.py

This file was deleted.

1 change: 1 addition & 0 deletions povms/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""TODO."""
79 changes: 55 additions & 24 deletions base_povm.py → povms/base_povm.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""TODO."""

from __future__ import annotations

import numpy as np

from qiskit.quantum_info import Operator, DensityMatrix
Expand All @@ -6,41 +10,49 @@
class Povm:
"""Abstract base class that collects all information that any POVM should specifiy."""

def __init__(self, povm_ops: np.ndarray):
def __init__(self, povm_ops: np.ndarray) -> None:
"""Initialize from explicit POVM operators.
Args:
povm_operators: np.ndarray that contains the explicit list of POVM operators"""
povm_operators: np.ndarray that contains the explicit list of POVM operators.
Raises:
ValueError: TODO.
"""
if not (len(povm_ops.shape) == 3 and povm_ops.shape[1] == povm_ops.shape[1]):
raise ValueError(
f"POVM operators need to be square instead of {povm_ops.shape[1:]}"
)
raise ValueError(f"POVM operators need to be square instead of {povm_ops.shape[1:]}")

self.n_outcomes = povm_ops.shape[0]
self.dimension = povm_ops.shape[1]
self.povm_operators = [Operator(op) for op in povm_ops]
self.n_outcomes: int = povm_ops.shape[0]
self.dimension: int = povm_ops.shape[1]
self.povm_operators: list[Operator] = [Operator(op) for op in povm_ops]
self.array_ops = None

self.dual_operators = None
self.frame_superop = None
self.informationlly_complete = None

def check_validity(self) -> bool:
"""Checks if POVM axioms are fulfilled."""
"""Check if POVM axioms are fulfilled.
summed_op = np.zeros((self.dimension, self.dimension), dtype=complex)
Returns:
TODO.
for k in range(len(self)):
Raises:
ValueError: TODO.
"""
summed_op: np.ndarray = np.zeros((self.dimension, self.dimension), dtype=complex)

if not np.allclose(self.povm_operators[k].data.conj().T - self.povm_operators[k].data, 0.0, atol=1e-5):
for k in range(len(self)):
if not np.allclose(
self.povm_operators[k].data.conj().T - self.povm_operators[k].data,
0.0,
atol=1e-5,
):
raise ValueError(f"POVM operator {k} is not hermitian.")

for eigval in np.linalg.eigvalsh(self.povm_operators[k].data):
if eigval.real < -1e-6 or np.abs(eigval.imag) > 1e-5:
raise ValueError(
f"Negative eigenvalue {eigval} in POVM operator {k}."
)
raise ValueError(f"Negative eigenvalue {eigval} in POVM operator {k}.")

summed_op += self.povm_operators[k].data

Expand All @@ -49,22 +61,41 @@ def check_validity(self) -> bool:

return True

def __getitem__(self, index: slice) -> np.ndarray:
def __getitem__(self, index: slice) -> Operator:
"""Return a povm operator or a list of povm operators."""
return self.povm_operators[index]

def __len__(self):

def __len__(self) -> int:
"""TODO."""
return len(self.povm_operators)

def get_prob(self, rho: DensityMatrix) -> np.ndarray:
return np.array([
np.real(np.trace(rho.data @ povm_op.data))
for povm_op in self.povm_operators])
"""TODO.
Args:
rho: TODO.
Returns:
TODO.
"""
return np.array(
[np.real(np.trace(rho.data @ povm_op.data)) for povm_op in self.povm_operators]
)

@classmethod
def from_vectors(cls, povm_vectors: np.ndarray):
"""Initialize a POVM from the bloch vectors |psi> (not normalized!) such that Pi = |psi><psi|."""
povm_operators = np.zeros((povm_vectors.shape[0], povm_vectors.shape[1], povm_vectors.shape[1]), dtype=complex)
def from_vectors(cls, povm_vectors: np.ndarray) -> Povm:
"""Initialize a POVM from the bloch vectors |psi> (not normalized!) such that Pi = |psi><psi|.
Args:
povm_vectors: TODO.
Returns:
TODO.
"""
povm_operators: np.ndarray = np.zeros(
(povm_vectors.shape[0], povm_vectors.shape[1], povm_vectors.shape[1]),
dtype=complex,
)
for i, vec in enumerate(povm_vectors):
povm_operators[i] = np.outer(vec, vec.conj())
return cls(povm_operators)
Expand Down
Loading

0 comments on commit 6165fcb

Please sign in to comment.