第四章 工程中间表示——连接工程责任与可执行推理的桥梁
编译器不能执行自然语言。
工程系统也不能。
第三章确立了交通工程的基本单元是责任——不是函数,不是任务,不是工作流。但用自然语言表达的责任无法被任何计算系统直接执行。工程师直觉上理解“评估交叉口 A 是否需要重新配时”是什么意思;计算机不理解。本章介绍工程中间表示(Engineering IR)——一种结构化表征,填补自然语言工程意图与可执行推理之间的鸿沟。工程中间表示之于交通智能体工程,犹如 LLVM IR 之于现代编译器:一个稳定的、语义化的、可优化的中间形式,使从意图到执行的系统性转换成为可能。
4.1 缺失的层
每一项工程责任都始于一种意图——一个想法、一项请求、一条用自然语言表达的指令。看看这个例子:
评估交叉口 A 是否需要重新配时。
交通工程师立刻明白这是什么意思。她知道:
- 该收集什么数据(流量计数、延误测量、排队观测)
- 该做什么分析(通行能力分析、LOS 评估、配时审查)
- 该适用什么标准(HCM 方法论、机构政策、MUTCD 要求)
- 该产出什么交付物(一份附有发现和建议的备忘录)
计算机完全不懂这些。计算机执行的是具有明确语义的结构化表征——而非模棱两可的自然语言。
这种错位贯穿了整个工程软件史,而且每次都以同一种方式解决:人工翻译。
┌─────────────────────┐ ┌──────────────────────┐
│ 自然语言 │ ??? │ 结构化执行 │
│ 责任 │ ──────► │ (算法、代码) │
│ "评估交叉口A..." │ 错位 │ │
└─────────────────────┘ └──────────────────────┘
▲ │
│ 工程师 │
└────────────────────────────┘
(人工翻译)
传统交通系统以手动方式解决这个错位:
- 工程师分解 责任为子任务
- 软件执行 每个子任务的独立算法
- 工程师整合 结果为连贯结论
- 工程师产出 最终产物
推理过程——关于什么重要、什么不重要、证据如何支撑结论、约束是否满足的关键工程判断——始终停留在工程师的大脑里。软件从不参与推理;它只做计算。
交通智能体工程提出了一个根本不同的解决方案:不再要求工程师把责任翻译成计算,而是引入一种中间表征,以结构化、机器可处理的形式捕获工程语义。 我们把这个表征称为工程中间表示,简称 Engineering IR。
4.2 从编译器设计中学到的
连接人类意图与机器执行的问题并非交通工程独有。它在软件工程领域通过编译器中间表示的发展得到了决定性的解决。
现代编程语言从不直接执行源代码。相反,编译器将源代码经过多层表征进行转换,每层服务于不同目的:
| 层级 | 表征 | 用途 |
|---|---|---|
| 源码 | C++、Rust、Swift | 人类可读的意图表达 |
| 语法 | 抽象语法树(AST) | 结构解析、错误检查 |
| 中间 | LLVM IR、WASM | 与平台无关的优化 |
| 目标 | x86、ARM、RISC-V | 特定硬件上的执行 |
考虑 C++ 的转换管线:
C++ 源代码
↓
[词法分析与语法分析]
↓
抽象语法树(AST)
↓
[语义分析与类型检查]
↓
LLVM 中间表示
↓
[优化遍]
↓
机器码(x86/ARM/RISC-V)
每一层有不同的用途:
- 语法消失:源语言的具体语法被规范化。
- 执行成为可能:机器码可以在硬件上实际运行。
- 优化变得独立:优化遍操作的是 IR 而非源代码,使其可以跨语言复用。
交通工程需要类似的转换。自然语言的责任不能被直接执行——它们必须先变成可执行的工程结构。工程中间表示恰恰扮演这个角色:它是工程语义变得显式、优化成为可能、执行可以被系统性推导出来的那个中间层。
4.3 工程语言不是编程语言
在精确定义工程中间表示之前,我们必须理解为什么现有表征不够用。关键洞见在于:工程描述在编程语言不会容忍的方式上故意保留模糊性。
看看下面这个看似简单的请求:
“优化这个交叉口。”
对人类工程师来说,这句话立刻隐含了大量假设和上下文知识:
| 隐藏维度 | 工程师会问的问题 |
|---|---|
| 目标 | 延误最小化?排队缩减?安全改善?通行量最大化?燃油效率? |
| 范围 | 单个交叉口?路网范围?通道?仅高峰时段还是全天? |
| 需求条件 | 现状需求?设计年(5/10/20 年)?增长率假设? |
| 标准 | HCM 第六版?州 DOT 手册?机构特定准则?必须符合 MUTCD? |
| 约束 | 最小绿灯时间?最大周期长度?存储容量限制?行人要求?预算? |
| 可用证据 | 检测器数据质量?历史计数?仿真模型已校准?做过现场踏勘吗? |
| 利益相关方关切 | 居民投诉?紧急车辆通道?公交优先?自行车保障? |
自然语言把这些工程语义隐藏在共享上下文和专业经验背后。每个字都携带着从业者心照不宣但对计算系统完全不透明的假设。
计算机需要显式语义。每个假设都必须陈述。每个约束都必须指定。每条证据都必须识别。每个成功标准都必须定义。
工程中间表示的存在正是为了暴露这些隐藏结构——让自然语言留下的隐含信息变得显式,从而使计算系统能够以编译器带给程序分析同样的结构清晰度来推理工程问题。
4.4 责任作为声明式规范
一个关键的设计决策塑造了整个工程中间表示:它是声明式的,而非命令式的。
- 命令式描述规定怎么做:逐步指令、算法、工作流、流程。
- 声明式描述规定要达成什么:目标、约束、要求、期望结果。
工程中间表示坚定地属于声明式阵营。概念上,转换过程如下:
责任(自然语言)
│
▼
┌─────────────────────────────────┐
│ 工程中间表示 │
│ (声明式规范) │
│ │
│ • 工程目标 │
│ • 工程约束 │
│ • 所需证据 │
│ • 推理目标 │
│ • 预期交付物 │
│ • 置信度策略 │
└─────────────────────────────────┘
│
▼
可执行推理图
(由领域推理编译器生成)
注意 IR 明确规定了什么——以及刻意省略了什么:
| IR 规定的内容 | IR 省略的内容 |
|---|---|
| 必须达成什么目标 | 使用哪种算法 |
| 什么约束界定可行解 | 操作按什么顺序执行 |
| 需要什么证据 | 证据如何在内部收集 |
| 什么产物算成功 | 内部数据结构 |
| 可接受什么置信度水平 | 实现细节 |
这种区分至关重要。责任描述工程必须达成什么。IR 描述开始执行之前工程必须知道什么。而怎么做——具体的计算序列、算法和数据转换——留给领域推理编译器去决定,我们将在后续章节详细讨论。
4.5 工程中间表示的解剖结构
每一个工程中间表示都由六个语义段组成,每段捕获工程责任的一个不同侧面:
┌──────────────────────────────────────────────────────────────┐
│ 工程中间表示 │
│ │
│ ┌────────────────┐ │
│ │ 责任 │ ◄── 要求做什么? │
│ └───────┬────────┘ │
│ │ │
│ ┌───────▼────────┐ │
│ │ 世界上下文 │ ◄── 在哪里适用? │
│ └───────┬────────┘ │
│ │ │
│ ┌───────▼────────┐ │
│ │ 所需证据 │ ◄── 需要什么证据? │
│ └───────┬────────┘ │
│ │ │
│ ┌───────▼────────┐ │
│ │ 约束 │ ◄── 适用哪些规则? │
│ └───────┬────────┘ │
│ │ │
│ ┌───────▼────────┐ │
│ │ 交付物 │ ◄── 产出什么产物? │
│ └───────┬────────┘ │
│ │ │
│ ┌───────▼────────┐ │
│ │ 置信度策略 │ ◄── 结果需要多确定? │
│ └────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘
逐一详细解读各段:
第一段:责任
对必须达成什么的正式陈述。这是自然语言责任,现在被正式声明为规范目标。
示例:OptimizeSignalTiming(Intersection_A)
第二段:世界上下文
定义责任在何处何时适用的情境信息。包括地理范围、时间段、相关基础设施、利益相关方背景,以及任何为当前请求提供依据的前序工程工作。
示例:Intersection_A = { location: "Main St & 5th Ave", type: "4-leg pretimed", detectors: ["D1","D2","D3"], last_review: "2024-03", complaints: 12 }
第三段:所需证据
推理能够启动之前必须具备的具体数据项、测量值和分析。每条证据都有类型、来源、质量要求和时效阈值。
示例:{ QueueLength(detector), DegreeOfSaturation(movement), StorageLength(lane), TurningMovementCounts(period) }
第四段:约束
界定可行解空间的规则、法规、物理限制和政策要求。约束分为硬约束(必须满足)和软约束(尽可能满足)。
示例:{ MaxCycleLength <= 180s, MinGreen[ped] >= 7s, StorageUtilization <= 0.85, MUTCD_Compliance = true }
第五段:交付物
构成责任成功完成的产物。交付物指定格式、内容要求和受众。
示例:{ TimingPlan(ring_diagram, timing_sheet), RecommendationMemo(findings, alternatives_selected, justification) }
第六段:置信度策略
结论所需的确信度等级以及处理不确定性的协议。有些责任要求高置信度的确定性答案;有些则接受带置信区间的概率性估计。
示例:{ DelayEstimation: CI_95%, CapacityAnalysis: Deterministic, Recommendation: Expert_Judgment_Allowed }
关键点:工程中间表示中没有任何地方出现算法。 IR 只规定工程需求——必须知道什么、必须满足什么、必须产出什么。从需求到算法的映射是领域推理编译器的工作,而不是 IR 本身的事。
4.6 工程中间表示具有稳定性
工程中间表示最重要的属性之一是其相对于算法的稳定性。算法不断演变;工程责任却在数十年间保持惊人的稳定。
考虑这一单一工程责任:估算信号交叉口的通行能力。 过去六十年间,这同一项责任使用了截然不同的算法来实现:
| 时代 | 算法/方法 | 备注 |
|---|---|---|
| 1950s–1960s | 韦伯斯特公式 | 解析法,均匀到达假设 |
| 1970s–1980s | HCM 第1–3版 | 经验回归模型 |
| 1990s | Akçelik 排队模型 | 时变、感知车队 |
| 2000s | 元胞传输模型(CTM) | 运动波理论 |
| 2010s | 微观仿真(VISSIM、Synchro) | 逐车建模 |
| 2020s | 神经交通模型 | 数据驱动、学习动力学 |
尽管实现方法发生了剧烈演变,工程责任始终不变:估算给定条件下该进口能通过多少辆车。1960 年的工程师和 2026 年的工程师回答的是同一个问题。
这个观察有着深远的架构意义:
工程中间表示独立于算法。
运行时可以把韦伯斯特公式替换为神经能力估计器,而不改变责任本身、不修改 IR 结构、也不改变交付物格式。IR 规定必须计算什么;算法选择决定怎么计算。这两种决策被正确地分离了。
这种分离代表了交通智能体工程的基本设计原则之一:
| 关注点 | 归属方 | 稳定性 |
|---|---|---|
| 什么(责任、IR) | 工程师 / 领域专家 | 高度稳定(数十年) |
| 怎么做(算法选择) | 领域推理编译器 | 中等稳定(数年) |
| 执行(运行时) | 交通智能体运行环境 | 频繁更新(月级) |
4.7 工程中间表示具有领域语义
工程中间表示在工作流描述、过程脚本或任务列表之间有一个根本区别:它捕获的是语义意图,而非计算顺序。
考虑两个表面相似的工程请求:
| 请求 | 共享的计算 | 不同的语义 |
|---|---|---|
| 评估服务水平 | 延误估计、排队分析、v/c 比 计算 | 目标:对照 HCM 阈值分类性能;输出是 LOS 等级(A–F) |
| 审查信号配时方案 | 延误估计、排队分析、v/c 比 计算 | 目标:核验合规性;输出是通过/不通过及具体发现 |
两个请求可能调用完全相同的计算原语:
- 估计各流向延误
- 分析排队动态
- 计算饱和度
- 对照阈值比较
然而它们的工程含义完全不同:
- 所需证据可能不同(LOS 评估需要 HCM 定义指标;配时审查需要 MUTCD 合规检查)。
- 施加的约束不同(LOS 用标准假设;配时审查应用机构特定的最小值)。
- 成功标准不同(LOS 产出等级;配时审查产出合规判定)。
- 产出的产物不同(LOS 报告 vs 工程审查文件)。
工程中间表示捕获的是语义意图——为什么要执行这些计算——而不是计算顺序——即怎么排列它们。执行顺序属于推理引擎,由它根据数据可用性、依赖关系和优化机会来确定最优顺序。
这个特性使工程中间表示具有可组合性:同样的原语操作可以根据其语义上下文服务于不同责任,就像同样的 LLVM 指令可以根据源代码语义服务于不同高层程序一样。
4.8 工程中间表示支持编译器优化
一旦工程责任变成了结构化表征(而非晦涩难懂的自然语言字符串),一种强大的新能力就出现了:编译器优化。正如优化编译器转换 IR 以提升执行效率,TAE 编译器也可以转换工程中间表示以提升工程效率。
工程级优化的示例包括:
| 优化类别 | 描述 | 示例 |
|---|---|---|
| 自动证据复用 | 如果两项责任需要同一证据,只收集一次 | “评估 LOS”和”优化配时”都需要转向流量 → 收集一次,共享 |
| 约束传播 | 在昂贵计算之前提前拒绝不可行解 | 如果存储长度 < 所需排队 → 跳过仿真,立即报告约束违反 |
| 原语替换 | 在精度允许的情况下用更廉价的等价物替换昂贵的原语 | 初筛时用解析延误代替微观仿真 |
| 并行推理 | 并发执行独立的推理分支 | 同时评估所有候选配时方案 |
| 增量验证 | 在部分结果可用时就验证,而非等待全部完成 | 每个 v/c 比一算出来就检查,超阈值立即失败 |
| 工程缓存复用 | 在相关责任之间缓存中间结果 | 能力分析结果在同时评估 LOS 和安全时复用 |
这些优化都不需要修改底层的工程责任。它们完全作用于工程中间表示,在传递给推理引擎之前将其转换为更高效的形式。
这与 LLVM IR 在软件编译中的角色精确对应:
| 软件编译器 | TAE 编译器 |
|---|---|
| 源代码 → LLVM IR | 责任 → 工程中间表示 |
| 对 LLVM IR 执行优化遍 | 对工程中间表示执行优化遍 |
| LLVM IR → 机器码 | 工程中间表示 → 推理图 → 原语 |
| 特定目标的代码生成 | 特定领域的原语绑定 |
4.9 工程中间表示支持泛化
交通工程涵盖数千种截然不同的工程问题,横跨众多子领域:
| 领域 | 代表性责任 |
|---|---|
| 信号控制 | 优化配时、协调通道、设计感应控制、评估连续推进 |
| 高速公路运营 | 管理匝道调节、检测事件、实施可变限速、管理拥堵 |
| 公交运营 | 设计信号优先、优化车头时距、调度可靠性、分配路权 |
| 交通安全 | 开展安全审计、分析事故模式、评估视距、审查冲突点 |
| 停车管理 | 监控占用率、动态定价、引导司机、执法管控 |
| 施工区管控 | 设计临时管控、管理排队、维持通道、保护工人 |
| 事件响应 | 检测事件、派遣响应、管理分流、清空道路 |
| 规划 | 预测需求、比选方案、评估环境影响、项目排序 |
为每种可能的责任编写专用软件是不可能的——领域 × 任务 × 上下文的组合爆炸会击败任何全面覆盖的尝试。
工程中间表示通过提供一个横跨所有领域的通用表征来解决这个问题。不同工程领域变成同一语义结构的不同实例:
┌─────────────────────────────────────────────────────┐
│ 通用 IR 结构 │
│ │
│ 责任 + 世界上下文 + 证据 + │
│ 约束 + 交付物 + 置信度策略 │
│ │
└──────────────────────┬──────────────────────────────┘
│
┌────────────┼────────────┬────────────┐
▼ ▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 信号 │ │ 高速公路 │ │ 安全 │ │ 规划 │
│ 控制 │ │ 运营 │ │ 审计 │ │ 研究 │
│ 实例 │ │ 实例 │ │ 实例 │ │ 实例 │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
每个领域实例用领域特定值填充通用 IR 结构:
- 信号控制用 MUTCD 配时上下限填充约束
- 安全审计用事故历史和冲突点清单填充证据
- 规划研究用环境影响评价和成本效益分析填充交付物
编译器不再依赖交通控制的细节。它依赖的是工程语义——所有领域共用的通用结构。领域特定知识编码在原语库(第七章讨论)和约束数据库(第八章讨论)中,而非编译器本身。
4.10 迈向推理编译
工程中间仍然不可执行。它规定的是工程语义——必须达成什么、什么约束解空间、需要什么证据——但它不规定工程推理——如何通过有效的推断步骤从证据走向结论。
因此还需要第二次转换:
工程责任
│
▼
┌─────────────────────┐
│ 工程中间表示 │ ◄── 声明式规范
│ (是什么 & 为什么)│
└──────────┬──────────┘
│
▼ [领域推理编译器]
│
┌─────────────────────┐
│ 推理图 │ ◄── 结构化推断计划
│ (怎么推理) │
└──────────┬──────────┘
│
▼ [原语绑定]
│
┌─────────────────────┐
│ 原语图 │ ◄── 绑定到可执行操作
│ (运行什么) │
└──────────┬──────────┘
│
▼ [交通智能体运行时]
│
┌─────────────────────┐
│ 工程产物 │ ◄── 最终交付物
└─────────────────────┘
在这个转换管线中:
- 责任变成规范(工程中间表示)。
- 编译器把规范转换为推理(推理图 → 原语图)。
- 运行时执行推理(交通智能体运行环境)。
- 结果变成工程产物(原始 IR 中规定的交付物)。
实现这次转换的核心机制——读取工程中间表示并产出可执行推理图的组件——就是领域推理编译器,这是下一章的主题。
本章小结
第四章介绍了工程中间表示(Engineering IR)——连接自然语言工程意图与可执行推理的桥梁。主要贡献包括:
- 缺失的层:传统系统依赖人工将责任翻译为计算;TAE 引入了自动化的中间表征。
- 编译器类比:正如 LLVM IR 使软件编译中的跨语言优化成为可能,工程中间表示使工程系统中的跨领域优化成为可能。
- 声明式本质:工程中间表示规定必须达成什么(目标、约束、证据、交付物),而非怎么做(算法、执行顺序)。
- 六段解剖结构:每个工程中间表示包含责任、世界上下文、所需证据、约束、交付物和置信度策略。
- 算法独立性:即使底层算法持续演变(韦伯斯特 → HCM → 神经模型),IR 保持稳定——因为 IR 捕获的是工程意图,而非实现方式。
- 语义 vs 过程:IR 捕获工程的含义,而非计算的顺序——使同一批原语可以为不同责任服务。
- 编译器优化:结构化的 IR 支持证据复用、约束传播、并行推理、增量验证和其他工程级优化。
- 泛化:通用 IR 结构覆盖所有交通领域(信号控制、高速运营、安全、规划等),领域特定实例填充同一套模式。
- 下一步:工程中间表示必须经由领域推理编译器(第五章起)转换为可执行推理。