Efficient way of finding all feasible solutions to set of Boolean constrains - combinations

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

Related

How to code: "If (A is True) and (B is True when C is True)"

How do I code this if statement (let's say in c++):
if (condition1 == true and condition2 == true (when condition3 == true))
{
// condition2 need to be true only when condition3 is true
}
When figuring out how to express any boolean-predicate it helps to build a truth-table that lists the possible values of each boolean value in separate columns and the expected output in its own column. The values in each column increment by +1 as though each column is a binary-digit in a base-2 number.
Like so:
A B C Output
---------------------
0 0 0 ?
0 0 1 ?
0 1 0 ?
0 1 1 ?
1 0 0 ?
1 0 1 ?
1 1 0 ?
1 1 1 ?
Based on your question's title (and not the example pseudocode that you posted), I assume you want this output:
A B C Output
---------------------
0 0 0 0
0 0 1 0
0 1 0 0
0 1 1 0
1 0 0 0
1 0 1 0
1 1 0 0
1 1 1 1
...which is just a trivial AND between all 3 values:
bool a = ...
bool b = ...
bool c = ...
if( a && b && c )
{
do_the_thing();
}

Extract submatrix of unknown size from bigger matrix while values are equal to specified value

So let's say we have this matrix:
0 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0
0 1 1 1 0 0 0 0
0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 0
0 0 0 0 1 1 1 0
And we need those outputs:
Submatrix 1:
1 1 1
1 1 1
1 1 1
Submatrix 2:
1 1 1
1 1 1
The matrix size can vary, so can the submatrix sizes but they will have either square or rectangle shape. And is only 0 and 1.
How can i do that? Is there any algorithm to do that?
for (i=0; i<m;i++){
for (j=2; j<n; j++){
if ( A[i+1,j]==1 && A[i,j+1]==1 || A[i+1,j]==1 && A[i,j-1]==1 || A[i-1,j]==1 && A[i,j+1]==1 || A[i-1,j]==1 && A[i,j-1]==1 || A[i-1,j]==1 && A[i+1,j]==1 && A[i,j-1]==1 && A[i,j+1]==1 )
B[i,j]=A[i,j];
}
}
This is the first ideea that comes to my mind, but i don't know how to stop after i'm done with the first block of ones, and in the end the matrix B is the same as matrix A. Also i don't know how to set the submatrix size to be exactly the size that it needs to be. For now i'm only trying to break the big matrix in 2. Should i allocate the submatrix dynamically?

How to format & write desired components of two arrays in a specified order to each line of a text file?

This is my code:
Program Arrays
Implicit none
Integer::i
Integer,parameter,dimension(3,4)::Fir_array=0,Sec_array=1
Open(Unit=15,File='Output.txt',Status='Unknown',Action='Readwrite')
Do concurrent(i=1:3)
Write(15,'(1x,i0,".",4(2x,i0,1x,i0))') i,Fir_array(i,:),Sec_array(i,:)
End Do
Close(Unit=15,Status='Keep')
End Program Arrays
The content of Output.txt is:
1. 0 0 0 0 1 1 1 1
2. 0 0 0 0 1 1 1 1
3. 0 0 0 0 1 1 1 1
My intention with this code is to get this content in Output.txt:
1. 0 1 0 1 0 1 0 1
2. 0 1 0 1 0 1 0 1
3. 0 1 0 1 0 1 0 1
How to do that with do loops or implied do?
As usual, there is more than one way of going about this, but the first thing that came to my mind would be to place the desired components of fir_array and sec_array into a temporary array, in the desired order, and then print it.
! Add the following variables to your code:
integer, dimension(8) :: temp
integer :: d1
! Begin:
d1 = size(fir_array, dim=1)
do i = 1, d1
temp([1,3,5,7]) = fir_array(i,:) !! If you're clever you can create a scheme to
temp([2,4,6,8]) = sec_array(i,:) !! obtain the proper indices for arrays of any size.
write(15, '(1x,i0,".",4(2x,i0,1x,i0))') i, temp
enddo
You get the output desired:
0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1

Performing MCDC for a condition (A && B && C) || D

I have a situation where I need to write few test cases to get complete coverage of the code.
At a perticular branch I got following situation
if((A && B && C) || D)
if((A && B && C) || D)
{
//perform task 1'
}
else
{
//perform task 2;
}
But with this I am unable to get test case combination for MCDC..
What could be the way out here...
Your way out could be to use the tool MCDC to identify possible test cases.
Doing this manually could be really a lot of work, because of the many possible test pair combinations.
I am sorry that I cannot share all the details of my research. I would recomend to start with reading "An Investigation of Three Forms of the Modified Condition Decision Coverage (MCDC) Criterion", published by the FAA (DOT/FAA/AR-01/18).
Including Masking there are 52 possible test pairs. If you do a proper WhiteBox Analysis, including boolean short cut evaluation, then you will find even 63 MCDC test pairs. Apllying the set cover algorithm will result in 3 possible minimum test sets.
Doing some heuristics will lead to the maybe surprising test vector:
Test Pair for Condition 'a': 0 14 (Unique Cause)
Test Pair for Condition 'b': 8 14 (Unique Cause)
Test Pair for Condition 'c': 12 14 (Unique Cause)
Test Pair for Condition 'd': 0 1 (Unique Cause)
Testvector: Recommended Result: 0 1 8 12 14
0: a=0 b=0 c=0 d=0 (0)
1: a=0 b=0 c=0 d=1 (1)
8: a=1 b=0 c=0 d=0 (0)
12: a=1 b=1 c=0 d=0 (0)
14: a=1 b=1 c=1 d=0 (1)
With MC/DC you have to find, for each condition (input) i, a pair of combinations where only i toggles, and the output changes. For A to have a toggling effect on the result of (A && B && C) || D, B and C need to be true and D needs to be false. Similarly, for B to have a toggling effect, A and C need to be true, and D needs to be false. With D it is a bit different: The output toggles on D given that at least one of A, B, C is false. This gives the following combinations (x represents the toggling input):
A B C D
x 1 1 0 - for A
1 x 1 0 - for B
1 1 x 0 - for C
q r s x - for D, where q + r + s < 3
By multiplying out the lines for A, B, and C we get (added lines numbers and column R for the result):
# A B C D R
1 0 1 1 0 0 - for A
2 1 1 1 0 1 - for A
3 1 0 1 0 0 - for B
4 1 1 1 0 1 - for B (duplicate)
5 1 1 0 0 0 - for C
6 1 1 1 0 1 - for C (duplicate)
7 q r s x - for D, where q + r + s < 3
Lines 4 and 6 are duplicates of line 2. To represent line 7, we can use one of the lines 1,3,5 and add the same line with D set to 1, which gives the following result (picked line 1):
# A B C D R
1 0 1 1 0 0 - for A and D
2 1 1 1 0 1 - for A,B,C
3 1 0 1 0 0 - for B
4 1 1 0 0 0 - for C
5 0 1 1 1 1 - for D
That's one possible solution.
I think one way could be for all the false combination of (A && B && C) keep D = 1 and for true combination of (A && B && C) keep D = 0 and at the last Keep all inputs 0. So test case combination can be:
a b c d
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
0 0 0 0

Bitwise operation to get 1 if both are 0

I'd need to perform a bitwise operation (or a serie) so that:
0 1 = 0
1 1 = 1
1 0 = 0
so far AND (&) works fine but I also need that
0 0 = 1
and here AND (&) is not the correct one.
I'm using it in a jquery grep function that reads:
jQuery.grep(json, function (e, index) {
return (e.value & (onoff << 3)) != 0;
});
where onoff could be either 1 or 0 and e.value is a representation of a 4 bits string (i.e. could be "1001"). In this above example I'm testing first bit on the left (<< 3).
Can this be done with a serie of AND, OR, XOR?
This is just XNOR(a, b), which is equal to NOT(XOR(a, b)), i.e. exclusive OR with the output inverted. In C and C-like languages this would be:
!(a ^ b)
or in your specific case:
return !((e.value >> 3) ^ onoff);
Having said that, you could just test for equality:
return (e.value >> 3) == onoff;
This looks roughly like XOR which has the following results table:
0 0 = 0
0 1 = 1
1 0 = 1
1 1 = 0
Now you want to have the opposite, meaning that you want 1 if both inputs are the same value. And this leads us to NOT XOR
0 0 = 1
0 1 = 0
1 0 = 0
1 1 = 1