Contents

Optaplanner

Example

We will be using OptaPlanner to find the roots for a polynomial. We start by defining our planning entity, PolynomialEntity, which will calculate the polynomial value for a specific value. The polynomial we will use is

\[ f(x) = 2x^3 + 3x^2 + x + 6 \]

This polynomial has a root for \(x=-2\). The entity is then

Define the Lesson:

import org.optaplanner.core.api.domain.entity.PlanningEntity;
import org.optaplanner.core.api.domain.valuerange.ValueRange;
import org.optaplanner.core.api.domain.valuerange.ValueRangeFactory;
import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider;
import org.optaplanner.core.api.domain.variable.PlanningVariable;

@PlanningEntity
    public class PolynomialEntity {
    private double value;

    private PolynomialEntity() {
    }

    public PolynomialEntity(double i) {
        this.value = i;
    }

    @Override public String toString() {
        return "PolynomialEntity{" +
                "value=" + value +
                '}';
    }

    @PlanningVariable(valueRangeProviderRefs = { "polynomialRange" })
    public Double getValue() {
        return value;
    }

    public void setValue(Double value) {
        this.value = value;
    }

    @ValueRangeProvider(id = "polynomialRange")
    public ValueRange<Double> getCountValue() {
        return ValueRangeFactory.createDoubleValueRange(-100, 100);
    }

    public double calculate() {
        return 2.0 * Math.pow(this.value, 3) + 3 * Math.pow(this.value, 2) + this.value + 6;
    }

}

We now define the solution PolynomialSolution:

import org.optaplanner.core.api.domain.solution.PlanningEntityProperty;
import org.optaplanner.core.api.domain.solution.PlanningScore;
import org.optaplanner.core.api.domain.solution.PlanningSolution;
import org.optaplanner.core.api.score.buildin.simplebigdecimal.SimpleBigDecimalScore;

@PlanningSolution
public class PolynomialSolution {

    @PlanningEntityProperty
    PolynomialEntity polynomialEntity;

    @PlanningScore
    private SimpleBigDecimalScore score;

    public PolynomialSolution() {
        this.polynomialEntity = new PolynomialEntity(0.0);
    }

    public PolynomialSolution(PolynomialEntity polynomialEntity) {
        this.polynomialEntity = polynomialEntity;
    }

    public PolynomialEntity getPolynomialEntity() {
        return polynomialEntity;
    }

    public void setPolynomialEntity(PolynomialEntity polynomialEntity) {
        this.polynomialEntity = polynomialEntity;
    }

    public SimpleBigDecimalScore getScore() {
        return score;
    }

}

And the score calculator:

import java.math.BigDecimal;

import org.optaplanner.core.api.score.buildin.simplebigdecimal.SimpleBigDecimalScore;
import org.optaplanner.core.api.score.calculator.EasyScoreCalculator;

public class PolynomialEasyScoreCalculator implements EasyScoreCalculator<PolynomialSolution, SimpleBigDecimalScore> {

    @Override
    public SimpleBigDecimalScore calculateScore(PolynomialSolution polynomialSolution) {
        PolynomialEntity entity = polynomialSolution.getPolynomialEntity();
        double y = -Math.abs(entity.calculate());
        return SimpleBigDecimalScore.of(BigDecimal.valueOf(y));
    }

}

Finally we run it

import org.optaplanner.core.api.solver.Solver;
import org.optaplanner.core.api.solver.SolverFactory;
import org.optaplanner.core.config.solver.SolverConfig;
import org.optaplanner.core.config.solver.termination.TerminationConfig;

SolverFactory<PolynomialSolution> solverFactory = SolverFactory.create(new SolverConfig()
    .withSolutionClass(PolynomialSolution.class)
    .withEntityClasses(PolynomialEntity.class)
    .withEasyScoreCalculatorClass(PolynomialEasyScoreCalculator.class)
    .withTerminationConfig(new TerminationConfig().withSecondsSpentLimit(5L)));

// Load the problem
PolynomialSolution problem = new PolynomialSolution();

// Solve the problem
Solver<PolynomialSolution> solver = solverFactory.buildSolver();
PolynomialSolution solution = solver.solve(problem);
System.out.println(solution.getPolynomialEntity());
PolynomialEntity{value=-2.0000069627535737}