def solutionList(poly,nterms,asPuiseuxObject=False): """ Calls :py:func:`recurse` to compute a list of the first :py:data:`nterms` puiseux series solutions of :py:data:`poly`. If :py:data:`asPuiseuxObject` is false, they are returned as lists of *(gamma,c)* pairs; otherwise they are returned as :py:class:`puiseuxPoly.puiseux` objects. """ if poly.degree()==0:return [] toReturn = [] lowest = poly.lowestDegree() if lowest>0: toReturn+=[puiseux({0:0}) for i in xrange(lowest)] poly = poly.reduced() it = initialTerms(poly) p = puiseux({it[0][0]:it[0][1]}) for firstTerm in initialTerms(poly): recurse(poly,firstTerm,[firstTerm],toReturn,nterms-1) if len(toReturn)!=poly.degree()+lowest: print "Uh-oh. Polynomial is degree ",poly.degree()," but we've found ",len(toReturn)," solutions" # return as a list of puiseux objects instead of a list of term tuples if asPuiseuxObject: newRet = [] for item in toReturn: pu = {} for pair in item: pu[pair[0]]=pair[1] newRet.append(puiseux(pu)) toReturn = newRet return toReturn
def solutionList(poly, nterms, asPuiseuxObject=False): """ Calls :py:func:`recurse` to compute a list of the first :py:data:`nterms` puiseux series solutions of :py:data:`poly`. If :py:data:`asPuiseuxObject` is false, they are returned as lists of *(gamma,c)* pairs; otherwise they are returned as :py:class:`puiseuxPoly.puiseux` objects. """ if poly.degree() == 0: return [] toReturn = [] lowest = poly.lowestDegree() if lowest > 0: toReturn += [puiseux({0: 0}) for i in xrange(lowest)] poly = poly.reduced() it = initialTerms(poly) p = puiseux({it[0][0]: it[0][1]}) for firstTerm in initialTerms(poly): recurse(poly, firstTerm, [firstTerm], toReturn, nterms - 1) if len(toReturn) != poly.degree() + lowest: print "Uh-oh. Polynomial is degree ", poly.degree( ), " but we've found ", len(toReturn), " solutions" # return as a list of puiseux objects instead of a list of term tuples if asPuiseuxObject: newRet = [] for item in toReturn: pu = {} for pair in item: pu[pair[0]] = pair[1] newRet.append(puiseux(pu)) toReturn = newRet return toReturn
def rootGen(): nextPoly = poly prevRoot = root lastExp = 0 while True: yield puiseux({prevRoot[1]+lastExp:prevRoot[0]}) nextPoly = nextPoly(mypoly({1:puiseux({prevRoot[1]:1}),0:puiseux({prevRoot[1]:prevRoot[0]})}))
def recurse(poly, currentMonomial, currentList, bigList, depth): """ bigList will contain lists of terms for each solution (list of lists). currentList is the one we're currently computing. Working with lists instead of Puiseux objects for speed and ease of access Assumes currentMonomial is already in the list, and adds the new ones found. """ if depth == 0: bigList.append(currentList) return toPlug = mypoly({ 1: puiseux({currentMonomial[0]: 1}), 0: puiseux({currentMonomial[0]: currentMonomial[1]}) }) nextPoly = poly(toPlug) if len(nextPoly.internal.keys()) == 1: bigList.append(currentList) return nextTerms = initialTerms(nextPoly, positivesOnly=True) if nextTerms == []: bigList.append(currentList) return for term in nextTerms: revisedList = [a for a in currentList] revisedList.append((term[0] + currentList[-1][0], term[1])) recurse(nextPoly, term, revisedList, bigList, depth - 1)
def recurse(poly,currentMonomial,currentList,q,depth): """ bigList will contain lists of terms for each solution (list of lists). currentList is the one we're currently computing. Working with lists instead of Puiseux objects for speed and ease of access Assumes currentMonomial is already in the list, and adds the new ones found. """ if depth<1 or currentMonomial==(0,0): q.put(currentList) ###### return toPlug = mypoly({1:puiseux({currentMonomial[0]:1}),0:puiseux({currentMonomial[0]:currentMonomial[1]})}) nextPoly = poly(toPlug) nextTerms = initialTerms(nextPoly,positivesOnly=True) if nextTerms==[]: q.put(currentList) ###### return procList = [] for term in nextTerms[1:]: revisedList = [] for a in currentList: revisedList.append(a) revisedList.append((term[0]+currentList[-1][0],term[1])) p = Process(target=recurse,args=(nextPoly,term,revisedList,q,depth-1)) ###### procList.append(p) ###### p.start() ###### revisedList = [] for a in currentList: revisedList.append(a) nt = nextTerms[0] revisedList.append((nt[0]+currentList[-1][0],nt[1])) recurse(nextPoly,nt,revisedList,q,depth-1) for p in procList: p.join() ######
def __init__(self,poly,checkReduced=True): """ 2x^2-3x+1 would be input as [[2,2],[-3,1],[1,0]] and represented internally as {2:2,1:-3,0:1} i.e. the keys are the exponents and the values are the coefficients --OR-- can be input as a dictionary, in which case it will just be copied to internal Coefficients can be complex, int, long (if you really want to), or (in the most usefull case) puiseux polynomials (using the puiseuxPoly class). **Maybe not**: they might need to be Puiseux objects? checkReduced is a flag that determines if when setting up the internal representation we check for like terms. Be careful with it!!! If poly is a dict, checkReduced doesn't matter since it can't have repeated keys (exponents) """ self.internal = {} if type(poly)==str: """ This is bad. Uses eval. """ from sympy import poly as symp from sympy.abc import x,y s = poly s = s.replace('^','**') p = symp(eval(s),x,y,domain='CC') print p d = {item[0][1]:puiseux({item[0][0]:complex(item[1])}) for item in p.terms()} for item in p.terms(): if item[0][1] in d.keys(): d[item[0][1]]+=puiseux({item[0][0]:complex(item[1])}) else: d[item[0][1]] = puiseux({item[0][0]:complex(item[1])}) poly = d if type(poly)==dict: for key in poly.keys(): if type(poly[key])!=puiseux: self.internal[key] = puiseux({0:poly[key]}) else: self.internal[key] = poly[key] elif checkReduced: self.internal = {poly[0][1]:poly[0][0]} for mon in poly[1:]: coeff = mon[0] exponent = mon[1] if exponent in self.internal: self.internal[exponent] += coeff else: self.internal[exponent] = coeff else: self.internal = {} for elt in poly: self.internal[elt[1]]=elt[0] for key in self.internal.keys(): if self.internal[key]==0: self.internal.pop(key) if self.internal=={}:self.internal = {0:0}
def rootGen(): nextPoly = poly prevRoot = root lastExp = 0 while True: yield puiseux({prevRoot[1] + lastExp: prevRoot[0]}) nextPoly = nextPoly( mypoly({ 1: puiseux({prevRoot[1]: 1}), 0: puiseux({prevRoot[1]: prevRoot[0]}) }))
def __pow__(self,other): if type(other)==int and other>=0: if other==0: return mypoly({0:puiseux({Fraction(0,1):1})}) else: toReturn = mypoly({0:puiseux({Fraction(0,1):1})}) for i in xrange(other): toReturn = self*toReturn return toReturn elif type(other)==int: raise TypeError("don't have support for negative exponents") else: raise TypeError("can't do that")
def genRandom(self): """ Generates a random polynomial whose y-degree is <= ``self.ydeg`` and x-degree <= ``self.xdeg``. """ poly = {} size = randint(2, len(self.monomials)) support = choice(len(self.monomials), size, replace=False) support = [self.monomials[i] for i in support] for mon in support: angle = random() coeff = complex(cos(angle), sin(angle)) if mon[0] not in poly: poly[mon[0]] = puiseux({mon[1]: coeff}) else: poly[mon[0]] += puiseux({mon[1]: coeff}) return mypoly(poly)
def firstTerms(poly): """ Using :py:func:`initialTerms`, returns a list of the first terms of the puiseux solotions of :py:data:`poly` as :py:class:`puiseuxPoly.puiseux` objects. """ toReturn = [] for (gamma,c) in initialTerms(poly): toReturn.append(puiseux({gamma:c})) return toReturn
def firstTerms(poly): """ Using :py:func:`initialTerms`, returns a list of the first terms of the puiseux solotions of :py:data:`poly` as :py:class:`puiseuxPoly.puiseux` objects. """ toReturn = [] for (gamma, c) in initialTerms(poly): toReturn.append(puiseux({gamma: c})) return toReturn
def puiseuxify(listy): """ Takes a list of lists of (*c,gamma*) tuples and turns it into the corresponding list of puiseux polynomials. """ newRet = [] for item in listy: pu = {} for pair in item: pu[pair[0]]=pair[1] newRet.append(puiseux(pu)) return newRet
def puiseuxify(listy): """ Takes a list of lists of (*c,gamma*) tuples and turns it into the corresponding list of puiseux polynomials. """ newRet = [] for item in listy: pu = {} for pair in item: pu[pair[0]] = pair[1] newRet.append(puiseux(pu)) return newRet
def recurse(poly,currentMonomial,currentList,bigList,depth): """ bigList will contain lists of terms for each solution (list of lists). currentList is the one we're currently computing. Working with lists instead of Puiseux objects for speed and ease of access Assumes currentMonomial is already in the list, and adds the new ones found. """ if depth==0: bigList.append(currentList) return toPlug = mypoly({1:puiseux({currentMonomial[0]:1}),0:puiseux({currentMonomial[0]:currentMonomial[1]})}) nextPoly = poly(toPlug) if len(nextPoly.internal.keys())==1: bigList.append(currentList) return nextTerms = initialTerms(nextPoly,positivesOnly=True) if nextTerms==[]: bigList.append(currentList) return for term in nextTerms: revisedList = [a for a in currentList] revisedList.append((term[0]+currentList[-1][0],term[1])) recurse(nextPoly,term,revisedList,bigList,depth-1)
def recurse(poly, currentMonomial, currentList, q, depth): """ bigList will contain lists of terms for each solution (list of lists). currentList is the one we're currently computing. Working with lists instead of Puiseux objects for speed and ease of access Assumes currentMonomial is already in the list, and adds the new ones found. """ if depth < 1 or currentMonomial == (0, 0): q.put(currentList) ###### return toPlug = mypoly({ 1: puiseux({currentMonomial[0]: 1}), 0: puiseux({currentMonomial[0]: currentMonomial[1]}) }) nextPoly = poly(toPlug) nextTerms = initialTerms(nextPoly, positivesOnly=True) if nextTerms == []: q.put(currentList) ###### return procList = [] for term in nextTerms[1:]: revisedList = [] for a in currentList: revisedList.append(a) revisedList.append((term[0] + currentList[-1][0], term[1])) p = Process(target=recurse, args=(nextPoly, term, revisedList, q, depth - 1)) ###### procList.append(p) ###### p.start() ###### revisedList = [] for a in currentList: revisedList.append(a) nt = nextTerms[0] revisedList.append((nt[0] + currentList[-1][0], nt[1])) recurse(nextPoly, nt, revisedList, q, depth - 1) for p in procList: p.join() ######
if __name__ == '__main__': import sys """ try: n = int(sys.argv[1]) except Exception: n = 0 """ try: s = sys.argv[1] except Exception: s = 'circle' try: numterms = int(sys.argv[2]) except Exception: numterms = 4 optList = {'other':mypoly({0:puiseux({1:1}),1:puiseux({0:2}),2:puiseux({1:1})}),\ 'arxiv':mypoly({0:puiseux({4:2}),1:puiseux({2:1}),2:puiseux({1:4}),3:puiseux({0:4})}),\ 'walker':mypoly({0:puiseux({Fraction(5):1}), 1:puiseux({Fraction(7,2):1}), 2:puiseux({Fraction(1):1}), 3:puiseux({Fraction(-1):1}), 5:puiseux({Fraction(-1,2):1}), 6:puiseux([[1,[1,2]]]), 7:puiseux([[1,[10,3]]]), 8:puiseux([[1,[5,2]]])}),\ 'terminates':mypoly({0:puiseux({1:1}),1:puiseux({2:2})}),\ 'seminar':mypoly({2:puiseux({0:1}),1:puiseux({1:2,2:2}),0:puiseux({0:-1})}),\ 'circle':mypoly({0:puiseux({0:-1,2:1}),2:puiseux({0:1})}),\ 'squares':mypoly({0:puiseux({2:1}),2:puiseux({0:1})}),\ 'ellipticNonsmooth':mypoly({2:puiseux({0:-1}),0:puiseux({3:1,1:-27,0:2*27})}),\ 'test':mypoly({0:puiseux({1:1}),1:puiseux({2:4,0:2}),3:puiseux({1:2}),5:puiseux({2:-1})}),\ 'homotopy1':mypoly({2:puiseux({0:1}),1:puiseux({1:3}),0:puiseux({0:-1,1:-3})}),\ 'ellipticSmooth':mypoly({2:puiseux({0:-1}),0:puiseux({3:1,1:1,0:1})})} if s not in optList.keys() or s == 'help': toPrint = '\n' + s + ' is not a valid option. Please choose from: \n' toPrint += str(optList.keys()) raise Exception(toPrint) p = optList[s]
recurse(nextPoly, term, revisedList, bigList, depth - 1) if __name__ == '__main__': import sys try: n = int(sys.argv[1]) except Exception: n = 0 try: numterms = int(sys.argv[2]) except Exception: numterms = 4 if n == 0: p = mypoly({ 0: puiseux({1: 1}), 1: puiseux({0: 2}), 2: puiseux({1: 1}) }) elif n == 1: p = mypoly({ 0: puiseux({4: 2}), 1: puiseux({2: 1}), 2: puiseux({1: 4}), 3: puiseux({0: 4}) }) elif n == 2: p = mypoly({ 0: puiseux({Fraction(5): 1}), 1: puiseux({Fraction(7, 2): 1}), 2: puiseux({Fraction(1): 1}),
recurse(nextPoly,nt,revisedList,q,depth-1) for p in procList: p.join() ###### if __name__=='__main__': import sys """ try: n = int(sys.argv[1]) except Exception: n = 0 """ try: s = sys.argv[1] except Exception: s = 'circle' try: numterms = int(sys.argv[2]) except Exception: numterms = 4 optList = {'other':mypoly({0:puiseux({1:1}),1:puiseux({0:2}),2:puiseux({1:1})}),\ 'arxiv':mypoly({0:puiseux({4:2}),1:puiseux({2:1}),2:puiseux({1:4}),3:puiseux({0:4})}),\ 'walker':mypoly({0:puiseux({Fraction(5):1}), 1:puiseux({Fraction(7,2):1}), 2:puiseux({Fraction(1):1}), 3:puiseux({Fraction(-1):1}), 5:puiseux({Fraction(-1,2):1}), 6:puiseux([[1,[1,2]]]), 7:puiseux([[1,[10,3]]]), 8:puiseux([[1,[5,2]]])}),\ 'terminates':mypoly({0:puiseux({1:1}),1:puiseux({2:2})}),\ 'seminar':mypoly({2:puiseux({0:1}),1:puiseux({1:2,2:2}),0:puiseux({0:-1})}),\ 'circle':mypoly({0:puiseux({0:-1,2:1}),2:puiseux({0:1})}),\ 'squares':mypoly({0:puiseux({2:1}),2:puiseux({0:1})}),\ 'ellipticNonsmooth':mypoly({2:puiseux({0:-1}),0:puiseux({3:1,1:-27,0:2*27})}),\ 'test':mypoly({0:puiseux({1:1}),1:puiseux({2:4,0:2}),3:puiseux({1:2}),5:puiseux({2:-1})}),\ 'homotopy1':mypoly({2:puiseux({0:1}),1:puiseux({1:3}),0:puiseux({0:-1,1:-3})}),\ 'ellipticSmooth':mypoly({2:puiseux({0:-1}),0:puiseux({3:1,1:1,0:1})})} if s not in optList.keys() or s=='help': toPrint = '\n'+s+' is not a valid option. Please choose from: \n' toPrint += str(optList.keys()) raise Exception(toPrint) p = optList[s]
self.slider = Slider(self.sliderax, 'Value', 0, self.NUMTERMS - 3, valinit=self.inc) self.slider.on_changed(self.update) self.slider.drawon = False self.dot, = self.ax.plot(self.sols[0][0], self.sols[0][1], 'bo') self.ax.axis(self.windowBounds) def update(self, value): value = int(value) self.dot.set_data(self.sols[value][0], self.sols[value][1]) self.slider.valtext.set_text('{}'.format(value)) self.fig.canvas.draw() def show(self): plt.show() if __name__ == '__main__': NUMTERMS = 75 poly = mypoly({0: puiseux({0: -1, 2: 1}), 2: puiseux({0: 1})}) print solutionList(poly, 4) #poly = mypoly({2:puiseux({0:-1}),0:puiseux({3:1,1:-27,0:2*27})}) p = ChangingPlot(poly, NUMTERMS) if '-s' in sys.argv: p.show()
""" A convenience class that uses Sympy to allow easier command line input. Asks user for a polynomial and for the number of desired terms. Poly can be input as, for example, (x^3-y)*(2x+4). Sympy takes care of the simplification and the script transforms it into a mypoly object and calls the solutionList function. """ if len(sys.argv)==3: s = sys.argv[1] n = int(sys.argv[2]) else: s = raw_input("Enter a polynomial in x and y --> ") n = input("Enter the number of desired terms --> ") s = s.replace('^','**') p = poly(eval(s),x,y,domain='CC') """ d = {item[0][1]:puiseux({item[0][0]:complex(item[1])}) for item in p.terms()} for item in p.terms(): if item[0][1] in d.keys(): d[item[0][1]]+=puiseux({item[0][0]:complex(item[1])}) else: d[item[0][1]] = puiseux({item[0][0]:complex(item[1])}) m = mypoly(d) """ d = {item[0][1]:0 for item in p.terms()} for item in p.terms(): d[item[0][1]]+=puiseux({item[0][0]:complex(item[1])}) m = mypoly(d) print m for sol in solutionList(m,n,True): print print sol.LT() print sol
self.inc = 1.0 self.fig, self.ax = plt.subplots() self.sliderax = self.fig.add_axes([0.2, 0.02, 0.6, 0.03], axisbg='yellow') self.slider = Slider(self.sliderax, 'Value', 0, self.NUMTERMS-3, valinit=self.inc) self.slider.on_changed(self.update) self.slider.drawon = False self.dot, = self.ax.plot(self.sols[0][0],self.sols[0][1], 'bo') self.ax.axis(self.windowBounds) def update(self, value): value = int(value) self.dot.set_data(self.sols[value][0],self.sols[value][1]) self.slider.valtext.set_text('{}'.format(value)) self.fig.canvas.draw() def show(self): plt.show() if __name__=='__main__': NUMTERMS = 75 poly = mypoly({0:puiseux({0:-1,2:1}),2:puiseux({0:1})}) print solutionList(poly,4) #poly = mypoly({2:puiseux({0:-1}),0:puiseux({3:1,1:-27,0:2*27})}) p = ChangingPlot(poly,NUMTERMS) if '-s' in sys.argv: p.show()
""" A convenience class that uses Sympy to allow easier command line input. Asks user for a polynomial and for the number of desired terms. Poly can be input as, for example, (x^3-y)*(2x+4). Sympy takes care of the simplification and the script transforms it into a mypoly object and calls the solutionList function. """ if len(sys.argv) == 3: s = sys.argv[1] n = int(sys.argv[2]) else: s = raw_input("Enter a polynomial in x and y --> ") n = input("Enter the number of desired terms --> ") s = s.replace('^', '**') p = poly(eval(s), x, y, domain='CC') """ d = {item[0][1]:puiseux({item[0][0]:complex(item[1])}) for item in p.terms()} for item in p.terms(): if item[0][1] in d.keys(): d[item[0][1]]+=puiseux({item[0][0]:complex(item[1])}) else: d[item[0][1]] = puiseux({item[0][0]:complex(item[1])}) m = mypoly(d) """ d = {item[0][1]: 0 for item in p.terms()} for item in p.terms(): d[item[0][1]] += puiseux({item[0][0]: complex(item[1])}) m = mypoly(d) print m for sol in solutionList(m, n, True): print print sol.LT() print sol
bigList.append(currentList) return for term in nextTerms: revisedList = [a for a in currentList] revisedList.append((term[0]+currentList[-1][0],term[1])) recurse(nextPoly,term,revisedList,bigList,depth-1) if __name__=='__main__': import sys try: n = int(sys.argv[1]) except Exception: n = 0 try: numterms = int(sys.argv[2]) except Exception: numterms = 4 if n==0: p = mypoly({0:puiseux({1:1}),1:puiseux({0:2}),2:puiseux({1:1})}) elif n==1: p = mypoly({0:puiseux({4:2}),1:puiseux({2:1}),2:puiseux({1:4}),3:puiseux({0:4})}) elif n==2: p = mypoly({0:puiseux({Fraction(5):1}), 1:puiseux({Fraction(7,2):1}), 2:puiseux({Fraction(1):1}), 3:puiseux({Fraction(-1):1}), 5:puiseux({Fraction(-1,2):1}), 6:puiseux([[1,[1,2]]]), 7:puiseux([[1,[10,3]]]), 8:puiseux([[1,[5,2]]])}) elif n==3: p = mypoly({0:puiseux({1:1}),1:puiseux({2:2})}) elif n==4: p = mypoly({0:puiseux({0:-1,2:1}),2:puiseux({0:1})}) else: p = mypoly({0:puiseux({2:1}),2:puiseux({0:1})}) print p print "\n\n" for item in solutionList(p,numterms): print '---->----' sol = puiseux({itemy[0]:itemy[1] for itemy in item}) print 'Solution: ',sol print 'First term of p(solution): ',p(sol).LT() print '----<----' def solutionIterators(poly):
from puiseuxPoly import puiseux from mypoly import mypoly from expandParallel import solutionList from fractions import Fraction as fr import cPickle if __name__=='__main__': p = mypoly({0:puiseux({5:1}),1:puiseux({fr(7,2):1}),2:puiseux({1:1}),3:puiseux({-1:1}),5:puiseux({fr(-1,2):1}),6:puiseux({fr(1,2):1}),7:puiseux({fr(10,3):1}),8:puiseux({fr(5,2):1})}) p = mypoly({0:puiseux({0:(0.602188930612+0.991723585529j)}),4:puiseux({3:0.991343060948+0.811367139699j})}) p = cPickle.load(open("failurePoly.p","rb")) n=4 sols = solutionList(p,n,True) for sol in sols: expList = [p(sol.trunc(j)).order() for j in xrange(1,len(sol.internal))] print sol.trunc(1),'\r\t\t\t\t\t\t',[str(item) for item in expList]
""" return max(self.internal.keys()) def lowestDegree(self): """ Returns the degree of the lowest-degree monomial. """ return min(self.internal.keys()) def reduced(self): """ Returns ``self`` without any (y-0) factors. """ toReturn = {} lowest = self.lowestDegree() for i in self.internal.keys(): toReturn[i-lowest] = self.internal[i] return mypoly(toReturn) if __name__=='__main__': poly = mypoly({0:puiseux({2:1,3:-1}),1:puiseux({1:-2}),2:puiseux({0:1})}) poly = mypoly({0:puiseux({4:2}),1:puiseux({2:1}),2:puiseux({1:4}),3:puiseux({0:4})}) print 'poly: ',poly first = puiseux({2:-2}) print first print poly(first) print poly print poly.support() print poly.degree()