#求解器 # #响应式 #逻辑 #无std

无std gpp-solver

一个兼具两者之长的轻量级混合推拉求解器/规划器

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

BSD-2-Clause

39KB
743

通用推拉求解器。

这个crate实现了一个通用求解器,用于任何具有清晰依赖图的实体。该实现是推(急切)和拉(懒惰)架构的混合,具有用户驱动的递归。

功能集中在 Solver 结构上。用户记录他们想要评估的所有 片段,并且只记录这些。片段由一个整数 FragmentId 表示,但 什么是 片段是任意的,求解器并不关心。它可以代表一个变量、一个动作、一个对象或任何其他东西。

用户还必须实现 Problem 特性,它定义了一个依赖图和评估求解器找到的既可解又必需的片段的接口。这个依赖图不需要是完整的或明确的,只要实现者能够在求解器探索依赖图时返回指定片段的直接依赖项即可。

Solver::runSolver::step 将逐步探索依赖图,并在满足所有依赖项的片段上调用 Problem::evaluate

最终,所有请求的片段都将被评估或被证明是依赖循环的一部分。用户可以选择将循环报告为错误,或者使用 Solver::assume_evaluatedSolver::clone_with_evaluation_assumptions 来打破它们。另请参阅 Solver::status

Solver::punted_iter 将返回一个迭代器,生成迄今为止所有已被 推迟 的片段。一个推迟的片段是指已被考虑评估,但其依赖尚未满足的片段。如果求解器已完成,推迟的片段必须至少是某个循环的一部分。

并发

Solver 是完全异步的,但核心算法目前不是并行的。同时运行多个 Solver::step 或使用 concurrency > 1 调用 Solver::run 是安全的,但这不会使求解器本身运行更快。这所允许的是,多个 Problem::direct_dependenciesProblem::evaluate 调用可以并发运行。

构建功能

该软件包具有多个功能。其中,有三个功能用户必须指定其中一个: futures-locktokio-lockasync-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_evaluatedSolver::clone_with_evaluation_assumptions 打破循环。这使实现更加简单。

依赖关系

~1.2–4.5MB
~83K SLoC