Dealing with solutions

How to deal with Solution?

Recording solutions

A solution can be stored through a Solution object which maps every variable with its current value. It can be created as follows:

Solution solution = new Solution(model);

Reducing data recorded

By default, a solution records the value of every variable, but you can specify a smaller scope in the Solution constructor.

Let X be the set of decision variables and Y another variable set that you need to store. To record other variables (e.g. an objective variables) you have two options:

  • Declare them in the search strategy using a complementary strategy
solver.set(strategy(X),strategy(Y)).
  • Specify which variables to store in the solution constructor
Solution solution = new Solution(model(), ArrayUtils.append(X,Y));

You can record the last solution found as follows :

Solution solution = new Solution(model);
while (solver.solve()) {
    solution.record();
}

You can also use a monitor as follows:

Solution solution = new Solution(model);
solver.plugMonitor(new IMonitorSolution() {
      @Override
      public void onSolution() {
          s.record();
      }
});

Or with lambdas:

Solution solution = new Solution(model);
solver.plugMonitor((IMonitorSolution) () -> s.record());

Note that the solution is erased on each new recording. To store all solutions, you need to create one new solution object for each solution.

You can then access the value of a variable in a solution as follows:

int val = s.getIntVal(Y[0])

The solution object can be used to store all variables in Choco Solver (binaries, integers, sets and reals)

Accessing variable value

The value of a variable can be accessed directly through the getValue() method only once the variable is instantiated, i.e. the value has been computed (call isInstantiated() to check it). Otherwise, the lower bound is returned (or an exception is thrown if -ea is set as JVM argument).

For instance, the following code will return the lower bound of var (or an assertion exception) since the resolution has not begun:

int val = var.getValue();
solver.solve();

On the other hand, the following code may return the lower bound of var (or an assertion exception) if no solution could be found (unsat problem or time limit reached):

solver.solve();
int val = var.getValue();

The correct approach to get the value of a variable var in a solution is :

if(solver.solve()){
    int val = var.getValue();
}

In optimization, you can print its value in each solution:

while(solver.solve()){
    System.out.println(variable.getValue());
}

The last printed value corresponds to the one in the best solution found.

However, the following code does NOT display the best solution found:

while(solver.solve()){
    System.out.println(variable.getValue());
}
System.out.println("best solution found: "+variable.getValue());

Because it is outside the while loop, this code is reached once the search tree has been closed. It does not correspond to a solution state and therefore variable is no longer instantiated at this stage. To use solutions afterward, you need to record them using Solution objects.

Last modified 16.03.2020: Update solving part (9d077c6)