By

What happens when a single application has to address a problem using distinct configurations? How can you solve two different planning problems in the same application, potentially in sequence? With two SolverManager instances, one for each problem. In the article, we’ll show you how to configure and inject two SolverManager instances in a single application.

An application may require different configurations to solve a problem or solve problem A to acquire input for solving problem B. That’s why using multiple solvers within one application becomes necessary. The Timefold Solver integrates with Quarkus and Spring Boot, making it easy to manage various solver configurations. It provides all the tools for the hassle-free configuration and utilization of distinct solvers.

In this article, we will discuss how Timefold allows us to configure multiple solver settings and explain how to use the different SolverManager instances in the application.

Distinct Solver Configurations Problem

Let’s consider a situation where we need to solve two distinct school timetabling problems:

  1. Initially, a specific group of teachers is designated to teach the available lessons.

  2. The next step involves assigning lessons to the rooms.

The first step will need a different domain model compared to the second. The file teachersConfig.xml shows the XML structure of the first step:

<solver xmlns="https://timefold.ai/xsd/solver" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="https://timefold.ai/xsd/solver https://timefold.ai/xsd/solver/solver.xsd">
  <solutionClass>org.acme.schooltimetabling.domain.TeacherToLessonSchedule</solutionClass>
  <entityClass>org.acme.schooltimetabling.domain.Teacher</entityClass>
</solver>

The following XML file, roomsConfig.xml, describes the model of the second optimization stage:

<solver xmlns="https://timefold.ai/xsd/solver" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="https://timefold.ai/xsd/solver https://timefold.ai/xsd/solver/solver.xsd">
  <solutionClass>org.acme.schooltimetabling.domain.Timetable</solutionClass>
  <entityClass>org.acme.schooltimetabling.domain.Lesson</entityClass>
</solver>

While we can manually create factories that instantiate managed resources for each problem, doing so requires boilerplate and error-prone code.

Injecting Multiple Instances of SolverManager

The Timefold Quarkus and Spring integrations provide built-in managed instances of the SolverManager resource for each problem definition identified during the configuration process. Therefore, there is no need for custom logic to instantiate managed resources when configuring multiple solver settings. Instead, named properties should be defined for each desired configuration. Let’s examine a simple example where we set the maximum amount of time spent on optimizing a single solver configuration in both Quarkus and Spring Boot:

        
# The Quarkus configuration limits the optimization time to 5 seconds
quarkus.timefold.solver.termination.spent-limit=5s
        
      
        
# The Spring Boot configuration limits the optimization time to 5 seconds
timefold.solver.termination.spent-limit=5s
        
      

Let’s add two configurations to optimize with distinct optimization time spent. One configuration runs for 5 seconds, and the other runs for 60 seconds.

        
# The Quarkus configuration solver1 limits optimization to 5 seconds.
# solver2 runs for 60 seconds.
quarkus.timefold.solver."solver1".termination.spent-limit=5s
quarkus.timefold.solver."solver2".termination.spent-limit=60s
        
      
        
# The Spring Boot configuration solver1 limits optimization to 5 seconds.
# solver2 runs for 60 seconds.
timefold.solver.solver1.termination.spent-limit=5s
timefold.solver.solver2.termination.spent-limit=60s
        
      

We can configure multiple solvers using the namespace *.timefold.solver.<solverName> and specify the named property <solverName> for each solver. It is important to note that Quarkus configuration requires properties to have a prefix quarkus and named properties enclosed in double quotes.

Solver Configuration Properties

The following properties are supported:

[quarkus].timefold.solver.<solverName>.solver-config-xml
A classpath resource to read the solver configuration XML.

[quarkus].timefold.solver.<solverName>.environment-mode
Enable runtime assertions to detect common bugs in your implementation during development.
Defaults to REPRODUCIBLE.

[quarkus].timefold.solver.<solverName>.daemon
Enable daemon mode. Defaults to false.

[quarkus].timefold.solver.<solverName>.move-thread-count
Enable multi-threaded solving for a single problem. Defaults to NONE.

[quarkus].timefold.solver.<solverName>.domain-access-type
How Timefold Solver should access the domain model. Defaults to REFLECTION.

[quarkus].timefold.solver.<solverName>.termination.spent-limit
How long the solver can run.

[quarkus].timefold.solver.<solverName>.termination.unimproved-spent-limit
How long the solver can run without finding a new best solution after finding a new best solution.

[quarkus].timefold.solver.<solverName>.termination.best-score-limit
Terminates the solver when a specific score (or better) has been reached.

Working with Multiple Solvers

When revisiting the timetabling problem discussed in Section 2, it is necessary to fill out the properties file for both Quarkus and Spring Boot for the two distinct optimization problems in the following way:

        
# Quarkus timetabling solver configurations

quarkus.timefold.solver."teacherSolver".solver-config-xml=teachersConfig.xml
quarkus.timefold.solver."roomSolver".solver-config-xml=roomsConfig.xml
        
      
        
# Spring Boot timetabling solver configurations

timefold.solver.teacherSolver.solver-config-xml=teachersConfig.xml
timefold.solver.roomSolver.solver-config-xml=roomsConfig.xml
        
      

Use the following code to inject the resources.

@Path("/path")
public class Resource {

    @Named("teacherSolver")
    SolverManager<TeacherToLessonSchedule, String> teacherToLessonScheduleSolverManager;

    @Named("roomSolver")
    SolverManager<Timetable, String> lessonToRoomTimeslotSolverManager;

    ...
}
@RestController
@RequestMapping("/path")
public class Resource {

    @Autowired
    @Qualifier("teacherSolver")
    SolverManager<TeacherToLessonSchedule, String> teacherToLessonScheduleSolverManager;

    @Autowired
    @Qualifier("roomSolver")
    SolverManager<Timetable, String> lessonToRoomTimeslotSolverManager;

    ...
}

Conclusion

We evaluated the approach necessary to set up and use multiple solver configurations within the same application. Timefold Solver offers a simple solution for defining and utilizing different solver configurations without requiring custom logic to create and inject related managed resources.

Continue reading

  • Java versus Python performance benchmarks on PlanningAI models

    Discover the techniques Timefold Engineers deploy to make your Python code faster.

  • Simplify the Shadow Variable Listener Implementation

    Learn how to simplify creating listeners for planning list variables with the new shadow variable @CascadingUpdateShadowVariable.

  • Load balancing and fairness in constraints

    Discover how to bring fairness to your Timefold solution

  • Optimize routing and scheduling in Python: a new open source solver Timefold

    Automate and optimize your operations scheduling in Python with Timefold AI

  • Timefold Solver Python live in Alpha

    Empowering developers to solve planning problems

  • How to speed up Timefold Solver Startup Time by 20x with native images

    Discover how to build a Spring native image and the benefits from doing so.

Sign up for our newsletter

And stay up to date with announcements, the latest news, events, roadmap progress & product updates from Timefold!

We care about the protection of your data. Read our Privacy Policy.

Stay In-The-Know

Sign Up for Our Newsletter

We care about the protection of your data. Read our Privacy Policy.

Timefold

Timefold is an AI planning optimization platform, built on powerful open-source solver technology, enabling software builders to tackle real-world, complex and high-impact operational planning problems. It delivers significant economic value in optimization operations like extended VRP, maintenance scheduling, field service routing, task sequencing, etc.

© 2024 Timefold BV