166 lines
4.3 KiB
Go
166 lines
4.3 KiB
Go
package scheduler
|
|||
|
|
|
||
|
|
import "sort"
|
||
|
|
|
||
|
|
// PolicyEngine 策略引擎——对候选任务排序,决定执行顺序。
|
||
|
|
// 只管"先做哪个",不管"做什么"(生成由 TaskGenerator 负责),
|
||
|
|
// 也不管"能不能做"(过滤由 ConstraintFilter 负责)。
|
||
|
|
type PolicyEngine interface {
|
||
|
|
Rank(candidates []CandidateTask, state SystemState) []CandidateTask
|
||
|
|
}
|
||
|
|
|
||
|
|
// RankingRule 排序规则——比较两个候选任务的优先级。
|
||
|
|
// 返回 -1 表示 a 优先,1 表示 b 优先,0 表示相等。
|
||
|
|
type RankingRule func(a, b CandidateTask, state SystemState) int
|
||
|
|
|
||
|
|
// PriorityPolicy 基于优先级规则的策略引擎
|
||
|
|
type PriorityPolicy struct {
|
||
|
|
rules []RankingRule
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewPriorityPolicy(rules ...RankingRule) *PriorityPolicy {
|
||
|
|
return &PriorityPolicy{rules: rules}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (p *PriorityPolicy) Rank(candidates []CandidateTask, state SystemState) []CandidateTask {
|
||
|
|
if len(candidates) <= 1 {
|
||
|
|
return candidates
|
||
|
|
}
|
||
|
|
|
||
|
|
sorted := make([]CandidateTask, len(candidates))
|
||
|
|
copy(sorted, candidates)
|
||
|
|
|
||
|
|
sort.SliceStable(sorted, func(i, j int) bool {
|
||
|
|
for _, rule := range p.rules {
|
||
|
|
if cmp := rule(sorted[i], sorted[j], state); cmp != 0 {
|
||
|
|
return cmp < 0
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false
|
||
|
|
})
|
||
|
|
|
||
|
|
return sorted
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- 内置排序规则 ---
|
||
|
|
|
||
|
|
// BasePriorityRule 基础优先级排序(数值越小越优先)
|
||
|
|
func BasePriorityRule(a, b CandidateTask, _ SystemState) int {
|
||
|
|
if a.Priority < b.Priority {
|
||
|
|
return -1
|
||
|
|
}
|
||
|
|
if a.Priority > b.Priority {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
// JobIDSmallerFirstRule 工件 ID 小的优先(FIFO 公平性)
|
||
|
|
func JobIDSmallerFirstRule(a, b CandidateTask, _ SystemState) int {
|
||
|
|
if a.JobID < b.JobID {
|
||
|
|
return -1
|
||
|
|
}
|
||
|
|
if a.JobID > b.JobID {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
// UnloadFirstRule 卸料优先于装料(避免机床堵塞)
|
||
|
|
func UnloadFirstRule(a, b CandidateTask, _ SystemState) int {
|
||
|
|
aIsUnload := a.Action.IsUnload()
|
||
|
|
bIsUnload := b.Action.IsUnload()
|
||
|
|
if aIsUnload && !bIsUnload {
|
||
|
|
return -1
|
||
|
|
}
|
||
|
|
if !aIsUnload && bIsUnload {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
// ExchangeFirstRule exchange 任务优先于普通装/卸料
|
||
|
|
func ExchangeFirstRule(a, b CandidateTask, _ SystemState) int {
|
||
|
|
aIsExchange := a.Action == ActionExchange
|
||
|
|
bIsExchange := b.Action == ActionExchange
|
||
|
|
if aIsExchange && !bIsExchange {
|
||
|
|
return -1
|
||
|
|
}
|
||
|
|
if !aIsExchange && bIsExchange {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
// LaterStageUnloadFirstRule 越靠后工序的下料越优先(避免下游设备堵塞)
|
||
|
|
func LaterStageUnloadFirstRule(a, b CandidateTask, _ SystemState) int {
|
||
|
|
aIsUnload := a.Action.IsUnload()
|
||
|
|
bIsUnload := b.Action.IsUnload()
|
||
|
|
if aIsUnload && bIsUnload {
|
||
|
|
if a.StepIndex > b.StepIndex {
|
||
|
|
return -1
|
||
|
|
}
|
||
|
|
if a.StepIndex < b.StepIndex {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
// LaterStageLoadFirstRule 越靠后工序的上料越优先(缩短整体完工时间)
|
||
|
|
func LaterStageLoadFirstRule(a, b CandidateTask, _ SystemState) int {
|
||
|
|
aIsLoad := a.Action.IsLoad()
|
||
|
|
bIsLoad := b.Action.IsLoad()
|
||
|
|
if aIsLoad && bIsLoad {
|
||
|
|
if a.StepIndex > b.StepIndex {
|
||
|
|
return -1
|
||
|
|
}
|
||
|
|
if a.StepIndex < b.StepIndex {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
// IdleMachineLoadFirstRule 向空闲设备装料优先于向忙碌/有料设备装料
|
||
|
|
// (避免机器等人——空闲设备的 Load 任务提到前面,不让机器停下来)
|
||
|
|
func IdleMachineLoadFirstRule(a, b CandidateTask, state SystemState) int {
|
||
|
|
aPriority := a.Action.IsLoad() && a.TargetID > 0 &&
|
||
|
|
!state.MachineBusy[a.TargetID] && state.MachineHasJob[a.TargetID] == 0
|
||
|
|
bPriority := b.Action.IsLoad() && b.TargetID > 0 &&
|
||
|
|
!state.MachineBusy[b.TargetID] && state.MachineHasJob[b.TargetID] == 0
|
||
|
|
if aPriority && !bPriority {
|
||
|
|
return -1
|
||
|
|
}
|
||
|
|
if !aPriority && bPriority {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
// SamplingFirstRule 抽检任务优先——抽检台阻塞后续工序,需优先处理
|
||
|
|
func SamplingFirstRule(a, b CandidateTask, _ SystemState) int {
|
||
|
|
aIsSampling := a.Action == ActionLoadSampling || a.Action == ActionUnloadSampling
|
||
|
|
bIsSampling := b.Action == ActionLoadSampling || b.Action == ActionUnloadSampling
|
||
|
|
if aIsSampling && !bIsSampling {
|
||
|
|
return -1
|
||
|
|
}
|
||
|
|
if !aIsSampling && bIsSampling {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
// SameMachineRule 同一 CNC 的任务优先排在一起(减少机器人移动)
|
||
|
|
func SameMachineRule(a, b CandidateTask, _ SystemState) int {
|
||
|
|
if a.TargetID != 0 && b.TargetID != 0 {
|
||
|
|
if a.TargetID < b.TargetID {
|
||
|
|
return -1
|
||
|
|
}
|
||
|
|
if a.TargetID > b.TargetID {
|
||
|
|
return 1
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|