OptaPlanner

Do more business
with less resources

What is business resource optimization?

TSP and VRP demo

What is a planning problem?

  • Complete goals
  • With limited resources
  • Under constraints

Planning problem use cases

Are planning problems
difficult to solve?

Find optimal solution and scale out
for an NP-complete problem?

⇔ Is P = NP?

Yes,
planning problems are
difficult to solve!

(and humans suck at it)

(but they don't realize it)

Reuse optimization algorithms

Find better solutions in time and scale out

CloudBalancing demo

CloudBalancing demo

Domain model

Computer

public class Computer {

  private int cpuPower;
  private int memory;
  private int networkBandwidth;

  private int cost;

  // getters
}

Process is a planning entity

@PlanningEntity
public class Process {

  private int requiredCpuPower;
  private int requiredMemory;
  private int requiredNetworkBandwidth;

  ...

  // getters
}

Process has a planning variable

@PlanningEntity
public class Process {
  ...
  private Computer computer;

  @PlanningVariable(valueRangeProviderRefs = {"computerRange"})
  public Computer getComputer() {
    return computer;
  }
  public void setComputer(Computer computer) {...}
  ...
}

Solution CloudBalance: problem facts

public class CloudBalance
    implements Solution<HardSoftScore> {

  private List<Computer> computerList;

  @ValueRangeProvider(id = "computerRange")
  public List<Computer> getComputerList() {
    return computerList;
  }

  ...
}

Solution CloudBalance: planning entities

public class CloudBalance
    implements Solution<HardSoftScore> {
  ...

  private List<Process> processList;

  @PlanningEntityCollectionProperty
  public List<Process> getProcessList() {
    return processList;
  }

  ...
}

Solution CloudBalance: getProblemFacts()

public class CloudBalance
    implements Solution<HardSoftScore> {
  ...

  // Used in score constraints
  public Collection<Object> getProblemFacts() {
    List<Object> facts = new ArrayList<Object>();
    facts.addAll(computerList);
    return facts;
  }

  ...
}

Solution CloudBalance: score

public class CloudBalance
    implements Solution<HardSoftScore> {
  ...

  private HardSoftScore score;

  public HardSoftScore getScore() {...}
  public void setScore(HardSoftScore score) {...}

  ...
}

Score constraints

Given 2 solutions
which one is better?

Score calculation

Easy Java score calculation

public class CloudBalancingEasyScoreCalculator
    implements EasyScoreCalculator<CloudBalance> {

  public Score calculateScore(CloudBalance cb) {
    ...
    return DefaultHardSoftScore.valueOf(
        hardScore, softScore);
  }

}

Incremental Java score calculation

Drools score calculation

DRL soft constraint: computer cost

rule "computerCost"
  when
    // there is a computer
    $s : Computer($c : cost)
    // there is a processes on that computer
    exists Process(computer == $s)
  then
    // lower soft score by the maintenance cost
    scoreHolder.addSoftConstraintMatch(kcontext,
        - $cost);
end

DRL hard constraint: CPU power

rule "requiredCpuPowerTotal"
  when
    // there is a computer
    $s : Computer($cpu : cpuPower)
    // with too little cpu for its processes
    $total : Number(intValue > $cpu) from accumulate(
      Process(computer == $s,
          $requiredCpu : requiredCpuPower),
      sum($requiredCpu)
    )
  then
    // lower hard score by the excessive CPU usage
    scoreHolder.addHardConstraintMatch(kcontext,
        $cpu - $total.intValue());
end

Solving it

Solver configuration by XML

<solver>
  <solutionClass>...CloudBalance</solutionClass>
  <entityClass>...Process</entityClass>

  <scoreDirectorFactory>
    <scoreDefinitionType>HARD_AND_SOFT</scoreDefinitionType>
    <scoreDrl>...ScoreRules.drl</scoreDrl>
  </scoreDirectorFactory>

  <!-- optimization algorithms -->
</solver>

Solving

SolverFactory factory = SolverFactory.createFromXmlResource(
    "...SolverConfig.xml");
Solver solver = factory.buildSolver();

solver.solve(cloudBalance);
cloudBalance = (CloudBalance) solver.getBestSolution();

Optimization algorithms

Brute force config

<solver>
  ...

  <exhaustiveSearch>
    <exhaustiveSearchType>BRUTE_FORCE</exhaustiveSearchType>
  </exhaustiveSearch>
</solver>

Brute force scalability

Plan 1200 processes with brute force?


First Fit config

<solver>
  ...

  <constructionHeuristic>
    <constructionHeuristicType>FIRST_FIT</constructionHeuristicType>
  </constructionHeuristic>
</solver>

First Fit scalability

First Fit results

All hard constraints satisfied: maintenance cost shown

First Fit Decreasing config

<solver>
  ...

  <constructionHeuristic>
    <constructionHeuristicType>FIRST_FIT_DECREASING</constructionHeuristicType>
  </constructionHeuristic>
</solver>

DifficultyComparator

public class ProcessDifficultyComparator
    implements Comparator<Process> {
  public int compare(Process a, Process b) {
    // Compare on requiredCpuPower * requiredMemory
    //     * requiredNetworkBandwidth
  }
}

@PlanningEntity(difficultyComparatorClass
    = ProcessDifficultyComparator.class)
public class Process  {
  ...
}

First Fit Decreasing scalability

First Fit Decreasing results

Construction Heuristics + Local Search

<solver>
  ...

  <constructionHeuristic>
    <constructionHeuristicType>FIRST_FIT_DECREASING</constructionHeuristicType>
  </constructionHeuristic>
  <localSearch>
    ...
  <localSearch>
</solver>

Hill Climbing config

<localSearch>
  <forager>
    <!-- Untweaked standard value -->
    <acceptedCountLimit>1000</acceptedCountLimit>
  </forager>
</localSearch>

Tabu Search config

<localSearch>
  <acceptor>
    <!-- Untweaked standard value -->
    <entityTabuSize>7</entityTabuSize>
  </acceptor>
  <forager>
    <!-- Untweaked standard value -->
    <acceptedCountLimit>1000</acceptedCountLimit>
  </forager>
</localSearch>

Simulated Annealing config

<localSearch>
  <acceptor>
    <!-- Tweaked value -->
    <simulatedAnnealingStartingTemperature>
        0hard/400soft
    </simulatedAnnealingStartingTemperature>
  </acceptor>
  <forager>
    <!-- Untweaked standard value -->
    <acceptedCountLimit>4</acceptedCountLimit>
  </forager>
</localSearch>

Local Search results

Cost ($) reduction

  • Compared to First Fit
  • First Fit Decreasing
    • 49 480 $ = 4 %
  • Tabu Search
    • 160 860 $ = 14 %
  • Simulated Annealing
    • 128 950 $ = 11 %
  • Few constraints
    • ⇒ low ROI

Repeated planning:
continuous/real-time

Summary

Build from source

$ git clone git@github.com:droolsjbpm/optaplanner.git
...
$ cd optaplanner
$ mvn clean install -DskipTests
...
$ mvn exec:exec
...

Q & A


Introduction to
heuristics and metaheuristics
for
business resource optimization

N Queens demo

demo

Simplified problem

N Queens

Bad

Good

What solution is better?

N Queens

Score = -2

Conflicts: A-B, B-D

Score = 0

How do we find the best solution?

Brute Force scalability

8 queens = 15.7 seconds
9 queens = 2.5 minutes (times 10)
10 queens = 0.83 hours (times 20)

How many combinations for 100 queens?

Source: NASA (wikipedia)

> humans?
7 000 000 000

How many combinations for 100 queens?

Source: NASA and ESA (wikipedia)

> minimum atoms
in the observable universe?
1080

How many combinations for 100 queens?

100100 = 10200

1 0000000000 0000000000 0000000000 0000000000 0000000000
  0000000000 0000000000 0000000000 0000000000 0000000000
  0000000000 0000000000 0000000000 0000000000 0000000000
  0000000000 0000000000 0000000000 0000000000 0000000000

How many combinations for n queens?

nn

|valueSet||variableSet|

How long?

Presume 109 scores/ms ⇒ 1020 scores/year

Queens Combinations Calculation time
100 100100 = 10200 10180 years
1000 10001000 = 103000 102980 years
10000 1000010000 = 1040000 1039980 years

Moore's law == a drop in the ocean

Exhaustive Search doesn't scale

Move types

All change moves

n # moves # solutions
4 16 256
8 64 16777216
64 4096 10^116
n n^2 n^n

Multiple moves

Multiple moves can reach any solution

Performance tricks

Benchmark results

Demo

Reuse existing business code

public class Nurse {

  private Country country;

  public boolean isHoliday(Date date) {
    if (country == Country.BE) {
      // true if date is 1-JAN, easter monday, 21-JUL, ...
    } else if (country == Country.FR) {
      // true if date is 1-JAN, easter monday, 14-JUL, ...
    } else if (...) {
      ...
    }
    ...
  }

}

Q & A