# Jordan-Wigner $\leftrightarrow$ Bravyi-Kitaev transformation in Qiskit

A couple of questions regarding the conversion between Jordan-Wigner (JW) and Bravyi-Kitaev (BK) states in Qiskit.

The JW $$\rightarrow$$ BK conversion matrix I refer to below is the one from equation (29) here. (I'm not referring to equation (24) in Ibid. for it contains a typo.)

1. Is there a way to generate a circuit which would map JW-encoded states to BK-encoded states? (The circuit is actually very simple since it multiplies the input $$n$$-qubit vector by a $$n\times n$$ matrix $$\operatorname{mod} 2$$; since the matrix is upper-triangular, it is rather trivial to construct it out of CNOTs.)

2. Assuming that the answer to the previous question is NO: is there a way to, at least, generate the matrix implementing the conversion between the Jordan-Wigner and Bravyi-Kitaev states, for a given number of qubits $$n$$?

I have not found such functionality in Qiskit. However, one can use the openfermion function openfermion.transforms._encoder_bk():

def _encoder_bk(n_modes):
""" Helper function for bravyi_kitaev_code that outputs the binary-tree
(dimension x dimension)-matrix used for the encoder in the
Bravyi-Kitaev transform.

Args:
n_modes (int): length of the matrix, the dimension x dimension

Returns (numpy.ndarray): encoder matrix
"""
reps = int(numpy.ceil(numpy.log2(n_modes)))
mtx = numpy.array([[1, 0], [1, 1]])
for repetition in numpy.arange(1, reps + 1):
mtx = numpy.kron(numpy.eye(2, dtype=int), mtx)
for column in numpy.arange(0, 2 ** repetition):
mtx[2 ** (repetition + 1) - 1, column] = 1
return mtx[0:n_modes, 0:n_modes]


With the aid of this function, one constructs the JW → BK circuit as follows:

def jw_to_bk_circuit_qiskit(n):
"""
Creates a Qiskit circuit which performs the JW -> BK transformation on qubits.
One needs this function to prepare initial states when using BK encoding.
:param n: Number of qubits.
:return:
"""

# Initializing qubits:
qc = qiskit.QuantumCircuit( n )

# JW->BK encoder (lower-triangluar!) matrix
bk_encoder = openfermion.transforms._encoder_bk( n )
# print(bk_encoder)
# Matrix multiplication mod 2 using CNOTs (starting from the bottom row)
for i in reversed( range( 1, n ) ):
for j in range( i  ):
if bk_encoder[i, j] == 1:
qc.cx(j,i)

return qc


Not that it is crucial to perform the matrix multiplication using CNOTs starting from the bottom row, since the encoder matrix is lower-triangular.