problem with writing if statement using Boolean variable in CPLEX - c++

here is a part of my cplex code. i defined the PreReq as boolean variable but in the constraint i get the error for PreReq that "expression must have bool type" what am i doing wrong?
IloBoolVarArray2 PreReq(env), CoRec(env), Offered(env);
//Constraint 6: if course d is taken and course c is its pre-req, then course c must be taken before d
IloExpr constraint6a(env);
IloExpr constraint6b(env);
IloExpr constraint6c(env);
IloExpr constraint6d(env);
for (c = 0; c < NumberOfCourses; c++) {
for (d = 0; d < NumberOfCourses; d++) {
if (PreReq[c][d] == 1 ) {
for (s = 0; s < NumberOfSemesters; s++) {
constraint6a += X[d][s];
constraint6b += X[c][s];
constraint6c += s*X[c][s];
constraint6d += s*X[d][s];
}
}
}
mod.add(constraint6a <= constraint6b);
mod.add(constraint6c <= constraint6d + (NumberOfSemesters)*(1 - onstraint6a) );
constraint6a.end();
constraint6b.end();
constraint6c.end();
constraint6d.end();
}

You'd rather use IloIfThen (logical constraints)
The example in CPLEX documentation:
IloIfThen(env, (x >= y && x >= z), IloNot(x <= 300 || y >= 700))

Expanding on Alex's answer: your problem is that you are mixing constraints with constraint generation: In the statement if ( PreReq[c][d] == 1 ) the operator== is overloaded to generate a constraint that requires PreReq[c][d] to take the value 1. So the result in this expression is of type IloConstraint, which is not a boolean type (it is a constraint object instead). That is why you get the error message. What you want instead is to add a constraint to your model that requires additional constraints in case PreReq[c][d] is 1.
So you probably want something like this:
for (d = 0; d < NumberOfCourses; d++) {
for (s = 0; s < NumberOfSemesters; s++) {
mod.add(IloIfThen(PreReq[c][d] == 1, constraint6a + X[d][s] <= constraint6b + X[c][s]));
mod.add(IloIfThen(PreReq[c][d] == 0, constraint6a <= constraint6b));
}
}
Which adds two variants of the constraint, only one of which will ever be active (depending on the value of PreReq[c][d]). Also see the reference documentation of class IloIfThen.

Related

How does c++ evaluate assignment operators (if statement)

Consider the following
int main() {
int a = 8;
int b = 10;
while (true) {
if (a /= 2 && b < 12) {
b++;
std::cout << b << std::endl;
}
else break;
}
return 0;
}
Now c++ is not my main language, but how does c++ evaluate this if statement?
In this case, when b>=12, the compiler throws the "division by zero" exception, but why?
Now if i wrap the states in parentheses i do not get the exception.
if( (a /= 2) && (b < 12))
Does this have something to do with how c++ evaluates the statements?
If evaluation is not the problem:
I am aware of that
a = (a/2 && b<12)
would not hold either.
P Λ Q does not hold for P Λ ¬Q but the state of P should not be affected? Why is it P gets blamed instead of ¬Q?
if (a /= 2 && b < 12)
is the same as:
if (a /= (2 && b < 12))
so:
2 is evaluated, which is converted to true in the context of an operand to &&. This does not trigger short-circuit evaluation so we continue...
b < 12, which in the case you're talking about is false
So 2 && b < 12 evaluates to false overall
a /= 2 && b < 12 is therefore equivalent to a /= false here, which is equivalent to a /= 0.

CPLEX ILOG OPL Optimization

The model is optimizing the costs of Machines in Cell layout design
regarding the duplication and subcontracting.
Mod Const. is,
forall (k in 1..Cells, i in 1..nbMachines, j in 1..nbComps)
{
if (U[i][j][k] == 1 && A[k][i] < ((D[k][j]*S[k][j])*52))
DN[i][j][k] == 1;
SC[i][j][k] == 0;
INT[i][j][k] == 0;
}
forall (k in 1..Cells, i in 1..nbMachines, j in 1..nbComps)
{
if (V[i][j][k] == 1 && A[k][i] >= ((D[k][j]*S[k][j])*52))
DN[i][j][k] == 0;
SC[i][j][k] == 1;
INT[i][j][k] == 1;}
U , V are extracted in previous steps, A, D, S are input data.
The variables reqd. are DN, SC and INT.
Errors are those expressions are cannot be extracted, U, V are unbounded,
Please help in this regard,
Since U and V are decision variables, you should not write:
if (U[i][j][k] == 1 && A[k][i] < ((D[k][j]*S[k][j])*52))
DN[i][j][k] == 1;
Instead write:
((U[i][j][k] == 1) && (A[k][i] <= -1+((D[k][j]*S[k][j])*52)))
=> (DN[i][j][k] == 1);

How I can speed up my algorithm?

I'm solving some problems and I can't solve these one. I have to write a code where user enter a decimal number, and I need to count how many times that number starts with digit 1 in other numerous systems.
Here is algorithm:
for (int i = 3; i <= n; i++) {
int z = n;
while (z != 0) {
x = z % i;
z = z / i;
}
if (x == 1) {
brOsnova++;
}
}
You can accelerate it already by not checking the i's that verify
i <= n < 2*i since all of them will satisfy.
Therefore, check only for(int i = 3; i <= n/2; ++i) and then add (n+1)/2 to the final brOsnova.
I am sure it can be further accelerated and there must be some O(log(n)) algorithm, but maybe it would be far fetched... or a good candidate question for the algorithm tag.
Instead of the loop, use this:
x = x - ((x / i) * i);
if (x == 1)
{
...
}
This only works for integer maths.

Double comparison

Can I do this in C++?
if (4<5<6)
cout<<"valid"<<endl;
i.e a double comparison? Since I know that I can
bool a;
a = 1+2<3+4<5>6;//etc
Yes, you can do it, but it won't be what you expect. It's parsed as
if ( (4<5) < 6 )
which yields
if ( 1 < 6 )
because 4<5 evaluates to true which is promoted to 1, which yields, obviously, true.
You'll need
if ( (4<5) && (5<6) )
Also, yes, you can do
a = 1+2<3+4<5>6;
but that as well is parsed as
a = ((1+2)<((3+4)<5))>6;
which will evaluate to false since (1+2)<((3+4)<5) yields a boolean, which is always smaller than 6.
It compiles but won't do what you expect -
if( 4 < 5 < 2)
same as
if( (4 < 5) < 2)
same as
if( (1 < 2) ) //1 obtained from cast to boolean
which is of course true, even though I imagine you were expecting something quite different.
It may be clumsy but this will work:
int i, j, k;
i = 4; j = 5; k = 6;
if ( (i < j) && (j < k) )
{
cout << "Valid!" << endl;
}

How can I write a for loop with (a < b < c) under one statement?

I'm trying to do a for loop that looks like this.
int a = 3;
int b;
int c = 20;
for ( a = 1; a < b < c; ++a )
But the program doesn't work like this. How am i suppose to correctly state that stament in the middle a < b < c?
Change a < b < c to a < b && b < c
Explanation
The reason is that, < is evaluated from left-to-right, so your statement is evaluated like this:
a < b < c --> (a < b) < c
(a < b) is a boolean value (0 or 1) and c is being compared to that value.
If you have both a < b and b < c, since < is transitive, you would know that the mathematical a < b < c holds.
Note: Taking a look at the C operator precedence table, you can see that in the expression a < b && b < c, first a < b and b < c are evaluated, then the results are "and"ed.
Your example
In your example, since b is not set, a < b is not known, but whether it is 0 or 1, it is definitely smaller than c which is 20. So basically you've got an infinite loop.