首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Optaplanner ConstraintStreams

Optaplanner ConstraintStreams
EN

Stack Overflow用户
提问于 2021-04-27 02:10:27
回答 2查看 70关注 0票数 1

我正在与“更高级别”的ConstraintStreams (bi,tri ..)作斗争。在Optaplanner用户指南中,显示了最简单的案例,我理解它们。同样,通过这些示例,我能够对BiConstraintStream求和。现在我有了一个TriConstraintStream,并且面临着问题。有谁知道更好的信息来源来更好地理解ConstraintStreams吗?

我的案例:问题结构与运输问题非常相似。我有节点和边,想要计算边的数量。

我的主要问题是:

代码语言:javascript
复制
class Node{
   UUID id;
   int itemsInInventory;
   ...
}

和规划实体:

代码语言:javascript
复制
@PlanningEntity
class Edge{
   Node from;
   Node to; 
   @PlanningVariable
   int itemsTransported;

   getFromId(){return from.getId()}
   getToId(){return to.getId()}

}

我希望将边连接到节点中两次,然后groupBy它们确实有一个像(Node, Sum(to), Sum(from))这样的对象

约束的当前代码为:

代码语言:javascript
复制
public Constraint minimizeShortage(ConstraintFactory constraintFactory) {
    return constraintFactory.fromUnfiltered(Node.class)
            .join(Edge.class,
                    equal(Node::getId, Edge::getFromId))
            .join(Edge.class,
                    equal((node, edge) -> node.getId(), Edge::getToId))
            groupBy(...)
}

对于BiConstraintStream (仅使用fromNode或toNode),groupBy将为.groupBy((node, edge) -> node, sum((node, edge) -> edge.getItemsTransported())),但在第二次连接后,我没有获得TriConstraintStream。

EN

回答 2

Stack Overflow用户

发布于 2021-04-27 15:40:03

我将把前面答案中的代码作为我的起点:

代码语言:javascript
复制
public Constraint minimizeShortage(ConstraintFactory constraintFactory) {
    return constraintFactory.fromUnfiltered(Node.class)
        .join(Edge.class,
                equal(Node::getId, Edge::getFromId))
        .groupBy((node, edgeFrom) -> node,
                sum((node, tsaO) -> edgeFrom.transportedItems()))
        .join(Edge.class,
                equal((node, edge) -> node.getId(), Edge::getToId))
        .groupBy((node, edgeFrom, edgeTo) -> node,
                (node, edgeFrom, edgeTo) -> qtO,
                sum((node, qtO, edgeTo) -> edgeTo.transportedItems()))
        ...
}

这段代码不太可能执行得很好,因为groupBy()是昂贵的,并且链接它们会使问题逐渐变得更糟。让我们看看我们是否可以用一个groupBy()做同样的事情

代码语言:javascript
复制
public Constraint minimizeShortage(ConstraintFactory constraintFactory) {
    return constraintFactory.fromUnfiltered(Node.class)
        .join(Edge.class,
                equal(Node::getId, Edge::getFromId))
        .join(Edge.class,
                equal((node, edge) -> node.getId(), Edge::getToId))
        .groupBy((node, edgeFrom, edgeTo) -> node,
                sum((node, edgeFrom, edgeTo) -> edgeFrom.transportedItems()),
                sum((node, edgeFrom, edgeTo) -> edgeTo.transportedItems())
        ...
}

让我们再多讨论一下。这个特殊的groupBy()重载由两部分组成:键映射和收集器。

键映射将三元组分成组-在本例中((node, edgeFrom, edgeTo) -> node)具有相同node的所有三元组将落入同一组。

然后,每个收集器对每个这样的三元组应用给定的操作(在本例中为sum),从而产生一个结果。我们在这里使用了两个收集器,一个收集器汇总在edgeFrom中传输的项目,另一个收集器对edgeTo执行相同的操作。这两个收集器只适用于共享相同node的边-正如前面提到的键映射所保证的那样。

顺便说一句,在开发像这样的非平凡约束时,我绝对建议使用Constraint Verifier对一些典型的结果进行建模,并查看约束是否按预期运行。

票数 2
EN

Stack Overflow用户

发布于 2021-04-27 06:45:31

我找到了解决我的问题的办法。解决方案是使用下面的语法,特别是不要在一个groupBy中总结。我必须将求和分成两个groupBys,并按以下顺序进行计算: Join1 - groupBy1 - join2 - groupBy2。

代码语言:javascript
复制
public Constraint minimizeShortage(ConstraintFactory constraintFactory) {
    return     constraintFactory.fromUnfiltered(Node.class)
            .join(Edge.class,
                    equal(Node::getId, Edge::getFromId))
            .groupBy((node, edgeFrom) -> node,
                    sum((node, tsaO) -> edgeFrom.transportedItems()))
            .join(Edge.class,
                    equal((node, edge) -> node.getId(), Edge::getToId))
            .groupBy((node, edgeFrom, edgeTo) -> node,
                    (node, edgeFrom, edgeTo) -> qtO,
                    sum((node, qtO, edgeTo) -> edgeTo.transportedItems()))
            ...
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67271731

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档