HAMILTONIAN SIMULATION - starter kit

Hi Classiq,
Can you provide a bit of a starter kit for this problem that shows how to read in the H string to qiskit or pennylane? Would be awesome to provide more of a toy example of a trivial approximation with scoring function so we can focus on the actual search problem. (prob get more engagement and submissions that way, e.g. I spent quite a while trying to figure out how to read in the Pauli string format to various frameworks.)
Best,
John

1 Like

John,

We’ll see if we can provide something, but in the meantime, here are examples from Qiskit and PennyLane:

Yuval

Thanks for the quick response Yuval. I had already traversed all those links before posting lol :slight_smile: e.g. either we have to manually go through your provided H string and paste in ^ signs for qiskit , or in pannylane case, jump through a bunch of parsing hoops to get into qml.Hamiltonian object.

No promises, but we’ll see if we can come up with something

For those following, here is a way to load in pennylane. This will read in the Pauli string provided (save in file), and map to needed pennylane format (either direct H definition or based on qml.Hamiltonian() class) in these three files:
qml_coefficients.txt
qml_hamiltonian.txt
qml_observables.txt

import os
import pennylane as qml

this_dir = os.getcwd()+"/"
H_filename = 'LiH_Hamiltonian.txt'
H_filepath =  this_dir + H_filename

def get_pl_qml_gate_string(gate, wire):
    if gate == 'Y':
        return "qml.PauliY("+wire+")"
    elif gate == 'X':
        return "qml.PauliX("+wire+")"
    elif gate == 'Z':
        return "qml.PauliZ("+wire+")"
    elif gate == 'I':
       return "qml.Identity("+wire+")"

qml_hamiltonian = "hamiltonian = "
qml_observables = "hamiltonian_observables = ["
qml_coefficients = "hamiltonian_coefficients = ["
with open(H_filepath) as f:
    
    lines = f.readlines()
    lines = [l for l in lines if l != "\n"]
    line_number = 1
    n_lines = len(lines)
    for line in lines:
        #line = lines[1]
        split_string =  line.split("*")
        c_raw = split_string[0]
        term_raw = split_string[1]
        term_raw = term_raw.replace("\n","").strip()
        
        minus_sign = False
        if "-" in c_raw:
            minus_sign = True
            
        this_coeff = c_raw.replace(" ", "")
        term_split = list(term_raw)
        
        tensor_term = ""
        component_index = 0
        n_gates = len(term_split)
        for term_component in term_split:
            #term_component = term_split[]
            tensor_term += (get_pl_qml_gate_string(term_component, str(component_index)) + ("" if component_index == (n_gates-1) else " @ "))
            component_index += 1
      
            
        qml_hamiltonian += ( (this_coeff + " * " + tensor_term)) # + ("" if line_number == n_lines else "" )
        qml_observables += (tensor_term + ("]" if line_number == n_lines else "," ))
        
        # update so only has minus signs before qml_coefficients
        this_coeff = c_raw.replace("+", "").replace(" ", "")
        qml_coefficients += (this_coeff + ("]" if line_number == n_lines else "," ))
        
        line_number+=1


qml_hamiltonian_file = open(this_dir + "qml_hamiltonian.txt", "w")
qml_hamiltonian_file.write(qml_hamiltonian)
qml_hamiltonian_file.close()

qml_observables_file = open(this_dir + "qml_observables.txt", "w")
qml_observables_file.write(qml_observables)
qml_observables_file.close()

qml_coefficients_file = open(this_dir + "qml_coefficients.txt", "w")
qml_coefficients_file.write(qml_coefficients)
qml_coefficients_file.close()
1 Like

For those trying to load the hamiltonian into qiskit, I’ve written a python script that will format it for you. Just copy paste the hamiltonian given into a txt file and then run the script on it. This will add the necessary ^ and parentheses needed to input the hamiltonian as an operator object, A new file will be generated with the formatted hamiltonian. When you copy paste the formatted hamiltonian in, make sure to add parentheses on each end of it.

2 Likes

I’ve only dabbled in PennyLane before, and wondering if someone can comment on why my error is going up with trotter steps, should go down! This snippet was supposed to be my baseline example to see what can be achieved out-of-the-box approx method and learn more PennyLane.

import os
import pennylane as qml
import numpy as np
from numpy import linalg as linalg

# set the actual_H from the qml_hamiltonian.txt statement 
actual_H = ...
actual_H_matrix = qml.matrix(actual_H)
real_unitary_operator = np.cos(-1)*np.identity(actual_H_matrix.shape[0]) + complex(0,1)*np.sin(-1)*actual_H_matrix

t = 1
n = 10

dev = qml.device('default.qubit', wires=10)

@qml.qnode(dev)
def circuit():
    qml.ApproxTimeEvolution(actual_H, t, n)
    return qml.expval(qml.PauliZ(0)) #needs some kind of exp value of observable to run

circuit()
print(qml.draw(circuit, expansion_strategy='device')())

approximated_circuit = qml.matrix(circuit)()
difference = approximated_circuit - real_unitary_operator

eigenvalues, eigenvectors = linalg.eig(difference)
eigenvalues_real_part = np.real(eigenvalues).tolist()
error_metric = np.max(np.abs(eigenvalues_real_part))
print(error_metric)

#n = 1  -> 1.5394352891879617
#n = 2  -> 1.5394515923677892
#n = 10 -> 1.5394566586296325