当前位置: 首页 > 知识库问答 >
问题:

由于groupBy操作,OptaPlanner中出现ClassCastException

余阳秋
2023-03-14

我正在创建一个学校时间表生成器,我从我的一个约束中获得了一个例外,该约束检查所有学生每天都有午休时间。

我正在使用约束流JavaAPI。我的约束编译(显然)如下所示:

public Constraint studentsShouldHaveLunchEveryDay(ConstraintFactory cf) {
    return cf.from(RecurringLecture.class)
            .filter(RecurringLecture::isScheduled)                     // [Lecture]...
            .groupBy(l -> l, l -> l.getCourseRound().getStudents())    // [Lecture, Set<Student>]...
            .flattenLast(students -> students)                         // [Lecture, Student]...
            .groupBy((l, s) -> s,                                      // [Student, Map<Day, Set<Lecture>>]...
                    ConstraintCollectors.toMap(
                            (l, s) -> l.getStartTimeslot().getDay(),
                            (l, s) -> l))
            //.flattenLast(Map::values)                                // [Student, Set<Lecture>]...
            //.filter((student, dailyLectures) -> !LunchBreakAnalyzer.hasLunchBreak(dailyLectures))
            .penalize(StudentLunchProblem.class.getName(), HardSoftScore.ONE_HARD);
}

出于调试原因,我暂时注释掉了flattenLastfilter,问题仍然会重现。不过,如果我注释掉最后一个groupBy,问题似乎不会重现。

出于某种原因,该框架试图将学生准确地说是ImMutable学生)强制转换为Object[]

框架中抛出的行位于arrayelementrader中,如下所示:

public Object getValue(InternalWorkingMemory workingMemory,
                       Object object) {
    Object[] array = (Object[]) this.arrayReadAccessor.getValue( workingMemory,
                                                                 object );
    return array[this.index];
}

完整的例外如下所示:

java.util.concurrent.ExecutionException: java.lang.IllegalStateException: The move thread with moveThreadIndex (1) has thrown an exception. Relayed here in the parent thread.
    at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
    at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
    at java.desktop/javax.swing.SwingWorker.get(SwingWorker.java:613)
    at vngschedules.ui.automation.AutomationPanel$1$1.done(AutomationPanel.java:44)
    at java.desktop/javax.swing.SwingWorker$5.run(SwingWorker.java:750)
    at java.desktop/javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(SwingWorker.java:847)
    at java.desktop/sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:112)
    at java.desktop/javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(SwingWorker.java:857)
    at java.desktop/javax.swing.Timer.fireActionPerformed(Timer.java:317)
    at java.desktop/javax.swing.Timer$DoPostEvent.run(Timer.java:249)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Caused by: java.lang.IllegalStateException: The move thread with moveThreadIndex (1) has thrown an exception. Relayed here in the parent thread.
    at org.optaplanner.core.impl.heuristic.thread.OrderByMoveIndexBlockingQueue.take(OrderByMoveIndexBlockingQueue.java:147)
    at org.optaplanner.core.impl.localsearch.decider.MultiThreadedLocalSearchDecider.forageResult(MultiThreadedLocalSearchDecider.java:189)
    at org.optaplanner.core.impl.localsearch.decider.MultiThreadedLocalSearchDecider.decideNextStep(MultiThreadedLocalSearchDecider.java:160)
    at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.solve(DefaultLocalSearchPhase.java:95)
    at org.optaplanner.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:99)
    at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:192)
Caused by: java.lang.IllegalStateException: The move thread with moveThreadIndex (1) has thrown an exception. Relayed here in the parent thread.

    at vngschedules.ui.automation.SolverSwingWorker.doInBackground(SolverSwingWorker.java:29)
    at vngschedules.ui.automation.SolverSwingWorker.doInBackground(SolverSwingWorker.java:10)
    at java.desktop/javax.swing.SwingWorker$1.call(SwingWorker.java:304)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.desktop/javax.swing.SwingWorker.run(SwingWorker.java:343)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.ClassCastException: class vngschedules.schedule.ImmutableStudent cannot be cast to class [Ljava.lang.Object; (vngschedules.schedule.ImmutableStudent is in unnamed module of loader 'app'; [Ljava.lang.Object; is in module java.base of loader 'bootstrap')
    at org.drools.core.base.extractors.ArrayElementReader.getValue(ArrayElementReader.java:162)
    at org.drools.core.base.extractors.ArrayElementReader.getValue(ArrayElementReader.java:279)
    at org.drools.modelcompiler.KiePackagesBuilder.lambda$getBindingFunction$66de2761$1(KiePackagesBuilder.java:794)
    at org.drools.modelcompiler.constraints.LambdaReadAccessor.getValue(LambdaReadAccessor.java:43)
    at org.drools.core.rule.Declaration.getValue(Declaration.java:257)
    at org.optaplanner.core.impl.score.stream.drools.common.AbstractAccumulator.extractValue(AbstractAccumulator.java:42)
Caused by: java.lang.ClassCastException: class vngschedules.schedule.ImmutableStudent cannot be cast to class [Ljava.lang.Object; (vngschedules.schedule.ImmutableStudent is in unnamed module of loader 'app'; [Ljava.lang.Object; is in module java.base of loader 'bootstrap')

    at org.optaplanner.core.impl.score.stream.drools.common.BiAccumulator.accumulate(BiAccumulator.java:55)
    at org.drools.core.rule.SingleAccumulate.accumulate(SingleAccumulate.java:96)
    at org.drools.modelcompiler.constraints.LambdaGroupByAccumulate.accumulate(LambdaGroupByAccumulate.java:121)
    at org.drools.modelcompiler.constraints.LambdaGroupByAccumulate.accumulate(LambdaGroupByAccumulate.java:114)
    at org.drools.core.phreak.PhreakAccumulateNode.addMatch(PhreakAccumulateNode.java:736)
    at org.drools.core.phreak.PhreakAccumulateNode.doRightInserts(PhreakAccumulateNode.java:253)
    at org.drools.core.phreak.PhreakAccumulateNode.doNode(PhreakAccumulateNode.java:99)
    at org.drools.core.phreak.RuleNetworkEvaluator.switchOnDoBetaNode(RuleNetworkEvaluator.java:586)
    at org.drools.core.phreak.RuleNetworkEvaluator.evalBetaNode(RuleNetworkEvaluator.java:555)
    at org.drools.core.phreak.RuleNetworkEvaluator.evalNode(RuleNetworkEvaluator.java:382)
    at org.drools.core.phreak.RuleNetworkEvaluator.innerEval(RuleNetworkEvaluator.java:342)
    at org.drools.core.phreak.RuleNetworkEvaluator.evalStackEntry(RuleNetworkEvaluator.java:240)
    at org.drools.core.phreak.RuleNetworkEvaluator.outerEval(RuleNetworkEvaluator.java:183)
    at org.drools.core.phreak.RuleNetworkEvaluator.evaluateNetwork(RuleNetworkEvaluator.java:136)
    at org.drools.core.phreak.RuleExecutor.reEvaluateNetwork(RuleExecutor.java:235)
    at org.drools.core.phreak.RuleExecutor.evaluateNetworkAndFire(RuleExecutor.java:91)
    at org.drools.core.concurrent.AbstractRuleEvaluator.internalEvaluateAndFire(AbstractRuleEvaluator.java:33)
    at org.drools.core.concurrent.SequentialRuleEvaluator.evaluateAndFire(SequentialRuleEvaluator.java:43)
    at org.drools.core.common.DefaultAgenda.fireLoop(DefaultAgenda.java:869)
    at org.drools.core.common.DefaultAgenda.internalFireAllRules(DefaultAgenda.java:816)
    at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:808)
    at org.drools.core.impl.StatefulKnowledgeSessionImpl.internalFireAllRules(StatefulKnowledgeSessionImpl.java:1343)
    at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1334)
    at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1326)
    at org.optaplanner.core.impl.score.director.stream.DroolsConstraintStreamScoreDirector.calculateScore(DroolsConstraintStreamScoreDirector.java:90)
    at org.optaplanner.core.impl.score.director.AbstractScoreDirector.doAndProcessMove(AbstractScoreDirector.java:220)
    at org.optaplanner.core.impl.heuristic.thread.MoveThreadRunner.run(MoveThreadRunner.java:147)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    ... 3 more

我已经注释掉了程序中的所有其他约束流。

  1. 这看起来像是我的代码中的错误,还是OptaPlanner的问题

如果需要的话,我们很乐意提供更多类型,但递归结构实际上非常简单,而且学生是编译成不可变学生的不可变接口。

我正在使用OptaPlanner 8.12.0.Final和Java 11。

我尝试按如下方式重写约束流:

public Constraint studentsShouldHaveLunchEveryDay(ConstraintFactory cf) {
    return cf.from(RecurringLecture.class)
            .filter(RecurringLecture::isScheduled)                     // [Lecture]...
            .groupBy(l -> l, l -> l.getCourseRound().getStudents())    // [Lecture, Set<Student>]...
            .flattenLast(students -> students)                         // [Lecture, Student]...
            .groupBy((l, s) -> ImmutableStudentAndDay.of(s, l.getStartTimeslot().getDay()),
                    ConstraintCollectors.toSet((l, s) -> l))
            .filter((student, dailyLectures) -> !LunchBreakAnalyzer.hasLunchBreak(dailyLectures))
            .penalize(StudentLunchProblem.class.getName(), HardSoftScore.ONE_HARD);
}

这样可以避免使用toMap采集器。然而,我仍然遇到了完全相同的问题。

共有1个答案

谷梁鸣
2023-03-14

一般来说,如果您的约束编译并且代码在运行时仍然抛出ClassCastException,您应该期望错误在OptaPlanner端。除非您愿意查看Drools可执行模型,否则您在那里没有什么可调试的。

我建议重构约束,使其看起来像这样:

public Constraint studentsShouldHaveLunchEveryDay(ConstraintFactory cf) {
    return cf.from(RecurringLecture.class)
        .filter(RecurringLecture::isScheduled)
        .join(Student.class,
              Joiners.filtering((l, s) -> l.getCourseRound().getStudents().contains(s)))
        .groupBy((l, s) -> ImmutableStudentAndDay.of(s, l.getStartTimeslot().getDay()),
                ConstraintCollectors.toSet((l, s) -> l))
        .filter((student, dailyLectures) -> !LunchBreakAnalyzer.hasLunchBreak(dailyLectures))
        .penalize(StudentLunchProblem.class.getName(), HardSoftScore.ONE_HARD);
}

我希望这会表现得更好,也可能会消除这个异常。无论如何,异常仍然是一个问题,如果您提供简化的可执行复制程序,我将进一步调查它。

 类似资料:
  • 我有一个java方法可以从所有不遵循给定首选项的TeamCalendar对象(pinned=true的规划实体)中创建constraintstream。 因此,我希望有一个约束流,表示每个部门存在多少这些差异。这是java代码: 在调试模式下运行时,第一个过滤器(tc- 我尝试了一些琐碎的选择: . groupBy(tc- 以及计数方法的替代方案: 。groupBy(TeamCalendar::g

  • 我试图解决一个调度问题,它围绕着以下安排: 是否可以使用和实现约束?我尝试过以下路线: 我认为应该没有问题,但不确定如何获得这个来实现我想要的。这里是否需要?还是有一个不同的、更好的整体方法? 作为参考,ShiftAssignment类可以很容易地拥有如下所示的方法:

  • GroupBy 将一个Observable分拆为一些Observables集合,它们中的每一个发射原始Observable的一个子序列 GroupBy操作符将原始Observable分拆为一些Observables集合,它们中的每一个发射原始Observable数据序列的一个子序列。哪个数据项由哪一个Observable发射是由一个函数判定的,这个函数给每一项指定一个Key,Key相同的数据会被同

  • 主要内容:创建DataFrame对象,创建groupby分组对象,查看分组结果,遍历分组数据,应用聚合函数,组的转换操作,组的数据过滤操作在数据分析中,经常会遇到这样的情况:根据某一列(或多列)标签把数据划分为不同的组别,然后再对其进行数据分析。比如,某网站对注册用户的性别或者年龄等进行分组,从而研究出网站用户的画像(特点)。在 Pandas 中,要完成数据的分组操作,需要使用 groupby() 函数,它和 SQL 的 操作非常相似。  在划分出来的组(group)上应用一些统计函数,从而达到

  • 我一直在尝试在android上编写一个简单的笔记应用程序。我想在主要活动的操作栏中显示一个“添加”按钮。然而,它只显示为溢出。我试过了 但是我不能运行这个应用程序,因为Android Studio告诉我 应将app:showAsAction与带有xmlns:app=”的appcompat库一起使用http://schemas.android.com/apk/res-auto" 有什么想法吗?据我所

  • 问题内容: 我已经从Rich Faces 3.3升级到Rich Faces 4.2,因为Ajax不适用于IE9。现在它仍然不起作用。 收到响应后,IE会收到一个JS错误 “ SCRIPT58734:从源头上来的东西”:c00ce56e。 在尝试时 在jsf.js.html?ln = javax.faces&conversationContext = 2,第1行第21747行 我认为是因为HTTP标