Hacker News new | ask | show | jobs
by chriswarbo 1523 days ago
At my current job we use Optaplanner in a project, to move around seat reservations (in blocks of several hundred) whilst keeping the new seats as similar as possible to the old ones (each seat having 'attributes' with various weights). I mostly chose it due to being JVM (although it needed a little Java shim to make it usable from Scala)

In grad school I used MiniZinc to find exact optimal subsets for a certain problem, which took AGES and was only practical up to sets of size 11, but I could use its output as a benchmark for my own approximate solver.

1 comments

I’m curious to know how your experience with Optaplanner has been. As I understand you model your problems quite differently and it is more of a search for a good enough solution using metaheuristics?
I think Optaplanner has its own DSL, but we use the Java/JVM API: a 'solution' is just a normal JVM object, which references other objects in the usual way. Certain fields are annotated, which tells Optaplanner that it can mutate/alter them.

Implementing the domain objects is pretty natural. The only part that feels weird is that solving is completely based around mutation; whilst that's pretty idiomatic for Java, it feels a bit alien in Scala (I previously worked mostly in Haskell, and haven't written Java in over a decade).

There's a bunch of configuration boilerplate; including the following, which is the only Java code in the whole project (and almost looks like a parody of "Enterprise Java"!):

    class Config {
        public static ScoreDirectorFactoryConfig config =
            (new ScoreDirectorFactoryConfig())
            .withEasyScoreCalculatorClass(ScoreCalculator.class);
    }
IIRC, this had to be Java due to some weird self-referential interface that makes Scala's type-checker explode.

We can give each solution both a "hard" score and a "soft" score, where the soft score will be sacrificed if it improves the hard score. We use the hard score to count errors which make a solution invalid (e.g. trying to assign two people to the same seat); and the soft score as a weighted sum of mismatched seat attributes (e.g. it would be nice to stay facing the same direction; but not crucial).

Once the problem has been defined, it can be sent to a bunch of solvers; we use simulated annealing with a timeout. Since it's an anytime-algorithm, we can adjust the timeout to however long we're prepared to wait.

To avoid "obvious" problems in Optaplanner's results, we send them through a simple hill-climbing loop to ensure we're at a local maximum.