Skip to main content

Pauli string organizer for dense operators.

Project description

The psfam package is a python package which organizes the complete set of pauli strings of any size into commuting families for VQE, finding a unitary matrix from clifford operators which diagonalizes all of the strings, and implementing this unitary matrix on a qiskit circuit.

psfam can be installed with

pip install psfam

Usage

Below are instructions on how to use the Psfam package. It will show the process of using a PauliOrganizer object to partition strings, then calculating an expectation value on a qiskit simulator.

You'll need numpy and qiskit, so lets import those:

from psfam.pauli_organizer import *
import numpy as np
from qiskit import *
from qiskit.circuit.library import EfficientSU2

Pick the number of qubits, and assign this to $m$. Pauli_organizer takes only the number of qubits as an argument. In its constructor, it partitions all the families. We can look at the properties of the object using properties(). This will tell us what $A$ matrix was used to generate all of the families.

m=2
PO = PauliOrganizer(m)

print(PO.properties())

print()

for fam in PO.get_families():
    print(fam)
Qubits: 2
Generating Matrix:
[1, 1]
[1, 0]

XZ,YX,ZY
XY,ZX,YZ
IY,YI,YY
IX,XI,XX
II,IZ,ZI,ZZ

The get_families() function returns a list of all of the $2^m + 1$ family objects. The final 2 objects will be the x and z families.

For normal families, there will be a permutation which generates the family, and the generating matrix for that family $A^i$ can be printed from that permutation. The following methods can be used to get the individual properties. Printing a family will show the strings in that family

The coefficients of the family will tell you how to calculate the measurement at the end. These would be the coefficients $\alpha_{i,j}$ of the contribution of this family to the expectation value of the Hamiltonian:

$$ \langle H \rangle = \sum_i \alpha_{i,j} |\langle \psi | U_i | \chi_j \rangle |^2 $$

Since we have not entered the decomposition of the Hamiltonian, these can't be calculated yet

fam = PO.get_families()[0]

print(fam)
print(fam.get_permutation())
print(fam.get_generating_matrix())
print(fam.get_coefficients())
XZ,YX,ZY
[2, 3, 1]
[[1, 0], [1, 1]]
unassigned

This information can also be accessed using properties()

print(fam.properties())
Qubits: 2
Permutation:[2, 3, 1]
Coefficients: unassigned
Generating Matrix:
[1, 0]
[1, 1]

This part can be skipped if you wish to calculate your coefficients differently. Suppose we have decomposed our Hamiltonian into pauli strings. This function I wrote to simulate this. It generates a dictionary with the decomposition of the hamiltonian into each Pauli string. $H = \sum \beta_i P_i$, and the dictionary is ${ P_i : \beta_i }$

def gen_random_pauli_dict(m):
    pauli_dict = dict()
    cp = ['I']*m
    coords = ([0]*m,[0]*m)
    pauli_dict["".join(cp)] = np.random.random()
    for i in range(4 ** m):
        coords = increment_coords(coords,m - 1)
        cp = increment_string(cp,m - 1)
        pauli_dict["".join(cp)] = np.random.random()
    return pauli_dict

Hamiltonian_decomp = gen_random_pauli_dict(m)

Use the input_pauli_decomps() function to input this into the Hamiltonian. Then, the calc_coefficients() function calculates all the coefficients of the families, and returns the set of families for convenience. Now, when we read the properties of the family, the coefficients are calculated:

PO.input_pauli_decomps(Hamiltonian_decomp)
f = PO.calc_coefficients()
fam1 = f[0]
print(fam1.properties())
Qubits: 2
Permutation:[2, 3, 1]
Coefficients: [-1.1435602789371138, 0.7861666705463014, 0.5364746867002518, -0.1790810783094393]
Generating Matrix:
[1, 0]
[1, 1]

Now lets make a sample measurement.

The family object has a method apply_to_circuit() which automatically applies the correct unitary to the circuit. We will create a circuit which has a variational form, a unitary matrix, and a measurement at the end.

qc = QuantumCircuit(m,m)

ansatz = EfficientSU2(m,su2_gates=['rx', 'y'], reps=1)
for parameter in ansatz.parameters:
    ansatz = ansatz.bind_parameters({parameter: np.random.random()*(2*np.pi)})
qc.compose(ansatz,inplace = True)
fam1.apply_to_circuit(qc)
qc.measure(range(m), range(m))

qc.draw('mpl')

Cirucit diagram

This code is straight from here: https://qiskit.org/documentation/tutorials/circuits/1_getting_started_with_qiskit.html. qiskit has methods to visualize the results.

backend_sim = Aer.get_backend('qasm_simulator')
job_sim = backend_sim.run(transpile(qc, backend_sim), shots=1024)
result_sim = job_sim.result()
counts = result_sim.get_counts(qc)
print(counts)
qiskit.visualization.plot_histogram(counts)
{'11': 933, '00': 44, '01': 24, '10': 23}

Counts histogram

Now that we have this result, we can use the counts of each result to get the probability of getting that result:

$$ P(010) = |\langle 010 | U | \psi \rangle |^2 $$

So we can just multiply these by the corresponding coefficients. The coefficients are in ascending binary order. The measurement for this family is calculated below:

cfs = fam1.get_coefficients()
measurement = 0

for i in range(2**m):
    bi = bin(i)[2:]
    while(len(bi)<m):
        bi = '0' + bi
    if(bi in counts):
        measurement = measurement + counts[bi]*cfs[i]/1024

print(measurement)
0.2523065901195194

Now this is repeated for each family and all of the results are added together

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

psfam-0.0.16.tar.gz (15.9 kB view details)

Uploaded Source

File details

Details for the file psfam-0.0.16.tar.gz.

File metadata

  • Download URL: psfam-0.0.16.tar.gz
  • Upload date:
  • Size: 15.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.10.4

File hashes

Hashes for psfam-0.0.16.tar.gz
Algorithm Hash digest
SHA256 9ad5664309398139464a8ffa96d178c803a59e9f61c122cd9bcdfd0ea648e1bc
MD5 d804c059fe6fea327a75c36c3fef85d2
BLAKE2b-256 d32b5a6a5b6dadcf6b98d1717332c464b404a31c3fef3fb2a07136af041921c9

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page