Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upated Indexing from 1 -> 0 #602

Merged
merged 18 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions toqito/channel_metrics/fidelity_of_separability.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def fidelity_of_separability(
raise ValueError("This function only works for pure states.")

# We first permure psi_{BAR} to psi_{RAB} to simplify the code.
psi = permute_systems(psi, [3, 2, 1], psi_dims)
psi = permute_systems(psi, [2, 1, 0], psi_dims)
dim_b, dim_a, dim_r = psi_dims
psi_dims = [dim_r, dim_a, dim_b]

Expand Down Expand Up @@ -163,7 +163,7 @@ def fidelity_of_separability(
pi_sym
* picos.partial_trace(
(picos.partial_transpose(psi, [0], psi_dims) @ picos.I(dim_a))
* permute_systems(choi_partial @ picos.I(dim_b * dim_a), [1, 4, 3, 2], dim_list),
* permute_systems(choi_partial @ picos.I(dim_b * dim_a), [0, 3, 2, 1], dim_list),
[0, 2],
dim_list,
)
Expand Down
2 changes: 1 addition & 1 deletion toqito/channel_ops/partial_channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def partial_channel(

phi_map = permute_systems(
np.kron(np.kron(psi_r1 * psi_c1.conj().T, phi_map), psi_r2 * psi_c2.conj().T),
[1, 3, 5, 2, 4, 6],
[0, 2, 4, 1, 3, 5],
dim,
)

Expand Down
4 changes: 2 additions & 2 deletions toqito/channels/partial_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,10 @@ def partial_trace(
sys = np.array(sys)
if isinstance(sys, int):
sys = np.array([sys])
set_diff = list(set(list(range(1, num_sys + 1))) - set(sys + 1))

set_diff = list(set(list(range(0, num_sys))) - set(sys))
anushkrishnav marked this conversation as resolved.
Show resolved Hide resolved
perm = set_diff
perm.extend(sys + 1)
perm.extend(sys)

a_mat = permute_systems(input_mat, perm, dim)

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 @@ -167,8 +167,8 @@ def partial_transpose(
sub_sys_vec_r = prod_dim_r * np.ones(int(sub_prod_r)) / sub_prod_r
sub_sys_vec_c = prod_dim_c * np.ones(int(sub_prod_c)) / sub_prod_c

set_diff = list(set(list(range(1, num_sys + 1))) - set(sys + 1))
perm = (sys + 1).tolist()[:]
set_diff = list(set(list(range(0, num_sys ))) - set(sys ))
anushkrishnav marked this conversation as resolved.
Show resolved Hide resolved
perm = (sys ).tolist()[:]
perm.extend(set_diff)

# Permute the subsystems so that we just have to do the partial transpose
Expand Down Expand Up @@ -198,6 +198,6 @@ def partial_transpose(
# Return the subsystems back to their original positions.
dim[:, sys] = np.flipud(dim[:, sys])

dim = dim[:, (np.array(perm) - 1).tolist()]
dim = dim[:, (np.array(perm) ).tolist()]

return permute_systems(z_tmp, perm, dim, False, True)
4 changes: 2 additions & 2 deletions toqito/nonlocal_games/quantum_hedging.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ def __init__(self, q_a: np.ndarray, num_reps: int) -> None:
# action:
# π(y1 ⊗ y2 ⊗ x1 ⊗ x2) = y1 ⊗ x1 ⊗ y2 ⊗ x2
# for all y1 ∈ Y1, y2 ∈ Y2, x1 ∈ X1, x2 ∈ X2.).
l_1 = list(range(1, self._num_reps + 1))
l_2 = list(range(self._num_reps + 1, self._num_reps**2 + 1))
l_1 = list(range(0, self._num_reps ))
purva-thakre marked this conversation as resolved.
Show resolved Hide resolved
l_2 = list(range(self._num_reps , self._num_reps**2 ))
if self._num_reps == 1:
self._pperm = np.array([1])
else:
Expand Down
2 changes: 1 addition & 1 deletion toqito/perms/antisymmetric_projection.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def antisymmetric_projection(dim: int, p_param: int = 2, partial: bool = False)
if dim < p_param:
return np.zeros((dimp, dimp * (1 - partial)))

p_list = np.array(list(permutations(np.arange(1, p_param + 1))))
p_list = np.array(list(permutations(np.arange(0, p_param ))))
purva-thakre marked this conversation as resolved.
Show resolved Hide resolved
p_fac = p_list.shape[0]

anti_proj = np.zeros((dimp, dimp))
Expand Down
9 changes: 4 additions & 5 deletions toqito/perms/permutation_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def permutation_operator(
qubits

.. math::
P_{2, [2, 1]} =
P_{2, [1, 0]} =
\begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 \\
Expand All @@ -38,13 +38,12 @@ def permutation_operator(
Using :code:`toqito`, this can be achieved in the following manner.

>>> from toqito.perms import permutation_operator
>>> permutation_operator(2, [2, 1])
>>> permutation_operator(2, [1, 0])
array([[1., 0., 0., 0.],
[0., 0., 1., 0.],
[0., 1., 0., 0.],
[0., 0., 0., 1.]])


:param dim: The dimensions of the subsystems to be permuted.
:param perm: A permutation vector.
:param inv_perm: Boolean dictating if :code:`perm` is inverse or not.
Expand All @@ -54,10 +53,10 @@ def permutation_operator(
"""
# Allow the user to enter a single number for `dim`.
if isinstance(dim, int):
dim = dim * np.ones(max(perm))
dim = [dim] * len(perm)
purva-thakre marked this conversation as resolved.
Show resolved Hide resolved
if isinstance(dim, list):
dim = np.array(dim)

mat = sp.sparse.identity(int(np.prod(dim))) if is_sparse else np.identity(int(np.prod(dim)))
# Swap the rows of the identity matrix appropriately.
anushkrishnav marked this conversation as resolved.
Show resolved Hide resolved

return permute_systems(mat, perm, dim, True, inv_perm)
19 changes: 12 additions & 7 deletions toqito/perms/permute_systems.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def permute_systems(

For spaces :math:`\mathcal{A}` and :math:`\mathcal{B}` where :math:`\text{dim}(\mathcal{A}) =
\text{dim}(\mathcal{B}) = 2` we may consider an operator :math:`X \in \mathcal{A} \otimes \mathcal{B}`. Applying the
`permute_systems` function with vector :math:`[2,1]` on :math:`X`, we may reorient the spaces such that :math:`X \in
`permute_systems` function with vector :math:`[1,0]` on :math:`X`, we may reorient the spaces such that :math:`X \in
\mathcal{B} \otimes \mathcal{A}`.

For example, if we define :math:`X \in \mathcal{A} \otimes \mathcal{B}` as
Expand All @@ -53,7 +53,7 @@ def permute_systems(
yield the following matrix

.. math::
X_{[2,1]} = \begin{pmatrix}
X_{[1,0]} = \begin{pmatrix}
1 & 3 & 2 & 4 \\
9 & 11 & 10 & 12 \\
5 & 7 & 6 & 8 \\
Expand All @@ -63,15 +63,15 @@ def permute_systems(
>>> from toqito.perms import permute_systems
>>> import numpy as np
>>> test_input_mat = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
>>> permute_systems(test_input_mat, [2, 1])
>>> permute_systems(test_input_mat, [1, 0])
array([[ 1, 3, 2, 4],
[ 9, 11, 10, 12],
[ 5, 7, 6, 8],
[13, 15, 14, 16]])

For spaces :math:`\mathcal{A}, \mathcal{B}`, and :math:`\mathcal{C}` where :math:`\text{dim}(\mathcal{A}) =
\text{dim}(\mathcal{B}) = \text{dim}(\mathcal{C}) = 2` we may consider an operator :math:`X \in \mathcal{A} \otimes
\mathcal{B} \otimes \mathcal{C}`. Applying the :code:`permute_systems` function with vector :math:`[2,3,1]` on
\mathcal{B} \otimes \mathcal{C}`. Applying the :code:`permute_systems` function with vector :math:`[1,2,0]` on
:math:`X`, we may reorient the spaces such that :math:`X \in \mathcal{B} \otimes \mathcal{C} \otimes \mathcal{A}`.

For example, if we define :math:`X \in \mathcal{A} \otimes \mathcal{B} \otimes \mathcal{C}` as
Expand All @@ -93,7 +93,7 @@ def permute_systems(
\otimes \mathcal{C}` yield the following matrix

.. math::
X_{[2, 3, 1]} =
X_{[1, 2, 0]} =
\begin{pmatrix}
1 & 5 & 2 & 6 & 3 & 7 & 4, 8 \\
33 & 37 & 34 & 38 & 35 & 39 & 36 & 40 \\
Expand All @@ -119,7 +119,7 @@ def permute_systems(
... [57, 58, 59, 60, 61, 62, 63, 64],
... ]
... )
>>> permute_systems(test_input_mat, [2, 3, 1])
>>> permute_systems(test_input_mat, [1, 2, 0])
array([[ 1, 5, 2, 6, 3, 7, 4, 8],
[33, 37, 34, 38, 35, 39, 36, 40],
[ 9, 13, 10, 14, 11, 15, 12, 16],
Expand All @@ -145,6 +145,7 @@ def permute_systems(
else:
input_mat_dims = input_mat.shape


is_vec = np.min(input_mat_dims) == 1
num_sys = len(perm)

Expand Down Expand Up @@ -176,7 +177,7 @@ def permute_systems(
prod_dim_r = int(np.prod(dim[0, :]))
prod_dim_c = int(np.prod(dim[1, :]))

if sorted(perm) != list(range(1, num_sys + 1)):
if sorted(perm) != list(range(0, num_sys )):
purva-thakre marked this conversation as resolved.
Show resolved Hide resolved
raise ValueError("InvalidPerm: `perm` must be a permutation vector.")
if input_mat_dims[0] != prod_dim_r or (not row_only and input_mat_dims[1] != prod_dim_c):
raise ValueError("InvalidDim: The dimensions specified in DIM do not agree with the size of X.")
Expand All @@ -185,6 +186,10 @@ def permute_systems(
if input_mat.shape[0] == 1:
input_mat = input_mat[0]
vec_orien = 1
# Rather than using subtraction to generate new indices,
# it's better to use methods designed for handling permutations directly.
# This avoids the risk of negative indices and is more straightforward.
num_sys -= 1 # 0-indexing (Since we're using 0-indexing, we need to subtract 1 from the number of subsystems.)
permuted_mat_1 = input_mat.reshape(dim[vec_orien, ::-1].astype(int), order="F")
if inv_perm:
permuted_mat = vec(np.transpose(permuted_mat_1, np.argsort(num_sys - np.array(perm[::-1])))).T
Expand Down
2 changes: 1 addition & 1 deletion toqito/perms/swap.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def swap(
raise ValueError("InvalidSys: `sys` must be a vector with exactly two elements.")

# Swap the indicated subsystems.
perm = np.array(range(1, num_sys + 1))
perm = np.array(range(0, num_sys ))
purva-thakre marked this conversation as resolved.
Show resolved Hide resolved
sys = np.array(sys) - 1

perm[sys] = perm[sys[::-1]]
Expand Down
2 changes: 1 addition & 1 deletion toqito/perms/symmetric_projection.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def symmetric_projection(dim: int, p_val: int = 2, partial: bool = False) -> [np
if p_val == 1:
return np.eye(dim)

p_list = np.array(list(permutations(np.arange(1, p_val + 1))))
p_list = np.array(list(permutations(np.arange(0, p_val ))))
purva-thakre marked this conversation as resolved.
Show resolved Hide resolved
p_fac = math.factorial(p_val)
sym_proj = np.zeros((dimp, dimp))

Expand Down
36 changes: 18 additions & 18 deletions toqito/perms/tests/test_permutation_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,28 @@


def test_permutation_operator_standard_swap():
"""Generates the standard swap operator on two qubits."""
"""Generates the standard swap operator on two qubits with zero-based indexing."""
expected_res = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]])

res = permutation_operator(2, [2, 1])
res = permutation_operator(2, [1, 0])

bool_mat = np.isclose(res, expected_res)
np.testing.assert_equal(np.all(bool_mat), True)


def test_permutation_operator_standard_swap_list_dim():
"""Generates the standard swap operator on two qubits."""
"""Generates the standard swap operator on two qubits with zero-based indexing."""
expected_res = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]])

res = permutation_operator([2, 2], [2, 1])
res = permutation_operator([2, 2], [1, 0])

bool_mat = np.isclose(res, expected_res)
np.testing.assert_equal(np.all(bool_mat), True)


def test_permutation_operator_sparse_option():
"""Sparse swap operator on two qutrits."""
res = permutation_operator(3, [2, 1], False, True)
"""Sparse swap operator on two qutrits with zero-based indexing."""
res = permutation_operator(3, [1, 0], False, True)

expected_res = np.array(
[
Expand All @@ -46,17 +46,17 @@ def test_permutation_operator_sparse_option():
np.testing.assert_equal(np.all(bool_mat), True)


def test_permutation_operator_dim_3_perm_1_2():
"""Test permutation operator when dim is 3 and perm is [1, 2]."""
res = permutation_operator(3, [1, 2])
def test_permutation_operator_dim_3_perm_0_1():
"""Test permutation operator when dim is 3 and perm is [0, 1] using zero-based indexing."""
res = permutation_operator(3, [0, 1])
expected_res = np.identity(9)
bool_mat = np.isclose(res, expected_res)
np.testing.assert_equal(np.all(bool_mat), True)


def test_permutation_operator_dim_2_perm_1_3_2():
"""Test permutation operator when dim is 2 and perm is [1, 3, 2]."""
res = permutation_operator(2, [1, 3, 2])
def test_permutation_operator_dim_2_perm_0_2_1():
"""Test permutation operator when dim is 2 and perm is [0, 2, 1] using zero-based indexing."""
res = permutation_operator(2, [0, 2, 1])
expected_res = np.array(
[
[
Expand All @@ -75,17 +75,17 @@ def test_permutation_operator_dim_2_perm_1_3_2():
np.testing.assert_equal(np.all(bool_mat), True)


def test_permutation_operator_dim_2_2_perm_1_2():
"""Test permutation operator when dim is [2, 2] and perm is [1, 2]."""
res = permutation_operator([2, 2], [1, 2])
def test_permutation_operator_dim_2_2_perm_0_1():
"""Test permutation operator when dim is [2, 2] and perm is [0, 1] using zero-based indexing."""
res = permutation_operator([2, 2], [0, 1])
expected_res = np.identity(4)
bool_mat = np.isclose(res, expected_res)
np.testing.assert_equal(np.all(bool_mat), True)


def test_permutation_operator_dim_2_2_perm_2_1():
"""Test permutation operator when dim is [2, 2] and perm is [2, 1]."""
res = permutation_operator([2, 2], [2, 1])
def test_permutation_operator_dim_2_2_perm_1_0():
"""Test permutation operator when dim is [2, 2] and perm is [1, 0] using zero-based indexing."""
res = permutation_operator([2, 2], [1, 0])
expected_res = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]])
bool_mat = np.isclose(res, expected_res)
np.testing.assert_equal(np.all(bool_mat), True)
15 changes: 7 additions & 8 deletions toqito/perms/tests/test_permute_systems.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ def test_permute_systems_vec():
test_input_mat = np.array([1, 2, 3, 4])
expected_res = np.array([1, 3, 2, 4])

res = permute_systems(test_input_mat, [2, 1])
res = permute_systems(test_input_mat, [1, 0])

bool_mat = np.isclose(res, expected_res)
np.testing.assert_equal(np.all(bool_mat), True)


def test_permute_systems_m2_m2():
"""Permute system for perm = [2,1] and dim = [2, 2]."""
"""Permute system for perm = [0,1] and matrix of dimension 2-by-2."""
anushkrishnav marked this conversation as resolved.
Show resolved Hide resolved
test_input_mat = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])

expected_res = np.array([[1, 3, 2, 4], [9, 11, 10, 12], [5, 7, 6, 8], [13, 15, 14, 16]])

res = permute_systems(test_input_mat, [2, 1], [2, 2])
res = permute_systems(test_input_mat, [1, 0], dim=[2, 2])

bool_mat = np.isclose(res, expected_res)
np.testing.assert_equal(np.all(bool_mat), True)
Expand All @@ -34,7 +34,7 @@ def test_permute_systems_m2_m2_np_array():

expected_res = np.array([[1, 3, 2, 4], [9, 11, 10, 12], [5, 7, 6, 8], [13, 15, 14, 16]])

res = permute_systems(test_input_mat, np.array([2, 1]))
res = permute_systems(test_input_mat, np.array([1, 0]))

bool_mat = np.isclose(res, expected_res)
np.testing.assert_equal(np.all(bool_mat), True)
Expand Down Expand Up @@ -68,7 +68,7 @@ def permute_systems_test_2_3_1():
]
)

res = permute_systems(test_input_mat, [2, 3, 1])
res = permute_systems(test_input_mat, [1, 2, 0])

bool_mat = np.isclose(res, expected_res)
np.testing.assert_equal(np.all(bool_mat), True)
Expand Down Expand Up @@ -96,9 +96,8 @@ def test_permute_systems_16_by_16():
[151, 152, 183, 184, 215, 216, 247, 248, 159, 160, 191, 192, 223, 224, 255, 256],
]
)
perm = [2, 3, 1, 4]
perm = [1, 2, 0, 3]
dim = [[2, 2, 2, 2], [2, 2, 2, 2]]

res = permute_systems(rho, perm, dim, True, False)
expected_res = np.array(
[
Expand Down Expand Up @@ -152,7 +151,7 @@ def test_permute_systems_invalid_perm_vector():
"""Invalid input for permute systems."""
with np.testing.assert_raises(ValueError):
test_input_mat = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
permute_systems(test_input_mat, [0, 1])
permute_systems(test_input_mat, [1, 2])
anushkrishnav marked this conversation as resolved.
Show resolved Hide resolved


def test_permute_systems_invalid_empty_input():
Expand Down
3 changes: 1 addition & 2 deletions toqito/state_opt/optimal_clone.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def optimal_clone(
# sequence from: https://oeis.org/A023123
q_a = tensor(q_a, num_reps)
perm = []
for i in range(1, num_spaces + 1):
for i in range(0, num_spaces ):
purva-thakre marked this conversation as resolved.
Show resolved Hide resolved
perm.append(i)
var = i
for j in range(1, num_reps):
Expand All @@ -141,7 +141,6 @@ def optimal_clone(
return primal_problem(q_a, pperm, num_reps)
return dual_problem(q_a, pperm, num_reps)


def primal_problem(q_a: np.ndarray, pperm: np.ndarray, num_reps: int) -> float:
"""Primal problem for counterfeit attack.

Expand Down
2 changes: 1 addition & 1 deletion toqito/state_props/is_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def _operator_is_product(rho: np.ndarray, dim: int | list[int] = None) -> list[i
dim = np.array([dim, dim])

op_1 = rho.reshape(int(np.prod(np.prod(dim))), 1)
perm = swap(np.array(list(range(2 * num_sys))), [1, 2], [2, num_sys]) + 1
perm = swap(np.array(list(range(2 * num_sys))), [1, 2], [2, num_sys])
perm_dim = np.concatenate((dim[1, :].astype(int), dim[0, :].astype(int)))
op_3 = permute_systems(op_1, perm, perm_dim).reshape(-1, 1)

Expand Down
1 change: 1 addition & 0 deletions toqito/states/brauer.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def brauer(dim: int, p_val: int) -> np.ndarray:
matchings = perfect_matchings(2 * p_val)
num_matchings = matchings.shape[0]
state = np.zeros((dim ** (2 * p_val), num_matchings))
matchings = matchings - 1
anushkrishnav marked this conversation as resolved.
Show resolved Hide resolved

# Turn these perfect matchings into the corresponding states.
for i in range(num_matchings):
Expand Down
Loading
Loading