Closed jjgoings closed 2 years ago
It is probably the best place to ask - especially since that question arises often. Then we have it online for others to find.
We currently don't have a standardised procedure since circuits can be different in structure (mostly the angles make it difficult as they can be plain numbers, variables, but also to.Objectives i.e. arbitrary complicated objects).
I personally always reconstruct instead of save/load as I find it more convenient. But it depends on the task at hand.
I'll give some examples for different circuit types that maybe are helpful:
import pickle
import tequila as tq
U = tq.gates.Ry("a",0) + tq.gates.Ry(1.0,1)
with open("circuit.pickle", "wb") as f:
pickle.dump(U,f)
with open("circuit.pickle", "rb") as f:
U2 = pickle.load(f)
dill
instead of pickle
(reason: in the construction of the tq.Objective lambdas are used and they can not be pickled)
import dill
import tequila as tq
a = tq.Variable("a") # this is a variable f = a**2 + 5.0 # this is a tq.Objective U = tq.gates.Ry(f,0) + tq.gates.Ry(1.0,1) with open("circuit.pickle", "wb") as f: dill.dump(U,f)
with open("circuit.pickle", "rb") as f: U2 = dill.load(f)
3. Complicated: e.g. when you used tq.grad at this point jax complied gradients are in the circuit parameters. Here I don't have a good way to save/load (instead of saving the entire jax tree, but this is more complicated than reconstruction)
Potentially useful for workarounds
```python
# U is a circuit with complicated parameters
# map all to primitive variables
variables=U.extract_variables()
M = {variables[i]:tq.Variable((i,))}
U2 = U.map_variables(M)
now U2 can be saved and loaded with pickle and the variables can be changed again after loading.
Regarding qasm: If I remember correctly, the issue was that, at least back then, open qasm 2 did not support variables. So you always need to pass a variables dictionary to the export function that sets explicit numbers. I heard it can be done now with open qasm 3.
If you have a good idea on how to integrate save/load or if you want to give it a go with the suggestion here + some if/else business or qasm3 support feel free to make a PR :-).
Disclaimer: Trying to write from my phone (internet issues at home) .... Don't know how the formatting will look and I might have some syntax errors in the code.
Maybe also helpful: I Had to write a small serialiser once for a project, but since it was not able to handle all types of parameters I did not integrate it into tq. Maybe it gives some inspiration
Hey thanks! What worked for me (thanks to your help) was
import dill
import tequila as tq
geomstring="H 0.0 0.0 0.0\nH 0.0 0.0 0.75"
mol = tq.Molecule(geometry=geomstring, backend='pyscf', basis_set='sto6g')
# get the qubit hamiltonian
H = mol.make_hamiltonian()
# get the ansatz (circuit)
U = mol.make_ansatz(name='UCCSD')
with open("circuit.pickle", "wb") as f:
dill.dump(U,f)
with open("circuit.pickle", "rb") as f:
U2 = dill.load(f)
variables = U2.extract_variables()
M = {variables[i]:tq.Variable(i) for i in range(len(variables))}
U2 = U2.map_variables(M)
# define the expectation value
E = tq.ExpectationValue(H=H, U=U2)
# minimize the expectation value
result = tq.minimize(E, method='COBYLA')
print("VQE : {:+2.8}".format(result.energy))
Sorry if this isn't the best place to ask this. I was hoping to be able to save and load parameterized circuits. For example,
gives the circuit
and I've attached the saved qasm 2.0 file (
example_circuit.txt
.) But in the saved output it does not seem the variables are passed correctly, if at all. Is there a way to do this? I wasn't sure if I needed to pass in atq.Variable
object, but this does not seem to change anything and I get an error inconvert_to_open_qasm_2
sayingTypeError: Argument 'a' of type <class 'tequila.objective.objective.Variable'> is not a valid JAX type.
Similarly, is there a way to read in parameterized circuits into Tequila?
If QASM is not the way to go, that's fine too ... just would like some way to save / load / share circuits.