Search code examples
javaquarkusoptaplannertimefold

How to create a model that assigns a time, employee, and equipment to a job?


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?


Solution

  • 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.