Fixiaobai
2023-11-17 2fb28b36f15de26249ae34160e1accf118c011c7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package com.chinaztt.mes.aps.core.solver;
 
import cn.hutool.core.collection.CollUtil;
import com.chinaztt.mes.aps.core.domain.Task;
import com.chinaztt.mes.aps.core.helper.ApsConstraintHelper;
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
import org.optaplanner.core.api.score.stream.Constraint;
import org.optaplanner.core.api.score.stream.ConstraintFactory;
import org.optaplanner.core.api.score.stream.ConstraintProvider;
 
import java.time.Duration;
 
 
/**
 * @Author: zhangxy
 * @Date: 2020-10-20 10:26
 */
public class ApsConstraintProvider implements ConstraintProvider {
    @Override
    public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
        return new Constraint[]{
                capabilityConflict(constraintFactory),
                timeOverlapConflict(constraintFactory),
                delayConflict(constraintFactory),
                firstDelayConflict(constraintFactory),
        };
    }
 
 
    /**
     * 第一道工序开工越快越好
     *
     * @param constraintFactory
     * @return
     */
    private Constraint firstDelayConflict(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Task.class)
                .filter(t -> {
                    if (t.getPredecessorOfRouting() == null && t.getResourceBo() != null) {
                        if (t.getPlanStartTime().compareTo(t.getResourceBo().getPlanEndTime()) > 0) {
                            return true;
                        }
                    }
                    return false;
                })
                .penalize("Start delay conflict", HardSoftScore.ONE_SOFT, (t) ->
                        {
                            Duration duration = Duration.between(t.getResourceBo().getPlanEndTime(), t.getPlanStartTime());
                            return (int) duration.toMinutes();
                        }
                );
    }
 
 
    /**
     * 工序间尽量减少等待时间
     *
     * @param constraintFactory
     * @return
     */
    private Constraint delayConflict(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Task.class)
                .filter(t -> {
                    if (t.getPredecessorOfRouting() != null && t.getPlanStartTime() != null) {
                        if ((t.getPlanStartTime().compareTo(t.getPredecessorOfRouting().getPlanEndTime())) > 0) {
                            return true;
                        }
                    }
                    return false;
                })
                .penalize("Delay conflict", HardSoftScore.ONE_SOFT, (t) -> {
                    Duration duration = Duration.between(t.getPredecessorOfRouting().getPlanEndTime(), t.getPlanStartTime());
                    return (int) duration.toMinutes();
                });
    }
 
    /**
     * 工序、资源能力必须匹配
     *
     * @param constraintFactory
     * @return
     */
    private Constraint capabilityConflict(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Task.class)
                .filter(t -> {
                    if (t.getResourceBo() == null) {
                        return false;
                    }
                    if (CollUtil.isEmpty(t.getResourceBo().getCapabilityIds())) {
                        return true;
                    } else {
                        return !t.getResourceBo().getCapabilityIds().containsAll(t.getCapabilityIds());
                    }
                })
                .penalize("Capability conflict", HardSoftScore.ofHard(10));
    }
 
 
    /**
     * 任务不能重合
     *
     * @param constraintFactory
     * @return
     */
    private Constraint timeOverlapConflict(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Task.class)
                .join(Task.class)
                .filter((t1, t2) -> ApsConstraintHelper.taskOverlap(t1, t2))
                .penalize("Time conflict", HardSoftScore.ONE_HARD);
    }
 
 
}