OmX 自适应排序优化 Mission 实战:混合排序策略、加权成本评估与沙箱契约解析
【免费下载链接】oh-my-codexOmX - Oh My codeX: Your codex is not alone. Add hooks, agent teams, HUDs, and so much more.项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-codex
本文围绕 OmX(Oh My codeX)仓库中的missions/adaptive-sort-optimization/任务包,深入讲解如何在一个确定性的混合数据分布排序基准上做算法工程优化。你将掌握 OmX autoresearch 任务沙箱(sandbox)的评估契约与安全边界、混合排序(hybrid sort)的调度原理与三个核心阈值参数的作用,以及"以加权比较/移动成本替代墙钟时间"的基准打分机制,并了解如何在保持排序正确性的前提下通过参数调优与轻量启发式提升评估分数。
一、任务定位:这是 OmX 的一次"算法工程"型研究演示
在 OmX 仓库中,missions/adaptive-sort-optimization/是一个面向omx autoresearch流程设计的任务包(pilot mission)。与仓库内其他演示(如 ML 表格分类、噪声高维贝叶斯优化、潜在子空间发现)不同,本任务不是"调模型超参",而是把排序算法策略本身当作被优化的对象:在多个确定的输入分布上,让混合排序策略以更少的加权操作代价完成排序。
任务包由两个文件组成,职责分离清晰:
- mission.md:定义目标——"在多个确定性输入分布上优化自适应排序策略",并明确成功标准(加权成本分数优于当前保留基线、所有基准用例排序正确、策略保持轻量与确定性);
- sandbox.md:定义评估契约与沙箱操作规则——评估器命令、输出格式、保留策略,以及"允许改动/避免改动"的边界。
对应地,被优化的代码与基准位于 playground/adaptive_sort_demo/(含 config.json 与 sort_benchmark.py),而外层的 playground/README.md 将本演示归入"确定性或种子可控评估、小代码足迹、评估器驱动的 keep/discard 循环"这一设计目标之下。
二、沙箱评估契约(sandbox.md)逐条解读
sandbox.md 的核心是一段 YAML front-matter,它直接决定了 autoresearch 流程如何评判每次候选改动:
evaluator: command: python3 scripts/eval-adaptive-sort-optimization.py format: json keep_policy: score_improvement各字段的实际语义如下:
- evaluator.command:评估器的调用命令。它运行一个独立脚本,把基准结果以 JSON 形式输出。注意:仓库内实际的评估器脚本位于 src/scripts/eval/eval-adaptive-sort-optimization.py,实际运行时需要按该路径调用;
- evaluator.format: json:评估器必须以 JSON 作为与上层(autoresearch 监督器)交换结果的格式;
- keep_policy: score_improvement:保留策略为"分数改进"。只有候选改动的评分严格优于当前保留基线时才被采纳,这与 playground/README.md 中"evaluator-driven keep/discard loops"的描述一致——每次迭代的取舍由分数决定,而非人工主观判断。
sandbox 正文则把任务严格收拢在playground/adaptive_sort_demo/范围内,并用两栏列出边界:
允许的改动(Allowed changes)
- hybrid sort 的调度逻辑(hybrid sort dispatch logic)
- 阈值调优(threshold tuning)
- 轻量级确定性启发式(lightweight deterministic heuristics)
- 直接支撑优化目标的小型结构性清理(small structural cleanups that directly support the optimization)
避免的改动(Avoid)
- 与仓库无关的改动(unrelated repository changes)
- 新增依赖(adding new dependencies)
- 仅为了让分数更容易而修改基准用例(changing the benchmark cases only to make the score easier)
最后一句把任务定性为"算法工程任务":保持基准确定性,并在混合数据分布上改进加权成本。这意味着"作弊式"改基准、引入第三方排序库、或顺手重构仓库其他模块,都属于契约外的行为。
三、被优化的基准实现:加权成本模型与四种基础算法
sort_benchmark.py 是整套基准的核心,它不测量墙钟时间,而是用可计数的操作原语模拟排序代价。关键设计如下。
3.1 成本模型:Metrics与Ops
Metrics记录两类操作并给出加权总分:
@dataclass class Metrics: comparisons: int = 0 moves: int = 0 def score(self) -> float: return self.comparisons + 0.35 * self.movesOps封装了所有"触碰数据"的动作:compare(a, b)每次比较计一次comparisons;move(count)按count累加moves。所有排序算法都只能通过Ops访问数据,从而让代价统计做到精确且零墙钟噪声。
这里的权重系数0.35是关键:一次移动的代价只相当于 0.35 次比较。也就是说,在成本函数看来,"多搬几次数据"比"多做几次比较"更便宜——这直接影响了后续策略选择的取舍方向(例如:对接近有序的数据,用移动多但比较少的插入排序可能是划算的)。
3.2 四种基础算法
基准内置了三种子算法,外加一个纯归并排序的基线对照:
insertion_sort:标准插入排序。每轮取key,向前比较并搬移元素,最后落位。对近乎有序输入表现优秀,代价为 O(n) 量级比较 + O(n) 移动;merge_sort:递归归并排序。先切分再合并,合并阶段每次比较后move()一次,剩余片段用move(len(left) - i)等批量记数。它是稳定的 O(n log n) 对照基线;counting_sort:计数排序。ops.move(len(counts))记录初始化计数数组的"成本",遍历填入counts[value - offset] += 1再展开输出。当值域跨度小时近乎线性;baseline_sort:直接转发给merge_sort,用于给整个任务提供"纯归并排序"的参照分数。
3.3 确定性:没有随机源
基准中的每个用例都由算术递推式生成(如((i * 37 + 11) % 101)),没有任何随机种子或采样步骤;Ops统计与Metrics.score()也都是纯函数计算。因此同一份 config 在任何机器、任何时间运行都会得到完全相同的分数——这正是 sandbox 强调"保持基准确定性"的底气,也让score_improvement保留策略具备可复现性。
四、混合排序调度器:hybrid_sort与三个阈值参数
hybrid_sort是任务真正要优化的对象,它根据输入特征在三种子算法之间做运行时调度,调度决策由 config.json 中的三个参数控制:
{ "algorithm": "hybrid_sort", "params": { "insertion_threshold": 12, "run_detection_min": 10, "counting_span_limit": 128 } }调度逻辑如下(sort_benchmark.py 中的hybrid_sort):
def hybrid_sort(values, config, ops): params = dict(config.get('params', {})) insertion_threshold = int(params.get('insertion_threshold', 12)) run_detection_min = int(params.get('run_detection_min', 10)) counting_span_limit = int(params.get('counting_span_limit', 128)) if len(values) <= insertion_threshold: return insertion_sort(values, ops) if values: min_value = min(values) max_value = max(values) if max_value - min_value <= counting_span_limit: return counting_sort(values, min_value, max_value, ops) if longest_non_decreasing_run(values) >= run_detection_min: return insertion_sort(values, ops) return merge_sort(values, ops)三个参数各自的含义与影响:
| 参数 | 默认值 | 作用 | 优化影响 |
|---|---|---|---|
insertion_threshold | 12 | 数组长度不超过该值时直接走插入排序 | 决定小规模输入用"移动多、比较少"的插入排序替代归并的开销拐点 |
counting_span_limit | 128 | 值域跨度max - min不超过该值时走计数排序 | 决定何时用线性计数排序吃掉小值域输入(duplicates、low-cardinality 用例的胜负手) |
run_detection_min | 10 | 最长非递减段(run)长度达到该值时走插入排序 | 让近乎有序输入跳过归并,享受插入排序的 O(n) 近似代价 |
配套的辅助函数longest_non_decreasing_run(values)在单次线性扫描中计算最长非递减连续段的长度,用于run_detection_min判定。从源码结构看,这三个阈值共同构成一个两阶段路由:先看规模 → 再看值域 → 再看有序度 → 兜底归并。
值得注意的一点:counting_sort在实现中把初始化计数数组和遍历展开都计入移动成本(ops.move(len(counts))、ops.move(count)),因此当值域跨度接近counting_span_limit时,计数排序的初始化成本会被放大。据 playground/README.md 记录,该任务的已保留最优结果是"把计数排序切换到观测到的值域跨度"(score 从2.1198297352756628提升到9.411498969440865,提升约 7.29)——这意味着对调度逻辑做工程级调整(而非堆依赖、改基准)正是契约鼓励的优化方向。
五、评估器脚本与分数公式
评估器 src/scripts/eval/eval-adaptive-sort-optimization.py 是 sandbox 契约里evaluator.command指向的落地实现,它把"成本"翻译成"分数":
result = subprocess.run( [sys.executable, 'playground/adaptive_sort_demo/sort_benchmark.py'], check=False, capture_output=True, text=True, ) # ... payload = json.loads(result.stdout) total_cost = float(payload['total_cost']) score = 10000.0 / total_cost print(json.dumps({'pass': total_cost > 0, 'score': score}))几个要点:
- 评估器通过子进程调用
sort_benchmark.py的main(),后者输出run_config(load_config())的 JSON; - 若子进程返回码非零,评估器输出
{'pass': False, 'score': 0.0}并退出; - 分数定义为
10000.0 / total_cost,即总加权成本越低、分数越高,且pass仅在total_cost > 0时成立。
这个score正是keep_policy: score_improvement直接比较的量:autoresearch 监督器每一轮拿到候选改动的score,若高于当前基线则保留,否则丢弃。
六、基准用例:五个分布 × 三个规模 × 权重
build_cases()在 sort_benchmark.py 中生成 15 个用例(5 种分布 × 规模 32/64/96),每种用例带一个权重:
| 用例族 | 生成方式 | 权重 | 分布特征 |
|---|---|---|---|
random-{n} | ((i * 37 + 11) % 101) | 1.0 | 伪随机、值域 0–100,考验通用排序能力 |
reverse-{n} | list(range(n, 0, -1)) | 1.1 | 完全逆序,最坏输入之一 |
nearly-sorted-{n} | i if i % 9 else max(0, i - 3) | 1.2 | 几乎有序、偶发小扰动,适配 run 检测与插入排序 |
duplicates-{n} | ((i * 7) % 8) | 1.3 | 大量重复值、值域仅 8,适配计数排序 |
low-cardinality-{n} | ((i * 13 + 5) % 16) | 1.15 | 低基数、值域 16,同样利好计数排序 |
每个用例的加权成本为weight * ops.metrics.score(),总和累加为total_cost。由于权重侧重:duplicates(1.3)与 nearly-sorted(1.2)占比最高,一套好的策略应当优先在重复值与近有序输入上压低成本,而不是把力气都花在 random 用例上——这正是"自适应"三个字的含义所在。
正确性由评估循环内的断言兜底:
if out != sorted(values): raise AssertionError(f'incorrect sort output for {name}')任何产生错误排序的候选改动都会在断言处失败,进而导致评估器输出pass: false, score: 0.0,无法通过保留策略。
七、如何在仓库中运行与验证
7.1 直接运行基准
不需要安装任何依赖(仅标准库json、dataclasses、pathlib),在仓库根目录执行:
python3 playground/adaptive_sort_demo/sort_benchmark.py输出为 JSON,包含algorithm、total_cost与逐用例的weighted_cost,例如结构如下:
{"algorithm": "hybrid_sort", "total_cost": 1062.3, "cases": [{"case": "random-32", "weighted_cost": 89.1}, ...]}7.2 通过评估器打分
python3 src/scripts/eval/eval-adaptive-sort-optimization.py输出为{"pass": true, "score": <分数>},其中score = 10000.0 / total_cost。
7.3 作为 autoresearch mission 运行
在已安装 OmX 的环境下,可以走完整的自动研究循环:
omx autoresearch missions/adaptive-sort-optimization运行后可在.omx/logs/autoresearch/<run-id>/下检查manifest.json、candidate.json、iteration-ledger.json,查看监督器对每轮候选的 keep/discard/stop 决策(参见 missions/README.md 的说明)。快捷方式方面,run-autoresearch-showcase.sh 提供了sorting这个 showcase 别名映射到本 mission,可用scripts/run-autoresearch-showcase.sh sorting一键启动。
八、优化要点总结(算法工程视角)
综合 sandbox 契约、基准实现与评估公式,可归纳出几条可落地的优化路线:
- 阈值调优优先:
insertion_threshold、run_detection_min、counting_span_limit三个参数直接控制调度路由,是成本最低、风险最小的优化面;调参后跑评估器对比score即可。 - 启发式可以更"细":sandbox 明确允许"轻量级确定性启发式"。例如可以基于
Ops成本模型推断,对已检测到的长 run 段走插入排序、对剩余部分再递归调度,属于契约允许的"hybrid sort dispatch logic"改进。 - 警惕值域跨度陷阱:
counting_sort会把计数数组初始化计入移动成本,因此当值域接近counting_span_limit时计数排序未必划算——据 playground 记录,保留最优解正是通过将计数排序切换到观测到的值域跨度来大幅降本(分数 2.12 → 9.41),这说明"成本模型的细节"本身就藏着优化空间。 - 守住边界:不新增依赖、不改基准用例、不做无关仓库改动。任何让
sorted(values)断言失败或让pass变 false 的改动都会被评估器直接判 0 分。
最后提醒:本任务的评判完全由keep_policy: score_improvement驱动,优化目标始终是"在保持正确性与确定性的前提下降低加权成本"。这是一次典型的、可复现的算法工程练习——先读懂成本模型,再谈调度优化。
【免费下载链接】oh-my-codexOmX - Oh My codeX: Your codex is not alone. Add hooks, agent teams, HUDs, and so much more.项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-codex
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考