Je suis un peu nouveau dans l'optimisation linéaire, et je veux l'appliquer aux problèmes d'ordonnancement classiques. En ce qui concerne les problèmes de dotation, je ne vois pas très bien comment déclarer les fonctions qui capturent le concept de «changement». J'utilise ojAlgo qui a été plutôt génial jusqu'à maintenant. Voici mon petit problème artificiel je suis venu avec:ojAlgo Optimisation linéaire - Prévention des chevauchements de travail?
SCENARIO:
You have three drivers to make deliveries.
Driver 1 costs $10/hr
Driver 2 costs $12/hr
Driver 3 costs $14/hr
Each driver can only work 3-6 hours a day.
Only one shift can be worked by a worker a day.
Operating day is 6:00 to 22:00, which must be fully covered.
Driver 2 cannot work after 11:00.
Create a schedule that minimizes the cost.
Solve Variables:
Tsx = shift start for Driver X
Tex = shift end for Driver X
Minimize:
10(Te1 - Ts1) + 12(Te2 - Ts2) + 14(Te3 - Ts3)
10Te1 - 10Te2 + 12Te2 - 12Ts2 + 14Te3 - 14Ts3
Constraints:
4.0 <= Te - Ts <= 6.0
6.0 <= Ts, Te <= 22.0
(Te1 - Ts1) + (Te2 - Ts2) + (Te3 - Ts3) = (22.0 - 6.0)
Te2 <= 11
Voici le code de Kotlin que j'ai mis ensemble. J'ai trouvé plus facile pour chaque instance Driver
de prendre en charge autant de ses entrées de fonction que possible (ce qui a donné quelques motifs intéressants avec OOP).
import org.ojalgo.optimisation.ExpressionsBasedModel
import org.ojalgo.optimisation.Variable
fun main(args: Array<String>) {
val model = ExpressionsBasedModel()
val drivers = sequenceOf(
Driver(1, 10.0, model),
Driver(2, 12.0, model),
Driver(3, 14.0, model)
).map { it.driverNumber to it }
.toMap()
model.addExpression("EnsureCoverage")
.level(16.0)
.apply {
drivers.values.forEach {
set(it.shiftEnd, 1)
set(it.shiftStart, -1)
}
}
model.addExpression("Driver2OffAt11")
.upper(11)
.set(drivers[1]!!.shiftEnd, 1)
val result = model.minimise()
println(result)
}
data class Driver(val driverNumber: Int,
val rate: Double,
val model: ExpressionsBasedModel) {
val shiftStart = Variable.make("${driverNumber}shiftStart").weight(rate).lower(6).upper(22).apply(model::addVariable)
val shiftEnd = Variable.make("${driverNumber}shiftEnd").weight(rate).lower(6).upper(22).apply(model::addVariable)
init {
model.addExpression("${driverNumber}shiftLength")
.lower(4.0)
.upper(6.0)
.set(shiftEnd, 1)
.set(shiftStart, -1)
}
}
Mais je reçois cette sortie indiquant que les trois pilotes ont été assignés à 06h00 et de travailler simultanément. Le chauffeur 1 de 6h00 à 11h00, le chauffeur 2 de 6h00 à 12h00 et le chauffeur 3 de 6h00 à 11h00.
OPTIMAL 624.0 @ [6.0, 11.0, 6.0, 12.0, 6.0, 11.0]
Je ne veux pas qu'ils se chevauchent. Je ne veux qu'un seul conducteur à la fois, et je veux que toute la journée de travail soit couverte. Comment exprimer l'état binaire du temps déjà occupé?
Voici un exemple d'un problème similaire [[link] (http://yetanothermathprogrammingconsultant.blogspot.com/2017/03/employee-scheduling-iv- direct.html)]. Il a des liens avec d'autres formulations et approches. –
C'est une question de modélisation qui n'est pas spécifique à ojAlgo. Si vous cherchez des problèmes de planification et/ou d'affectation, vous trouverez qu'il y a beaucoup à lire. – apete