跳到正文
原文
Google AI:DEV 作者专属(RSS)· Malcolm Low·· 3 小时前AI 评分33

如何在 Android Termux 上用 Matplotlib 绘制量子图(无需编译 Qiskit)

Drawing Quantum Diagrams with Matplotlib on Android Termux

AI 导读

在 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.py module 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