具有多个源的Optaplanner阴影变量

时间:2016-07-01 09:20:48

标签: optaplanner

Optaplanner允许阴影变量具有多个源(sources = {}),但只允许一个variableListsnerClass。在我的实现中,我有一个带有阴影变量的规划实体,应该可以由两个列表器进行更改,但这似乎不支持,或者我错了?有没有办法让两个侦听器影响一个影子变量?

我有以下规划实体:PlannerActivity,PlannerTask和PlannerTaskResourceAllocation。

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

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

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

uml PlannerTask:

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;
}
}

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:0)

您可以使影子变量依赖于影子变量

VariableListener创建一个自定义阴影变量(带有startIndex impl),该变量取决于endIndexlength(它们都是影子变量)。