On this tutorial, we current a sophisticated, hands-on tutorial that demonstrates how we use Qrisp to construct and execute non-trivial quantum algorithms. We stroll by core Qrisp abstractions for quantum knowledge, assemble entangled states, after which progressively implement Grover’s search with automated uncomputation, Quantum Section Estimation, and a full QAOA workflow for the MaxCut drawback. Additionally, we give attention to writing expressive, high-level quantum applications whereas letting Qrisp handle circuit building, management logic, and reversibility behind the scenes. Try the FULL CODES right here.
import sys, subprocess, math, random, textwrap, time
def _pip_install(pkgs):
cmd = [sys.executable, "-m", "pip", "install", "-q"] + pkgs
subprocess.check_call(cmd)
print("Putting in dependencies (qrisp, networkx, matplotlib, sympy)...")
_pip_install(["qrisp", "networkx", "matplotlib", "sympy"])
print("✓ Installedn")
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
from qrisp import (
QuantumVariable, QuantumFloat, QuantumChar,
h, z, x, cx, p,
management, QFT, multi_measurement,
auto_uncompute
)
from qrisp.qaoa import (
QAOAProblem, RX_mixer,
create_maxcut_cost_operator, create_maxcut_cl_cost_function
)
from qrisp.grover import diffuserWe start by organising the execution setting and putting in Qrisp together with the minimal scientific stack required to run quantum experiments. We import the core Qrisp primitives that enable us to signify quantum knowledge varieties, gates, and management circulate. We additionally put together the optimization and Grover utilities that may later allow variational algorithms and amplitude amplification. Try the FULL CODES right here.
def banner(title):
print("n" + "="*90)
print(title)
print("="*90)
def topk_probs(prob_dict, okay=10):
gadgets = sorted(prob_dict.gadgets(), key=lambda kv: kv[1], reverse=True)[:k]
return gadgets
def print_topk(prob_dict, okay=10, label="Prime outcomes"):
gadgets = topk_probs(prob_dict, okay=okay)
print(label)
for state, prob in gadgets:
print(f" {state}: {prob:.4f}")
def bitstring_to_partition(bitstring):
left = [i for i, b in enumerate(bitstring) if b == "0"]
proper = [i for i, b in enumerate(bitstring) if b == "1"]
return left, proper
def classical_maxcut_cost(G, bitstring):
s = set(i for i, b in enumerate(bitstring) if b == "0")
price = 0
for u, v in G.edges():
if (u in s) != (v in s):
price += 1
return price
banner("SECTION 1 — Qrisp Core: QuantumVariable, QuantumSession, GHZ State")
def GHZ(qv):
h(qv[0])
for i in vary(1, qv.dimension):
cx(qv[0], qv[i])
qv = QuantumVariable(5)
GHZ(qv)
print("Circuit (QuantumSession):")
print(qv.qs)
print("nState distribution (printing QuantumVariable triggers a measurement-like dict view):")
print(qv)
meas = qv.get_measurement()
print_topk(meas, okay=6, label="nMeasured outcomes (approx.)")
qch = QuantumChar()
h(qch[0])
print("nQuantumChar measurement pattern:")
print_topk(qch.get_measurement(), okay=8)We outline utility features that assist us examine likelihood distributions, interpret bitstrings, and consider classical prices for comparability with quantum outputs. We then assemble a GHZ state to display how Qrisp handles entanglement and circuit composition by high-level abstractions. We additionally showcase typed quantum knowledge utilizing QuantumChar, reinforcing how symbolic quantum values may be manipulated and measured. Try the FULL CODES right here.
banner("SECTION 2 — Grover + auto_uncompute: Resolve x^2 = 0.25 (QuantumFloat oracle)")
@auto_uncompute
def sqrt_oracle(qf):
cond = (qf * qf == 0.25)
z(cond)
qf = QuantumFloat(3, -1, signed=True)
n = qf.dimension
iterations = int(0.25 * math.pi * math.sqrt((2**n) / 2))
print(f"QuantumFloat qubits: {n} | Grover iterations: {iterations}")
h(qf)
for _ in vary(iterations):
sqrt_oracle(qf)
diffuser(qf)
print("nGrover end result distribution (QuantumFloat prints decoded values):")
print(qf)
qf_meas = qf.get_measurement()
print_topk(qf_meas, okay=10, label="nTop measured values (decoded by QuantumFloat):")We implement a Grover oracle utilizing automated uncomputation, permitting us to specific reversible logic with out manually cleansing up intermediate states. We apply amplitude amplification over a QuantumFloat search house to unravel a easy nonlinear equation utilizing quantum search. We lastly examine the ensuing measurement distribution to establish essentially the most possible options produced by Grover’s algorithm. Try the FULL CODES right here.
banner("SECTION 3 — Quantum Section Estimation (QPE): Managed U + inverse QFT")
def QPE(psi: QuantumVariable, U, precision: int):
res = QuantumFloat(precision, -precision, signed=False)
h(res)
for i in vary(precision):
with management(res[i]):
for _ in vary(2**i):
U(psi)
QFT(res, inv=True)
return res
def U_example(psi):
phi_1 = 0.5
phi_2 = 0.125
p(phi_1 * 2 * np.pi, psi[0])
p(phi_2 * 2 * np.pi, psi[1])
psi = QuantumVariable(2)
h(psi)
res = QPE(psi, U_example, precision=3)
print("Joint measurement of (psi, phase_estimate):")
mm = multi_measurement([psi, res])
gadgets = sorted(mm.gadgets(), key=lambda kv: (-kv[1], str(kv[0])))
for (psi_bits, phase_val), prob in gadgets:
print(f" psi={psi_bits} section≈{phase_val} prob={prob:.4f}")We construct an entire Quantum Section Estimation pipeline by combining managed unitary purposes with an inverse Quantum Fourier Rework. We display how section data is encoded right into a quantum register with tunable precision utilizing QuantumFloat. We then collectively measure the system and section registers to interpret the estimated eigenphases. Try the FULL CODES right here.
banner("SECTION 4 — QAOA MaxCut: QAOAProblem.run + greatest minimize visualization")
G = nx.erdos_renyi_graph(6, 0.65, seed=133)
whereas G.number_of_edges() < 5:
G = nx.erdos_renyi_graph(6, 0.65, seed=random.randint(0, 9999))
print(f"Graph: |V|={G.number_of_nodes()} |E|={G.number_of_edges()}")
print("Edges:", listing(G.edges())[:12], "..." if G.number_of_edges() > 12 else "")
qarg = QuantumVariable(G.number_of_nodes())
qaoa_maxcut = QAOAProblem(
cost_operator=create_maxcut_cost_operator(G),
mixer=RX_mixer,
cl_cost_function=create_maxcut_cl_cost_function(G),
)
depth = 3
max_iter = 25
t0 = time.time()
outcomes = qaoa_maxcut.run(qarg, depth=depth, max_iter=max_iter)
t1 = time.time()
print(f"nQAOA completed in {t1 - t0:.2f}s (depth={depth}, max_iter={max_iter})")
print("Returned measurement distribution dimension:", len(outcomes))
cl_cost = create_maxcut_cl_cost_function(G)
print("nTop 8 candidate cuts (bitstring, prob, price):")
top8 = sorted(outcomes.gadgets(), key=lambda kv: kv[1], reverse=True)[:8]
for bitstr, prob in top8:
cost_val = cl_cost({bitstr: 1})
print(f" {bitstr} prob={prob:.4f} cut_edges≈{cost_val}")
best_bitstr = top8[0][0]
best_cost = classical_maxcut_cost(G, best_bitstr)
left, proper = bitstring_to_partition(best_bitstr)
print(f"nMost possible answer: {best_bitstr}")
print(f"Partition 0-side: {left}")
print(f"Partition 1-side: {proper}")
print(f"Classical crossing edges (verified): {best_cost}")
pos = nx.spring_layout(G, seed=42)
node_colors = ["#6929C4" if best_bitstr[i] == "0" else "#20306f" for i in G.nodes()]
plt.determine(figsize=(6.5, 5.2))
nx.draw(
G, pos,
with_labels=True,
node_color=node_colors,
node_size=900,
font_color="white",
edge_color="#CCCCCC",
)
plt.title(f"QAOA MaxCut (greatest bitstring = {best_bitstr}, minimize={best_cost})")
plt.present()
banner("DONE — You now have Grover + QPE + QAOA workflows operating in Qrisp on Colab ✅")
print("Tip: Attempt rising QAOA depth, altering the graph, or swapping mixers (RX/RY/XY) to discover habits.")We formulate the MaxCut drawback as a QAOA occasion utilizing Qrisp’s problem-oriented abstractions and run a hybrid quantum–classical optimization loop. We analyze the returned likelihood distribution to establish high-quality minimize candidates and confirm them with a classical price operate. We conclude by visualizing the perfect minimize, connecting summary quantum outcomes again to an intuitive graph construction.
We conclude by exhibiting how a single, coherent Qrisp workflow permits us to maneuver from low-level quantum state preparation to fashionable variational algorithms utilized in near-term quantum computing. By combining automated uncomputation, managed operations, and problem-oriented abstractions similar to QAOAProblem, we display how we quickly prototype and experiment with superior quantum algorithms. Additionally, this tutorial establishes a robust basis for extending our work towards deeper circuits, different mixers and price features, and extra complicated quantum-classical hybrid experiments.
Try the FULL CODES right here. Additionally, be happy to comply with us on Twitter and don’t overlook to hitch our 100k+ ML SubReddit and Subscribe to our E-newsletter. Wait! are you on telegram? now you’ll be able to be a part of us on telegram as properly.
