qiboteam / qibo

A framework for quantum computing
https://qibo.science
Apache License 2.0
287 stars 57 forks source link

Optimizing correlated parameters #553

Closed ghost closed 2 years ago

ghost commented 2 years ago

I am looking for the correct way within Qibo to optimize a cost function where some of the parameters being trained are repeated within the ansatz.

i.e. in one of your examples, you have the following code snippet for inverting a gate sequence:

from qibo.models import Circuit
from qibo import gates

# Create a subroutine
subroutine = Circuit(6)
subroutine.add([gates.RX(i, theta=0.1) for i in range(5)])
subroutine.add([gates.CZ(i, i + 1) for i in range(0, 5, 2)])

# Create the middle part of the circuit
middle = Circuit(6)
middle.add([gates.CU2(i, i + 1, phi=0.1, lam=0.2) for i in range(0, 5, 2)])

# Create the total circuit as subroutine + middle + subroutine^{-1}
circuit = subroutine + middle + subroutine.invert()

What I would like to do is optimize this circuit (with respect to some arbitrary expectation value) where the parameters of 'subroutine' and 'middle' are being trained, wheras 'subroutine.invert()' is always kept as the inverse of subroutine, rather than being an independent gate sequence. How can I do this?

DiegoGM91 commented 2 years ago

@JoeGibbs88, an easy option for this particular circuit could be the following:

# Create a subroutine
subroutine = Circuit(6)
subroutine.add([gates.RX(i, theta=0.1) for i in range(5)])
subroutine.add([gates.CZ(i, i + 1) for i in range(0, 5, 2)])

# Create the middle part of the circuit
middle = Circuit(6)
middle.add([gates.CU2(i, i + 1, phi=0.1, lam=0.2) for i in range(0, 5, 2)])

# Create the total circuit as subroutine + middle + subroutine^{-1}
circuit = subroutine + middle + subroutine.invert()

# Define cost function and correlate parameters within this function
def cost_function(params): # Here `params` must be a list with parameters for subroutine + middle only
    correlated_params = list(params)
    for i in range(5):
        correlated_params.append(-params[4-i])
    circuit.set_parameters(correlated_params)
    cost = # whatever
    return cost

I'm not sure if there is currently a more elegant, built-in way to do this using the .invert() method. @stavros11

DiegoGM91 commented 2 years ago

@JoeGibbs88 after talking with @stavros11 we can tell you that the .invert() method does not support automatic optimization of correlated parameters at the moment. So correlating parameters should be handled manually for the time being.

Also, please notice the edit in the code snippet provided above. Now it should work as expected beyond the first iteration of the optimization too.

ghost commented 2 years ago

@DiegoGM91 Thanks for looking into this for me