from vs fromUnfiltered with nullable variable - Optaplanner

from vs fromUnfiltered with nullable variable - Optaplanner

我需要澄清在 Optaplanner 中使用 planningEntitiesnullable 变量时 fromfromUnfiltered 的行为。

user documentation 表示

The .from(T) building block selects every T instance that is in a problem fact collection or a planning entity collection and has no null planning variables.

To include instances with a null planning variable, especially if you use nullable variables, replace the from() building block by fromUnfiltered():

但是 from 方法的 java doc 声明 from 方法将过滤具有空变量的实体,除非它是 nullable 变量:

Start a ConstraintStream of all instances of the fromClass that are known as problem facts or planning entities.

If the fromClass is a PlanningEntity, then it will be automatically filtered to only contain fully initialized entities, for which each genuine PlanningVariable (of the fromClass or a superclass thereof) is initialized (so when the value is not null - unless PlanningVariable.nullable() is modified). This filtering will NOT automatically apply to genuine planning variables of subclass planning entities of the fromClass.

我不确定我的理解是否正确,我的测试表明 javadoc 是正确的,而用户文档具有误导性。或许我没抓住重点。

有人澄清一下吗?

from(...) 的整个情况已经痛苦了一段时间。 OptaPlanner 8.13.0.Final 及更早版本中的行为如下:

  • 对于具有 nullable = false 计划变量(默认)的实体,from(...) return 仅在其任何真正计划中没有 null 的实体变量。
  • 对于具有 nullable = true 规划变量(过度约束规划)的实体,在这些实体被初始化。换句话说 - 它不会在构造启发式期间 return 它们,但它会在随后的本地搜索中 return 它们,如果构造启发式决定 保持 null 那里。

然而,这并不是 null 处理中唯一令人困惑的行为。通过条件传播(ifExists(...) 等),我们将 总是 return 个具有 null 真实变量的实体,在任何情况下。

我们最近意识到这种情况是不可持续的,从 OptaPlanner 8.14 开始。0.Final(即将发布),我们弃用了 from(...) 并引入了 forEach(...),这清理了所有这些混乱。从这个版本开始,当使用新的 API 时,关于 null 变量的行为将更加清晰,更重要的是,将保持一致。

forEach(...) 永远不会 return 具有 null 变量的实体,forEachIncludingNullVars(...) 应该用于此。条件传播也将尊重这一点。

新版本发布时请参阅upgrade recipe