Skip to content

Commit

Permalink
quick fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
purva-thakre committed Oct 29, 2023
1 parent 9f3cee1 commit b23aa80
Show file tree
Hide file tree
Showing 17 changed files with 69 additions and 69 deletions.
2 changes: 1 addition & 1 deletion toqito/channel_metrics/completely_bounded_trace_norm.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def completely_bounded_trace_norm(phi: np.ndarray) -> float:
if is_quantum_channel(phi):
return 1

elif is_completely_positive(phi):
if is_completely_positive(phi):
v = apply_channel(np.eye(dim_ly), dual_channel(phi))
return trace_norm(v)

Expand Down
39 changes: 18 additions & 21 deletions toqito/channel_metrics/fidelity_of_separability.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@


def fidelity_of_separability(
psi: np.ndarray, psi_dims: list[int], k: int = 1, verbosity_option=2, solver_option="cvxopt"
psi: np.ndarray, psi_dims: list[int], k: int = 1, verbosity_option: int=2, solver_option: str="cvxopt"
) -> float:
r"""
Define the first benchmark introduced in Appendix I of [Phil23.1]_ .
Expand Down Expand Up @@ -113,28 +113,25 @@ def fidelity_of_separability(
“The Theory of Quantum Information”
Cambridge University Press, 2018
Args:
psi: the density matrix for the tripartite state of interest psi_{BAR}
psi_dims: the dimensions of System A, B, & R in
:param psi: the density matrix for the tripartite state of interest psi_{BAR}
:param psi_dims: the dimensions of System A, B, & R in
the input state density matrix. It is assumed that the first
quantity in this list is the dimension of System B.
k: value for k-extendibility.
verbosity_option: Parameter option for `picos`. Default value is `verbosity = 2`.
For more info, visit https://picos-api.gitlab.io/picos/api/picos.modeling.options.html#option-verbosity
solver_option: Optimization option for `picos` solver. Default option is `solver_option="cvxopt"`
For more info, visit https://picos-api.gitlab.io/picos/api/picos.modeling.options.html#option-solver
Raises:
AssertionError:
* If the provided dimensions are not for a tripartite density
matrix.
TypeError:
* If the matrix is not a density matrix (square matrix that is \n
PSD with trace 1).
TypeError:
* If the input state is a mixed state.
Returns:
Optimized value of the SDP when maximized over a set of linear
operators subject to some constraints.
:param k: value for k-extendibility.
:param verbosity_option: Parameter option for `picos`. Default value is
`verbosity = 2`. For more info, visit
https://picos-api.gitlab.io/picos/api/picos.modeling.options.html#option-verbosity.
:param solver_option: Optimization option for `picos` solver. Default option is
`solver_option="cvxopt"`. For more info, visit
https://picos-api.gitlab.io/picos/api/picos.modeling.options.html#option-solver.
:raises AssertionError: If the provided dimensions are not for a tripartite density matrix.
:raises ValueError: If the matrix is not a density matrix (square matrix that
is PSD with trace 1).
:raises ValueError: the input state is entangled.
:raises ValueError: the input state is a mixed state.
:return: Optimized value of the SDP when maximized over a set of linear
operators subject to some constraints.
"""
if not is_density(psi):
raise ValueError("Provided input state is not a density matrix.")
Expand Down
9 changes: 6 additions & 3 deletions toqito/channels/partial_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

def partial_trace(
input_mat: np.ndarray | Variable,
sys: int | list[int] = [1],
sys: int | list[int] = None,
dim: int | list[int] = None,
) -> np.ndarray | Expression:
r"""
Expand Down Expand Up @@ -130,6 +130,9 @@ def partial_trace(
equal.
:return: The partial trace of matrix :code:`input_mat`.
"""
if not isinstance(sys, int):
if sys is None:
sys = [1]
# If the input matrix is a CVX variable for an SDP, we convert it to a numpy array,
# perform the partial trace, and convert it back to a CVX variable.
if isinstance(input_mat, Variable):
Expand All @@ -145,10 +148,10 @@ def partial_trace(
if isinstance(dim, list):
dim = np.array(dim)

num_sys = len(dim)


# Allow the user to enter a single number for dim.
if num_sys == 1:
if (num_sys := len(dim)) == 1:
dim = np.array([dim[0], len(input_mat) / dim[0]])
if np.abs(dim[1] - np.round(dim[1])) >= 2 * len(input_mat) * np.finfo(float).eps:
raise ValueError(
Expand Down
6 changes: 3 additions & 3 deletions toqito/channels/partial_transpose.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

def partial_transpose(
rho: np.ndarray | Variable,
sys: list[int] | np.ndarray | int = [1],
sys: list[int] | np.ndarray | int = 1,
dim: list[int] | np.ndarray = None,
) -> np.ndarray | Expression:
r"""Compute the partial transpose of a matrix [WikPtrans]_.
Expand Down Expand Up @@ -135,9 +135,9 @@ def partial_transpose(
if isinstance(sys, int):
sys = np.array([sys])

num_sys = max(dim.shape)

# Allow the user to enter a single number for dim.
if num_sys == 1:
if (num_sys := max(dim.shape)) == 1:
dim = np.array([dim, list(rho.shape)[0] / dim])
if np.abs(dim[1] - np.round(dim[1]))[0] >= 2 * list(rho.shape)[0] * np.finfo(float).eps:
raise ValueError(
Expand Down
2 changes: 1 addition & 1 deletion toqito/helper/npa_hierarchy.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def _get_nonlocal_game_params(
return a_out, a_in, b_out, b_in


def npa_constraints(
def npa_constraints(# pylint: disable=too-many-locals
assemblage: dict[tuple[int, int], cvxpy.Variable], k: int | str = 1, referee_dim: int = 1
) -> list[cvxpy.constraints.constraint.Constraint]:
r"""
Expand Down
3 changes: 2 additions & 1 deletion toqito/matrix_ops/inner_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ def inner_product(v1: np.ndarray, v2: np.ndarray) -> float:
https://en.wikipedia.org/wiki/Inner_product_space
:raises ValueError: Vector dimensions are mismatched.
:param args: v1 and v2, both vectors of dimenstions :math:`(n,1)` where :math:`n>1`.
:param v1: v1 and v2, both vectors of dimenstions :math:`(n,1)` where :math:`n>1`.
:param v2: v1 and v2, both vectors of dimenstions :math:`(n,1)` where :math:`n>1`.
:return: The computed inner product.
"""
# Check for dimensional validity
Expand Down
3 changes: 2 additions & 1 deletion toqito/matrix_ops/outer_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ def outer_product(v1: np.ndarray, v2: np.ndarray) -> np.ndarray:
https://en.wikipedia.org/wiki/Outer_product
:raises ValueError: Vector dimensions are mismatched.
:param args: v1 and v2, both vectors of dimensions :math:`(n,1)` where :math:`n>1`.
:param v1: v1 and v2, both vectors of dimenstions :math:`(n,1)` where :math:`n>1`.
:param v2: v1 and v2, both vectors of dimenstions :math:`(n,1)` where :math:`n>1`.
:return: The computed outer product.
"""
# Check for dimensional validity
Expand Down
8 changes: 6 additions & 2 deletions toqito/matrix_ops/vectors_from_gram_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@


def vectors_from_gram_matrix(gram: np.ndarray) -> list[np.ndarray]:
"""Obtain the corresponding ensemble of states from the Gram matrix."""
"""Obtain the corresponding ensemble of states from the Gram matrix.
:param gram: Input Gram matrix.
:return: list of ensemble states
"""
dim = gram.shape[0]
# If matrix is PD, can do Cholesky decomposition:
try:
decomp = np.linalg.cholesky(gram)
return [decomp[i][:] for i in range(dim)]
# Otherwise, need to do eigendecomposition:
except Exception:
except Exception: # pylint: disable=broad-except
print("Matrix is not positive semidefinite. Using eigendecomposition as alternative.")
d, v = np.linalg.eig(gram)
return [np.sqrt(np.diag(d)) @ v[i].conj().T for i in range(dim)]
15 changes: 6 additions & 9 deletions toqito/matrix_props/sk_norm.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from toqito.states import max_entangled


def sk_operator_norm(
def sk_operator_norm( # pylint: disable=too-many-locals
mat: np.ndarray,
k: int = 1,
dim: int | list[int] = None,
Expand Down Expand Up @@ -227,7 +227,7 @@ def sk_operator_norm(
return op_norm * lower_bound, op_norm * upper_bound

# Start the semidefinite programming approach for getting upper bounds.
if effort >= 1 and (
if effort >= 1 and (# pylint: disable=too-many-boolean-expressions
(lower_bound + tol < upper_bound and is_positive)
or (is_positive and is_trans_exact and k == 1)
):
Expand Down Expand Up @@ -328,7 +328,7 @@ def __target_is_proved(
# Schmidt vectors of the other sub-system. This optimization is equivalent to
# a generalized eigenvalue problem. The algorithm terminates when an iteration
# cannot improve the lower bound by more than tol.
def __lower_bound_sk_norm_randomized(
def __lower_bound_sk_norm_randomized(# pylint: disable=too-many-locals
mat: np.ndarray,
k: int = 1,
dim: int | list[int] = None,
Expand All @@ -350,8 +350,7 @@ def __lower_bound_sk_norm_randomized(
opt_vec = None
if start_vec is not None:
singular_vals, vt_mat, u_mat = schmidt_decomposition(start_vec, dim)
s_rank = len(singular_vals)
if s_rank > k:
if (s_rank := len(singular_vals)) > k:
warnings.warn(
f"The Schmidt rank of the initial vector is {s_rank}, which is larger than k={k}. \
Using a randomly-generated intial vector instead."
Expand Down Expand Up @@ -383,8 +382,7 @@ def __lower_bound_sk_norm_randomized(
for p in range(2):
# If Schmidt rank is not full, we will have numerical problems; go to
# lower Schmidt rank iteration.
s_rank = schmidt_rank(opt_vec, dim)
if s_rank < k:
if (s_rank := schmidt_rank(opt_vec, dim)) < k:
return __lower_bound_sk_norm_randomized(mat, s_rank, dim, tol, opt_vec)

# Fix one of the parties and optimize over the other party.
Expand All @@ -399,9 +397,8 @@ def __lower_bound_sk_norm_randomized(
largest_eigval, largest_eigvec = scipy.linalg.eigh(
a_mat, b=b_mat, subset_by_index=[a_mat.shape[0] - 1, a_mat.shape[0] - 1]
)
new_sk_lower_bound = np.real(largest_eigval[0])

if new_sk_lower_bound >= sk_lower_bound + tol:
if (new_sk_lower_bound := np.real(largest_eigval[0])) >= sk_lower_bound + tol:
it_lower_bound_improved = True
sk_lower_bound = new_sk_lower_bound

Expand Down
4 changes: 1 addition & 3 deletions toqito/perms/perfect_matchings.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@ def perfect_matchings(num: list[int] | int | np.ndarray) -> np.ndarray:
if isinstance(num, list):
num = np.array(num)

len_num = len(num)

# Base case, `num = 2`: only one perfect matching.
if len_num == 2:
if (len_num := len(num)) == 2:
return num

# There are no perfect matchings of an odd number of objects.
Expand Down
5 changes: 1 addition & 4 deletions toqito/random/random_povm.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,7 @@ def random_povm(dim: int, num_inputs: int, num_outputs: int) -> np.ndarray:
povms = []
gram_vectors = np.random.normal(size=(num_inputs, num_outputs, dim, dim))
for input_block in gram_vectors:
normalizer = sum(
[np.array(output_block).T.conj() @ output_block for output_block in input_block]
)

normalizer = sum(np.array(output_block).T.conj() @ output_block for output_block in input_block)
u_mat, d_mat, _ = np.linalg.svd(normalizer)

output_povms = []
Expand Down
6 changes: 3 additions & 3 deletions toqito/state_metrics/fidelity_of_separability.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
from toqito.state_props import is_pure, is_separable


def fidelity_of_separability(# pylint: disable = missing-type-doc
def fidelity_of_separability(
input_state_rho: np.ndarray,
input_state_rho_dims: list[int],
k: int = 1,
verbosity_option=2,
solver_option="cvxopt",
verbosity_option: int=2,
solver_option: str ="cvxopt",
) -> float:
r"""
Define the first benchmark introduced in Appendix H of [Phil23]_.
Expand Down
4 changes: 2 additions & 2 deletions toqito/state_opt/ppt_distinguishability.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def ppt_distinguishability(


def primal_problem(
states: list[np.ndarray], probs: list[float] = None, dist_method="min-error"
states: list[np.ndarray], probs: list[float] = None, dist_method: str="min-error"
) -> float:
r"""
Calculate primal problem for PPT distinguishability.
Expand Down Expand Up @@ -204,7 +204,7 @@ def primal_problem(


def dual_problem(
states: list[np.ndarray], probs: list[float] = None, dist_method="min-error"
states: list[np.ndarray], probs: list[float] = None, dist_method: str="min-error"
) -> float:
r"""
Calculate dual problem for PPT distinguishability.
Expand Down
11 changes: 7 additions & 4 deletions toqito/state_opt/state_exclusion.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


def state_exclusion(
vectors: list[np.ndarray], probs: list[float] = None, solver: str = "cvxopt", primal_dual="dual"
vectors: list[np.ndarray], probs: list[float] = None, solver: str = "cvxopt", primal_dual: str ="dual"
) -> tuple[float, list[picos.HermitianVariable]]:
r"""
Compute probability of single state exclusion.
Expand Down Expand Up @@ -86,16 +86,19 @@ def state_exclusion(
Physical Review A 89.2 (2014): 022336.
arXiv:1306.4683
:param states: A list of states provided as vectors.
:param vectors: A list of states provided as vectors.
:param probs: Respective list of probabilities each state is selected. If no
probabilities are provided, a uniform probability distribution is assumed.
:param solver: Optimization option for `picos` solver. Default option is
`solver_option="cvxopt"`.
:param primal_dual: Option for the optimization problem
:return: The optimal probability with which Bob can guess the state he was
not given from `states` along with the optimal set of measurements.
"""
if primal_dual == "primal":
return _min_error_primal(vectors, probs, solver)
else:
return _min_error_dual(vectors, probs, solver)

return _min_error_dual(vectors, probs, solver)


def _min_error_primal(vectors: list[np.ndarray], probs: list[float] = None, solver: str = "cvxopt"):
Expand Down
3 changes: 1 addition & 2 deletions toqito/state_props/is_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,10 @@ def _is_product(rho: np.ndarray, dim: int | list[int] = None) -> list[int, bool]
# If there are only two subsystems, just use the Schmidt decomposition.
if num_sys == 2:
singular_vals, u_mat, vt_mat = schmidt_decomposition(rho, dim, 2)
ipv = singular_vals[1] <= np.prod(dim) * np.spacing(singular_vals[0])

# Provide this even if not requested, since it is needed if this
# function was called as part of its recursive algorithm (see below)
if ipv:
if (ipv := singular_vals[1] <= np.prod(dim) * np.spacing(singular_vals[0])):
u_mat = u_mat * np.sqrt(singular_vals[0])
vt_mat = vt_mat * np.sqrt(singular_vals[0])
dec = [u_mat[:, 0], vt_mat[:, 0]]
Expand Down
16 changes: 8 additions & 8 deletions toqito/state_props/is_separable.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from toqito.channels import realignment
from toqito.matrix_props import is_positive_semidefinite, trace_norm
from toqito.perms import swap

from toqito.state_props import in_separable_ball, is_ppt
from toqito.state_props.has_symmetric_extension import has_symmetric_extension

Expand Down Expand Up @@ -161,10 +161,11 @@ def is_separable(

# For the rest of the block-matrix tests, we need the 2-dimensional subsystem to be the
# first subsystem, so swap accordingly.
if dim[0] > 2:
Xt = swap(state, [1, 2], dim)
else:
Xt = state
#if dim[0] > 2:
# Xt = swap(state, [1, 2], dim)
#else:
# Xt = state
# commented out because pylint flagged this as an unused variable

# Check the proximity of X with the maximally mixed state.
if in_separable_ball(state):
Expand All @@ -182,7 +183,6 @@ def is_separable(
return True

# The search for symmetric extensions.
for _ in range(2, level):
if has_symmetric_extension(state, level):
return True
if any(has_symmetric_extension(state, level) for _ in range(2, level)):
return True
return False
2 changes: 1 addition & 1 deletion toqito/states/basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def basis(dim: int, pos: int) -> np.ndarray:
"Invalid: The `pos` variable needs to be less than `dim` for ket function."
)

ret = np.array(list(map(int, list(f"{0:0{dim}}"))))
ret = np.array(list(int(x) for x in list(f"{0:0{dim}}")))
ret[pos] = 1
ret = ret.conj().T.reshape(-1, 1)
return ret

0 comments on commit b23aa80

Please sign in to comment.