# ResSing: Calculating regular models of curves

ResSing calculates regular models of smooth projective, geometrically irreducible curves defined over the rational numbers. We do not assume any special properties about the curves we resolve. First define a scheme by specifying equations (see below). Then, we can compute a regular model by executing:
`sage: Y = Resolve(X)  `
Now we can compute various invariants. Eg,
```sage: X.componentGroup(2)
...
[1, 3]
```
The returned answer, [1,3] specifies that the component group of the Neron model of the Jacobian is isomorphic to ℤ/3ℤ.

This software is written using the free mathematics software Sage and Macaulay2. For some applications, examples, and algorithms see below. If you are aware of other applications please send me an email.

### Input, Output, and Basic Operation

Input: Arbitrary equations defining a smooth, proper and geometrically irreducible curve over the rationals, ℚ.
Output: Equations defining a regular model of the same curve over the integers, ℤ. That is, a regular scheme \$X\$, proper and faithfully flat over ℤ with generic fiber isomorphic to the given one.

ResSing is designed to be highly multi-tasking and the user can specify it to operate differently if he/she has access to a server with e.g. 10 processors.

When you ask ResSing to compute a regular model we call a number of instances of Macaulay2 to preform various computations. All intensive computations are carried out by instances of Macaulay2. If Macaulay2 computes a groebner basis then we save those computations and pass these results to additional instances of Macaulay2.

The program is highly customizable. See the file "config.py" for various options (also documented there). By default, the program is configured for ResSing to run on a laptop.

### Applications:

1. Pic^0 & Reduction of Jacobian: We can deduce properties of \$\Pic^0\$ of a special fiber (See Chapter 9 of BLR or the document below for some examples.) Further, if the regular model satisfies certain properties then one can deduce properties about the reduction of the jacobian of the special fiber. See Chapter 9 of BLR and section 2 of Ribet's Inventiones 100 paper for details (or the document below).

2. Effective Chabauty: Given a regular model one can also calculate the Chabauty-Coleman bound, which bounds #X(ℚ), as given by [3]. This bound by E. Katz and D. Zureick-Brown also takes into account the behaviour at bad primes and give is sometimes sharp, see (Example 5.1, 3).

3. Existence of p-adic points: Given the input above, we can easily (via a straightforward computation) determine if if it has p-adic solutions for any \$p\$ at which X has good reduction. Given a regular model we can also determine if it has p-adic solutions for bad fibers. See for example (Lemma 1.1, 2)

4. Beilinson's conjecture on special values of L-functions for curves: Given an element Σ {f, g} in the kernel of the tame symbol of a curve over the rationals one can check if it satisfies the integrality condition imposed by the special fiber of a regular model. The collection of such classes is used to define the integral part of a K-group and is an ingredient to Beilinson's conjecture on special values of L-functions for curves. See Numerical verification of Beilinson's conjecture for K2 of hyperelliptic curves Tim Dokchitser, Rob de Jeu, Don Zagier, Compositio Math. 142, Issue 02 (2006) for an introduction.

Notes: The input and output are given via charts and glueing maps. One should keep the number of equations and charts small so that computations are manageable. Please email me if you find any bugs.

## Instructions:

Running the progam is fairly simple. Just edit one line and load it in sage. Here are detailed instructions.
1. Insure that you have Sage and Macaulay2 installed. Download the program above and extract it. We will extract it to "/home/user/ResSing/".
2. Open the file "main.sage" in your favorite text editor (eg, notepad.exe, emacs, vi, ... ). Update the line
PATH = "..."

to the path where you extracted the program. Hence, we declare

PATH = "/home/user/ResSing/"
This is done so the program knows where to find requisite files. Please email me if you know a way to avoid this step.
3. From sage, type
runfile "/home/user/ResSing/main.sage"
The program is now loaded. You can now define schemes and resolve singularities. Try the examples below.

## Examples

### Example 1: (A first example y^2 = x^3 + 1)

We compute various invariants attached to a regular model of the elliptic curve with affine equation y^2 = x^3 + 1. We assume that you have downloaded the program and loaded it in sage as the instructions above indicate.
1. Define the elliptic curve with affine equation y^2 = x^3 + 1
```sage: X = EC(0,1)
Elliptic Curve with defining polynomial -x^3 + y^2*z - z^3.Cremona Label = 36a1
Initializing ResolveScheme from projective variety.
Note: we assume that the given projective variety defines a 2-dimensional integral scheme faithfully flat over ZZ.
Trimmed  1  of  3  charts. Removed  0  relations from chart  U0   1  remain.
Trimmed  2  of  3  charts. Removed  0  relations from chart  U1   1  remain.
Trimmed  3  of  3  charts. Removed  0  relations from chart  U2   1  remain.
Removing redundant charts
...
Removed  1  charts, 2  charts remain!
...
done
```
2. Compute a regular model.
```sage: Y = Resolve(X)
...
-------------------------------------------
ResolveScheme and groebner bases saved to  /tmp/tmpHiWZfj/step-1.RS  load with the importRS(*) function
DONE. Updating saved groebner basis calculations ...
ResolveScheme and groebner bases saved to  /tmp/tmpHiWZfj/step-REGULAR.RS  load with the importRS(*) function
done.
Computed Groebner Bases:
-------------------------------------------
Computed  100  groebner bases  72  for Polynomial Rings and  28  for quotient rings.
Computed by:
{'rad': 16, 'linearCombination': 2, 'ringMap+simplify': 2, 'dimFiberComponent': 17, 'trimRS': 4, 'BlowUpChart': 6, 'redundantCharts': 5, 'minMapsRS': 25, 'trim-regularPoint': 4, 'nonFreeLocus': 16, 'minRingMap': 3}
Groebner bases computed over the base rings :
{2: 25, 3: 24, 'ℤ': 51}
Average number of sets of generators known (among those with more than one set known): 3.25000000000000
A total of  195  groebner bases were loaded.
-------------------------------------------
Shutting down saveGomputedGB
Saving all computed Groebner bases to  /tmp/tmpHiWZfj/step-computeGB.GB

```
```sage: Y.exportRS("/home/user/myScheme.RS")
ResolveScheme and groebner bases saved to  /home/user/myScheme.RS  load with the importRS(*) function
sage: importRS("/home/user/myScheme.RS")
...
```
All groebner bases computations are automatically also saved to/loaded from the same file.
4. Now Y is a regular model of X. Typing Y. and pressing the TAB key shows a number of things one can compute. Eg,
```sage: Y.badprimes
6
sage: Y.chabautyBound(2)
Computing non smooth locus.
Computing Nonfree locus... done.
Computing Nonfree locus... done.
Computing Nonfree locus... done.
Computing Nonfree locus... done.
Computing Nonfree locus... done.
Counting points ( total  5  charts):
. . . . .
Let J be the Jacobian of the curve X and p the given prime and g the genus.
r = rank J(ℚ)
Assume g >= 2, r < g, p > 2r + 2.
Then, X(ℚ) <=  6  + 2r
6
```
5. Compute information about a special fiber (eg, dual graph) and attempt to use Macaulay2/Singular to compute the genus of curves appearing in the fibers. The genus calculations may not always work.
```sage: Y.fiberInformation(2, attempt_genus=True)

Calculating ideal sheaves,  5  charts:
. . . . .
Number of prime components D_1, D_2, ... over the fiber at  2  :  3

Returning a list of ideal sheaves of irreducible components of the fiber with all non-reduced structure.

The fiber over  2  is (1)*D_0 + (1)*D_1 + (1)*D_2

Returning a tuple [A,B] (of ideal sheaves (with non-reduced structure) and multiplicites):

A =  ['I_{(1)*D_0}', 'I_{(1)*D_1}', 'I_{(1)*D_2}']
B =  [1, 1, 1]

Computing intersection matrix: . . .

Intersection Matrix:
[-2  1  1]
[ 1 -2  1]
[ 1  1 -2]

Genus...
Warning: genus calculation may fail.
Warning: genus calculation may fail.
Warning: genus calculation may fail.
Reduced...
Smooth...
===============Key (Vertex/Sheaf of ideals)==================
Vertex  C0
Genus of reduced normalization:  0
Reduced:  True
Multiplicity: 1
Self-intersection: -2
{'CHa2': ['a0', 'z*a1^3+z+1', '2'], 'CHa0': ['1'], 'CHa1': ['z*a2^3+a2^3+z', '2'], 'CHb1': ['z^2*a2^2+z*a2^2+z^2+z+1', '2'], 'CHb0': ['a1^3+a1*a2^2+a1^2+a2^2+a1', '2']}

Vertex  C1
Genus of reduced normalization:  0
Reduced:  True
Multiplicity: 1
Self-intersection: -2
{'CHa2': ['a1', 'z+1', '2'], 'CHa0': ['a1', '2'], 'CHa1': ['1'], 'CHb1': ['1'], 'CHb0': ['1']}

Vertex  C2
Genus of reduced normalization:  0
Reduced:  True
Multiplicity: 1
Self-intersection: -2
{'CHa2': ['a0+a1', 'z+1', '2'], 'CHa0': ['a1+1', '2'], 'CHa1': ['z+1', '2'], 'CHb1': ['1'], 'CHb0': ['1']}

===============Key (Vertex/Sheaf of ideals)==================
=============================================================
Dual graph saved to DualGraph-BESLBfiber-2.png
=============================================================
Returning elementary divisors... [1, 3]
[
[{'CHa2': ['a0', 'z*a1^3+z+1', '2'], 'CHa0': ['1'], 'CHa1': ['z*a2^3+a2^3+z', '2'], 'CHb1': ['z^2*a2^2+z*a2^2+z^2+z+1', '2'], 'CHb0': ['a1^3+a1*a2^2+a1^2+a2^2+a1', '2']}, {'CHa2': ['a1', 'z+1', '2'], 'CHa0': ['a1', '2'], 'CHa1': ['1'], 'CHb1': ['1'], 'CHb0': ['1']}, {'CHa2': ['a0+a1', 'z+1', '2'], 'CHa0': ['a1+1', '2'], 'CHa1': ['z+1', '2'], 'CHb1': ['1'], 'CHb0': ['1']}],

[-2  1  1]
[ 1 -2  1]
[1, 1, 1], [ 1  1 -2],

, [1, 3]
]

```
As the program runs it prints out various pieces of information about it's progress, and what it is currently working on.

## Example 2: (Fermat Quartic)

We examine a regular model of the Fermat Quartic.
1. Define the Fermat quartic as a proper scheme over the integers ℤ.
```
sage: X = ResolveScheme("x,y,z",['x^4 + y^4 - z^4'], message = "Fermat quartic: x^4 + y^4 - z^4")
Initializing ResolveScheme from projective variety.
Note: we assume that the given projective variety defines a 2-dimensional integral scheme faithfully flat over ℤ.
```
2. Check if it this scheme is normal or regular or regular in codimension one (R_1).
```
sage: X.isNormal()
Computing badprimes... Computing Nonfree locus... done.
done.
Computing badprimes... Computing Nonfree locus... done.
done.
Computing badprimes... Computing Nonfree locus... done.
done.
Checking if chart  U0  is normal
Checking if chart  U1  is normal
Checking if chart  U2  is normal
True
sage: X.isRegular()
Computing Nonfree locus... done.
Checking regularity...
...
False
sage: X.isR1() #This must be true since X is normal.
True
```
3. Calculate the locus of irregular points. Note this is in general different from the non-smooth locus. The former is trivial for a regular model while the latter is non-trivial for curves of genus at least one. For each chart, we have a system of generators of ideal defining the irregular locus (with the reduced induced structure). We can similarly calculate the ideal sheaf defining the non-smooth locus using the function X.nonSmoothLocus()
```
sage: X.irregLocusIdealSheaf()
{'U0': ['2', 'x1+1', 'x0'],
'U1': ['x0', '2', 'x1+1'],
'U2': ['x0*x1 + x0 + x1 + 1', 'x1^2 + x1', '2', 'x0*x1']}
```
If we wanted to compute the irregular locus only in a given open set then we can specify this via the "chart = " variable. Many functions accept this parameter.
```
sage: X.irregLocusIdealSheaf(chart = "U0")
['2', 'x1+1', 'x0']
```
4. Compute a regular model by executing
` sage: Y = Resolve(X) `
(or simply load a previously computed regular model) and print some information.
```
sage: runfile "/home/user/ResSing/main.sage"
sage: X = importRS("/home/user/ResSing/Schemes/Fermat/FermatQuartic-REGULAR.RS")
Loaded file.  Fermat curve: x^4 + y^4 = z^4 (REGULAR)

#Give names of charts
sage: X.CNames
['CHb0', 'CHb2', 'CHb3', 'CHa2']

#This function prints some information about the scheme (including information about each chart).
sage: X.information()
numcharts =  4
Names of charts =  ['CHb0', 'CHb2', 'CHb3', 'CHa2']
Names of intersections =  ['CHb3#CHa2', 'CHa2#CHb0', 'CHa2#CHb3', 'CHa2#CHb2', 'CHb2#CHb3', 'CHb2#CHb0', 'CHb3#CHb2', 'CHb2#CHa2', 'CHb0#CHb3', 'CHb0#CHb2', 'CHb3#CHb0', 'CHb0#CHa2']
...

#Print only information about the specifed chart.
sage: X.information(chart = "CHb0")
Open set  CHb0
________________________________
Coordinate ring is R = P/I with
P = ℤ[ x0,x1,a0,a1,a2,a3]
I =  [a0 - 1, x1*a3 - x1 + a1 + a3, x0*x1*a3 - x0*x1 + x0*a3 + x1*a3 + a3, x0*x1*a2 + x0*a2 + x1*a2 + a2 - 2, x0*x1*a1 - x1^2*a3 - x1*a3, x0^3*a3 + x1^3*a3 - x0^3 - x1^3 + x0^2 + x1^2 - x0 - x1 + a3 + 1, x0^2*a3^2 + x1^2*a3^2 - 2*x0^2*a3 - 2*x1^2*a3 + x0^2 + x1^2 + 2*x0*a3 + 2*x1*a3 - a3^2 - 2*x0 - 2*x1 - 2*a2 + 3, x0*a3^3 + x1*a3^3 - 3*x0*a3^2 - 3*x1*a3^2 + a3^3 + a2^2 + 3*x0*a3 + 3*x1*a3 + 2*a2*a3 + a3^2 - x0 - x1 - 3*a2 - 5*a3 + 3, 2*a3^4 - a2^3 - 2*a2^2*a3 - 4*a2*a3^2 - 8*a3^3 + 3*a2^2 + 8*a2*a3 + 12*a3^2 - 4*a2 - 8*a3 + 2, x0*x1*a0 - x0*x1 + x0*a0 + x1*a0 - x0 - x1 + a0 - 1, x0*x1*a1 - x1^2 + x0*a1 + x1*a1 - x1 + a1, x0*x1*a2 + x0*a2 + x1*a2 + a2 - 2, x0*x1*a3 - x0*x1 + x0*a3 + x1*a3 + a3, x0^4 + x1^4 - 1]

regular =  True
is_Normal =  True
is_R1 = ? True
nonNormalR1
-------
codim2_sing
-------
codim1_sing
-------
________________________________
```
5. Prove that the object X in fact defines a scheme by checking the glueing conditions (and preform other basic sanity checks). This is mostly for debugging purposes.
```sage: X.sanityCheck()
Preforming basic sanity checks. (Only errors are reported)...
Intersection of all pairs of charts known...
CNames and INames calculated correctly ...
irregLocusHints,irreg_locus calculated correctly...
Localization maps are canonical (and of the form R[z]/(zf - 1)...)
Checking R_1 property...
Calculating ideal sheaves,  4  charts:
. . . .
There are  7  components over the fiber at  2
(total  28 ):
. . . . . . . . . . . . . . . . . .
Checking if the glueing conditions are satisfied:
Checking that all maps exist as stated (total  24 ):
. . . . . . . . . . . . . . . . . . . . . . . .
Natural maps between interesections of two charts compose to the identity (total  12 ):
. . . . . . . . . . . .
Checking glueing conditions, that phi_ji(U_ji \cap U_jk) == U_ij \cap U_ik (total  24 ):
. . . . . . . . . . . . . . . . . . . . . . . .
Checking phi_ik = phi_jk \circ phi_ij as maps Uij \cap Uik ---> Uki \cap Ukj (total  24 ):
* * * * * * * * * * * * * * * * * * * * * * * *
Done.
```
6. Compute the dual graph of the fiber over 2. (Some intermediate information is printed.)
```#The only non-smooth fiber is over 2
2

sage: X.fiberInformation(2)

Calculating ideal sheaves,  4  charts:
. . . .
Number of prime components D_1, D_2, ... over the fiber at  2  :  7

Returning a list of ideal sheaves of irreducible components of the fiber with all non-reduced structure.

The fiber over  2  is (1)*D_0 + (2)*D_1 + (1)*D_2 + (2)*D_3 + (4)*D_4 + (1)*D_5 + (1)*D_6

Returning a tuple [A,B] (of ideal sheaves (with non-reduced structure) and multiplicites):

A =  ['I_{(1)*D_0}', 'I_{(2)*D_1}', 'I_{(1)*D_2}', 'I_{(2)*D_3}', 'I_{(4)*D_4}', 'I_{(1)*D_5}', 'I_{(1)*D_6}']
B =  [1, 2, 1, 2, 4, 1, 1]

Computing intersection matrix: . . . . . . . . . . . . . . . . . . . . .

Intersection Matrix:
[-3  1  0  0  0  1  0]
[ 1 -3  0  0  1  1  0]
[ 0  0 -3  1  0  0  1]
[ 0  0  1 -3  1  0  1]
[ 0  1  0  1 -1  0  0]
[ 1  1  0  0  0 -3  0]
[ 0  0  1  1  0  0 -3]

Genus...
Reduced...
Ideal sheaf over  CHb0  is different.
Ideal sheaf over  CHb0  is different.
Ideal sheaf over  CHb0  is different.
Smooth...
===============Key (Vertex/Sheaf of ideals)==================
Vertex  C0
Genus of reduced normalization:  Not Calculated
Reduced:  True
Multiplicity: 1
Self-intersection: -3
{'CHa2': ['1'], 'CHb3': ['a3+1', 'a1+1', 'a0+a2', 'x1', 'x0+1', '2'], 'CHb2': ['a2+1', 'a1+a3', 'a0+1', 'x1', 'x0+1', '2'], 'CHb0': ['a2+1', 'a1+a3', 'a0+1', 'x1', 'x0+1', '2']}

Vertex  C1
Genus of reduced normalization:  Not Calculated
Reduced:  False
Multiplicity: 2
Self-intersection: -3
{'CHa2': ['1'], 'CHb3': ['a3+1', 'x0+x1+a1', 'a2^2', 'a1*a2+a2', 'x1*a2', 'a1^2+1', 'x1*a1+x1', 'x1*a0+x1+a1+1', 'x1^2', 'a0^3*a1+a0^3+a0^2*a1+a0^2*a2+a0^2+a0*a1+a0+a1+1', '2'], 'CHb2': ['1'], 'CHb0': ['a0+1', 'x1*a3+x1+a1+a3', 'x0*a3+x1+a3', 'a2^2', 'x1*a2', 'x0*a2+a2', 'a1^2+a3^2', 'x1*a1+x1+a1+a3', 'x0*a1+x1+a1', 'x1^2', 'x0*x1+x1', 'x0^2+1', 'a1*a3^2+a3^3+a1*a3+a3^2+x0+x1+a1+a2+a3+1', 'a1*a2*a3+a2*a3^2', '2']}

Vertex  C2
Genus of reduced normalization:  Not Calculated
Reduced:  True
Multiplicity: 1
Self-intersection: -3
{'CHa2': ['a2+1', 'a1+1', 'x1+1', 'x0', '2'], 'CHb3': ['a3+1', 'a1+a2', 'a0+a2', 'x1+1', 'x0', '2'], 'CHb2': ['a2+1', 'a1+1', 'a0+1', 'x1+1', 'x0', '2'], 'CHb0': ['a2+1', 'a1+1', 'a0+1', 'x1+1', 'x0', '2']}

Vertex  C3
Genus of reduced normalization:  Not Calculated
Reduced:  False
Multiplicity: 2
Self-intersection: -3
{'CHa2': ['a2+1', 'a1^2', 'x1*a1+a1', 'x0*a1', 'x1*a0+x0+a0', 'x1^2+1', 'x0*x1+x0', 'x0^2', 'x0*a0^3+x1+a1+1', '2'], 'CHb3': ['a3+1', 'a2^2', 'a0*a2+a1*a2', 'x1*a2+a2', 'x0*a2', 'x1*a1+x1+a0+1', 'x0*a1+x1+1', 'a0^2+a1^2', 'x1*a0+x1+a1+1', 'x0*a0+x1+1', 'x1^2+1', 'x0*x1+x0', 'x0^2', 'a0*a1^2+a1^3+a1^2*a2+a0*a1+a1^2+x0+x1+a0+a1+1', '2'], 'CHb2': ['1'], 'CHb0': ['a0+1', 'x0+x1+a1', 'x1*a3+x1+a1+a3', 'a2^2', 'a1*a2+a2', 'x1*a2+a2', 'a1^2+1', 'x1*a1+x1+a1+1', 'x1^2+1', 'a1*a3^3+a1*a3^2+a3^3+a1*a3+a3^2+a1+a2+a3+1', '2']}

Vertex  C4
Genus of reduced normalization:  Not Calculated
Reduced:  False
Multiplicity: 4
Self-intersection: -1
{'CHa2': ['a2+1', 'a1', 'x1*a0+x0+a0', 'a0^4+1', 'x0*a0^3+x1+1', 'x0^2*a0^2+x1^2+1', 'x0^3*a0+x1^3+x1^2+x1+1', 'x0^4+x1^4+1', '2'], 'CHb3': ['a3+1', 'a2', 'x0*a1+x1+1', 'x1*a0+x1+a1+1', 'a0*a1^2+a1^3+x0*a0+a0*a1+a1^2+x0+a0+a1', 'a1^4+1', 'a0^3*a1+a0^3+a0^2*a1+a0^2+a0*a1+a0+a1+1', 'x1^3*a1+x0^3+x1^2*a1+x1*a1+a1', 'a0^4+1', 'x0^2*a0^2+x0^2+a0^2+a1^2', 'x0^3*a0+x0^3+x1^2*a1+x1*a1^2+x0^2+x1*a1+a0*a1', 'x0^4+x1^4+1', '2'], 'CHb2': ['1'], 'CHb0': ['a2', 'a0+1', 'x1*a3+x1+a1+a3', 'x0*a1+x1+a1', 'a1^2*a3+x0*a3^2+a1*a3^2+a1^2+a1*a3+a3^2+x0+1', 'a3^4+1', 'a1*a3^3+a1*a3^2+a3^3+a1*a3+a3^2+a1+a3+1', 'x0*a3^3+x0*a3^2+a1*a3^2+x0*a3+a3^2+x0+a1+1', 'x0^3*a3+x0^3+x1^2*a1+x0^2+x1*a1+x0+a1+1', 'x0^4+x1^4+1', '2']}

Vertex  C5
Genus of reduced normalization:  Not Calculated
Reduced:  True
Multiplicity: 1
Self-intersection: -3
{'CHa2': ['1'], 'CHb3': ['a3+1', 'a1+1', 'a0', 'x1', 'x0+1', '2'], 'CHb2': ['a2+1', 'a1+a3', 'a0', 'x1', 'x0+1', '2'], 'CHb0': ['1']}

Vertex  C6
Genus of reduced normalization:  Not Calculated
Reduced:  True
Multiplicity: 1
Self-intersection: -3
{'CHa2': ['1'], 'CHb3': ['a3+1', 'a1', 'a0', 'x1+1', 'x0', '2'], 'CHb2': ['a2+1', 'a1', 'a0', 'x1+1', 'x0', '2'], 'CHb0': ['1']}

===============Key (Vertex/Sheaf of ideals)==================
=============================================================
Dual graph saved to DualGraph-BVQDsfiber-2.png
=============================================================
Returning elementary divisors... [1, 1, 1, 1, 4, 4]
[
[{'CHa2': ['1'], 'CHb3': ['a3+1', 'a1+1', 'a0+a2', 'x1', 'x0+1', '2'], 'CHb2': ['a2+1', 'a1+a3', 'a0+1', 'x1', 'x0+1', '2'], 'CHb0': ['a2+1', 'a1+a3', 'a0+1', 'x1', 'x0+1', '2']}, {'CHa2': ['1'], 'CHb3': ['a3+1', 'x0+x1+a1', 'a2^2', 'a1*a2+a2', 'x1*a2', 'a1^2+1', 'x1*a1+x1', 'x1*a0+x1+a1+1', 'x1^2', 'a0^3*a1+a0^3+a0^2*a1+a0^2*a2+a0^2+a0*a1+a0+a1+1', '2'], 'CHb2': ['1'], 'CHb0': ['a0+1', 'x1*a3+x1+a1+a3', 'x0*a3+x1+a3', 'a2^2', 'x1*a2', 'x0*a2+a2', 'a1^2+a3^2', 'x1*a1+x1+a1+a3', 'x0*a1+x1+a1', 'x1^2', 'x0*x1+x1', 'x0^2+1', 'a1*a3^2+a3^3+a1*a3+a3^2+x0+x1+a1+a2+a3+1', 'a1*a2*a3+a2*a3^2', '2']}, {'CHa2': ['a2+1', 'a1+1', 'x1+1', 'x0', '2'], 'CHb3': ['a3+1', 'a1+a2', 'a0+a2', 'x1+1', 'x0', '2'], 'CHb2': ['a2+1', 'a1+1', 'a0+1', 'x1+1', 'x0', '2'], 'CHb0': ['a2+1', 'a1+1', 'a0+1', 'x1+1', 'x0', '2']}, {'CHa2': ['a2+1', 'a1^2', 'x1*a1+a1', 'x0*a1', 'x1*a0+x0+a0', 'x1^2+1', 'x0*x1+x0', 'x0^2', 'x0*a0^3+x1+a1+1', '2'], 'CHb3': ['a3+1', 'a2^2', 'a0*a2+a1*a2', 'x1*a2+a2', 'x0*a2', 'x1*a1+x1+a0+1', 'x0*a1+x1+1', 'a0^2+a1^2', 'x1*a0+x1+a1+1', 'x0*a0+x1+1', 'x1^2+1', 'x0*x1+x0', 'x0^2', 'a0*a1^2+a1^3+a1^2*a2+a0*a1+a1^2+x0+x1+a0+a1+1', '2'], 'CHb2': ['1'], 'CHb0': ['a0+1', 'x0+x1+a1', 'x1*a3+x1+a1+a3', 'a2^2', 'a1*a2+a2', 'x1*a2+a2', 'a1^2+1', 'x1*a1+x1+a1+1', 'x1^2+1', 'a1*a3^3+a1*a3^2+a3^3+a1*a3+a3^2+a1+a2+a3+1', '2']}, {'CHa2': ['a2+1', 'a1', 'x1*a0+x0+a0', 'a0^4+1', 'x0*a0^3+x1+1', 'x0^2*a0^2+x1^2+1', 'x0^3*a0+x1^3+x1^2+x1+1', 'x0^4+x1^4+1', '2'], 'CHb3': ['a3+1', 'a2', 'x0*a1+x1+1', 'x1*a0+x1+a1+1', 'a0*a1^2+a1^3+x0*a0+a0*a1+a1^2+x0+a0+a1', 'a1^4+1', 'a0^3*a1+a0^3+a0^2*a1+a0^2+a0*a1+a0+a1+1', 'x1^3*a1+x0^3+x1^2*a1+x1*a1+a1', 'a0^4+1', 'x0^2*a0^2+x0^2+a0^2+a1^2', 'x0^3*a0+x0^3+x1^2*a1+x1*a1^2+x0^2+x1*a1+a0*a1', 'x0^4+x1^4+1', '2'], 'CHb2': ['1'], 'CHb0': ['a2', 'a0+1', 'x1*a3+x1+a1+a3', 'x0*a1+x1+a1', 'a1^2*a3+x0*a3^2+a1*a3^2+a1^2+a1*a3+a3^2+x0+1', 'a3^4+1', 'a1*a3^3+a1*a3^2+a3^3+a1*a3+a3^2+a1+a3+1', 'x0*a3^3+x0*a3^2+a1*a3^2+x0*a3+a3^2+x0+a1+1', 'x0^3*a3+x0^3+x1^2*a1+x0^2+x1*a1+x0+a1+1', 'x0^4+x1^4+1', '2']}, {'CHa2': ['1'], 'CHb3': ['a3+1', 'a1+1', 'a0', 'x1', 'x0+1', '2'], 'CHb2': ['a2+1', 'a1+a3', 'a0', 'x1', 'x0+1', '2'], 'CHb0': ['1']}, {'CHa2': ['1'], 'CHb3': ['a3+1', 'a1', 'a0', 'x1+1', 'x0', '2'], 'CHb2': ['a2+1', 'a1', 'a0', 'x1+1', 'x0', '2'], 'CHb0': ['1']}],

[-3  1  0  0  0  1  0]
[ 1 -3  0  0  1  1  0]
[ 0  0 -3  1  0  0  1]
[ 0  0  1 -3  1  0  1]
[ 0  1  0  1 -1  0  0]
[ 1  1  0  0  0 -3  0]
[1, 2, 1, 2, 4, 1, 1], [ 0  0  1  1  0  0 -3],

, [1, 1, 1, 1, 4, 4]
]

```

## Example 3: (Resolving singularities interactively)

A theorem of J. Lipman (Lipman's algorithm) states that successively normalizing and blowing up the irregular locus (with reduced induced structure) will eventually produce a regular model. Of course, a regular model (of a curve over the integers as above) can be constructed by one (cleverly chosen) blow up. The Resolve() function implements Lipman's algorithm. However, this may take too long for a given example. Here are some of the tools one could use to construct a regular model interactively.
1. Normalization
```
sage: X = importRS("/home/user/ResSing/Schemes/Modular/ModularCurve-X045.RS")
Modular Curve X0(45), from "Defining Equations of Modular Curves X0(N)" by Mahoro Shimura
Equation x^4 + y^4 + 81*z^4 - 2*x^2*y^2 - 2*x^2*z^2 - 18*y^2*z^2 - 16*x*y^2*z

sage: X.isNormal()
Checking if chart  U1  is normal
Chart  U1  is not normal
False

sage: X.isR1()
Computing Nonfree locus... done.
Checking regularity...
P =  Multivariate Polynomial Ring in x0, x1 over Integer Ring
I =  Ideal (x0^4 - 2*x0^2*x1^2 + 81*x1^4 - 2*x0^2 - 16*x0*x1 - 18*x1^2 + 1) of Multivariate Polynomial Ring in x0, x1 over Integer Ring
m =  ['x0 + x1 + 1', '2', 'x0^4 - 2*x0^2*x1^2 + 81*x1^4 - 2*x0^2 - 16*x0*x1 - 18*x1^2 + 1', '2']
base =  ℤ
done (dim m/m^2 = 2)
False

sage: Y = NormalizeScheme(X)
-----------------------------------
Normalized affine scheme with coordinate ring R = P/I
P = ℤ ['x0', 'x1']

I =  ['x0^4 - 2*x0^2*x1^2 + 81*x1^4 - 2*x0^2 - 16*x0*x1 - 18*x1^2 + 1']

(x0 + x1 + 1) / (2)
(x0) / (1)
(x1) / (1)
Normalization of affine scheme completed. Total time:  0.384817
-----------------------------------
-----------------------------------
Normalized affine scheme with coordinate ring R = P/I
P = ℤ ['x0', 'x1']

I =  ['x0^4 - 2*x0^2*x1^2 + x1^4 - 16*x0*x1^2 - 2*x0^2 - 18*x1^2 + 81']

(x0 + x1 + 1) / (2)
(x0) / (1)
(x1) / (1)
Normalization of affine scheme completed. Total time:  0.38311
-----------------------------------
Done calculating normalizations of rings.
Need to compute expression for  2  fractions in other chart.
Solving for  1  fractions: .

Solving for  1  fractions: .

100.000000000000 % done calculating glueing maps.

sage: Y.isNormal()
Checking if chart  U1  is normal
Checking if chart  U2  is normal
True
```
2. Blowing up. We investigate this with a Shimura curve of discriminant 26 over Q.
```sage: X = importRS("/home/user/Desktop/Math/Dropbox/code/ResSing/Schemes/Shimura26/Shimura26-singular.RS")
Shimura curve of discriminant 26 over Q (Kurihara)

26

###################################
The function X.ignorePrimesOutside() affects the irregular locus
calculation. See documentation of this function for details. This is
different from the base change over Z[1/n], which can be constructed
via the X.invert(n) function.
###################################
sage: X.ignorePrimesOutside(13)

sage: X.irregLocusIdealSheaf()
Computing Nonfree locus... done.
Computing Nonfree locus... done.
Checking regularity...
P =  Multivariate Polynomial Ring in x, y over Integer Ring
I =  Ideal (169*x^6 + 24*x^4 - 19*x^2 + y^2 + 2) of Multivariate Polynomial Ring in x, y over Integer Ring
m =  ['y', 'x^2 - 5', '13', '169*x^6 + 24*x^4 - 19*x^2 + y^2 + 2', '13']
base =  ℤ
done (dim m/m^2 = 3)
done.
Computing Nonfree locus... done.
Computing Nonfree locus... done.
Checking regularity...
P =  Multivariate Polynomial Ring in a, b over Integer Ring
I =  Ideal (2*a^6 - 19*a^4 + 24*a^2 + b^2 + 169) of Multivariate Polynomial Ring in a, b over Integer Ring
m =  ['b', 'a^2 + 5', '13', '2*a^6 - 19*a^4 + 24*a^2 + b^2 + 169', '13']
base =  ℤ
done (dim m/m^2 = 3)
Checking regularity...
P =  Multivariate Polynomial Ring in a, b over Integer Ring
I =  Ideal (2*a^6 - 19*a^4 + 24*a^2 + b^2 + 169) of Multivariate Polynomial Ring in a, b over Integer Ring
m =  ['b', 'a', '13', '2*a^6 - 19*a^4 + 24*a^2 + b^2 + 169', '13']
base =  ℤ
done (dim m/m^2 = 3)
done.
Computing Nonfree locus... done.
Computing Nonfree locus... done.
{'U': ['13', '-y', '-x^2 + 5'], 'V': ['a^3+5*a', '13', 'b']}

###################################
Now blow up this ideal sheaf and check if the resulting scheme is regular (note we are ignoring irregular points over the prime 2)
###################################

sage: Y = X.BlowUp({'U': ['13', '-y', '-x^2 + 5'], 'V': ['a^3+5*a', '13', 'b']})
Will blow up ideal sheaf =  {'U': ['13', '-y', '-x^2 + 5'], 'V': ['a^3+5*a', '13', 'b']}
-----------------------------------
Blowing up affine scheme  CHa  with coordinate ring R = P/I
P = ℤ ['x', 'y']

I =  ['169*x^6 + 24*x^4 - 19*x^2 + y^2 + 2']

At ideal : ['13', '-y', '-x^2 + 5']

-----------------------------------
Will compute glueing maps for  1  pairs of blowups.
1  of  3  charts for BlowUp_Affine(CHa ) completed: CHa0 completed.
2  of  3  charts for BlowUp_Affine(CHa ) completed: CHa1 completed.
3  of  3  charts for BlowUp_Affine(CHa ) completed: CHa2 completed.
Affine charts of blow up of  CHa calculated in 0.00002 hours. Calculating affine glueing maps...
########Blow up of affine scheme  CHa  completed  in 0.00003  hours. ########
-----------------------------------
Blowing up affine scheme  CHb  with coordinate ring R = P/I
P = ℤ ['a', 'b']

I =  ['2*a^6 - 19*a^4 + 24*a^2 + b^2 + 169']

At ideal : ['a^3+5*a', '13', 'b']

-----------------------------------
1  of  3  charts for BlowUp_Affine(CHb ) completed: CHb0 completed.
2  of  3  charts for BlowUp_Affine(CHb ) completed: CHb1 completed.
3  of  3  charts for BlowUp_Affine(CHb ) completed: CHb2 completed.
Affine charts of blow up of  CHb calculated in 0.00002 hours. Calculating affine glueing maps...
########Blow up of affine scheme  CHb  completed  in 0.00003  hours. ########
Calculated linear combinations for  U , V , minimizing...
Constructing open sets and glueing maps...
Calculated glueing maps for (V  chart 1 of  3 ) with (U chart 1 of  3 )
Calculated glueing maps for (V  chart 1 of  3 ) with (U chart 3 of  3 )
Calculated glueing maps for (V  chart 1 of  3 ) with (U chart 2 of  3 )
Calculated glueing maps for (V  chart 2 of  3 ) with (U chart 1 of  3 )
Calculated glueing maps for (V  chart 2 of  3 ) with (U chart 2 of  3 )
Calculated glueing maps for (V  chart 2 of  3 ) with (U chart 3 of  3 )
Calculated glueing maps for (V  chart 3 of  3 ) with (U chart 1 of  3 )
Calculated glueing maps for (V  chart 3 of  3 ) with (U chart 2 of  3 )
Calculated glueing maps for (V  chart 3 of  3 ) with (U chart 3 of  3 )
len(computedGB), finished calculating glueing, we calculated  4  new groebner bases.
100.000000000000 % done calculating glueing maps.
<__main__.ResolveScheme instance at 0x7670248>

sage: Y.isRegular()
Computing Nonfree locus... done.
Computing Nonfree locus... done.
Computing Nonfree locus... done.
Computing Nonfree locus... done.
Computing Nonfree locus... done.
Computing Nonfree locus... done.
True
```
We calculated a regular model of this shimura curve (as a scheme over Z[1/13]). You can load this model by
```sage X = importRS("/home/user/ResSing/Schemes/Shimura26/Shimura26-inv2-REGULAR.RS")

```
3. Simplification: Sometimes we are in the position where we would like to preform various operations after a blow up (eg, Y1 = BlowUp(X) and Y2 = BlowUp(Y1) or Y2 = NormalizeScheme(Y1)) but the second operation computes too slowly. It may help to compute a more simplified presentation of the scheme Y1. One can do this via the optional trim_level parameter. sage: Y = Resolve(X, trim_level = 3) ... sage: BlowUp(X, trim_level = 1) The parameter trim_level controls how much we attempt to simplify the BlowUp. Possibilities for this optional parameter are 0, 1, 2, and 3, ranging from least to most simplification. Playing with this parameter can sometimes yield schemes with substantially better presentation. The default value is 0. Optimizations preformed here cannot be preformed after a regular model is calculated. This optional parameter can be passed to Resolve(), X.BlowUp() and BlowUp() and Resolve()
4. Another function for this is X.trim() which attempts to simplify the scheme (in different ways from trim_level). It also accepts optional parameters, see it's documentation in sage. Running X.trim(...) before a computation can drastically improve its speed.
```sage: X.trim(?

Simplify the presentation of self by removing redundant charts,
trimming the presentation of each of the coordinate rings and the
presentation of isomorphisms between the rings.

This function replaces self with a trimmed copy and then returns.

if compute == True we compute groebner bases with respect to the
elimination ordering for the chart specified via chart (and all
charts if none is specified.)

if compute == False then don't compute any elimination order
groebner bases, and more simply try to remove relations.
```

## Other functions

1. There are lots of other functions available. After you have constructed a scheme that you are interested in type
` sage: X. (and press the tab key) `
This prints
```sage: X.
X.BlowUp                 X.chabautyBound          X.genericFiberSmooth     X.irregLocus             X.nonSmoothLocus         X.sanityCheck
X.CNames                 X.chart                  X.genericGenus           X.irregLocusHints        X.normal                 X.singularities
X.G                      X.complement             X.genus                  X.irregLocusIdealSheaf   X.numcharts              X.smoothComponent
X.INames                 X.componentGroup         X.glueingConditions      X.irreg_locus            X.ord                    X.trim
X.Lelement               X.components             X.hyperelliptic          X.isNormal               X.pickle                 X.twoCharts
X.Lname                  X.computeGB              X.ignorePrimesOutside    X.isR1                   X.projVar                X.values
X.Normalize              X.deleteNode             X.information            X.isRegular              X.r1                     X.zetaSeries
X.affineScheme           X.disjointUnion          X.intersection           X.map                    X.reducedFibers
X.calculatedNormalLocus  X.exportRS               X.intersectionNumber     X.nonSmoothFibers        X.regular
X.calculatedSingLocus    X.fiberInformation       X.invert                 X.nonSmoothIdealSheaf    X.rmap
```
Now you can see the documentation for any of these functions via the usual method. Eg, typing
```sage: X.zetaSeries(?

and pressing enter
Type:       instancemethod
String Form:>
File:       Dynamically generated function. No source code available.
Definition: X.zetaSeries(self, p, n, ideals=None)
Docstring:
Compute the zeta function of the fiber of the ResolveScheme self at
the prime p. The first n terms of the zeta series are returned as a
power series in u.

p >1 is a prime integer, and n is an integer. t is a string.

if ideals is a specified sheaf of ideals supported over the prime
p, then compute the zeta function of the scheme it defines.

```

## Configuration (optional)

1. By default config.py is configured for this program to run on a laptop. Here are a few lines from "config.py" that the user can modify according to the computing resources available to them.
```#Number of processes to use (values larger than 1 consume alot of memory). (excluding solving for fractions in normalization)
num_processes = 1

#Number of threads to use in quick part of BlowUp routine.
num_glueTwoChartsBL = 5

#Number of processes to use for solving fractions. Must be at least 1, else normalizaton will hang.
num_solve_fracs = 5

#Number of charts to simultaneously blow up. Must be at least 1.
num_charts_blowup = 1
```
They are all self-documented in "config.py". The main number a user (with access to many processors) will want to increase is "num_processors". If normalization or blowing up is slow (and the computer still has available resources) then the user could try increasing num_solve_fracs (for normalization) or num_glueTwoChartsBL and num_charts_blowup (for blowups) respectively.

[1] Siegfried Bosch, Werner Lutkebohmert, and Michel Raynaud. Neron models, volume 21 of Ergebnisse der Mathematik und ihrer Grenzgebiete (3) [Results in Mathematics and Related Areas (3)]. Springer- Verlag, Berlin, 1990.

[2] Bruce W. Jordan and Ron A. Livne. Local Diophantine properties of Shimura curves. Math. Ann., 270(2):235-248, 1985.

[3] Eric Katz and David Zureick-Brown. The Chabauty-Coleman bound at a prime of bad reduction and Clifford bounds for geometric rank functions. Compos. Math., 149(11):1818-1838, 2013.

This software is © Copyright 2013-2014 by Suchandan Pal and released under the GNU LGPL.