内容
# metis
**在您的 Mac 上运行量子模拟、优化和采样。正确的算法自行选择。无需 CUDA。无需云服务。无需供应商锁定。**
[](https://github.com/frankiearmijo1234-droid/metis/actions/workflows/ci.yml)
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
[](https://github.com/frankiearmijo1234-droid/metis/actions)
[](https://github.com/frankiearmijo1234-droid/metis#engines)
[](https://github.com/frankiearmijo1234-droid/metis#known-limitations)
---
## 如果您使用 Apple Silicon,并且曾经:
- 运行 `pip install qsim` 并发现 [CUDA 支持在 macOS 上不可用](https://quantumai.google/qsim/install_qsimcirq) — 只好走缓慢的 CPU 路径。
- 花了一个下午 [将 BLAS 绑定到 Accelerate](https://schuckert.medium.com/apple-silicon-m1-for-the-quantum-physicist-4f101ea99cf4) ,只为了让 TeNPy 或 quspin 以半速运行。
- 手动下载旧的 Microsoft.Quantum.Sdk nupkg, [解压为 ZIP](https://www.strathweb.com/2022/07/running-q-and-qdk-on-arm64-mac/) ,并复制原生二进制文件到 `.nuget/packages` 以在 M1 上使用 QDK。
- 盯着一个 unsigned alpha 二进制文件,运行 `xattr -d com.apple.quarantine /Applications/...` 以绕过 Gatekeeper,只是为了使用 *唯一* 的 MLX 原生量子模拟器。
- 在一个项目中同时建立 Qiskit *和* Cirq *和* D-Wave Ocean *和* OR-Tools *和* PennyLane,因为 [没有一个库能处理所有这些](https://medium.com/@adnanmasood/quantum-sundays-27-qubo-inc-selecting-the-right-solver-in-a-nisq-world-0ee797d3f2c3)。
- 想知道选择哪个求解器 — tabu?模拟退火?Gurobi?CPLEX?D-Wave?QAOA? — 并不得不学习五个 API 来了解。
- 看着笔记本电脑的风扇狂转,因为一个 30 量子位的态矢量消耗了 16 GB 的 RAM,然后意识到可以 [使用稳定器模拟器](https://github.com/frankiearmijo1234-droid/metis) 运行 1,000 量子位。
… 那么您就体会到了 metis 所解决的痛苦。
---
## 什么是 metis
metis 是一个用于解决复杂计算问题的 Python 库。您只需将问题交给它。它会从十个引擎中为特定问题选择最佳算法,在您的本地硬件上运行(在 Metal 帮助下使用 MLX 加速),并返回答案,并附有完整的审计 trail,解释为什么选择该算法。
十个引擎。一个 API。一个安装。无需 CUDA。无需云账户。无需许可证服务器。MIT 许可,仅由 Apple 编译器签名。
## 安装
metis 依赖于 [`qmlx`](https://github.com/frankiearmijo1234-droid/qmlx),即 metis 包装的量子引擎。在两者都发布到 PyPI 之前,请从源代码安装:
```bash
# 首先安装 qmlx(状态矢量模拟器 metis 包装)
git clone https://github.com/frankiearmijo1234-droid/qmlx.git
cd qmlx
pip install -e .
cd ..
# 然后安装 metis 本身
git clone https://github.com/frankiearmijo1234-droid/metis.git
cd metis
pip install -e ".[all,dev]" # all = MLX + OR-Tools + Claude Code MCP
```
验证安装:
```bash
pytest # 应该为 200/200
python -m benchmarks.system_test --quick # 应该为 29 通过,0 失败,2 个有文档记录的痛点
```
```python
from metis import default_router, Problem, ProblemKind
router = default_router()
# 一个 1000 量子位的 GHZ 状态。状态矢量模拟器无法触及这一点 — 他们需要 16 个 exabytes 的 RAM。metis 路由到稳定器引擎。
n = 1000
ops = [{"gate": "H", "qubits": [0]}]
for q in range(n - 1):
ops.append({"gate": "CNOT", "qubits": [q, q + 1]})
sol = router.solve(Problem(
kind=ProblemKind.QUANTUM_CIRCUIT,
payload={"n_qubits": n, "ops": ops, "task": "sample",
"task_args": {"n_shots": 5}},
))
print(sol.engine_name) # 'stabilizer'
print(sol.metadata["routing_decision"].reason)
print(list(sol.value["counts"].keys())[0][:50]) # 都是 0 或 1
```
这是在一台 CPU 上以 25 秒运行的 1000 量子位电路。使用 MLX,时间更短。
---
## 为什么存在这个问题
没有一种算法能解决所有难题。
- 10 变量优化需要暴力破解。
- 100 变量 *约束* 优化需要 CP-SAT。
- 5000 变量无约束优化需要模拟退火。
- 20 量子位电路带有任意旋转需要状态矢量模拟器。
- 1000 量子位克利福德电路需要稳定器模拟器。
- 低缠绕度状态下 200 量子位需要 MPS 张量网络。
- 贝叶斯后验需要 MCMC。
- 受挫的自旋玻璃需要并行退火。
大多数“AI 计算”工具迫使您自己选择引擎,然后学习其 API,然后在其中一个引擎不合适时用其他三个库进行平衡。
metis 为您选择。您描述问题。metis 检查大小、结构和约束,然后路由到最合适的引擎。引擎在统一接口后面可互换 - 添加新引擎(您自己的自定义求解器、连接到 D-Wave 等)不会更改调用者的任何内容。
---
## 您从一开始就能得到什么
| 引擎 | 处理 | 获胜时 |
|---|---|---|
| `classical` | 连续优化,小型 QUBO | n ≤ 22(精确答案,毫秒级) |
| `simulated_annealing` | 无约束 QUBO,任意大小 | 大型 n,快速启发式 |
| `simulated_annealing_mlx` | 无约束 QUBO,n ≥ 256 | Apple Silicon 上的大型 n |
| `parallel_tempering` | 无约束 QUBO | 崎岖景观(受挫系统) |
| `qaoa` | 小型 QUBO(≤ 18 量子位) | 混合量子/经典,主动选择 |
| `mcmc` | 连续和二进制采样 | 唯一具有采样能力的引擎 |
| `ortools_cpsat` | QUBO + 线性约束,ILP | 约束问题,精确答案 |
| `qmlx_statevector` | 量子电路,任意门 | 最高 28 量子位,精确 |
| `mps` | 量子电路 | 低缠绕度,n 最高 200,主动选择 |
| `stabilizer` | 克利福德电路 | 最高 10,000+ 量子位 |
十个引擎。一个路由器。一份审计 trail。所有地方都使用相同的 `Problem(kind, payload)`。
---
## 您实际上可以用它解决什么问题
三种问题类型。十个引擎。路由器选择最合适的引擎 - 您用代码描述问题,而不是算法选择。
### 桶 1 — 优化
*"我有很多二进制选择,并希望找到使某个数量最小化的组合。"*
现实示例:
- 投资组合选择(从 N 中选择 K 个资产,以在预算约束下最大化夏普比率)
- 资源分配(将卡车分配到路线以最小化里程)
- 调度(将任务拟合到时间段内,同时尊重优先级)
- 图上的最大割、顶点覆盖、集合覆盖、背包问题
引擎触发:`classical`、`simulated_annealing`、`simulated_annealing_mlx`、`parallel_tempering`、`qaoa`、`ortools_cpsat`
```python
from metis import default_router, Problem, ProblemKind
import numpy as np
# 投资组合:从 8 个资产中选择 3 个,风险调整成本最小化
Q = np.random.default_rng(42).standard_normal((8, 8))
Q = (Q + Q.T) / 2
sol = default_router().solve(Problem(
kind=ProblemKind.OPTIMIZATION,
payload={
"qubo_Q": Q,
"qubo_solve": True,
"linear_constraints": [{"coeffs": [1.0]*8, "lo": 3, "hi": 3}],
},
hints={"size": 8},
))
print(sol.engine_name) # 'ortools_cpsat' — 唯一处理约束的引擎
print(sol.value["x"]) # 具有 3 个 1 的二进制向量
```
### 桶 2 — 采样
*"我有一个概率分布,并希望绘制样本来了解其形状。"*
现实示例:
- 贝叶斯后验推理(使用不确定性估计参数)
- 自旋玻璃探索(映射能量景观)
- 连续变量 MCMC(矩、模式、尾部)
引擎触发:`mcmc`(注册表中唯一具有采样能力的引擎)
```python
from metis import default_router, Problem, ProblemKind
import numpy as np
# 在有限温度下从 20 变量 QUBO 中采样
Q = np.random.default_rng(0).standard_normal((20, 20))
Q = (Q + Q.T) / 2
sol = default_router().solve(Problem(
kind=ProblemKind.SAMPLING,
payload={"qubo_Q": Q, "qubo_sample": True, "T": 0.5, "n_samples": 500},
hints={"n_chains": 4, "burn_in": 1000, "seed": 0},
))
print(sol.value["samples"].shape) # (500, 4, 20) — 500 个样本 × 4 条链 × 20 个变量
print(sol.value["min_energy_seen"]) # 探索到的最低能量
```
### 桶 3 — 量子模拟
*"我有一个量子电路,我想知道它做了什么。"*
现实示例:
- 算法原型设计(Grover、QFT、Deutsch-Jozsa、VQE 热身)
- 大规模稳定器电路(1,000+ 量子位克利福德电路,精确)
- 低缠绕度电路最高 200 量子位(MPS 张量网络)
- 通用门集最高 28 量子位(全状态矢量)
引擎触发:`qmlx_statevector`、`mps`、`stabilizer`
```python
from metis import default_router, Problem, ProblemKind
# 1000 量子位 GHZ 状态。只有稳定器才能处理它。
# 状态矢量需要 2^1000 ≈ 10^301 幅值。
ops = [{"gate": "H", "qubits": [0]}]
for q in range(999):
ops.append({"gate": "CNOT", "qubits": [q, q + 1]})
sol = default_router().solve(Problem(
kind=ProblemKind.QUANTUM_CIRCUIT,
payload={"n_qubits": 1000, "ops": ops, "task": "sample",
"task_args": {"n_shots": 10}},
))
print(sol.engine_name) # 'stabilizer' — 自动选择
# 所有射击都是 1000 个零或 1000 个一,绝不会出现混合比特串。
```
### 为什么路由器很重要
相同的 `Problem(kind, payload)` API 用于所有三个桶。相同的 `Solution` 形状返回。路由器选择引擎,您不需要。当 30 变量 QUBO 路由到 `parallel_tempering` 而不是 `simulated_annealing` 因为 PT 在该大小下的成本估计较低,您不需要知道这一点。当 1000 量子位 GHZ 路由到 `stabilizer` 而不是 `qmlx_statevector` 因为电路仅限克利福德,并且量子位计数超过状态矢量范围时,您不需要知道。
每个路由决策都是可审计的:
```python
sol.metadata["routing_decision"].chosen # 哪个引擎
sol.metadata["routing_decision"].reason # 为什么选择这个
sol.metadata["routing_decision"].rejected # 为什么其他引擎拒绝
```
---
## 样本运行 — 所有引擎演示
```bash
python examples/02_all_engines.py
```
六个不同问题,六个不同引擎自动选择:
_在 Apple Silicon 上使用 `QMLX_BACKEND=numpy` 测量(未安装 MLX);问题 1-2 的墙上时间包括首次调用 Python 模块导入开销。_
```
1. 小型 QUBO (n=8) → classical (547ms, optimal)
2. 约束 QUBO (n=12, hi=5) → ortools_cpsat (624ms, optimal)
3. 大型 QUBO (n=2000) → simulated_annealing (0.39s, heuristic)
4. ILP (resource alloc) → ortools_cpsat (3.7ms, optimal)
5. 量子 + T 门 (n=4) → qmlx_statevector (3.4ms, exact)
6. 1000-qubit GHZ → stabilizer (49.0s, exact)
```
相同的路由器。相同的 API。六个不同的引擎。每个选择都有路由原因可供检查。
---
## 路由工作原理
每个引擎都会回答关于每个问题的两个问题:
1. `can_handle(problem)` — 我有资格吗?
2. `estimate_cost(problem)` — 我需要多长时间?
路由器询问每个引擎,选择符合条件的引擎中成本最低的,并记录每个考虑因素:
```python
sol.metadata["routing_decision"].chosen # 'ortools_cpsat'
sol.metadata["routing_decision"].candidates # [('ortools_cpsat', 0.05)]
sol.metadata["routing_decision"].rejected # [('classical', 'can_handle=False'), ...]
sol.metadata["routing_decision"].reason # 人类可读的解释
```
当某些操作比预期更慢或不同时,您会确切地知道原因。没有魔术。没有猜测。
---
## 使用 Claude Code 驱动
```json
{
"mcpServers": {
"metis": {
"command": "python3",
"args": ["-m", "metis.mcp_server"]
}
}
```
然后在 Claude Code 中:
> "我有 30 只股票,具有这些预期回报率和协方差矩阵。选择一个投资组合,在 12 个位置的基数约束下最大化夏普比率。"
Claude 调用 `solve_qubo` 并带有约束。metis 路由到 OR-Tools(唯一处理线性约束的引擎)。您获得最佳答案并附有路由说明。
> "运行 100-qubit GHZ 状态并采样 1000 测量。"
Claude 调用 `run_quantum_circuit"。metis 路由到稳定器(qmlx 在 28 量子位上限)。您在几秒内获得计数。
MCP 服务器在每个层都具有防御性输入验证。
---
## metis 是诚实的关于以下内容
* **不是量子计算机。** 量子模拟运行在经典硬件上。对于真正的量子执行,请使用他们的 SDK 连接 IBM/IonQ/AWS Braket。
* **不是超级计算机。** metis 让现有的 Apple Silicon 工作效率更高 - 没有神奇的能力提升。
* **无边界。** 稳定器仅处理克利福德电路。状态矢量上限为 28 量子位。 QUBO 求解器上限为 5000 变量。这些是诚实的物理限制,而不是错误。
* **两个已知痛点** 在系统测试中有文档记录。MCMC 没有收敛诊断(R-hat,ESS) - 多峰后验可以静默陷入模式。路由审计轨迹不显示引擎内部状态(FEASIBLE vs OPTIMAL 当 OR-Tools 在时间预算下终止)。两者都是记录的限制而不是隐藏的错误。运行 `python -m benchmarks.system_test`,您将看到它们。
它是什么:一个干净、小的、可扩展的库,让您和 Claude Code 使用它而无需思考。
---
## 测试和基准测试
```bash
pytest # 200 个单元测试,~15s
python -m benchmarks.system_test # 端到端测试,**33s
python -m benchmarks.run --quick # 跨引擎性能,~60s
python -m benchmarks.run --full # 完整扫描,几分钟
```
JSON 输出的基准测试结果,您可以将其与其他硬件进行比较。
---
## 架构
```
metis/
├── metis/
│ ├── types.py # Problem,Solution,引擎协议
│ ├── router.py # 调度器,可选回退
│ ├── engines/
│ │ ├── classical.py
│ │ ├── simulated_annealing.py
│ │ ├── simulated_annealing_mlx.py # MLX 加速 SA
│ │ ├── parallel_tempering.py
│ │ ├── qaoa.py # 混合量子/经典
│ │ ├── mcmc.py # MH + Gibbs 采样
│ │ ├── ortools_cpsat.py # CP-SAT
│ │ ├── stabilizer.py # 1,000+ 量子位克利福德
│ │ ├── quantum_sim.py # qmlx 状态矢量
│ │ └── mps.py # 张量网络模拟器
├── benchmarks/ # 跨引擎性能 + 系统测试
├── tests/ # 200 个单元测试
├── examples/
│ ├── 01_portfolio.py # 投资组合优化示例
│ └── 02_all_engines.py # 所有引擎,一个路由器
└── claude_skill/
└── mcp_server.py # Claude Code 接口
```
---
## 安全
每个输入都经过两次验证层(MCP 服务器 + 引擎)。资源上限可防止通过巨大电路、超大矩阵、十亿次迭代扫描或巨大时间预算进行 DoS 攻击。生产代码中没有 `eval`、`exec`、`pickle`、`subprocess` 或 `shell=True`。针对已知安全漏洞的 21+ 回归测试。
---
## 许可
MIT。您可以使用、分叉和交付。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器