Chained Variables / Anchor Variable and Error: Only a chained variable supports a singleton inverse
Chained Variables / Anchor Variable and Error: Only a chained variable supports a singleton inverse
前言:Google+SO+docu搜索未出现相关信息
领域模型:
我的域模型试图描绘一个包含机器列表的生产计划。
每个机器都有一个链式作业列表,因此一个作业有一个 getNextEntry():Job 方法,创建一个作业列表。
我试图用链式 PlanningVariables 解决这个问题,但显然不理解 chainedVariables/shadowVariables/anchorVariables 的概念。
据我了解,所有作业都被链接起来,并且 anchorShadowVariable 指向列表的开头,因此指向机器。
为了实现链接,Job 和 Machine 需要实现接口或扩展超类,因此我创建了 ChainSuperClass。此外,我不知道是否必须覆盖 getter/setter 才能在 Machine-Class 中设置注释,我的猜测是因为 Machine 扩展了 ChainSuperClass,这些注释会继续存在。
编辑: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.
超级链Class:
@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!!
}
}
我认为使用链式变量实现的最重要的事情是:当你有一个实体时,说 Job A 并且求解器分配一个值 (job/machine)到它的变量,这不像是从 Job A 开始向前构建的链。恰恰相反。通过为 Job A 的计划变量赋值,Job A 连接到现有链的末端。
请查看 documentation 以查找有关链和有效链示例的更多详细信息。
通过理解这一点,应该清楚 Job
的计划变量名称应该类似于 previousJobOrMachine
(您可能想要更简单的名称,例如 previousStep
)而 nextJob
属性 是从中派生的反向关系影子变量(因此当 Job X 连接到以 Job 结尾的现有链C赋值Job X.previousStep=Job C,自动建立反关系:Job C .nextJob=工作 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
。
您的域与 vehicle routing domain 非常相似,您可以在其中看到链接的工作示例。充分理解链接原则后,您应该能够在您的域中复制它。
前言:Google+SO+docu搜索未出现相关信息
领域模型:
我的域模型试图描绘一个包含机器列表的生产计划。 每个机器都有一个链式作业列表,因此一个作业有一个 getNextEntry():Job 方法,创建一个作业列表。
我试图用链式 PlanningVariables 解决这个问题,但显然不理解 chainedVariables/shadowVariables/anchorVariables 的概念。 据我了解,所有作业都被链接起来,并且 anchorShadowVariable 指向列表的开头,因此指向机器。
为了实现链接,Job 和 Machine 需要实现接口或扩展超类,因此我创建了 ChainSuperClass。此外,我不知道是否必须覆盖 getter/setter 才能在 Machine-Class 中设置注释,我的猜测是因为 Machine 扩展了 ChainSuperClass,这些注释会继续存在。
编辑: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.
超级链Class:
@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!!
}
}
我认为使用链式变量实现的最重要的事情是:当你有一个实体时,说 Job A 并且求解器分配一个值 (job/machine)到它的变量,这不像是从 Job A 开始向前构建的链。恰恰相反。通过为 Job A 的计划变量赋值,Job A 连接到现有链的末端。
请查看 documentation 以查找有关链和有效链示例的更多详细信息。
通过理解这一点,应该清楚 Job
的计划变量名称应该类似于 previousJobOrMachine
(您可能想要更简单的名称,例如 previousStep
)而 nextJob
属性 是从中派生的反向关系影子变量(因此当 Job X 连接到以 Job 结尾的现有链C赋值Job X.previousStep=Job C,自动建立反关系:Job C .nextJob=工作 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
。
您的域与 vehicle routing domain 非常相似,您可以在其中看到链接的工作示例。充分理解链接原则后,您应该能够在您的域中复制它。