# Affine schemes

Let $\mathbb k$ be a commutative noetherian base ring (in practice: an algebraic extension of $\mathbb Q$ or $\mathbb F_p$). We support functionality for affine schemes $X = \mathrm{Spec}(R)$ over $\mathbb k$. Currently, we support rings $R$ of type `MPolyRing`

, `MPolyQuoRing`

, `MPolyLocRing`

, and `MPolyQuoLocRing`

defined over the integers, a finite field or algebraic field extensions of $\mathbb Q$

## Constructors

### General constructors

Besides `spec(R)`

for `R`

of either one of the types `MPolyRing`

, `MPolyQuoRing`

, `MPolyLocRing`

, or `MPolyQuoLocRing`

, we have the following constructors:

`spec`

— Method`spec(R::MPolyRing, I::MPolyIdeal)`

Construct the affine scheme of the ideal $I$ in the ring $R$. This is the spectrum of the quotient ring $R/I$.

**Examples**

```
julia> R, (x, y) = polynomial_ring(QQ, ["x", "y"]);
julia> I = ideal(R, [x]);
julia> spec(R, I)
Spectrum
of quotient
of multivariate polynomial ring in 2 variables x, y
over rational field
by ideal (x)
```

`spec`

— Method`spec(R::MPolyRing, U::AbsMPolyMultSet)`

Given a polynomial ring $R$, we can localize that polynomial ring at a multiplicatively closed subset $U$ of $R$. The spectrum of the localized ring $U^{-1} R$ is computed by this method.

**Examples**

```
julia> R, (x, y) = polynomial_ring(QQ, ["x", "y"]);
julia> I = ideal(R, [x]);
julia> U = complement_of_prime_ideal(I);
julia> spec(R, U)
Spectrum
of localization
of multivariate polynomial ring in 2 variables x, y
over rational field
at complement of prime ideal (x)
```

`spec`

— Method`spec(R::MPolyRing, I::MPolyIdeal, U::AbsMPolyMultSet)`

We allow to combine quotients and localizations at the same time. That is, consider a polynomial ring $R$, an ideal $I$ of $R$ and a multiplicatively closed subset $U$ of $R$. The spectrum of the localized ring $U^{-1} (R/I)$ is computed by this method.

**Examples**

```
julia> R, (x, y) = polynomial_ring(QQ, ["x", "y"]);
julia> I = ideal(R, [x]);
julia> U = complement_of_prime_ideal(ideal(R, [y]));
julia> spec(R, I, U)
Spectrum
of localization
of quotient
of multivariate polynomial ring in 2 variables x, y
over rational field
by ideal (x)
at complement of prime ideal (y)
```

See `inclusion_morphism(::AbsAffineScheme, ::AbsAffineScheme)`

for a way to obtain the ideal $I$ from $X = \mathrm{Spec}(R, I)$.

### Affine n-space

`affine_space`

— Method`affine_space(kk::BRT, n::Int; variable_name="x") where {BRT<:Ring}`

The $n$-dimensional affine space over a ring $kk$ is created by this method. By default, the variable names are chosen as `x1`

, `x2`

and so on. This choice can be overwritten with a third optional argument.

**Examples**

```
julia> affine_space(QQ, 5)
Affine space of dimension 5
over rational field
with coordinates [x1, x2, x3, x4, x5]
julia> affine_space(QQ,5,variable_name="y")
Affine space of dimension 5
over rational field
with coordinates [y1, y2, y3, y4, y5]
```

`affine_space`

— Method`affine_space(kk::BRT, var_names::AbstractVector{<:VarName}) where {BRT<:Ring}`

Create the $n$-dimensional affine space over a ring $kk$, but allows more flexibility in the choice of variable names. The following example demonstrates this.

**Examples**

```
julia> affine_space(QQ, [:x, :y, :z])
Affine space of dimension 3
over rational field
with coordinates [x, y, z]
julia> affine_space(QQ, ['x', 'y', 'z'])
Affine space of dimension 3
over rational field
with coordinates [x, y, z]
julia> affine_space(QQ, ["x", "y", "z"])
Affine space of dimension 3
over rational field
with coordinates [x, y, z]
```

### Closed subschemes

`subscheme`

— Method`subscheme(X::AbsAffineScheme, f::Vector{<:RingElem})`

For an affine spectrum $X$ and elements $f_1$, $f_2$, etc. of the coordinate ring of $X$, this method computes the subscheme $V(f_1, f_2, \dots)$ of $X$.

**Examples**

```
julia> X = affine_space(QQ,3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> R = OO(X)
Multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
julia> (x1,x2,x3) = gens(R)
3-element Vector{QQMPolyRingElem}:
x1
x2
x3
julia> subscheme(X,x1)
Spectrum
of quotient
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
by ideal (x1)
julia> subscheme(X,[x1,x2])
Spectrum
of quotient
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
by ideal (x1, x2)
```

`subscheme`

— Method`subscheme(X::AbsAffineScheme, I::Ideal)`

For a scheme $X = Spec(R)$ and an ideal $I ⊂ 𝒪(X)$, return the closed subscheme defined by $I$.

**Examples**

```
julia> X = affine_space(QQ,3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> R = OO(X)
Multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
julia> (x1,x2,x3) = gens(R)
3-element Vector{QQMPolyRingElem}:
x1
x2
x3
julia> subscheme(X,ideal(R,[x1*x2]))
Spectrum
of quotient
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
by ideal (x1*x2)
```

### Intersections

`intersect`

— Method`Base.intersect(X::AbsAffineScheme, Y::AbsAffineScheme)`

This method computes the intersection to two affine schemes that reside in the same ambient affine space.

**Examples**

```
julia> X = affine_space(QQ,3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> R = OO(X)
Multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
julia> (x1,x2,x3) = gens(R)
3-element Vector{QQMPolyRingElem}:
x1
x2
x3
julia> Y1 = subscheme(X,[x1])
Spectrum
of quotient
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
by ideal (x1)
julia> Y2 = subscheme(X,[x2])
Spectrum
of quotient
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
by ideal (x2)
julia> intersect(Y1, Y2)
Spectrum
of quotient
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
by ideal (x1, x2)
```

### Open subschemes

`hypersurface_complement`

— Method`hypersurface_complement(X::AbsAffineScheme, f::RingElem)`

For a scheme $X = Spec(R)$ and an element $f ∈ R$, return the open subscheme $U = Spec(R[f⁻¹]) = X ∖ V(f)$ defined by the complement of the vanishing locus of $f$.

**Examples**

```
julia> X = affine_space(QQ,3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> R = OO(X)
Multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
julia> (x1, x2, x3) = gens(R)
3-element Vector{QQMPolyRingElem}:
x1
x2
x3
julia> hypersurface_complement(X, x1)
Spectrum
of localization
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
at products of (x1)
```

`hypersurface_complement`

— Method`hypersurface_complement(X::AbsAffineScheme, f::Vector{<:RingElem})`

For a scheme $X = Spec(R)$ and elements $f₁, f₂, ... ∈ R$, return the open subscheme $U = Spec(R[f₁⁻¹,f₂⁻¹, ...]) = X ∖ V(f₁⋅f₂⋅…)$ defined by the complement of the vanishing locus of the product $f₁⋅f₂⋅…$.

**Examples**

```
julia> X = affine_space(QQ,3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> R = OO(X)
Multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
julia> (x1,x2,x3) = gens(R)
3-element Vector{QQMPolyRingElem}:
x1
x2
x3
julia> hypersurface_complement(X,[x1,x2])
Spectrum
of localization
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
at products of (x1, x2)
```

### Closure

`closure`

— Method`closure(X::AbsAffineScheme, Y::AbsAffineScheme)`

Return the closure of $X$ in $Y$.

**Examples**

```
julia> X = affine_space(QQ,3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> R = OO(X)
Multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
julia> (x1,x2,x3) = gens(R)
3-element Vector{QQMPolyRingElem}:
x1
x2
x3
julia> H = subscheme(X,ideal(R,[x1]))
Spectrum
of quotient
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
by ideal (x1)
julia> closure(H, X)
Spectrum
of quotient
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
by ideal (x1)
```

## Attributes

### Ambient affine space

Most affine schemes in Oscar $X = \mathrm{Spec}(R)$ over a ring $B$, come with an embedding into an affine space $\mathbb{A}_B$. More precisely, `ambient_space(X)`

is defined for `X = spec(R)`

if `R`

is constructed from a polynomial ring. In particular $\mathrm{Spec}(\mathbb{Z})$ or $\mathrm{Spec}(\mathbb{k})$ for $\mathbb k$ a field do not have an ambient affine space.

`ambient_space`

— Method`ambient_space(X::AbsAffineScheme)`

Return the ambient affine space of $X$.

Use `ambient_embedding(::AbsAffineScheme)`

to obtain the embedding of $X$ in its ambient affine space.

**Examples**

```
julia> X = affine_space(QQ, [:x,:y])
Affine space of dimension 2
over rational field
with coordinates [x, y]
julia> ambient_space(X) == X
true
julia> (x, y) = coordinates(X);
julia> Y = subscheme(X, [x])
Spectrum
of quotient
of multivariate polynomial ring in 2 variables x, y
over rational field
by ideal (x)
julia> X == ambient_space(Y)
true
julia> Z = subscheme(Y, y)
Spectrum
of quotient
of multivariate polynomial ring in 2 variables x, y
over rational field
by ideal (x, y)
julia> ambient_space(Z) == X
true
julia> V = hypersurface_complement(Y, y)
Spectrum
of localization
of quotient
of multivariate polynomial ring in 2 variables x, y
over rational field
by ideal (x)
at products of (y)
julia> ambient_space(V) == X
true
```

We can create $X$, $Y$ and $Z$ also by first constructing the corresponding coordinate rings. The subset relations are inferred from the coordinate rings. More precisely, for a polynomial ring $P$ an ideal $I ⊆ P$ and a multiplicatively closed subset $U$ of $P$ let $R$ be one of $P$, $U^{-1}P$, $P/I$ or $U^{-1}(P/I)$. In each case the ambient affine space is given by `Spec(P)`

.

**Examples**

```
julia> P, (x, y) = polynomial_ring(QQ, [:x, :y])
(Multivariate polynomial ring in 2 variables over QQ, QQMPolyRingElem[x, y])
julia> X = spec(P)
Spectrum
of multivariate polynomial ring in 2 variables x, y
over rational field
julia> I = ideal(P, x)
Ideal generated by
x
julia> RmodI, quotient_map = quo(P, I);
julia> Y = spec(RmodI)
Spectrum
of quotient
of multivariate polynomial ring in 2 variables x, y
over rational field
by ideal (x)
julia> ambient_space(Y) == X
true
julia> J = ideal(RmodI, y);
julia> RmodJ, quotient_map2 = quo(RmodI, J);
julia> Z = spec(RmodJ)
Spectrum
of quotient
of multivariate polynomial ring in 2 variables x, y
over rational field
by ideal (x, y)
julia> ambient_space(Z) == X
true
julia> U = powers_of_element(y)
Multiplicative subset
of multivariate polynomial ring in 2 variables over QQ
given by the products of [y]
julia> URmodI, _ = localization(RmodI, U);
julia> V = spec(URmodI)
Spectrum
of localization
of quotient
of multivariate polynomial ring in 2 variables x, y
over rational field
by ideal (x)
at products of (y)
julia> ambient_space(V) == X
true
```

Note: compare with `==`

, as the same affine space could be represented internally by different objects for technical reasons.

**Examples**

```
julia> AX = ambient_space(X);
julia> AY = ambient_space(Y);
julia> AX == AY
true
julia> AX === AY
false
```

### Other attributes

`base_ring`

— Method`base_ring(M::PMat)`

The `PMat`

$M$ defines an $R$-module for some maximal order $R$. This function returns the $R$ that was used to defined $M$.

`base_ring(I::MPolyIdeal)`

Return the ambient ring of `I`

.

**Examples**

```
julia> R, (x, y) = polynomial_ring(QQ, ["x", "y"])
(Multivariate polynomial ring in 2 variables over QQ, QQMPolyRingElem[x, y])
julia> I = ideal(R, [x, y])^2
Ideal generated by
x^2
x*y
y^2
julia> base_ring(I)
Multivariate polynomial ring in 2 variables x, y
over rational field
```

`base_ring(X::AbsAffineScheme)`

On an affine scheme $X/𝕜$ over $𝕜$ this returns the ring $𝕜$.

**Examples**

```
julia> X = affine_space(QQ,3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> base_ring(X)
Rational field
```

`codim`

— Method`codim(X::AbsAffineScheme)`

Return the codimension of $X$ in its ambient affine space.

Throws and error if $X$ does not have an ambient affine space.

**Examples**

```
julia> X = affine_space(QQ,3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> codim(X)
0
julia> R = OO(X)
Multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
julia> (x1,x2,x3) = gens(R)
3-element Vector{QQMPolyRingElem}:
x1
x2
x3
julia> Y = subscheme(X, x1)
Spectrum
of quotient
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
by ideal (x1)
julia> codim(Y)
1
```

`ambient_embedding`

— Method`ambient_embedding(X::AbsAffineScheme)`

Return the embedding of $X$ in its ambient affine space.

**Examples**

```
julia> X = affine_space(QQ, [:x,:y])
Affine space of dimension 2
over rational field
with coordinates [x, y]
julia> (x, y) = coordinates(X);
julia> Y = subscheme(X, [x])
Spectrum
of quotient
of multivariate polynomial ring in 2 variables x, y
over rational field
by ideal (x)
julia> inc = ambient_embedding(Y)
Affine scheme morphism
from [x, y] scheme(x)
to [x, y] affine 2-space over QQ
given by the pullback function
x -> 0
y -> y
julia> inc == inclusion_morphism(Y, X)
true
```

`dim`

— Method`dim(X::AbsAffineScheme)`

Return the dimension the affine scheme $X = Spec(R)$.

By definition, this is the Krull dimension of $R$.

**Examples**

```
julia> X = affine_space(QQ,3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> dim(X)
3
julia> Y = affine_space(ZZ, 2)
Spectrum
of multivariate polynomial ring in 2 variables x1, x2
over integer ring
julia> dim(Y) # one dimension comes from ZZ and two from x1 and x2
3
```

`name`

— Method`name(X::AbsAffineScheme)`

Return the current name of an affine scheme.

This name can be specified via `set_name!`

.

**Examples**

```
julia> X = affine_space(QQ, 3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> name(X)
"unnamed affine variety"
julia> set_name!(X, "affine 3-dimensional space")
julia> name(X)
"affine 3-dimensional space"
```

`OO`

— Method`OO(X::AbsAffineScheme)`

On an affine scheme $X = Spec(R)$, return the ring $R$.

### Type getters

We support functions which return the types of schemes, associated rings, and their elements. See the source code for details.

## Properties

`is_open_embedding`

— Method`is_open_embedding(X::AbsAffineScheme, Y::AbsAffineScheme)`

Checks whether $X$ is openly embedded in $Y$.

**Examples**

```
julia> X = affine_space(QQ,3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> R = OO(X)
Multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
julia> (x1,x2,x3) = gens(R)
3-element Vector{QQMPolyRingElem}:
x1
x2
x3
julia> Y = subscheme(X,ideal(R,[x1*x2]))
Spectrum
of quotient
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
by ideal (x1*x2)
julia> is_open_embedding(Y, X)
false
julia> Z = hypersurface_complement(X, x1)
Spectrum
of localization
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
at products of (x1)
julia> is_open_embedding(Z, X)
true
```

`is_closed_embedding`

— Method`is_closed_embedding(X::AbsAffineScheme, Y::AbsAffineScheme)`

Checks whether $X$ is closed embedded in $Y$.

**Examples**

```
julia> X = affine_space(QQ,3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> R = OO(X)
Multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
julia> (x1,x2,x3) = gens(R)
3-element Vector{QQMPolyRingElem}:
x1
x2
x3
julia> Y = subscheme(X,ideal(R,[x1*x2]))
Spectrum
of quotient
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
by ideal (x1*x2)
julia> is_closed_embedding(Y, X)
true
julia> Z = hypersurface_complement(X, x1)
Spectrum
of localization
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
at products of (x1)
julia> is_closed_embedding(Z, X)
false
```

`isempty`

— Method`is_empty(X::AbsAffineScheme)`

Check whether the affine scheme $X$ is empty.

**Examples**

```
julia> X = affine_space(QQ,3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> isempty(X)
false
julia> is_empty(subscheme(X, one(OO(X))))
true
julia> isempty(EmptyScheme(QQ))
true
```

`is_subscheme`

— Method`is_subscheme(X::AbsAffineScheme, Y::AbsAffineScheme)`

Check whether $X$ is a subset of $Y$ based on the comparison of their coordinate rings. See `inclusion_morphism(::AbsAffineScheme, ::AbsAffineScheme)`

for the corresponding morphism.

**Examples**

```
julia> X = affine_space(QQ,3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> R = OO(X)
Multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
julia> (x1,x2,x3) = gens(R)
3-element Vector{QQMPolyRingElem}:
x1
x2
x3
julia> Y = subscheme(X,ideal(R,[x1*x2]))
Spectrum
of quotient
of multivariate polynomial ring in 3 variables x1, x2, x3
over rational field
by ideal (x1*x2)
julia> is_subscheme(X, Y)
false
julia> is_subscheme(Y, X)
true
```

## Methods

`tangent_space`

— Method`tangent_space(X::AbsAffineScheme{<:Field}, P::AbsAffineRationalPoint) -> AlgebraicSet`

Return the Zariski tangent space of `X`

at its rational point `P`

.

`is_normal`

— Method`is_normal(X::AbsAffineScheme; check::Bool=true) -> Bool`

**Input:**

- a reduced scheme $X$,
- if
`check`

is`true`

, then confirm that $X$ is reduced; this is expensive.

**Output:**

Returns whether the scheme $X$ is normal.

**Examples**

```
julia> R, (x, y, z) = rational_field()["x", "y", "z"];
julia> X = spec(R);
julia> is_normal(X)
true
```

`normalization`

— Method`normalization(X::AbsAffineScheme) -> Vector{Tuple{AbsAffineScheme, AbsAffineSchemeMor}}`

Return the normalization of the reduced affine scheme $X$.

**Input:**

- A reduced affine scheme $X$
- if
`check`

is`true`

confirm that $X$ is reduced; this is expensive - the keyword argument
`algorithm`

is passed on to`normalization(::MPolyQuoRing)`

**Output:**

A list of pairs $(Y_i, f_i)$ where $Y_i$ is a normal scheme and $f_i$ is a morphism from $Y_i$ to $X$. The disjoint union of the $Y_i$ is the normalization of $X$ and the $f_i$ are the restrictions of the normalization morphism to $Y_i$.

### Comparison

Two schemes $X$ and $Y$ can be compared if their ambient affine spaces are equal. In particular $X$ and $Y$ are considered equal (`==`

) if and only if the identity morphism of their ambient affine space induces an isomorphism of $X$ and $Y$. For $X$ and $Y$ with different ambient affine space `X==Y`

is always `false`

.

### Auxiliary methods

`is_non_zero_divisor`

— Method`is_non_zero_divisor(f::RingElem, X::AbsAffineScheme)`

Checks if a ring element is a non-zero divisor in the coordinate ring of an affine scheme.

**Examples**

```
julia> X = affine_space(QQ,3)
Affine space of dimension 3
over rational field
with coordinates [x1, x2, x3]
julia> (x1, x2, x3) = gens(OO(X))
3-element Vector{QQMPolyRingElem}:
x1
x2
x3
julia> is_non_zero_divisor(x1, X)
true
julia> is_non_zero_divisor(zero(OO(X)), X)
false
```