【发布时间】:2020-06-06 23:56:51
【问题描述】:
我正在尝试使用 OptaPlanner 解决问题,但程序返回给我并且解决方案为空。我已经按照这个例子来解决它:https://github.com/ge0ffrey/getting-started-guides/tree/gs-constraint-solving-ai-optaplanner/complete
我正在使用 SpringBoot JPA 集成。
这里有实现的代码:
- 规划解决方案
@PlanningSolution
public class HorarioComidas {
@ValueRangeProvider(id = "recetaRange")
@ProblemFactCollectionProperty
private List<Receta> recetaList;
@ValueRangeProvider(id = "fechaSemanaRange")
@ProblemFactCollectionProperty
private List<FechaSemana> fechaSemanaList;
@ValueRangeProvider(id = "comidaRange")
@ProblemFactCollectionProperty
private List<Comida> comidaList;
@PlanningEntityCollectionProperty
private List<UsuarioReceta> usuarioRecetas;
@PlanningScore
private HardSoftScore score;
// Ignored by OptaPlanner, used by the UI to display solve or stop solving button
private SolverStatus solverStatus;
...
}
- OptaPlanner 服务
@Service
public class OptaPlannerService {
@Autowired
private HorarioComidasService horarioComidasService;
@Autowired
private SolverManager<HorarioComidas, Usuario> solverManager;
@Autowired
private ScoreManager<HorarioComidas> scoreManager;
public HorarioComidas getTimeTable(Usuario usuario) {
// Get the solver status before loading the solution
// to avoid the race condition that the solver terminates between them
SolverStatus solverStatus = getSolverStatus(usuario);
HorarioComidas solution = horarioComidasService.findByUsuario(usuario);
scoreManager.updateScore(solution); // Sets the score
solution.setSolverStatus(solverStatus);
return solution;
}
public void solve(Usuario usuario) {
horarioComidasService.usuario = usuario;
solverManager.solveAndListen(usuario,
horarioComidasService::findByUsuario,
horarioComidasService::save);
}
public SolverStatus getSolverStatus(Usuario usuario) {
return solverManager.getSolverStatus(usuario);
}
public void stopSolving(Usuario usuario) {
solverManager.terminateEarly(usuario);
}
}
- HorarioComidaService:
@Service
public class HorarioComidasService {
@Autowired
private UsuarioRecetaService usuarioRecetaService;
@Autowired
private RecetaService recetaService;
public Usuario usuario;
public HorarioComidas findByUsuario(Usuario usuario) {
if (!usuarioRecetaService.findByUsuario(usuario).isEmpty()) {
throw new IllegalStateException("No hay una lista de comida para este usuario.");
}
// Occurs in a single transaction, so each initialized lesson references the same timeslot/room instance
// that is contained by the timeTable's timeslotList/roomList.
return new HorarioComidas(recetaService.findAll(), usuarioRecetaService.findByUsuario(usuario), Arrays.asList(FechaSemana.values()), Arrays.asList(Comida.values()));
}
public void save(HorarioComidas horarioComidas) {
for (UsuarioReceta usuarioReceta : horarioComidas.getUsuarioRecetas()) {
usuarioReceta.setUsuario(usuario);
usuarioRecetaService.create(usuarioReceta);
}
}
}
- 调用 OptaPlanner 服务的函数:
public void generarListaCompra(Usuario usuario) throws InterruptedException {
optaPlannerService.solve(usuario);
HorarioComidas horarioComidas = optaPlannerService.getTimeTable(usuario);
while (horarioComidas.getSolverStatus() != SolverStatus.NOT_SOLVING) {
// Quick polling (not a Test Thread Sleep anti-pattern)
// Test is still fast on fast machines and doesn't randomly fail on slow machines.
Thread.sleep(20L);
horarioComidas = optaPlannerService.getTimeTable(usuario);
}
}
- 约束提供者,但目前没有限制:
public class HorarioComidasConstraintProvider implements ConstraintProvider {
@Autowired
private IntoleranciaUsuarioService intoleranciaUsuarioService;
@Autowired
private IntoleranciaRecetaService intoleranciaRecetaService;
@Override
public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
return new Constraint[]{};
}
}
- 控制台返回的内容:
2020-06-04 14:12:42.186 INFO 10130 --- [ restartedMain] .ConditionEvaluationDeltaLoggingListener :
Condition evaluation unchanged
2020-06-04 14:21:37.238 INFO 10130 --- [pool-5-thread-1] o.o.core.impl.solver.DefaultSolver :
Solving started: time spent (3), best score (0hard/0soft), environment mode (REPRODUCIBLE), random (JDK with seed 0).
2020-06-04 14:21:37.239 INFO 10130 --- [pool-5-thread-1] o.o.core.impl.solver.DefaultSolver : Skipped all phases (2): out of 0 planning entities, none are movable (non-pinned).
2020-06-04 14:21:37.239 INFO 10130 --- [pool-5-thread-1] o.o.core.impl.solver.DefaultSolver : Solving ended: time spent (4), best score (0hard/0soft), score calculation speed (250/sec), phase total (2), environment mode (REPRODUCIBLE).
【问题讨论】:
-
在
horarioComidasService::save方法中放置一个断点。那里的解决方案参数是空的吗?如果是这样,请在您的horarioComidasService::findByUsuario方法中放置一个断点,那里返回的解决方案是空的吗? -
我不明白为什么函数不调用 horarioComidasService::save 方法。我添加了一个名为 horarioComidaService 的新类,但我仍然遇到同样的问题。
-
在输入和输出方法中设置断点,检查解决方案的目的是确认 optaplanner 确实做错了你认为它做错的事情。通常问题出在输入之前或输出之后的数据处理中,与 SolverManager 的工作无关。
-
目前,我不知道我能做什么,我对此非常困惑,我不知道如何解决这个问题。我一直在关注这个例子,但我现在不知道该怎么做。
-
调试时如何设置java断点:jetbrains.com/help/idea/using-breakpoints.html#
标签: java spring-data-jpa optaplanner