# CP-SAT Solver

OR-Tools provides two solvers for constraint programming:

The CP-SAT solver is technologically superior to the original CP solver and should be preferred in almost all situations. The exceptions are small problems for which solutions can be found quickly using either solver. In those cases you may find that the original CP solver outperforms CP-SAT.

## Example: finding a feasible solution

The following sections present several examples that illustrate how to use the CP-SAT solver. Let's start with a simple example problem in which there are:

• Three variables, x, y, and z, each of which can take on the values: 0, 1, or 2.
• One constraint: x ≠ y

We'll start by showing how to use the CP-SAT solver to find a single feasible solution in all four of the supported languages (Python, C++, Java, and C#). While finding a feasible solution is trivial in this case, in more complex constraint programming problems it can be very difficult to determine whether there is a feasible solution.

### Declare the model

The following code declares the CP-SAT model.

### Python

`    model = cp_model.CpModel()`

### C++

`  CpModelBuilder cp_model;`

### Java

`    CpModel model = new CpModel();`

### C#

`    CpModel model = new CpModel();`

### Create the variables

The following code creates the variables for the problem.

### Python

```    num_vals = 3
x = model.NewIntVar(0, num_vals - 1, 'x')
y = model.NewIntVar(0, num_vals - 1, 'y')
z = model.NewIntVar(0, num_vals - 1, 'z')```

### C++

```  const Domain domain(0, 2);
const IntVar x = cp_model.NewIntVar(domain).WithName("x");
const IntVar y = cp_model.NewIntVar(domain).WithName("y");
const IntVar z = cp_model.NewIntVar(domain).WithName("z");```

### Java

```    int numVals = 3;

IntVar x = model.newIntVar(0, numVals - 1, "x");
IntVar y = model.newIntVar(0, numVals - 1, "y");
IntVar z = model.newIntVar(0, numVals - 1, "z");```

### C#

```    int num_vals = 3;

IntVar x = model.NewIntVar(0, num_vals - 1, "x");
IntVar y = model.NewIntVar(0, num_vals - 1, "y");
IntVar z = model.NewIntVar(0, num_vals - 1, "z");```

The solver creates three variables, x, y, and z, each of which can take on the values 0, 1, or 2.

### Create the constraint

The following code creates the constraint xy.

### Python

`    model.Add(x != y)`

### C++

`  cp_model.AddNotEqual(x, y);`

### Java

`    model.addDifferent(x, y);`

### C#

`    model.Add(x != y);`

### Call the solver

The following code calls the solver.

### Python

```    solver = cp_model.CpSolver()
status = solver.Solve(model)```

### C++

```  const CpSolverResponse response = Solve(cp_model.Build());
LOG(INFO) << CpSolverResponseStats(response);```

### Java

```    CpSolver solver = new CpSolver();
CpSolverStatus status = solver.solve(model);```

### C#

```    CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);```

The CP-SAT solver returns one of the status values shown in the table below. In this example, the value returned is `OPTIMAL`

Status Description
`OPTIMAL` An optimal feasible solution was found.
`FEASIBLE` A feasible solution was found, but we don't know if it's optimal.
`INFEASIBLE` The problem was proven infeasible.
`MODEL_INVALID` The given CpModelProto didn't pass the validation step. You can get a detailed error by calling `ValidateCpModel(model_proto)`.
`UNKNOWN` The status of the model is unknown because a search limit was reached.

### Display the first solution

The following code displays the first feasible solution found by the solver. Note that the code checks whether the value of the `status` is `FEASIBLE`.

### Python

```if status == cp_model.FEASIBLE:
print('x = %i' % solver.Value(x))
print('y = %i' % solver.Value(y))
print('z = %i' % solver.Value(z))```

### C++

```if (response.status() == CpSolverStatus::FEASIBLE) {
// Get the value of x in the solution.
LOG(INFO) << "x = " << SolutionIntegerValue(response, x);
LOG(INFO) << "y = " << SolutionIntegerValue(response, y);
LOG(INFO) << "z = " << SolutionIntegerValue(response, z);
}```

### Java

```if (status == CpSolverStatus.FEASIBLE) {
System.out.println("x = " + solver.value(x));
System.out.println("y = " + solver.value(y));
System.out.println("z = " + solver.value(z));
}```

### C#

```if (status == CpSolverStatus.Feasible)
{
Console.WriteLine("x = " + solver.Value(x));
Console.WriteLine("y = " + solver.Value(y));
Console.WriteLine("z = " + solver.Value(z));
}```

### Run the program

The complete programs are shown the next section. When you run a program, it returns the first solution found by the solver:

```x = 1
y = 0
z = 0```

### Complete programs

The complete programs are shown below.

### Python

```from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from ortools.sat.python import cp_model

def SimpleSatProgram():
"""Minimal CP-SAT example to showcase calling the solver."""
# Creates the model.
model = cp_model.CpModel()

# Creates the variables.
num_vals = 3
x = model.NewIntVar(0, num_vals - 1, 'x')
y = model.NewIntVar(0, num_vals - 1, 'y')
z = model.NewIntVar(0, num_vals - 1, 'z')

# Creates the constraints.

# Creates a solver and solves the model.
solver = cp_model.CpSolver()
status = solver.Solve(model)

if status == cp_model.FEASIBLE:
print('x = %i' % solver.Value(x))
print('y = %i' % solver.Value(y))
print('z = %i' % solver.Value(z))

SimpleSatProgram()```

### C++

```#include "ortools/sat/cp_model.h"

namespace operations_research {
namespace sat {

void SimpleSatProgram() {
CpModelBuilder cp_model;

const Domain domain(0, 2);
const IntVar x = cp_model.NewIntVar(domain).WithName("x");
const IntVar y = cp_model.NewIntVar(domain).WithName("y");
const IntVar z = cp_model.NewIntVar(domain).WithName("z");

// Solving part.
const CpSolverResponse response = Solve(cp_model.Build());
LOG(INFO) << CpSolverResponseStats(response);

if (response.status() == CpSolverStatus::FEASIBLE) {
// Get the value of x in the solution.
LOG(INFO) << "x = " << SolutionIntegerValue(response, x);
LOG(INFO) << "y = " << SolutionIntegerValue(response, y);
LOG(INFO) << "z = " << SolutionIntegerValue(response, z);
}
}

}  // namespace sat
}  // namespace operations_research

int main() {
operations_research::sat::SimpleSatProgram();

return EXIT_SUCCESS;
}```

### Java

```import com.google.ortools.sat.CpModel;

/** Minimal CP-SAT example to showcase calling the solver. */
public class SimpleSatProgram {
static {
}

public static void main(String[] args) throws Exception {
// Create the model.
CpModel model = new CpModel();

// Create the variables.
int numVals = 3;

IntVar x = model.newIntVar(0, numVals - 1, "x");
IntVar y = model.newIntVar(0, numVals - 1, "y");
IntVar z = model.newIntVar(0, numVals - 1, "z");

// Create the constraints.

// Create a solver and solve the model.
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.solve(model);

if (status == CpSolverStatus.FEASIBLE) {
System.out.println("x = " + solver.value(x));
System.out.println("y = " + solver.value(y));
System.out.println("z = " + solver.value(z));
}
}
}```

### C#

```using System;

public class SimpleSatProgram
{
static void Main()
{
// Creates the model.
CpModel model = new CpModel();

// Creates the variables.
int num_vals = 3;

IntVar x = model.NewIntVar(0, num_vals - 1, "x");
IntVar y = model.NewIntVar(0, num_vals - 1, "y");
IntVar z = model.NewIntVar(0, num_vals - 1, "z");

// Creates the constraints.

// Creates a solver and solves the model.
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);

if (status == CpSolverStatus.Feasible)
{
Console.WriteLine("x = " + solver.Value(x));
Console.WriteLine("y = " + solver.Value(y));
Console.WriteLine("z = " + solver.Value(z));
}
}
}```

## Finding an optimal solution

Next, we'll show how to find an optimal solution to the problem in the previous section, with the additional objective: maximize x + 2y + 3z.

### Add the objective function

To create the objective function, add the following line of code after the constraint in the previous example.

### Python

`  model.Maximize(x + 2 * y + 3 * z)`

### C++

`  maximize({x, y, z}, {1, 2, 3});`

### Java

`  model.maximizeScalProd(new IntVar[] {x, y, z}, new int[] {1, 2, 3});`

### C#

`  model.Maximize(x + 2 * y + 3 * z);`

Next, modify the code that displays solutions as shown below.

### Python

```  if status == cp_model.OPTIMAL:
print('x = %i' % solver.Value(x))
print('y = %i' % solver.Value(y))
print('z = %i' % solver.Value(z))```

### C++

```  if (response.status() == CpSolverStatus::OPTIMAL) {
// Get the values of x, y, and z in the solution.
const int64 value_x = response.solution(x);
const int64 value_y = response.solution(y);
const int64 value_z = response.solution(z)

LOG(INFO) << "x = " << value_x;
LOG(INFO) << "y = " << value_y;
LOG(INFO) << "z = " << value_z;
}```

### Java

```  if (status == CpSolverStatus.OPTIMAL) {
System.out.println("x = " + solver.value(x));
System.out.println("y = " + solver.value(y));
System.out.println("z = " + solver.value(z));
}```

### C#

```  if (status == CpSolverStatus.Optimal)
{
Console.WriteLine("x = " + solver.Value(x));
Console.WriteLine("y = " + solver.Value(y));
Console.WriteLine("z = " + solver.Value(z));
}```

Note that the code now prints a solution that is `OPTIMAL`, instead of `FEASIBLE`, as in the previous example.

### Run the program

When you make the changes above and run the program, it returns the following solution, which maximizes the objective function.

```x = 1
y = 2
z = 2```

## Display all solutions

Next, we'll show how to modify the program above, which displays the first feasible solution, so that it displays all feasible solutions.

Note: there is no objective function in this example.

The main addition to the program is a solution printer—a callback that you pass to the solver, which displays each solution as it is found.

### Add the solution printer

The following code creates the solution printer.

### Python

```class VarArraySolutionPrinter(cp_model.CpSolverSolutionCallback):
"""Print intermediate solutions."""

def __init__(self, variables):
cp_model.CpSolverSolutionCallback.__init__(self)
self.__variables = variables
self.__solution_count = 0

def on_solution_callback(self):
self.__solution_count += 1
for v in self.__variables:
print('%s=%i' % (v, self.Value(v)), end=' ')
print()

def solution_count(self):
return self.__solution_count```

### C++

```  Model model;

int num_solutions = 0;
model.Add(NewFeasibleSolutionObserver([&](const CpSolverResponse& r) {
LOG(INFO) << "Solution " << num_solutions;
LOG(INFO) << "  x = " << SolutionIntegerValue(r, x);
LOG(INFO) << "  y = " << SolutionIntegerValue(r, y);
LOG(INFO) << "  z = " << SolutionIntegerValue(r, z);
num_solutions++;
}));```

### Java

```  static class VarArraySolutionPrinter extends CpSolverSolutionCallback {
public VarArraySolutionPrinter(IntVar[] variables) {
variableArray = variables;
}

@Override
public void onSolutionCallback() {
System.out.printf("Solution #%d: time = %.02f s%n", solutionCount, wallTime());
for (IntVar v : variableArray) {
System.out.printf("  %s = %d%n", v.getName(), value(v));
}
solutionCount++;
}

public int getSolutionCount() {
return solutionCount;
}

private int solutionCount;
private final IntVar[] variableArray;
}```

### C#

```public class VarArraySolutionPrinter : CpSolverSolutionCallback
{
public VarArraySolutionPrinter(IntVar[] variables)
{
variables_ = variables;
}

public override void OnSolutionCallback()
{
{
Console.WriteLine(String.Format("Solution #{0}: time = {1:F2} s",
solution_count_, WallTime()));
foreach (IntVar v in variables_)
{
Console.WriteLine(
String.Format("  {0} = {1}", v.ShortString(), Value(v)));
}
solution_count_++;
}
}

public int SolutionCount()
{
return solution_count_;
}

private int solution_count_;
private IntVar[] variables_;
}```

### Call the solver

The following code calls the solver, and passes the solution printer to it.

### Python

```    solver = cp_model.CpSolver()
solution_printer = VarArraySolutionPrinter([x, y, z])
status = solver.SearchForAllSolutions(model, solution_printer)```

### C++

```  SatParameters parameters;
parameters.set_enumerate_all_solutions(true);
const CpSolverResponse response = SolveCpModel(cp_model.Build(), &model);```

### Java

```    CpSolver solver = new CpSolver();
VarArraySolutionPrinter cb = new VarArraySolutionPrinter(new IntVar[] {x, y, z});
solver.searchAllSolutions(model, cb);```

### C#

```    CpSolver solver = new CpSolver();
VarArraySolutionPrinter cb =
new VarArraySolutionPrinter(new IntVar[] { x, y, z });
solver.SearchAllSolutions(model, cb);```

### Run the program

The complete program is shown in the next section. When you run the program, it displays all 18 feasible solutions:

```x=1 y=0 z=0
x=2 y=0 z=0
x=2 y=1 z=0
x=2 y=1 z=1
x=2 y=1 z=2
x=2 y=0 z=2
x=2 y=0 z=1
x=1 y=0 z=1
x=0 y=1 z=1
x=0 y=1 z=2
x=0 y=2 z=2
x=1 y=2 z=2
x=1 y=2 z=1
x=1 y=2 z=0
x=0 y=2 z=0
x=0 y=1 z=0
x=0 y=2 z=1
x=1 y=0 z=2
Status = FEASIBLE```

### Complete programs

The complete programs are shown below.

### Python

```from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from ortools.sat.python import cp_model

class VarArraySolutionPrinter(cp_model.CpSolverSolutionCallback):
"""Print intermediate solutions."""

def __init__(self, variables):
cp_model.CpSolverSolutionCallback.__init__(self)
self.__variables = variables
self.__solution_count = 0

def on_solution_callback(self):
self.__solution_count += 1
for v in self.__variables:
print('%s=%i' % (v, self.Value(v)), end=' ')
print()

def solution_count(self):
return self.__solution_count

def SearchForAllSolutionsSampleSat():
"""Showcases calling the solver to search for all solutions."""
# Creates the model.
model = cp_model.CpModel()

# Creates the variables.
num_vals = 3
x = model.NewIntVar(0, num_vals - 1, 'x')
y = model.NewIntVar(0, num_vals - 1, 'y')
z = model.NewIntVar(0, num_vals - 1, 'z')

# Create the constraints.

# Create a solver and solve.
solver = cp_model.CpSolver()
solution_printer = VarArraySolutionPrinter([x, y, z])
status = solver.SearchForAllSolutions(model, solution_printer)

print('Status = %s' % solver.StatusName(status))
print('Number of solutions found: %i' % solution_printer.solution_count())

SearchForAllSolutionsSampleSat()```

### C++

```#include "ortools/sat/cp_model.h"
#include "ortools/sat/model.h"
#include "ortools/sat/sat_parameters.pb.h"

namespace operations_research {
namespace sat {

void SearchAllSolutionsSampleSat() {
CpModelBuilder cp_model;

const Domain domain(0, 2);
const IntVar x = cp_model.NewIntVar(domain).WithName("x");
const IntVar y = cp_model.NewIntVar(domain).WithName("y");
const IntVar z = cp_model.NewIntVar(domain).WithName("z");

Model model;

int num_solutions = 0;
model.Add(NewFeasibleSolutionObserver([&](const CpSolverResponse& r) {
LOG(INFO) << "Solution " << num_solutions;
LOG(INFO) << "  x = " << SolutionIntegerValue(r, x);
LOG(INFO) << "  y = " << SolutionIntegerValue(r, y);
LOG(INFO) << "  z = " << SolutionIntegerValue(r, z);
num_solutions++;
}));

// Tell the solver to enumerate all solutions.
SatParameters parameters;
parameters.set_enumerate_all_solutions(true);
const CpSolverResponse response = SolveCpModel(cp_model.Build(), &model);

LOG(INFO) << "Number of solutions found: " << num_solutions;
}

}  // namespace sat
}  // namespace operations_research

int main() {
operations_research::sat::SearchAllSolutionsSampleSat();

return EXIT_SUCCESS;
}```

### Java

```import com.google.ortools.sat.CpModel;

/** Code sample that solves a model and displays all solutions. */
public class SearchForAllSolutionsSampleSat {
static {
}

static class VarArraySolutionPrinter extends CpSolverSolutionCallback {
public VarArraySolutionPrinter(IntVar[] variables) {
variableArray = variables;
}

@Override
public void onSolutionCallback() {
System.out.printf("Solution #%d: time = %.02f s%n", solutionCount, wallTime());
for (IntVar v : variableArray) {
System.out.printf("  %s = %d%n", v.getName(), value(v));
}
solutionCount++;
}

public int getSolutionCount() {
return solutionCount;
}

private int solutionCount;
private final IntVar[] variableArray;
}

public static void main(String[] args) throws Exception {
// Create the model.
CpModel model = new CpModel();

// Create the variables.
int numVals = 3;

IntVar x = model.newIntVar(0, numVals - 1, "x");
IntVar y = model.newIntVar(0, numVals - 1, "y");
IntVar z = model.newIntVar(0, numVals - 1, "z");

// Create the constraints.

// Create a solver and solve the model.
CpSolver solver = new CpSolver();
VarArraySolutionPrinter cb = new VarArraySolutionPrinter(new IntVar[] {x, y, z});
solver.searchAllSolutions(model, cb);

System.out.println(cb.getSolutionCount() + " solutions found.");
}
}```

### C#

```using System;

public class VarArraySolutionPrinter : CpSolverSolutionCallback
{
public VarArraySolutionPrinter(IntVar[] variables)
{
variables_ = variables;
}

public override void OnSolutionCallback()
{
{
Console.WriteLine(String.Format("Solution #{0}: time = {1:F2} s",
solution_count_, WallTime()));
foreach (IntVar v in variables_)
{
Console.WriteLine(
String.Format("  {0} = {1}", v.ShortString(), Value(v)));
}
solution_count_++;
}
}

public int SolutionCount()
{
return solution_count_;
}

private int solution_count_;
private IntVar[] variables_;
}

public class SearchForAllSolutionsSampleSat
{
static void Main()
{
// Creates the model.
CpModel model = new CpModel();

// Creates the variables.
int num_vals = 3;

IntVar x = model.NewIntVar(0, num_vals - 1, "x");
IntVar y = model.NewIntVar(0, num_vals - 1, "y");
IntVar z = model.NewIntVar(0, num_vals - 1, "z");

// Adds a different constraint.