Closed EnBr55 closed 2 years ago
This is great @EnBr55, looking forward to discussing more with @BoxiLi and other contributors. As a small comment, all names proposed look very "pythonic" :) and the tutorial looks great.
Hi @EnBr55, thanks very much for dragting this issue. This is very intriguing. Adding a VQA will definitely be a very useful feature to qutip-qip. It can also be easily integrated with the pulse-level simulation once this VQA class is constructed. Feel free to open a PR and happy to discuss!
Some thoughts of mine:
Is it correct to understand the VQA
class as a special type of gate (defined by a sequence of rotations and two-qubit gates)? If so, the gate class drafted in https://github.com/qutip/qutip-qip/pull/96 might be helpful. Eventually, this allows define arbitrary gate as a subclass of Gate
and provide it to the QubitCircuit
. I guess the VQA
class could be one of the gates? Though I have to get the time to finish that PR.
Can be either an "initial" element or not - this will determine if the block is repeated in the circuit layers.
I don't really get the concept of "initial" element. Is this to save memories and avoid defining the same gate many times?
I wonder how a Parameterized_Hamiltonian
works. One provides Hamiltonians as Qobj
and the control strength being the parameters to optimize? If that is the case it might be useful to build that on top of the Processor
class. This will probably mean that the Hamiltonian model will be saved in the Processor
and the parameters saved in QubitCircuit
. It will allow one to use the Noise
module to add different noise to the Hamiltonian and study noisy VQA. This can be drafted separately from VQA for QubitCircuit.
Thanks for your thoughts, @BoxiLi !
VQA
class as more of a superset of QubitCircuit
. It has a method (construct_circuit
) which can generate QubitCircuit
instances. The VQA_Block
I think is closer to what you mean by special type of gate, as it contains a get_unitary
method (which can be defined in a few different ways) which can be passed straight into a user-defined gate for the QubitCircuit
model. Thanks for linking this drafted new gate representation - this would certainly be useful given how reliant this module would be on user-defined gates.VQA
class constructs a circuit, it only applies these elements once, whereas other elements are repeated a number of times set by VQA.n_layers
.Parameterized_Hamiltonian
, as I see it, allows for specification of a list of Qobj
which are to be given unique parameters in the optimisation process done by the VQA
class. Within the circuit model this parameterized Hamiltonian would currently make up a single vqa_block
which can generate a gate/unitary by pairing free parameters with Hamiltonian terms and exponentiating the sum. I'm not sure about the nicest interface for this, but currently thinking something like Parameterized_Hamiltonian(parameterized_terms=[], constant_term: Qobj=None)
, where the number of free parameters is just len(parameterized_terms)
. Simulating this with the Processor
class and only storing the parameters in the VQA
as you suggest could be great - I'll have a look at how that might work soon.Thanks for the answers.
The VQA_Block I think is closer to what you mean by special type of gate
Yes I meant VQA_Block, somehow I forgot the "block" after I started typing :) These all make sense.
The "initial" elements are intended as a convenience for problem/circuit initialisation.
Ah I think now I get it, the initial layer and those repeated once.
About the Parameterized_Hamiltonian
. If I understand correctly, each VQE block will be computed by
U = expm(H0 + c_1 * H_1 + c_2 * H_2 + ...)
where c_i
are the parameters for VQA to optimize.
What Processor
does is implementing this
pairing free parameters with Hamiltonian terms
in a more sophisticated and modulated way. In the framework of Processor
, those Hamiltonian Qobj
s are saved in Model
and the control coefficient c_i
are generated by GateCompiler
. In this sense, VQA with Hamiltonian based ansatz can even be implemented as a subclass of Processor
that optimize the compilers! Of course, because VQA has quite some optimization procedures just for itself, it is probably better to define it as a separate class and just using Processor
for the Hamiltonian ansatz or QubitCircuit
for the usual circuit.
In the second case, I can think of a workflow like this
QubitCircuit
, but with VQA_Block
containing Hamiltonian index like "sigmax0"
(not the full Qobj
for memory sake), and parameters c_i
.Processor
is saved in VQA with all Hamiltonians Qobj
saved. It takes the circuit maps "sigmax0"
to the Qobj
and multiplies it with the parameter c_i
. Then you can compute the unitary evolution and get the result.This might look like a detour. However, the advantage of building this on top of Processor
is that you automatically get the functionality such as switching between expm
and qutip solvers, using the noise model, using continuous pulse shape instead of piecewise constant, etc.
For small implementation and testing whether the Hamiotnian ansatz works at all, it is faster I guess to use expm
and build the unitary gates within VQA_block
. I'm just saying that when this pairing part starts to get too long and complicated, you might find some of these workflows already written in qutip-qip. You could have a look at the paper for detailed examples if you are interested.
I like this workflow suggested with the Processor
class. I'll see if I can implement this after the base stuff is done, thanks!
Indeed, a very interesting project.
Sorry to be very dull, but should we not avoid underscores in class names?
Good catch, thanks - not sure why my linter didn't pick that up.
QuTiP currently lacks any functionality directly related to VQAs. It would be useful to have a class-based implementation that allows for problem specification down to the details of parametrized/fixed Hamiltonians and the optimisation method.
To outline a possible structure for this module, I have implemented something along these lines in my fork of this repository. This includes:
Optimization_Result
classVQA_Block
classqutip_qip.operations.x_gate
).QubitCircuit
'suser_gates
dictionary.VQA
classn_qubits
,n_layers
add_block(block: VQA_Block)
appendsVQA_Block
to the circuit and, if necessary, updates the circuit'suser_gates
dictionary to include the new gate.optimise_parameters
method performs optimisation on the free parameters of the circuit and returns anOptimization_Result
instance.QubitCircuit
to simulate the circuitA usage example can be found at https://github.com/EnBr55/qutip-vqa-examples/blob/main/notebooks/QAOA.ipynb.
I'm currently working on a
Parameterized_Hamiltonian
model as aVQA_Block
input that will allow for defining more general quantum control problems.Any discussion/suggestions as to these proposed models would be great!