Optaplanner 7.9.0 和添加多线程:相同的 planningId 异常

Optaplanner 7.9.0 and Adding Multithreading: same planningId exception

我有一个 optaplanner 项目已经工作了一段时间,它使用 java 中编写的各种评分属性将工作分配给工人列表。对它的工作方式感到满意,我决定从 7.7.0 更新到 7.9.0 并打开新的多线程选项,看看它是否运行得更快。但是,我现在收到以下错误:

线程异常"Thread-8" java.lang.IllegalStateException: moveThreadIndex (0) 的移动线程抛出异常。在父线程中中继到这里。 Caused by: java.lang.IllegalArgumentException: 无法查找外部对象 (...Worker@72d2327a)。 也许给 class (class Worker) 一个 PlanningId 注释或更改 PlanningSolution 注释的 LookUpStrategyType 或不依赖依赖于 ScoreDirector.lookUpWorkingObject().[= 的功能11=]

所以我尝试将@PlanningId 添加到工作人员的唯一标识符 class 并且我得到:

线程异常"Thread-7" java.lang.IllegalStateException:工作对象(Worker@4438b624,Worker@4438b624)具有相同的planningId((class Worker,50) ).工作对象必须是唯一的。

...不过看起来是在比较一个Worker对象和自己,所以当然是同一个id了????

也许这归结于我在 assign/unassign 方法中的 java 代码,但我不明白这个问题是从哪里来的,有人有什么想法吗?

编辑: 因此,在@n1ck 的大量帮助之后,我得到了改变@PlanningSolution class 中的方法,returns Workers 列表每次都创建新实例但具有相同的值。这会将错误更改为:'...The workingObjects (Worker@1eba2b4d, Worker@67a7ef08) have the same planningId...' 所以它不再比较相同的实例但确实似乎是将它与之前调用的实例进行比较。然而,这至少确认每个返回的列表没有重复。因此,我随后将计划 ID 更改为一个新的(长)字段,其值始终从最后创建的实例开始递增,即第一次调用 Worker id 为 1-10,接下来调用 11-20,依此类推。这完全绕过了错误,但现在没有任何东西分配给工人。它进行初始设置和空分配,然后停止,直到达到求解器的时间限制。我仍然认为这是我没有设置正确的地方,但错误可能有点转移注意力,但是根据要求,我看到的完整堆栈跟踪是:

线程异常"Thread-10" java.lang.IllegalStateException:工作对象(Worker@42094cc1,Worker@647a1c5c)具有相同的planningId((class Worker,50) ).工作对象必须是唯一的。 在 org.optaplanner.core.impl.domain.lookup.PlanningIdLookUpStrategy.addWorkingObject(PlanningIdLookUpStrategy.java:40) 在 org.optaplanner.core.impl.domain.lookup.LookUpManager.addWorkingObject(LookUpManager.java:49) 在 org.optaplanner.core.impl.domain.lookup.LookUpManager.resetWorkingObjects(LookUpManager.java:43) 在 org.optaplanner.core.impl.score.director.AbstractScoreDirector.setWorkingSolution(AbstractScoreDirector.java:167) 在 org.optaplanner.core.impl.score.director.incremental.IncrementalScoreDirector.setWorkingSolution(IncrementalScoreDirector.java:62) 在 org.optaplanner.core.impl.solver.scope.DefaultSolverScope.setWorkingSolutionFromBestSolution(DefaultSolverScope.java:230) 在 org.optaplanner.core.impl.solver.AbstractSolver.solvingStarted(AbstractSolver.java:75) 在 org.optaplanner.core.impl.solver.DefaultSolver.solvingStarted(DefaultSolver.java:210) 在 org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:190) 在 SolverThread.run(SolverThread.java:86)

编辑:@PlanningSolution class 根据要求:

package code.test.scheduler;

import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty;
import org.optaplanner.core.api.domain.solution.PlanningScore;
import org.optaplanner.core.api.domain.solution.PlanningSolution;
import org.optaplanner.core.api.domain.solution.drools.ProblemFactCollectionProperty;
import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider;
import org.optaplanner.core.api.score.buildin.hardmediumsoft.HardMediumSoftScore;
import org.optaplanner.persistence.xstream.api.score.buildin.hardmediumsoft.HardMediumSoftScoreXStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamConverter;

@PlanningSolution
public class Planner
{       
@ProblemFactCollectionProperty
private java.util.List<Worker> _workerList;
@ValueRangeProvider(id="workerRange")
@ProblemFactCollectionProperty
public java.util.List<Worker> getWorkerList() {
    return _workerList;
}
public void setWorkerList(java.util.List<Worker> newWorkerList) {
    _workerList = newWorkerList;
}
public int getWorkerListSize() {
    return _workerList.size();
}

@ProblemFactCollectionProperty
private int[][] _travelTimes;
@ValueRangeProvider(id="travelTimes")
@ProblemFactCollectionProperty
public int[][] getTravelTimes() {
    return _travelTimes;
}
public void setTravelTimes(int[][] newTravelTimes) {
    _travelTimes = newTravelTimes;
}

@PlanningEntityCollectionProperty
private java.util.List<Job> _jobList;
public java.util.List<Job> getJobList() {
    return _jobList;        
}
public void setJobList(java.util.List<Job> newJobList) {
    _jobList = newJobList;
}

@XStreamConverter(HardMediumSoftScoreXStreamConverter.class)
private HardMediumSoftScore _score;

@PlanningScore
public HardMediumSoftScore getScore() {
    return _score;
}

public void setScore(HardMediumSoftScore score) {
    _score = score;     
}
}

我认为您的 PlanningEntityCollection 中有一些重复的实体。您确定此列表中的所有 Worker 对象都是唯一的(例如,不是同一实例)?

我故意在我的实体集合中复制了一个实体,但得到了同样的错误。

编辑:原来问题是在字段和 getter 上方声明了 @ProblemFactCollectionProperty 注释。它应该只在一个或另一个之上声明。在字段和 getter 之上声明它,并结合使用 @PlanningId 注释,将导致 'Working objects must be unique' 错误。