You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

273 lines
8.2 KiB

  1. class Unique(object):
  2. def __init__(self,name):
  3. self.name = name
  4. def __str__(self):
  5. return self.name
  6. def __repr__(self):
  7. return "Unique(\"%s\")" % self.name
  8. class Idealized(object):
  9. UNION = ["UNION"]
  10. def __init__(self, R, idealMap = 0, vars = {}):
  11. self.varnames = vars
  12. if not isinstance(idealMap,dict):
  13. idealMap = {()*R:idealMap}
  14. self.idealMap = idealMap
  15. self.R = R
  16. self._sqrt = None
  17. self._isqrt = None
  18. @staticmethod
  19. def uvar(x):
  20. return Idealized.var(Unique(x))
  21. @staticmethod
  22. def var(x):
  23. name = str(x)
  24. R = PolynomialRing(QQ,[name])
  25. rx = R.gens()[0]
  26. return Idealized(R,rx,{x:(name,rx)})
  27. @staticmethod
  28. def vars(xs):
  29. return tuple((Idealized.var(x) for x in xs))
  30. @staticmethod
  31. def uvars(xs):
  32. return tuple((Idealized.uvar(x) for x in xs))
  33. def __str__(self):
  34. def rep(I,x):
  35. x = str(x)
  36. gs = I.gens()
  37. gs = [g for g in gs if g != 0]
  38. if len(gs) == 0: return x
  39. else:
  40. g = ", ".join(["(%s)" % str(gen) for gen in gs])
  41. return g + ": " + x
  42. return "\n".join([rep(I,self.idealMap[I]) for I in self.idealMap])
  43. def __repr__(self):
  44. # HACK!
  45. if len(self.idealMap) == 0:
  46. return "undef"
  47. if len(self.idealMap) > 1:
  48. return str(self)
  49. for _,v in self.idealMap.iteritems():
  50. return str(v)
  51. def prune(self):
  52. self.idealMap = {I:v for I,v in self.idealMap.iteritems() if not (I*self.R).is_one()}
  53. return self
  54. def __add__(self,other):
  55. def f(x,y): return x+y
  56. return self.op(other,f)
  57. def __radd__(self,other):
  58. def f(x,y): return y+x
  59. return self.op(other,f)
  60. def __rsub__(self,other):
  61. def f(x,y): return y-x
  62. return self.op(other,f)
  63. def __neg__(self):
  64. def f(x,y): return y-x
  65. return self.op(0,f)
  66. def __sub__(self,other):
  67. def f(x,y): return x-y
  68. return self.op(other,f)
  69. def is_square(self):
  70. for _,v in self.idealMap.iteritems():
  71. if not is_square(v): return False
  72. return True
  73. def sqrt(self):
  74. if self._sqrt is None:
  75. s = Idealized.uvar("s")
  76. self._sqrt = s.assuming(s^2 - self)
  77. return self._sqrt
  78. def isqrt(self):
  79. if self._isqrt is None:
  80. s = Idealized.uvar("s")
  81. z = Idealized(0).assuming(Self)
  82. self._isqrt = s.assuming(s^2*self-1).union(z)
  83. return self._isqrt
  84. def __mul__(self,other):
  85. def f(x,y): return x*y
  86. return self.op(other,f)
  87. def __rmul__(self,other):
  88. def f(x,y): return y*x
  89. return self.op(other,f)
  90. def __pow__(self,n):
  91. if n < 0: return 1/self^(-n)
  92. if n == 0: return 1
  93. if n == 1: return self
  94. if is_even(n): return (self*self)^(n//2)
  95. if is_odd(n): return (self*self)^(n//2) * self
  96. def __div__(self,other):
  97. def f(x,y): return x/y
  98. return self.op(other,f)
  99. def __rdiv__(self,other):
  100. def f(x,y): return y/x
  101. return self.op(other,f)
  102. def union(self,other):
  103. return self.op(other,Idealized.UNION)
  104. def __eq__(self,other):
  105. return (self - other).is_zero()
  106. def __ne__(self,other):
  107. return not (self==other)
  108. def __hash__(self):
  109. return 0
  110. def assume_zero(self):
  111. out = {}
  112. for I,J in self.idealMap.iteritems():
  113. IJ = I+J.numerator()
  114. if IJ.is_one(): continue
  115. out[IJ] = self.R(0)
  116. if len(out) == 0:
  117. raise Exception("Inconsistent assumption")
  118. return Idealized(self.R,out,self.varnames)
  119. def assuming(self,other):
  120. return self + other.assume_zero()
  121. def is_zero(self):
  122. for I,v in self.idealMap.iteritems():
  123. if v.denominator() in I: return False
  124. if v.numerator() not in I: return False
  125. return True
  126. def op(self,other,f):
  127. if not isinstance(other,Idealized):
  128. other = Idealized(self.R,other,self.varnames)
  129. bad = False
  130. for v in self.varnames:
  131. if v not in other.varnames or self.varnames[v] != other.varnames[v]:
  132. bad = True
  133. break
  134. for v in other.varnames:
  135. if v not in self.varnames or self.varnames[v] != other.varnames[v]:
  136. bad = True
  137. break
  138. if bad:
  139. def incrVar(v):
  140. if v[-1] not in "0123456789": return v + "1"
  141. elif v[-1] == 9: return incrVar(v[:-1]) + "0"
  142. else: return v[:-1] + str(int(v[-1])+1)
  143. vars = {}
  144. names = set()
  145. for v,(name,_) in self.varnames.iteritems():
  146. assert(name not in names)
  147. names.add(name)
  148. vars[v] = name
  149. subMe = {n:n for n in names}
  150. subThem = {}
  151. for v,(name,_) in other.varnames.iteritems():
  152. if v in self.varnames:
  153. subThem[name] = self.varnames[v][0]
  154. else:
  155. oname = name
  156. while name in names:
  157. name = incrVar(name)
  158. names.add(name)
  159. subThem[oname] = name
  160. vars[v] = name
  161. R = PolynomialRing(QQ,sorted(list(names)),order="degrevlex")
  162. gd = R.gens_dict()
  163. subMe = {m:gd[n] for m,n in subMe.iteritems()}
  164. subThem = {m:gd[n] for m,n in subThem.iteritems()}
  165. vars = {v:(n,gd[n]) for v,n in vars.iteritems()}
  166. def subIdeal(I,sub):
  167. return [g(**sub) for g in I.gens()]*R
  168. idealMe = {subIdeal(I,subMe):v(**subMe) for I,v in self.idealMap.iteritems()}
  169. idealThem = {subIdeal(I,subThem):v(**subThem) for I,v in other.idealMap.iteritems()}
  170. else:
  171. R = self.R
  172. idealMe = self.idealMap
  173. idealThem = other.idealMap
  174. vars = self.varnames
  175. def consist(I,x,y):
  176. if (x-y).numerator() not in I:
  177. raise Exception("Inconsistent: %s != %s in ideal %s" %
  178. (str(x),str(y),str(I)))
  179. out = {}
  180. if f is Idealized.UNION:
  181. for I,v in idealMe.iteritems():
  182. if I in idealThem:
  183. consist(I,v,idealThem[I])
  184. out[I] = v
  185. for I,v in idealThem.iteritems():
  186. if I in idealMe:
  187. consist(I,v,idealMe[I])
  188. out[I] = v
  189. else:
  190. for I,v in idealMe.iteritems():
  191. if I in idealThem:
  192. x = f(v,idealThem[I])
  193. if I in out:
  194. consist(I,x,out[I])
  195. else: out[I] = x
  196. else:
  197. for J,w in idealThem.iteritems():
  198. IJ = I+J
  199. if not IJ.is_one():
  200. x = f(v,w)
  201. if IJ in out:
  202. consist(IJ,x,out[IJ])
  203. else:
  204. out[IJ] = x
  205. def gb(I):
  206. II = [0]*R
  207. for g in I.gens():
  208. if g not in II: II = II+[g]*R
  209. return II
  210. def red(I,v):
  211. if I.is_zero(): return v
  212. return I.reduce(R(v.numerator())) / I.reduce(R(v.denominator()))
  213. out = {gb(I):v for I,v in out.iteritems()}
  214. out = {I:red(I,v) for I,v in out.iteritems()}
  215. return Idealized(R,out,vars)
  216. def reduce(self):
  217. def red(I,v):
  218. if I.is_zero(): return v
  219. return I.reduce(R(v.numerator())) / I.reduce(R(v.denominator()))
  220. out = {I:red(I,v) for I,v in self.idealMap.iteritems()}
  221. return Idealized(self.R,out,self.vars)
  222. Idealized.INF = Idealized.uvar("inf")
  223. Idealized.ZOZ = Idealized.uvar("zoz")