# Path: openfermioncirq/experiments/hfvqe/util.py
# def generate_permutations(n_orbitals: int,
#                           no_truncation: Optional[bool] = False):
#     qubit_orderings = [list(range(n_orbitals))]
#     if n_orbitals % 2 == 0:
#         perm_order = n_orbitals // 2
#     else:
#         perm_order = n_orbitals // 2 + 1
#     for _ in range(perm_order):
#         qubit_orderings.append(swap_forward(qubit_orderings[-1],
#                                             starting_index=0))
#         qubit_orderings.append(swap_forward(qubit_orderings[-1],
#                                             starting_index=1))
#     if no_truncation:
#         return qubit_orderings
#     else:
#         return qubit_orderings[::2][:-1]
# 
# def swap_forward(iterable_item: Iterable,
#                  starting_index: Optional[int] = 0):
#     new_sequence = copy.deepcopy(iterable_item)
#     for i in range(starting_index, len(iterable_item) - 1, 2):
#         new_sequence[i + 1], new_sequence[i] = \
#             new_sequence[i], new_sequence[i + 1]
#     return new_sequence
# 
# def generate_fswap_pairs(depth: int, dimension: int):
#     swap_list = []
#     for i in range(0, depth):
#         if i % 2 == 0:
#             swap_list.append([(i, i + 1) for i in range(0, dimension - 1, 2)])
#         else:
#             swap_list.append([(i, i + 1) for i in range(1, dimension - 1, 2)])
#     return swap_list
# 
# def generate_fswap_unitaries(swap_pairs: List[List[Tuple]], dimension: int):
#     swap_unitaries = []
#     for swap_tuples in swap_pairs:
#         generator = np.zeros((dimension, dimension), dtype=np.complex128)
#         for i, j in swap_tuples:
#             generator[i, i] = -1
#             generator[j, j] = -1
#             generator[i, j] = 1
#             generator[j, i] = 1
#         swap_unitaries.append(expm(-1j * np.pi * generator / 2))
#     return swap_unitaries


import numpy as np
import scipy as sp
from openfermioncirq.experiments.hfvqe.util import (generate_permutations,
                        swap_forward,
                        generate_fswap_pairs,
                        generate_fswap_unitaries)
    test_swapped_list = swap_forward(list_to_swap, starting_index=1)
    assert test_swapped_list == [0, 2, 1, 4, 3, 5]


def test_generate_fswap_pairs():
    swap_set = generate_fswap_pairs(2, 6)
    assert swap_set[0] == [(0, 1), (2, 3), (4, 5)]
    assert swap_set[1] == [(1, 2), (3, 4)]

    swap_set = generate_fswap_pairs(1, 4)
    assert swap_set[0] == [(0, 1), (2, 3)]


def test_gen_fswap_unitaries():
    fswapu = generate_fswap_unitaries([((0, 1), (2, 3))], 4)
    true_generator = np.zeros((4, 4), dtype=np.complex128)
    true_generator[0, 0], true_generator[1, 1] = -1, -1
    true_generator[0, 1], true_generator[1, 0] = 1, 1
    true_generator[2, 2], true_generator[3, 3] = -1, -1
    true_generator[2, 3], true_generator[3, 2] = 1, 1
    true_u = sp.linalg.expm(-1j * np.pi * true_generator / 2)
    assert np.allclose(true_u, fswapu[0])


def test_permutation_generator():
    perms = generate_permutations(3)
    assert len(perms) == 2  # N//2+1 circuits
    assert perms[0] == [0, 1, 2]
    assert perms[1] == [1, 2, 0]


# Path: openfermioncirq/experiments/hfvqe/util.py
# def generate_permutations(n_orbitals: int,
#                           no_truncation: Optional[bool] = False):
#     qubit_orderings = [list(range(n_orbitals))]
#     if n_orbitals % 2 == 0:
#         perm_order = n_orbitals // 2
#     else:
#         perm_order = n_orbitals // 2 + 1
#     for _ in range(perm_order):
#         qubit_orderings.append(swap_forward(qubit_orderings[-1],
#                                             starting_index=0))
#         qubit_orderings.append(swap_forward(qubit_orderings[-1],
#                                             starting_index=1))
#     if no_truncation:
#         return qubit_orderings
#     else:
#         return qubit_orderings[::2][:-1]
# 
# def swap_forward(iterable_item: Iterable,
#                  starting_index: Optional[int] = 0):
#     new_sequence = copy.deepcopy(iterable_item)
#     for i in range(starting_index, len(iterable_item) - 1, 2):
#         new_sequence[i + 1], new_sequence[i] = \
#             new_sequence[i], new_sequence[i + 1]
#     return new_sequence
# 
# def generate_fswap_pairs(depth: int, dimension: int):
#     swap_list = []
#     for i in range(0, depth):
#         if i % 2 == 0:
#             swap_list.append([(i, i + 1) for i in range(0, dimension - 1, 2)])
#         else:
#             swap_list.append([(i, i + 1) for i in range(1, dimension - 1, 2)])
#     return swap_list
# 
# def generate_fswap_unitaries(swap_pairs: List[List[Tuple]], dimension: int):
#     swap_unitaries = []
#     for swap_tuples in swap_pairs:
#         generator = np.zeros((dimension, dimension), dtype=np.complex128)
#         for i, j in swap_tuples:
#             generator[i, i] = -1
#             generator[j, j] = -1
#             generator[i, j] = 1
#             generator[j, i] = 1
#         swap_unitaries.append(expm(-1j * np.pi * generator / 2))
#     return swap_unitaries


# Path: openfermioncirq/experiments/hfvqe/util_test.py
import numpy as np
import scipy as sp
from openfermioncirq.experiments.hfvqe.util import (generate_permutations,
                        swap_forward,
                        generate_fswap_pairs,
                        generate_fswap_unitaries)

    test_swapped_list = swap_forward(list_to_swap, starting_index=1)
    assert test_swapped_list == [0, 2, 1, 4, 3, 5]


def test_generate_fswap_pairs():
    swap_set = generate_fswap_pairs(2, 6)
    assert swap_set[0] == [(0, 1), (2, 3), (4, 5)]
    assert swap_set[1] == [(1, 2), (3, 4)]

    swap_set = generate_fswap_pairs(1, 4)
    assert swap_set[0] == [(0, 1), (2, 3)]


def test_gen_fswap_unitaries():
    fswapu = generate_fswap_unitaries([((0, 1), (2, 3))], 4)
    true_generator = np.zeros((4, 4), dtype=np.complex128)
    true_generator[0, 0], true_generator[1, 1] = -1, -1
    true_generator[0, 1], true_generator[1, 0] = 1, 1
    true_generator[2, 2], true_generator[3, 3] = -1, -1
    true_generator[2, 3], true_generator[3, 2] = 1, 1
    true_u = sp.linalg.expm(-1j * np.pi * true_generator / 2)
    assert np.allclose(true_u, fswapu[0])


def test_permutation_generator():
    perms = generate_permutations(3)
    assert len(perms) == 2  # N//2+1 circuits
    assert perms[0] == [0, 1, 2]
    assert perms[1] == [1, 2, 0]


    perms = generate_permutations(4)