链式变量/锚变量和错误:仅链式变量支持单例逆

问题描述 投票:0回答:1

前言:Google + SO + docu搜索似乎未提供相关信息。

域模型:

我的域模型尝试描绘一个包含机器列表的ProductionPlan。每台计算机都有一个链式作业列表,因此一个作业具有一个getNextEntry():Job方法,以创建一个作业列表。

我曾尝试通过链接的PlanningVariables解决此问题,但显然不了解chainedVariables / shadowVariables / anchorVariables的概念。据我了解,所有作业都已链接在一起,并且anchorShadowVariable指向列表的开头,因此也指向了计算机。

要实现链接,Job and Machine需要实现接口或扩展超类,因此我创建了ChainSuperClass。另外,我不知道是否必须覆盖getter / setter才能在Machine-Class中设置Annotations,我的猜测是由于Machine扩展了ChainSuperClass,所以这些Annotation仍然有效。

编辑:Kotlin的特定改进也受到赞赏。

我的代码执行的完整错误日志现在是:

Exception in thread "main" java.lang.IllegalArgumentException: The entityClass (class optaplanner.productionPlan.domain.ChainSuperClass) has a InverseRelationShadowVariable annotated property (nextEntry) which does not return a Collection with sourceVariableName (machine) which is not chained. Only a chained variable supports a singleton inverse.

ChainSuperClass:

@PlanningEntity
abstract class ChainSuperClass {

@PlanningId
open val id = Random.nextInt().toString()

@InverseRelationShadowVariable(sourceVariableName = "machine")
abstract fun getNextEntry(): Job?

abstract fun setNextEntry(job: Job)
}

工作:

@PlanningEntity
class Job(
    val jobType: JobType,
    val itemNumber: String,
    val orderNumber: String,
    val setupTime: Int,
    val productionTime: Int
) : ChainSuperClass() {

     @AnchorShadowVariable(sourceVariableName = "machine")
     var machine: Machine? = null

     private var nextEntry: Job? = null

     @PlanningVariable(
          valueRangeProviderRefs = ["jobList"],
          graphType = PlanningVariableGraphType.CHAINED
     )
     override fun getNextEntry(): Job? {
          return nextEntry
     }

     override fun setNextEntry(job: Job) {
          this.nextEntry = nextEntry
     }
}

机器:

class Machine(override val id: String, val jobTypes: List<JobType>) : ChainSuperClass() {

    private var nextEntry: Job? = null

    override fun setNextEntry(job: Job) {
        this.nextEntry = job
    }

    override fun getNextEntry(): Job? {
        return nextEntry!!
    }
}
kotlin optaplanner
1个回答
0
投票

我认为使用链式变量实现的最重要的事情是:当您有一个实体时,说作业A,求解器为其变量分配一个值(作业/机器),这并不像链在从作业A开始向前构建。相反。通过为工作A的计划变量分配一个值,工作A在现有链的末尾获得连接。

[请查看documentation,以找到有关链接和有效链示例的更多详细信息。

通过了解这一点,应该很清楚,Job的计划变量名称应类似于previousJobOrMachine(您可能希望更简单的名称,例如previousStep),而nextJob属性是反函数由此得出的关系阴影变量(因此,当通过分配Job X。previousStep = Job C来将Job X连接到以Job C结尾的现有链时,则反关系会自动建立:Job C。nextJob = Job X)。

基于该信息,您的模型应看起来像这样:

@PlanningEntity
abstract class ChainSuperClass {

@PlanningId
open val id = Random.nextInt().toString()

// changed sourceVariableName to point to the planning variable
@InverseRelationShadowVariable(sourceVariableName = "previousStep")
abstract fun getNextEntry(): Job?

abstract fun setNextEntry(job: Job)
}
@PlanningEntity
class Job(
    val jobType: JobType,
    val itemNumber: String,
    val orderNumber: String,
    val setupTime: Int,
    val productionTime: Int
) : ChainSuperClass() {

     // changed sourceVariableName to point to the planning variable
     @AnchorShadowVariable(sourceVariableName = "previousStep")
     var machine: Machine? = null

     // added planning variable
     private var previousStep: ChainSuperClass? = null
     private var nextEntry: Job? = null

     @PlanningVariable(
          // added machineList value range provider
          valueRangeProviderRefs = ["jobList", "machineList"],
          graphType = PlanningVariableGraphType.CHAINED
     )
     // getter for the new planning variable
     fun getPreviousStep(): ChainSuperClass {
          return previousStep
     }

     override fun getNextEntry(): Job? {
          return nextEntry
     }

     override fun setNextEntry(job: Job) {
          this.nextEntry = nextEntry
     }
}

注意,在上一步中,我添加了machineList作为previousStep规划变量的可能值的来源,它可能是非空链末尾的Job或代表空链的Machine

© www.soinside.com 2019 - 2024. All rights reserved.