如何在 Android Termux 上用 Matplotlib 绘制量子图(无需编译 Qiskit)
Drawing Quantum Diagrams with Matplotlib on Android Termux
在 Android Termux 上可用纯 NumPy 与 Matplotlib 渲染 3D Bloch 球和量子线路图,无需编译完整 Qiskit。
Part of the Quantum Computing: A Complete Learning Path and Developer Workflows on Termux series on malcolmlow.com.
Rendering publication-grade quantum state diagrams directly on an Android device is surprisingly practical. With modern high-resolution mobile screens and terminal environments like Termux, you can generate vector charts, calculate unitary matrix transformations, and export WebP figures on the go.
However, anyone who has tried running pip install qiskit directly on Termux knows the pain: modern Qiskit requires a Rust toolchain (qiskit-aer and core binaries) that often fails to compile on mobile ARM64 or exhausts device memory during wheel builds.
In this guide, we walk through a lean, tested workflow for rendering multi-panel 3D Bloch sphere progression diagrams (tracking Pauli $X$, Hadamard $H$, and Pauli $Z$ gates) on Android Termux using pure NumPy, Matplotlib, and a lightweight standalone loader—no Rust compiler required.
Quick Answer & Key Insight
Can you render 3D Bloch spheres and quantum circuits on Android Termux without building full Qiskit?
Yes, you can generate 3D Bloch spheres on Termux using pure NumPy and Matplotlib. Full Qiskit wheel builds frequently crash mobile devices due to Rust compiler memory exhaustion. By dynamically isolating Qiskit's pure-Python
bloch.pymodule and computing state evolution with 2x2 NumPy matrix operators, you generate identical publication-grade figures in seconds without compiling heavy binaries.
1. What Was Tested
The workflow was verified on an Android ARM64 device running Termux under the standard user environment (no root required):
- Python: 3.12+ (Termux packages)
-
Libraries:
numpy,matplotlib,cwebp(libwebp) - Diagram: 3 rows × 2 columns of 3D Bloch spheres (X, H, and Z gate before/after states)
- Output: High-resolution WebP image under 150 KB with crisp vector typography
2. Install Termux Prerequisites
Open Termux and install Python, Clang, and Matplotlib's system dependencies:
pkg update && pkg upgrade -y
pkg install -y python python-numpy python-matplotlib libpng libjpeg-turbo libwebp
Verify your Matplotlib installation:
python -c "import matplotlib, numpy; print('Matplotlib:', matplotlib.__version__, '| NumPy:', numpy.__version__)"
3. When Full Qiskit Will Not Install
Running pip install qiskit on native Android Termux typically fails with:
error: can't find Rust compiler
...
Building wheel for qiskit-aer (setup.py) ... error: killed
Even if you install the rust package via pkg install rust, compiling Qiskit’s core C/Rust extensions takes 30–45 minutes and often triggers the Linux Out-Of-Memory (OOM) killer on phones with less than 8 GB of RAM.
The Solution: We don't need the entire quantum simulator just to draw a Bloch sphere! Qiskit's Bloch class is written in pure Python using Matplotlib 3D axes (mpl_toolkits.mplot3d). We can download the pinned Qiskit source tarball, extract only qiskit/visualization/bloch.py, and dynamically import it into our script.
4. The Lean Standalone Bloch Loader
Run this one-time command in Termux to download and extract the visualizer module:
mkdir -p $PREFIX/tmp/qiskit-source
cd $PREFIX/tmp/qiskit-source
curl -sL https://github.com/Qiskit/qiskit/archive/refs/tags/2.5.2.tar.gz -o qiskit-2.5.2.tar.gz
tar -xzf qiskit-2.5.2.tar.gz qiskit-2.5.2/qiskit/visualization/bloch.py
Now, create your standalone generator script generate_bloch.py:
from pathlib import Path
import importlib.util
import os
import sys
import types
import matplotlib.pyplot as plt
import numpy as np
# 1. Locate the standalone bloch.py module
version = "2.5.2"
bloch_source = (
Path(os.environ.get("PREFIX", "/data/data/com.termux/files/usr"))
/ "tmp"
/ "qiskit-source"
/ f"qiskit-{version}"
/ "qiskit"
/ "visualization"
/ "bloch.py"
)
# 2. Stub minimal Qiskit visualization namespace
def matplotlib_close_if_inline(_figure):
return None
visualization_pkg = types.ModuleType("qiskit.visualization")
visualization_pkg.__path__ = []
utils_module = types.ModuleType("qiskit.visualization.utils")
utils_module.matplotlib_close_if_inline = matplotlib_close_if_inline
sys.modules["qiskit"] = types.ModuleType("qiskit")
sys.modules["qiskit.visualization"] = visualization_pkg
sys.modules["qiskit.visualization.utils"] = utils_module
# 3. Dynamically import the Bloch class
spec = importlib.util.spec_from_file_location("qiskit.visualization.bloch", bloch_source)
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
spec.loader.exec_module(module)
Bloch = module.Bloch
# 4. Pure NumPy state vector coordinate calculation
def bloch_vector(state):
"""Converts a 2-element complex state vector [alpha, beta] to [x, y, z]."""
alpha, beta = state
overlap = np.conj(alpha) * beta
return [
float(2 * np.real(overlap)),
float(2 * np.imag(overlap)),
float(abs(alpha) ** 2 - abs(beta) ** 2),
]
# 5. Define Unitary Operators
zero = np.array([1, 0], dtype=complex)
x_gate = np.array([[0, 1], [1, 0]], dtype=complex)
h_gate = np.array([[1, 1], [1, -1]], dtype=complex) / np.sqrt(2)
z_gate = np.array([[1, 0], [0, -1]], dtype=complex)
# State progressions
one = x_gate @ zero
plus = h_gate @ zero
minus = z_gate @ plus
# Verify unit normalization
assert np.allclose(one, [0, 1])
assert np.allclose(plus, np.array([1, 1]) / np.sqrt(2))
assert np.allclose(minus, np.array([1, -1]) / np.sqrt(2))
states = [zero, one, zero, plus, plus, minus]
titles = [
r"X input: $|0\rangle$",
r"X output: $|1\rangle$",
r"H input: $|0\rangle$",
r"H output: $|+\rangle$",
r"Z input: $|+\rangle$",
r"Z output: $|-\rangle$",
]
colors = ["#1565C0", "#D32F2F"] * 3
# 6. Render the 3x2 Figure
fig = plt.figure(figsize=(9.6, 12.6), facecolor="white")
for index, (state, title, color) in enumerate(zip(states, titles, colors)):
axis = fig.add_subplot(3, 2, index + 1, projection="3d")
sphere = Bloch(fig=fig, axes=axis, font_size=13)
sphere.xlabel = [r"$|+\rangle$", r"$|-\rangle$"]
sphere.vector_color = [color]
sphere.add_vectors(bloch_vector(state))
sphere.render(title=title)
# Annotate Gate labels along the left margin
gate_labels = [("X gate", 0.805), ("H gate", 0.495), ("Z gate", 0.185)]
for label, y_pos in gate_labels:
fig.text(0.03, y_pos, label, rotation=90, va="center", ha="center", fontweight="bold", fontsize=14)
fig.suptitle("Bloch-Sphere Gate Order: X, then H, then Z", fontsize=18, fontweight="bold", y=0.98)
plt.savefig("bloch_progression.png", dpi=300, bbox_inches="tight")
print("✓ Rendered bloch_progression.png in < 3 seconds!")
5. Convert PNG to High-Performance WebP
Matplotlib outputs high-DPI PNGs, but for web publishing, converting to lossy WebP dramatically reduces file size while retaining crystal-clear vector line rendering:
python generate_bloch.py
cwebp -q 88 bloch_progression.png -o bloch_progression.webp
- Original PNG: ~1.4 MB
- WebP Output: ~128 KB (91% reduction)
6. Problems Encountered and Their Fixes
| Issue Encountered | Root Cause | Working Solution |
|---|---|---|
No module named 'mpl_toolkits.mplot3d' |
Incomplete Matplotlib build | Run pkg install python-matplotlib instead of pip |
| Matplotlib GUI window fails | Termux has no X11/Wayland display by default | Use non-interactive backend: plt.switch_backend('Agg')
|
| Labels truncated at figure boundaries | Complex 3D subplots clipping margins | Use bbox_inches="tight" and adjust figsize
|
| LaTeX math font syntax errors | Missing system LaTeX distribution | Matplotlib's built-in mathtext parser handles $...$ without LaTeX installed |
Frequently Asked Questions
Can I run Qiskit Aer simulations on Termux?
Yes, but running Qiskit Aer reliably on Termux requires using PRoot Debian or Ubuntu (pkg install proot-distro), which provides pre-compiled glibc ARM64 Linux wheels rather than compiling against Android Bionic libc.
Why not just use matplotlib-inline?
matplotlib-inline is designed for interactive Jupyter notebooks. For headless mobile scripting and automation pipelines, using Matplotlib's Agg backend and exporting directly to disk is significantly faster and requires zero server overhead.
Originally published at malcolmlow.com.
来源:Google AI:DEV 作者专属(RSS) · dev.to