Search code examples
javaoptimizationload-balancingoptaplanner

Cloud Balancing Optaplanner: implement an overconstrained planning


I'm trying to implement a simple cloud balancing system with an Overconstrained plannig with the Optaplanner with java.

favorite I'm trying to implement a simple cloud balancing system with an Overconstrained plannig with the Optaplanner library for Java. I mapping the model to my problem (vehicles and assets) doing a variables substitution cpuPower -> weight, memory -> volume. After rules definition for not exceed any of this 2 variables, the drl file:

package org.optaplanner.examples.cloudbalancing.solver;
    dialect "java"

import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder;

import org.optaplanner.examples.cloudbalancing.domain.Mission;
import org.optaplanner.examples.cloudbalancing.domain.Vehicle;
import org.optaplanner.examples.cloudbalancing.domain.Asset;

global HardSoftScoreHolder scoreHolder;

// ############################################################################
// Hard constraints
// ############################################################################

rule "requiredVolumeTotal"
    dialect "mvel"
    when
        $vehicle : Vehicle($maxVolume : maxVolume)
        Number( $totalReqVolume : intValue() > $maxVolume ) from accumulate 
            ( Asset( vehicle == $vehicle , $volume : volume),
            sum($volume)) 
    then
        scoreHolder.addHardConstraintMatch(kcontext, -($totalReqVolume -$maxVolume));
end

rule "requiredWeightTotal"
    dialect "mvel"
    when
        $vehicle : Vehicle($maxWeight : maxWeight)
        Number( $totalReqWeight : intValue() > $maxWeight ) from accumulate 
            ( Asset( vehicle == $vehicle , $weight : weight),
            sum($weight)) 
    then
        scoreHolder.addHardConstraintMatch(kcontext, -($totalReqWeight -$maxWeight));
end

If I use the simple example, I receive a response with all processes asigned although if some of this cannot be assigned to computers. For this problem, optaplanner purpuse is to change the implementation to a overconstained plannig. The documentation says:

  • Add a additional score level (usually a medium level between the hard and soft level) by switching Score type.
  • Make the planning variable nullable.
  • Add a score constraint on the new level (so usually a medium constraint) to penalize the number of unassigned entities (or a weighted sum of them).

I'm doing the nullable annotation and the check in the compare method:

 @PlanningVariable(valueRangeProviderRefs = {"computerRange"},
        strengthComparatorClass = CloudComputerStrengthComparator.class,
        nullable = true)
public CloudComputer getComputer() {
    return computer;
}

_

@Override
public int compare(CloudComputer a, CloudComputer b) {
     if (a == null || b == null)
         return 0;
    return new CompareToBuilder()
            .append(a.getMultiplicand(), b.getMultiplicand())
            .append(b.getCost(), a.getCost()) // Descending (but this is debatable)
            .append(a.getId(), b.getId())
            .toComparison();
}

Whith this changes the processes after the solve method are all unasigned and the solution are incorrect cause ever is 0soft/0hard.

How can define a new constraint (with medium level) to penalize the number of unassigned entities?


Solution

  • Start by using HardMediumSoftScoreHolder in your DRL and HardMediumSoftScore in your domain. Take a look at the hospital bed planning example for the DRL rule.