boolean sat check my code - python

I am getting a wrong answer for my code
n is the number of variables
and formula is a list containing clauses
Given a SAT instance with 'n' variables and clauses encoded in list 'formula',
returns 'satisfiable' if the instance is satisfiable, and 'unsatisfiable'
otherwise. Each element of 'formula' represents a clause and is a list of
integers where an integer i indicates that the literal Xi is present in the
clause and an integer -i indicates that the literal ~Xi is present in the
clause. For example, a clause "X1 v ~X11 v X7" is represented with the list
[1, -11, 7].
import itertools
n = 4
formula = [[1, -2, 3], [-1, 3], [-3], [2, 3]]
booleanValues = [True,False] * n
allorderings = set(itertools.permutations(booleanValues, n)) #create possible combinations of variables that can check if formula is satisfiable or not
print(allorderings)
for potential in allorderings:
l = [] #boolean value for each variable / different combination for each iteration
for i in potential:
l.append(i)
#possible = [False]*n
aclause = []
for clause in formula:
something = []
#clause is [1,2,3]
for item in clause:
if item > 0:
something.append(l[item-1])
else:
item = item * -1
x = l[item-1]
if x == True:
x = False
else:
x = True
something.append(x)
counter = 0
cal = False
for thingsinclause in something:
if counter == 0:
cal = thingsinclause
counter = counter + 1
else:
cal = cal and thingsinclause
counter = counter + 1
aclause.append(cal)
counter2 = 0
formcheck = False
for checkformula in aclause:
if counter2 == 0:
formcheck = checkformula
counter2 = counter2 + 1
else:
formcheck = formcheck or checkformula
print("this combination works", checkformula)

Here is a corrected version:
import itertools
n = 4
formula = [[1, -2, 3], [-1, 3], [-3], [2, 3]]
allorderings = itertools.product ([False, True], repeat = n)
for potential in allorderings:
print ("Initial values:", potential)
allclauses = []
for clause in formula:
curclause = []
for item in clause:
x = potential[abs (item) - 1]
curclause.append (x if item > 0 else not x)
cal = any (curclause)
allclauses.append (cal)
print ("Clauses:", allclauses)
formcheck = all (allclauses)
print ("This combination works:", formcheck)
Points to consider:
Instead of introducing some complex — and also wrong — logic to find the conjunction and disjunction, you can use any and all. That's cleaner and less prone to bugs.
The natural object to loop over is itertools.product([False, True], repeat = n), that is, the set [False, True] of possible boolean values raised to the power of n. In other words, the Cartesian product of n copies of [False, True]. Here is the documentation for itertools.product.
I introduced a bit more output to see how things are going. Here is the output I get with Python3 (Python2 adds parentheses but prints essentially the same):
Initial values: (False, False, False, False)
Clauses: [True, True, True, False]
This combination works: False
Initial values: (False, False, False, True)
Clauses: [True, True, True, False]
This combination works: False
Initial values: (False, False, True, False)
Clauses: [True, True, False, True]
This combination works: False
Initial values: (False, False, True, True)
Clauses: [True, True, False, True]
This combination works: False
Initial values: (False, True, False, False)
Clauses: [False, True, True, True]
This combination works: False
Initial values: (False, True, False, True)
Clauses: [False, True, True, True]
This combination works: False
Initial values: (False, True, True, False)
Clauses: [True, True, False, True]
This combination works: False
Initial values: (False, True, True, True)
Clauses: [True, True, False, True]
This combination works: False
Initial values: (True, False, False, False)
Clauses: [True, False, True, False]
This combination works: False
Initial values: (True, False, False, True)
Clauses: [True, False, True, False]
This combination works: False
Initial values: (True, False, True, False)
Clauses: [True, True, False, True]
This combination works: False
Initial values: (True, False, True, True)
Clauses: [True, True, False, True]
This combination works: False
Initial values: (True, True, False, False)
Clauses: [True, False, True, True]
This combination works: False
Initial values: (True, True, False, True)
Clauses: [True, False, True, True]
This combination works: False
Initial values: (True, True, True, False)
Clauses: [True, True, False, True]
This combination works: False
Initial values: (True, True, True, True)
Clauses: [True, True, False, True]
This combination works: False

Related

How can I shorten this 2D array code?

I have the following snippet which works fine.
P=im1.copy()
for i in range(P.shape[0]):
for j in range(P.shape[1]):
if (n_dens.data[i][j]==-5000 or T_k.data[i][j]==-5000):
P.data[i][j]=-5000
else :
P.data[i][j]=n_dens.data[i][j]*T_k.data[i][j]
where P is a 2D array.
I was wondering how to trim this down to something along the following lines:
P.data=n_dens.data*T_k.data
P.data=[foo-2.5005*10**7 if n_dens.data==-5000 or T_k.data==-5000 else foo for foo in P.data]
For my trial above I get the following error:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
How can I correct the error? Or is there another method to trim it down?
The n_dens.data==-5000 produces an array of true/false values, not a single value. So, the if can't handle it. You are close to the idea though. You can use logical indexing in numpy.
Also logical operators cannot be overloaded in python. So, numpy does not handle them as you would wish. So, you have to do something like
index = np.logical_or(n_dens.data ==-5000, T_k.data==-5000)
P.data[index] = -5000
Similarly, P.data[np.logical_not(index)] = n_dens.data * T.data for the second branch of if-else.
You can try this:
P.data[(n_dens.data == -5000) | (T_k.data == -5000)] = -5000
cond = ~(n_dens.data == -5000) & ~(T_k.data == -5000) # 2D array of booleans
P.data[cond] = n_dens.data[cond] * T_k.data[cond]
A complete example:
import numpy as np
from copy import deepcopy
class IMAGE:
def __init__(self, data):
self.data = data
self.shape = self.data.shape
np.random.seed(0)
P, n_dens, T_k = IMAGE(np.zeros((5,5))), IMAGE(np.reshape(np.random.choice([-5000,1,2],25), (5,5))), IMAGE(3*np.ones((5,5)))
P1 = deepcopy(P)
# with loop
for i in range(P.shape[0]):
for j in range(P.shape[1]):
if (n_dens.data[i][j]==-5000 or T_k.data[i][j]==-5000):
P.data[i][j]=-5000
else :
P.data[i][j]=n_dens.data[i][j]*T_k.data[i][j]
# vectorized
P1.data[(n_dens.data == -5000) | (T_k.data == -5000)] = -5000
cond = ~(n_dens.data == -5000) & ~(T_k.data == -5000) # 2D array of booleans
P1.data[cond] = n_dens.data[cond] * T_k.data[cond]
cond
# array([[False, True, False, True, True],
# [ True, False, True, False, False],
# [False, True, True, True, True],
# [False, True, True, True, True],
# [False, True, False, False, True]], dtype=bool)
# with same output for both
P.data == P1.data
# array([[ True, True, True, True, True],
# [ True, True, True, True, True],
# [ True, True, True, True, True],
# [ True, True, True, True, True],
# [ True, True, True, True, True]], dtype=bool)

Logical operation between two Boolean lists

I get a weird result and I try to apply the and or the or operator to 2 Boolean lists in python. I actually get the exact opposite of what I was expecting.
[True, False, False] and [True, True, False]
> [True, True, False]
[True, False, False] or [True, True, False]
> [True, False, False]
Is that normal, and if yes, why?
If what you actually wanted was element-wise boolean operations between your two lists, consider using the numpy module:
>>> import numpy as np
>>> a = np.array([True, False, False])
>>> b = np.array([True, True, False])
>>> a & b
array([ True, False, False], dtype=bool)
>>> a | b
array([ True, True, False], dtype=bool)
This is normal, because and and or actually evaluate to one of their operands. x and y is like
def and(x, y):
if x:
return y
return x
while x or y is like
def or(x, y):
if x:
return x
return y
Since both of your lists contain values, they are both "truthy" so and evaluates to the second operand, and or evaluates to the first.
I think you need something like this:
[x and y for x, y in zip([True, False, False], [True, True, False])]
Both lists are truthy because they are non-empty.
Both and and or return the operand that decided the operation's value.
If the left side of and is truthy, then it must evaluate the right side, because it could be falsy, which would make the entire operation false (false and anything is false). Therefore, it returns the right side.
If the left side of or is truthy, it does not need to evaluate the right side, because it already knows that the expression is true (true or anything is true). So it returns the left side.
If you wish to perform pairwise comparisons of items in the list, use a list comprehension, e.g.:
[x or y for (x, y) in zip(a, b)] # a and b are your lists
Your lists aren't comparing each individual value, they're comparing the existence of values in the list.
For any truthy variables a and b:
a and b
> b #The program evaluates a, a is truthy, it evaluates b, b is truthy, so it returns the last evaluated value, b.
a or b
> a #The program evaluates a, a is truthy, so the or statement is true, so it returns the last evaluated value, a.
Now, truthy depends on the type. For example, integers are truthy for my_int != 0, and are falsy for my_int == 0. So if you have:
a = 0
b = 1
a or b
> b #The program evaluates a, a is falsy, so the or statement goes on to evaluate b, b is truthy, so the or statement is true and it returns the last evaluated value b.
Very convenient way:
>>> import numpy as np
>>> np.logical_and([True, False, False], [True, True, False])
array([ True, False, False], dtype=bool)
>>> np.logical_or([True, False, False], [True, True, False])
array([ True, True, False], dtype=bool)
Мore functional:
from operator import or_, and_
from itertools import starmap
a = [True, False, False]
b = [True, True, False]
starmap(or_, zip(a,b)) # [True, True, False]
starmap(and_, zip(a,b)) # [True, False, False]

Convert 4-bit integer into Boolean list

I have an integer of which I know that it's between 0 and 15, i.e., can be expressed in 4 bits. I would like to get the bit representation of that array as a Boolean array, i.e.,
0: [False, False, False, False],
1: [True, False, False, False],
2: [False, True, False, False],
# [...]
15: [True, True, True, True]
How can I best achieve that?
Through formatting as binary:
def int_to_bool_list(num):
bin_string = format(num, '04b')
return [x == '1' for x in bin_string[::-1]]
or bitwise and:
def int_to_bool_list(num):
return [bool(num & (1<<n)) for n in range(4)]
The first function requires that the bin_string contents be reversed (with [::-1]) because string formatting formats the number the way we read it - most significant bit first, whereas the question asked for the bits in least significant bit first order.
With list comprehension:
my_int = 3
[b == '1' for b in bin(my_int)[2:].rjust(4)[::-1]] # Convert, pad and reverse
output:
[True, True, False, False]
1 2 4 8 = 3
Try that:
Bitmasks = []
Bitmasks.append(int("0001", 2))
Bitmasks.append(int("0010", 2))
Bitmasks.append(int("0100", 2))
Bitmasks.append(int("1000", 2))
myNumber = 12
Bools = []
for bm in Bitmasks:
Bools.append(myNumber|bm==myNumber)
R = 16
list = []
print bin(R)[2:]
for i in bin(R)[2:]:
if (i=="1"):
list.append(True)
else:
list.append(False)
print list
output-click here
[True, False, False, False, False]
x = 7
strBin = str(bin(x))
lsBoolVal = [i == '1' for i in strBin[2:].zfill(4)]

How to construct logical expression for advanced slicing

I am trying to figure out a cleaner way of doing the following:
import numpy
a = np.array([1,2,4,5,1,4,2,1])
cut = a == (1 or 2)
print cut
[ True False False False True False False True]
The above is of course a simplified example. The expression (1 or 2) can be large or complicated. As a start, I would like to generalize this thusly:
cutexp = (1 or 2)
cut = a == cutexp
Maybe, cutexp can be turned into a function or something but I'm not sure where to start looking.
You could also try numpy.in1d. Say
>>> a = np.array([1,2,4,5,1,4,2,1])
>>> b = np.array([1,2]) # Your test array
>>> np.in1d(a,b)
array([ True, True, False, False, True, False, True, True], dtype=bool)
>>> (a == 2) | (a == 1)
array([ True, True, False, False, True, False, True, True], dtype=bool)

Bitmask parsing in python using only standard library

I want to parse an integer that is unpack()ed using the struct module to a list of truth values.
My current approach is this:
>>> [bool(int(_)) for _ in ("%8s" % str(bin(235)).split("b")[1]).replace(" ","0")]
[True, True, True, False, True, False, True, True]
It does the job, but is quite horribly convoluted. Anyone have an elegant and pythonesque way of doing the same?
Please note that above is just for an example and the bitmasks are not necessarily just 8 bits long, but the solution should work for an bitmask of arbitrary length (in practice it might be ok to just work with multiples of 4)
Arithmetic done elegantly, without C-style proceduralism:
size = 8
[bool(235 & (1 << size - i - 1)) for i in xrange(size)]
How about:
>>> masklen = 8
>>> [bool(int(i)) for i in str(bin(235))[2:].rjust(masklen, '0')]
[True, True, True, False, True, False, True, True]
So if you skip pack step and just use the integer:
def bitboollist(v,n=0):
l = []
t = v
while t != 0:
l.append(bool(t % 2))
t = t / 2
l.reverse()
if len(l) == 0:
l = [False]
if n > len(l):
l = [False]*(n-len(l)) + l
return l
using that on an example 1234 yields:
>>> bitboollist(1234)
[True, False, False, True, True, False, True, False, False, True, False]
>>> bitboollist(1234,n=16)
[False, False, False, False, False, True, False, False, True, True, False, True, False, False, True, False]

Categories