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 way of core Qrisp abstractions for quantum knowledge, assemble entangled states, after which progressively implement Grover’s search with automated uncomputation, Quantum Part Estimation, and a full QAOA workflow for the MaxCut downside. Additionally, we concentrate on writing expressive, high-level quantum applications whereas letting Qrisp handle circuit building, management logic, and reversibility behind the scenes. Try the FULL CODES 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 establishing the execution atmosphere 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 circulation. We additionally put together the optimization and Grover utilities that can later allow variational algorithms and amplitude amplification. Try the FULL CODES here.
def banner(title):
print("n" + "="*90)
print(title)
print("="*90)
def topk_probs(prob_dict, ok=10):
gadgets = sorted(prob_dict.gadgets(), key=lambda kv: kv[1], reverse=True)[:k]
return gadgets
def print_topk(prob_dict, ok=10, label="High outcomes"):
gadgets = topk_probs(prob_dict, ok=ok)
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")
value = 0
for u, v in G.edges():
if (u in s) != (v in s):
value += 1
return value
banner("SECTION 1 — Qrisp Core: QuantumVariable, QuantumSession, GHZ State")
def GHZ(qv):
h(qv[0])
for i in vary(1, qv.measurement):
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, ok=6, label="nMeasured outcomes (approx.)")
qch = QuantumChar()
h(qch[0])
print("nQuantumChar measurement pattern:")
print_topk(qch.get_measurement(), ok=8)We outline utility capabilities that assist us examine chance distributions, interpret bitstrings, and consider classical prices for comparability with quantum outputs. We then assemble a GHZ state to exhibit how Qrisp handles entanglement and circuit composition by way of high-level abstractions. We additionally showcase typed quantum knowledge utilizing QuantumChar, reinforcing how symbolic quantum values might be manipulated and measured. Try the FULL CODES 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.measurement
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 consequence distribution (QuantumFloat prints decoded values):")
print(qf)
qf_meas = qf.get_measurement()
print_topk(qf_meas, ok=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 resolve 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 here.
banner("SECTION 3 — Quantum Part 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} part≈{phase_val} prob={prob:.4f}")We construct a whole Quantum Part Estimation pipeline by combining managed unitary purposes with an inverse Quantum Fourier Remodel. We exhibit how part info is encoded right into a quantum register with tunable precision utilizing QuantumFloat. We then collectively measure the system and part registers to interpret the estimated eigenphases. Try the FULL CODES here.
banner("SECTION 4 — QAOA MaxCut: QAOAProblem.run + greatest lower 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 measurement:", len(outcomes))
cl_cost = create_maxcut_cl_cost_function(G)
print("nTop 8 candidate cuts (bitstring, prob, value):")
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 doubtless resolution: {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}, lower={best_cost})")
plt.present()
banner("DONE — You now have Grover + QPE + QAOA workflows working 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 downside as a QAOA occasion utilizing Qrisp’s problem-oriented abstractions and run a hybrid quantum–classical optimization loop. We analyze the returned chance distribution to establish high-quality lower candidates and confirm them with a classical value perform. We conclude by visualizing the most effective lower, 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 trendy variational algorithms utilized in near-term quantum computing. By combining automated uncomputation, managed operations, and problem-oriented abstractions resembling QAOAProblem, we exhibit how we quickly prototype and experiment with superior quantum algorithms. Additionally, this tutorial establishes a powerful basis for extending our work towards deeper circuits, different mixers and price capabilities, and extra complicated quantum-classical hybrid experiments.
Try the FULL CODES here. Additionally, be at liberty to comply with us on Twitter and don’t overlook to affix our 100k+ ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.

