# Integer arithmetic recipes for the CP-SAT solver. ## Introduction The CP-SAT solver can express integer variables and constraints. ## Integer variables Integer variables are discrete variables ranging over 64 bit signed integer values. When creating them, a domain must be given. The format of this domain is a flattened list of disjoint intervals. - To represent a interval from 0 to 10, just pass a domain [0, 10]. - To represent a single value (5), create a domain [5, 5]. - From these, it is easy to represent an enumerated list of values [-5, -4, -3, 1, 3, 4, 5, 6] is encoded as [-5, -3, 1, 1, 3, 6]. - To exclude a single value, use int64min and int64max values as in [int64min, 4, 6, int64max]. ## Linear constraints In **C++**, the model supports linear constraints as in: sum (a_i * x_i) in domain Where domain uses the same encoding as integer variables. From this, the usual modeling tricks can express general arithmetic constraints: x > y can be rewritten as 1 * x + (-1) * y in [1, int64max] **Python** and **C\#** CP-SAT APIs support general linear arithmetic (+, *, -, ==, >=, >, <, <=, !=). ## Rabbits and Pheasants examples Let's solve a simple children's puzzle: the Rabbits and Pheasants problem. WIn a field of rabbits and pheasants, there are 20 heads and 56 legs. How many rabbits and pheasants are there? ### Python code ```python """Rabbits and Pheasants quizz.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function from ortools.sat.python import cp_model def RabbitsAndPheasants(): """Solves the rabbits + pheasants problem.""" model = cp_model.CpModel() r = model.NewIntVar(0, 100, 'r') p = model.NewIntVar(0, 100, 'p') # 20 heads. model.Add(r + p == 20) # 56 legs. model.Add(4 * r + 2 * p == 56) # Solves and prints out the solution. solver = cp_model.CpSolver() status = solver.Solve(model) if status == cp_model.FEASIBLE: print('%i rabbits and %i pheasants' % (solver.Value(r), solver.Value(p))) RabbitsAndPheasants() ``` ### C++ code ```cpp #include "ortools/sat/cp_model.pb.h" #include "ortools/sat/cp_model_solver.h" #include "ortools/sat/cp_model_utils.h" #include "ortools/sat/model.h" namespace operations_research { namespace sat { void RabbitsAndPheasants() { CpModelProto cp_model; // Trivial model with just one variable and no constraint. auto new_variable = [&cp_model](int64 lb, int64 ub) { CHECK_LE(lb, ub); const int index = cp_model.variables_size(); IntegerVariableProto* const var = cp_model.add_variables(); var->add_domain(lb); var->add_domain(ub); return index; }; auto add_linear_constraint = [&cp_model](const std::vector& vars, const std::vector& coeffs, int64 lb, int64 ub) { LinearConstraintProto* const lin = cp_model.add_constraints()->mutable_linear(); for (const int v : vars) { lin->add_vars(v); } for (const int64 c : coeffs) { lin->add_coeffs(c); } lin->add_domain(lb); lin->add_domain(ub); }; // Creates variables. const int r = new_variable(0, 100); const int p = new_variable(0, 100); // 20 heads. add_linear_constraint({r, p}, {1, 1}, 20, 20); // 56 legs. add_linear_constraint({r, p}, {4, 2}, 56, 56); // Solving part. Model model; LOG(INFO) << CpModelStats(cp_model); const CpSolverResponse response = SolveCpModel(cp_model, &model); LOG(INFO) << CpSolverResponseStats(response); if (response.status() == CpSolverStatus::FEASIBLE) { // Get the value of x in the solution. LOG(INFO) << response.solution(r) << " rabbits, and " << response.solution(p) << " pheasants"; } } } // namespace sat } // namespace operations_research int main() { operations_research::sat::RabbitsAndPheasants(); return EXIT_SUCCESS; } ``` ### Java code ```java import com.google.ortools.sat.CpSolverStatus; import com.google.ortools.sat.CpModel; import com.google.ortools.sat.CpSolver; import com.google.ortools.sat.IntVar; /** * In a field of rabbits and pheasants, there are 20 heads and 56 legs. How many rabbits and * pheasants are there? */ public class RabbitsAndPheasants { static { System.loadLibrary("jniortools"); } public static void main(String[] args) throws Exception { // Creates the model. CpModel model = new CpModel(); // Creates the variables. IntVar r = model.newIntVar(0, 100, "r"); IntVar p = model.newIntVar(0, 100, "p"); // 20 heads. model.addLinearSumEqual(new IntVar[] {r, p}, 20); // 56 legs. model.addScalProdEqual(new IntVar[] {r, p}, new long[] {4, 2}, 56); // Creates a solver and solves the model. CpSolver solver = new CpSolver(); CpSolverStatus status = solver.solve(model); if (status == CpSolverStatus.FEASIBLE) { System.out.println(solver.value(r) + " rabbits, and " + solver.value(p) + " pheasants"); } } } ``` ### C\# code ```cs using System; using Google.OrTools.Sat; public class CodeSamplesSat { static void RabbitsAndPheasants() { // Creates the model. CpModel model = new CpModel(); // Creates the variables. IntVar r = model.NewIntVar(0, 100, "r"); IntVar p = model.NewIntVar(0, 100, "p"); // 20 heads. model.Add(r + p == 20); // 56 legs. model.Add(4 * r + 2 * p == 56); // Creates a solver and solves the model. CpSolver solver = new CpSolver(); CpSolverStatus status = solver.Solve(model); if (status == CpSolverStatus.Feasible) { Console.WriteLine(solver.Value(r) + " rabbits, and " + solver.Value(p) + " pheasants"); } } static void Main() { RabbitsAndPheasants(); } } ```