How do I write such constraints in CPLEX (linear-programming) ?
forall(p in P, x in X, y in Y)
if ((remx[p,x] <= 0) OR (remy[p,y] <= 0)) then
pbl[p,x,y] == 0 // MUST be 0
else
pbl[p,x,y] == 1 OR == 0 // can be 0 or 1
where pbl is a decision variable (matrix), remx and remy is a normal matrix variable and p,x,y are indices.
I can not use if-then
Thanks,
I believe this cannot be done using (continuous) linear programming, but using mixed-integer programming we can use binary variables.
One way to attack this is using a bunch of inequalities, something like:
remx[p,x] <= 0 + bx[p,x]*M
remx[p,x] >= 0 - (1-bx[p,x])*M
remy[p,y] <= 0 + by[p,y]*M
remy[p,y] >= 0 - (1-by[p,y])*M
pbl[p,x,y] >= bx[p,x]+by[p,y]-1
pbl[p,x,y] <= bx[p,x]
pbl[p,x,y] <= bx[p,x]
bx[p,x],bx[p,x] in {0,1}
where M is indicating a sufficiently large number (they form a bound on remx and remy). Alternatively you can use the indicator constraints in Cplex to model implications:
bx[p,x]=0 => remx[p,x] <= 0
bx[p,x]=1 => remx[p,x] >= 0
by[p,y]=0 => remy[p,y] <= 0
by[p,y]=1 => remy[p,y] >= 0
pbl[p,x,y] = 1 => bx[p,x]+by[p,y] = 2
pbl[p,x,y] = 0 => bx[p,x]+by[p,y] <= 1
(Note: the question has changed, so these fragments are no longer 100% correct).
Related
I'm solving the following problem with cp_model from ortools.sat.python in Python, but I'm looking for a more efficient solver.
Problem:
Let's have n boolean variables A, B, C, ...
The goal is to find all possible/feasible combinations on boolean values that satisfy a set of rules. There are 3 types of rules:
One and only one of (A, B) might be true. I'm applying this as:
model.AddBoolXOr([A,B])
model.Add(A == False).OnlyEnforceIf(B)
model.Add(B == False).OnlyEnforceIf(A)
At most one of (C, D, E) might be true. I'm applying this as:
model.Add(C == False).OnlyEnforceIf(D)
model.Add(C == False).OnlyEnforceIf(E)
model.Add(D == False).OnlyEnforceIf(C)
model.Add(D == False).OnlyEnforceIf(E)
model.Add(E == False).OnlyEnforceIf(C)
model.Add(E == False).OnlyEnforceIf(D)
F is only possible when (A and ~C) or (B and (C or E)). First I'm converting this to CNF: (A or B) and (B or ~C) and (A or C or E). Then I insert that to the model:
model.Add(F == False).OnlyEnforceIf([A.Not(), B.Not()])
model.Add(F == False).OnlyEnforceIf([B.Not(), C])
model.Add(F == False).OnlyEnforceIf([A.Not(), C.Not(), E.Not()])
The result for above looks like:
1 0 0 0 0 0
1 0 1 0 0 0
1 0 0 1 0 0
1 0 0 0 1 0
1 0 0 0 1 1
1 0 0 0 0 1
1 0 0 1 0 1
0 1 0 0 1 1
0 1 0 0 1 0
0 1 0 0 0 0
0 1 0 1 0 0
0 1 1 0 0 0
0 1 1 0 0 1
Since my problem is big, I'm looking for a more efficient solution. I found minisat but I'm not sure if it is possible to express the above constraints in the DIMACS form and make minisat calculate all feasible solutions (by default it finds first and stops).
Is there any there solver capable of solving such a problem?
what a convoluted way of writing the model.
1)
model.Add(a + b == 1)
or
model.AddBoolOr([a, b])
model.AddImplication(a, b.Not())
model.AddImplication(b, a.Not())
model.Add(c + d + e <= 1)
or
model.AddImplication(c, d.Not())
model.AddImplication(c, e.Not())
model.AddImplication(d, c.Not())
model.AddImplication(d, e.Not())
model.AddImplication(e, c.Not())
model.AddImplication(e, d.Not())
Create 1 bool var for each and
(A and ~C) <=> G
model.AddImplication(G, A)
model.AddImplication(G, C.Not())
model.AddBoolOr([A.Not(), C, G.Not())
then F is only possible if x1 or x2 or x3
model.AddBoolOr([F.Not(), x1, x2, x3])
I am new to CPLEx and trying to set up my first problem. What I want to do set up a LP to minimise the sum of absolute deviations. I have set up the below as a start (based on googling possibilities). This is only a single deviation. I thought I would get this to work and then add to ti. It loads ok but won't solve. Can anyone shed some light on where I need to go next?
Minimize
obj: y1pos + y1neg
Subject To
c1: x0 + x1 + x2 + x3 = 1
c2: y1pos - y1neg + 451320 x0 + 500870 x1 + 483425 x2 + 447330 x3 = 58999
Bounds
0 <= x0 <= 1
0 <= x1 <= 1
0 <= x2 <= 1
0 <= x3 <= 1
y1pos >= 0
y1neg <= 0
End
As Erwin Kalvelagen suggested, changing y1neg <= 0 to y1neg >= 0 was the answer since our our error factor in our constraint is y1pos - y1neg which we want to minimise.
I have two dimensional array of chars, where all numbers, excluding one * (as given in picture (two examples)
My task is to sum up all neighbour integers ( in example 1, neighbours of * are 4,2,5,8 and sum is 4+2+5+8=19)
But in example 2, * doesn't have top neighbour.
My initial code was like:
arr[i-1][j] + arr[i+1][j] + arr[i][j-1] + arr[i][j+1]
But then I understood that in case like a[0][-1] doesn't exist. So can you help me to to solve my problem
You need to explicitly check each one. The following should work:
bool inRange(int i, int j) {
const auto n = 4; // you need to set this somewhere, or pass it in
return (i >= 0) && (i < n) && (j >= 0) && (j < n);
}
auto sum = (inRange(i-1, j) ? arr[i-1][j] : 0)
+ (inRange(i+1, j) ? arr[i+1][j] : 0)
+ (inRange(i, j-1) ? arr[i][j-1] : 0)
+ (inRange(i, j+1) ? arr[i][j+1] : 0);
You can probably write this a little cleaner, but you need to check not only for the -1, but also for when you go over 3.
There can be multiple solutions to this problem, but if you want to avoid checking bound each time you can extend the matrix dimension by 1 than needed. That means if you have an array:
1 * 4 7
8 9 2 3
5 1 2 4
4 3 6 5
Implement it as:
0 0 0 0 0 0
0 1 * 4 7 0
0 8 9 2 3 0
0 5 1 2 4 0
0 4 3 6 5 0
0 0 0 0 0 0
Doing this won't even affect your sum at the end.
I came across this template of C++
template <typename T> int sgn(T val) {
return (T(0) < val) - (val < T(0));
}
And I have to admit I don't really get it.
If I try to do a numeric application, let's say -1:
(0<(-1))-(-1 < 0) => False - True I get a subtraction of Bool.
Is that how it should work? Can someone explain the different steps the compiler will do?
It will return-1 if negative +1 if possitive 0 if 0
lets say -1:
(T(0) < val) - (val < T(0))
0<-1 false or 0
-
-1 < 0 true or 1
0 - 1 = -1
lets say 0
(T(0) < val) - (val < T(0))
0<0 false or 0
-
0 < 0 false or 0
0 - 0 = 0
lets say 1:
(T(0) < val) - (val < T(0))
0<1 true or 1
-
1 < 0 false or 0
1 - 0 = 1
There are implicit conversions happening there: True=>1 and False=>0.
You need to check both conditions to see if the value could be equal to zero - that's how signum is defined. If your interested in checking only greater or lower than 0, you could get away with a single comparison.
Nevertheless, having your example with -1 and the posted template, in result you get:
return False - True; => return 0 - 1; => return -1;
false and true would be converted to 0 and 1. So depending if one or both expressions evaluate to false, you get -1, 0, 1 results. That's a canon definition of signum function.
PS.Thats not an effective template, for better work there should be three specializations.
This question features answer that explains those:
Is there a standard sign function (signum, sgn) in C/C++?
So I'm working on the life game, and so far I have come up with this http://ideone.com/QG4tsS I'm not sure exactly if I am on the right track or not. Basically I have a function putting out random values to try and test my code. But nothing seems to happen. I suspect my problem lies with the following code
int sum = 0;
for (int k = (i - 1); k <= (i + 1); k++) {
for (int l = (j - 1); l <= (j + 1); l++) {
sum += currentGen[k][l];
}
}
return sum;
So my result gives me a 2d array with all 0's but shouldn't I start to see some changes and patterns starting to form? I get one 1 and the rest are 0.
Output
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 1
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
I provide this answer based on the code you posted at http://ideone.com/QG4tsS . You really should consider adding that code to your original question, so that future folks who find this on StackOverflow have the full context.
Your RandomCells function only sets cells to 1 if they meet the RANDOM threshold. It doesn't clear them to 0 otherwise. Once you fix that, you'll be all set. ie.
void RandomCells(int currentGen[][CELLY]) {
for (int i = 0; i < CELLX; i++) {
for (int j = 0; j < CELLY; j++) {
if (rand() % 100 + 1 < RANDOM) {
currentGen[i][j] = 1;
} else
{
currentGen[i][j] = 0;
}
}
}
}
Without that else clause, I was seeing initial generations that looked like this:
0 0 4196155 1
1813657216 1 4197653 0
-870503576 1 4197584 1
Clearly, most of those cells were non-zero, and so Conway's Life algorithm would map them to 0 in the next generation because of "crowding".
The reason currentGen was filled with such 'random' values is that it was allocated as an automatic variable to main. Automatic variables do not get initialized to any particular value. You need to initialize them yourself. You can do that by modifying your algorithm (as I did above), or by adding an explicit bit of code to initialize the structure.
This differs from file-scope variables, which C and C++ define as initialized-to-zero on program start if they don't have initializers or default constructors. (Pedants will point out that even that has caveats.)
Once you make the required fixes, to truly see Conway's Life, you'll need to set CELLX and CELLY to larger values...