from operator import add, sub, mul, truediv, pow
[docs]class Stack(list):
[docs] def push(self, x):
self.append(x)
[docs] def top(self):
return self[-1]
[docs]class Queue(list):
[docs] def push(self, x):
self.insert(0, x)
[docs] def top(self):
return self[-1]
[docs]def parse_infix_expression(op, is_operand_fx, is_operator_fx, precedence_fx):
tokens = Queue(op[::-1])
output = Queue()
opstk = Stack()
while tokens:
token = tokens.pop()
if is_operand_fx(token):
output.push(token)
elif is_operator_fx(token):
while opstk and ((opstk.top() != '(') and ((precedence_fx(token) < precedence_fx(opstk.top())) or (
left_operator_association(opstk.top()) and (precedence_fx(token) == precedence_fx(opstk.top()))))):
output.push(opstk.pop())
opstk.push(token)
elif token == '(':
opstk.push(token)
elif token == ')':
while opstk and (opstk.top() != '('):
output.push(opstk.pop())
if opstk.top() != '(':
print('Mismatched parentheses found!')
else:
opstk.pop()
while opstk:
op_remaining = opstk.pop()
if op_remaining in ('(', ')'):
print('Mismatched parentheses found')
output.push(op_remaining)
return list(output)[::-1]
[docs]def evaluate_postfix_expression(op, eval_fx, type_conv=int):
stk = Stack()
for token in op:
if is_operator_token(token):
o1, o2 = type_conv(stk.pop()), type_conv(stk.pop())
result = eval_fx(token, o1, o2)
stk.push(result)
elif is_number_token(token):
stk.push(token)
return stk.pop()
[docs]def tokenize_infix_expression(inf_exp_str):
return list(filter(lambda x: x != '', inf_exp_str.replace('(', ' ( ').replace(')', ' ) ').split(' ')))
# def tokenize_boolean_expression(inf_exp_str, default_value='1'):
# return [tok if tok in ('0', '1', 'and', 'not', 'or', ')', '(') else default_value for tok in
# tokenize_infix_expression(inf_exp_str)]
[docs]def tokenize_boolean_expression(inf_exp_str):
return tokenize_infix_expression(inf_exp_str)
[docs]def is_number_token(token):
return token.replace('.', '', 1).replace('-', '', 1).isnumeric()
[docs]def is_operator_token(token):
return token in ['**', '/', '*', '+', '-']
[docs]def is_string_token(token):
return isinstance(token, str) and not is_boolean_operator(token) and (('(' not in token) and (')' not in token))
[docs]def op_prec(op):
precedence = {
'**': 4,
'/': 3,
'*': 3,
'+': 2,
'-': 1}
return precedence[op]
[docs]def left_operator_association(op):
return False if op == '**' else True
operators = {
'+': add,
'-': sub,
'*': mul,
'/': truediv,
'**': lambda a, b: pow(b, a)
}
[docs]def eval_math_operator(operator, o1, o2):
return operators[operator](o1, o2)
[docs]def is_boolean_value(token):
if token in ('1', '0'):
return True
elif token.isnumeric():
print('Illegal token', token, 'found.')
return False
else:
return False
[docs]def is_boolean_operator(token):
return token.upper() in ['AND', 'OR', 'NOT']
[docs]def boolean_precedence(token):
pdict = {'not': 3,
'and': 2,
'or': 1}
return pdict[token]
truth_table = {
'and': {
(0, 0): 0,
(1, 0): 0,
(0, 1): 0,
(1, 1): 1
},
'or': {
(0, 0): 0,
(1, 0): 1,
(0, 1): 1,
(1, 1): 1
},
'not': {
0: 1,
1: 0
}
}
[docs]def eval_boolean_operator(operator, o1, o2):
return truth_table[operator][(o1, o2)]
if __name__ == '__main__':
def test_algebraic_expression():
op = tokenize_infix_expression('((15 / (7 - (1 + 1))) * 3) - (2 + (1 + 1)) ')
psfix = parse_infix_expression(op, is_number_token, is_operator_token, op_prec)
res = evaluate_postfix_expression(psfix, eval_math_operator)
print(res)
def test_boolean_expression():
from urllib.request import urlretrieve
from cobra.io.sbml3 import read_sbml_model
from random import random
path, content = urlretrieve('http://bigg.ucsd.edu/static/models/RECON1.xml')
model = read_sbml_model(path)
ogpr = model.reactions.ATPS4m.gene_name_reaction_rule
gene_activation = {k: 1 for k in [g.id for g in model.genes]}
for test in range(20):
gpr = ogpr
for gene in gene_activation:
dec = random() > 0.6
gpr = gpr.replace(gene, '1' if dec else '0')
op = [tok if tok in ('0', '1', 'and', 'not', 'or', ')', '(') else '1' for tok in
tokenize_infix_expression(gpr)]
psfix = parse_infix_expression(op, is_boolean_value, is_boolean_operator, boolean_precedence)
print(gpr, ''.join(psfix), evaluate_postfix_expression(psfix, eval_boolean_operator), sep=',')