stein-jmm2012-Solving_Cubics

145 days ago by WilliamStein

 

olving Cubic Equations (JMM 2012 Short Course)
William Stein

 

 

 

Solving Cubic Equations (JMM 2012 Short Course)

William Stein

This worksheet accompanies these slides.

 
       
 
       

Pythagorean triples

@interact def _(t=(1/4,(1/16,1/8,..,1))): t0 = t x,y,t=var('x,y,t') show([x==(1-t^2)/(1+t^2), y==2*t/(1+t^2)]) t = t0 (x,y) = ((1-t^2)/(1+t^2), 2*t/(1+t^2)) a = 1/3 G = circle((0,0), 1, color='blue', thickness=3) G += arrow((-1-a,-t*a), (x+a,y+t*a), head=2, color='red') G += point((0,t), pointsize=150, color='black', zorder=100) G += point((-1,0), pointsize=150, color='black', zorder=100) G += point((x,y), pointsize=190, color='lightgreen', zorder=100) G += text("$(0, %s)$"%t, (-.3, t+.2), fontsize=16, color='black') G += text(r"$(%s,\,%s)$"%(x,y), (x+.35, y+.25), fontsize=16, color='black') G.show(aspect_ratio=1, ymin=-1.1, ymax=1.1, xmax=1.3, xmin=-1.3, fontsize=0, figsize=6) 
       

Click to the left again to hide and once more to show the dynamic interactive window

 
       

Cubic equations

var('x,y') implicit_plot(x^3 + y^3 == 1, (x,-2,2), (y,-2,2), aspect_ratio=1, figsize=5, gridlines=True) 
       
var('x,y') implicit_plot(y^2 + y == x^3 - x, (x,-2,3), (y,-4.5,4), aspect_ratio=1/2, figsize=5, gridlines=True) 
       
@interact def _(equation='x^3 + y^3 == 1', xmin=-2, xmax=2, ymin=-2, ymax=2, aspect_ratio=1, gridlines=True): x,y = var('x,y') eqn = sage_eval(equation, {'x':x, 'y':y}) print eqn G = implicit_plot(eqn, (x,xmin,xmax), (y,ymin,ymax), aspect_ratio=aspect_ratio, gridlines=gridlines) G.show(figsize=4) 
       

Click to the left again to hide and once more to show the dynamic interactive window

 
       

The Group Law

How the figure in the slide was made:

E = EllipticCurve([0,0,1,-1,0]); print E G = E.plot(plot_points=600, thickness=2) G += arrow((-2,1), (3,-4), head=2, color='red', width=2) G += points([(-1,0), (0,-1), (2,-3)], color='black', pointsize=70, zorder=50) G += text("$(2,-3)$", (1.3,-3.1), fontsize=18, color='black') G += text("$(-1,0)$", (-.9,1), fontsize=18, color='black') G += text("$(0,-1)$", (-.7,-1.85), fontsize=18, color='black') G.show(gridlines=True, frame=True, aspect_ratio=1/2, xmax=3.1, xmin=-2, figsize=5) 
       
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
E = EllipticCurve([0,0,1,-1,0]) P = E([-1,0]); Q = E([0,-1]); R = E([2,-3]) print P + Q + R print -(P+Q) print 7*P 
       
(0 : 1 : 0)
(2 : -3 : 1)
(1849037896/6941055969 : -260151768440137/578280195945297 : 1)
(0 : 1 : 0)
(2 : -3 : 1)
(1849037896/6941055969 : -260151768440137/578280195945297 : 1)
for n in range(10): print n, n*P 
       
0 (0 : 1 : 0)
1 (-1 : 0 : 1)
2 (6 : -15 : 1)
3 (-20/49 : 92/343 : 1)
4 (1357/841 : -53277/24389 : 1)
5 (8385/98596 : -2882165/30959144 : 1)
6 (12551561/13608721 : -41922509264/50202571769 : 1)
7 (1849037896/6941055969 : -260151768440137/578280195945297 : 1)
8 (4881674119706/5677664356225 :
-4590618167456560854/13528653463047586625 : 1)
9 (2786836257692691/16063784753682169 :
-1600059682932627475385835/2035972062206737347698803 : 1)
0 (0 : 1 : 0)
1 (-1 : 0 : 1)
2 (6 : -15 : 1)
3 (-20/49 : 92/343 : 1)
4 (1357/841 : -53277/24389 : 1)
5 (8385/98596 : -2882165/30959144 : 1)
6 (12551561/13608721 : -41922509264/50202571769 : 1)
7 (1849037896/6941055969 : -260151768440137/578280195945297 : 1)
8 (4881674119706/5677664356225 : -4590618167456560854/13528653463047586625 : 1)
9 (2786836257692691/16063784753682169 : -1600059682932627475385835/2035972062206737347698803 : 1)
 
       

The Rank

E = EllipticCurve([0,0,1,-1,0]) E.rank() 
       
1
1
E.rank? 
       

File: /home/wstein/sage/sage-4.8.alpha5/local/lib/python2.6/site-packages/sage/schemes/elliptic_curves/ell_rational_field.py

Type: <type ‘instancemethod’>

Definition: E.rank(use_database=False, verbose=False, only_use_mwrank=True, algorithm=’mwrank_lib’, proof=None)

Docstring:

Return the rank of this elliptic curve, assuming no conjectures.

If we fail to provably compute the rank, raises a RuntimeError exception.

INPUT:

  • use_database (bool) - (default: False), if True, try to look up the regulator in the Cremona database.
  • verbose - (default: None), if specified changes the verbosity of mwrank computations. algorithm -
  • - 'mwrank_shell' - call mwrank shell command
  • - 'mwrank_lib' - call mwrank c library
  • only_use_mwrank - (default: True) if False try using analytic rank methods first.
  • proof - bool or None (default: None, see proof.elliptic_curve or sage.structure.proof). Note that results obtained from databases are considered proof = True

OUTPUT:

  • rank (int) - the rank of the elliptic curve.

IMPLEMENTATION: Uses L-functions, mwrank, and databases.

EXAMPLES:

sage: EllipticCurve('11a').rank()
0
sage: EllipticCurve('37a').rank()
1
sage: EllipticCurve('389a').rank()
2
sage: EllipticCurve('5077a').rank()
3
sage: EllipticCurve([1, -1, 0, -79, 289]).rank()   # This will use the default proof behavior of True
4
sage: EllipticCurve([0, 0, 1, -79, 342]).rank(proof=False)
5
sage: EllipticCurve([0, 0, 1, -79, 342]).simon_two_descent()[0]
5

Examples with denominators in defining equations:

sage: E = EllipticCurve([0, 0, 0, 0, -675/4])
sage: E.rank()
0
sage: E = EllipticCurve([0, 0, 1/2, 0, -1/5])
sage: E.rank()
1
sage: E.minimal_model().rank()
1

A large example where mwrank doesn’t determine the result with certainty:

sage: EllipticCurve([1,0,0,0,37455]).rank(proof=False)
0
sage: EllipticCurve([1,0,0,0,37455]).rank(proof=True)
Traceback (click to the left of this block for traceback)
...
                                
                            

File: /home/wstein/sage/sage-4.8.alpha5/local/lib/python2.6/site-packages/sage/schemes/elliptic_curves/ell_rational_field.py

Type: <type ‘instancemethod’>

Definition: E.rank(use_database=False, verbose=False, only_use_mwrank=True, algorithm=’mwrank_lib’, proof=None)

Docstring:

Return the rank of this elliptic curve, assuming no conjectures.

If we fail to provably compute the rank, raises a RuntimeError exception.

INPUT:

  • use_database (bool) - (default: False), if True, try to look up the regulator in the Cremona database.
  • verbose - (default: None), if specified changes the verbosity of mwrank computations. algorithm -
  • - 'mwrank_shell' - call mwrank shell command
  • - 'mwrank_lib' - call mwrank c library
  • only_use_mwrank - (default: True) if False try using analytic rank methods first.
  • proof - bool or None (default: None, see proof.elliptic_curve or sage.structure.proof). Note that results obtained from databases are considered proof = True

OUTPUT:

  • rank (int) - the rank of the elliptic curve.

IMPLEMENTATION: Uses L-functions, mwrank, and databases.

EXAMPLES:

sage: EllipticCurve('11a').rank()
0
sage: EllipticCurve('37a').rank()
1
sage: EllipticCurve('389a').rank()
2
sage: EllipticCurve('5077a').rank()
3
sage: EllipticCurve([1, -1, 0, -79, 289]).rank()   # This will use the default proof behavior of True
4
sage: EllipticCurve([0, 0, 1, -79, 342]).rank(proof=False)
5
sage: EllipticCurve([0, 0, 1, -79, 342]).simon_two_descent()[0]
5

Examples with denominators in defining equations:

sage: E = EllipticCurve([0, 0, 0, 0, -675/4])
sage: E.rank()
0
sage: E = EllipticCurve([0, 0, 1/2, 0, -1/5])
sage: E.rank()
1
sage: E.minimal_model().rank()
1

A large example where mwrank doesn’t determine the result with certainty:

sage: EllipticCurve([1,0,0,0,37455]).rank(proof=False)
0
sage: EllipticCurve([1,0,0,0,37455]).rank(proof=True)
Traceback (most recent call last):
...
RuntimeError: Rank not provably correct.

Try a random curve (if you try a different one it could take a long time -- press "escape" with the cursor in the box to interrupt):

E = EllipticCurve([2012,3]) print E.rank() print E.gens() 
       
1
[(7753/19044 : 75356155/2628072 : 1)]
1
[(7753/19044 : 75356155/2628072 : 1)]

A family

def F(a): return EllipticCurve([0,(a-1),1,-a,0]) for a in [0..20]: print a, F(a).rank() 
       
0 0
1 1
2 2
3 2
4 3
5 2
6 2
7 3
8 3
9 3
10 2
11 3
12 3
13 3
14 3
15 2
16 4
17 3
18 2
19 3
20 3
0 0
1 1
2 2
3 2
4 3
5 2
6 2
7 3
8 3
9 3
10 2
11 3
12 3
13 3
14 3
15 2
16 4
17 3
18 2
19 3
20 3

Exercise: Find the first a such that F(a) has rank 5.  Rank 6.

 
       
 
       

Elkies Curve of Rank (at least) 28

E = EllipticCurve([1,-1,1,-20067762415575526585033208209338542750930230312178956502, 34481611795030556467032985690390720374855944359319180361266008296291939448732243429]) 
       

That the first few good a_p=p+1-\#E(F_p) are negative is evidence that E has high rank:

D = E.discriminant(); [p for p in primes(1000) if D%p==0] 
       
[2, 3, 5, 7, 11, 13, 17, 19]
[2, 3, 5, 7, 11, 13, 17, 19]
for p in primes(20,200): print E.ap(p), 
       
-9 -10 -8 -11 -10 -12 -12 -9 -12 -15 -16 -16 -15 -13 -18 -16 -13 -6 -20
-12 -20 -19 -11 -16 -10 -22 -17 -9 -24 -12 -23 -22 -7 -10 -7 -22 -22 -25
-9 -10 -8 -11 -10 -12 -12 -9 -12 -15 -16 -16 -15 -13 -18 -16 -13 -6 -20 -12 -20 -19 -11 -16 -10 -22 -17 -9 -24 -12 -23 -22 -7 -10 -7 -22 -22 -25

Exercise: What is the smallest good prime p such that a_p>0?

P = [E([-2124150091254381073292137463, 259854492051899599030515511070780628911531]), E([2334509866034701756884754537, 18872004195494469180868316552803627931531]), E([-1671736054062369063879038663, 251709377261144287808506947241319126049131]), E([2139130260139156666492982137, 36639509171439729202421459692941297527531]), E([1534706764467120723885477337, 85429585346017694289021032862781072799531]), E([-2731079487875677033341575063, 262521815484332191641284072623902143387531]), E([2775726266844571649705458537, 12845755474014060248869487699082640369931]), E([1494385729327188957541833817, 88486605527733405986116494514049233411451]), E([1868438228620887358509065257, 59237403214437708712725140393059358589131]), E([2008945108825743774866542537, 47690677880125552882151750781541424711531]), E([2348360540918025169651632937, 17492930006200557857340332476448804363531]), E([-1472084007090481174470008663, 246643450653503714199947441549759798469131]), E([2924128607708061213363288937, 28350264431488878501488356474767375899531]), E([5374993891066061893293934537, 286188908427263386451175031916479893731531]), E([1709690768233354523334008557, 71898834974686089466159700529215980921631]), E([2450954011353593144072595187, 4445228173532634357049262550610714736531]), E([2969254709273559167464674937, 32766893075366270801333682543160469687531]), E([2711914934941692601332882937, 2068436612778381698650413981506590613531]), E([20078586077996854528778328937, 2779608541137806604656051725624624030091531]), E([2158082450240734774317810697, 34994373401964026809969662241800901254731]), E([2004645458247059022403224937, 48049329780704645522439866999888475467531]), E([2975749450947996264947091337, 33398989826075322320208934410104857869131]), E([-2102490467686285150147347863, 259576391459875789571677393171687203227531]), E([311583179915063034902194537, 168104385229980603540109472915660153473931]), E([2773931008341865231443771817, 12632162834649921002414116273769275813451]), E([2156581188143768409363461387, 35125092964022908897004150516375178087331]), E([3866330499872412508815659137, 121197755655944226293036926715025847322531]), E([2230868289773576023778678737, 28558760030597485663387020600768640028531])] 
       
P[0] + P[1] 
       
(3108017602820373171270912268547263377137814553518653/114651172764479849\
0358769 :
180255809065592657084558925414149675357657278492965377853843866121745650\
1493/1227630733053376047702643420235410103 : 1)
(3108017602820373171270912268547263377137814553518653/1146511727644798490358769 : 1802558090655926570845589254141496753576572784929653778538438661217456501493/1227630733053376047702643420235410103 : 1)
time E.regulator_of_points(P[:7]) 
       
3.04313979267944e11
Time: CPU 3.18 s, Wall: 3.18 s
3.04313979267944e11
Time: CPU 3.18 s, Wall: 3.18 s
time E.regulator_of_points(P[:15]) 
       
1.97964758730350e23
Time: CPU 15.72 s, Wall: 15.71 s
1.97964758730350e23
Time: CPU 15.72 s, Wall: 15.71 s

The following takes about 60 seconds (on my laptop), and shows that the 28 points are independent:

time E.regulator_of_points(P) 
       
Traceback (click to the left of this block for traceback)
...
__SAGE__
^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "_sage_input_38.py", line 10, in <module>
    exec compile(u'open("___code___.py","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("dGltZSBFLnJlZ3VsYXRvcl9vZl9wb2ludHMoUCk="),globals())+"\\n"); execfile(os.path.abspath("___code___.py"))
  File "", line 1, in <module>
    
  File "/tmp/tmpUqfU0_/___code___.py", line 2, in <module>
    exec compile(u'__time__=misc.cputime(); __wall__=misc.walltime(); E.regulator_of_points(P); print "Time: CPU %.2f s, Wall: %.2f s"%(misc.cputime(__time__), misc.walltime(__wall__))
  File "", line 1, in <module>
    
  File "/home/wstein/sage/install/sage-4.8.alpha5/local/lib/python2.6/site-packages/sage/schemes/elliptic_curves/ell_number_field.py", line 465, in regulator_of_points
    mat = self.height_pairing_matrix(points=points, precision=precision)
  File "/home/wstein/sage/install/sage-4.8.alpha5/local/lib/python2.6/site-packages/sage/schemes/elliptic_curves/ell_number_field.py", line 363, in height_pairing_matrix
    mat[j,k]=((points[j]+points[k]).height(precision=precision) - mat[j,j] - mat[k,k])/2
  File "/home/wstein/sage/install/sage-4.8.alpha5/local/lib/python2.6/site-packages/sage/schemes/elliptic_curves/ell_point.py", line 2496, in height
    if self.has_finite_order():
  File "/home/wstein/sage/install/sage-4.8.alpha5/local/lib/python2.6/site-packages/sage/schemes/elliptic_curves/ell_point.py", line 2104, in has_finite_order
    return self.order() != oo
  File "/home/wstein/sage/install/sage-4.8.alpha5/local/lib/python2.6/site-packages/sage/schemes/elliptic_curves/ell_point.py", line 2056, in order
    n = int(E.pari_curve().ellorder(self))
  File "gen.pyx", line 6353, in sage.libs.pari.gen.gen.ellorder (sage/libs/pari/gen.c:24847)
KeyboardInterrupt
__SAGE__
points([(x,y) for x,y,_ in P]) + plot(E, color='grey', xmax=2e28, ymin=-50) 
       
 
       
 
       

Primes

prime_range(50) 
       
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
primes(50) 
       
<generator object primes at 0x5c53d20>
<generator object primes at 0x5c53d20>
for p in primes(50): print p, 
       
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
@interact def _(n=(20,30,..,2000)): prime_pi.plot(0, n).show(figsize=[12,3],gridlines=True) 
       

Click to the left again to hide and once more to show the dynamic interactive window

time p = 2^43112609 - 1 
       
Time: CPU 0.00 s, Wall: 0.01 s
Time: CPU 0.00 s, Wall: 0.01 s

It takes a while to compute the string representation of p.

time s_bigp = str(2^43112609 - 1) len(s_bigp) 
       
Time: CPU 14.81 s, Wall: 15.02 s
12978189
Time: CPU 14.81 s, Wall: 15.02 s
12978189
@interact def _(digits = (5,20,..,10000)): print "Showing %.5f percent of the digits"%(100*2.0*digits/len(s_bigp)) print "p = " + s_bigp[:digits] + ' ... ' + s_bigp[-digits:] 
       

Click to the left again to hide and once more to show the dynamic interactive window

 
       
E = EllipticCurve([0,0,1,-1,0]); E 
       
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
E23 = E.change_ring(GF(23)); E23 
       
Elliptic Curve defined by y^2 + y = x^3 + 22*x over Finite Field of size
23
Elliptic Curve defined by y^2 + y = x^3 + 22*x over Finite Field of size 23
E23.plot(pointsize=50, figsize=4, gridlines=True) 
       

Exercise: Make an interact that has a slider letting you select a prime, which plots the graph of E modulo that prime.

 
       
 
       

The L-Series

E = EllipticCurve([0,0,1,-1,0]) L = E.lseries(); L 
       
Complex L-series of the Elliptic Curve defined by y^2 + y = x^3 - x over
Rational Field
Complex L-series of the Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
show(line([(x,L(x)) for x in [1.5,1.6, .., 8]]), figsize=[8,3], xmin=0, ymin=0) 
       
@interact def _(E = ['y^2 + y = x^3 - x^2', 'y^2 + y = x^3 - x', 'a rank 4 curve', 'elkies rank>=28 curve', '2012'], B = (30..1000)): if E == 'y^2 + y = x^3 - x^2': E = EllipticCurve([0,-1,1,0,0]) r = E.rank() elif E == 'y^2 + y = x^3 - x': E = EllipticCurve([0,0,1,-1,0]) r = E.rank() elif E == 'a rank 4 curve': E = EllipticCurve([1, -1, 0, -79, 289]) r = 4 elif E == 'elkies rank>=28 curve': E = EllipticCurve([1,-1,1, -20067762415575526585033208209338542750930230312178956502, 34481611795030556467032985690390720374855944359319180361266008296291939448732243429]) r = ">=28" elif E == '2012': E = EllipticCurve([0,2012]) r = "?" L_approx = 1 print '%4s%6s%5s%9s%20s'%('p', 'A(p)', 'p/Ap', ' prod p/Ap', 'Rank = %s'%r) v = [] t = '' for p in primes(B): if E.discriminant()%p: Ap = p+1-E.ap(p) L_approx *= float(p/Ap) t += '%4s%4s%8.3f%8.3f\n'%(p, Ap, float(p/Ap), L_approx) v.append((p, L_approx)) (line(v) + points(v,color='black')).show(figsize=[8,2]) print t 
       

Click to the left again to hide and once more to show the dynamic interactive window

 
       
 
       

Natural (analytic) continuation

var('x') f = 1/(1-x) plot(f, -6, 2, figsize=[4,2], ymax=5, ymin=-5) 
       
f.taylor(x,0,5) 
       
x^5 + x^4 + x^3 + x^2 + x + 1
x^5 + x^4 + x^3 + x^2 + x + 1
 
       
 
       

The Birch and Swinnerton-Dyer Conjecture:

A Rank 1 Curve

E = EllipticCurve([0,0,1,-1,0]) L = E.lseries() Lser = L.taylor_series(); Lser 
       
0.305999773834052*z + 0.186547797268162*z^2 - 0.136791463097188*z^3 +
0.0161066468496401*z^4 + 0.0185955175398802*z^5 + O(z^6)
0.305999773834052*z + 0.186547797268162*z^2 - 0.136791463097188*z^3 + 0.0161066468496401*z^4 + 0.0185955175398802*z^5 + O(z^6)
c = Lser[1]; c 
       
0.305999773834052
0.305999773834052
Omega_E = E.period_lattice().omega(); Omega_E 
       
5.98691729246392
5.98691729246392
Reg_E = E.regulator(); Reg_E 
       
0.0511114082399688
0.0511114082399688
# this *uses* the formula; but we do know in this case that Sha_E=1. Sha_E = E.sha().an(); Sha_E 
       
1
1
prod_cp = E.tamagawa_product_bsd(); prod_cp 
       
1
1
T = E.torsion_order()^2; T 
       
1
1
Omega_E * Reg_E * Sha_E * prod_cp / T^2 
       
0.305999773834052
0.305999773834052
 
       
 
       

A Rank 2 Curve

E = EllipticCurve([0,1,1,-2,0]) L = E.lseries() Lser = L.taylor_series(); Lser 
       
-2.69129566562797e-23 + (1.52514901968783e-23)*z + 0.759316500288427*z^2
- 0.430302337583362*z^3 - 0.193509313829981*z^4 + 0.459971558373642*z^5
+ O(z^6)
-2.69129566562797e-23 + (1.52514901968783e-23)*z + 0.759316500288427*z^2 - 0.430302337583362*z^3 - 0.193509313829981*z^4 + 0.459971558373642*z^5 + O(z^6)
E.rank() 
       
2
2

If you solve for the order of the Shafarevich-Tate group in the conjecture:

E.sha().an() 
       
1.00000000000000
1.00000000000000
S = E.sha(); S 
       
Tate-Shafarevich group for the Elliptic Curve defined by y^2 + y = x^3 +
x^2 - 2*x over Rational Field
Tate-Shafarevich group for the Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field

The following proves that p=5, 7 do not divide the order of this group:

S.p_primary_bound(5) 
       
0
0
S.p_primary_bound(7) 
       
0
0
 
       

Open Problem: Prove that the Shafarevich-Tate group of E is finite.

 
       

A Rank 4 Curve

E = EllipticCurve([0,15,1,-16,0]); E 
       
Elliptic Curve defined by y^2 + y = x^3 + 15*x^2 - 16*x over Rational
Field
Elliptic Curve defined by y^2 + y = x^3 + 15*x^2 - 16*x over Rational Field
E.rank() 
       
4
4
E.gens() 
       
[(-15 : 15 : 1), (-14 : 20 : 1), (-51/4 : 187/8 : 1), (22 : 132 : 1)]
[(-15 : 15 : 1), (-14 : 20 : 1), (-51/4 : 187/8 : 1), (22 : 132 : 1)]
L = E.lseries() Lser = L.taylor_series(); Lser 
       
4.32638791417839e-24 + (-1.96674959799307e-23)*z +
(2.05660099586894e-22)*z^2 + (-7.97704812013524e-22)*z^3 +
10.8463853245874*z^4 - 49.3070071384507*z^5 + O(z^6)
4.32638791417839e-24 + (-1.96674959799307e-23)*z + (2.05660099586894e-22)*z^2 + (-7.97704812013524e-22)*z^3 + 10.8463853245874*z^4 - 49.3070071384507*z^5 + O(z^6)
 
       

Open Problem:  Prove that L(E,s) vanishes to order 4 at s=1