def foil(self, node): if node is None: return if (node.getLeft() is None) and (node.getRight() is None): return node else: right = self.foil(node.getRight()) left = self.foil(node.getLeft()) if not node.isAlgOpp(): raise TypeError("Nodal element issue") if node.getElement() == Sign("+"): newEl = right.getElement() + left.getElement() node.setElement(newEl) elif node.getElement() == Sign("-"): newEl = right.getElement() - left.getElement() node.setElement(newEl) elif node.getElement() == Sign("*"): newEl = copy.deepcopy(right.getElement()) * copy.deepcopy( left.getElement()) node.setElement(newEl) node.setLeft(None) node.setRight(None) return node
def distributePs(self, node): if node is None: return if node.getLeft() is None and node.getRight() is None: node.getElement().distributePartials() return else: self.distributePs(node.getLeft()) self.distributePs(node.getRight()) if node.getElement() == Sign("*") and ( node.getLeft() is not None and node.getLeft().isLeaf() ) and (node.getRight() is not None and node.getRight().isLeaf()): if len(node.getLeft().getElement().getSums()) == 1: if node.getLeft().getElement().getSums()[0].isOnlyPartials( ): node.getRight().getElement().addPartials( node.getLeft().getElement().getSums() [0].getPartials()) node.getLeft().getElement().getSums()[0].setPartials( []) if node.getLeft().getElement().getSums( )[0] == MultGroup("-"): node.getLeft().getElement().getSums()[0].swapSign() node.getRight().getElement().swapSign() if node.getLeft().getElement().getSums( )[0] == MultGroup("+"): node.setElement(node.getRight().getElement()) node.setLeft(None) node.setRight(None) elif len(node.getRight().getElement().getSums()) == 1: if node.getRight().getElement().getSums( )[0].isOnlyPartials(): node.getLeft().getElement().addPartials( node.getRight().getElement().getSums() [0].getPartials()) node.getRight().getElement().getSums()[0].setPartials( []) if node.getRight().getElement().getSums( )[0] == MultGroup("-"): node.getRight().getElement().getSums()[0].swapSign( ) node.getLeft().getElement().swapSign() if node.getRight().getElement().getSums( )[0] == MultGroup("+"): node.setElement(node.getLeft().getElement()) node.setLeft(None) node.setRight(None)
def subTreeRepr(self, node, strx): if node is not None: brac = node.getBrackets() if brac: strx += "\\(" if type(node.getElement()) is Sign and node.getElement() == Sign( "*"): if node.getRight() is not None and node.getRight().isSum(): if len(node.getRight().getElement().getSums()) == 1: node.getRight().getElement().getSums()[0].setShowNum( False) else: for summ in node.getRight().getElement().getSums(): summ.setShowNum(True) if node.getLeft() is not None and node.getLeft().isSum(): if len(node.getLeft().getElement().getSums()) == 1: node.getLeft().getElement().getSums()[0].setShowNum( False) else: for summ in node.getLeft().getElement().getSums(): summ.setShowNum(True) #if node.getRight().isLeaf(): strx += self.subTreeRepr(node.getRight(), "") # else: # strx += "\\(" + self.subTreeRepr(node.getRight(), "") + "\\)" # if node.getLeft().isLeaf(): strx += self.subTreeRepr(node.getLeft(), "") # else: # strx += "\\(" + self.subTreeRepr(node.getLeft(), "") + "\\)" else: if node.getLeft() is not None and node.getLeft().isSum(): for summ in node.getLeft().getElement().getSums(): summ.setShowNum(True) if node.getRight() is not None and node.getRight().isSum(): for summ in node.getRight().getElement().getSums(): summ.setShowNum(True) strx += self.subTreeRepr(node.getRight(), "") + repr( node.getElement()) + self.subTreeRepr(node.getLeft(), "") if brac: strx += "\\)" return strx else: return ""
def noPfoil(self, node): # print("in no P mul") # print(self.traverse()) if (node.getLeft() is None) and (node.getRight() is None): return node else: right = self.noPfoil(node.getRight()) left = self.noPfoil(node.getLeft()) if not node.isAlgOpp(): raise TypeError("Nodal element issue") if node.getRight().isLeaf() and node.getLeft().isLeaf(): set = False if node.getElement() == Sign("+"): if not (right.getElement().hasPartials()) and not ( left.getElement().hasPartials()): newEl = right.getElement().noPAdd(left.getElement()) node.setElement(newEl) set = True elif node.getElement() == Sign("-"): if not (right.getElement().hasPartials()) and not ( left.getElement().hasPartials()): newEl = right.getElement().noPSub(left.getElement()) node.setElement(newEl) set = True elif node.getElement() == Sign("*"): if not (right.getElement().hasPartials()) and not ( left.getElement().hasPartials()): newEl = right.getElement().noPMul(left.getElement()) node.setElement(newEl) set = True # special case - multiply constants in elif right.getElement().hasPartials( ) and not left.getElement().hasPartials(): # print("special case left") set = self.constantCaseHelper(node, right, left) elif left.getElement().hasPartials( ) and not right.getElement().hasPartials(): # print("special case right") set = self.constantCaseHelper(node, left, right) if set: node.setLeft(None) node.setRight(None) # print("after mult:", self.traverse()) elif node.getElement() == Sign("*"): if node.getRight().isLeaf() and node.getLeft( ).getElement == Sign("*"): if not node.getRight().getElement().hasPartials(): lr = node.getLeft().getRight() ll = node.getLeft().getLeft() if lr.isSum() and (not lr.getElement().hasPartials()): newEl = right.getElement().noPMul(lr.getElement()) right.setElement(newEl) node.setLeft(ll) elif ll.isSum() and ( not ll.getElement().hasPartials()): newEl = right.getElement().noPMul(ll.getElement()) right.setElement(newEl) node.setLeft(lr) elif node.getLeft().isLeaf() and node.getRight().getElement( ) == Sign("*"): if not node.getLeft().getElement().hasPartials(): rr = node.getRight().getRight() rl = node.getRight().getLeft() if rr.isSum() and (not rr.getElement().hasPartials()): newEl = left.getElement().noPMul(rr.getElement()) left.setElement(newEl) node.setRight(rl) elif rl.isSum() and ( not rl.getElement().hasPartials()): newEl = left.getElement().noPMul(rl.getElement()) left.setElement(newEl) node.setRight(rr) elif node.getLeft().getElement() == Sign( "*") and node.getRight().getElement() == Sign("*"): mul = True if left.getLeft().isSum() and not ( left.getLeft().getElement().hasPartials()): lOpen = left.getLeft() lPart = left.getRight() elif left.getRight().isSum() and not ( left.getRight().getElement().hasPartials()): lOpen = left.getRight() lPart = left.getLeft() else: mul = False lOpen = None lPart = left if right.getLeft().isSums() and not ( right.getLeft().getElement().hasPartials()): rOpen = right.getLeft() rPart = right.getRight() elif right.getRight().isSums() and not ( right.getRight().getElement().hasPartials()): rOpen = right.getRight() rPart = right.getLeft() else: mul = False rOpen = None rPart = right if mul: node.setLeft(EquationNode(lOpen.noPMul(rOpen))) node.getRight().setRight(rPart) node.getRight().setLeft(lPart) return node
def gcf(self, node): if not node.isSum(): return sums = node.getElement().getSums() if len(sums) == 1 or len(sums) == 0: return for summy in sums: summy.factorNumFromTensorCo() summy.factorSymFromTensorCo() otherTerm = MultGroup("+") added = False symCo = copy.deepcopy(sums[0].getSymbolCo()) tensors = copy.deepcopy(sums[0].getTensors()) variations = copy.deepcopy(sums[0].getVariations()) etas = copy.deepcopy(sums[0].getEtas()) deltas = copy.deepcopy(sums[0].getDeltas()) partials = copy.deepcopy(sums[0].getPartials()) tensorCos = copy.deepcopy(sums[0].getTensorCos()) numCosList = list() for sum1 in sums: numCosList.append(sum1.getNumCo()) numCo = min(numCosList) inAll = True for frac in numCosList: if frac % numCo != Fraction(0): inAll = False if inAll: otherTerm.addNumCo(numCo) added = True for sum2 in sums: sum2.setNumCo(sum2.getNumCo() / numCo) inAll = True for sum1 in sums: if not symCo == sum1.getSymbolCo(): inAll = False if inAll: otherTerm.setSymCo(symCo) added = True for sum2 in sums: sum2.setSymCo(SymbolCo()) inAll = True for sum1 in sums: if not tensorCos == sum1.getTensorCos(): inAll = False if inAll: otherTerm.addTensorCos(tensorCos) added = True for sum2 in sums: sum2.setTensorCos(TensorCoefficients([Coefficient()])) for tensor in tensors: inAll = True for sum1 in sums: if tensor not in sum1.getTensors(): inAll = False if inAll: otherTerm.addTensors(tensor) added = True for sum2 in sums: sum2.removeTensor(tensor) for variation in variations: inAll = True for sum1 in sums: if variation not in sum1.getVariations(): inAll = False if inAll: otherTerm.addVariations(variation) added = True for sum2 in sums: sum2.removeVar(variation) for delta in deltas: inAll = True for sum1 in sums: if delta not in sum1.getDeltas(): inAll = False if inAll: otherTerm.addDeltas(delta) added = True for sum2 in sums: sum2.removeDelta(delta) for eta in etas: inAll = True for sum1 in sums: if eta not in sum1.getEtas(): inAll = False if inAll: otherTerm.addEtas(eta) added = True for sum2 in sums: sum2.removeEta(eta) for partial in partials: inAll = True for sum1 in sums: if partial not in sum1.getPartials(): inAll = False if inAll: otherTerm.addPartials(partial) added = True for sum2 in sums: sum2.removePartial(partial) if added: node.setRight(EquationNode(Summation([otherTerm]))) node.setLeft(EquationNode(node.getElement())) node.setElement(Sign("*"))
def replaceSum(self, node, ogSumsInit, newSumsInit): print("ogSumsInit: ", ogSumsInit) print("newSumsInit: ", newSumsInit) if not node.isSum(): return sums = node.getElement().getSums() ogSums = ogSumsInit.getSums() # list of MultGroup objects newSums = newSumsInit.getSums() # list of MultGroup objects if len(ogSums) == 1: if ogSums[0].isOnlyTensor(): if len(newSums) == 1 and newSums[0].isOnlyTensor(): self.replaceOnlyTensor(sums, ogSums[0].getTensors()[0], newSums[0].getTensors()[0], 'ten') else: if ogSums[0].getSign() == "-": neg = True else: neg = False self.replaceTensor(node, ogSums[0].getTensors()[0], newSumsInit, neg, 'ten') return elif ogSums[0].isOnlyVar(): if len(newSums) == 1 and newSums[0].isOnlyVar(): self.replaceOnlyTensor(sums, ogSums[0].getVariations()[0], newSums[0].getVariations()[0], 'var') else: if ogSums[0].getSign() == "-": neg = True else: neg = False self.replaceTensor(node, ogSums[0].getVariations()[0], newSumsInit, neg, 'var') return elif len(newSums) == 1: ogSum = ogSums[0] newSum = newSums[0] i = 0 while i < len(sums): summy = sums[i] # MultGroup object if summy.patternEqIncludesH(ogSum): newSummy = copy.deepcopy(newSum) # MultGroup object newSummy.changeIndicesMultH(ogSum, summy) newSummy.addNumCo(summy.getNumCo() / ogSum.getNumCo()) newSummy.addSymCo(summy.getSymCo() / ogSum.getSymCo()) if not (summy.getTensorCo() == ogSum.getTensorCo()): newSummy.setTensorCo(summy.getTensorCo() * newSummy.getTensorCo()) if not (summy.getSign() == ogSum.getSign()): newSummy.swapSign() sums[i] = newSummy #node.getElement().replaceTerm(summy, newSummy) i += 1 # whether or not anything was replaced, we need to move on elif len(newSums) != 1: ogSum = ogSums[0] i = 0 while i < len(sums): summy = sums[i] posVersion = copy.deepcopy(ogSum) posVersion.swapSign( ) # create a positive version to test against if (summy.patternEqH(ogSum)) or ( summy.patternEqH(posVersion)): newAdd = copy.deepcopy(newSumsInit) if summy.getSign() != ogSum.getSign( ): # if they have opposite signs, factor out a negative, then multiply it through new for newSum in newAdd.getSums(): newSum.swapSign() newAdd.changeIndicesMultH(ogSum, summy) node.getElement().removeTerm(summy) for newSum in newAdd.getSums(): sums.insert(i, newSum) i += 1 elif summy.patternEqIncludesH(ogSum): newAdd = copy.deepcopy(newSumsInit) newAdd.changeIndicesMultH(ogSum, summy) node.getElement().removeTerm(summy) ## deal with what is left of multgroup outerMult = MultGroup("+") if summy.getSign() != ogSum.getSign(): outerMult.swapSign() outerMult.addNumCo(summy.getNumCo() / ogSum.getNumCo()) outerMult.addSymbolCo(summy.getSymCo() / ogSum.getSymCo()) if not (summy.getTensorCos() == ogSum.getTensorCos()): outerMult.setTensorCos(summy.getTensorCo()) ## create the reconstructed tree #if outerMult.getSign() == "-": # outerMult.swapSign() newNode = EquationNode(Sign("*")) newNode.setRight(EquationNode(Summation([outerMult]))) newNode.setLeft( EquationNode(Summation(newAdd.getSums()))) node.setLeft(EquationNode(node.getElement())) node.setRight(newNode) node.setElement(Sign("+")) node = node.getLeft() else: i += 1 else: # neither length is one testSums = copy.deepcopy(sums) testSumsPos = copy.deepcopy(sums) newAdd = copy.deepcopy(newSums) foundSums = list() for sum in testSumsPos: sum.swapSign() allIn = True for ogSum in ogSums: rem = False for summy in testSums: if ogSum.patternEqH(summy) and (not rem): testSums.remove(summy) foundSums.append(summy) rem = True if not rem: allIn = False allInPos = False if not allIn: foundSums.clear() allInPos = True for ogSum in ogSums: rem = False for summy in testSumsPos: if ogSum.patternEqH(summy) and (not rem): testSumsPos.remove(summy) foundSums.append(summy) rem = True if not rem: allInPos = False if allInPos: for summy in newAdd: summy.swapSign() allIn = True if allIn: old = ogSumsInit.getSortedIndicesList() new = Summation(foundSums).getSortedIndicesList() for newSum in newAdd: newSum.changeIndicesListH(old, new) sums = node.getElement().getSums() i = 0 for foundSum in foundSums: rem = False for oldSum in sums: if (oldSum == foundSum) and (not rem): i = sums.index(oldSum) sums.remove(oldSum) rem = True for newSum in newAdd: sums.insert(i, newSum) i += 1
def replaceTensor(self, node, jfk, lbj, neg, typae): # jfk is tensor, lbj is summation object i = len(node.getElement().getSums()) - 1 done = False while not done and i >= 0: pres = node.getElement().getSums()[i] if typae == 'ten': toAssassinate = pres.findTensor(jfk) # uses patternEq to find elif typae == 'var': toAssassinate = pres.findVariation(jfk) else: raise TypeError("can only assassinate variations or tensors") if toAssassinate is not None: # fugitive has been found done = True node.getElement().remRef( pres) # remove method removes first instance if typae == "ten": pres.removeTensorRef(toAssassinate) # PRES IS A MULTGROUP else: pres.removeVarRef(toAssassinate) if neg: pres.swapSign() toAssassinate.setSums() toIndsTen = copy.deepcopy(toAssassinate) toIndsTen.setPartials([]) # remove all partials fromIndsTen = copy.deepcopy(jfk) partials = copy.deepcopy(toAssassinate.getPartials()) for partial in jfk.getPartials(): rem = False for oPartial in partials: if (not rem) and (oPartial.patternEqH(partial)): partials.remove( oPartial ) # leave only non-shared partials: this will later be added to new Summation object (lbj) toIndsTen.addPartial( oPartial) # add back shared partials toMult = MultGroup("+") toMult.addThing(toIndsTen) fromMult = MultGroup("+") fromMult.addThing(fromIndsTen) lbjNEW = copy.deepcopy(lbj) lbjNEW.changeIndicesMultHNOSUMS(fromMult, toMult) #!!!!!!!!!!!! lbjNEW.setPartials(partials) # SUMMATION OBJECT newPres = EquationNode(lbjNEW) if pres.getSign() == "-" and node.getElement() != Summation(): signage = Sign("-") pres.swapSign() else: signage = Sign("+") if not (pres == MultGroup("+")): # if it's not empty jackie = EquationNode(Summation([pres])) self.replaceTensor(jackie, copy.deepcopy(jfk), copy.deepcopy(lbj), neg, typae) signNode = EquationNode(Sign("*")) signNode.setRight(jackie) signNode.setLeft( newPres) # multiply Jackie and the replacement victim = signNode.getLeft() else: signNode = newPres victim = signNode if node.getElement() != Summation(): # if it's not empty vietnam = EquationNode(node.getElement()) node.setElement(signage) node.setLeft(signNode) node.setRight( vietnam ) # add together the full replacement and the leftovers self.replaceTensor( node.getRight(), jfk, lbj, neg, typae ) # change pointer to node with element we haven't looked at yet else: #if signage == Sign("-"): # victim.getElement().getSums()[0].swapSign() #if signage == Sign("-"): node.setElement(signNode.getElement()) node.setRight(signNode.getRight()) node.setLeft(signNode.getLeft()) #self.replaceTensor(victim, jfk, lbj, neg, typae) else: i += -1
def noPfoil(self, node): if (node.getLeft() is None) and (node.getRight() is None): return node else: right = self.noPfoil(node.getRight()) left = self.noPfoil(node.getLeft()) if not node.isAlgOpp(): raise TypeError("Nodal element issue") if node.getRight().isLeaf() and node.getLeft().isLeaf(): set = False if node.getElement() == Sign("+"): if not (right.getElement().hasPartials()) and not ( left.getElement().hasPartials()): newEl = right.getElement().noPAdd(left.getElement()) node.setElement(newEl) set = True elif node.getElement() == Sign("-"): if not (right.getElement().hasPartials()) and not ( left.getElement().hasPartials()): newEl = right.getElement().noPSub(left.getElement()) node.setElement(newEl) set = True elif node.getElement() == Sign("*"): if not (right.getElement().hasPartials()) and not ( left.getElement().hasPartials()): newEl = right.getElement().noPMul(left.getElement()) node.setElement(newEl) set = True if set: node.setLeft(None) node.setRight(None) elif node.getElement() == Sign("*"): if node.getRight().isLeaf() and node.getLeft( ).getElement == Sign("*"): if not node.getRight().getElement().hasPartials(): lr = node.getLeft().getRight() ll = node.getLeft().getLeft() if lr.isSum() and (not lr.getElement().hasPartials()): newEl = right.getElement().noPMul(lr.getElement()) right.setElement(newEl) node.setLeft(ll) elif ll.isSum() and ( not ll.getElement().hasPartials()): newEl = right.getElement().noPMul(ll.getElement()) right.setElement(newEl) node.setLeft(lr) elif node.getLeft().isLeaf() and node.getRight().getElement( ) == Sign("*"): if not node.getLeft().getElement().hasPartials(): rr = node.getRight().getRight() rl = node.getRight().getLeft() if rr.isSum() and (not rr.getElement().hasPartials()): newEl = left.getElement().noPMul(rr.getElement()) left.setElement(newEl) node.setRight(rl) elif rl.isSum() and ( not rl.getElement().hasPartials()): newEl = left.getElement().noPMul(rl.getElement()) left.setElement(newEl) node.setRight(rr) elif node.getLeft().getElement() == Sign( "*") and node.getRight().getElement() == Sign("*"): mul = True if left.getLeft().isSum() and not ( left.getLeft().getElement().hasPartials()): lOpen = left.getLeft() lPart = left.getRight() elif left.getRight().isSum() and not ( left.getRight().getElement().hasPartials()): lOpen = left.getRight() lPart = left.getLeft() else: mul = False lOpen = None lPart = left if right.getLeft().isSums() and not ( right.getLeft().getElement().hasPartials()): rOpen = right.getLeft() rPart = right.getRight() elif right.getRight().isSums() and not ( right.getRight().getElement().hasPartials()): rOpen = right.getRight() rPart = right.getLeft() else: mul = False rOpen = None rPart = right if mul: node.setLeft(EquationNode(lOpen.noPMul(rOpen))) node.getRight().setRight(rPart) node.getRight().setLeft(lPart) return node