If I have an IntVar s[j] stored in a vector s, is it possible to iterate for (a period of time) t and create a BoolVar b such that b[t] is true if and only if s[j]==t? I tried setting some restrictions:

    for (int j = 0; j < nbTasks; ++j)
        for (int t = 0; t < tmax; ++t)
            const IntVar expr = cp_model.NewIntVar(Domain(-1000000000,100000000000));
            const IntVar actual_t = cp_model.NewConstant(t).WithName("actual_t");
            const BoolVar b = cp_model.NewBoolVar().WithName("b");
            const IntVar value = cp_model.NewConstant(w[j][t]);


            cp_model.AddEquality(b, starts[j]==actual_t);
            cp_model.AddProductEquality(expr, {value, b});

I created the BoolVar b and then set an equality to the bool value of s[j]==t, then I used the constraint expr == value*b and added the expression to the vector obj_final, and finally set the objective: cp_model.Maximize(LinearExpr::Sum(obj_final)); The problem is that my solution is optimal but the objective is zero, so I guess b is always false.

My goal is to assign a value to an expression if and only if s[j]==t. Enforce constraints isn't what i need because the other expressions must be zero. I'll be thankful for any help.

  • 2
    $\begingroup$ You should read this: github.com/google/or-tools/blob/stable/ortools/sat/doc/… $\endgroup$
    – Stradivari
    Jan 31, 2020 at 14:41
  • $\begingroup$ Thanks for your answer! The problem is that OnlyEnforceIf takes only BoolVar as argument, and the condition i need (s[j]==t) is just bool , i tried but the function don't match the argument. $\endgroup$ Jan 31, 2020 at 15:06
  • $\begingroup$ I might be wrong, but isn't what you want: cp_model.AddEquality(s[j], t).OnlyEnforceIf(b) and cp_model.AddEquality(s[j], 0).OnlyEnforceIf(Not(b)) ? Which is more or less the same as the example linked $\endgroup$
    – Stradivari
    Jan 31, 2020 at 15:08
  • $\begingroup$ Nope, i want to cp_model.AddEquality(expr, value).OnlyEnforceIf(s[j]==t) but OnlyEnforceIf takes only BoolVar arguments and not bool (as s[j]==t). So i want to create a BoolVar that is true if s[j]==t, else false. $\endgroup$ Jan 31, 2020 at 15:24

1 Answer 1


To create an intermediate boolean that is true iff s[j] == t you just have to create 2 constraints:

cp_model.AddEquality(s[j], t).OnlyEnforceIf(b);
cp_model.AddNotEqual(s[j], t).OnlyEnforceIf(Not(b));

The problem with this line:

cp_model.AddEquality(b, starts[j]==actual_t);

is that starts[j]==actual_t "always" evaluates to false.

To learn more about channeling, see:

  • $\begingroup$ Thanks! its solving. I'm modelling an RCPSP with discount rate (precomputed and rounded) do you think that it is the best way to model it? $\endgroup$ Jan 31, 2020 at 18:01
  • $\begingroup$ I am no expert in that, sorry. It might be better to ask a new question explaining your model so people can comment on it $\endgroup$
    – Stradivari
    Jan 31, 2020 at 18:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.