6

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]);

            obj_final.push_back(expr);
            actuals[j].push_back(actual_t);
            expressions[j].push_back(expr);
            values[j].push_back(value);

            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.

Michiel uit het Broek
  • 2,491
  • 2
  • 15
  • 36
  • 2
    You should read this: https://github.com/google/or-tools/blob/stable/ortools/sat/doc/channeling.md – Stradivari Jan 31 '20 at 14:41
  • 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. – Diego R. Troncoso Jan 31 '20 at 15:06
  • 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 – Stradivari Jan 31 '20 at 15:08
  • 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. – Diego R. Troncoso Jan 31 '20 at 15:24

1 Answers1

5

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:

Stradivari
  • 1,414
  • 6
  • 14
  • 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? – Diego R. Troncoso Jan 31 '20 at 18:01
  • 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 – Stradivari Jan 31 '20 at 18:07