def _distributive(self):
    if self.type in __distributions:
        star = __distributions[self.type]

        extracted = []
        factorList = Counter()

        def _pushToExtracted(child, count):
            assert count == 1
            extracted.append(child)
            factorList.update(keysExcept(child.children,
                                         Expression.isConstant))

        (rest, hasStar) = performIf(self.children, Expression.isType(star),
                                    _pushToExtracted)

        if hasStar:
            # Algorithm for factorization:
            #
            #  1. find the most common factor
            #  2. check if that factor has appeared >1 times. If no, quit.
            #  3. otherwise, scan for all children which contain that factor.
            #  4. remove that factor from those children, and create a new
            #     a*(b+c+d) style expression.

            factorizedOnce = False
            while factorList:
                (commonest, count) = factorList.most_common(1)[0]
                if count == 1:
                    if factorizedOnce:
                        rest.update(extracted)
                        return self.replaceChildren(rest)
                    else:
                        return None
                else:
                    factorizedOnce = True
                    oldExtracted = extracted
                    extracted = []
                    newChildrenList = []
                    for child in oldExtracted:
                        if commonest in child.children:
                            factorList.subtract(
                                keysExcept(child.children,
                                           Expression.isConstant))
                            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))
Beispiel #2
0
def _involution(self):
    # (a ^ a) == 0
    if self.type == '^':
        if any(count > 1 for count in list(self.children.values())):
            return Expression(
                self.type,
                *(k for k, c in list(self.children.items()) if c % 2 != 0))
Beispiel #3
0
def _evaluateIfThenElse(self):
    if self.type == '?:' and Expression.isConstant(self.children[0]):
        if self.children[0].value:
            return self.children[1]
        else:
            return self.children[2]
    else:
        return None
Beispiel #4
0
def _negatedComparison(self):
    # !(a < b)    <=>    b <= a

    if self.type == '!':
        child = self.children[0]
        if child.type in __negatedComparisonMap:
            return Expression(__negatedComparisonMap[child.type],
                              child.children[1], child.children[0])
Beispiel #5
0
def _evaluateIfThenElse(self):
	if self.type == '?:' and Expression.isConstant(self.children[0]):
		if self.children[0].value:
			return self.children[1]
		else:
			return self.children[2]
	else:
		return None
Beispiel #6
0
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)
Beispiel #7
0
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)
Beispiel #8
0
def _distributive(self):
    if self.type in __distributions:
        star = __distributions[self.type]

        extracted = []
        factorList = Counter()

        def _pushToExtracted(child, count):
            assert count == 1
            extracted.append(child)
            factorList.update(
                keysExcept(child.children, Expression.isConstant))

        (rest, hasStar) = performIf(self.children, Expression.isType(star),
                                    _pushToExtracted)

        if hasStar:
            # Algorithm for factorization:
            #
            #  1. find the most common factor
            #  2. check if that factor has appeared >1 times. If no, quit.
            #  3. otherwise, scan for all children which contain that factor.
            #  4. remove that factor from those children, and create a new
            #     a*(b+c+d) style expression.

            factorizedOnce = False
            while factorList:
                (commonest, count) = factorList.most_common(1)[0]
                if count == 1:
                    if factorizedOnce:
                        rest.update(extracted)
                        return self.replaceChildren(rest)
                    else:
                        return None
                else:
                    factorizedOnce = True
                    oldExtracted = extracted
                    extracted = []
                    newChildrenList = []
                    for child in oldExtracted:
                        if commonest in child.children:
                            factorList.subtract(
                                keysExcept(child.children,
                                           Expression.isConstant))
                            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))
Beispiel #9
0
def _equalityWithZero(self):
	# a == 0     <=>    !a
	if self.type in ('==', '!='):
		otherChildIndex = __findNonZeroSide(self)
		
		if otherChildIndex >= 0:
			rv = self.children[otherChildIndex]
			if self.type == '==':
				rv = Expression.not_(rv)
			return rv
Beispiel #10
0
def _equalityWithZero(self):
    # a == 0     <=>    !a
    if self.type in ('==', '!='):
        otherChildIndex = __findNonZeroSide(self)

        if otherChildIndex >= 0:
            rv = self.children[otherChildIndex]
            if self.type == '==':
                rv = Expression.not_(rv)
            return rv
Beispiel #11
0
def _recursiveRule(self):
	if Expression.isAtomic(self):
		return None

	simplifier = _ChildSimplifier()
		
	if isinstance(self.children, Counter):
		retval = Counter({simplifier(child): count for child, count in self.children.items()})
	else:
		retval = [simplifier(child) for child in self.children]
						
	if simplifier.simplified:
		return self.replaceChildren(retval)
Beispiel #12
0
def _flatten(self):
	# flatten an expression tree of the same type by applying associativity.
	# a + (b + c) == a + b + c.
	
	if self.type in ('+', '*', '&', '|', '^', '&&', '||'):
		flatPart = Counter()
		def _flattenAction(child, count):
			nonlocal flatPart
			flatPart += Counter({k: v*count for k, v in child.children.items()})
		
		(rest, hasFlatten) = performIf(self.children, Expression.isType(self.type), _flattenAction)
	
		if hasFlatten:
			rest += flatPart
			return self.replaceChildren(rest)
Beispiel #13
0
def _recursiveRule(self):
    if Expression.isAtomic(self):
        return None

    simplifier = _ChildSimplifier()

    if isinstance(self.children, Counter):
        retval = Counter({
            simplifier(child): count
            for child, count in list(self.children.items())
        })
    else:
        retval = [simplifier(child) for child in self.children]

    if simplifier.simplified:
        return self.replaceChildren(retval)
Beispiel #14
0
def _flatten(self):
    # flatten an expression tree of the same type by applying associativity.
    # a + (b + c) == a + b + c.

    if self.type in ('+', '*', '&', '|', '^', '&&', '||'):
        flatPart = Counter()

        def _flattenAction(child, count):
            nonlocal flatPart
            flatPart += Counter(
                {k: v * count
                 for k, v in list(child.children.items())})

        (rest, hasFlatten) = performIf(self.children,
                                       Expression.isType(self.type),
                                       _flattenAction)

        if hasFlatten:
            rest += flatPart
            return self.replaceChildren(rest)
Beispiel #15
0
class _ChildSimplifier(object):
    def __init__(self):
        self.simplified = False

    def __call__(self, child):
        if not Expression.isAtomic(child):
            (child, hasSimplified) = child.simplify(getSimplifyState=True)
            self.simplified = self.simplified or hasSimplified
        return child


def _recursiveRule(self):
    if Expression.isAtomic(self):
        return None

    simplifier = _ChildSimplifier()

    if isinstance(self.children, Counter):
        retval = Counter({
            simplifier(child): count
            for child, count in list(self.children.items())
        })
    else:
        retval = [simplifier(child) for child in self.children]

    if simplifier.simplified:
        return self.replaceChildren(retval)


Expression.addSimplificationRule(_recursiveRule, 'recursive simplify')
Beispiel #16
0
            return Expression(self.type, *list(self.children.keys()))


# 1-ary and 0-ary cases are handled in fold_constant.py already.


def _involution(self):
    # (a ^ a) == 0
    if self.type == '^':
        if any(count > 1 for count in list(self.children.values())):
            return Expression(
                self.type,
                *(k for k, c in list(self.children.items()) if c % 2 != 0))


Expression.addSimplificationRule(_flatten,
                                 'commutative semigroup (a*(b*c) == a*b*c)')
Expression.addSimplificationRule(_idempotent, 'idempotent ((a&a) == a)')
Expression.addSimplificationRule(_involution, 'involution ((a^a) == 0)')

if __name__ == '__main__':
    import symbolic.simplify.recursive
    from symbolic.expression import Symbol

    Expression.setDebugSimplify(True)

    a = Symbol('foo') + Symbol('bar') + Symbol(
        'baz') + Symbol('ma') * Symbol('maz') - Symbol('y')
    assert a.simplify() == Expression(
        '+', Symbol('foo'), Symbol('bar'), Symbol('baz'),
        Expression('*', Symbol('ma'), Symbol('maz')), -Symbol('y'))
Beispiel #17
0
 def __call__(self, child):
     if not Expression.isAtomic(child):
         (child, hasSimplified) = child.simplify(getSimplifyState=True)
         self.simplified = self.simplified or hasSimplified
     return child
Beispiel #18
0
			return Constant(__naryDefaultValue[self.type])
		elif uniqueChildrenCount == 1:
			(child, value) = list(self.children.items())[0]
			if value == 1:
				return child

def _evaluateIfThenElse(self):
	if self.type == '?:' and Expression.isConstant(self.children[0]):
		if self.children[0].value:
			return self.children[1]
		else:
			return self.children[2]
	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()
	
Beispiel #19
0
def __isNegativeFactor(self):
    if self.type == '*':
        for c in self.children:
            if Expression.isConstant(c) and c.value < 0:
                return True
    return False
Beispiel #20
0
from symbolic.expression import Expression
from collections import Counter

class _ChildSimplifier(object):
	def __init__(self):
		self.simplified = False
	
	def __call__(self, child):
		if not Expression.isAtomic(child):
			(child, hasSimplified) = child.simplify(getSimplifyState=True)
			self.simplified = self.simplified or hasSimplified
		return child


def _recursiveRule(self):
	if Expression.isAtomic(self):
		return None

	simplifier = _ChildSimplifier()
		
	if isinstance(self.children, Counter):
		retval = Counter({simplifier(child): count for child, count in self.children.items()})
	else:
		retval = [simplifier(child) for child in self.children]
						
	if simplifier.simplified:
		return self.replaceChildren(retval)
		
		
Expression.addSimplificationRule(_recursiveRule, 'recursive simplify')
Beispiel #21
0

__negatedComparisonMap = {'==': '!=', '!=': '==', '<': '<=', '<=': '<'}


def _negatedComparison(self):
    # !(a < b)    <=>    b <= a

    if self.type == '!':
        child = self.children[0]
        if child.type in __negatedComparisonMap:
            return Expression(__negatedComparisonMap[child.type],
                              child.children[1], child.children[0])


Expression.addSimplificationRule(_selfCompare,
                                 '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)
Beispiel #22
0
					for child in oldExtracted:
						if commonest in child.children:
							factorList.subtract(keysExcept(child.children, Expression.isConstant))
							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'))
	
Beispiel #23
0
def __isNegativeFactor(self):
	if self.type == '*':
		for c in self.children:
			if Expression.isConstant(c) and c.value < 0:
				return True
	return False
Beispiel #24
0
	def __call__(self, child):
		if not Expression.isAtomic(child):
			(child, hasSimplified) = child.simplify(getSimplifyState=True)
			self.simplified = self.simplified or hasSimplified
		return child
Beispiel #25
0
def __findNonZeroSide(self):
	# Check if one side is zero.
	for i, c in enumerate(self.children):
		if Expression.isConstant(c) and c.value == 0:
			return (1 - i)
	return -1
Beispiel #26
0
def _idempotent(self):
    # (a & a) == a
    if self.type in ('&', '|', '&&', '||'):
        if any(count > 1 for count in list(self.children.values())):
            return Expression(self.type, *list(self.children.keys()))
 def _evaluteRepetition(child, count):
     grouped.append(Expression(star, child, Constant(count)))
Beispiel #28
0
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))
Beispiel #29
0
def __findNonZeroSide(self):
    # Check if one side is zero.
    for i, c in enumerate(self.children):
        if Expression.isConstant(c) and c.value == 0:
            return (1 - i)
    return -1
Beispiel #30
0
def _idempotent(self):
	# (a & a) == a
	if self.type in ('&', '|', '&&', '||'):
		if any(count > 1 for count in self.children.values()):
			return Expression(self.type, *self.children.keys())

# 1-ary and 0-ary cases are handled in fold_constant.py already.

def _involution(self):
	# (a ^ a) == 0
	if self.type == '^':
		if any(count > 1 for count in self.children.values()):
			return Expression(self.type, *(k for k, c in self.children.items() if c % 2 != 0))

Expression.addSimplificationRule(_flatten, 'commutative semigroup (a*(b*c) == a*b*c)')
Expression.addSimplificationRule(_idempotent, 'idempotent ((a&a) == a)')
Expression.addSimplificationRule(_involution, 'involution ((a^a) == 0)')

if __name__ == '__main__':
	import symbolic.simplify.recursive
	from symbolic.expression import Symbol

	Expression.setDebugSimplify(True)
	
	a = Symbol('foo') + Symbol('bar') + Symbol('baz') + Symbol('ma') * Symbol('maz') - Symbol('y')
	assert a.simplify() == Expression('+', Symbol('foo'), Symbol('bar'), Symbol('baz'), Expression('*', Symbol('ma'), Symbol('maz')), -Symbol('y'))
	
	a = (Expression('&', Symbol('foo'), Symbol('bar'), Symbol('foo'), Symbol('baz'), Symbol('bar'), Symbol('bar')) & \
		 Expression('^', Symbol('foo'), Symbol('bar'), Symbol('foo'), Symbol('baz'), Symbol('bar'), Symbol('bar')))
	assert a.simplify() == Expression('&', Symbol('foo'), Symbol('bar'), Symbol('baz'), Expression('^', Symbol('bar'), Symbol('baz')))
Beispiel #31
0
            (child, value) = list(self.children.items())[0]
            if value == 1:
                return child


def _evaluateIfThenElse(self):
    if self.type == '?:' and Expression.isConstant(self.children[0]):
        if self.children[0].value:
            return self.children[1]
        else:
            return self.children[2]
    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()
                                           Expression.isConstant))
                            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'))
Beispiel #33
0
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))
Beispiel #34
0
	'==': '!=',
	'!=': '==',
	'<': '<=',
	'<=': '<'}

def _negatedComparison(self):
	# !(a < b)    <=>    b <= a

	if self.type == '!':
		child = self.children[0]
		if child.type in __negatedComparisonMap:
			return Expression(__negatedComparisonMap[child.type], child.children[1], child.children[0])
			


Expression.addSimplificationRule(_selfCompare, '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()
Beispiel #35
0
                                           Expression.isConstant))
                            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'))