File: fission.py

package info (click to toggle)
saml 970418-3
  • links: PTS
  • area: main
  • in suites: slink
  • size: 1,204 kB
  • ctags: 1,701
  • sloc: ansic: 17,182; sh: 2,583; yacc: 497; perl: 264; makefile: 250; python: 242
file content (101 lines) | stat: -rwxr-xr-x 3,503 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/usr/bin/python
#
# I really like this problem. Let K be any field containing the rationals
# and two elements a and c, and let A be the K-algebra generated by
# the X[i], where i runs over the integers, with the relations
#
#   X[i]^2 = X[i+1] - c + a.X[i-1]  for all i in Z.
#
# Clearly, any element of A can be written as a polynomial in X[i] so that
# all variables have exponents less than two -- otherwise, you could use
# the relation above to reduce the global degree. It's less easy to see that
# the reduced representation is canonic; in particular, it doesn't depend on
# the order of the reductions.
#
# For instance, you have:
#
# X[0]^2.X[1] = (X[1]-c+a.X[-1]).X[1]
#             = X[1]^2 - c.X[1] + a.X[-1].X[1]
#             = X[2] - c + a.X[0] - c.X[1] + a.X[-1].X[1]
#
# This first phase is called "melting". Now, it turns out that there is
# a linear form on A (let's call it the integral) which is particularly
# easy to describe on the reduced form. Each term is (up to a factor)
# a product of X[i] where i runs over some finite subset S of the integers.
# Then we define integral(prod X[i]) = (3.a/4)^(card(S)/2) if all the
# connected components of S have even cardinality, and 0 otherwise.
# In the above case the integral is (-c).
#
# If you want to know where all of this comes from, get the preprint at
# http://topo.math.u-psud.fr/~bousch/preprints/ called "Algebres de Henon"
# (in french). Also, have a look at the file called "fission.form" if
# you're interested in the contorsions necessary to do this in FORM.
# And if you have FORM, don't forget to do some performance comparisons.

from saml1 import *
import sys, string, regex

def extract_literals(poly, rx):
  """Extract all literals matching a certain regular expression"""
  from string import splitfields, joinfields
  prog = regex.compile(rx)
  str = repr(poly)
  found = {}
  while 1:
    position = prog.search(str)
    if position < 0:
      break
    matched = prog.match(str, position)
    lit = str[position:position+matched]
    found[lit] = 1
    # Now replace all the occurences of this literal with zeroes
    str = joinfields(splitfields(str,lit),'0')
  return found.keys()

def melt(poly):
  sys.stderr.write('Literals: ');
  candidates = extract_literals(poly, "X\\[-?[0-9]+\\]")
  sys.stderr.write(string.join(candidates,',')+'\n')
  sys.stderr.write('melting... ')
  for x in candidates:
    p = string.atoi(x[2:-1])
    X = poly.parse('X[%d]^2' % p)
    Y = poly.parse('a.X[%d]-c+X[%d]' % (p-1,p+1))
    poly = poly.subs(X,Y)
  sys.stderr.write('done\n')
  return poly

def combine(poly):
  literals = extract_literals(poly, "X\\[-?[0-9]+\\]")
  indices = map(lambda s:string.atoi(s[2:-1]), literals)
  for i in range(min(indices),max(indices)-min(indices)):
    X = poly.parse('X[%d].X[%d]' % (i,i+1))
    Y = poly.parse('3.a/4')
    poly = poly.subs(X,Y)
  for l in literals:
    poly = poly.subs(poly.parse(l), poly.zero())
  return poly

def test(expression):
  model = Mathnode(ST_RATIONAL,'0').cast(ST_APOLY)
  poly = model.parse(expression)
  while 1:
    new = melt(poly)
    if new==poly: break
    poly = new
  print 'After melting:'
  print poly
  print 'Integral:'
  poly = combine(poly)
  print poly
  print 'And when a=0 it reduces to:'
  print poly.subs(poly.parse('a'), poly.zero())

if __name__ == '__main__':
  if len(sys.argv) == 1:
    expr = '(X[-1]+X[0]+X[1])^12'
    print 'Initial expression:', expr
  else:
    expr = sys.argv[1]
  test(expr)
  print MnAllocStats()