Tensor network simulation method in qml.beta

I have tested tensor network simulation method in qml.beta.

qml.beta — PennyLane 0.15.1 documentation

However, the reult was very different from state vector simulation method (default.qubit).

Here is a very simple example of three qubits GHZ state.

Pennylane version : 0.15.0
Tensornetwork version : 0.3

n_qubits = 3
dev = qml.device("default.tensor", wires=n_qubits, shots=100, representation="exact")
#dev = qml.device("default.qubit", wires=n_qubits, shots=100)

@qml.qnode(dev)
def circuit():
    qml.Hadamard(wires=[0])
    for i in range(0,n_qubits-1):
        qml.CNOT(wires=[i,i+1])
    return [qml.sample(qml.PauliZ(i)) for i in range(n_qubits)]
>>> print(circuit.draw())
 0: ──H──╭C──────┤ Sample[Z] 
 1: ─────╰X──╭C──┤ Sample[Z] 
 2: ─────────╰X──┤ Sample[Z] 

Plot the histogram.

def sample_to_counts(sample):
    n_qubits, n_shots = np.shape(sample)
    sample_bin = (1+sample)/2
    weights = [2**i for i in range(n_qubits)]
    sample_dec = np.average(sample_bin,axis=0,weights=weights)*np.sum(weights) # sum b_n*2^n
    sample_dec = sample_dec.astype('int8')
    u, freq = np.unique(sample_dec, return_counts=True) # count frequency
    counts=dict()
    for i,j in zip(u,freq):
        counts.setdefault(format(i, '0'+str(n_qubits)+'b'),j)
    for i in range (2**n_qubits):
        counts.setdefault(format(i, '0'+str(n_qubits)+'b'),0) # zero-padding
    return counts

counts = sample_to_counts(circuit())

import matplotlib.pyplot as plt
plt.bar(counts.keys(), counts.values());
plt.xlabel('bitstrings');
plt.ylabel('counts');
plt.xticks(rotation=90);

image

The histograms are very different.

Ofcourse, the raw counts are also diffferent.

default.qubit:

array([[-1,  1,  1,  1, -1,  1,  1, -1, -1,  1],
       [-1,  1,  1,  1, -1,  1,  1, -1, -1,  1],
       [-1,  1,  1,  1, -1,  1,  1, -1, -1,  1]], dtype=int64)

tensor

array([[ 1.,  1., -1.,  1.,  1.,  1.,  1., -1., -1.,  1.],
       [ 1.,  1.,  1.,  1., -1.,  1.,  1., -1.,  1., -1.],
       [ 1.,  1.,  1.,  1., -1., -1.,  1., -1.,  1.,  1.]])

How can I understand this?

Additonally, no improvement of processing time was observed altough tensor network was used.

Hi @Kuma-quant!

Thanks for catching this – this looks like a bug in the default.tensor simulator. Specifically, default.tensor is not returning correlated samples as it should (and default.qubit is).

I’ve opened a bug report here: https://github.com/PennyLaneAI/pennylane/issues/1419

1 Like

Thanks a lot!
I am glad to contribute to PennyLane.

sample_bin = (1+sample)/2

sample cannot be an integer or list. Here sample is passed as the output of circuit, which is necessarily either a list or int. How the code gave the correct result or even run? I tried it running but I am unsuccessful.

Hey @Dhawal_Verma, welcome back!

Keep in mind that this thread is from a while ago, and as PennyLane gets updates, things might break. Best to keep track of breaking changes here: Release notes — PennyLane 0.35.1 documentation. Or follow us on Twitter / LinkedIn for announcements!

Looks like default.tensor was removed in v0.19. I updated the code above and it seems to work:

n_qubits = 3
dev = qml.device("default.qubit", wires=n_qubits, shots=100)
#dev = qml.device("default.qubit", wires=n_qubits, shots=100)

@qml.qnode(dev)
def circuit():
    qml.Hadamard(wires=[0])
    for i in range(0,n_qubits-1):
        qml.CNOT(wires=[i,i+1])
    return [qml.sample(qml.PauliZ(i)) for i in range(n_qubits)]
def sample_to_counts(sample):
    n_qubits, n_shots = np.shape(sample)
    sample_bin = (1+np.array(sample))/2
    weights = [2**i for i in range(n_qubits)]
    sample_dec = np.average(sample_bin,axis=0,weights=weights)*np.sum(weights) # sum b_n*2^n
    sample_dec = sample_dec.astype('int8')
    u, freq = np.unique(sample_dec, return_counts=True) # count frequency
    counts=dict()
    for i,j in zip(u,freq):
        counts.setdefault(format(i, '0'+str(n_qubits)+'b'),j)
    for i in range (2**n_qubits):
        counts.setdefault(format(i, '0'+str(n_qubits)+'b'),0) # zero-padding
    return counts

counts = sample_to_counts(circuit())

import matplotlib.pyplot as plt
plt.bar(counts.keys(), counts.values());
plt.xlabel('bitstrings');
plt.ylabel('counts');
plt.xticks(rotation=90);

Let me know if that helps!

1 Like

Yes, it helped. thanks.