Search code examples
optaplannerconstraint-programming

OptaPlanner Solution's score not matches the score given by `ScoreManager::explainScore`


To be honest, I have a complicated model, and there's a chance there's an error in my OptaPlanner model.

I'm not sure that the following is possible and normal, or there's some error somewhere in my mapping, and I should create an MCVE based on my entities.

TLDR:

I have the following Kotlin code somewhere in my project:

        val solverJob = solverManager.solveAndListen(problem.id, problemMap::get) {
            val hardScore = it.score!!.hardScore
            if (scoreManager.explainScore(it).score.hardScore != hardScore) {
                throw IllegalStateException()
            }
            onBetterSolutionFoundCallback(mapSolutionToFrontendObject(it))
        }

It's pretty easy, it gives a problem to OptaPlanner, and calls a callback when a better solution is found. The trick here is that it double-checks whether the solution is feasible or not.

Aaaaand, sometimes the IllegalStateException is thrown. The scoreManager.explainScore(it).score reports, that there's one hard constraint violation, while the solution.score says there's no hard constraint violation.

The tricky part is that solution.score is updated after the scoreManager.explainScore method is called.

I've taken a look at the solution, and the ScoreManager is correct: there's one hard constraint violation in the solution. But everything reports, that it's a feasible solution until I call the scoreManager.explainScore method.

The OptaPlanner finds 2 correct solutions before this exception is thrown in my case, so there are feasible solutions, but OptaPlanner replaces them with a non-feasible one.

Is it correct behavior?

Or is there some error in my domain model?

Or it's a bug in OptaPlanner, and I should create a bugreport based on this?

I'm using Quarkus 1.11.1.Final, and OptaPlanner 8.1.0.Final.

Thanks,


Solution

  • Temporarly add this in your application.properties to fail faster with a clearer error message pointing toward the cause:

    # To detect common bugs in your code
    quarkus.optaplanner.solver.environment-mode=FULL_ASSERT
    

    Give it more time, because FULL_ASSERT heavily slows things down. See optaplanner docs section "environment mode" to understand what it does.