【问题标题】:Optaplanner shadow variable with more than one source具有多个源的 Optaplanner 阴影变量
【发布时间】:2016-07-01 09:20:48
【问题描述】:

Optaplanner 允许影子变量有多个源(sources = {}),但只有一个 variableListsnerClass。在我的实现中,我有一个带有阴影变量的计划实体,应该能够由两个列表器更改,但这似乎不受支持,还是我错了?有没有办法让两个监听器影响一个影子变量?

我有以下计划实体:PlannerActivity、PlannerTask 和 PlannerTaskResourceAllocation。

ActivityStartIndexVariableListener 会监听 PlannerActivity startIndex(真正的 var)上的任何更改,它会在属于该活动的所有任务上移动 startindex(shadow var)和 endIndex(shadow var)。这很好用

除此之外,对 PlannerTaskResourceAllocation 资源 (geniune var) 的任何更改都会被 TaskResourceVariableListener 监听,并且当资源是产品时,还会更新该产品的 ohHandAmounts,这也可以正常工作。

我遇到的问题是我需要添加逻辑,即当在 PlannerTaskResourceAllocation 上更改资源并且该资源是设​​备时,我可能需要重新计算任务持续时间,因为新设备可能比原来的设备更慢或更快之前分配的。 所以我在这里需要的是 PlannerActivity 和 PlannerTask startIndex 和 endIndex 也应该能够被 TaskResourceVariableListener 更改,但它们已经被 ActivityStartIndexVariableListener,我无法为一个影子变量指定两个监听器。

计划任务:

public class PlannerTask extends InventoryTransactionCause {

private static final long serialVersionUID = 1L;

@Getter
@Setter
private Activity activity;

@Getter
@Setter
private Integer indexInActivity;

// shadow variable
private Integer startIndex;

@Getter
@Setter
private double startOffset;

// shadow variable
private Integer length;

// shadow variable
private Integer endIndex;

@Getter
@Setter
private double endOffset;

@Getter
@Setter
private Integer originalStartIndex;

@Getter
@Setter
private Integer originalEndIndex;

@Getter
@Setter
private String state;

// getters and setters for shadow variables
// this is one of the shadow variables that i need affected by two 
// listeners, one is the ActivityStartIndexVariableListener and the 
// other is TaskResourceVariableListener
@CustomShadowVariable(variableListenerClass = ActivityStartIndexVariableListener.class,
        sources = { @CustomShadowVariable.Source(entityClass = PlannerActivity.class, variableName = "endIndex"),
                @CustomShadowVariable.Source(entityClass = PlannerTaskResourceAllocation.class,
                        variableName = "resource") })
public Integer getStartIndex() {
    return this.startIndex;
}

public void setStartIndex(Integer startIndex) {
    this.startIndex = startIndex;
}

@CustomShadowVariable(variableListenerClass = ActivityStartIndexVariableListener.class,
        sources = { @CustomShadowVariable.Source(entityClass = PlannerActivity.class, variableName = "endIndex"),
                @CustomShadowVariable.Source(entityClass = PlannerTaskResourceAllocation.class,
                        variableName = "resource") })
public Integer getEndIndex() {
    return this.endIndex;
}

public void setEndIndex(Integer endIndex) {
    this.endIndex = endIndex;
}

@CustomShadowVariable(variableListenerClass = TaskResourceVariableListener.class,
        sources = { @CustomShadowVariable.Source(entityClass = PlannerTaskResourceAllocation.class,
                variableName = "resource") })
public Integer getLength() {
    return this.length;
}

public void setLength(Integer length) {
    this.length = length;
}
}

【问题讨论】:

    标签: optaplanner


    【解决方案1】:

    variableListenerRef 属性支持这一点:第一个影子变量有一个普通的影子变量注释,第二个影子变量用@CustomShadowVariable(variableListenerRef = @PlanningVariableReference(variableName = "firstShadow")) 指向第一个影子变量

    例如,1 个变量侦听器更改基于 2 个真实变量的 2 个影子变量:

    @PlanningVariable(valueRangeProviderRefs = "valueRange")
    public TestdataValue getPrimaryValue() {
        return primaryValue;
    }
    
    public void setPrimaryValue(TestdataValue primaryValue) {
        this.primaryValue = primaryValue;
    }
    
    @PlanningVariable(valueRangeProviderRefs = "valueRange")
    public TestdataValue getSecondaryValue() {
        return secondaryValue;
    }
    
    public void setSecondaryValue(TestdataValue secondaryValue) {
        this.secondaryValue = secondaryValue;
    }
    
    @CustomShadowVariable(variableListenerClass = ComposedValuesUpdatingVariableListener.class,
            sources = {@CustomShadowVariable.Source(variableName = "primaryValue"),
                    @CustomShadowVariable.Source(variableName = "secondaryValue")})
    public String getComposedCode() {
        return composedCode;
    }
    
    public void setComposedCode(String composedCode) {
        this.composedCode = composedCode;
    }
    
    @CustomShadowVariable(variableListenerRef = @PlanningVariableReference(variableName = "composedCode"))
    public String getReverseComposedCode() {
        return reverseComposedCode;
    }
    
    public void setReverseComposedCode(String reverseComposedCode) {
        this.reverseComposedCode = reverseComposedCode;
    }
    

    【讨论】:

    • 这不能解决我的问题。澄清一下,我的一个计划实体有一个计划变量,该变量需要能够被其他两个不同类型的真实变量更改,因此我需要两个不同的侦听器,因此我需要能够在一个上指定两个侦听器阴影变量
    • 你能为此做一个复合监听器吗?用一个清晰​​的例子更新问题,因为我没有看到任何未涵盖的用例。
    • 我编辑了问题并将我的计划实体放在那里。如果接口只接受一种类型作为参数,我如何创建复合变量侦听器?如何创建一个监听两个计划实体的监听器?在您的示例中,两个真正的变量都在同一个实体上,但在我的示例中,它们在两个不同的实体上
    • Geoffrey,您有机会复习这个问题吗?现在更详细了...谢谢:)
    【解决方案2】:

    您可以制作依赖于影子变量的影子变量。

    为依赖于endIndex 和length(两者都是影子变量)的startIndex 创建一个自定义影子变量(带有VariableListener impl)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多