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$?


1 Answer 1


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.

    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.

    # 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:

    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.

  • $\begingroup$ What do you mean by Matrix multiplication mod 2 using CNOTs ? $\endgroup$
    – kevin
    Aug 20, 2022 at 9:41
  • 1
    $\begingroup$ Every bitstring is a vector with components in $\{0,1\}$. Define their scalar product in a usual way. Calculate the result $\mod 2$. Similarly define the matrix product. The circuit above for a given input bitstring outputs this bitstring multiplied by the JW$\leftrightarrow$BK encoder matrix. $\endgroup$
    – mavzolej
    Aug 21, 2022 at 10:25
  • 1
    $\begingroup$ Such an implementation relies crucially on the encoder matrix being lower-triangular. If one calculates the resulting vector, starting from the last entry, then for $j$-th output component, the input components larger than $j$ are not used, and so they can store the final values, obtained on earlier steps. $\endgroup$
    – mavzolej
    Aug 21, 2022 at 10:39
  • $\begingroup$ I am actually confused as in how you come up with the logic inside the for loop inside the two functions respectively. $\endgroup$
    – kevin
    Aug 21, 2022 at 14:22
  • $\begingroup$ if I have an input QASM file already mapped in Jordan-Wigner, how would I replace the argument n inside jw_to_bk_circuit_qiskit(n) ? $\endgroup$
    – kevin
    Aug 21, 2022 at 14:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.