yassine
yassine

Reputation: 41

Optaplanner : Initializing planning variable problem

I am new to Optaplanner and to get familiar with it I tried to run a simple code. The idea is I have one single planning variable of type integer, that has a range between 1 and 30, that I try to maximize. So normally the solver should give me a value of 30.

My code is as follows :

Planning entity and planning variable :

@PlanningEntity
public class variable {

    @PlanningVariable(valueRangeProviderRefs = "xRange")
    private Integer x;

    public variable() {

    }   

    public Integer getX() {
        return x;
    }

    public void setX(Integer x) {
        this.x = x;
    }
    
}

Planning solution

@PlanningSolution public class Planningsolution {

@PlanningEntityProperty
private variable variable;

@ValueRangeProvider(id="xRange")
public CountableValueRange<Integer> getxRange(){
    return ValueRangeFactory.createIntValueRange(1, 30);
}

@PlanningScore
private HardSoftScore score;

public Planningsolution() {

}

public variable getVariable() {
    return variable;
}

public void setVariable(variable variable) {
    this.variable = variable;
}

public HardSoftScore getScore() {
    return score;
}

public void setScore(HardSoftScore score) {
    this.score = score;
}       

}

Constraint Provider

public class SimpleConstraintProvider implements ConstraintProvider {


    
     @Override
        public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
            return new Constraint[] {
                    // Hard constraints
                    maxValue(constraintFactory),

            };
     }
            
         private Constraint maxValue (ConstraintFactory constraintFactory) {
                
                return constraintFactory.forEach(variable.class)
                        .reward("maximum", HardSoftScore.ONE_SOFT,variable::getX);
                    }
}

Main :

public class SimpleApp {

     private static final Logger LOGGER = LoggerFactory.getLogger(SimpleApp.class);

        public static void main(String[] args) {
            SolverFactory<Planningsolution> solverFactory = SolverFactory.create(new SolverConfig()
                    .withSolutionClass(Planningsolution.class)
                    .withEntityClasses(variable.class)
                    .withConstraintProviderClass(SimpleConstraintProvider.class)

                    .withTerminationSpentLimit(Duration.ofSeconds(10)));

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

            // Solve the problem
            Solver<Planningsolution> solver = solverFactory.buildSolver();
            Planningsolution solution = solver.solve(problem);

            // Visualize the solution
           System.out.println("solution: " + display(solution) + "\n" + "score: " + solution.getScore());;
        }
    
        
        public static Integer display(Planningsolution solution) {
            variable var = new variable();
            return var.getX();
        }
}

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

  <appender name="appender" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d [%t] %-5p %m%n</pattern>
    </encoder>
  </appender>

  <logger name="org.optaplanner" level="info"/>

  <root level="warn">
    <appender-ref ref="appender"/>
  </root>

</configuration>

The output i get is :

solution: null score: 0hard/0soft

Upvotes: 1

Views: 323

Answers (1)

In order for planning variables to be initializable, they must be able to accept null as a value. Java primitive types (such as int) are not capable of doing that, therefore your planning variable needs to be an Integer. The error message even tells you to do that, although the wording is a bit cryptic.

As a side note, I think we should be able to handle this situation better. If people don't want null in there, we should not force them. Something to consider for future development.

Upvotes: 0

Related Questions