Help to building cost function

In this git repo they wrote the single_cost with expvalcost. But in the new version I need to use expval . How can i change the code?

single_cost = qml.ExpvalCost(ansatz, H, dev)
w = np.arange(num_qubits, 0, -1)

def total_cost(params):
cost = 0
for state_idx in range(num_qubits):
cost += w[state_idx] * single_cost(params, state_idx=state_idx)
return cost
opt = qml.AdamOptimizer(stepsize=0.05)
max_iterations = 200
costs =

Initial parameters for the ansatz

num_layers = 8
params = np.random.uniform(low=0, high=2*np.pi, size=(num_layers, num_qubits, 3))

Hi @Kaushik ,
Below is an example of how qml.expval works.

@qml.qnode(dev)
def cost_function(params):
    some_qfunc(params)
    return qml.expval(Hamiltonian)

Comparing to the code you’re looking at, some_qfunc would become ansatz , params would become params, wires, state_idx=0, and Hamiltonian would become H.

Then you can write single_cost =cost_function(params, wires, state_idx=0).

I hope this helps you!

I tried to write it

    @qml.qnode(self.dev)
    def cost_function( params,wires=self.num_qubits, state_idx=0):
        self.ansatz(params,wires=self.num_qubits,state_idx=0)
        return qml.expval(H)
    self.single_cost = cost_function(params,wires = self.num_qubits,state_idx=0)

and total_cost like this

def total_cost(self,params, kwargs):
single_cost = kwargs.get(‘single_cost’)
w = kwargs.get(‘w’)
cost = 0
for state_idx in range(2
self.num_qubits):
cost +=w[state_idx]*single_cost(params,wires=self.num_qubits, state_idx=state_idx)
return cost

Error: cost +=w[state_idx]*single_cost(params,wires=self.num_qubits, state_idx=state_idx)

TypeError: ‘tensor’ object is not callable

Here
self.w = np.arange(2**self.num_qubits, 0, -1)

Hi @Kaushik,

Can you please write a minimal example which shows this error?
Something that I can use to try to replicate your error.

Below is an example of how to perform an optimization within a class (taken from another Forum thread). It might help you get an idea on how to set up your program.

import pennylane as qml
from pennylane import numpy as np

class MyClass:
    def __init__(self, n_qubits):
        self.n_qubits = n_qubits
        device = qml.device("default.qubit", wires=n_qubits)

        self.quantum_node = qml.QNode(self.quantum_function, device)

    def quantum_function(self, params):
        for i in range(len(params)):
            qml.RX(params[i], wires=i)
        return [qml.expval(qml.PauliZ(i)) for i in range(len(params))]

    def cost(self, params):
        return -np.sum(self.quantum_node(params))

    def do_optimization(self):
        params = np.random.uniform(0, np.pi, size=(self.n_qubits,), requires_grad=True)
        opt = qml.GradientDescentOptimizer(0.1)
        for n in range(10):
            params = opt.step(self.cost, params)
            print(self.cost(params))

obj = MyClass(4)
obj.do_optimization()

I hope this helps you solve your question!

Thank you for help. But when I am changing the way of writing of single_cost , should I change the way of writing total_cost also?

 def states(self, nq=None)->list:
        if not nq:
            nq = self.num_qubits
        st = []
        for i in range(2 ** nq):
            formStr = '0' + repr(nq) + 'b'
            st.append(format(i, formStr))
        return st

 def ansatz(self, params, wires, state_idx=0)-> None:
        state = self.states(nq =self.num_qubits)
        
        for ind_qb, qb in enumerate(list(state[state_idx])):
            if qb =='1':
                qml.PauliX(wires=wires[ind_qb])

then cost total cost is defined

Hi @Kaushik,

Actually the original code runs if you leave total_cost as it is but change single_cost in a different way. So instead of having a cost_function qnode, you can have a single_cost qnode instead.

@qml.qnode(dev)
def single_cost(params, state_idx=0):
  ansatz(params,wires=range(num_qubits),state_idx=state_idx)
  return qml.expval(H)

I hope this helps you!

1 Like

I changed the single_cost function

  @qml.qnode(self.dev)
    def single_cost( params, state_idx=0):
        self.ansatz(params,wires=range(num_qubits),state_idx=state_idx)
        return qml.expval(H)

Still the program is showing error

self.params,prev_energy = opt.step_and_cost(self.total_cost, self.params, single_cost = self.single_cost, w= self.w)

AttributeError: ‘SSVQE’ object has no attribute ‘single_cost’

Hi @Kaushik,

Here you have a part of the line saying self.single_cost but you haven’t defined it as an attribute. If you change it to single_cost you shouldn’t see the error anymore.

1 Like
import pandas as pd
import scipy as scp

from pennylane import numpy as np
import matplotlib.pyplot as plt
from math import pi
import os
os.environ["OMP_NUM_THREADS"] = "6"
from pennylane import numpy as np
import pennylane as qml
from pennylane.templates import RandomLayers
from pennylane import broadcast
from pennylane import expval, var, device
from pennylane.transforms import mitigate_with_zne
from ase.build import bulk
from ase.lattice import FCC
from pennylane import numpy as np
from multiprocessing import pool

from functools import wraps
from time import time


class KP:
    def __init__(self, ep0=1.5292, delta=0.340, a=5.653, Ep=22.71, verbose=1, npoints_path=15):
        self.RY =1
        self.ep0= 1.5292
        self.delta = 0.341
        self.a=a
        self.verbose = verbose
        self.npoints_path = npoints_path
        self.Ep = 22.71
        self.gamma1 = 7.03
        self.gamma2 = 2.33
        self.gamma3 = 3.03
        self.mass = 0.0665
        self.P = 9.75
        
        
    def lattice(self,atom = 'Si',structure = 'diamond', path = 'XGL'):
        self.atom =atom
        self.structure = structure
        self.pathPoints = path
        
        struc = bulk(self.atom,self.structure, a= self.a)
        self.lat = struc.cell.get_bravais_lattice()
        
        self.path = struc.cell.bandpath(self.pathPoints, npoints=self.npoints_path)
        pt = FCC(self.a).bandpath(self.pathPoints, npoints = self.npoints_path)
       
        self.p_axis = pt.get_linear_kpoint_axis(eps = 1e-5)[0]
        self.p_labels_vert = pt.get_linear_kpoint_axis(eps = 1e-5)[1]
        self.p_labels_stg = pt.get_linear_kpoint_axis(eps = 1e-5)[2]
        
        if self.verbose == 1:
            print('Symmetry points =  ',list(self.lat.get_special_points()))
            print('k-vector-path = ', self.p_axis)
            print('Path vertices = ', self.p_labels_vert)
            print('Path labels = ', self.p_labels_stg)
            
            
        self.data = pd.DataFrame(self.path.kpts,columns=['kx','ky','kz'])
        self.data['k'] = np.sqrt((self.data['kx'])**2+(self.data['kx'])**2+(self.data['kx'])**2)
        
        
    def Hamilton_GaAs(self, index = 0, nqbits=3, custom_lattice = False)->np.array:
        if not custom_lattice:
            self.lattice()
        else:
            print("define a custom lattice")
        
        
        k = self.data.iloc[index].k
        kx = self.data.iloc[index].kx
        ky = self.data.iloc[index].ky
        kz = self.data.iloc[index].kz
        kmais = kx + 1j * ky
        kmenos = kx - 1j * ky
        e = 1 / self.mass - (self.Ep/3) * ((2 / self.ep0) + 1 / (self.ep0 + self.delta))
        P = 9.75
        
        Q = - ((self.gamma1 + self.gamma2)*(kx**2 - ky**2) - (self.gamma1 - 2*self.gamma2)*kz**2 )
        R = -np.sqrt(3)*(self.gamma2*(kx**2 - ky**2) + 2*1j*self.gamma3*kx*ky)
        Ec = self.ep0 + e*(kx**2 + ky**2 + kz**2)
        Pz = self.P * kz
        T = - ((self.gamma1 - self.gamma2)*(kx**2 + ky**2) + (self.gamma1 + 2*self.gamma2)*kz**2 )
        S = 1j * (2*np.sqrt(3) * self.gamma3 * kz * kmenos)
        Pmais = self.P * kmais / np.sqrt(2)
        Pmenos = self.P * kmenos / np.sqrt(2)
        H = np.zeros((4,4), dtype=np.complex64)               
        
        H[0,0] = T/2
        H[0,1] = - S
        H[0,2] = - 1j * (T-Q) / np.sqrt(2)
        H[0,3] = - 1j * np.sqrt(2/3) * Pz
        H[1,1] = Q/2
        H[1,2] = -1j * np.conjugate(S) / np.sqrt(2)
        H[1,3] = - Pmais
        H[2,2] = ((Q+T)/2 - self.delta) / 2
        H[2,3] = -Pz  / np.sqrt(3)
        H[3,3] = Ec/2
        self.H = H + np.transpose(np.conjugate(H))
        return self.H[:2**nqbits,:2**nqbits]
    
class SSVQE:
    def __init__(self, index=0, ep0=1.5292, delta=0.752, a=5.653, num_qubits=2, verbose=1, 
                 npoints_path=15, machine=None, num_layers=2, num_excited=0): 
            self.time = []
            self.num_qubits= num_qubits
            self.index=index
            self.verbose=verbose
            self.npoints_path= npoints_path
            self.ep0=ep0
            self.delta=delta
            self.a=a
            self.HKP= KP(ep0=self.ep0, delta=self.delta, a=self.a, verbose=self.verbose, npoints_path= self.npoints_path)
            self.HH = self.HKP.Hamilton_GaAs(index=self.index,nqbits =self.num_qubits)
            self.data = self.HKP.data
            self.machine= machine
            self.num_layers= num_layers
            self.num_excited= num_excited

            
            
            if self.machine == "PennyLane_statevector":
                self.dev = qml.device("default.qubit", wires = self.num_qubits)
            elif self.machine == "PennyLane_simulator":
                self.dev = qml.device("default.mixed", wires = self.num_qubits, shots= 1024)
            elif self.machine == "qasm_Statevector":
                self.dev = qml.device('qiskit.aer', wires=self.num_qubits, backened='aer_simulator_Statevector')
            
            if self.verbose ==1:
                print('Hamiltonian:')
                print(self.HH)
                print('Number of Qubits:', self.num_qubits)
                print('Running on ', machine)
                self.epoch2print =50
            elif self.verbose == 0:
                self.epoch2print = 200
                
    def states(self, nq=None)->list:
        if not nq:
            nq = self.num_qubits
        st = []
        for i in range(2 ** nq):
            formStr = '0' + repr(nq) + 'b'
            st.append(format(i, formStr))
        return st
   
    


    
    
    
    def ansatz(self, params, wires, state_idx=0)-> None:
        state = self.states(nq =self.num_qubits)
        
        for ind_qb, qb in enumerate(list(state[state_idx])):
            if qb =='1':
                qml.PauliX(wires=wires[ind_qb])
                
                
        qml.templates.StronglyEntanglingLayers(params, wires = range(self.num_qubits))
    

    

    
        
    
        
    def total_cost(self,params, **kwargs):
       single_cost = kwargs.get('single_cost')
       w = kwargs.get('w')
       cost = 0
       for state_idx in range(2**self.num_qubits):
           cost +=w[state_idx]*single_cost(params,wires=self.num_qubits, state_idx=state_idx)
       return cost
    def run(self, params, max_iterations =1000, conv_tol = 1e-5, n_excited = 1, optimizer = 'Adam', 
            opt_rate = 0.1,method= 'simple',processes=None):
        self.n_excited = n_excited
        self.max_iterations = max_iterations
        self.conv_tol = conv_tol
        self.params = params

        coeffs, obs_list = qml.pauli.conversion._generalized_pauli_decompose(self.HH)
        obs_groupings = qml.pauli.group_observables(observables=obs_list, grouping_type="qwc", method="rlf")
        


        H = qml.Hamiltonian(coeffs, obs_list)
        eigen,_ = np.linalg.eigh(self.HH)
        energies = np.zeros(2)
        
        
        self.dev = qml.device("default.qubit", wires = self.num_qubits)


            
       
        
        
        @qml.qnode(self.dev)
        def single_cost( params,wires=self.num_qubits, state_idx=0):
            self.ansatz(params,wires=self.num_qubits,state_idx=0)
            return qml.expval(H)
        self.single_cost = single_cost
        
        


        self.w = np.arange(2**self.num_qubits, 0, -1)
        energy_optimized, ind, energies_during_opt = self.optimize(params, optm=optimizer, opt_rate=opt_rate, conv_tol=self.conv_tol)

        results = {
            'energy_optimized': energy_optimized,
            'param_optimized': params,
            'all_energies': energies_during_opt,
            'number_of_cycles': ind,
            'convergence_tolerance': self.conv_tol
        }
        return results

    
    
    
    def optimize(self,params,optm = 'Adam', opt_rate = 0.1, conv_tol = 1e-3):
        self.params = params
        opt = self.optimizers(optm,opt_rate)
        costs = []
        
        conv = 10
        KP_callback_energies = np.zeros((self.n_excited+1,self.max_iterations))
        low_energy = 1e3
        param_low_energy = params
        
        prev = 1e3
        for i in range(self.max_iterations):
            self.params,prev_energy = opt.step_and_cost(self.total_cost, self.params, single_cost = self.single_cost, w= self.w)
            energy = self.total_cost(self.params, single_cost = self.single_cost, w = self.w)
            conv = np.abs(prev_energy - energy)
            
            
            KP_callback_energies[0,i] = prev_energy
            if energy < low_energy:
                print('Energy lowered, Actual low energy = ', energy)
                low_energy = energy
                param_low_energy = self.params
                
                
            if i%1 == 0:
                print('iteration = ', i)
                print('conv = ', conv)
                print('energy = ', energy)
                   
            if(conv<= self.conv_tol):
                break
                
                
        print("optimization converged after ", i , "cycles1")
        if energy > low_energy:
            self.params = param_low_energy
            print('Energy non_converged after maximum iterations... ')
            
            
        energy_optimized = np.zeros(self.num_excited + 1)
        for exc in range(self.num_excited+1):
            energy_optimized[exc] = self.single_cost(self.params, state_idx = exc)


        return enrgy_optimized, i, KP_callback_energies
    def optimizers(self, optm, opt_rate, eps=1e-8):
        if optm == 'Adam':
            opt = qml.AdamOptimizer(stepsize=opt_rate, eps=eps)
        elif optm == 'Adagrad':
            opt = qml.AdagradOptimizer(stepsize=opt_rate, eps=eps)
        
        else:
            raise ValueError("Unsupported optimizer: {}".format(optm))
        return opt
            


if __name__=='__main__':
    num_layers = 5 # number of entangling layers of the ansatz
    num_qubits = 2 # number of qubits
    point_path = 1 # number of points in Brillouin Zone path
    num_excited = num_qubits**2 - 1

    vqe = SSVQE(index=0, num_qubits=num_qubits, num_excited=num_excited, npoints_path=1, machine="PennyLane_statevector")
    params = np.random.uniform(low=0, high=2*np.pi, size=(num_layers, num_qubits, 3), requires_grad=True) 
    print('params', params)

    res = vqe.run(params, max_iterations=1)

This is the program but it is showing error again and again.

TypeError                                 Traceback (most recent call last)
Cell In[1], line 295
    292 params = np.random.uniform(low=0, high=2*np.pi, size=(num_layers, num_qubits, 3), requires_grad=True) 
    293 print('params', params)
--> 295 res = vqe.run(params, max_iterations=1)

Cell In[1], line 214, in SSVQE.run(self, params, max_iterations, conv_tol, n_excited, optimizer, opt_rate, method, processes)
    208 self.single_cost = single_cost
    213 self.w = np.arange(2**self.num_qubits, 0, -1)
--> 214 energy_optimized, ind, energies_during_opt = self.optimize(params, optm=optimizer, opt_rate=opt_rate, conv_tol=self.conv_tol)
    216 results = {
    217     'energy_optimized': energy_optimized,
    218     'param_optimized': params,
   (...)
    221     'convergence_tolerance': self.conv_tol
    222 }
    223 return results

Cell In[1], line 240, in SSVQE.optimize(self, params, optm, opt_rate, conv_tol)
    238 prev = 1e3
    239 for i in range(self.max_iterations):
--> 240     self.params,prev_energy = opt.step_and_cost(self.total_cost, self.params, single_cost = self.single_cost, w= self.w)
    241     energy = self.total_cost(self.params, single_cost = self.single_cost, w = self.w)
    242     conv = np.abs(prev_energy - energy)

File ~\anaconda3\Lib\site-packages\pennylane\optimize\gradient_descent.py:64, in GradientDescentOptimizer.step_and_cost(self, objective_fn, grad_fn, *args, **kwargs)
     44 def step_and_cost(self, objective_fn, *args, grad_fn=None, **kwargs):
     45     """Update trainable arguments with one step of the optimizer and return the corresponding
     46     objective function value prior to the step.
     47 
   (...)
     61         If single arg is provided, list [array] is replaced by array.
     62     """
---> 64     g, forward = self.compute_grad(objective_fn, args, kwargs, grad_fn=grad_fn)
     65     new_args = self.apply_grad(g, args)
     67     if forward is None:

File ~\anaconda3\Lib\site-packages\pennylane\optimize\gradient_descent.py:122, in GradientDescentOptimizer.compute_grad(objective_fn, args, kwargs, grad_fn)
    104 r"""Compute gradient of the objective function at the given point and return it along with
    105 the objective function forward pass (if available).
    106 
   (...)
    119     will not be evaluted and instead ``None`` will be returned.
    120 """
    121 g = get_gradient(objective_fn) if grad_fn is None else grad_fn
--> 122 grad = g(*args, **kwargs)
    123 forward = getattr(g, "forward", None)
    125 num_trainable_args = sum(getattr(arg, "requires_grad", False) for arg in args)

File ~\anaconda3\Lib\site-packages\pennylane\_grad.py:165, in grad.__call__(self, *args, **kwargs)
    162     self._forward = self._fun(*args, **kwargs)
    163     return ()
--> 165 grad_value, ans = grad_fn(*args, **kwargs)  # pylint: disable=not-callable
    166 self._forward = ans
    168 return grad_value

File ~\anaconda3\Lib\site-packages\autograd\wrap_util.py:20, in unary_to_nary.<locals>.nary_operator.<locals>.nary_f(*args, **kwargs)
     18 else:
     19     x = tuple(args[i] for i in argnum)
---> 20 return unary_operator(unary_f, x, *nary_op_args, **nary_op_kwargs)

File ~\anaconda3\Lib\site-packages\pennylane\_grad.py:186, in grad._grad_with_forward(fun, x)
    183 vjp, ans = _make_vjp(fun, x)  # pylint: disable=redefined-outer-name
    185 if vspace(ans).size != 1:
--> 186     raise TypeError(
    187         "Grad only applies to real scalar-output functions. "
    188         "Try jacobian, elementwise_grad or holomorphic_grad."
    189     )
    191 grad_value = vjp(vspace(ans).ones())
    192 return grad_value, ans

TypeError: Grad only applies to real scalar-output functions. Try jacobian, elementwise_grad or holomorphic_grad.

Can you help me to debug the code and run it properly?

Hi @Kaushik,

You’re getting this error because you’re trying to find the gradient over a function that returns multiple values instead of just one (you can learn more here in the docs).

I think the best is to check the return for your cost function and reduce it to a single value. Or roll back some of the changes you made since the last working version.

Let me know if this helps!

@qml.qnode(self.dev)
def single_cost( params,wires=self.num_qubits, state_idx=0):
self.ansatz(params,wires=self.num_qubits,state_idx=0)
return qml.expval(H)
self.single_cost = single_cost(params,wires=self.num_qubits, state_idx=0)

If I define the single_cost like this , it is showing error

cost +=w[state_idx]*single_cost(params,wires=self.num_qubits, state_idx=state_idx)

TypeError: ‘tensor’ object is not callable

I tried to use pennylane 0.32 version

import pennylane.utils
from matplotlib import pyplot as plt

import pandas as pd
import scipy as scp

from pennylane import numpy as np
import matplotlib.pyplot as plt
from math import pi

import os
os.environ[“OMP_NUM_THREADS”] = “6”
from pennylane import numpy as np
import pennylane as qml
from pennylane.templates import RandomLayers
from pennylane import broadcast
from pennylane import expval, var, device

from mitiq.zne.scaling import fold_global
from mitiq.zne.inference import RichardsonFactory
from mitiq.zne.scaling import fold_gates_at_random as folding
from mitiq.zne.inference import AdaExpFactory
from pennylane.transforms import mitigate_with_zne
from mitiq.zne import execute_with_zne
from mitiq.zne.scaling import fold_gates_at_random as folding
from qiskit.providers.fake_provider import FakeLima
from qiskit.providers.aer.noise import NoiseModel

from ase.build import bulk
from ase.lattice import FCC
from pennylane import numpy as np
from qiskit.providers.fake_provider import FakeLima
from multiprocessing import pool

from functools import wraps
from time import time

from qiskit import Aer
from optimparallel import minimize_parallel
from qiskit import IBMQ

class KP:
def init(self, ep0=1.5292, delta=0.340, a=5.653, Ep=22.71, verbose=1, npoints_path=15):

    self.RY =1
    self.ep0= 1.5292
    self.delta = 0.341
    self.a=a
    self.verbose = verbose
    self.npoints_path = npoints_path
    self.Ep = 22.71
    self.gamma1 = 7.03
    self.gamma2 = 2.33
    self.gamma3 = 3.03
    self.mass = 0.0665
    self.P = 9.75
    
def lattice(self,atom = 'Si',structure = 'diamond', path = 'XGL'):
    self.atom =atom
    self.structure = structure
    self.pathPoints = path
    
    struc = bulk(self.atom,self.structure, a= self.a)
    self.lat = struc.cell.get_bravais_lattice()
    
    self.path = struc.cell.bandpath(self.pathPoints, npoints=self.npoints_path)
    pt = FCC(self.a).bandpath(self.pathPoints, npoints = self.npoints_path)
   
    self.p_axis = pt.get_linear_kpoint_axis(eps = 1e-5)[0]
    self.p_labels_vert = pt.get_linear_kpoint_axis(eps = 1e-5)[1]
    self.p_labels_stg = pt.get_linear_kpoint_axis(eps = 1e-5)[2]
    
    if self.verbose == 0:
        print('Symmetry points =  ',list(self.lat.get_special_points()))
        print('k-vector-path = ', self.p_axis)
        print('Path vertices = ', self.p_labels_vert)
        print('Path labels = ', self.p_labels_stg)

    #creating a dataframe to stroe the path
    self.data = pd.DataFrame(self.path.kpts,columns=['kx','ky','kz'])
    self.data['k'] = np.sqrt((self.data['kx'])**2+(self.data['kx'])**2+(self.data['kx'])**2)
   


def Hamilton_GaAs(self, index = 0, nqbits=3, custom_lattice = False)->np.array:
    if not custom_lattice:
        self.lattice()
    else:
        print("define a custom lattice")
    
    
    k = self.data.iloc[index].k
    kx = self.data.iloc[index].kx
    ky = self.data.iloc[index].ky
    kz = self.data.iloc[index].kz

    kmais = kx + 1j * ky
    kmenos = kx - 1j * ky

    e = 1 / self.mass - (self.Ep/3) * ((2 / self.ep0) + 1 / (self.ep0 + self.delta))
    P = 9.75
    
    Q = - ((self.gamma1 + self.gamma2)*(kx**2 - ky**2) - (self.gamma1 - 2*self.gamma2)*kz**2 )
    R = -np.sqrt(3)*(self.gamma2*(kx**2 - ky**2) + 2*1j*self.gamma3*kx*ky)
    Ec = self.ep0 + e*(kx**2 + ky**2 + kz**2)
    Pz = self.P * kz

    T = - ((self.gamma1 - self.gamma2)*(kx**2 + ky**2) + (self.gamma1 + 2*self.gamma2)*kz**2 )
    S = 1j * (2*np.sqrt(3) * self.gamma3 * kz * kmenos)
    Pmais = self.P * kmais / np.sqrt(2)
    Pmenos = self.P * kmenos / np.sqrt(2)

    H = np.zeros((4,4), dtype=np.complex64)               
    
    H[0,0] = T/2
    H[0,1] = - S
    H[0,2] = - 1j * (T-Q) / np.sqrt(2)
    H[0,3] = - 1j * np.sqrt(2/3) * Pz
    H[1,1] = Q/2
    H[1,2] = -1j * np.conjugate(S) / np.sqrt(2)
    H[1,3] = - Pmais

    H[2,2] = ((Q+T)/2 - self.delta) / 2
    H[2,3] = -Pz  / np.sqrt(3)

    H[3,3] = Ec/2

    self.H = H + np.transpose(np.conjugate(H))
    return self.H[:2**nqbits,:2**nqbits]

class SSVQE:

def __init__(self, index=0, ep0=1.5292, delta=0.752, a=5.653, num_qubits=2, verbose=1, npoints_path=15, machine=None, num_layers=2, num_excited=0):

    
    
    self.time = []
    self.num_qubits= num_qubits
    self.index=index
    self.verbose=verbose
    self.npoints_path= npoints_path
    self.ep0=ep0
    self.delta=delta
    self.a=a
    self.HKP= KP(ep0=self.ep0, delta=self.delta, a=self.a, verbose=self.verbose, npoints_path= self.npoints_path)
    self.HH = self.HKP.Hamilton_GaAs(index=self.index,nqbits =self.num_qubits)
    self.data = self.HKP.data
    self.machine= machine
    self.num_layers= num_layers
    self.num_excited= num_excited
    
    
    
    if self.machine == "PennyLane_statevector":
        self.dev = qml.device("default.qubit", wires = self.num_qubits)
    elif self.machine == "PennyLane_simulator":
        self.dev = qml.device("default.mixed", wires = self.num_qubits, shots= 1024)
    elif self.machine == "qasm_Statevector":
        self.dev = qml.device('qiskit.aer', wires=self.num_qubits, backened='aer_simulator_Statevector')
        
        
    if self.verbose ==1:
        print('Hamiltonian:')
        print(self.HH)
        print('Number of Qubits:', self.num_qubits)
        print('Running on ', machine)
        self.epoch2print =50
    elif self.verbose == 0:
        self.epoch2print = 200
        
        
        
def states(self, nq=None)->list:
    if not nq:
        nq = self.num_qubits
    st = []
    for i in range(2 ** nq):
        formStr = '0' + repr(nq) + 'b'
        st.append(format(i, formStr))
    return st


def ansatz(self, params, wires, state_idx=0)-> None:
    state = self.states(nq =self.num_qubits)
    
    for ind_qb, qb in enumerate(list(state[state_idx])):
        if qb =='1':
            qml.PauliX(wires=wires[ind_qb])
            
            
    qml.templates.StronglyEntanglingLayers(params, wires = range(self.num_qubits))
    
    
def total_cost(self,params, **kwargs):
    single_cost = kwargs.get('single_cost')
    w = kwargs.get('w')
    cost = 0
    for state_idx in range(2**self.num_qubits):
        cost +=w[state_idx]*single_cost(params, state_idx=state_idx)
    return cost


def run(self, params, max_iterations =1000, conv_tol = 1e-5, n_excited = 1, optimizer = 'Adam', opt_rate = 0.1,method= 'simple',processes=None):
   self.n_excited = n_excited
   self.max_iterations = max_iterations
   self.conv_tol = conv_tol
   self.params = params
   
   coeffs, obs_list = qml.pauli.conversion._generalized_pauli_decompose(self.HH)
   
   
   obs_groupings = qml.pauli.group_observables(observables=obs_list, grouping_type="qwc", method="rlf")
   print("Number of required measurements after optimization", len(obs_groupings))
   
   
   H = qml.Hamiltonian(coeffs, obs_list)
   
   
   
   eigen,_ = np.linalg.eigh(self.HH)
   energies = np.zeros(2)
   
   
   if self.machine == "PennyLane_statevector":
       self.dev = qml.device("default.qubit", wires = self.num_qubits)
   elif self.machine == "PennyLane_simulator":
       self.dev = qml.device("default.mixed", wires = self.num_qubits, shots= 1024)
   elif self.machine == "qasm_Statevector":
       self.dev = qml.device('qiskit.aer', wires=self.num_qubits, backened='aer_simulator_Statevector')
       
       
       
   self.nonoiseDev = qml.device("default.qubit", wires = self.num_qubits)
   self.nonoisesingle_cost = qml.ExpvalCost(self.ansatz, H , self.nonoiseDev, optimize = True)
   
   
   
   
   
   
   single_cost = qml.ExpvalCost(self.ansatz, H, self.dev, optimize = True)
   self.single_cost=qml.jacobian(single_cost)
   
   self.w = np.arange(2**self.num_qubits, 0, -1)
   
   
   if method == "parallel" and optimizer !='COBYLA':
       energy_optimized, ind, energies_during_opt = self.optimize_parallel(
        params,optm = optimizer, opt_rate= opt_rate, conv_tol = self.conv_tol)
   elif method =="adaptive_parallel" :
       energy_optimized,ind,energies_during_opt = self.adaptive_optimize_parallel(
           params,optm=optimizer,opt_rate=opt_rate,conv_tol=self.conv_tol)
   elif method == "simple":
       energy_optimized, ind, energies_during_opt = self.optimize(
        params,optm = optimizer, opt_rate= opt_rate, conv_tol = self.conv_tol)
   elif method == "adaptive_parallel":
       energy_optimized, ind, energies_during_opt = self.optimize_parallel(
        params,optm = optimizer, opt_rate= opt_rate, conv_tol = self.conv_tol)
   elif method == "adaptive":
       energy_optimized, ind, energies_during_opt = self.adaptive_optimize(
        params,optm = optimizer, opt_rate= opt_rate, conv_tol = self.conv_tol)
   
   
   
   results = {
        'energy_optimized': energy_optimized,
        'param_optimized':params,
        'all_energies':energies_during_opt,
        'number_of_cycles':ind,
        'convergence_tolerance':self.conv_tol
        
    }
    
       
   return results


def timing(f):
    @wraps(f)
    def wrap(self,*args,**kw):
        ts=time()
        result = f(self,*args,**kw)
        te = time()
        dt = te-ts
        print('function_time'%(f.__name__,args,kw,te-ts))
        self.time.append({'seconds': dt})
        return result
    return wrap


def optimize_conver(self,params,optm='Adam', opt_rate = 0.1, conv_tol = 1e-3):
   self.params = params
   opt = self.optimizers(optm, opt_rate= opt_rate)
   costs = []
   
   conv = np.ones(self.n_excited +1)
   
   KP_callback_energies = np.zeros(self.n_excited+1,self.max_iterations)
   
   prev = np.ones(self.n_excited+1)* 1e3
   for i in range(self.max_iterations):
       self.params,prev_energy = opt.step_and_cost(
       self.total_cost,self.params,single_cost = self.single_cost, w= self.w)
       energy = self.total_cost(self.params,single_cost= self.single_cost, w= self.w)
       
       
       for exc in range(self.n_excited+1):
           if conv[exc] == self.conv_tol:
               en = self.single_cost(self.params, state_idx = exc)
               conv[exc] = np.abs(en-prev[exc])
               prev[exc] = en
               
               
           KP_callback_energies[exc, i] = en
           
           
       if i%1==0:
           print('iteration = ', i)
           print('conv = ', conv)
           print('energy = ', prev)
           
           
       if np.all(conv = self.conv_tol):
           break
           
   print("optimization convergence after ",i,"cycles1")
   energy_optimized = prev
   
   return energy_optimized, i, KP_callback_energies

@timing
def optimize(self,params,optm = 'Adam', opt_rate = 0.1, conv_tol = 1e-3):
   self.params = params
   opt = self.optimizers(optm,opt_rate)
   costs = []
   
   conv = 10
   KP_callback_energies = np.zeros((self.n_excited+1,self.max_iterations))
   low_energy = 1e3
   param_low_energy = params
   
   prev = 1e3
   for i in range(self.max_iterations):
       self.params,prev_energy = opt.step_and_cost(self.total_cost, self.params, single_cost = self.single_cost, w= self.w)
       energy = self.total_cost(self.params, single_cost = self.single_cost, w = self.w)
       conv = np.abs(prev_energy - energy)
       
       
       KP_callback_energies[0,i] = prev_energy
       
       
       if energy < low_energy:
           print('Energy lowered, Actual low energy = ', energy)
           low_energy = energy
           param_low_energy = self.params
           
           
       if i%1 == 0:
           print('iteration = ', i)
           print('conv = ', conv)
           print('energy = ', energy)
           
           
       if(conv<= self.conv_tol):
           break
           
           
   print("optimization converged after ", i , "cycles1")
   
   if energy > low_energy:
       self.params = param_low_energy
       print('Energy non_converged after maximum iterations... ')
       
       
   energy_optimized = np.zeros(self.num_excited + 1)
   for exc in range(self.num_excited+1):
       energy_optimized[exc] = self.single_cost(self.params, state_idx = exc)
       
       
   return energy_optimized, i, KP_callback_energies


@timing
def adaptive_optimizer(self,params, optm = 'Adam', opt_rate= 0.1, conv_tol = 1e-4):
 self.params = params
 opt = self.optimizers(optm, opt_rate = opt_rate)
 
 costs = []
 
 self.conv_tol_local = 1e-2
 conv = 10
 
 
 KP_callback_energies = []
 en = np.zeros(self.n_excited+1)
 prev = 1e3
 for i in range(self.max_iterations):
     self.params,prev_energy = opt.step_and_cost(self.total_cost, self.params, single_cost= self.single_cost, w= self.w)
     energy = self.total_cost(self.params, single_cost = self.single_cost, w= self.w)
     
     
     KP_callback_energies.append(energy)
     
     if conv > self.conv_tol_local:
         conv = np.abs(prev_energy = energy)
         prev = energy
     elif  (self.conv_tol_local > self.conv_tol and conv <= self.conv_tol_local):
         opt_rate = opt_rate/2
         self.conv_tol_local = self.conv_tol_local/10
         opt = self.optimizers(optm,opt_rate = opt_rate)
         conv = np.abs(prev_energy - energy)
         prev = energy
         
     elif self.conv_tol_local<= self.conv_tol and conv <= self.conv_tol:
         for exc in range (self.n_excited +1):
             en[exc] = self.single_cost(self.params, state_idx = exc)
             
             
     if i%1 ==0:
         print('iteration', i)
         print('conv=', conv)
         print('energy', energy)
         print('step_size= ', opt_rate)
         print('conv_tol_local = ', self.conv_tol_local)
         
         
     print("optimization converged after ", i, "cycles1")
     print("optimized energies ", en)
     return en, i, KP_callback_energies
 
def optimizers(self, optm, opt_rate, eps=1e-8):
    if optm == 'Adam':
        opt = qml.AdamOptimizer(stepsize=opt_rate, eps=eps)
    elif optm == 'Adagrad':
        opt = qml.AdagradOptimizer(stepsize=opt_rate, eps=eps)
    
    else:
        raise ValueError("Unsupported optimizer: {}".format(optm))
    return opt

if name==‘main’:
num_layers = 5 # number of entangling layers of the ansatz
num_qubits = 2 # number of qubits
point_path = 1 # number of points in Brillouin Zone path
num_excited = num_qubits**2 - 1

vqe = SSVQE(index=0, num_qubits=num_qubits, num_excited=num_excited, npoints_path=1, machine="PennyLane_statevector")
params = np.random.uniform(low=0, high=2*np.pi, size=(num_layers, num_qubits, 3), requires_grad=True) 
print('params', params)

res = vqe.run(params, max_iterations=2000)

params = res.get(‘param_optimized’)

It is showing error:ValueError: cannot reshape array of size 60 into shape (5,2,3)

import pennylane.utils
from matplotlib import pyplot as plt

import pandas as pd
import scipy as scp

from pennylane import numpy as np
import matplotlib.pyplot as plt
from math import pi

import os
os.environ[“OMP_NUM_THREADS”] = “6”
from pennylane import numpy as np
import pennylane as qml
from pennylane.templates import RandomLayers
from pennylane import broadcast
from pennylane import expval, var, device

from mitiq.zne.scaling import fold_global
from mitiq.zne.inference import RichardsonFactory
from mitiq.zne.scaling import fold_gates_at_random as folding
from mitiq.zne.inference import AdaExpFactory
from pennylane.transforms import mitigate_with_zne
from mitiq.zne import execute_with_zne
from mitiq.zne.scaling import fold_gates_at_random as folding
from qiskit.providers.fake_provider import FakeLima
from qiskit.providers.aer.noise import NoiseModel

from ase.build import bulk
from ase.lattice import FCC
from pennylane import numpy as np
from qiskit.providers.fake_provider import FakeLima
from multiprocessing import pool

from functools import wraps
from time import time

from qiskit import Aer
from optimparallel import minimize_parallel
from qiskit import IBMQ

class KP:
def init(self, ep0=1.5292, delta=0.340, a=5.653, Ep=22.71, verbose=1, npoints_path=15):

    self.RY =1
    self.ep0= 1.5292
    self.delta = 0.341
    self.a=a
    self.verbose = verbose
    self.npoints_path = npoints_path
    self.Ep = 22.71
    self.gamma1 = 7.03
    self.gamma2 = 2.33
    self.gamma3 = 3.03
    self.mass = 0.0665
    self.P = 9.75
    
def lattice(self,atom = 'Si',structure = 'diamond', path = 'XGL'):
    self.atom =atom
    self.structure = structure
    self.pathPoints = path
    
    struc = bulk(self.atom,self.structure, a= self.a)
    self.lat = struc.cell.get_bravais_lattice()
    
    self.path = struc.cell.bandpath(self.pathPoints, npoints=self.npoints_path)
    pt = FCC(self.a).bandpath(self.pathPoints, npoints = self.npoints_path)
   
    self.p_axis = pt.get_linear_kpoint_axis(eps = 1e-5)[0]
    self.p_labels_vert = pt.get_linear_kpoint_axis(eps = 1e-5)[1]
    self.p_labels_stg = pt.get_linear_kpoint_axis(eps = 1e-5)[2]
    
    if self.verbose == 0:
        print('Symmetry points =  ',list(self.lat.get_special_points()))
        print('k-vector-path = ', self.p_axis)
        print('Path vertices = ', self.p_labels_vert)
        print('Path labels = ', self.p_labels_stg)

    #creating a dataframe to stroe the path
    self.data = pd.DataFrame(self.path.kpts,columns=['kx','ky','kz'])
    self.data['k'] = np.sqrt((self.data['kx'])**2+(self.data['kx'])**2+(self.data['kx'])**2)
   


def Hamilton_GaAs(self, index = 0, nqbits=3, custom_lattice = False)->np.array:
    if not custom_lattice:
        self.lattice()
    else:
        print("define a custom lattice")
    
    
    k = self.data.iloc[index].k
    kx = self.data.iloc[index].kx
    ky = self.data.iloc[index].ky
    kz = self.data.iloc[index].kz

    kmais = kx + 1j * ky
    kmenos = kx - 1j * ky

    e = 1 / self.mass - (self.Ep/3) * ((2 / self.ep0) + 1 / (self.ep0 + self.delta))
    P = 9.75
    
    Q = - ((self.gamma1 + self.gamma2)*(kx**2 - ky**2) - (self.gamma1 - 2*self.gamma2)*kz**2 )
    R = -np.sqrt(3)*(self.gamma2*(kx**2 - ky**2) + 2*1j*self.gamma3*kx*ky)
    Ec = self.ep0 + e*(kx**2 + ky**2 + kz**2)
    Pz = self.P * kz

    T = - ((self.gamma1 - self.gamma2)*(kx**2 + ky**2) + (self.gamma1 + 2*self.gamma2)*kz**2 )
    S = 1j * (2*np.sqrt(3) * self.gamma3 * kz * kmenos)
    Pmais = self.P * kmais / np.sqrt(2)
    Pmenos = self.P * kmenos / np.sqrt(2)

    H = np.zeros((4,4), dtype=np.complex64)               
    
    H[0,0] = T/2
    H[0,1] = - S
    H[0,2] = - 1j * (T-Q) / np.sqrt(2)
    H[0,3] = - 1j * np.sqrt(2/3) * Pz
    H[1,1] = Q/2
    H[1,2] = -1j * np.conjugate(S) / np.sqrt(2)
    H[1,3] = - Pmais

    H[2,2] = ((Q+T)/2 - self.delta) / 2
    H[2,3] = -Pz  / np.sqrt(3)

    H[3,3] = Ec/2

    self.H = H + np.transpose(np.conjugate(H))
    return self.H[:2**nqbits,:2**nqbits]

class SSVQE:

def __init__(self, index=0, ep0=1.5292, delta=0.752, a=5.653, num_qubits=2, verbose=1, npoints_path=15, machine=None, num_layers=2, num_excited=0):

    
    
    self.time = []
    self.num_qubits= num_qubits
    self.index=index
    self.verbose=verbose
    self.npoints_path= npoints_path
    self.ep0=ep0
    self.delta=delta
    self.a=a
    self.HKP= KP(ep0=self.ep0, delta=self.delta, a=self.a, verbose=self.verbose, npoints_path= self.npoints_path)
    self.HH = self.HKP.Hamilton_GaAs(index=self.index,nqbits =self.num_qubits)
    self.data = self.HKP.data
    self.machine= machine
    self.num_layers= num_layers
    self.num_excited= num_excited
    
    
    
    if self.machine == "PennyLane_statevector":
        self.dev = qml.device("default.qubit", wires = self.num_qubits)
    elif self.machine == "PennyLane_simulator":
        self.dev = qml.device("default.mixed", wires = self.num_qubits, shots= 1024)
    elif self.machine == "qasm_Statevector":
        self.dev = qml.device('qiskit.aer', wires=self.num_qubits, backened='aer_simulator_Statevector')
        
        
    if self.verbose ==1:
        print('Hamiltonian:')
        print(self.HH)
        print('Number of Qubits:', self.num_qubits)
        print('Running on ', machine)
        self.epoch2print =50
    elif self.verbose == 0:
        self.epoch2print = 200
        
        
        
def states(self, nq=None)->list:
    if not nq:
        nq = self.num_qubits
    st = []
    for i in range(2 ** nq):
        formStr = '0' + repr(nq) + 'b'
        st.append(format(i, formStr))
    return st


def ansatz(self, params, wires, state_idx=0)-> None:
    state = self.states(nq =self.num_qubits)
    
    for ind_qb, qb in enumerate(list(state[state_idx])):
        if qb =='1':
            qml.PauliX(wires=wires[ind_qb])
            
            
    qml.templates.StronglyEntanglingLayers(params, wires = range(self.num_qubits))
    
    
def total_cost(self,params, **kwargs):
    single_cost = kwargs.get('single_cost')
    w = kwargs.get('w')
    cost = 0
    for state_idx in range(2**self.num_qubits):
        cost +=w[state_idx]*single_cost(params, state_idx=state_idx)
    return cost


def run(self, params, max_iterations =1000, conv_tol = 1e-5, n_excited = 1, optimizer = 'Adam', opt_rate = 0.1,method= 'simple',processes=None):
   self.n_excited = n_excited
   self.max_iterations = max_iterations
   self.conv_tol = conv_tol
   self.params = params
   
   coeffs, obs_list = qml.pauli.conversion._generalized_pauli_decompose(self.HH)
   
   
   obs_groupings = qml.pauli.group_observables(observables=obs_list, grouping_type="qwc", method="rlf")
   print("Number of required measurements after optimization", len(obs_groupings))
   
   
   H = qml.Hamiltonian(coeffs, obs_list)
   
   
   
   eigen,_ = np.linalg.eigh(self.HH)
   energies = np.zeros(2)
   
   
   if self.machine == "PennyLane_statevector":
       self.dev = qml.device("default.qubit", wires = self.num_qubits)
   elif self.machine == "PennyLane_simulator":
       self.dev = qml.device("default.mixed", wires = self.num_qubits, shots= 1024)
   elif self.machine == "qasm_Statevector":
       self.dev = qml.device('qiskit.aer', wires=self.num_qubits, backened='aer_simulator_Statevector')
       
       
       
   self.nonoiseDev = qml.device("default.qubit", wires = self.num_qubits)
   self.nonoisesingle_cost = qml.ExpvalCost(self.ansatz, H , self.nonoiseDev, optimize = True)
   
   
   
   
   
   
   self.single_cost = qml.ExpvalCost(self.ansatz, H, self.dev, optimize = True,requires_grad=True)
   
   
   self.w = np.arange(2**self.num_qubits, 0, -1)
   
   
   if method == "parallel" and optimizer !='COBYLA':
       energy_optimized, ind, energies_during_opt = self.optimize_parallel(
        params,optm = optimizer, opt_rate= opt_rate, conv_tol = self.conv_tol)
   elif method =="adaptive_parallel" :
       energy_optimized,ind,energies_during_opt = self.adaptive_optimize_parallel(
           params,optm=optimizer,opt_rate=opt_rate,conv_tol=self.conv_tol)
   elif method == "simple":
       energy_optimized, ind, energies_during_opt = self.optimize(
        params,optm = optimizer, opt_rate= opt_rate, conv_tol = self.conv_tol)
   elif method == "adaptive_parallel":
       energy_optimized, ind, energies_during_opt = self.optimize_parallel(
        params,optm = optimizer, opt_rate= opt_rate, conv_tol = self.conv_tol)
   elif method == "adaptive":
       energy_optimized, ind, energies_during_opt = self.adaptive_optimize(
        params,optm = optimizer, opt_rate= opt_rate, conv_tol = self.conv_tol)
   
   
   
   results = {
        'energy_optimized': energy_optimized,
        'param_optimized':params,
        'all_energies':energies_during_opt,
        'number_of_cycles':ind,
        'convergence_tolerance':self.conv_tol
        
    }
    
       
   return results


def timing(f):
    @wraps(f)
    def wrap(self,*args,**kw):
        ts=time()
        result = f(self,*args,**kw)
        te = time()
        dt = te-ts
        print('function_time'%(f.__name__,args,kw,te-ts))
        self.time.append({'seconds': dt})
        return result
    return wrap


def optimize_conver(self,params,optm='Adam', opt_rate = 0.1, conv_tol = 1e-3):
   self.params = params
   opt = self.optimizers(optm, opt_rate= opt_rate)
   costs = []
   
   conv = np.ones(self.n_excited +1)
   
   KP_callback_energies = np.zeros(self.n_excited+1,self.max_iterations)
   
   prev = np.ones(self.n_excited+1)* 1e3
   for i in range(self.max_iterations):
       self.params,prev_energy = opt.step_and_cost(
       self.total_cost,self.params,single_cost = self.single_cost, w= self.w)
       energy = self.total_cost(self.params,single_cost= self.single_cost, w= self.w)
       
       
       for exc in range(self.n_excited+1):
           if conv[exc] == self.conv_tol:
               en = self.single_cost(self.params, state_idx = exc)
               conv[exc] = np.abs(en-prev[exc])
               prev[exc] = en
               
               
           KP_callback_energies[exc, i] = en
           
           
       if i%1==0:
           print('iteration = ', i)
           print('conv = ', conv)
           print('energy = ', prev)
           
           
       if np.all(conv = self.conv_tol):
           break
           
   print("optimization convergence after ",i,"cycles1")
   energy_optimized = prev
   
   return energy_optimized, i, KP_callback_energies

@timing
def optimize(self,params,optm = 'Adam', opt_rate = 0.1, conv_tol = 1e-3):
   self.params = params
   opt = self.optimizers(optm,opt_rate)
   costs = []
   
   conv = 10
   KP_callback_energies = np.zeros((self.n_excited+1,self.max_iterations))
   low_energy = 1e3
   param_low_energy = params
   
   prev = 1e3
   for i in range(self.max_iterations):
       self.params,prev_energy = opt.step_and_cost(self.total_cost, self.params, single_cost = self.single_cost, w= self.w)
       energy = self.total_cost(self.params, single_cost = self.single_cost, w = self.w)
       conv = np.abs(prev_energy - energy)
       
       
       KP_callback_energies[0,i] = prev_energy
       
       
       if energy < low_energy:
           print('Energy lowered, Actual low energy = ', energy)
           low_energy = energy
           param_low_energy = self.params
           
           
       if i%1 == 0:
           print('iteration = ', i)
           print('conv = ', conv)
           print('energy = ', energy)
           
           
       if(conv<= self.conv_tol):
           break
           
           
   print("optimization converged after ", i , "cycles1")
   
   if energy > low_energy:
       self.params = param_low_energy
       print('Energy non_converged after maximum iterations... ')
       
       
   energy_optimized = np.zeros(self.num_excited + 1)
   for exc in range(self.num_excited+1):
       energy_optimized[exc] = self.single_cost(self.params, state_idx = exc)
       
       
   return energy_optimized, i, KP_callback_energies


@timing
def adaptive_optimizer(self,params, optm = 'Adam', opt_rate= 0.1, conv_tol = 1e-4):
 self.params = params
 opt = self.optimizers(optm, opt_rate = opt_rate)
 
 costs = []
 
 self.conv_tol_local = 1e-2
 conv = 10
 
 
 KP_callback_energies = []
 en = np.zeros(self.n_excited+1)
 prev = 1e3
 for i in range(self.max_iterations):
     self.params,prev_energy = opt.step_and_cost(self.total_cost, self.params, single_cost= self.single_cost, w= self.w)
     energy = self.total_cost(self.params, single_cost = self.single_cost, w= self.w)
     
     
     KP_callback_energies.append(energy)
     
     if conv > self.conv_tol_local:
         conv = np.abs(prev_energy = energy)
         prev = energy
     elif  (self.conv_tol_local > self.conv_tol and conv <= self.conv_tol_local):
         opt_rate = opt_rate/2
         self.conv_tol_local = self.conv_tol_local/10
         opt = self.optimizers(optm,opt_rate = opt_rate)
         conv = np.abs(prev_energy - energy)
         prev = energy
         
     elif self.conv_tol_local<= self.conv_tol and conv <= self.conv_tol:
         for exc in range (self.n_excited +1):
             en[exc] = self.single_cost(self.params, state_idx = exc)
             
             
     if i%1 ==0:
         print('iteration', i)
         print('conv=', conv)
         print('energy', energy)
         print('step_size= ', opt_rate)
         print('conv_tol_local = ', self.conv_tol_local)
         
         
     print("optimization converged after ", i, "cycles1")
     print("optimized energies ", en)
     return en, i, KP_callback_energies
 
def optimizers(self, optm, opt_rate, eps=1e-8):
    if optm == 'Adam':
        opt = qml.AdamOptimizer(stepsize=opt_rate, eps=eps)
    elif optm == 'Adagrad':
        opt = qml.AdagradOptimizer(stepsize=opt_rate, eps=eps)
    
    else:
        raise ValueError("Unsupported optimizer: {}".format(optm))
    return opt

if name==‘main’:
num_layers = 5 # number of entangling layers of the ansatz
num_qubits = 2 # number of qubits
point_path = 1 # number of points in Brillouin Zone path
num_excited = num_qubits**2 - 1

vqe = SSVQE(index=0, num_qubits=num_qubits, num_excited=num_excited, npoints_path=1, machine="PennyLane_statevector")
params = np.random.uniform(low=0, high=2*np.pi, size=(num_layers, num_qubits, 3), requires_grad=True) 

print('params', params)

res = vqe.run(params, max_iterations=2000)

Can you debug this code? Because it is showing same error again

TypeError: Grad only applies to real scalar-output functions. Try jacobian, elementwise_grad or holomorphic_grad.

Hi @Kaushik,

I’m sorry if my message was confusing. I didn’t mean to say that you should roll back the version of PennyLane. You should always try to use the latest version which in this case is v0.35.1.

My suggestion is that you keep it as close as possible to the original code here since it runs properly with just removing the line single_cost = qml.ExpvalCost(...) and adding a qnode for single_cost:

@qml.qnode(dev)
def single_cost(params, state_idx=0):
  ansatz(params,wires=range(num_qubits),state_idx=state_idx)
  return qml.expval(H)

If you want to make any additional changes I recommend that you make them one by one and specify exactly what you changed because otherwise it’s very hard to know. For your last error though it’s clear that you’re optimizing something that is not a scalar so this needs to change.

My recommendation would be to go back to PennyLane version 0.35.1, go back to the original code here and change only single_cost. Then if you need to make any changes make them one by one and noting exactly what you changed. Then it will be easier to debug.

I hope this helps!

1 Like

How can I solve this error

AttributeError: ‘ExpectationMP’ object has no attribute ‘get’.

run method contains this

results = {
‘energy_optimized’: energy_optimized,
‘param_optimized’: params,
‘all_energies’: energies_during_opt,
‘number_of_cycles’: ind,
‘convergence_tolerance’: self.conv_tol
}

Later I used

if name==‘main’:
num_layers = 5 # number of entangling layers of the ansatz
num_qubits = 2 # number of qubits
point_path = 1 # number of points in Brillouin Zone path
num_excited = num_qubits**2 - 1
params = np.random.uniform(low =0, high=2*np.pi, size=(num_layers, num_qubits,3))

for i in range(point_path):
VQE = SSVQE(index = i, verbose = 0, num_qubits= num_qubits,
num_excited = num_excited, npoints_path=point_path, machine = “PennyLane_statevector”,
num_layers = num_layers)
results = VQE.run(params, max_iterations = 2000,
conv_tol = 1e-4, optimizer = ‘Adam’, n_excited = num_excited, opt_rate = 0.01,
method = ‘simple’)

params = results.get(params)

import pandas as pd
import scipy as scp

from pennylane import numpy as np
import matplotlib.pyplot as plt
from math import pi

import os
os.environ[“OMP_NUM_THREADS”] = “6”
from pennylane import numpy as np
import pennylane as qml
from pennylane.templates import RandomLayers
from pennylane import broadcast
from pennylane import expval, var, device

from mitiq.zne.scaling import fold_global
from mitiq.zne.inference import RichardsonFactory
from mitiq.zne.scaling import fold_gates_at_random as folding
from mitiq.zne.inference import AdaExpFactory
from pennylane.transforms import mitigate_with_zne
from mitiq.zne import execute_with_zne
from mitiq.zne.scaling import fold_gates_at_random as folding
from qiskit.providers.fake_provider import FakeLima
from qiskit.providers.aer.noise import NoiseModel

from ase.build import bulk
from ase.lattice import FCC
from pennylane import numpy as np
from qiskit.providers.fake_provider import FakeLima
from multiprocessing import pool

from functools import wraps
from time import time

from qiskit import Aer
from optimparallel import minimize_parallel
from qiskit import IBMQ

class KP:
def init(self, ep0=1.5292, delta=0.340, a=5.653, Ep=22.71, verbose=1, npoints_path=15):

    self.RY =1
    self.ep0= 1.5292
    self.delta = 0.341
    self.a=a
    self.verbose = verbose
    self.npoints_path = npoints_path
    self.Ep = 22.71
    self.gamma1 = 7.03
    self.gamma2 = 2.33
    self.gamma3 = 3.03
    self.mass = 0.0665
    self.P = 9.75
    
def lattice(self,atom = 'Si',structure = 'diamond', path = 'XGL'):
    self.atom =atom
    self.structure = structure
    self.pathPoints = path
    
    struc = bulk(self.atom,self.structure, a= self.a)
    self.lat = struc.cell.get_bravais_lattice()
    
    self.path = struc.cell.bandpath(self.pathPoints, npoints=self.npoints_path)
    pt = FCC(self.a).bandpath(self.pathPoints, npoints = self.npoints_path)
   
    self.p_axis = pt.get_linear_kpoint_axis(eps = 1e-5)[0]
    self.p_labels_vert = pt.get_linear_kpoint_axis(eps = 1e-5)[1]
    self.p_labels_stg = pt.get_linear_kpoint_axis(eps = 1e-5)[2]
    
    if self.verbose == 0:
        print('Symmetry points =  ',list(self.lat.get_special_points()))
        print('k-vector-path = ', self.p_axis)
        print('Path vertices = ', self.p_labels_vert)
        print('Path labels = ', self.p_labels_stg)

    #creating a dataframe to stroe the path
    self.data = pd.DataFrame(self.path.kpts,columns=['kx','ky','kz'])
    self.data['k'] = np.sqrt((self.data['kx'])**2+(self.data['kx'])**2+(self.data['kx'])**2)
   


def Hamilton_GaAs(self, index = 0, nqbits=3, custom_lattice = False)->np.array:
    if not custom_lattice:
        self.lattice()
    else:
        print("define a custom lattice")
    
    
    k = self.data.iloc[index].k
    kx = self.data.iloc[index].kx
    ky = self.data.iloc[index].ky
    kz = self.data.iloc[index].kz

    kmais = kx + 1j * ky
    kmenos = kx - 1j * ky

    e = 1 / self.mass - (self.Ep/3) * ((2 / self.ep0) + 1 / (self.ep0 + self.delta))
    P = 9.75
    
    Q = - ((self.gamma1 + self.gamma2)*(kx**2 - ky**2) - (self.gamma1 - 2*self.gamma2)*kz**2 )
    R = -np.sqrt(3)*(self.gamma2*(kx**2 - ky**2) + 2*1j*self.gamma3*kx*ky)
    Ec = self.ep0 + e*(kx**2 + ky**2 + kz**2)
    Pz = self.P * kz

    T = - ((self.gamma1 - self.gamma2)*(kx**2 + ky**2) + (self.gamma1 + 2*self.gamma2)*kz**2 )
    S = 1j * (2*np.sqrt(3) * self.gamma3 * kz * kmenos)
    Pmais = self.P * kmais / np.sqrt(2)
    Pmenos = self.P * kmenos / np.sqrt(2)

    H = np.zeros((4,4), dtype=np.complex64)               
    
    H[0,0] = T/2
    H[0,1] = - S
    H[0,2] = - 1j * (T-Q) / np.sqrt(2)
    H[0,3] = - 1j * np.sqrt(2/3) * Pz
    H[1,1] = Q/2
    H[1,2] = -1j * np.conjugate(S) / np.sqrt(2)
    H[1,3] = - Pmais

    H[2,2] = ((Q+T)/2 - self.delta) / 2
    H[2,3] = -Pz  / np.sqrt(3)

    H[3,3] = Ec/2

    self.H = H + np.transpose(np.conjugate(H))
    return self.H[:2**nqbits,:2**nqbits]

class SSVQE:

def __init__(self, index=0, ep0=1.5292, delta=0.752, a=5.653, num_qubits=2, verbose=1, npoints_path=15, machine=None, num_layers=2, num_excited=0):

    
    
    self.time = []
    self.num_qubits= num_qubits
    self.index=index
    self.verbose=verbose
    self.npoints_path= npoints_path
    self.ep0=ep0
    self.delta=delta
    self.a=a
    self.HKP= KP(ep0=self.ep0, delta=self.delta, a=self.a, verbose=self.verbose, npoints_path= self.npoints_path)
    self.HH = self.HKP.Hamilton_GaAs(index=self.index,nqbits =self.num_qubits)
    self.data = self.HKP.data
    self.machine= machine
    self.num_layers= num_layers
    self.num_excited= num_excited
    
    
    
    if self.machine == "PennyLane_statevector":
        self.dev = qml.device("default.qubit", wires = self.num_qubits)
    elif self.machine == "PennyLane_simulator":
        self.dev = qml.device("default.mixed", wires = self.num_qubits, shots= 1024)
    elif self.machine == "qasm_Statevector":
        self.dev = qml.device('qiskit.aer', wires=self.num_qubits, backened='aer_simulator_Statevector')
        
        
    if self.verbose ==1:
        print('Hamiltonian:')
        print(self.HH)
        print('Number of Qubits:', self.num_qubits)
        print('Running on ', machine)
        self.epoch2print =50
    elif self.verbose == 0:
        self.epoch2print = 200
    coeffs, obs_list = qml.pauli.conversion._generalized_pauli_decompose(self.HH)
    
    
    obs_groupings = qml.pauli.group_observables(observables=obs_list, grouping_type="qwc", method="rlf")
    print("Number of required measurements after optimization", len(obs_groupings))
    
    
    H = qml.Hamiltonian(coeffs, obs_list)
    

def single_cost(self,params, state_idx=0):
    self.ansatz(params,wires=range(num_qubits),state_idx=state_idx)
    coeffs, obs_list = qml.pauli.conversion._generalized_pauli_decompose(self.HH)
    
    
    obs_groupings = qml.pauli.group_observables(observables=obs_list, grouping_type="qwc", method="rlf")
    H = qml.Hamiltonian(coeffs, obs_list)
    return qml.expval(H)
    
    
        
        
def states(self, nq=None)->list:
    if not nq:
        nq = self.num_qubits
    st = []
    for i in range(2 ** nq):
        formStr = '0' + repr(nq) + 'b'
        st.append(format(i, formStr))
    return st


def ansatz(self, params, wires, state_idx=0)-> None:
    state = self.states(nq =self.num_qubits)
    
    for ind_qb, qb in enumerate(list(state[state_idx])):
        if qb =='1':
            qml.PauliX(wires=wires[ind_qb])
            
            
    qml.templates.StronglyEntanglingLayers(params, wires = range(self.num_qubits))
    

    
    
def total_cost(self,params, **kwargs):
    single_cost = kwargs.get('single_cost')
    w = kwargs.get('w')
    cost = 0
    for state_idx in range(2**self.num_qubits):
        cost +=w[state_idx]*single_cost(params, state_idx=state_idx)
    return cost


def run(self, params, max_iterations =1000, conv_tol = 1e-5, n_excited = 1, optimizer = 'Adam', opt_rate = 0.1,method= 'simple',processes=None):
   self.n_excited = n_excited
   self.max_iterations = max_iterations
   self.conv_tol = conv_tol
   self.params = params
   
   coeffs, obs_list = qml.pauli.conversion._generalized_pauli_decompose(self.HH)
   
   
   obs_groupings = qml.pauli.group_observables(observables=obs_list, grouping_type="qwc", method="rlf")
   print("Number of required measurements after optimization", len(obs_groupings))
   
   
   H = qml.Hamiltonian(coeffs, obs_list)
   
   
   
   eigen,_ = np.linalg.eigh(self.HH)
   energies = np.zeros(2)
   
   
   if self.machine == "PennyLane_statevector":
       self.dev = qml.device("default.qubit", wires = self.num_qubits)
   elif self.machine == "PennyLane_simulator":
       self.dev = qml.device("default.mixed", wires = self.num_qubits, shots= 1024)
   elif self.machine == "qasm_Statevector":
       self.dev = qml.device('qiskit.aer', wires=self.num_qubits, backened='aer_simulator_Statevector')
       
       
       
   
   
   
   
   
   
   
  
   
   
   
   self.w = np.arange(2**self.num_qubits, 0, -1)
   
   if method == "simple":
        energy_optimized, ind, energies_during_opt = self.optimize(
         params,optm = optimizer, opt_rate= opt_rate, conv_tol = self.conv_tol)
   
   
   results = {
    'energy_optimized': energy_optimized,
    'param_optimized': params,
    'all_energies': energies_during_opt,
    'number_of_cycles': ind,
    'convergence_tolerance': self.conv_tol
}
    
       
   return results



def timing(f):
    @wraps(f)
    def wrap(self,*args,**kw):
        ts=time()
        result = f(self,*args,**kw)
        te = time()
        dt = te-ts
        print('function_time'%(f.__name__,args,kw,te-ts))
        self.time.append({'seconds': dt})
        return result
    return wrap


def optimize_conver(self,params,optm='Adam', opt_rate = 0.1, conv_tol = 1e-3):
   self.params = params
   opt = self.optimizers(optm, opt_rate= opt_rate)
   costs = []
   
   conv = np.ones(self.n_excited +1)
   
   KP_callback_energies = np.zeros(self.n_excited+1,self.max_iterations)
   
   prev = np.ones(self.n_excited+1)* 1e3
   for i in range(self.max_iterations):
       self.params,prev_energy = opt.step_and_cost(
       self.total_cost,self.params,single_cost = self.single_cost, w= self.w)
       energy = self.total_cost(self.params,single_cost= self.single_cost, w= self.w)
       
       
       for exc in range(self.n_excited+1):
           if conv[exc] == self.conv_tol:
               en = self.single_cost(self.params, state_idx = exc)
               conv[exc] = np.abs(en-prev[exc])
               prev[exc] = en
               
               
           KP_callback_energies[exc, i] = en
           
           
       if i%1==0:
           print('iteration = ', i)
           print('conv = ', conv)
           print('energy = ', prev)
           
           
       if np.all(conv = self.conv_tol):
           break
           
   print("optimization convergence after ",i,"cycles1")
   energy_optimized = prev
   
   return energy_optimized, i, KP_callback_energies

@timing
def optimize(self,params,optm = 'Adam', opt_rate = 0.1, conv_tol = 1e-3):
   self.params = params
   opt = self.optimizers(optm,opt_rate)
   costs = []
   
   conv = 10
   KP_callback_energies = np.zeros((self.n_excited+1,self.max_iterations))
   low_energy = 1e3
   param_low_energy = params
   
   prev = 1e3
   for i in range(self.max_iterations):
       self.params,prev_energy = opt.step_and_cost(self.total_cost, self.params, single_cost = self.single_cost, w= self.w)
       energy = self.total_cost(self.params, single_cost = self.single_cost, w = self.w)
       conv = np.abs(prev_energy - energy)
       
       
       KP_callback_energies[0,i] = prev_energy
       
       
       if energy < low_energy:
           print('Energy lowered, Actual low energy = ', energy)
           low_energy = energy
           param_low_energy = self.params
           
           
       if i%1 == 0:
           print('iteration = ', i)
           print('conv = ', conv)
           print('energy = ', energy)
           
           
       if(conv<= self.conv_tol):
           break
           
           
   print("optimization converged after ", i , "cycles1")
   
   if energy > low_energy:
       self.params = param_low_energy
       print('Energy non_converged after maximum iterations... ')
       
       
   energy_optimized = np.zeros(self.num_excited + 1)
   for exc in range(self.num_excited+1):
       energy_optimized[exc] = self.single_cost(self.params, state_idx = exc)
       
       
   return energy_optimized, i, KP_callback_energies




@timing
def adaptive_optimizer(self,params, optm = 'Adam', opt_rate= 0.1, conv_tol = 1e-4):
 self.params = params
 opt = self.optimizers(optm, opt_rate = opt_rate)
 
 costs = []
 
 self.conv_tol_local = 1e-2
 conv = 10
 
 
 KP_callback_energies = []
 en = np.zeros(self.n_excited+1)
 prev = 1e3
 for i in range(self.max_iterations):
     self.params,prev_energy = opt.step_and_cost(self.total_cost, self.params, single_cost= self.single_cost, w= self.w)
     energy = self.total_cost(self.params, single_cost = self.single_cost, w= self.w)
     
     
     KP_callback_energies.append(energy)
     
     if conv > self.conv_tol_local:
         conv = np.abs(prev_energy = energy)
         prev = energy
     elif  (self.conv_tol_local > self.conv_tol and conv <= self.conv_tol_local):
         opt_rate = opt_rate/2
         self.conv_tol_local = self.conv_tol_local/10
         opt = self.optimizers(optm,opt_rate = opt_rate)
         conv = np.abs(prev_energy - energy)
         prev = energy
         
     elif self.conv_tol_local<= self.conv_tol and conv <= self.conv_tol:
         for exc in range (self.n_excited +1):
             en[exc] = self.single_cost(self.params, state_idx = exc)
             
             
     if i%1 ==0:
         print('iteration', i)
         print('conv=', conv)
         print('energy', energy)
         print('step_size= ', opt_rate)
         print('conv_tol_local = ', self.conv_tol_local)
         
         
     print("optimization converged after ", i, "cycles1")
     print("optimized energies ", en)
     return en, i, KP_callback_energies
 
def optimizers(self, optm, opt_rate, eps=1e-8):
    if optm == 'Adam':
        opt = qml.AdamOptimizer(stepsize=opt_rate, eps=eps)
    elif optm == 'Adagrad':
        opt = qml.AdagradOptimizer(stepsize=opt_rate, eps=eps)
    
    else:
        raise ValueError("Unsupported optimizer: {}".format(optm))
    return opt

if name==‘main’:
num_layers = 5 # number of entangling layers of the ansatz
num_qubits = 2 # number of qubits
point_path = 1 # number of points in Brillouin Zone path
num_excited = num_qubits**2 - 1
params = np.random.uniform(low =0, high=2*np.pi, size=(num_layers, num_qubits,3))

for i in range(point_path):
VQE = SSVQE(index = i, verbose = 0, num_qubits= num_qubits,
num_excited = num_excited, npoints_path=point_path, machine = “PennyLane_statevector”,
num_layers = num_layers)
results = VQE.run(params, max_iterations = 2000,
conv_tol = 1e-4, optimizer = ‘Adam’, n_excited = num_excited, opt_rate = 0.01,
method = ‘simple’)
print(f"Results for point {i}: {results}")

In this program I took out the single_cost outside the run function
But it is showing error

File c:\users\kaushik das\untitled2.py:222 in total_cost
cost +=w[state_idx]*single_cost(params, state_idx=state_idx)

File ~\anaconda3\Lib\site-packages\pennylane\numpy\tensor.py:155 in array_ufunc
res = super().array_ufunc(ufunc, method, *args, **kwargs)

TypeError: unsupported operand type(s) for *: ‘int’ and ‘ExpectationMP’

Hi @Kaushik, thank you for your question.

Unfortunately your code is too big for me to be able to identify the issue.

Note that ExpectationMP is the return type for qml.expval() so the errors you’re getting indicate that you’re doing some unsupported processing with qml.expval().

In this code single_cost is returning ExpectationMP type value,

cost +=w[state_idx]*single_cost(params, state_idx=state_idx)

In this line we are multiplying an integer with ExpectationMP . w[state_idx] is returning int value. So it is showing error

TypeError:unsupported operand type(s) for *: ‘int’ and ‘ExpectationMP’

How can I solve this problem?