def polsolve(self,coeffarr): """ Solves a polynomial with the coefficients input is an array of [coefficient,int of the exponent] returns an array of solutions """ degree=max([n[1] for n in coeffarr]) if degree==2: a=ent.number(["0"]) b=ent.number(["0"]) c=ent.number(["0"]) for n in coeffarr: if n[1]==0: if c!=ent.number(["0"]): raise ValueError("bad polynomial") c=n[0] elif n[1]==1: if b!=ent.number(["0"]): raise ValueError("bad polynomial") b=n[0] elif n[1]==2: if a!=ent.number(["0"]): raise ValueError("bad polynomial") a=n[0] minusfour=ent.product([ent.number(["-1"]),ent.number(["4"])]) sqrtdiscriminant=ent.potens([ent.addition([ent.potens([b,ent.number(["2"])]),ent.product([minusfour,a,c])]),ent.division([ent.number(["1"]),ent.number(["2"])])]) solvedenominator=ent.product([ent.number(["2"]),a]) minusb=ent.product([ent.number(["-1"]),b]) minussquarerootd=ent.product([ent.number(["-1"]),sqrtdiscriminant]) solutionone=ent.division([ent.addition([minusb,sqrtdiscriminant]),solvedenominator]) solutiontwo=ent.division([ent.addition([minusb,minussquarerootd]),solvedenominator]) return [solutionone,solutiontwo]
def movesolvenumstoleftside(self,solvesideinput,constantsideinput,solvenum,firstrun=True): """ Returns to new expressions that are just as equal as the one you put in. Should have put the solvenum on the solveside (the first index in the return value) """ solvenumstring=solvenum.num if solvesideinput.contains(solvenumstring) and not constantsideinput.contains(solvenumstring): return [solvesideinput,constantsideinput] elif constantsideinput.contains(solvenumstring) and not solvesideinput.contains(solvenumstring): return [constantsideinput,solvesideinput] elif not constantsideinput.contains(solvenumstring) and not solvesideinput.contains(solvenumstring): return [constantsideinput,solvesideinput] solveside=solvesideinput.simplify(solvenum) constantside=constantsideinput.simplify(solvenum) if constantside.type()=="addition": # newconstantsideaddends=[] newsolvesideaddends=[solveside] for addend in constantside.addends: if addend.contains(solvenumstring): newsolvesideaddends.append( ent.maybeclass([ent.number(["-1"]),addend],ent.product) ) else: newconstantsideaddends.append(addend) newsolveside=ent.addition(newsolvesideaddends) newconstantside=ent.addition(newconstantsideaddends) return self.movesolvenumstoleftside(newsolveside,newconstantside,solvenum,False) elif constantside.type()=="product": newsolvedividors=[] newconstantsidefacts=[] for factor in constantside.factors: if factor.contains(solvenumstring): newsolvedividors.append(factor) else: newconstantsidefacts.append(factor) newsolveside=ent.division([solveside,ent.maybeclass(newsolvedividors,ent.product)]) newconstantside=ent.maybeclass(newconstantsidefacts,ent.product) return self.movesolvenumstoleftside(newsolveside,newconstantside,solvenum,False) elif constantside.type()=="division": num=constantside.numerator denom=constantside.denominator if num.contains(solvenumstring): newsolveside=ent.addition([solveside,ent.product([ent.number(["-1"]),constantside])]) newconstantside=ent.number(["0"]) elif denom.contains(solvenumstring): newsolveside=ent.product([denom,solveside]) newconstantside=num return self.movesolvenumstoleftside(newsolveside,newconstantside,solvenum,False) elif constantside.type()=="potens": root=constantside.root exponent=constantside.exponent newsolveside=ent.addition([solveside,ent.product([ent.number(["-1"]),constantside])]) newconstantside=ent.number(["0"]) return self.movesolvenumstoleftside(newsolveside,newconstantside,solvenum,False) elif constantside.type() in ["number","sine","cosine","tangent","arcsine","arccosine","arctangent","natlogarithm","comlogarithm","squareroot"]: newsolveside=ent.addition([solveside,ent.product([ent.number(["-1"]),constantside])]) newconstantside=ent.number(["0"]) return self.movesolvenumstoleftside(newsolveside,newconstantside,solvenum,False)
def solvepotens(self,solveside,constantside,solvenum): """ Is a solving method if f(x)^c=k -> f(x)=k^(1/c) if c^f(x)=k -> f(x)=ln(k)/ln(c) else: return None """ root=solveside.root exponent=solveside.exponent if not exponent.contains(solvenum.num): #if exponent==ent.number(["2"]): # returnsolveside=root # returnconstantside=ent.squareroot([constantside]) # return [[returnsolveside,returnconstantside],[returnsolveside,ent.product([ent.number(["-1"]),returnconstantside])]] if exponent.evaluable(True) and eval(exponent.tostring().replace("^","**"))%2==0: returnsolveside=root returnconstantside=ent.potens([constantside,ent.division([ent.number(["1"]),exponent])]) return [[returnsolveside,returnconstantside],[returnsolveside,ent.product([ent.number(["-1"]),returnconstantside])]] else: returnsolveside=root returnconstantside=ent.potens([constantside,ent.division([ent.number(["1"]),exponent])]) return [[returnsolveside,returnconstantside]] if not root.contains(solvenum.num): returnsolveside=exponent returnconstantside=ent.division([ent.natlogarithm([constantside]),ent.natlogarithm([root])]) return [[returnsolveside,returnconstantside]] return None
def solvedivison(self,solveside,constantside,solvenum): """ is a solving method for division if solvenum is in the numerator, the constantside gets multiplied to the constantside if solvenum is in the denominator, the denominator gets multiplied to the other side, and the solveside and constantside are switched """ if not solveside.denominator.contains(solvenum.num): returnsolveside=solveside.numerator returnconstantside=ent.product([constantside,solveside.denominator]) return [[returnsolveside,returnconstantside]] if not solveside.numerator.contains(solvenum.num): returnsolveside=ent.product([solveside.denominator,constantside]) returnconstantside=solveside.numerator return [[returnsolveside,returnconstantside]] return None
def TextToCAS(instring,recursions=0): """ TextToCAS will turn a string (eg "2*x+3") and turn it into a tree of the classes you'll see in Entityclass """ origin=instring instring=instring.replace("-","+-").replace("++","+").replace("--","+").replace("(+-","(-") newinstring="" for index,char in enumerate(instring): if char=="_": if index==0: pass elif instring[index-1] not in ["*","/","+","-","("]: if index>=2 and instring[index-2]=="-": pass elif index+1<len(instring) and instring[index+1]=="{": pass else: newinstring+="*" newinstring+=char instring=newinstring[:] if ydersteparentes(stringtoparentespar(instring))==[0,len(instring)-1]: instring=instring[1:-1] #if instring[0]=="+":instring=instring[1:] if instring[0]=="+" or instring[0]=="*": instring=instring[1:] if instring[0]=="-" and findcharoutsideparentes("+",instring)==[]: return Entities.product([Entities.number(["-1"]),TextToCAS(instring[1:])]) if [0,len(instring)-1] in stringtoparentespar(instring): instring=instring[1:-1] if ydersteparentes(stringtoparentespar(instring))==[0,len(instring)-1]:instring=instring[1:-1] #debug(3,"new string: "+str(instring)) #foerst addition plusses=findcharoutsideparentes("+",instring) if plusses!=[]: debug(3,recursions*" "+origin+" becomes ADDITION "+str(splitstringbyindexes(instring,plusses)) ) return Entities.addition([TextToCAS(n,recursions+1) for n in splitstringbyindexes(instring,plusses)]) #saa produkt gangetegn=findcharoutsideparentes("*",instring) if gangetegn!=[]: debug(3,recursions*" "+origin+" becomes PRODUKT "+str(splitstringbyindexes(instring,gangetegn)) ) return Entities.product([TextToCAS(n,recursions+1) for n in splitstringbyindexes(instring,gangetegn)]) #saa division broekstreger=findcharoutsideparentes("/",instring) if broekstreger!=[]: if len(broekstreger)>1: debug(1,"TVETYDIG BROEK, STOPPER PROGRAMMET") exit() debug(3,recursions*" "+origin+" becomes DIVISION "+str(splitstringbyindexes(instring,broekstreger) )) return Entities.division([TextToCAS(n,recursions+1) for n in splitstringbyindexes(instring,broekstreger)]) #saa potenser eksponenttegn=findcharoutsideparentes("^",instring) if eksponenttegn!=[]: if len(eksponenttegn)>1: debug(1,"Bad exponentiation, quitting") exit() debug(3,recursions*" "+origin+" becomes POTENS "+str(splitstringbyindexes(instring,eksponenttegn)) ) return Entities.potens([TextToCAS(n,recursions+1) for n in splitstringbyindexes(instring,eksponenttegn)],True) #saa funktioner for index,char in enumerate(instring): #allowedchars=["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"] disallowedchars=[")","("] if char=="(" and instring[index-1] not in disallowedchars: startbracket=index #proceeds to find the string that defines the function, ie sin(2x) bracketoffset=1 for indexk in range(len(instring)-1,-1,-1): if instring[indexk]=="(": bracketoffset+=1 elif instring[indexk]==")": bracketoffset-=1 if bracketoffset==0: funcend=indexk break funcstring=instring[0:startbracket] insidebrackets=instring[startbracket+1:funcend] #findcommas escapeoffset=0 commaindexes=[] for index,char in enumerate(insidebrackets): if escapeoffset>0: if char=="}": escapeoffset-=1 if char=="{": escapeoffset+=1 elif char==",": commaindexes.append(index) #print(funcstring,insidebrackets) if commaindexes==[]:# functions with one argument if funcstring=="sin": debug(3,recursions*" "+origin+" becomes Sine: "+insidebrackets ) return Entities.sine([TextToCAS(insidebrackets,recursions+1)]) elif funcstring=="cos": debug(3,recursions*" "+origin+" becomes Cosine: "+insidebrackets ) return Entities.cosine([TextToCAS(insidebrackets,recursions+1)]) elif funcstring=="tan": debug(3,recursions*" "+origin+" becomes Tangent: "+insidebrackets ) return Entities.tangent([TextToCAS(insidebrackets,recursions+1)]) elif funcstring=="arcsin" or funcstring=="asin": debug(3,recursions*" "+origin+" becomes Arcsine: "+insidebrackets ) return Entities.arcsine([TextToCAS(insidebrackets,recursions+1)]) elif funcstring=="arccos" or funcstring=="acos": debug(3,recursions*" "+origin+" becomes Arccosine: "+insidebrackets ) return Entities.arccosine([TextToCAS(insidebrackets,recursions+1)]) elif funcstring=="arctan" or funcstring=="atan": debug(3,recursions*" "+origin+" becomes Arctangent: "+insidebrackets ) return Entities.arctangent([TextToCAS(insidebrackets,recursions+1)]) elif funcstring=="ln" or funcstring=="Ln": debug(3,recursions*" "+origin+" becomes Natlogarithm: "+insidebrackets ) return Entities.natlogarithm([TextToCAS(insidebrackets,recursions+1)]) elif funcstring=="log" or funcstring=="Log": debug(3,recursions*" "+origin+" becomes comlogarithm: "+insidebrackets ) return Entities.comlogarithm([TextToCAS(insidebrackets,recursions+1)]) elif funcstring=="sqrt": debug(3,recursions*" "+origin+" becomes squareroot: "+insidebrackets ) return Entities.squareroot([TextToCAS(insidebrackets,recursions+1)]) else: debug(3,recursions*" "+origin+" becomes unknownfunction: "+funcstring+"("+insidebrackets+")" ) return Entities.unknownfunction(funcstring,[TextToCAS(insidebrackets,recursions+1)]) else: argstrings=splitstringbyindexes(insidebrackets,commaindexes) debug(3,recursions*" "+origin+" becomes an unknownfunction: "+funcstring+"("+insidebrackets+")") return Entities.unknownfunction(funcstring,[TextToCAS(n) for n in argstrings]) if "+" in instring or "*" in instring or "/" in instring or "(" in instring or ")" in instring: #print("OIOI",instring,ydersteparentes(stringtoparentespar(instring))[0]) if instring[0]=="-" and ydersteparentes(stringtoparentespar(instring))[0]==1 and ydersteparentes(stringtoparentespar(instring))[1]==len(instring)-1: return Entities.product([Entities.number(["-1"]),TextToCAS(instring[1:])]) debug(1,"FEJL: TextToCAS vil lave number instance med regnetegn i udtrykket\nStopper programmet") exit() #til sidst laves number instance if instring[0]=="-": debug(3,recursions*" "+origin+" becomes PRODUKT ['-1',"+instring[1:]+"]") debug(3,(recursions+1)*" "+"-1"+" er et \"noegent\" tal") return Entities.product([Entities.number(["-1"]),TextToCAS(instring[1:],recursions+1)]) else: debug(3,recursions*" "+origin+" er et \"noegent\" tal") return Entities.number([instring])
def solveaddition(self,solveside,constantside,solvenum): """ The solving method if the solveside is an instance of addition will try to put terms on the constantside such that there's only one term with solvenum in it. If that fails, it will try to solve it as a polynomial (but that function is not finished) """ newaddends=[] newconstandsideaddends=[constantside] for addend in solveside.addends: if addend.contains(solvenum.num): newaddends.append(addend) else: newconstandsideaddends.append(ent.product([ent.number(["-1"]),addend])) returnsolveside=ent.maybeclass(newaddends,ent.addition) returnconstantside=ent.maybeclass(newconstandsideaddends,ent.addition) if len(newaddends)!=1: degrees=False ispol=True poladdends=[[ent.product([ent.number(["-1"]),returnconstantside]).simplify(solvenum),0]]# [coeff,potens] subvalue=False #the part that contains x for addend in newaddends: coeffadd=False if addend.type()=="product": for index,fact in enumerate(addend.factors): if fact.contains(solvenum.num): if coeffadd==False: if fact.type()=="potens": if fact.exponent.evaluable(True) and eval(fact.exponent.tostring().replace("^","**"))%1==0 and (subvalue==False or fact.root==subvalue) and coeffadd==False: subvalue=fact.root coeffadd=[addend.delfactor(index),int(eval(fact.exponent.tostring().replace("^","**")))] else: ispol=False break elif fact.type()=="product": #damned negative number if fact.factors[1].type()=="potens": exponent=fact.factors[1].exponent if exponent.evaluable(True) and eval(exponent.tostring().replace("^","**"))%1==0 and (subvalue==False or fact1.factors[1].root==subvalue) and coeffadd==False: subvalue=fact.factors[1].root coeffadd=[ent.product([ent.number(["-1"]),addend.delfactor(index)]),int(eval(exponent.tostring().replace("^","**")))] else: ispol=False break else: thisval=fact.factors[1] if coeffadd==False and (subvalue==False or thisval==subvalue): subvalue=thisval coeffadd[ent.product([ent.number(["-1"]),addend.delfactor(index)]),1] else: ispol=False break else: if coeffadd==False and (subvalue==False or subvalue==fact): subvalue=fact coeffadd=[addend.delfactor(index),1] else: ispol=False break else: ispol=False break elif addend.type()=="potens": if coeffadd==False and (addend.exponent.evaluable(True) and eval(addend.exponent.tostring().replace("^","**"))%1==0 and (subvalue==False or addend.root==subvalue)): subvalue=addend.root coeffadd=[ent.number(["1"]),int(eval(addend.exponent.tostring().replace("^","**")))] else: ispol=False break else: if coeffadd==False and (subvalue==False or addend==subvalue): subvalue=addend coeffadd=[ent.number(["1"]),1] else: ispol=False break if coeffadd!=False: poladdends.append(coeffadd) if subvalue==False or not ispol: return None polsolveresult=self.polsolve(poladdends) retvar=[] for solution in polsolveresult: retvar.append([subvalue,solution]) return retvar return [[returnsolveside,returnconstantside]]