timefold-solver icon indicating copy to clipboard operation
timefold-solver copied to clipboard

HardMediumSoftMicrosScore

Open ge0ffrey opened this issue 1 year ago • 0 comments

Motivation:

In use cases with a fairness or load balancing constraint, alongside other soft constraints, the only practical way to write that constraint is using the sqrt(sum(x²)) pattern. In the tennis example there's a loadBalance() function that does that for you.

This sqrt() gives a decimal number and that does not work well with LongScore:

  • BigDecimalScore is slow and a bit of a pain
  • Only the first 4 decimals matter (simple math support that this accuracy is accurate enough). So typically it is mulitplied by 1 milliion and put into a LongScore. The 6 digits (micros) are 2 digits for safety.

However, this is a pain:

  • for clarity (think logs etc)
  • for visualization in any UI (including score analysis etc)
  • for score weights

Proposal A

A new score: HardMediumSoftMicrosScore. It uses long underneath.

  • long hardMicros
  • long mediumMicros
  • long softMicros
  • toString() = hardMicros / 1M + (hardMicros % 1M == 0 ? "" : hardMicros % 1M ...
  • ONE_SOFT => softMicros = 1_000_000
  • ofSoft(7) => softMicros = 7_000_000
  • ofSoftMicros(7) => softMicros = 7

The score weight of the dayOffRequest constraint is ofSoft(10).

Is the score weight of the fairness constraint is ofSoftMicros(1)?

  • A1) Yes. But that's confusing for users to tune.
  • A2) No, it's ofSoft(1) and the constraint impl does a trick so the accuracy isn't lost.

Related design

  • [ ] Standarize and document loadBalance() of the tennis example
  • [ ] Guide for fairness and load balancing, including FTE (Full time equivelant) challenges
  • [ ] An understandable version of math of https://www.optaplanner.org/blog/2017/02/03/FormulaForMeasuringUnfairness.html

ge0ffrey avatar Jan 08 '24 08:01 ge0ffrey