Add truthtable processor
This commit is contained in:
parent
87fc73ca50
commit
9358971583
|
@ -7,3 +7,4 @@ default: python
|
|||
python:
|
||||
python python/Hasse.py graphics/src/example1.txt graphics/example1.tex
|
||||
python python/FSA.py graphics/src/example2.txt graphics/example2.tex
|
||||
python python/Truthtable.py graphics/src/example3.txt graphics/example3.tex
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
\begin{truthtable}
|
||||
{c|c|c|c|c|e|c}
|
||||
{$p$ & $q$ & $s$ & $p \wedge q$ & $p \Rightarrow q$ & $ p \Leftrightarrow q$ & $p \Leftrightarrow (q \wedge s)$}
|
||||
\T & \T & \T & \T & \T & \T & \T
|
||||
\T & \T & \F & \T & \T & \T & \F
|
||||
\T & \F & \T & \F & \F & \F & \F
|
||||
\T & \F & \F & \F & \F & \F & \F
|
||||
\F & \T & \T & \F & \T & \F & \F
|
||||
\F & \T & \F & \F & \T & \F & \T
|
||||
\F & \F & \T & \F & \T & \T & \T
|
||||
\F & \F & \F & \F & \T & \T & \T
|
||||
\end{truthtable}
|
||||
|
|
@ -0,0 +1 @@
|
|||
p, q, s, p and q, p implies q, E p iff q, p iff (q and s)
|
|
@ -0,0 +1,104 @@
|
|||
from sys import argv
|
||||
from pathlib import Path
|
||||
|
||||
def parseExpressionList(inputData):
|
||||
return [e.strip() for e in inputData.split(',')]
|
||||
|
||||
|
||||
class OverloadedBool:
|
||||
"""Overloads the bool in order to make Implies and Iff functions"""
|
||||
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
||||
def __bool__(self):
|
||||
return self.val
|
||||
|
||||
def __str__(self):
|
||||
return str(self.val)
|
||||
|
||||
def __add__(self, bool2):
|
||||
""" Implies """
|
||||
return (not self.val or bool2)
|
||||
|
||||
def __sub__(self, bool2):
|
||||
""" Iff """
|
||||
return (not self.val or bool2) and (not bool2 or self.val)
|
||||
|
||||
def flattenImpliesIff(exps):
|
||||
return [exp.replace('implies', '+').replace('iff', '-').replace('E', '') for exp in exps]
|
||||
|
||||
def generateTruthTable(exps):
|
||||
|
||||
exps = flattenImpliesIff(exps)
|
||||
|
||||
boolvars = [e for e in exps if len(e) == 1]
|
||||
|
||||
truthtable = []
|
||||
|
||||
for x in reversed(range(2 ** len(boolvars))):
|
||||
for i,digit in enumerate('{0:b}'.format(x).zfill(len(boolvars))):
|
||||
exec(f'{boolvars[i]} = OverloadedBool({digit == "1"})', globals())
|
||||
|
||||
def calculateGridLine():
|
||||
line = []
|
||||
for exp in exps:
|
||||
exec(f'line.append(({exp}).__bool__())')
|
||||
return line
|
||||
|
||||
truthtable.append(calculateGridLine())
|
||||
|
||||
return truthtable
|
||||
|
||||
|
||||
def latexify(exps, truthtable):
|
||||
|
||||
latex_expressions = \
|
||||
[ (
|
||||
'E' in exp,
|
||||
exp
|
||||
.replace('not', '\\neg')
|
||||
.replace('and', '\\wedge')
|
||||
.replace('or', '\\vee')
|
||||
.replace('implies', '\\Rightarrow')
|
||||
.replace('iff', '\\Leftrightarrow')
|
||||
.replace('E', ''
|
||||
.strip())
|
||||
)
|
||||
for exp in exps]
|
||||
|
||||
return \
|
||||
"""
|
||||
\\begin{{truthtable}}
|
||||
{{{}}}
|
||||
{{{}}}
|
||||
{}
|
||||
\\end{{truthtable}}
|
||||
""".format(
|
||||
'|'.join('e' if e else 'c' for e,_ in latex_expressions),
|
||||
' & '.join(f'${exp}$' for _,exp in latex_expressions),
|
||||
'\n'.join(' ' + ' & '.join('\\T' if b else '\\F' for b in line) for line in truthtable)
|
||||
)
|
||||
|
||||
def printTruthtable(exps, truthtable):
|
||||
stringTable = [ ['\033[32mT\033[0m ' if b else '\033[31mF\033[0m' for b in line] for line in truthtable]
|
||||
print(tabulate(stringTable, headers=exps))
|
||||
|
||||
if __name__ == '__main__':
|
||||
filename = argv[1]
|
||||
|
||||
with open(filename) as file:
|
||||
exps = parseExpressionList(file.read())
|
||||
truthtable = generateTruthTable(exps)
|
||||
|
||||
try:
|
||||
from tabulate import tabulate
|
||||
printTruthtable(exps, generateTruthTable(exps))
|
||||
except:
|
||||
print('Couldn\'t find tabulate. Do you have it installed?')
|
||||
|
||||
content = latexify(exps, truthtable)
|
||||
|
||||
with open(str(Path(__file__).parent.absolute()) + '/tex_templates/Truthtable.tex') as template:
|
||||
with open(argv[2], 'w') as destination_file:
|
||||
destination_file.write(template.read().replace('%CONTENT', content))
|
|
@ -0,0 +1 @@
|
|||
%CONTENT
|
Loading…
Reference in New Issue