Source code for BinPy.Algorithms.ExpressionConvert

[docs]def makeCompatible(expr): '''Used by convertExpression to convert logical operators to english words.''' expr = expr.replace('~&', ' NAND ') expr = expr.replace('~|', ' NOR ') expr = expr.replace('~^', ' XNOR ') expr = expr.replace('&', ' AND ') expr = expr.replace('|', ' OR ') expr = expr.replace('~', ' NOT ') expr = expr.replace('^', ' XOR ') return '((' + expr + '))'
[docs]def createList(expr): '''Creates a list which can be used by convertExpression for conversion.''' list1 = expr.split('(') list2 = [] list3 = [] while ('' in list1): list1.remove('') for string in list1: l = string.split() list2.extend(l) for string in list2: sublist = [] if ')' in string: while ')' in string: index = string.find(')') sublist.append(string[:index]) sublist.append(')') string = string[index + 1:] sublist.append(string) list3.extend(sublist) else: list3.extend([string]) while ('' in list3): list3.remove('') return (list3)
[docs]def mergeNot(case, expr): '''Combines NOR gate with othes to minimize the number of gates used.''' if expr[-1] == ')': index = expr.find('(') gate = expr[:index].upper() if gate == 'OR' and case == 'general': return 'NOR' + expr[index:] elif gate == 'AND' and case == 'general': return 'NAND' + expr[index:] elif gate == 'NOT': return expr[index + 1:-1] elif gate == 'XOR'and case == 'general': return 'XNOR' + expr[index:] elif gate == 'XNOR'and case == 'general': return 'XOR' + expr[index:] elif gate == 'NAND'and case == 'general': return 'AND' + expr[index:] elif gate == 'NOR'and case == 'general': return 'OR' + expr[index:] return 'NOT(' + expr + ')'
[docs]def to_and_or_not(gate, op1, op2): '''Converts a general two input gate and two of its operands to use only OR, NOT, or AND gates''' if gate == 'AND' or gate == 'OR': return gate + '(' + op1 + ', ' + op2 + ')' elif gate == 'NAND': return 'NOT(AND(' + '(' + op1 + ', ' + op2 + ')' elif gate == 'NOR': return 'NOT(OR(' + '(' + op1 + ', ' + op2 + ')' elif gate == 'XOR': return ('OR(AND(' + op1 + ', ' + mergeNot('general', op2) + '), AND(' + mergeNot('general', op1) + ', ' + op2 + '))') elif gate == 'XNOR': return ( 'OR(AND(' + mergeNot( 'general', op1) + ', ' + mergeNot( 'general', op2) + '), AND(' + op1 + ', ' + op2 + '))')
[docs]def to_nand(gate, op1, op2): '''Converts a general two input gate and two of its operands to use only NAND gates''' if gate == 'AND': return 'NOT(NAND(' + op1 + ', ' + op2 + '))' elif gate == 'OR': return ('NAND(' + mergeNot('special', op1) + ', ' + mergeNot('special', op2) + ')') elif gate == 'NAND': return gate + '(' + op1 + ', ' + op2 + ')' elif gate == 'NOR': return 'NOT(' + to_nand('OR', op1, op2) + ')' elif gate == 'XOR': return ( 'NAND(NAND(' + op1 + ', NAND(' + op1 + ', ' + op2 + ')), NAND(' + op2 + ', NAND(' + op1 + ', ' + op2 + ')))') elif gate == 'XNOR': return 'NOT(' + to_nand('XOR', op1, op2) + ')'
[docs]def to_nor(gate, op1, op2): '''Converts a general two input gate and two of its operands to use only NOR gates''' if gate == 'OR': return 'NOT(NOR(' + op1 + ', ' + op2 + '))' elif gate == 'AND': return ('NOR(' + mergeNot('special', op1) + ', ' + mergeNot('special', op2) + ')') elif gate == 'NOR': return gate + '(' + op1 + ', ' + op2 + ')' elif gate == 'NAND': return 'NOT(' + to_nor('AND', op1, op2) + ')' elif gate == 'XNOR': return ('NOR(NOR(' + op1 + ', NOR(' + op1 + ', ' + op2 + ')), NOR(' + op2 + ', NOR(' + op1 + ', ' + op2 + ')))') elif gate == 'XOR': return 'NOT(' + to_nor('XNOR', op1, op2) + ')'
[docs]def remove_not(gate, exp): '''Converts a NOT gate and its operand to use the specified gate only. The input gate must be NAND or NOR only.''' while 'NOT' in exp: index = exp.find('NOT(') index2 = index index3 = exp.find('(', index) while True: index2 = exp.find(')', index2 + 1) index3 = exp.find('(', index3 + 1) if index3 == -1 or index3 > index2: break exp = exp[:index] + gate + '(' + exp[index + 4:index2] + \ ', ' + exp[index + 4:index2] + ')' + exp[index2 + 1:] return exp
[docs]def convertExpression(expr, two_input=0, only_nand=0, only_nor=0, only_and_or_not=0): ''' Converts logical expression to an implementable form. Make two_input 1 if only two input gates must be used. Make only_nand 1 if only 2 input nand gates must be used. Make only_nor 1 if only 2 input nor gates must be used. Make only_and_or_not 1 if only 2 input AND, OR and NOTs be used. Error occurs if more than one variable is put to 1. convertExpression('( NOT(a) and NOT(b)) or (C and Not(d) and E and F)') OR(AND(NOT(a), NOT(b)), AND(C, NOT(d), E, F)) convertExpression('( NOT(a) and NOT(b)) or (C and Not(d) and E and F)', two_input=1) OR(AND(NOT(a), NOT(b)), AND(C, AND(NOT(d), E))) convertExpression('( NOT(a) and NOT(b)) or (C and Not(d) and E and F)', only_nand=1) NAND(NAND(NAND(a, a), NAND(b, b)), NAND(C, NAND(NAND(NAND(d, d), E), NAND(NAND(d, d), E)))) convertExpression('( NOT(a) and NOT(b)) or (C and Not(d) and E and F)', only_nor=1) NOR(NOR(NOR(a, b), NOR(NOR(C, C), NOR(NOR(d, NOR(E, E)),... NOR(d, NOR(E, E))))), NOR(NOR(a, b), NOR(NOR(C, C), NOR(NOR(d, NOR(E, E)), NOR(d, NOR(E, E)))))) convertExpression('( NOT(a) and NOT(b)) or (C and Not(d) and E and F)', only_and_or_not=1) OR(AND(NOT(a), NOT(b)), AND(C, AND(NOT(d), AND(E, F)))) ''' expr = makeCompatible(expr) list1 = createList(expr) while ')' in list1: index = list1.index(')') if index != len(list1) - 1 and list1[index + 1] == ')': last = 0 else: last = 1 if len(list1) > 1: op2 = list1.pop(index - 1) gate = list1.pop(index - 2) gate = gate.upper() if gate != 'NOT': try: op1 = list1.pop(index - 3) except: list1.insert(index - 1, gate) list1.insert(index - 2, op2) break previous_gate = op1[:len(gate)] previous_gate = previous_gate.upper() next_gate = op2[:len(gate)] next_gate = next_gate.upper() if (two_input == 0 and gate != 'NAND'and gate != 'NOR')and \ (only_nand == 0 and only_nor == 0 and only_and_or_not == 0): if (gate == previous_gate) and (gate == next_gate.upper()): new_element = gate + \ '(' + op1[len(gate) + 1:-1] + \ ', ' + op2[len(gate) + 1:-1] + ')' elif (gate == previous_gate) and (gate != next_gate.upper()): new_element = gate + \ '(' + op1[len(gate) + 1:-1] + ', ' + op2 + ')' elif (gate != previous_gate) and (gate == next_gate.upper()): new_element = gate + \ '(' + op1 + ', ' + op2[len(gate) + 1:-1] + ')' else: new_element = gate + '(' + op1 + ', ' + op2 + ')' else: if only_nand == 0 and only_nor == 0 and only_and_or_not == 0: new_element = gate + '(' + op1 + ', ' + op2 + ')' elif only_nand == 1 and only_nor == 0 and only_and_or_not == 0: new_element = to_nand(gate, op1, op2) elif only_nand == 0 and only_nor == 1 and only_and_or_not == 0: new_element = to_nor(gate, op1, op2) elif only_nand == 0 and only_nor == 0 and only_and_or_not == 1: new_element = to_and_or_not(gate, op1, op2) else: raise Exception("Invalid Input") list1.insert(index - 3, new_element) if (last != 1) or list1.index(')') == 1: temp1 = list1.index(')') temp2 = list1.pop(temp1) else: if only_nand == 0 and only_nor == 0 and only_and_or_not == 0: new_element = mergeNot('general', op2) else: new_element = mergeNot('special', op2) list1.insert(index - 2, new_element) temp1 = list1.index(')') temp2 = list1.pop(temp1) if list1.count(')') == len(list1) - 1: break if only_nand == 1: return (remove_not('NAND', list1[0])) elif only_nor == 1: return (remove_not('NOR', list1[0])) else: return (list1[0])