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))
Exemple #2
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))
Exemple #3
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)
Exemple #4
0
def _subtractionAndCompareWithZero(self):
	# a-b < 0    <=>    a < b
	if self.type in ('==', '<=', '!=', '<'):
		otherChildIndex = __findNonZeroSide(self)
		
		if otherChildIndex >= 0:
			otherChild = self.children[otherChildIndex]
			if otherChild.type == '+':
				negatedFactors = Counter()
				def addNegatedFactor(child, count):
					nonlocal negatedFactors
					negatedFactors[-child] += count
				
				(positiveFactors, anyNeg) = performIf(otherChild.children, __isNegativeFactor, addNegatedFactor)
				
				if anyNeg:
					lhs = otherChild.replaceChildren(positiveFactors)
					rhs = otherChild.replaceChildren(negatedFactors)
					return self.replaceChildren([lhs, rhs])
Exemple #5
0
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 _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)
Exemple #7
0
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)
Exemple #8
0
def _subtractionAndCompareWithZero(self):
    # a-b < 0    <=>    a < b
    if self.type in ('==', '<=', '!=', '<'):
        otherChildIndex = __findNonZeroSide(self)

        if otherChildIndex >= 0:
            otherChild = self.children[otherChildIndex]
            if otherChild.type == '+':
                negatedFactors = Counter()

                def addNegatedFactor(child, count):
                    nonlocal negatedFactors
                    negatedFactors[-child] += count

                (positiveFactors, anyNeg) = performIf(otherChild.children,
                                                      __isNegativeFactor,
                                                      addNegatedFactor)

                if anyNeg:
                    lhs = otherChild.replaceChildren(positiveFactors)
                    rhs = otherChild.replaceChildren(negatedFactors)
                    return self.replaceChildren([lhs, rhs])