0
$\begingroup$

I have a system of $N$ qubits and want to construct a quantum operator $Z_i Z_j + Z_k$, where $Z_i$ denotes the Pauli-Z operator acting on the $i$th qubit. Is there any direct way in qiskit, how I could implement this?

I know that I can construct an operator by e.g. saying op = Z^Z, if I have a system of 2 qubits and want the operator being the Pauli-Z on each qubit. But I would like to tell qiskit the indices of the qubits that $Z$ should act on (such that on all the other qubits Identity is applied).

My way so far consists of constructing a Quantum Circuit and converting this to an operator by

circZZ = QuantumCircuit(N)  # circuit for Z_i Z_j
circZ = QuantumCircuit(N)  # circuit for Z_k
circZZ.z(i)
circZZ.z(j)
circZ.z(k)
opZZ = CircuitOp(circZZ)  # convert circuit to operator
opZ = CircuitOp(circZ)  # convert circuit to operator
op = opZZ + opZ

But that means I have to create quantum circuits everytime I want to get this operator. Is there any shorter and more elegant way to create such an operator?

$\endgroup$

2 Answers 2

1
$\begingroup$

The class Operator has a from_label method: https://qiskit.org/documentation/stubs/qiskit.quantum_info.Operator.html?highlight=operator%20from_label#qiskit.quantum_info.Operator.from_label

That means you could do something like this:

opZZ = Operator.from_label('ZZ')
opZ = Operator.from_label('Z')

It's possible to add opZZ and opZ into N-sized op. However, you have to call the _add by hand:

op = 0 * Operator.from_label('I' * N)  # Set the initial operator to zero
op = op._add(opZZ, qargs=[i,j])
op = op._add(opZ, qargs=[k])
$\endgroup$
7
  • $\begingroup$ Thanks for your answer. I guess that is the same as what I would do with opZZ = Z^Zand opZ = Z. But that's not what I mean. I would like to tell qiskit that $Z_i Z_j$ acts on the $i$th and $j$th qubit, without setting the label to 'II..IZI...IZI...II' with $Z$ being on the $i$th and $j$th position of the string. Is there any way to tell qiskit the index of the qubit the operator should act on? $\endgroup$
    – ile2N
    Commented Dec 7, 2020 at 13:07
  • $\begingroup$ If I understand everything correctly, the system has three qubits, $i$, $j$, and $k$. If you want to operatore with those operators, I think they have to have the same size opZ = Operator.from_label('IIZ') and opZZ = Operator.from_label('ZZI'). $\endgroup$
    – luciano
    Commented Dec 7, 2020 at 13:19
  • $\begingroup$ No, the system has not only 3 qubits. It has $N$ qubits, and $i,j,k$ are three of these. $N$ can be any number larger than 3. I would like to address the qubit by indices, is this possible? $\endgroup$
    – ile2N
    Commented Dec 7, 2020 at 13:25
  • $\begingroup$ I see! The size is an immutable characteristic of an Operator (see Operator.num_qubits). So N needs to be defined at construction time. Then, there is the problem of construction. For that, I think 'II..IZI...IZI...II' is the best way to go so far, because I dont think there is an easy way to modify a specific qubit in an Operator instance. Shall I modify the answer to do it in a programmatically way? $\endgroup$
    – luciano
    Commented Dec 7, 2020 at 13:49
  • $\begingroup$ Just to clarify what I said above: $N$ is indeed fixed when the operator is created. I just wanted to point out that it is not necessarily $N=3$, but could also be some arbitrary large number, which is why I wanted to address the qubits to be manipulated by the indices. I think I will stick to my first approach to create a circuit first, since I need to create this operator for different qubits several times. Thank you anyways for your answer! $\endgroup$
    – ile2N
    Commented Dec 7, 2020 at 13:58
1
$\begingroup$

You could use the feature that the Opflow in Aqua can take integers as tensorpower, like Z ^ 5 and then fill the blanks with identities. In a short function that could look like

from qiskit.aqua.operators import Z, I

def get_term(i, j, k, n):
    """i, j and k as in your description and n is the number of qubits."""
    zz = (I ^ i) ^ Z ^ (I ^ j - i - 1) ^ Z ^ (I ^ (n - j - i - 1))
    z = (I ^ k) ^ Z ^ (I ^ (n - k - 1))
    return zz + z

print(get_term(0, 2, 4, 5))
# 1.0 * ZIZII
# + 1.0 * IIIIZ

Note that the order of Z's is reversed to what you did with the circuits, so to get the same results you can just call

get_term(n - i - 1, n - j - 1, n - k - 1, n)

But this is just one way to get to the result, I'm sure there are many others! Your method, via circuits, is looks perfectly good to me.

$\endgroup$

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.