Optaplanner至少一个发生约束

huangapple go评论127阅读模式
英文:

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&#39;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) -&gt; elementName == &quot;foo&quot; &amp;&amp; count &lt; 1)
                .penalize(HardSoftScore.ONE_HARD)
                .asConstraint(&quot;At least one occurency&quot;);
    }

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) -&gt; a.getName() == &quot;foo&quot; &amp;&amp; b.getName() == &quot;foo&quot;))
                .penalize(HardSoftScore.ONE_HARD)
                .asConstraint(&quot;At least one occurency&quot;);
    }

The problem is that using ifNotExists() also penalizes all the elements with a.getName() != &quot;foo&quot;

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 -&gt; elementName.getName().equals(&quot;foo&quot;))
            .ifNotExists(Element.class, Joiners.equal(ElementName::getName, Element::getName))
            .penalize(HardSoftScore.ONE_HARD)
            .asConstraint(&quot;At least one occurency&quot;);
}

huangapple
  • 本文由 发表于 2023年5月11日 02:10:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76221451.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定