edferda
edferda

Reputation: 450

Why does adding a hard constraint produce bad solutions?

I am trying to use Optaplanner to optimally assign production units to a group of contractors. The goal is to assign the production units so that the real inventory is as close as possible to the optimal inventory. For this, I am using a soft constraint which, in simple terms, follows this basic equation:

Soft constrint formula

This is the basis for my soft constraint score. The purpose of Optaplanner is to minimize this difference. However, I do have a hard constraint that specifies the minimum production units that can be assigned. Whenever this constraint is introduced to the problem, Optaplanner produces less than optimal solutions. It basically assigns all the available production units to one single contractor so as to not break the minimum production quantity constraint.

This ensures that no contractor is assigned a small amount of production units (assigning 0 is ok), but it has the unintended consequence that the soft constraint is not optimized at all. Extending the run time basically just moves the entirety of the production units around between different contractors.

It is not a matter of not having enough production units since I have around 10000 available units while the minimum production quantity is 120. This should be enough to assign it to several contractors and optimize the inventory instead of assigning the 10000 units to one single contractor.

Is there a way to include this hard constraint without Optaplanner completely ignoring the soft constraint?

EDIT: To clarify, the hard constraint is only punishing when the production units are bellow 120. It is not rewarding production units above 120. The max possible hard score is 0.

(For simplicity I said "assign units to contractors" when in reality Optaplanner is "assigning contractors to the units")

Upvotes: 0

Views: 256

Answers (1)

Geoffrey De Smet
Geoffrey De Smet

Reputation: 27337

It's probably stuck in a deep local optima due to lack of smart enough moves to get out of it (and it's too deep for the metaheuristics to get out of it). If you turn on DEBUG (and later TRACE) logging, you'll see the decisions that optaplanner makes.

Try adding pillar change and swap moves:

<constructionHeuristic/>
<localSearch>
  <unionMoveSelector>
    <changeMoveSelector/>
    <swapMoveSelector/>
    <pillarChangeMoveSelector/>
    <pillarSwapMoveSelector/>
  </unionMoveSelector>
</localSearch>

If that doesn't help, you'll need a custom move.

Upvotes: 1

Related Questions