Issue
I have taken the cloud balancing problem to a different direction:
A problem where you need to fill up all the computers with processes and computers can overfill (by changing the overfill constraint to a soft one)
The change was easy by adding the following constraints:
Constraint unfilledCpuPowerTotal(ConstraintFactory constraintFactory) {
return constraintFactory.forEach(CloudProcess.class)
.groupBy(CloudProcess::getComputer, sum(CloudProcess::getRequiredCpuPower))
.filter((computer, requiredCpuPower) -> requiredCpuPower < computer.getCpuPower())
.penalize("unfilledCpuPowerTotal",
HardSoftScore.ONE_HARD,
(computer, requiredCpuPower) -> computer.getCpuPower() - requiredCpuPower);
}
Constraint unfilledMemoryTotal(ConstraintFactory constraintFactory) {
return constraintFactory.forEach(CloudProcess.class)
.groupBy(CloudProcess::getComputer, sum(CloudProcess::getRequiredMemory))
.filter((computer, requiredMemory) -> requiredMemory < computer.getMemory())
.penalize("unfilledMemoryTotal",
HardSoftScore.ONE_HARD,
(computer, requiredMemory) -> computer.getMemory() - requiredMemory);
}
Constraint unfilledNetworkBandwidthTotal(ConstraintFactory constraintFactory) {
return constraintFactory.forEach(CloudProcess.class)
.groupBy(CloudProcess::getComputer, sum(CloudProcess::getRequiredNetworkBandwidth))
.filter((computer, requiredNetworkBandwidth) -> requiredNetworkBandwidth < computer.getNetworkBandwidth())
.penalize("unfilledNetworkBandwidthTotal",
HardSoftScore.ONE_HARD,
(computer, requiredNetworkBandwidth) -> computer.getNetworkBandwidth() - requiredNetworkBandwidth);
}
Constraint unusedComputer(ConstraintFactory constraintFactory) {
return constraintFactory.forEach(CloudComputer.class)
.ifNotExists(CloudProcess.class, equal(Function.identity(), CloudProcess::getComputer))
.penalize("unusedComputers",
HardSoftScore.ONE_HARD,
computer -> computer.getCpuPower() + computer.getMemory() + computer.getNetworkBandwidth());
}
I have also removed the cost constraint because it doesn't make sense in this context.
However, i dont want the planner to dump all the avalible processes into computers.
Meaning, if all the computers are already full and there are unused processes I would like them to stay that way and not be forced to add more overfill penalty to a computer.
I guess this can be done by somehow ignoring the init penalty but I can't seem to understand where or how to implement that idea.
I also thought about adding a "dummy" computer entity that just holds processes with no penalty (the planner will still fill regular computers because not filling them will resault in a soft penalty) but it seems like a lot of work and requires big changes to almost every part of the project so if there is a way to implement the first idea it would be preferred.
Solution
What you're describing is called over-constrained planning. Most likely, you are looking for nullable variables. Your idea with a dummy is called a "virtual value".
Answered By - Lukáลก Petrovický
Answer Checked By - Senaida (JavaFixing Volunteer)