Variables and domains


A variable

  • is a symbolic representation of an unknown quantity/decision,
  • comes with potential values that the solver can assign to it, a.k.a. its domain,
  • to be determined/assigned during the problem-solving process.

In a scheduling problem

  • Variables : the start time of various tasks
  • Domains : the set of possible start time slots
This is an alt

In a packing problem

  • Variables : the assignment of items to bins
  • Domains : the set of possible bins

In a routing problem

  • Variables : the nodes visited on a tour
  • Domains : the potential successors of each node

Different types of variables are available:

  • IntVar has its values in $\mathbb{Z}^1$
  • IntViews relies on an IntVar
    • like IntAffineView
  • BoolVar (and BoolView) has its values in {$0,1$}
    • sub-type of IntVar


$1$ : But it is always necessary to declare at least an interval.
  • Task to manage with task/interval: $s+d = e$
  • SetVar and SetView
  • (Un)DirectedGraphVar and GraphView
  • and also RealVar

Ways to declare integer variables

Model m = new Model();
IntVar x = m.intVar("x", 0, 4);
IntVar y = m.intVar("y", new int[]{1,3,5});
IntVar[] vs = m.intVarArray("v", 4, 1, 3);
IntVar[][] ws = m.intVarMatrix("w", 2, 2, 1, 2);

Ways to declare Boolean variables

Model m = new Model();
BoolVar b = m.boolVar("b");
BoolVar[] bs = m.boolVarArray("bs", 10);
BoolVar[][] bss = m.boolVarMatrix("bss", 4, 3);

Similar APIs for other types of variables.


Some views declaration

Model m = new Model();                        
IntVar x = m.intVar("x", 0, 5);               
IntVar v = m.intView(2, x, -3); // v = 2.x - 3
BoolVar b = m.isEq(x, 2); // b = (x == 2)     
BoolVar n = b.not(); // n = !b    

And also abs(x), mu(x, 2), neg(x), isLeq(x, 3),


Reading a variable

Model m = new Model();                                    
IntVar x = m.intVar("x", 0, 4);                           
System.out.printf("Variable : %s = [%d, %d]\n",           
        x.getName(), x.getLB(), x.getUB());               
System.out.printf("%s is %s instantiated\n",              
        x.getName(), x.isInstantiated() ? "" : "not");   

outputs

Variable : x = [0, 4]
x is not instantiated   

If instantiated, a variable can return its assignment value with x.getValue().


ABCDE x 4 = EDCBA

If ABCDE times 4 equals EDCBA, and each letter is a different digit from 0 to 9,

what is the value of each letter?

source


A Model

  • Variables:

    • $\forall i \in \{a,b,c,d,e\}, l_i \in [\![ 0,9]\!]$
  • Constraints :

    • $\forall i\neq j \in \{a,b,c,d,e\}, l_i \neq l_j$
    • $39999l_a + 3990l_b + 300l_c - 960l_d - 9996l_e = 0$

Choco-solver code

// Create a model
Model model = new Model("ABCDE x 4 = EDCBA");

// Declare the variables with their initial domain
IntVar A = model.intVar("A", 0, 9);
IntVar B = model.intVar("B", 0, 9);
IntVar C = model.intVar("C", 0, 9);
IntVar D = model.intVar("D", 0, 9);
IntVar E = model.intVar("E", 0, 9);

// Constraint 1:
// "each letter is a different digit from 0 to 9"
// the second part of the constraint is defined
// by the domain of each variable
model.allDifferent(A, B, C, D, E).post();

// Constraint 2:
// "org.step1.ABCDE times 4 equals EDCBA"
// 40000 A + 4000 B + 400 C + 40 D + 4 E = 10000 E + 1000 D + 100 C + 10 B + A
// <=> 39999 A + 3990 B + 300 C + -960 D - 9996 E = 0
model.scalar(
        new IntVar[]{A, B, C, D, E},
        new int[]{39_999, 3_990, 300, -960, -9_996},
        "=", 0).post();

// Find a solution and print it
if (model.getSolver().solve()) {
      int[] sol = new int[]{A.getValue(), B.getValue(), C.getValue(), D.getValue(), E.getValue()};
      System.out.printf(" %d%d%d%d%d\nx    4\n------\n %d%d%d%d%d\n",
        sol[0], sol[1], sol[2], sol[3], sol[4],
        sol[4], sol[3], sol[2], sol[1], sol[0]);
}else{
      System.out.println("No solution found");
}        

Output

 21978
x    4
------
 87912

Can you guess his year of birth?

Someone comes up to you and says:

On my birthday in 2025, my age will be equal to the sum of the digits of my birth year. I am less than 100 years old. What could my birth year be?

Can you model this as a CP problem?

source


A Model

  • Parameters
    • $input$: the current year
  • Variables
    • $\forall i \in \{th,hu,te,on\}, x_i \in [\![0,9]\!]$
    • $age \in [\![0,99]\!]$
  • Constraints
    • $x_{th} + x_{hu} + x_{te} + x_{on} = {age}$
    • $1000x_{th} + 100x_{hu} + 10x_{te} + x_{on} + age = input$

Hints

model.sum(IntVar[], String, int)
model.scalar(IntVar[], int[], String, int)

A Choco-solver code

Model model = new Model("Age equals sum of birth year digits");

IntVar th = model.intVar("th", 0, 9);
IntVar hu = model.intVar("hu", 0, 9);
IntVar te = model.intVar("te", 0, 9);
IntVar on = model.intVar("on", 0, 9);

IntVar age = model.intVar("age", 0, 99);

model.sum(new IntVar[]{th, hu, te, on}, "=", age).post();
model.scalar(
        new IntVar[]{th, hu, te, on, age},
        new int[]{1_000, 100, 10, 1, 1},
        "=", 2025).post();

while (model.getSolver().solve()) {
    int[] sol = new int[]{th.getValue(), hu.getValue(), te.getValue(), on.getValue()};
    System.out.printf("I was born in %d%d%d%d, I am %d years old\n", sol[0], sol[1], sol[2], sol[3], age.getValue());
}
if(model.getSolver().getSolutionCount() == 0) {
    System.out.println("No solution found");
}


Output

I was born in 1998, I am 27 years old
I was born in 2016, I am 9 years old