Creating a truth table for any expression in Python - python

I am attempting to create a program that when run will ask for the boolean expression, the variables and then create a truth table for whatever is entered. I need to use a class and this is what I have so far. I am not sure where to go from here.
from itertools import product
class Boolean(object):
def __init__(self, statement, vars):
self.exp = statement
self.vars = vars
def __call__(self, statement, vars):
def main():
expression = raw_input('Give an expression:')
vars = raw_input('Give names of variables:')
variables = vars.split(' ')
b = Boolean(expression, variables)
if __name__ == "__main__":
main()

I have a library that does exactly what you want!
Check out the github repo or find it here on pypi.
The readme describes how everything works, but here's a quick example:
from truths import Truths
print Truths(['a', 'b', 'x', 'd'], ['(a and b)', 'a and b or x', 'a and (b or x) or d'])
+---+---+---+---+-----------+--------------+---------------------+
| a | b | x | d | (a and b) | a and b or x | a and (b or x) or d |
+---+---+---+---+-----------+--------------+---------------------+
| 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 0 | 0 | 0 | 1 | 0 | 0 | 1 |
| 0 | 0 | 1 | 0 | 0 | 1 | 0 |
| 0 | 0 | 1 | 1 | 0 | 1 | 1 |
| 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 0 | 0 | 1 |
| 0 | 1 | 1 | 0 | 0 | 1 | 0 |
| 0 | 1 | 1 | 1 | 0 | 1 | 1 |
| 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 0 | 0 | 1 | 0 | 0 | 1 |
| 1 | 0 | 1 | 0 | 0 | 1 | 1 |
| 1 | 0 | 1 | 1 | 0 | 1 | 1 |
| 1 | 1 | 0 | 0 | 1 | 1 | 1 |
| 1 | 1 | 0 | 1 | 1 | 1 | 1 |
| 1 | 1 | 1 | 0 | 1 | 1 | 1 |
| 1 | 1 | 1 | 1 | 1 | 1 | 1 |
+---+---+---+---+-----------+--------------+---------------------+
Hope this helps!

You could simply define any boolean function right in python.
consider the following example:
def f(w,x,y,z):
return (x and y) and (w or z)
I've wrote a snippet that takes any function f, and returns its truth table:
import pandas as pd
from itertools import product
def truth_table(f):
values = [list(x) + [f(*x)] for x in product([False,True], repeat=f.func_code.co_argcount)]
return pd.DataFrame(values,columns=(list(f.func_code.co_varnames) + [f.func_name]))
Using this will yield (in a nicely formatted html if you're using IPython Notebook):
truth_table(f)
w x y z f
0 False False False False False
1 False False False True False
2 False False True False False
3 False False True True False
4 False True False False False
5 False True False True False
6 False True True False False
7 False True True True True
8 True False False False False
9 True False False True False
10 True False True False False
11 True False True True False
12 True True False False False
13 True True False True False
14 True True True False True
15 True True True True True
Cheers.

You probably want to do something like this:
from itertools import product
for p in product((True, False), repeat=len(variables)):
# Map variable in variables to value in p
# Apply boolean operators to variables that now have values
# add result of each application to column in truth table
pass
But the inside of the for loop is the hardest part, so good luck.
This is an example of what you would be iterating over in the case of three variables:
>>> list(product((True, False), repeat=3))
[(True, True, True), (True, True, False), (True, False, True), (True, False, False), (False, True, True), (False, True, False), (False, False, True), (False, False, False)]

If you don't mind providing the number of variables of the function (I think it is possible to get but I don't know how at this moment). I have the following:
from itertools import product
B = {0,1}
varNames= ["r","s","t","u","v","w","x","y","z"]
def booltable(f,n):
vars = varNames[-n:]
header = vars + ["f"]
table = [*reversed([*map(lambda input: [*input,f(*input)], product(B,repeat=len(vars)))])]
return [header] + table
If you want to have your 1's at the top (like I do), just reverse the answer.
return [*reversed([*map(lambda input: [*input,f(*input)],product(B,repeat=len(vars)))])]
Here is an example of how to use it, functions are defined using bitwise operations.
x | y - bitwise or of x and y
x ^ y - bitwise exclusive or of x and y
x & y - bitwise and of x and y
~x - the bits of x inverted
# Example function
def aBooleanFunction(x,y,z):
return (x | y) ^ ~(x ^ z) % 2
# Run
display(booltable(aBooleanFunction,3))
The output is:
[['x', 'y', 'z', 'f'],
[1, 1, 1, 0],
[1, 1, 0, 1],
[1, 0, 1, 0],
[1, 0, 0, 1],
[0, 1, 1, 1],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]]
You can then parse this to a table in whatever format you want using, for example, tabulate.

Related

Python. Dataframes. Select rows and apply condition on the selection

python newbie here. I have written the code that solves the issue. However, there should be a much better way of doing it.
I have two Series that come from the same table but due to some earlier process I get as separate sets. (They could be joined into a single dataframe again since the entries belong to the same record)
Ser1 Ser2
| id | | section |
| ---| |-------- |
| 1 | | A |
| 2 | | B |
| 2 | | C |
| 3 | | D |
df2
| id | section |
| ---|---------|
| 1 | A |
| 2 | B |
| 2 | Z |
| 2 | Y |
| 4 | X |
First, I would like to find those entries in Ser1, which match the same id in df2. Then, check if the values in the ser2 can NOT be found in the section column of df2
My expected results:
| id | section | result |
| ---|-------- |---------|
| 1 | A | False | # Both id(1) and section(A) are also in df2
| 2 | B | False | # Both id(2) and section(B) are also in df2
| 2 | C | True | # id(2) is in df2 but section(C) is not
| 3 | D | False | # id(3) is not in df2, in that case the result should also be False
My code:
for k, v in Ser2.items():
rslt_df = df2[df2['id'] == Ser[k]]
if rslt_df.empty:
print(False)
if(v not in rslt_df['section'].tolist()):
print(True)
else:
print(False)
I know the code is not very good. But after reading about merging and comprehension lists I am getting confused what the best way would be to improve it.
You can concat the series and compute the "result" with boolean arithmetic (XOR):
out = (
pd.concat([ser1, ser2], axis=1)
.assign(result=ser1.isin(df2['id'])!=ser2.isin(df2['section']))
)
Output:
id section result
0 1 A False
1 2 B False
2 2 C True
3 3 D False
Intermediates:
m1 = ser1.isin(df2['id'])
m2 = ser2.isin(df2['section'])
m1 m2 m1!=m2
0 True True False
1 True True False
2 True False True
3 False False False

set df to value between tuple

i would like to set a df value between two values x_lim(0,2) to True.
I would like to get a df that looks like this:
x | y | z
0 | 7 | True
1 | 3 | True
2 | 4 | True
3 | 8 | False
i tried :
def set_label(df, x_lim, y_lim, variable):
for index, row in df.iterrows():
for i in range(x_lim[0],x_lim[1]):
df['Label'] = variable.get()
print(df)
could anyone help me to solve this problem ?

Working with python, do I need to write down AST to evaluate a boolean function?

I am working on a project, one part of it is to generate a truth table for a given boolean expression ( such as: (A NOT B) NOR (C OR D)). I could not find a built in bitwise operator for NOR gate, so I wrote a code of my own for it, which works good with simple expressions. But if brackets are introduced for unambiguity and false results, the code does a terrible job. [for example, for the expression mentioned above, it gives an output of (a~b~()|()c|d)]
Here is the code snippet:
# to replace NOR gate with bitwise NOR operation of ~(var_a | var_b)
for m in range(0,len(expression)):
v=len(expression)
for v in range(0,len(expression)):
if (expression[v]=="!"):
prev='~(' + expression[v-1]
nextt=expression[v+1]+')'
replacement= prev + "|" + nextt
leftear= expression[:v-1]
rightear=expression[v+2:]
print('left right ears:',leftear,rightear)
expression= leftear+replacement+rightear
print('expression refined= X= ',expression)
The only solution that I found on google was to write a parse tree (which python says that, it has been deprecated so we are recommended to use AST). I am a total beginner and search out a little bit about parse trees, but I wanted to ask:
1)Is the AST or parsers the only way to do it? Are there any built in functions for it in python?
2) Whats the better way of handeling NOR gate ?
Why does it have to be bitwise? Judging from your example, you could just use the normal Boolean operators.
It's true there is no nor in Python, but you can easily translate it, because E NOR F equals NOT E AND NOT F, and not and and are available in Python.
For example:
from itertools import product
print(' A | B | C | D | (A AND NOT B) NOR (C OR D)')
print('---------------------------------------------------')
for a, b, c, d in product((True, False), repeat=4):
result = not (a and not b) and not (c or d)
print('{:^5}|{:^5}|{:^5}|{:^5}|{:^34}'.format(a, b, c, d, result))
A | B | C | D | (A AND NOT B) NOR (C OR D)
---------------------------------------------------
1 | 1 | 1 | 1 | 0
1 | 1 | 1 | 0 | 0
1 | 1 | 0 | 1 | 0
1 | 1 | 0 | 0 | 1
1 | 0 | 1 | 1 | 0
1 | 0 | 1 | 0 | 0
1 | 0 | 0 | 1 | 0
1 | 0 | 0 | 0 | 0
0 | 1 | 1 | 1 | 0
0 | 1 | 1 | 0 | 0
0 | 1 | 0 | 1 | 0
0 | 1 | 0 | 0 | 1
0 | 0 | 1 | 1 | 0
0 | 0 | 1 | 0 | 0
0 | 0 | 0 | 1 | 0
0 | 0 | 0 | 0 | 1
Assuming you can also use prefix notation, you might be able to use the
sympy library.
Below is a small program that demonstrates using it for
a sample expression derived from your question, with some code at the
end to generate the truth table for the expression using the satisfiable
function, which generates all possible models for the logic expression.
import itertools
from sympy import *
from sympy.logic import simplify_logic
from sympy.logic.inference import satisfiable
my_names = 'ABCD'
A,B,C,D = symbols(','.join(my_names))
e1 = Nor(Nor(A, B), Or(C, D))
e2 = ~(~(A | B) | (C | D))
print('e1 and e2 are same:', e1 == e2)
print(simplify_logic(e1))
my_symbols = sorted(e1.atoms(Symbol), key=lambda x: x.name)
print('Set of symbols used:', my_symbols)
models = satisfiable(e1, all_models=True)
sat_mods = []
for m in models:
sat_mods.append(dict(sorted(m.items(), key=lambda x: x[0].name)))
truth_tab = []
for c in itertools.product((True, False), repeat=4):
model = dict(zip(my_symbols, c))
truth_tab.append((model, model in sat_mods))
print(truth_tab)
Output:
# e1 and e2 are same: True
# ~C & ~D & (A | B)
# Set of symbols used: [A, B, C, D]
# [({A: True, B: True, C: True, D: True}, False),
# ({A: True, B: True, C: True, D: False}, False),
# ...

Calculate True Positives and False Negatives for Responses Within a DataFrame

I have survey results which I have one-hot encoded. I would like to calculate the sensitivity of each participant's response.
The below is an example of how my DataFrame is structured, whereby:
'Chocolate' and 'Ice-Cream' are correct
'Pizza' and 'None of the Above' are incorrect
Question 1 | Chocolate | Pizza | Ice-Cream | None of the Above |
Participant ID | | | | |
1 | 1 | 1 | 1 | 0 |
2 | 0 | 0 | 1 | 0 |
3 | 1 | 0 | 1 | 0 |
I would like to append a column that contains the sum of true positives and another with the sum of false negatives, to then create another with the sensitivity score (for each participant).
The below is an example of what I am trying to do:
Question 1 | Chocolate | ... | True Positive | False Negative | ..
Participant ID | | | | |
1 | 1 | ... | 2 | 0 | ..
2 | 0 | ... | 1 | 1 | ..
3 | 1 | ... | 2 | 1 | ..
I am not sure where to begin with this! Can anyone help me out?
Thanks a lot!
You could calculate the 'true pos', false neg' etc by using a confusion matrix (e.g. from Sklearn). Maybe the following code is usefull for you:
import pandas as pd
import sklearn
from sklearn.metrics import confusion_matrix
a = [[1,1,1,0], [0,0,1,0], [1,0,1,0]]
correct = [[1,0,1,0], [1,0,1,0], [1,0,1,0]]
df = pd.DataFrame(data=a)
df.columns=['chocolate', 'pizza', 'icecream', 'none']
for i in range(len(df)):
pred = a[i]
true = correct[i]
tn, fp, fn, tp = confusion_matrix(true,pred).ravel()
print (f'Nr:{i} true neg:{tn} false pos:{fp} false neg:{fn} true pos:{tp}')
The output is (which you could put in a DataFrame):
Nr:0 true neg:1 false pos:1 false neg:0 true pos:2
Nr:1 true neg:2 false pos:0 false neg:1 true pos:1
Nr:2 true neg:2 false pos:0 false neg:0 true pos:2

Pandas logical operation not applied

i want to give if condition in my pandas column, but nothing applied. I had check dtypes of column and it said Float32, am i wrong in any typing or somewhat i dont know
i had tried this code :
How to use numpy.where with logical operators
Numpy "where" with multiple conditions
multiple if else conditions in pandas dataframe and derive multiple columns
and i try to use numpy.where, but nothing happen.. data['growth'] always have result 2
my code :
data['growth'] = np.where(np.logical_and(data['tqty'] < 0, data['qty_x'] < 0), 1, 2)
i dont prefer to use if or numpy.where
many thanks
Try to use DataFrame's method 'apply':
Using this sample data:
df = pd.DataFrame(data=[(-1, -1),
(-1, 0),
(0, -1),
(0, 0),
(1, 1)],
columns=['tqty', 'qtyx'])
| | tqty | qtyx |
|---:|-------:|-------:|
| 0 | -1 | -1 |
| 1 | -1 | 0 |
| 2 | 0 | -1 |
| 3 | 0 | 0 |
| 4 | 1 | 1 |
You can get this using lambda functions:
df['growth'] = df.apply(
lambda row: 1 if ((row['tqty'] < 0) & (row['qtyx'] < 0))
else 2,
axis=1)
| | tqty | qtyx | growth |
|---:|-------:|-------:|---------:|
| 0 | -1 | -1 | 1 |
| 1 | -1 | 0 | 2 |
| 2 | 0 | -1 | 2 |
| 3 | 0 | 0 | 2 |
| 4 | 1 | 1 | 2 |
'Axis=1' allows you to iterate through rows, and lambda operates over each row testing both conditions.

Categories