Basic Example¶
This notebook demonstrates the basic usage of qTPU for quantum circuit processing.
[1]:
import numpy as np
from qiskit.circuit.library import TwoLocal
def simple_circuit(n: int):
circuit = TwoLocal(n, ["u"], "rzz", entanglement="linear", reps=2).decompose()
circuit = circuit.assign_parameters(
{param: np.random.rand() * np.pi / 2 for param in circuit.parameters}
)
circuit.measure_all()
return circuit
circuit = simple_circuit(6)
circuit.draw(output="mpl", fold=-1)
/tmp/ipykernel_3436/719864217.py:6: DeprecationWarning: The class ``qiskit.circuit.library.n_local.two_local.TwoLocal`` is deprecated as of Qiskit 2.1. It will be removed in Qiskit 3.0. Use the function qiskit.circuit.library.n_local instead.
circuit = TwoLocal(n, ["u"], "rzz", entanglement="linear", reps=2).decompose()
[1]:
[2]:
import qtpu
# cut the circuit into two halves
cut_circ = qtpu.cut(circuit, num_qubits=circuit.num_qubits // 2)
cut_circ.draw(output="mpl", fold=-1)
[2]:
[3]:
# convert the circuit into a hybrid tensor network
hybrid_tn = qtpu.circuit_to_hybrid_tn(cut_circ)
for i, subcirc in enumerate(hybrid_tn.subcircuits):
print(f"Subcircuit {i}:")
print(subcirc)
print("--------------------")
Subcircuit 0:
┌─────────────────────────┐ ┌──────────────────────────┐»
q_0: ──┤ U(1.2287,1.385,0.04084) ├───■───────────┤ U(0.60597,1.2127,1.2916) ├»
┌┴─────────────────────────┴─┐ │ZZ(1.4867) └──────────────────────────┘»
q_1: ─┤ U(1.4814,0.94981,0.056746) ├─■───────────────────■───────────────────»
┌┴────────────────────────────┤ │ZZ(0.34031) »
q_2: ┤ U(0.88569,0.070235,0.63864) ├─────────────────────■───────────────────»
└─────────────────────────────┘ »
c0: 1/════════════════════════════════════════════════════════════════════════»
»
c1: 1/════════════════════════════════════════════════════════════════════════»
»
c2: 1/════════════════════════════════════════════════════════════════════════»
»
« »
« q_0: ──────────────────────────────────────■─────────────────────»
« ┌───────────────────────────┐ │ZZ(0.084044) »
« q_1: ┤ U(1.0322,0.71946,0.26776) ├─────────■─────────────────────»
« └────────┬──────────┬───────┘┌─────────────────────────────┐»
« q_2: ─────────┤ Vec(i_0) ├────────┤ U(0.041932,0.16983,0.97966) ├»
« └──────────┘ └─────────────────────────────┘»
«c0: 1/════════════════════════════════════════════════════════════»
« »
«c1: 1/════════════════════════════════════════════════════════════»
« »
«c2: 1/════════════════════════════════════════════════════════════»
« »
« ┌────────────────────────┐ ┌─┐»
« q_0: ┤ U(1.11,1.2229,0.86582) ├────────────────────────────┤M├»
« └────────────────────────┘┌──────────────────────────┐└╥┘»
« q_1: ───────■──────────────────┤ U(0.41513,1.2743,1.0967) ├─╫─»
« │ZZ(0.85665) └───────┬──────────┬───────┘ ║ »
« q_2: ───────■──────────────────────────┤ Vec(i_1) ├─────────╫─»
« └──────────┘ ║ »
«c0: 1/═══════════════════════════════════════════════════════╩═»
« 0 »
«c1: 1/═════════════════════════════════════════════════════════»
« »
«c2: 1/═════════════════════════════════════════════════════════»
« »
«
« q_0: ──────────────────────────────────
« ┌─┐
« q_1: ────────────────────────────┤M├───
« ┌──────────────────────────┐└╥┘┌─┐
« q_2: ┤ U(0.33563,1.1255,1.3834) ├─╫─┤M├
« └──────────────────────────┘ ║ └╥┘
«c0: 1/═════════════════════════════╬══╬═
« ║ ║
«c1: 1/═════════════════════════════╩══╬═
« 0 ║
«c2: 1/════════════════════════════════╩═
« 0
--------------------
Subcircuit 1:
┌───────────────────────────┐ ┌──────────┐ »
q_0: ┤ U(1.4973,0.24524,0.90054) ├─┤ Vec(i_0) ├─■───────────»
├───────────────────────────┤ └──────────┘ │ZZ(1.0936) »
q_1: ┤ U(0.60545,0.86304,1.2455) ├──────────────■───────────»
├───────────────────────────┴┐ »
q_2: ┤ U(0.29003,0.28238,0.52261) ├─────────────────────────»
└────────────────────────────┘ »
c3: 1/═══════════════════════════════════════════════════════»
»
c4: 1/═══════════════════════════════════════════════════════»
»
c5: 1/═══════════════════════════════════════════════════════»
»
« ┌───────────────────────────┐ ┌──────────┐ »
« q_0: ┤ U(1.0966,0.88711,0.37093) ├─────────┤ Vec(i_1) ├─────────■────────────»
« └───────────────────────────┘┌────────┴──────────┴───────┐ │ZZ(0.68047) »
« q_1: ─────────■───────────────────┤ U(1.3449,0.53094,0.13781) ├─■────────────»
« │ZZ(0.45398) └┬──────────────────────────┤ »
« q_2: ─────────■────────────────────┤ U(0.36136,0.52691,1.211) ├──────────────»
« └──────────────────────────┘ »
«c3: 1/════════════════════════════════════════════════════════════════════════»
« »
«c4: 1/════════════════════════════════════════════════════════════════════════»
« »
«c5: 1/════════════════════════════════════════════════════════════════════════»
« »
« ┌────────────────────────┐ ┌─┐
« q_0: ┤ U(1.3996,1.0289,1.544) ├─────────────────────────────┤M├──────
« └────────────────────────┘ ┌─────────────────────────┐ └╥┘┌─┐
« q_1: ───────■───────────────────┤ U(0.753,1.3078,0.86319) ├──╫─┤M├───
« │ZZ(0.55997) ┌┴─────────────────────────┴┐ ║ └╥┘┌─┐
« q_2: ───────■──────────────────┤ U(0.91239,0.85419,0.1439) ├─╫──╫─┤M├
« └───────────────────────────┘ ║ ║ └╥┘
«c3: 1/════════════════════════════════════════════════════════╩══╬══╬═
« 0 ║ ║
«c4: 1/═══════════════════════════════════════════════════════════╩══╬═
« 0 ║
«c5: 1/══════════════════════════════════════════════════════════════╩═
« 0
--------------------
[4]:
# evaluate the hybrid tensor network to a classical tensor network
tn = qtpu.evaluate(hybrid_tn)
# contract the classical tensor network
qtpu_res = tn.contract(all, optimize="auto-hq", output_inds=[])
[5]:
from qiskit.circuit import QuantumCircuit
from qiskit_aer.primitives import EstimatorV2
def run_comparison(circuit: QuantumCircuit):
circuit = circuit.remove_final_measurements(inplace=False)
return (
EstimatorV2()
.run([(circuit, "Z" * circuit.num_qubits)], precision=0.0000)
.result()[0]
.data.evs
)
qiskit_res = run_comparison(circuit)
[6]:
print(f"QTPU result: {qtpu_res}")
print(f"Qiskit result: {qiskit_res}")
print(f"Error: {round(abs(qtpu_res - qiskit_res), 5)}")
QTPU result: 0.012268686234791753
Qiskit result: 0.012268686234791597
Error: 0.0