Hello! I’m trying to create a Hamiltonian that will be used in conjunction with qml.evolve()
. However, I want the Hamiltonian to be a parameterized one since I want the coefficients to also be optimized during the learning process. I’m creating my parameterized Hamiltonian as follows:
import pennylane as qml
import pennylane.numpy as np
import jax.numpy as jnp
import jax
class QuantumPerceptron():
def __init__ (self, n_wires, L, native_coupling = 1.0):
self.n_wires = n_wires
self.native_coupling = native_coupling
self.L = L
self.create_parameterized_hamiltonian()
def create_parameterized_hamiltonian(self):
self.create_native_hamiltonian()
self.H = self. H_native
def create_native_hamiltonian(self):
self.native_fields_squeezing = [self.get_control_field() for i in range(self.n_wires-1)]
self.H_native_operators_squeezing = [qml.PauliZ(i) @ qml.PauliZ(i+1) for i in range(self.n_wires-1)] # Assuming nearest neighbor interactions
self.native_fields_identity = [self.get_control_field() for i in range(self.n_wires)]
self.H_native_operators_identity = [qml.Identity(i) for i in range(self.n_wires)]
self.total_native_fields = self.native_fields_squeezing + self.native_fields_identity
self.H_total_native_operators = self.H_native_operators_squeezing + self.H_native_operators_identity
self.H_native = qml.dot(self.total_native_fields, self.H_total_native_operators)
def get_control_field(self):
def control_field(p,t):
# p is the trainable parameter
# t is the time
return p
return control_field
In particular, let’s say that I want to create this Hamiltonian for 5 wires. If I create my Hamiltonian using the above functions, I will get something like
(control_field(params_0, t)*(PauliZ(wires=[0]) @ PauliZ(wires=[1])))
+ (control_field(params_1, t)*(PauliZ(wires=[1]) @ PauliZ(wires=[2])))
+ (control_field(params_2, t)*(PauliZ(wires=[2]) @ PauliZ(wires=[3])))
+ (control_field(params_3, t)*(PauliZ(wires=[3]) @ PauliZ(wires=[4])))
+ (control_field(params_4, t)*(Identity(wires=[0])))
+ (control_field(params_5, t)*(Identity(wires=[1])))
+ (control_field(params_6, t)*(Identity(wires=[2])))
+ (control_field(params_7, t)*(Identity(wires=[3])))
+ (control_field(params_8, t)*(Identity(wires=[4])))
Thus, when I do qml.evolve(Hamiltonian)
it must be called as qml.evolve(Hamiltonian)([0,1,2,3,4,5,6,7,8], 1)
for it to run.
As one can see, each PauliZ(i) @ PauliZ(i+1)
term contains a different control_field(params, t)
coefficient. Ideally, I would want each PauliZ(i) @ PauliZ(i+1)
term to have the same coefficient and similarly for each Identity(i)
term. So, in this particular example, I’d like for my Hamiltonian to look like
(control_field(params_0, t)*(PauliZ(wires=[0]) @ PauliZ(wires=[1])))
+ (control_field(params_0, t)*(PauliZ(wires=[1]) @ PauliZ(wires=[2])))
+ (control_field(params_0, t)*(PauliZ(wires=[2]) @ PauliZ(wires=[3])))
+ (control_field(params_0, t)*(PauliZ(wires=[3]) @ PauliZ(wires=[4])))
+ (control_field(params_1, t)*(Identity(wires=[0])))
+ (control_field(params_1, t)*(Identity(wires=[1])))
+ (control_field(params_1, t)*(Identity(wires=[2])))
+ (control_field(params_1, t)*(Identity(wires=[3])))
+ (control_field(params_1, t)*(Identity(wires=[4])))
I want it such that I can just call qml.evolve(Hamiltonian)([0,1], 1)
to run the evolution.
Thank you in advance!