我有以下内容:
事实“工作”:
public class Job {
String name;
long duration;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getDuration() {
return duration;
}
public void setDuration(long duration) {
this.duration = duration;
}
}
事实“机器”:
public class Machine {
String name;
long capacity;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getCapacity() {
return capacity;
}
public void setCapacity(long capacity) {
this.capacity = capacity;
}
}
规划实体:
@PlanningEntity
public class Assignment {
Job job;
Machine machine;
@PlanningVariable(nullable = true, valueRangeProviderRefs = { "jobRange" })
public Job getJob() {
return job;
}
public void setJob(Job job) {
this.job = job;
}
@PlanningVariable(nullable = true, valueRangeProviderRefs = { "machineRange" })
public Machine getMachine() {
return machine;
}
public void setMachine(Machine machine) {
this.machine = machine;
}
}
解决方案:
public class Schedule implements Solution<BendableScore> {
private BendableScore score;
private ArrayList<Job> jobs;
private ArrayList<Machine> machines;
private ArrayList<Assignment> assignments = new ArrayList<>();
private final long CAPACITY = 4;
private final long DURATION = 1;
private final int JOBS = 4;
private final int MACHINES = 1;
@Override
public BendableScore getScore() {
return this.score;
}
@Override
public void setScore(BendableScore score) {
this.score = score;
}
@Override
public Collection<? extends Object> getProblemFacts() {
return new ArrayList<>();
}
@ValueRangeProvider(id = "jobRange")
public ArrayList<Job> getJobs() {
return jobs;
}
public void setJobs(ArrayList<Job> jobs) {
this.jobs = jobs;
}
@ValueRangeProvider(id = "machineRange")
public ArrayList<Machine> getMachines() {
return machines;
}
public void setMachines(ArrayList<Machine> machines) {
this.machines = machines;
}
@PlanningEntityCollectionProperty
public ArrayList<Assignment> getAssignments() {
return assignments;
}
public void setAssignments(ArrayList<Assignment> assignments) {
this.assignments = assignments;
}
private void addMachines() {
machines = new ArrayList<Machine>();
for (int i = 0; i < MACHINES; i++) {
Machine m = new Machine();
m.name = "Machine " + i;
m.capacity = CAPACITY;
machines.add(m);
}
}
private void addOperations() {
jobs = new ArrayList<>();
for (int i = 0; i < JOBS; i++) {
Job job = new Job();
job.name = "Job " + i;
job.duration = DURATION;
jobs.add(job);
}
}
private void addAssignments() {
for (Job job : jobs) {
for (Machine m : machines) {
Assignment a = new Assignment();
a.setJob(job);
a.setMachine(m);
assignments.add(a);
}
}
}
public static void main(String[] args) {
final Schedule s = new Schedule();
s.addMachines();
s.addOperations();
s.addAssignments();
SolverFactory solverFactory = SolverFactory
.createFromXmlResource("mauro/test2/domain/mauro.xml");
final Solver solver = solverFactory.buildSolver();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
solver.solve(s);
}
});
t.start();
try {
t.join(12000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (t.isAlive()) {
solver.terminateEarly();
}
Schedule sol = (Schedule) solver.getBestSolution();
for (Assignment a : sol.getAssignments()) {
if (a.getMachine() == null) {
System.out.println("Assignment without machine");
continue;
}
if (a.getJob() == null) {
System.out.println("Assignment without job");
continue;
}
Machine m = a.getMachine();
Job job = a.getJob();
System.out.println("Job " + job.name + " on machine " + m.name );
}
}
}
配置xml
<?xml version="1.0" encoding="UTF-8"?>
<solver>
<environmentMode>FULL_ASSERT</environmentMode>
<solutionClass>mauro.test2.domain.Schedule</solutionClass>
<entityClass>mauro.test2.domain.Assignment</entityClass>
<!-- Score configuration -->
<scoreDirectorFactory>
<scoreDefinitionType>BENDABLE</scoreDefinitionType>
<bendableHardLevelsSize>2</bendableHardLevelsSize>
<bendableSoftLevelsSize>2</bendableSoftLevelsSize>
<easyScoreCalculatorClass>mauro.test2.domain.ScheduleEasyScoreCalculator</easyScoreCalculatorClass>
</scoreDirectorFactory>
<!-- Optimization algorithms configuration -->
<constructionHeuristic>
<constructionHeuristicType>CHEAPEST_INSERTION</constructionHeuristicType>
</constructionHeuristic>
<localSearch>
<termination>
<secondsSpentLimit>10</secondsSpentLimit>
<unimprovedStepCountLimit>500</unimprovedStepCountLimit>
</termination>
<unionMoveSelector>
<changeMoveSelector>
<cacheType>PHASE</cacheType>
<selectionOrder>SHUFFLED</selectionOrder>
<valueSelector>
<variableName>machine</variableName>
</valueSelector>
<entitySelector>
<filterClass>mauro.test2.domain.MachineChangeMoveFilter</filterClass>
</entitySelector>
</changeMoveSelector>
<changeMoveSelector>
<cacheType>PHASE</cacheType>
<selectionOrder>SHUFFLED</selectionOrder>
<valueSelector>
<variableName>job</variableName>
</valueSelector>
<entitySelector>
<filterClass>mauro.test2.domain.MachineChangeMoveFilter</filterClass>
</entitySelector>
</changeMoveSelector>
</unionMoveSelector>
<acceptor>
<lateAcceptanceSize>400</lateAcceptanceSize>
<entityTabuSize>7</entityTabuSize>
</acceptor>
<forager>
<acceptedCountLimit>100</acceptedCountLimit>
</forager>
</localSearch>
</solver>
ScoreCalculator:
public class ScheduleEasyScoreCalculator implements
EasyScoreCalculator<Schedule> {
public Score<?> calculateScore(Schedule schedule) {
int hardScore1 = 0;
int softScore = 0;
HashMap<Machine, Long> loads = new HashMap<Machine, Long>();
for (Assignment a : schedule.getAssignments()) {
Machine m = a.getMachine();
Job job = a.getJob();
if (m != null && job != null) {
if (loads.containsKey(m)) {
loads.put(m, loads.get(m) + job.duration);
} else {
loads.put(m, job.duration);
}
softScore += job.duration;
}
}
for (Machine m : loads.keySet()) {
Long load = loads.get(m);
if (load > m.capacity) {
hardScore1 -= (load - m.capacity);
}
}
HashMap<Job, Integer> jobAssignments = new HashMap<>();
for (Assignment a : schedule.getAssignments()) {
if (a.getJob() != null) {
if (jobAssignments.containsKey(a.getJob())) {
jobAssignments.put(a.getJob(),
jobAssignments.get(a.getJob()) + 1);
} else {
jobAssignments.put(a.getJob(), 1);
}
}
}
int hardScore2 = 0;
for (Job job : jobAssignments.keySet()) {
if (jobAssignments.get(job) > 1) {
hardScore2 -= jobAssignments.get(job);
}
}
return BendableScore.valueOf(new int[] { hardScore1, hardScore2 },
new int[] { 0, softScore });
}
}
MoveFilter:
public class MachineChangeMoveFilter implements SelectionFilter<Assignment> {
public boolean accept(ScoreDirector scoreDirector, ChangeMove selection) {
return true;
}
@Override
public boolean accept(ScoreDirector scoreDirector, Assignment selection) {
if (selection.getMachine() != null && selection.getJob() != null
&& !selection.getJob().name.contains("1")) {
System.out.println("assignment " + selection.getMachine().getName()
+ " " + selection.getJob().getName() + " accepted");
return true;
}
System.out.println("assignment " + selection.getMachine().getName()
+ " " + selection.getJob().getName() + " NOT accepted");
return false;
}
}
如果我运行求解器,我会得到“作业1”的作业。 当然,我可以从问题事实中删除“作业1”,但在实际情况下,我不接受具有某些阴影变量值的作业。 怎么了? 感谢
莫罗
答案 0 :(得分:0)
您的实体类Assignment只有计划变量字段,这是非常奇怪的(可能是一个错误)。
@PlanningEntity
public class Assignment {
Job job; // @PlanningVariable - Probably should NOT be one
Machine machine; // @PlanningVariable
}
通常,总是(至少)1个字段唯一地定义实体和1个(或更多)规划变量。请参阅optaplanner示例,例如MachineReassignment。