SetEchoInput(true);

function MultPolFacts(f)
//Multiplies the factors with multiplicities
    if #f eq 0 then
        return Universe(f)[1]!1;
    end if;

    return &*[T[1]^(T[2]) : T in f];
end function;

//SetIsNicole(false);
//kummer_split
P<x> := PolynomialRing(Integers());
K := EquationOrder(x^2 + 2);
D := Factorization(Discriminant(DefiningPolynomial(K)));
M := MaximalOrder(K);
time Decomposition(K, D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
assert Minimum(MultPolFacts($1)) eq D[1][1];
assert MultPolFacts($1) eq D[1][1]*Order($1[1][1]);
assert &and[Minimum(d[1]) eq D[1][1]: d in $1];
[RamificationDegree(d[1]) : d in $1];

K := EquationOrder(x^2 + 11);
D := Factorization(Discriminant(DefiningPolynomial(K)));
M := MaximalOrder(K);
time Decomposition(K, D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
assert Minimum(MultPolFacts($1)) eq D[1][1];
assert MultPolFacts($1) eq D[1][1]*Order($1[1][1]);
assert &and[Minimum(d[1]) eq D[1][1]: d in $1];
[RamificationDegree(d[1]) : d in $1];
time Decomposition(K, D[2][1]);
time DD := Decomposition(M, D[2][1]);
DD;
assert Minimum(MultPolFacts($1)) eq D[2][1];
assert MultPolFacts($1) eq D[2][1]*Order($1[1][1]);
assert &and[Minimum(d[1]) eq D[2][1]: d in $1];
[RamificationDegree(d[1]) : d in $1];

k := CyclotomicField(3);
a := k!625;
K := ext<EquationOrder(k) | PolynomialRing(k).1^3 - a>;
D := Decomposition(MaximalOrder(k)!Discriminant(DefiningPolynomial(K)));
M := MaximalOrder(K);
time Decomposition(K, D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
assert MultPolFacts($1) meet Order(D[1][1]) eq D[1][1];
assert MultPolFacts($1) eq Order($1[1][1])!!D[1][1];
assert &and[d[1] meet Order(D[1][1]) eq D[1][1]: d in $1];
[RamificationDegree(d[1]) : d in $1];

time Decomposition(K, D[2][1]);
time DD := Decomposition(M, D[2][1]);
DD;
assert MultPolFacts($1) meet Order(D[2][1]) eq D[2][1];
assert MultPolFacts($1) eq Order($1[1][1])!!D[2][1];
assert &and[d[1] meet Order(D[2][1]) eq D[2][1]: d in $1];
[RamificationDegree(d[1]) : d in $1];

k := CyclotomicField(9);
a := k!2^4;
K := ext<EquationOrder(k) | PolynomialRing(k).1^9 - a>;
D := Decomposition(MaximalOrder(k)!Discriminant(DefiningPolynomial(K)));
M := MaximalOrder(K);
time Decomposition(K, D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
assert MultPolFacts($1) meet Order(D[1][1]) eq D[1][1];
assert MultPolFacts($1) eq Order($1[1][1])!!D[1][1];
assert &and[d[1] meet Order(D[1][1]) eq D[1][1]: d in $1];
[RamificationDegree(d[1]) : d in $1];

time Decomposition(K, D[2][1]);
time DD := Decomposition(M, D[2][1]);
DD;
assert MultPolFacts($1) meet Order(D[2][1]) eq D[2][1];
assert MultPolFacts($1) eq Order($1[1][1])!!D[2][1];
assert &and[d[1] meet Order(D[2][1]) eq D[2][1]: d in $1];
[RamificationDegree(d[1]) : d in $1];

k := CyclotomicField(6);
a := k!7^5;
K := ext<EquationOrder(k) | PolynomialRing(k).1^6 - a>;
D := Decomposition(MaximalOrder(k)!Discriminant(DefiningPolynomial(K)));
M := MaximalOrder(K);
time Decomposition(K, D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
assert MultPolFacts($1) meet Order(D[1][1]) eq D[1][1];
assert MultPolFacts($1) eq Order($1[1][1])!!D[1][1];
assert &and[d[1] meet Order(D[1][1]) eq D[1][1]: d in $1];
[RamificationDegree(d[1]) : d in $1];

time Decomposition(K, D[2][1]);
time DD := Decomposition(M, D[2][1]);
DD;
assert MultPolFacts($1) meet Order(D[2][1]) eq D[2][1];
assert MultPolFacts($1) eq Order($1[1][1])!!D[2][1];
assert &and[d[1] meet Order(D[2][1]) eq D[2][1]: d in $1];
[RamificationDegree(d[1]) : d in $1];

k := CyclotomicField(12);
a := k!5^7;
K := ext<EquationOrder(k) | PolynomialRing(k).1^12 - a>;
D := Decomposition(MaximalOrder(k)!Discriminant(DefiningPolynomial(K)));
M := MaximalOrder(K);
time Decomposition(K, D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
assert MultPolFacts($1) meet Order(D[1][1]) eq D[1][1];
assert MultPolFacts($1) eq Order($1[1][1])!!D[1][1];
assert &and[d[1] meet Order(D[1][1]) eq D[1][1]: d in $1];
[RamificationDegree(d[1]) : d in $1];

time Decomposition(K, D[2][1]);
time DD := Decomposition(M, D[2][1]);
DD;
assert MultPolFacts($1) meet Order(D[2][1]) eq D[2][1];
assert MultPolFacts($1) eq Order($1[1][1])!!D[2][1];
assert &and[d[1] meet Order(D[2][1]) eq D[2][1]: d in $1];
[RamificationDegree(d[1]) : d in $1];


//kummer_alff_split
P<x> := PolynomialRing(GF(5));
P<y> := PolynomialRing(P);
F<c> := FunctionField(y^4 + x);
D := Factorization(Discriminant(DefiningPolynomial(F)));
M := MaximalOrderFinite(F);
time Decomposition(EquationOrderFinite(F), D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
de := &* [d^RamificationDegree(d) : d in $1];
assert Minimum(de) eq D[1][1];
assert de eq MaximalOrderFinite(F)*D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in $1];
assert de eq D[1][1]*Order($1[1]);
[RamificationDegree(d) : d in $1];

D := Factorization(Discriminant(DefiningPolynomial(EquationOrderInfinite(F))));
M := MaximalOrderInfinite(F);
time Decomposition(EquationOrderInfinite(F), D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
de := &* [d^RamificationDegree(d) : d in $1];
assert Minimum(de) eq D[1][1];
assert de eq MaximalOrderInfinite(F)*D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in $1];
assert de eq D[1][1]*Order($1[1]);
[RamificationDegree(d) : d in $1];

P<x> := PolynomialRing(GF(7, 3));
P<y> := PolynomialRing(P);
F<c> := FunctionField(y^6 + 2*x^5);
D := Factorization(Discriminant(DefiningPolynomial(F)));
M := MaximalOrderFinite(F);
time Decomposition(EquationOrderFinite(F), D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
de := &* [d^RamificationDegree(d) : d in $1];
assert Minimum(de) eq D[1][1];
assert de eq MaximalOrderFinite(F)*D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in $1];
assert de eq D[1][1]*Order($1[1]);
[RamificationDegree(d) : d in $1];

D := Factorization(Discriminant(DefiningPolynomial(EquationOrderInfinite(F))));
M := MaximalOrderInfinite(F);
time Decomposition(EquationOrderInfinite(F), D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
de := &* [d^RamificationDegree(d) : d in $1];
assert Minimum(de) eq D[1][1];
assert de eq MaximalOrderInfinite(F)*D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in $1];
assert de eq D[1][1]*Order($1[1]);
[RamificationDegree(d) : d in $1];

P<x> := PolynomialRing(Rationals());
P<y> := PolynomialRing(P);
F<c> := FunctionField(y^2 - x);
D := Factorization(Discriminant(DefiningPolynomial(F)));
M := MaximalOrderFinite(F);
time Decomposition(EquationOrderFinite(F), D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
de := &* [d^RamificationDegree(d) : d in $1];
assert Minimum(de) eq D[1][1];
assert de eq MaximalOrderFinite(F)*D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in $1];
[RamificationDegree(d) : d in $1];

D := Factorization(Discriminant(DefiningPolynomial(EquationOrderInfinite(F))));
M := MaximalOrderInfinite(F);
time Decomposition(EquationOrderInfinite(F), D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
de := &* [d^RamificationDegree(d) : d in $1];
assert Minimum(de) eq D[1][1];
assert de eq MaximalOrderInfinite(F)*D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in $1];
[RamificationDegree(d) : d in $1];

/*
// no totally ramified primes here
P<x> := PolynomialRing(CyclotomicField(8));
P<y> := PolynomialRing(P);
F<c> := FunctionField(y^8 + 3*x^4);
*/

P<x> := PolynomialRing(CyclotomicField(3));
P<y> := PolynomialRing(P);
k := FunctionField(y^2 + x);
a := k!625*x;
K := ext<EquationOrderFinite(k) | PolynomialRing(k).1^3 - a>;
D := Factorization(MaximalOrderFinite(k)*Discriminant(DefiningPolynomial(K)));
M := MaximalOrder(K);
time Decomposition(K, D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
de := &* [d^RamificationDegree(d) : d in $1];
assert Minimum(de) eq D[1][1];
assert de eq MaximalOrder(K)!!D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in $1];
[RamificationDegree(d) : d in $1];

a := k!625/x;
K := ext<EquationOrderInfinite(k) | PolynomialRing(k).1^3 - a>;
D := Factorization(MaximalOrderInfinite(k)*Discriminant(DefiningPolynomial(K)));
M := MaximalOrder(K);
time Decomposition(K, D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
de := &* [d^RamificationDegree(d) : d in $1];
assert Minimum(de) eq D[1][1];
assert de eq MaximalOrder(K)!!D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in $1];
[RamificationDegree(d) : d in $1];

P<x> := PolynomialRing(CyclotomicField(9));
P<y> := PolynomialRing(P);
k := FunctionField(y^2 + x);
a := k!2^4*x;
K := ext<EquationOrderFinite(k) | PolynomialRing(k).1^9 - a>;
D := Factorization(MaximalOrderFinite(k)*Discriminant(DefiningPolynomial(K)));
M := MaximalOrder(K);
time Decomposition(K, D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
de := &* [d^RamificationDegree(d) : d in $1];
assert &and[Minimum(d) eq D[1][1]: d in $1];
assert Minimum(de) eq D[1][1];
assert de eq MaximalOrder(K)!!D[1][1];
[RamificationDegree(d) : d in $1];

a := k!2^4/x;
K := ext<EquationOrderInfinite(k) | PolynomialRing(k).1^9 - a>;
D := Factorization(MaximalOrderInfinite(k)*Discriminant(DefiningPolynomial(K)));
M := MaximalOrder(K);
time Decomposition(K, D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
de := &* [d^RamificationDegree(d) : d in $1];
assert de eq MaximalOrder(K)!!D[1][1];
assert Minimum(de) eq D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in $1];
[RamificationDegree(d) : d in $1];

/*
// no totally ramified primes in the next 2 examples
P<x> := PolynomialRing(CyclotomicField(6));
P<y> := PolynomialRing(P);
k := FunctionField(y^2 + x);
a := k!7^5*x;
K := ext<EquationOrderFinite(k) | PolynomialRing(k).1^6 - a>;

P<x> := PolynomialRing(CyclotomicField(12));
P<y> := PolynomialRing(P);
k := FunctionField(y^2 + x);
a := k!5^7*x;
K := ext<EquationOrderFinite(k) | PolynomialRing(k).1^12 - a>;
*/

P<x> := PolynomialRing(CyclotomicField(20));
P<y> := PolynomialRing(P);
F<c> := FunctionField(y^20 + 7*x^11);
D := Factorization(Discriminant(DefiningPolynomial(F)));
M := MaximalOrderFinite(F);
time Decomposition(EquationOrderFinite(F), D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
de := &* [d^RamificationDegree(d) : d in $1];
assert Minimum(de) eq D[1][1];
assert de eq MaximalOrderFinite(F)*D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in $1];
[RamificationDegree(d) : d in $1];

D := Factorization(Discriminant(DefiningPolynomial(EquationOrderInfinite(F))));
M := MaximalOrderInfinite(F);
time Decomposition(EquationOrderInfinite(F), D[1][1]);
time DD := Decomposition(M, D[1][1]);
DD;
de := &* [d^RamificationDegree(d) : d in $1];
assert Minimum(de) eq D[1][1];
assert de eq MaximalOrderInfinite(F)*D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in $1];
assert de eq D[1][1]*Order($1[1]);
[RamificationDegree(d) : d in $1];


//Artin/p_split_test
P<x> := PolynomialRing(GF(5));
P<y> := PolynomialRing(P);
F<c> := FunctionField(y^5 - y - x + 1);
D := Factorization(Discriminant(DefiningPolynomial(EquationOrderFinite(F))));
D;
D := Factorization(Discriminant(DefiningPolynomial(
EquationOrderInfinite(F))));
D;
M := MaximalOrderInfinite(F);
time DD := Decomposition(EquationOrderInfinite(F), D[1][1]);
DD;
time DD := Decomposition(M, D[1][1]);
DD;
assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq D[1][1];
assert &*[d^RamificationDegree(d) : d in DD] eq M*D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in DD];
[RamificationDegree(d) : d in DD];

P<x> := PolynomialRing(GF(11));
P<y> := PolynomialRing(FieldOfFractions(P));
F<c> := FunctionField(y^11 - y - x^2 + 1/x);
D := Factorization(Discriminant(DefiningPolynomial(EquationOrderFinite(F))));
D;
M := MaximalOrderFinite(F);
time DD := Decomposition(EquationOrderFinite(F), D[1][1]);
DD;
time DD := Decomposition(M, D[1][1]);
assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq D[1][1];
assert &*[d^RamificationDegree(d) : d in DD] eq M*D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in DD];
[RamificationDegree(d) : d in DD];

D := Factorization(Discriminant(DefiningPolynomial(
EquationOrderInfinite(F))));
D;
M := MaximalOrderInfinite(F);
time DD := Decomposition(EquationOrderInfinite(F), D[1][1]);
DD;
time DD := Decomposition(M, D[1][1]);
assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq D[1][1];
assert &*[d^RamificationDegree(d) : d in DD] eq MaximalOrderInfinite(F)*D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in DD];
[RamificationDegree(d) : d in DD];

P<x> := PolynomialRing(GF(7, 3));
P<y> := PolynomialRing(P);
F<c> := FunctionField(y^7 - y + x^3 + x + 1);
D := Factorization(Discriminant(DefiningPolynomial(EquationOrderFinite(F))));
D;

D := Factorization(Discriminant(DefiningPolynomial(
EquationOrderInfinite(F))));
D;
M := MaximalOrderInfinite(F);
time DD := Decomposition(EquationOrderInfinite(F), D[1][1]);
time DD := Decomposition(M, D[1][1]);
assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq D[1][1];
assert &*[d^RamificationDegree(d) : d in DD] eq MaximalOrderInfinite(F)*D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in DD];
[RamificationDegree(d) : d in DD];


//Artin/p_split_test_rel
P<x> := PolynomialRing(GF(5));
P<y> := PolynomialRing(P);
K<a> := FunctionField(y^3 + y + 1);
P<y> := PolynomialRing(K);
F<c> := FunctionField(y^5 - y + K!x);
D := Factorization(MaximalOrderFinite(K)*Discriminant(DefiningPolynomial(F)));
D;
D := Factorization(MaximalOrderInfinite(K)*Discriminant(DefiningPolynomial(
EquationOrderInfinite(F))));
D;
M := MaximalOrderInfinite(F);
time DD := Decomposition(EquationOrderInfinite(F), D[1][1]);
DD;
time DD := Decomposition(M, D[1][1]);
assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq D[1][1];
assert &*[d^RamificationDegree(d) : d in DD] eq M!!D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in DD];
[RamificationDegree(d) : d in DD];

P<x> := PolynomialRing(GF(11));
P<y> := PolynomialRing(FieldOfFractions(P));
K<a> := FunctionField(y^2 + 1);
P<y> := PolynomialRing(K);
F<c> := FunctionField(y^11 - y - K!x^2 + K!1/x);
D := Factorization(MaximalOrderFinite(K)*Discriminant(DefiningPolynomial(
						EquationOrderFinite(F))));
D;
M := MaximalOrderFinite(F);
time Decomposition(EquationOrderFinite(F), D[1][1]);
time DD := Decomposition(M, D[1][1]);
assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq D[1][1];
assert &*[d^RamificationDegree(d) : d in DD] eq M!!D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in DD];
[RamificationDegree(d) : d in DD];

D := Factorization(MaximalOrderInfinite(K)*Discriminant(DefiningPolynomial(
EquationOrderInfinite(F))));
D;
M := MaximalOrderInfinite(F);
time Decomposition(EquationOrderInfinite(F), D[1][1]);
time DD := Decomposition(M, D[1][1]);
assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq D[1][1];
assert &*[d^RamificationDegree(d) : d in DD] eq MaximalOrderInfinite(F)!!D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in DD];
[RamificationDegree(d) : d in DD];

P<x> := PolynomialRing(GF(7, 3));
P<y> := PolynomialRing(P);
K<a> := FunctionField(y^4 + y + 2);
P<y> := PolynomialRing(K);
F<c> := FunctionField(y^7 - y + K!x^3 + K!x + 1);

D := Factorization(MaximalOrderInfinite(K)*Discriminant(DefiningPolynomial(
EquationOrderInfinite(F))));
D;
M := MaximalOrderInfinite(F);
time Decomposition(EquationOrderInfinite(F), D[1][1]);
time DD := Decomposition(M, D[1][1]);
assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq D[1][1];
assert &*[d^RamificationDegree(d) : d in DD] eq MaximalOrderInfinite(F)!!D[1][1];
assert &and[Minimum(d) eq D[1][1]: d in DD];
[RamificationDegree(d) : d in DD];


//Artin/new_examples_split
k := GF(5);
kt<t> := FunctionField(k);
Places(kt, 1) cat Places(kt, 2);
p := $1;
D := 2*Random(p) + 2*Random(p);
R, mR := RayClassGroup(D);
U := 5*R; repeat U := sub<R|Random(R), U>; until #quo<R|U> eq 5;
A := AbelianExtension(D, U);
FunctionField(A);
F := $1;
F := FunctionField(DefiningPolynomials(F)[1]);
K := RationalExtensionRepresentation(CoefficientField(F));
D := Factorization(Discriminant(DefiningPolynomial(
EquationOrderFinite(F))));
D;
M := MaximalOrderFinite(F);
for d in D[1 .. #D by 2] do
    time DD := Decomposition(M, d[1]);
    assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq d[1];
    assert &*[d^RamificationDegree(d) : d in DD] eq M*d[1];
    assert &and[Minimum(dd) eq d[1]: dd in DD];
    [RamificationDegree(d) : d in DD];
end for;

D := Factorization(Discriminant(DefiningPolynomial(
EquationOrderInfinite(F))));
D;
M := MaximalOrderInfinite(F);

for d in D do
    time DD := Decomposition(M, d[1]);
    assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq d[1];
    assert &*[d^RamificationDegree(d) : d in DD] eq M*d[1];
    assert &and[Minimum(dd) eq d[1]: dd in DD];
    [RamificationDegree(d) : d in DD];
end for;

k := GF(5);
kt<t> := FunctionField(k);
kty<y> := PolynomialRing(kt);
K := FunctionField(y^3+y+1);
p := Places(K, 3) cat Places(K, 2);
D := 2*p[1] + 2*p[7];
R, mR := RayClassGroup(D);
U := 5*R; repeat U := sub<R|Random(R), U>; until #quo<R|U> eq 5;
U := sub<R | [ 2*R.1 + R.2, 2*R.1 + R.3, 2*R.1 + R.4, R.1 + R.5, 3*R.1 - R.6 ]>;
U := sub<R | [ R.3, 4*R.2 + R.4, 4*R.1 + R.5, 4*R.1 + 2*R.2,  3*R.1 + 2*R.2 + R.6, 4*R.1 + R.2 + R.7]>;
A := AbelianExtension(D, U);
FunctionField(A);
F := $1;
F := FunctionField(DefiningPolynomials(F)[1]);
K := RationalExtensionRepresentation(CoefficientField(F));
D := Factorization(MaximalOrderFinite(K)*Discriminant(DefiningPolynomial(
EquationOrderFinite(F))));
D;
M := MaximalOrderFinite(F);
for d in D[1 .. #D by 2] do
    time DD := Decomposition(M, d[1]);
    assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq d[1];
    assert &*[d^RamificationDegree(d) : d in DD] eq M!!d[1];
    assert &and[Minimum(dd) eq d[1]: dd in DD];
    [RamificationDegree(d) : d in DD];
end for;

D := Factorization(MaximalOrderInfinite(K)*Discriminant(DefiningPolynomial(
EquationOrderInfinite(F))));
D;
M := MaximalOrderInfinite(F);
for d in D[Minimum(2, #D) .. #D by 2] do
    time DD := Decomposition(M, d[1]);
    assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq d[1];
    assert &*[d^RamificationDegree(d) : d in DD] eq M!!d[1];
    assert &and[Minimum(dd) eq d[1]: dd in DD];
    [RamificationDegree(d) : d in DD];
end for;

k := GF(5);
kt<t> := FunctionField(k);
kty<y> := PolynomialRing(kt);
K := FunctionField(y^4+3*y+t^2+t+1);
Decomposition(MaximalOrderInfinite(K), CoefficientRing(MaximalOrderInfinite(K))!(1/t));
/*
p := Places(K, 1) cat Places(K, 2);
D := 2*p[1] + 2*p[7];
R, mR := RayClassGroup(D);
U := 5*R; repeat U := sub<R|Random(R), U>; until #quo<R|U> eq 5;
U := sub<R | [ R.2, 3*R.1 + R.3 ] >;
A := AbelianExtension(D, U);
FunctionField(A);
F := $1;
F := FunctionField(DefiningPolynomials(F)[1]);
*/
Fs := [ext<K | x^5 + 4*x + (4*t^2 + 3*t)/(t + 4)*K.1^3 + 4*t/(t + 4)*K.1^2 + 
	3*t^3/(t + 4)*K.1 + (4*t^2 + 3)/(t + 4)>, ext<K | x^5 + 4*x + 
	(4*t^2 + 3*t + 2)/(t + 4)*K.1^3 + (t + 2)/(t + 4)*K.1^2 + (2*t^3 + 
        4*t)/(t + 4)*K.1 + (4*t^2 + t + 4)/(t + 4)>] 
	where x is PolynomialRing(K).1;
//for F in Fs do
F := Fs[Random(1, 2)];
    K := RationalExtensionRepresentation(CoefficientField(F));
    D := Factorization(MaximalOrderFinite(K)*Discriminant(DefiningPolynomial(
    EquationOrderFinite(F))));
    D;
    M := MaximalOrderFinite(F);
    time DD := Decomposition(M, D[1][1]);
    assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq D[1][1];
    assert &*[d^RamificationDegree(d) : d in DD] eq M!!D[1][1];
    assert &and[Minimum(d) eq D[1][1]: d in DD];
    [RamificationDegree(d) : d in DD];

    time DD := Decomposition(M, D[2][1]);
    assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq D[2][1];
    assert &*[d^RamificationDegree(d) : d in DD] eq M!!D[2][1];
    assert &and[Minimum(d) eq D[2][1]: d in DD];
    [RamificationDegree(d) : d in DD];

    D := Factorization(MaximalOrderInfinite(K)*Discriminant(DefiningPolynomial(
    EquationOrderInfinite(F))));
    D;

    M := MaximalOrderInfinite(F);
    time DD := Decomposition(M, D[1][1]);
    assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq D[1][1];
    assert &*[d^RamificationDegree(d) : d in DD] eq M!!D[1][1];
    assert &and[Minimum(d) eq D[1][1]: d in DD];
    [RamificationDegree(d) : d in DD];

    time DD := Decomposition(M, D[2][1]);
    assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq D[2][1];
    assert &*[d^RamificationDegree(d) : d in DD] eq M!!D[2][1];
    assert &and[Minimum(d) eq D[2][1]: d in DD];
    [RamificationDegree(d) : d in DD];
//end for;


loop_start_time := Cputime();
//Artin/new_examples_split_loop
split_time := [];
no_splits := [];
unram_split_time := [];
k := GF(5);
kt<t> := FunctionField(k);
p := Places(kt, 1) cat Places(kt, 2);
for i in [1 .. 3] do
    Div := 2*Random(p) + 2*Random(p);
    R, mR := RayClassGroup(Div);
    for j in [1 .. 3] do 
	U := 5*R; repeat U := sub<R|Random(R), U>; until #quo<R|U> eq 5;
	A := AbelianExtension(Div, U);
	F := FunctionField(A);
	F := FunctionField(DefiningPolynomials(F)[1]);
	K := RationalExtensionRepresentation(CoefficientField(F));
	D := Factorization(Discriminant(DefiningPolynomial(
						EquationOrderFinite(F))));
	D;
	MaximalOrderFinite(F);
	Append(~no_splits, #D);
	for d in D[1 .. #D by 2] do
	    start_time := Cputime();
	    time DD := Decomposition(MaximalOrderFinite(F), d[1]);
	    assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq d[1];
	    assert &*[d^RamificationDegree(d) : d in DD] eq
						    MaximalOrderFinite(F)*d[1];
	    assert &and[Minimum(dd) eq d[1]: dd in DD];
	    [RamificationDegree(d) : d in DD];
	    if #DD eq 1 and RamificationDegree(DD[1]) eq Degree(F) then
		Append(~split_time, Cputime(start_time));
	    else
		Append(~unram_split_time, Cputime(start_time));
	    end if;
	end for;
	D := Factorization(Discriminant(
			    DefiningPolynomial(EquationOrderInfinite(F))));
	D;
	MaximalOrderInfinite(F);
	Append(~no_splits, #D);
	for d in D do
	    start_time := Cputime();
	    time DD := Decomposition(MaximalOrderInfinite(F), d[1]);
	    assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq d[1];
	    assert &*[d^RamificationDegree(d) : d in DD] eq
						MaximalOrderInfinite(F)*d[1];
	    assert &and[Minimum(dd) eq d[1]: dd in DD];
	    [RamificationDegree(d) : d in DD];
	    if #DD eq 1 and RamificationDegree(DD[1]) eq Degree(F) then
		Append(~split_time, Cputime(start_time));
	    else
		Append(~unram_split_time, Cputime(start_time));
	    end if;
	end for;
    end for;
end for;

k := GF(5);
kt<t> := FunctionField(k);
kty<y> := PolynomialRing(kt);
K := FunctionField(y^3+y+1);
p := Places(K, 3) cat Places(K, 2);
Div := 2*p[1] + 2*p[7];
R, mR := RayClassGroup(Div);
for i in [1 .. 5] do
    U := 5*R; repeat U := sub<R|Random(R), U>; until #quo<R|U> eq 5;
    A := AbelianExtension(Div, U);
    F := FunctionField(A);
    F := FunctionField(DefiningPolynomials(F)[1]);
    K := RationalExtensionRepresentation(CoefficientField(F));
    time MaximalOrderFinite(F);

    D := Factorization(MaximalOrderFinite(K)*Discriminant(DefiningPolynomial(
    EquationOrderFinite(F))));
    D;
    Append(~no_splits, #D);
    for d in D[1 .. #D by 2] do
	start_time := Cputime();
	time DD := Decomposition(MaximalOrderFinite(F), d[1]);
	assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq d[1];
	assert &*[d^RamificationDegree(d) : d in DD] eq
					    MaximalOrderFinite(F)!!d[1];
	assert &and[Minimum(dd) eq d[1]: dd in DD];
	[RamificationDegree(d) : d in DD];
	if #DD eq 1 and RamificationDegree(DD[1]) eq Degree(F) then
	    Append(~split_time, Cputime(start_time));
	else
	    Append(~unram_split_time, Cputime(start_time));
	end if;
    end for;
    time MaximalOrderInfinite(F);
    D := Factorization(MaximalOrderInfinite(K)*Discriminant(DefiningPolynomial(
    EquationOrderInfinite(F))));
    D;
    Append(~no_splits, #D);
    if #D gt 0 then
    for d in D[Minimum(2, #D) .. #D by 2] do
	start_time := Cputime();
	time DD := Decomposition(MaximalOrderInfinite(F), d[1]);
	assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq d[1];
	assert &*[d^RamificationDegree(d) : d in DD] eq
					    MaximalOrderInfinite(F)!!d[1];
	assert &and[Minimum(dd) eq d[1]: dd in DD];
	[RamificationDegree(d) : d in DD];
	if #DD eq 1 and RamificationDegree(DD[1]) eq Degree(F) then
	    Append(~split_time, Cputime(start_time));
	else
	    Append(~unram_split_time, Cputime(start_time));
	end if;
    end for;
    end if;
end for;

k := GF(5);
kt<t> := FunctionField(k);
kty<y> := PolynomialRing(kt);
K := FunctionField(y^4+3*y+t^2+t+1);
p := Places(K, 1) cat Places(K, 2);
p;
Div := 2*p[1] + 2*p[7];
R, mR := RayClassGroup(Div);
Fs := [];
p;
for i in [1 .. 5] do
    U := 5*R; repeat U := sub<R|Random(R), U>; until #quo<R|U> eq 5;
    A := AbelianExtension(Div, U);
    F := FunctionField(A);
    F := FunctionField(DefiningPolynomials(F)[1]);
    Append(~Fs, F);
    K := RationalExtensionRepresentation(CoefficientField(F));
    time MaximalOrderFinite(F);
    time MaximalOrderInfinite(F);

    D := Factorization(MaximalOrderFinite(K)*Discriminant(DefiningPolynomial(
    EquationOrderFinite(F))));
    D;
    Append(~no_splits, #D);
    for d in D[1 .. #D by 2] do
	start_time := Cputime();
	time DD := Decomposition(MaximalOrderFinite(F), d[1]);
	assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq d[1];
	assert &*[d^RamificationDegree(d) : d in DD] eq
						MaximalOrderFinite(F)!!d[1];
	assert &and[Minimum(dd) eq d[1]: dd in DD];
	[RamificationDegree(d) : d in DD];
	if #DD eq 1 and RamificationDegree(DD[1]) eq Degree(F) then
	    Append(~split_time, Cputime(start_time));
	else
	    Append(~unram_split_time, Cputime(start_time));
	end if;
    end for;

    D := Factorization(MaximalOrderInfinite(K)*Discriminant(DefiningPolynomial(
    EquationOrderInfinite(F))));
    D;
    Append(~no_splits, #D);
    for d in D[1 .. #D by 2] do
	start_time := Cputime();
	time DD := Decomposition(MaximalOrderInfinite(F), d[1]);
	assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq d[1];
	assert &*[d^RamificationDegree(d) : d in DD] eq
						MaximalOrderInfinite(F)!!d[1];
	assert &and[Minimum(dd) eq d[1]: dd in DD];
	[RamificationDegree(d) : d in DD];
	if #DD eq 1 and RamificationDegree(DD[1]) eq Degree(F) then
	    Append(~split_time, Cputime(start_time));
	else
	    Append(~unram_split_time, Cputime(start_time));
	end if;
    end for;
end for;
no_splits;
split_time;

Cputime(loop_start_time);

/*
assert cpu_times[1] lt 10*export_vb_factor;
assert cpu_times[2] lt 2.5*export_vb_factor;
assert cpu_times[3] lt 0.2*export_vb_factor;
assert cpu_times[4] lt 3*export_vb_factor;
assert cpu_times[5] lt 55*export_vb_factor;
assert cpu_times[6] lt 225*export_vb_factor;
*/

k := GF(5);
kt<t> := FunctionField(k);
kty<y> := PolynomialRing(kt);
K := FunctionField(y^4+3*y+t^2+t+1);
F := ext<K | x^5 + 4*x + 2/(t + 4)*K.1^3 + 4/(t + 4)*K.1^2 + (4*t + 4)/(t + \
4)*K.1 + (t + 
  1)/(t + 4)> where x is PolynomialRing(K).1;
time MaximalOrderFinite(F);
time Factorization(MaximalOrderInfinite(K)*Discriminant(DefiningPolynomial(
EquationOrderInfinite(F))));
time MaximalOrderInfinite(F);
D := Factorization(MaximalOrderFinite(K)*Discriminant(DefiningPolynomial(
EquationOrderFinite(F))));
D;
for d in D[Minimum(2, #D) .. #D by 2] do
    time DD := Decomposition(MaximalOrderFinite(F), d[1]);
    assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq d[1];
    assert &*[d^RamificationDegree(d) : d in DD] eq
					    MaximalOrderFinite(F)!!d[1];
    assert &and[Minimum(dd) eq d[1]: dd in DD];
    [RamificationDegree(d) : d in DD];
end for;
D := Factorization(MaximalOrderInfinite(K)*Discriminant(DefiningPolynomial(
EquationOrderInfinite(F))));
D;
for d in D[1 .. #D by 2] do
    time DD := Decomposition(MaximalOrderInfinite(F), d[1]);
    assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq d[1];
    assert &*[d^RamificationDegree(d) : d in DD] eq
					    MaximalOrderInfinite(F)!!d[1];
    assert &and[Minimum(dd) eq d[1]: dd in DD];
    [RamificationDegree(d) : d in DD];
end for;

/*
F := ext<K | x^5 + 4*x + 2/(t + 4)*K.1^3 + 4/(t + 4)*K.1^2 + (4*t + 4)/(t
+
4)*K.1 + (4*t +
    3)/(t + 4)> where x is PolynomialRing(K).1;
F;
K;
    time MaximalOrderFinite(F);
    time MaximalOrderInfinite(F);
split_time := [];
    D := Factorization(MaximalOrderFinite(K)*Discriminant(DefiningPolynomial(
    EquationOrderFinite(F))));
    D;
    for d in D do
        start_time := Cputime();
        time DD := Decomposition(MaximalOrderFinite(F), d[1]);
        assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq d[1];
        assert &*[d^RamificationDegree(d) : d in DD] eq
                                                MaximalOrderFinite(F)!!d[1];
        assert &and[Minimum(dd) eq d[1]: dd in DD];
        [RamificationDegree(d) : d in DD];
        if #DD eq 1 and RamificationDegree(DD[1]) eq Degree(F) then
            Append(~split_time, Cputime(start_time));
        end if;
    end for;

    D := Factorization(MaximalOrderInfinite(K)*Discriminant(DefiningPolynomial(
    EquationOrderInfinite(F))));
    D;
    EOI := Order(MaximalOrderInfinite(K), Basis(EquationOrderInfinite(F), F) :
                                                                        Order);

    for d in D do
        start_time := Cputime();
        time DD := Decomposition(MaximalOrderInfinite(F), d[1]);
        assert Minimum(&*[d^RamificationDegree(d) : d in DD]) eq d[1];
        assert &*[d^RamificationDegree(d) : d in DD] eq
                                                MaximalOrderInfinite(F)!!d[1];
        assert &and[Minimum(dd) eq d[1]: dd in DD];
        [RamificationDegree(d) : d in DD];
        if #DD eq 1 and RamificationDegree(DD[1]) eq Degree(F) then
            Append(~split_time, Cputime(start_time));
        end if;
    end for;

*/
