Expand description
可变的单分子构造器。
架构上刻意与 MolBatch 分开:编辑操作(解析建图、
反应产物构建)需要随意增删原子和键,而列式布局要为此付出高昂代价。
于是分成两段 —— MolBuilder 负责建,MolBatchBuilder::push 收进去之后
进入不可变的列式批,
所有算法都跑在后者上。
§邻接索引
MolBuilder 自带一份始终有效的邻接索引,neighbors
与 degree 都是 O(度数)。没有它的话,“取某原子的
邻居“只能扫全部键,而化学算法几乎每一步都在做这件事,整体就退化成
O(原子数 × 键数)。
§为什么是半边链表,不是 CSR
MolBatch 用 CSR,因为它不可变、只被扫描。MolBuilder 是增量构建
的:CSR 每加一条键都要重排整个邻接数组,解析一个 E 条键的分子就变成
O(E·(V+E))。半边链表加边是 O(1),代价是遍历时跳指针 —— 在编辑期的
规模下无所谓,真正吃吞吐的批量算法跑在 MolBatch 上。
这个分工是架构层面的:MolBuilder 为编辑优化,MolBatch 为扫描优化。
§索引不会失效
索引在 add_bond_data 里同步维护,不是缓存,
没有脏标记,也不需要谁记得去刷新。为此 bond_mut
返回的 BondMut 不暴露端点 —— 改端点就是改拓扑,只能走建边接口。
use omgkit_core::{MolBuilder, BondOrder};
// 乙醇 CCO
let mut b = MolBuilder::new();
let c0 = b.add_atom(6);
let c1 = b.add_atom(6);
let o = b.add_atom(8);
b.add_bond(c0, c1, BondOrder::Single).unwrap();
b.add_bond(c1, o, BondOrder::Single).unwrap();
assert_eq!(b.num_atoms(), 3);
assert_eq!(b.num_bonds(), 2);Structs§
- Atom
Data - 单个原子的可变数据。
- Bond
Data - 单条键的可变数据。端点为分子内局部原子下标。
- BondMut
- 键属性的可变句柄,由
MolBuilder::bond_mut取得。 - MolBuilder
- 可变的单分子构造器。
- Neighbors
MolBuilder::neighbors的迭代器,沿半边链表前进。