【免费下载链接】xquadA rust implementation of the Quip Networks quantum virtual machine.项目地址https://gitcode.com/gh_mirrors/xq/xquad点击查看免费下载本文以 xquad 仓库内置的 examples/portfolio_opt 示例为切入点完整讲解如何在 XQuad 工具链中用约束规划 DSLxqcp为「从 N 个候选资产中恰好选出 B 个」的组合优化问题建模、编译并端到端求解。读者将掌握如何用二进制变量表达资产选择、如何通过REDUCE指令把三次风险交互项降阶为 QUBO、如何用EQUALITY施加预算硬约束以及如何选择 CPU/GPU/QPU 求解器后端并验证结果有效性。问题定义与 QUBO 建模思路组合优化示例要解决的核心问题是从 N 个候选资产中恰好选择 B 个资产组成投资组合最大化期望收益同时对高阶三次风险交叉项进行惩罚。从 examples/portfolio_opt/README.md 可以提取出标准的 QUBO 形式化定义输入N 个资产的收益r_i、三次风险交互项(i, j, k, sigma)、预算 B模型N 个二进制变量x_i 1表示选中资产 ix_i 0表示未选中目标函数-sum(r_i * x_i) sum(sigma_ijk * x_i * x_j * x_k)第一项最大化收益通过最小化其负值实现第二项惩罚三个资产之间的相关性风险交互约束预算约束sum(x_i) B使用单位系数 EQUALITY惩罚系数 200这里有一个值得注意的建模哲学目标函数中的第一项是软约束式的偏好收益越高越好但未选中更多收益资产并不会导致非法而预算约束则是硬约束必须恰好选择 B 个违反即为 invalid。在 docs/book/src/cookbook/soft-vs-hard-constraints.md 中portfolio_opt 恰好被用作同一问题里同时承载软硬两类约束的教学案例预算通过apply_equality声明为硬规则风险项则直接写进目标函数、由sigma系数决定其权重。编码策略线性项、三次项降阶与预算等式线性收益项ADDLINE收益项是线性的因此每个资产直接对应一条ADDLINE(i, -r_i)。负号是因为求解器最小化能量而我们要最大化收益。三次风险项REDUCE ADDQUAD 两步降阶三次项sigma * x_i * x_j * x_k不能直接写入二次模型必须先降阶。示例采用 Rosenberg 降阶1975 年的经典 HOBO-to-QUBO 方法分为两步REDUCE(i, j, P_AUX) - w引入辅助变量 w用惩罚项强制w x_i * x_jADDQUAD(w, k, sigma)写入sigma * w * x_k等价于sigma * x_i * x_j * x_k关于 REDUCE 的精确展开spec/xqvm/HLF.md 给出了权威推导。设辅助变量 w 分配在model.size处模型大小因此增长 1展开后写入的项为quad[var_a, var_b] P_aux quad[var_a, w] -2 * P_aux quad[var_b, w] -2 * P_aux linear[w] 3 * P_aux这些项之和当w x_a * x_b时为 0否则 ≥ 1因此求解器总是倾向于选择正确的 w。该展开在 xqvm_py/xqmx.py 的expand_reduce中有直接实现并带有IndexOutOfBoundsvar 越界与check_i64算术溢出检查。辅助变量的索引 w 会被压入栈顶从而支持链式降阶例如四次的x_i * x_j * x_k * x_l可以通过两次连续的REDUCE调用再加ADDQUAD实现。仓库中的 conformance 向量 conformance/vectors/constraints/reduce_chain/program.xqasm 正是对两次链式 REDUCE 的验证其中第二次 REDUCE 直接把第一次产生的 w1 作为 var_a 使用。预算约束EQUALITY预算约束sum(x_i) B的实现方式是先构造两个单位系数的向量——indices 向量依次压入0..num_assetscoeffs 向量全部压入 1——然后调用EQUALITY指令目标值为 B惩罚系数为 200。EQUALITY 的数学展开是P * (sum(a_k * x_k) - b)^2。以 conformance 向量 conformance/vectors/constraints/equality_basic/program.xqasm 为例3 个变量、单位系数、target1、penalty2linear[k] 2 * 1 * (1 - 2) -2 每个 k quad[k, m] 2 * 2 * 1 * 1 4 每一对在生成的 encoder 程序中EQUALITY 指令会被发射到约束段而非目标函数段。这一区分由 xqcp/compiler.py 的_partition_body完成它以顶层块为单位把包含equality等约束动作的块划分到约束区其余块进入目标函数区。这就是 README 中所说「EQUALITY is emitted after all objective (body) actions because it lands in the constraint section」的底层实现。runner.py 源码拆解从数据生成到模型构建示例的完整实现位于 examples/portfolio_opt/runner.py。它由三大部分组成随机数据生成、build_problem模型构建、run端到端流水线。随机数据生成rng random.Random(args.seed) returns [rng.randint(5, 20) for _ in range(args.n)] num_risk max(1, args.n - 2) risk_terms: list[tuple[int, int, int, int]] [] for _ in range(num_risk): i, j, k sorted(rng.sample(range(args.n), 3)) sigma rng.randint(1, 10) risk_terms.append((i, j, k, sigma))每个资产的收益在[5, 20]区间内均匀随机风险项数量为max(1, n - 2)每个风险项随机取 3 个不同的资产下标排序保证i j ksigma在[1, 10]内随机build_problemDSL 建模build_problem是核心建模函数展示了 xqcp DSL 的典型用法def build_problem(n, returns, budget, risk_terms) - Problem: problem Problem(PortfolioOpt) num_assets problem.input(num_assets, typeTypes.Int) returns_in problem.input(returns, typeTypes.Vec) budget_in problem.input(budget, typeTypes.Int) num_risk problem.input(num_risk, typeTypes.Int) risk_in problem.input(risk, typeTypes.Vec) problem.define_model(sizenum_assets, domainDomain.BINARY) # 收益目标最小化 -sum(r_i * x_i) with problem.range(0, num_assets) as i: ri problem.stow(ri, returns_in.get(i)) problem.model.linear[i].add(-ri) # 三次风险项REDUCE 降阶 with problem.range(0, num_risk) as t: offset problem.stow(offset, t * 4) ti problem.stow(ti, risk_in.get(offset)) tj problem.stow(tj, risk_in.get(offset 1)) tk problem.stow(tk, risk_in.get(offset 2)) sigma problem.stow(sigma, risk_in.get(offset 3)) w problem.model.reduce(ti, tj, _P_AUX) problem.model.quadratic[w, tk].add(sigma) # 预算约束sum(x_i) B单位系数 EQUALITY indices problem.vec() coeffs problem.vec() with problem.range(0, num_assets) as i: indices.push(i) coeffs.push(1) problem.model.apply_equality(indices, coeffs, budget_in, 200) # 输出投资组合选择 portfolio problem.output(portfolio, typeTypes.Vec) with problem.range(0, num_assets) as i: portfolio.append(problem.sample.getline(i)) return problem几个值得注意的细节风险项以扁平向量传输risk输入是步长为 4 的扁平向量[i, j, k, sigma, ...]每个风险项占据 4 个连续槽位通过t * 4偏移读取见 runner.py 的 docstring 与实现。Rosenberg 惩罚强度_P_AUX 100模块级常量必须大于所有风险项sigma的最大值以保证 REDUCE 的惩罚项能压过目标项。本示例中sigma上限为 10因此 100 有充分裕量。problem.stow分配寄存器把向量元素读入寄存器以便参与运算。若传入字符串目标名则分配新寄存器若传入RegLoad则复用。模型大小会增长每个风险项引入一个 REDUCE 辅助变量因此最终模型大小从n增长到n num_risk。这与软/硬约束的成本分析一致——soft-vs-hard-constraints.md 明确指出 portfolio_opt 的每个风险项消耗一个辅助变量且与共享同一模型的硬预算约束无关。DSL 方法映射到指令README 中列出的三个 DSL 方法其底层发射逻辑分别位于DSL 方法生成的指令实现位置model.reduce(var_a, var_b, p_aux)REDUCE rmodelSTOWxqcp/symbols.py、xqcp/compiler.pyproblem.vec()VEC rregxqcp/problem.pymodel.apply_equality(indices, coeffs, target, penalty)EQUALITY rmodel rindices rcoeffsxqcp/symbols.py、xqcp/compiler.py从源码看reduce()会先分配一个寄存器用于存放辅助变量索引记录 REDUCE 动作并返回RegLoad供链式调用apply_equality()则记录一个equality动作同时把该动作加入约束列表——这正是约束段划分的依据。六阶段端到端流水线README 描述的流水线分为六个阶段runner.py 的run()函数逐段落实CPxqcp生成随机收益与三次风险交互项、声明二进制变量、通过 REDUCE 降阶风险项、添加预算 EQUALITY 约束Assemble.xqasm文本经xquad.asm汇编为字节码Rust 后端路径在 xquad/vm.py 中通过xqffi.asm.assemble_source完成Encode在选定 XQVM 上运行 encoder产出 XQMX 模型。对应代码vm VM(backendbackend) vm.set_calldata([n, returns, budget, num_risk, flat_risk]) vm.set_output_slots(1) vm.run(programs.encoder) model vm.outputs()[0] assert isinstance(model, XQMX)Sample求解器在模型上运行模拟退火SA/QPU/GPUsolver build_solver(solver_name, seedseed) sample solver.solve(model).sampleVerifyverifier 检查样本是否为二进制、预算约束是否成立、每个 REDUCE 辅助变量是否等于其所代表的乘积然后计算能量vm VM(backendbackend) vm.set_calldata([n, returns, budget, num_risk, flat_risk, model, sample]) vm.set_output_slots(2) vm.run(programs.verifier) outs vm.outputs() energy, valid outs[0], outs[1]Decodedecoder 提取被选中的资产vm VM(backendbackend) vm.set_calldata([sample, n]) vm.set_output_slots(1) vm.run(programs.decoder)problem.compile()返回的 CompiledPrograms 是三个.xqasm程序字符串encoder/verifier/decoder编译完成后还会通过xqffi.verifier.verify_source对每个生成程序做字节码验证若 xqffi 不可用则静默跳过见 xqcp/problem.py。关于 verifier 的机制从 xqcp/compiler.py 可以看到verifier 会重放encoder 的动作流输入、循环、stow、分支、向量构建但丢弃模型变更动作在每个约束点原位替换为对求解器样本的检查其 calldata 是 encoder 的输入按声明顺序后跟 model 和 sample输出槽 0 为能量、槽 1 为有效性标志。这正是run()中第二次 VM 调用的 calldata 布局来源。运行示例与参数详解基本用法uv run python examples/portfolio_opt/runner.py --seed 42 uv run python examples/portfolio_opt/runner.py --n 6 --budget 3 --interpreter rust命令行参数Flag默认值说明--n5候选资产数量--budget2需要选出的资产数量--solverdwave-cpu求解器后端见下节--interpreterpythonXQVM 后端python或rust--seed42随机种子-ostdout将 JSON 结果写入文件参数解析位于 runner.py--interpreter限定为python/rust二选一--solver的可选项直接来自sorted(SOLVERS)即求解器注册表默认值取DEFAULT_SOLVER。输出 JSON 结构运行结果以 JSON 输出默认写 stdout-o可重定向到文件字段包括{ _seed: 42, _note: canonical CI golden, n: 5, budget: 2, returns: [...], risk_terms: [[i, j, k, sigma], ...], portfolio: [0/1, ...], total_return: ..., num_selected: ..., energy: ..., valid: 1 }其中num_selected必须等于budget且valid 1才是合法解。选择求解器后端README 给出了五个求解器选项。它们在 xqsa/registry.py 的SOLVERS注册表中按名称映射到具体类名称硬件安装方式dwave-cpuCPU默认pip install xquaddwave-qpuD-Wave Leap 账户pip install xquad[dwave]cuda-gpuNVIDIA CUDA GPUpip install xquad[cuda]metal-gpuApple SiliconmacOSpip install xquad[metal]quipQuip Network远程矿工环境变量配置pip install xqsa[quip]驱动前置条件可参考 README.md 的 GPU/QPU 支持表CUDA 12.x 驱动、Metal 设备、D-Wave Leap API token、QUIP_RPC_URL与签名器各求解器的参数调优可参考 xqsa/README.md。build_solver的工厂逻辑xqsa/registry.py有几个值得注意的规则seed只转发给可复现的经典模拟退火族dwave-cpu、cuda-gpu、metal-gpuD-Wave QPU 是物理硬件、不接受 seedquip由环境配置驱动、也不接受 seedGPU 求解器构造时使用num_reads200, num_sweeps2000的默认参数重要提示非默认求解器不会复现规范输出不同 RNG/硬件。CI 的example-smoke始终使用dwave-cpu。因此若要复现文档中的规范结果请保持--solver dwave-cpu。规范输出与 CI 冒烟验证README 明确指出example-smoke以--seed 42 --solver dwave-cpu验证两个解释器都产出valid 1且冒烟测试是基于不变量的——它只检查有效性不检查精确输出。这一机制的实现位于 scripts/example-smoke.py。它遍历examples/下所有*/runner.py对每个 runner 分别在python和rust两种解释器下运行检查valid 1for interp in (python, rust): out run_example(runner, interp) valid out.get(valid) energy out.get(energy) if valid ! 1: print(f FAIL ({interp}): valid{valid}, energy{energy})之所以不要求字节级输出一致是因为模拟退火对 BQM 构建顺序敏感——两条路径可能找到不同但同样有效的优化解见 example-smoke.py 的模块 docstring。冒烟测试还要求xqffi.verifier.verify_source必须可导入以保证每个编译出的示例程序确实经过了字节码验证。portfolio_opt 在 examples/manifest.yaml 中被归入 selection-and-packing选择与装箱组hardware: true标记未开启因此它不在硬件后端的 CI 子集内但任何求解器下都要求在两个解释器上通过有效性检查。惩罚强度选择的工程要点从示例中可以提炼出两条对同类建模至关重要的工程经验REDUCE 的P_AUX必须大于相关项系数的最大值。这是 Rosenberg 降阶正确性的前提——只有惩罚项足够强求解器才会优先选择满足w x_a * x_b的辅助变量赋值。示例取 100而sigma随机范围上限为 10留出了 10 倍裕量。若P_AUX过小可能出现 w 不等于乘积却能量更低的作弊解。硬约束的惩罚系数需要足够大以压倒目标项。预算 EQUALITY 的 penalty 取 200。若惩罚过小求解器可能违反预算约束以换取更高收益若过大则需注意数值溢出边界XQVM 对算术溢出有ArithmeticOverflow检查。惩罚强度的通用讨论可参见 docs/book/src/concepts 中的 quadratic-models 相关章节。这两个数值都作为显式常量出现在 runner.py 与apply_equality(..., 200)调用中是模型可复现性的关键组成部分。小结portfolio_opt 示例是理解 XQuad 工具链「一段问题描述 → 三次降阶建模 → 字节码 → 求解 → 验证 → 解码」完整路径的极佳范本。它展示了三个核心能力二进制 QUBO 变量建模define_model(domainDomain.BINARY)、高阶项 Rosenberg 降阶REDUCEADDQUAD模型自动增长、加权等式硬约束EQUALITY并演示了如何通过--solver/--interpreter在 CPU 模拟退火、GPU 与量子退火后端之间切换。读者可以基于build_problem的骨架将同样的模式迁移到带容量约束的选品、特征选择、子集筛选等同类组合优化问题。赞分享【免费下载链接】xquadA rust implementation of the Quip Networks quantum virtual machine.项目地址https://gitcode.com/gh_mirrors/xq/xquad点击查看免费下载相关推荐xquad Vertex Cover 示例深度解析ATLEAST 约束编码与端到端 QUBO 求解管线xquad Vertex Cover 示例深度解析ATLEAST 约束编码与端到端 QUBO 求解管线 本文以 xquad 仓库中 Vertex Coverxquad 投资组合优化示例实战REDUCE 降次与 EQUALITY 约束的完整建模管线xquad 投资组合优化示例实战REDUCE 降次与 EQUALITY 约束的完整建模管线 Portfolio Optimization投资组合优化是 xXQuad Examples 全览14 个端到端 QUBO 建模与求解实例指南XQuad Examples 全览14 个端到端 QUBO 建模与求解实例指南 XQuad 是 Quip Network 量子虚拟机XQVM的 Rust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考