def _selfCompare(self): if self.type in ('==', '<='): if self.children[0] == self.children[1]: return Constant(True) elif self.type in ('!=', '<'): if self.children[0] == self.children[1]: return Constant(False)
def _naryBaseCondition(self): if self.type in __naryDefaultValue: uniqueChildrenCount = len(self.children) if uniqueChildrenCount == 0: return Constant(__naryDefaultValue[self.type]) elif uniqueChildrenCount == 1: (child, value) = list(self.children.items())[0] if value == 1: return child
def _shortCircuit(self): if self.type in __shortCircuitTarget: target = __shortCircuitTarget[self.type] targetType = type(target) for v in self.children: if Expression.isConstant(v): if targetType(v.value) == target: return Constant(target)
def _nary(self): if self.type in __naryDefaultValue: default = __naryDefaultValue[self.type] val = default rests = Counter() totalValCount = 0 def _updateVal(child, count): nonlocal val, totalValCount if child.value != default: val = _applyNtimes(self.type, child.value, count, val) totalValCount += count (rests, _) = performIf(self.children, Expression.isConstant, _updateVal) if val != default: rests[Constant(val)] += 1 if totalValCount > 1 or (totalValCount == 1 and val == default): return self.replaceChildren(rests)
def _evaluteRepetition(child, count): grouped.append(Expression(star, child, Constant(count)))
newChildChildren = Counter(child.children) newChildChildren[commonest] -= 1 newChild = child.replaceChildren(newChildChildren) newChildrenList.append(newChild) else: extracted.append(child) newExpression = Expression( star, commonest, Expression(self.type, *newChildrenList)) extracted.append(newExpression) factorList.update( keysExcept(child.children, Expression.isConstant)) Expression.addSimplificationRule(_repetition, 'repetition (a+a+a=3*a)') Expression.addSimplificationRule(_distributive, 'distributive (a*b+a*c=a*(b+c))') if __name__ == '__main__': import symbolic.simplify.recursive from symbolic.expression import Symbol Expression.setDebugSimplify(True) a = Expression('+', Symbol('a'), Symbol('a'), Symbol('b'), Symbol('a'), Symbol('b'), Symbol('b'), Symbol('a'), Symbol('c')) + \ Expression('+', Symbol('c'), Symbol('a'), Symbol('c'), Symbol('c'), Symbol('b'), Symbol('a'), Symbol('a'), Symbol('d')) assert a.simplify() == Expression( '+', Expression('*', Symbol('a'), Constant(7)), Expression('*', Symbol('b'), Constant(4)), Expression('*', Symbol('c'), Constant(4)), Symbol('d'))
else: return None Expression.addSimplificationRule(_unary, 'fold constant (unary)') Expression.addSimplificationRule(_binary, 'fold constant (binary)') Expression.addSimplificationRule(_shortCircuit, 'short circuit') Expression.addSimplificationRule(_nary, 'fold constant (N-ary)') Expression.addSimplificationRule(_naryBaseCondition, 'base condition (N-ary)') Expression.addSimplificationRule(_evaluateIfThenElse, 'constant condition (?:)') if __name__ == '__main__': from symbolic.simplify.recursive import * from symbolic.expression import Symbol Expression.setDebugSimplify(True) a = Constant(3) / Constant(2) assert Constant(1.5) == a.simplify() a = Expression('+', Constant(1), Constant(5), Constant(12), Constant(44)) assert Constant(62) == a.simplify() a = Expression.if_(Expression.ge(Constant(7), Constant(2)), Constant(11), Constant(55)) assert Constant(11) == a.simplify() a = (Constant(1) ^ Constant(5) - Constant(122) // Constant(4)) ** Constant(2) assert Constant(676) == a.simplify() a = Expression('*', Symbol("foo"), Constant(0), Symbol("boo")) assert Constant(0) == a.simplify()
'self comparison (a==a <=> True)') Expression.addSimplificationRule(_negatedComparison, 'negated comparison (!(a<b) <=> b<=a)') Expression.addSimplificationRule(_subtractionAndCompareWithZero, 'subtract and compare (a-b<0 <=> a<b)') Expression.addSimplificationRule(_equalityWithZero, 'equality with zero (a==0 <=> !a)') if __name__ == '__main__': import symbolic.simplify.recursive import symbolic.simplify.fold_constant import symbolic.simplify.distributive from symbolic.expression import Symbol Expression.setDebugSimplify(True) a = Expression.lt(Symbol('aaa'), Symbol('aaa')) assert Constant(False) == a.simplify() a = Expression.le(Symbol('aaa'), Symbol('aaa')) assert Constant(True) == a.simplify() a = Expression.eq(Constant(0), Symbol('aaa') - Symbol('bbb')) assert Expression.eq(Symbol('aaa'), Symbol('bbb')) == a.simplify() a = Expression.eq(Constant(0), Symbol('aaa') + Symbol('bbb')) assert Expression.not_(Symbol('aaa') + Symbol('bbb')) == a.simplify() a = Expression.not_(Expression.ge(Symbol('aaa'), Symbol('bbb'))) assert Expression.lt(Symbol('aaa'), Symbol('bbb')) == a.simplify()
def _binary(self): if self.type in __binaryFuncs and Expression.isConstant( self.children[0]) and Expression.isConstant(self.children[1]): return Constant(__binaryFuncs[self.type](self.children[0].value, self.children[1].value))
Expression.addSimplificationRule(_unary, 'fold constant (unary)') Expression.addSimplificationRule(_binary, 'fold constant (binary)') Expression.addSimplificationRule(_shortCircuit, 'short circuit') Expression.addSimplificationRule(_nary, 'fold constant (N-ary)') Expression.addSimplificationRule(_naryBaseCondition, 'base condition (N-ary)') Expression.addSimplificationRule(_evaluateIfThenElse, 'constant condition (?:)') if __name__ == '__main__': from symbolic.simplify.recursive import * from symbolic.expression import Symbol Expression.setDebugSimplify(True) a = Constant(3) / Constant(2) assert Constant(1.5) == a.simplify() a = Expression('+', Constant(1), Constant(5), Constant(12), Constant(44)) assert Constant(62) == a.simplify() a = Expression.if_(Expression.ge(Constant(7), Constant(2)), Constant(11), Constant(55)) assert Constant(11) == a.simplify() a = (Constant(1) ^ Constant(5) - Constant(122) // Constant(4))**Constant(2) assert Constant(676) == a.simplify() a = Expression('*', Symbol("foo"), Constant(0), Symbol("boo")) assert Constant(0) == a.simplify()