def findFirstContaining(expression, id, opposite=False, custom=None): # Make sure it's an AND or an OR, otherwise it's invlid if expression.getType() in ["and", "or"]: testfor = expression.getOperand(id) if opposite: testfor = removeNots(op_not(testfor)) if custom: testfor = custom if testfor.getType() in ["and", "or"]: for i, operand in enumerate(expression.getOperands()): if i != id and operand.getType() == testfor.getType(): copy = testfor.getOperands()[:] for var in operand.getOperands(): try: del copy[copy.index(var)] except ValueError: continue if len(copy) == 0: return i elif testfor.getType() in ["not", "var", "con"]: for i, operand in enumerate(expression.getOperands()): if i != id: if operand.getType() in ["not", "var", "con"]: if operand == testfor: return i elif operand.getType() == "and": for suboperand in operand.getOperands(): if suboperand == testfor: return i return None
def expandDeMorgans(expression): if expression.getType() in ["and", "or", "not"]: for i, operand in enumerate(expression.getOperands()): expression.setOperand(i, expandDeMorgans(operand)) if expression.getType() == "not": expand = expression.getOperand(0) if expand.getType() == "and": created = [] for operand in expand.getOperands(): created.append(op_not(operand)) return op_or(*created) elif expand.getType() == "or": created = [] for operand in expand.getOperands(): created.append(op_not(operand)) return op_and(*created) return expression
def findFirstOpposite(expression, id): # Make sure it's an AND or OR, otherwise it's invalid if expression.getType() in ["and", "or"]: testfor = removeNots(op_not(expression.getOperand(id))) for i, operand in enumerate(expression.getOperands()): if i != id and operand == testfor: return i return None
def removeNots(expression): if expression.getType() == "not": operand = removeNots(expression.getOperand(0)) if operand.getType() == "con": return op_con(str(-int(operand.getOperand(0))+1)) elif operand.getType() == "not": return operand.getOperand(0) else: return op_not(operand) elif expression.getType() in ["and", "or"]: for i, operand in enumerate(expression.getOperands()): expression.setOperand(i, removeNots(operand)) return expression else: return expression
def removeMagic(expression): if expression.getType() in ["and", "or", "not"]: for i, operand in enumerate(expression.getOperands()): expression.setOperand(i, removeMagic(operand)) if expression.getType() == "or": for i, operand in enumerate(expression.getOperands()): if operand.getType() == "and": for j, suboperand in enumerate(operand.getOperands()): # Invert 1 part of the AND and look for matches newand = copy.deepcopy(operand) newand.setOperand(j, removeNots(op_not(suboperand))) id = findFirstContaining(expression, i, False, newand) if id != None: # We've got a lot to remove container = expression.getOperand(id) # The container should always be an OR if container.getType() == "and": # Remove the notted version of out tets for l, test in enumerate(container.getOperands()): if test == removeNots(op_not(suboperand)): container.removeOperand(l) break return expression return expression
def editorGenerateExpression(win, operator): op = operator[0] if op == "not": # Find the first backlink from the NOT link = None for test in win.editor_links: if test[1] == operator: link = test break if link != None: return op_not(editorGenerateExpression(win, link[0])) else: raise EditorError("NOT operator not connected!", operator) elif op == "and": # Find all links that apply to this AND links = [] for test in win.editor_links: if test[1] == operator: links.append(test[0]) if len(links) >= 2: operands = [editorGenerateExpression(win, x) for x in links] return op_and(*operands) else: raise EditorError("AND operator only has {} links. 2 or more required.".format(len(links)), operator) elif op == "or": # Find all links that apply to this OR links = [] for test in win.editor_links: if test[1] == operator: links.append(test[0]) if len(links) >= 2: operands = [editorGenerateExpression(win, x) for x in links] return op_or(*operands) else: raise EditorError("OR operator only has {} links. 2 or more required.".format(len(links)), operator) elif op == "var": return op_var(operator[2]) elif op == "con": return op_con(operator[2])
def removeSubopposites(expression): if expression.getType() in ["and", "or", "not"]: for i, operand in enumerate(expression.getOperands()): expression.setOperand(i, removeSubopposites(operand)) if expression.getType() == "or": for i, operand in enumerate(expression.getOperands()): id = findFirstContaining(expression, i, True) if id != None: # We've found an expression containing our thing container = expression.getOperand(id) testfor = removeNots(op_not(operand)) if container.getType() in ["and", "or"]: for j, suboperand in enumerate(container.getOperands()): if suboperand == testfor: container.removeOperand(j) break else: expression.removeOperand(id) return removeSubopposites(expression) else: #print("{} not found in {}".format(operand, expression)) pass return expression
def generateExpression(expression, last=None): # Don't do anything if we've been given a blank expression if len(expression) <= 0: return last char = expression[0] if last == None: # If we're at the beginning of the expression, we can only accept A,1 or ( if char.isalpha(): return generateExpression(expression[1:], op_var(char)) elif char.isdigit(): return generateExpression(expression[1:], op_con(char)) elif char == "(": length = calcBracketLength(expression[1:]) return generateExpression( expression[length + 1:], op_bra(generateExpression(expression[1:length]))) else: raise ValueError("Expression is Invalid!") else: # We're mid-expression if char.isalpha() or char.isdigit(): if last.getType() == "or": last.setOperand( -1, op_and(last.getOperand(-1), generateExpression(expression[1:]))) return last elif last.getType() == "and": last.addOperand(generateExpression(char)) return generateExpression(expression[1:], last) else: return generateExpression( expression[1:], op_and(last, generateExpression(expression[0]))) elif char == "(": length = calcBracketLength(expression[1:]) if last.getType() == "and": last.addOperand( op_bra(generateExpression(expression[1:length]))) return generateExpression(expression[length + 1:], last) else: return generateExpression( expression[length + 1:], op_and(last, op_bra(generateExpression(expression[1:length])))) elif char == "+": if last.getType() == "or": last.addOperand(generateExpression(expression[1:])) return last else: new = generateExpression(expression[1:]) if new.getType() == "or": return op_or(last, *new.getOperands()) return op_or(last, new) elif char == "'": if last.getType() in ["bar", "var", "con", "not"]: return generateExpression(expression[1:], op_not(last)) else: last.setOperand(-1, op_not(last.getOperand(-1))) return generateExpression(expression[1:], last) else: raise ValueError("Expression is Invalid!")