Context: This is my first time working with Timefold/Optaplanner, so I might have some incorrect understanding of everything.
I'm working on developing a Quarkus Timefold app using/modifying the food packaging example. The goal is to update the model to be able to assign a time, which would be based on the previous job, an employee with the required skill, and required equipment. My model currently has a Job and Line from the example, and I'm trying to add a new Employee class. However, I'm getting this error:
java.lang.IllegalArgumentException: The config (QueuedValuePlacerConfig(ValueSelectorConfig(jobs), ListChangeMoveSelectorConfig(ValueSelectorConfig(null), null))) has no entityClass configured and because there are multiple in the entityClassSet ([class org.acme.foodpackaging.domain.Line, class org.acme.foodpackaging.domain.Job]), it cannot be deduced automatically.
In the job class, I added
@PlanningVariable(valueRangeProviderRefs = "employees")
private Employee employee;
and in the PackagingSchedule class, I added
@ProblemFactCollectionProperty
@ValueRangeProvider(id = "employees")
private List<Employee> employees;
This is my employee class:
package org.acme.foodpackaging.domain;
import java.time.LocalDateTime;
import java.util.*;
public class Employee {
private Long id;
private String name;
private String operator;
private LocalDateTime startDateTime;
Set<String> skills;
// No-arg constructor required for OptaPlanner and Jackson
public Employee() {
}
public Employee(Long id, String name, String operator, LocalDateTime startDateTime) {
this.id = id;
this.name = name;
this.operator = operator;
this.startDateTime = startDateTime;
this.skills = null;
}
public Employee(Long id, String name, String operator, LocalDateTime startDateTime, Set<String> skills) {
this.id = id;
this.name = name;
this.operator = operator;
this.startDateTime = startDateTime;
this.skills = skills;
}
@Override
public String toString() {
return name;
}
// ************************************************************************
// Getters and setters
// ************************************************************************
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getOperator() {
return operator;
}
public LocalDateTime getStartDateTime() {
return startDateTime;
}
public Set<String> getSkills() { return skills; }
}
I believe this error is because the Job class, which was originally a PlanningEntity with no genuine planning variables, now contains a genuine planning variable. How do I correctly create this model?
That error message should be improved, but the issue is that currently @PlanningListVariable
cannot exist with another @PlanningVariable
or @PlanningListVariable
. The variable defined by Line
is a @PlanningListVariable
, which means no other genuine variables can be defined (as noted in the docs: https://timefold.ai/docs/timefold-solver/latest/using-timefold-solver/modeling-planning-problems#planningListVariable
Planning list variable does not yet support all the advanced planning features that work with the chained planning variable. Use a chained planning variable instead of a planning list variable, if you need any of the following planning techniques:
- overconstrained planning,
- planning entity difficulty comparison or planning value strength comparison,
- exhaustive search,
- partitioned search,
- coexistence with another list or basic planning variable.
Converting the model to chained is not trivial; essentially, Line
becomes a problem fact that acts as an anchor, and Job
becomes a planning entity that points either to a Job
or a Line
. I recommend you look at the ordering picking quickstart (https://github.com/TimefoldAI/timefold-quickstarts/tree/stable/use-cases/order-picking) for an example of creating a chained model.