Help with UCCSD's error

Hi, I was working with the qml.UCCSD to construct an ansazt for VQE, and I have a little problem.
The above code give me the following error “DeviceError: Operation BasisState cannot be used after other Operations have already been applied on a default.qubit.autograd device.”

import pennylane as qml
from pennylane import numpy as np

dev = qml.device('default.qubit', wires=8)

@qml.qnode(dev)
def circuit2(x):
    singles, doubles = qml.qchem.excitations(1, 4)
    singles, doubles = qml.qchem.excitations_to_wires(singles, doubles)
    qml.UCCSD(weights= x, wires=[0,1,2,3], s_wires=singles, d_wires=doubles, init_state=[1,1,0,0])
    qml.UCCSD(weights= x, wires=[4,5,6,7], s_wires=singles, d_wires=doubles, init_state=[1,1,0,0])
    
    return qml.expval(qml.PauliZ(wires=[0]))


theta_optimizer = qml.GradientDescentOptimizer(stepsize=0.3)
theta = np.array([0])
energy = [circuit2(theta)]
theta_evol = [theta]
for _ in range(100):
    theta.requires_grad = True
    theta = theta_optimizer.step(circuit2, theta)
    energy.append(circuit2(theta))
    theta_evol.append(theta)
    prev_energy = energy[len(energy)-2]

    conv = np.abs(energy[-1] - prev_energy)
    if conv <= 1e-6:
        break

My idea was to introduce the repetition of the UCCSD “gate”, apply it k times, but I got that error and when I try to not consider the init_state variable of UCCSD that give me another error (“ValueError: Elements of ‘init_state’ must be integers; got object”). So, i dont know if I am missing something or it’s only possible to use it one time.

The reason to construct a circuit like that is because I want to create a destructive swap test to implement a naive version of VQD, just for context.
Thank you in advance and have a nice day.

Hello @jnorambu,

https://docs.pennylane.ai/en/stable/code/api/pennylane.UCCSD.html

In Usage Details, it looks like you have to define s_wires, d_wires = qml.qchem.excitations_to_wires(singles, doubles) to map excitations to the wires the UCCSD circuit will act on.

Hi kevin, yes I consider that line, but still give me the same error “DeviceError: Operation BasisState cannot be used after other Operations have already been applied on a default.qubit.autograd device.”". Even if I hardcode the s_wires and the d_wires to match the new wires ([4,5,6,7]) I got the same error.

Hello @jnorambu

The reason you are getting this error is because UCCSD uses qml.BasisState in the backend to prepare the initial state. BasisState can only be used at the very beginning of a circuit to prepare an initial state. Here, you’re using UCCSD twice, so BasisState is being applied a second time, when something already happened in the circuit.

A possible solution might be to prepare the initial state on the wires at the beginning of the whole circuit, instead of specifying init_state within UCCSD (you can leave that argument empty and it’ll default to None).

Please let me know if this helps!

Alvaro

Hi Alvaro, I done what you say, you can use the code below (i edit it to consider what you say), but still give an error.

import pennylane as qml
from pennylane import numpy as np

dev = qml.device('default.qubit', wires=8)

@qml.qnode(dev)
def circuit2(x):
    qml.BasisState( np.array([1,1,0,0,1,1,0,0]), wires=8 )
    singles, doubles = qml.qchem.excitations(1, 4)
    singles, doubles = qml.qchem.excitations_to_wires(singles, doubles)

    qml.UCCSD(weights= x, wires=[0,1,2,3], s_wires=singles, d_wires=doubles)
    qml.UCCSD(weights= x, wires=[4,5,6,7], s_wires=singles, d_wires=doubles)
    
    return qml.expval(qml.PauliZ(wires=[0]))


theta_optimizer = qml.GradientDescentOptimizer(stepsize=0.3)
theta = np.array([0])
energy = [circuit2(theta)]
theta_evol = [theta]
for _ in range(100):
    theta.requires_grad = True
    theta = theta_optimizer.step(circuit2, theta)
    energy.append(circuit2(theta))
    theta_evol.append(theta)
    prev_energy = energy[len(energy)-2]

    conv = np.abs(energy[-1] - prev_energy)
    if conv <= 1e-6:
        break

Here it’s the error

ValueError: Elements of 'init_state' must be integers; got object

It happen in this line, looks like the default option (None) gives and error.

qml.UCCSD(weights= x, wires=[0,1,2,3], s_wires=singles, d_wires=doubles)

Hello!

Yes you’re right! I was hoping that would work, but it didn’t :frowning:

Looking at your code more closely, I can’t help but wonder why you are dividing your code into two UCCSD applications, when they’re acting on disjoint wires. Wires [0,1,2,3] are never interacting with [4,5,6,7], so the latter should not affect the output on wire = 0. It’s as if they were two independent circuits! Unless you’re doing something more than what you’re showing, I think you have no choice but to solve this problem using UCCSD only once by restricting to one of the set of wires.

Cheers,

Alvaro

The reason that im doing that is because i want to implement a swap test.
Quantum-swap-test-circuit-correct
The first UCCSD is for the \phi state and the second is for \psi. The code that i provide was a toy code to test if was possible to have two UCCSD in the same circuit, that why the output of the circuit look like something nonsense.

I see…

Then I don’t think it’s possible at the moment, at least using a single circuit. You might want to try using more circuits and feed the output states of those circuits to the full algorithm you’re trying to implement… I’m aware this might be a bit of a pain. I’ll let the team know of this use case we’re not considering, and hopefully we can improve on the UCCSD template this way!

Cheers,

Alvaro