英文:
Optaplanner at least one occurency constraint
问题
I understand that you want a translation of the provided code without additional information. Here's the translated code:
我正在尝试实现一个约束,以便如果一个具有特定名称的元素没有至少分配一次,则会对解决方案进行惩罚。
我尝试使用 `GroupBy()` 但它不起作用:
```java
Constraint atLeastOne(ConstraintFactory cf) {
        return cf
                .forEach(Element.class)
                .groupBy(Element::getName, ConstraintCollectors.countDistinct())
                .filter((elementName, count) -> elementName == "foo" && count < 1)
                .penalize(HardSoftScore.ONE_HARD)
                .asConstraint("至少出现一次");
    }
我的想法是,如果没有名称为 "foo" 的元素存在,过滤器将不返回任何内容,因此不会强制执行约束。
我还尝试使用 ifNotExists():
Constraint atLeastOne(ConstraintFactory cf) {
        return cf
                .forEach(Element.class)
                .ifNotExists(Element.class, Joiners.filtering((a, b) -> a.getName() == "foo" && b.getName() == "foo"))
                .penalize(HardSoftScore.ONE_HARD)
                .asConstraint("至少出现一次");
    }
问题是使用 ifNotExists() 也会对所有具有 a.getName() != "foo" 的元素进行惩罚。
有没有办法使它工作?
<details>
<summary>英文:</summary>
I'm trying to implement a constraint so that if an element with a specific name is not assigned at least one time, the solution is penalized.
I tried using `GroupBy()` but it does not work:
```java
Constraint atLeastOne(ConstraintFactory cf) {
        return cf
                .forEach(Element.class)
                .groupBy(Element::getName, ConstraintCollectors.countDistinct())
                .filter((elementName, count) -> elementName == "foo" && count < 1)
                .penalize(HardSoftScore.ONE_HARD)
                .asConstraint("At least one occurency");
    }
My idea is that if no element with name "foo" is present the filter does not return anything and as a consequnce the costraint is not enforced.
I also tried using ifNotExists():
Constraint atLeastOne(ConstraintFactory cf) {
        return cf
                .forEach(Element.class)
                .ifNotExists(Element.class, Joiners.filtering((a, b) -> a.getName() == "foo" && b.getName() == "foo"))
                .penalize(HardSoftScore.ONE_HARD)
                .asConstraint("At least one occurency");
    }
The problem is that using ifNotExists() also penalizes all the elements with a.getName() != "foo"
Any idea to make it work?
答案1
得分: 0
在约束流中,groupby() 只有在至少有一个输入元组时才会产生结果。这意味着"至少有 X 个" 约束必须分别实现为两个独立的约束:
- 一个约束用于惩罚没有元素满足约束的情况
 - 一个约束用于惩罚一些(但不足够多)元素满足约束的情况(如果最小值是2或更多,则不需要此约束)
 
由于您正在使用分组键,您需要一种方法来访问"没有元素满足约束"情况下的所有可能键。在您的 @PlanningSolution 上创建一个包含所有可能名称的 ElementName 集合,并将其作为 @ProblemFactCollectionProperty。然后,约束会如下所示:
Constraint atLeastOne(ConstraintFactory cf) {
    return cf
            .forEach(ElementName.class)
            .filter(elementName -> elementName.getName().equals("foo"))
            .ifNotExists(Element.class, Joiners.equal(ElementName::getName, Element::getName))
            .penalize(HardSoftScore.ONE_HARD)
            .asConstraint("至少有一个出现");
}
请注意,这是原文的翻译,没有包括代码部分。
英文:
In constraint streams, a groupby() only produce a result if it has at least one input tuple. This means "have at least X" constraints must be implemented as two separate constraints:
- One constraint to penalize the case when no elements satisfy the constraint
 - One constraint to penalize the case when some (but not enough) elements satisfy the constraint (this is not needed since minimum is 1, but would be needed if minimum was 2 or more)
 
Since you are using a grouping key, you need a way to access all possible keys for the "no elements satisfy the constraint" case. Create an ElementName collection with all possible name and put it as a @ProblemFactCollectionProperty on your @PlanningSolution. Then the constraint would look like this:
Constraint atLeastOne(ConstraintFactory cf) {
    return cf
            .forEach(ElementName.class)
            .filter(elementName -> elementName.getName().equals("foo"))
            .ifNotExists(Element.class, Joiners.equal(ElementName::getName, Element::getName))
            .penalize(HardSoftScore.ONE_HARD)
            .asConstraint("At least one occurency");
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论