4个版本
0.2.2 | 2021年12月29日 |
---|---|
0.2.1 | 2021年11月27日 |
0.2.0 | 2021年11月27日 |
0.1.0 | 2021年11月25日 |
在 算法 中排名 2580
39KB
743 行
通用推拉求解器。
这个crate实现了一个通用求解器,用于任何具有清晰依赖图的实体。该实现是推(急切)和拉(懒惰)架构的混合,具有用户驱动的递归。
功能集中在 Solver
结构上。用户记录他们想要评估的所有 片段,并且只记录这些。片段由一个整数 FragmentId
表示,但 什么是 片段是任意的,求解器并不关心。它可以代表一个变量、一个动作、一个对象或任何其他东西。
用户还必须实现 Problem
特性,它定义了一个依赖图和评估求解器找到的既可解又必需的片段的接口。这个依赖图不需要是完整的或明确的,只要实现者能够在求解器探索依赖图时返回指定片段的直接依赖项即可。
Solver::run
和 Solver::step
将逐步探索依赖图,并在满足所有依赖项的片段上调用 Problem::evaluate
。
最终,所有请求的片段都将被评估或被证明是依赖循环的一部分。用户可以选择将循环报告为错误,或者使用 Solver::assume_evaluated
或 Solver::clone_with_evaluation_assumptions
来打破它们。另请参阅 Solver::status
。
Solver::punted_iter
将返回一个迭代器,生成迄今为止所有已被 推迟 的片段。一个推迟的片段是指已被考虑评估,但其依赖尚未满足的片段。如果求解器已完成,推迟的片段必须至少是某个循环的一部分。
并发
Solver
是完全异步的,但核心算法目前不是并行的。同时运行多个 Solver::step
或使用 concurrency > 1
调用 Solver::run
是安全的,但这不会使求解器本身运行更快。这所允许的是,多个 Problem::direct_dependencies
和 Problem::evaluate
调用可以并发运行。
构建功能
该软件包具有多个功能。其中,有三个功能用户必须指定其中一个: futures-lock
、tokio-lock
或 async-std-lock
。使用最方便的一个。
std
使用 std. 如果禁用 std
,则将不可用 Solver::run
。 待办事项:实际上使此断言成立。
js-bindings
在构建 WASM 时构建 JavaScript API。
futures-lock
使用 futures
软件包实现的锁。
tokio-lock
使用 tokio
软件包实现的锁。
async-std-lock
使用 async-lock
软件包实现的锁。
内部结构
Solver
实现了一个混合推送-拉取架构。只有在需要时(拉取,延迟评估)才会评估片段,但与递归评估依赖项不同,此过程将只评估已满足所有 直接 依赖项的片段。如果不是这种情况,该片段将被 推迟:存储起来,仅在未来的某个时刻所有依赖项都满足时才会再次考虑。
另一方面,如果片段成功评估,如果所有其他依赖项也已评估,则将推迟依赖该片段的片段紧急评估(推送)。
这种架构有两个主要优势
- 它是懒惰的。只有明确请求评估的片段及其依赖的片段才会被评估。并且永远不会评估超过一次。
- 与纯推送和纯拉取不同,不需要显式检测或处理循环。循环中的片段将自然被推迟并再次考虑。除非显式使用
Solver::assume_evaluated
或Solver::clone_with_evaluation_assumptions
打破循环。这使实现更加简单。
依赖关系
~1.2–4.5MB
~83K SLoC