# Clarification on the usage of class UCC of qiskit_nature

I am trying to develop a customized VQE algorithm in which I am making use of the class UCC of qiskit_nature. I am having trouble understanding the outputs of the methods of the class. I have elaborated it below.

The UCC operator is given by, $$U = e^{T-T^\dagger}$$ where $$T$$ is the cluster operator. $$T$$ is written as a linear combination of excitation operators with respect to a reference state, say the HartreeFock state. It is a function of many parameters that act as coefficients of these excitation operators. First, I would like to obtain $$U$$, preferably in the form of a QuantumCircuit. I believe this is definitely achievable through the class UCC but I am having a little hard time trying to understand how, or trying to see what I have obtained is actually correct. Here is what I did.

I imported the relevant modules and called the UCC with num_orbitlas = 4 and num_particles = (1,1) as follows.

from qiskit_nature.circuit.library.ansatzes import UCC
from qiskit_nature.mappers.second_quantization import JordanWignerMapper

UCC_operator = UCC(qubit_converter=QubitConverter(mapper=JordanWignerMapper()), num_particles=(1,1), num_spin_orbitals=4, excitations='s')


Once I obtained the UCC_operator object, I used the excitation_ops method of the UCC class to extract the excitation operators. The code:

ferm_ops = UCC_operator.excitation_ops()
print (ferm_ops)


and the output:

[FermionicOp([('+-II', 1j), ('-+II', 1j)], register_length=4, display_format='dense'), FermionicOp([('II+-', 1j), ('II-+', 1j)], register_length=4, display_format='dense')]


My first two questions concern the form of the output of this particular method.

1. Does the above output correspond to the operator $$T-T^\dagger$$ in the exponential of the conventional UCC operator? If so, am I correct in saying that the above form basically implies $$T-T^\dagger = t_0 (c_0^\dagger c_1 - c_1^\dagger c_0) + t_1 (c_2^\dagger c_3 - c_3^\dagger c_2)$$ ? Where $$t_0$$ & $$t_1$$ are just some parameters although not present in the above output but I believe are still contained in the UCC_operator.

2. Now, is it that the additional imaginary factor is multiplied to the above operators because Trotterization in qiskit somehow considers the evolution operators to be of the form $$e^{-i\hat{O}}$$ which for our case would be like $$e^{-i\cdot i(T-T^{\dagger})}$$ and hence the ferm_op printed above actually corresponds to $$i(T-T^{\dagger})$$ and not just $$T-T^{\dagger}$$? (I saw in the source code of UCC that the sign is due to PauliTrotterEvolution.convert but I was not sure if this is what it meant.)

Now, I wanted to convert this operator from second quantized form to a Pauli string. I used the map method of the JordanWignerMapper as follows,

JW = JordanWignerMapper()
print ([JW.map(second_q_op=ferm_ops[i]) for i in range (len(ferm_ops))])


to obtain,

[PauliSumOp(SparsePauliOp(['IIXY', 'IIYX'], coeffs=[ 0.5+0.j, -0.5+0.j]), coeff=1.0), PauliSumOp(SparsePauliOp(['XYII', 'YXII'], coeffs=[ 0.5+0.j, -0.5+0.j]), coeff=1.0)]


3. Am I then correct in interpreting the above result to mean $$i(T-T^{\dagger}) = 0.5\cdot t_0[IIXY - IIYX] + 0.5\cdot t_1[XYII - YXII]$$ under the Jordan-Wigner transformation?

Finally, I drew the circuit using the following code:

UCC_operator.decompose().draw(output='mpl', filename='my_circuit.png')


to obtain,

The image seems to be of the Trotterized UCC anstaz with Trotter step = 1. This I believe is due to the reps parameter of UCC which by default is equal to one. Then,

4. Why is there a "+" sign instead of a "-" sign between IIXY & IIYX and XYII & YXII in the above circuit if what I have written in question 3 is correct?

5. Also, are the factors of half present in the expression of question 3 are now absorbed in the constant parameters $$t[0]$$ and $$t[1]$$ given in the above circuit?

These are the questions I encountered while trying to understand the class UCC. Since I am trying to develop a modified VQE, it was essential for me to get these doubts clarified before heading on. Any hints or answers are greatly appreciated. Thank you.

• welcome, accept answer if it solve your problem, it will help a lot.
– poig
Jun 29, 2022 at 20:29
• Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer.
– Community Bot
Jun 30, 2022 at 6:22

From my understanding:

1. according to UCC docs here you should do UCC_operator.operators, not excitation_ops(), where you can see UCC operator:(becasue excitation_ops is, parses the excitations and generates the list of operators.)
[PauliSumOp(SparsePauliOp(['IIXY', 'IIYX'],
coeffs=[ 0.5+0.j, -0.5+0.j]), coeff=1.0),
PauliSumOp(SparsePauliOp(['XYII', 'YXII'],
coeffs=[ 0.5+0.j, -0.5+0.j]), coeff=1.0)]


2.yes, you are right, it will have imaginary factor after PauliTrotterEvolution, where EvolvedOpcome in.

3.yes, you are right, check PauliTrotterEvolution docs here,
4.A easy example in circuit why there is +, because they are adding together in SparsePauliOp where ['IIXY', 'IIYX'] :
UCC_operator.decompose().decompose().draw(output='mpl')# if you decompose second time

5. yes, example which will giving the same circuit, but contain only 1 parameter(t),and coeffs for simplicity: (which you can understand more about it.)

# Import Pauli operators (I, X, Y, Z), other things
from qiskit.circuit.library import PauliEvolutionGate
from qiskit.opflow import X, Y, Zero, I, PauliTrotterEvolution, Suzuki, CircuitStateFn
from qiskit.synthesis import SuzukiTrotter
import numpy as np

J = 0.5

# tight-binding Hamiltonian
def H_tb():
# Interactions (I is the identity matrix; X and Y are Pauli matricies; ^ is a tensor product)
XXs = (I^I^X^Y) + (I^I^Y^X)
YYs = (X^Y^I^I) + (Y^X^I^I)

# Sum interactions
H = J*(XXs+YYs)

# Return Hamiltonian
return H

#parameter
from qiskit.circuit import Parameter
t = Parameter('t')

# Unitary evolution under the tight-binding Hamiltonian
def U_tb(t):
H = H_tb()
return (t * H).exp_i()

#Example
display(U_tb(1))
#output:
#EvolvedOp(PauliSumOp(SparsePauliOp(['IIXY', 'IIYX', 'XYII', 'YXII'],
#              coeffs=[0.5+0.j, 0.5+0.j, 0.5+0.j, 0.5+0.j]), coeff=1), coeff=1.0)

op = H_tb()
evo_ham = U_tb(t)
reps = 1

#SuzukiTrotter 1st order is the same with LieTrotter,
evo_gate = PauliTrotterEvolution(trotter_mode=Suzuki(order=1, reps=1)).convert(evo_ham)
evo_gate.to_circuit().draw()
output:
┌──────────────────────────────────────────────┐
q_0: ┤0                                             ├
│                                              │
q_1: ┤1                                             ├
│  exp(-it (IIXY + IIYX + XYII + YXII))(1.0*t) │
q_2: ┤2                                             ├
│                                              │
q_3: ┤3                                             ├
└──────────────────────────────────────────────┘

• 1 Thank you for pointing out the operators attribute, I had somehow missed it. Jun 30, 2022 at 7:48
• @Kurious accept answer will help alot, thank you
– poig
Jun 30, 2022 at 7:51
• Sorry for not completing the comment. I still have doubts with 4 and 5. In 4 I do not understand where did the - sign disappear. Because, the coeffs of the SparsePauliOp were $(0.5+0.j, -0.5+0.j)$ by which I though it corresponds to saying $0.5\cdot IIXY - 0.5\cdot IIYX$. Hence, I was expecting the circuit to have the evolution operator $\exp(-it \cdot 0.5(IIXY - IIYX))$ but this does not seem to be the case. Can you please clarify why is this negative sign is replaced by a positive sign in the final circuit? Jun 30, 2022 at 8:01
• In 5 I still do not see where did the 0.5 factor disappear. Because, even with the code you provided, if J=0.5, the final circuit seems to have an additional multiple of 2 in the exponential which is being multiplied to this J. Or in other words, if you put J=2, the final circuit will actually have 4*t as the coefficient. Can you please explain why is this so? Jun 30, 2022 at 8:01
• I think I understood what you mean. Thank you for the clarification and suggestion. Jun 30, 2022 at 9:37