# Discrete random variables

The joint probability distribution of random variables $X_1, \ldots, X_n$ is given by a tensor of order $n$. If the random variable $X_i$ takes $d_i$ states, the tensor is of format $d_1 \times \cdots \times d_n$ and consists of non-negative real numbers $p_{x_1 \cdots x_n}$, for all choices $x_i \in [d_i]$, which sum to $1$. The functions below deal with the ambient polynomial ring in these $p$ variables, special forms in them like marginals, and conditional independence ideals.

`markov_ring`

— Method```
markov_ring(rvs::Pair{<:VarName, <:AbstractArray}...; unknown::VarName="p", K::Field=QQ, cached=false)::MarkovRing
tensor_ring(rvs::Pair{<:VarName, <:AbstractArray}...; unknown::VarName="p", K::Field=QQ, cached=false)::MarkovRing
```

The polynomial ring whose unknowns are the entries of a probability tensor. `rvs`

is a list of pairs `X => Q`

where `X`

is the name of a random variable and `Q`

is the list of states it takes. The polynomial ring being constructed will have one variable for each element in the cartesian product of the `Q`

s. It is a multivariate polynomial ring whose variables are named `p[...]`

and whose coefficient field `K`

is by default `QQ`

. These settings can be changed via the optional arguments.

If `cached`

is `true`

, the internally generated polynomial ring will be cached.

The name `tensor_ring`

is an alias for the constructor `markov_ring`

because that is really what a `MarkovRing`

is: the coordinate ring of tensors of a fixed format. The name `MarkovRing`

is kept for compatibility in terminology with the Macaulay2 package `GraphicalModels`

.

**Examples**

```
julia> R = markov_ring("A" => 1:2, "B" => 1:2, "X" => 1:2, "Y" => 1:2)
MarkovRing for random variables A -> {1, 2}, B -> {1, 2}, X -> {1, 2}, Y -> {1, 2} in 16 variables over Rational field
```

This function is part of the experimental code in Oscar. Please read here for more details.

This function is part of the experimental code in Oscar. Please read here for more details.

`tensor_ring`

— Method```
markov_ring(rvs::Pair{<:VarName, <:AbstractArray}...; unknown::VarName="p", K::Field=QQ, cached=false)::MarkovRing
tensor_ring(rvs::Pair{<:VarName, <:AbstractArray}...; unknown::VarName="p", K::Field=QQ, cached=false)::MarkovRing
```

The polynomial ring whose unknowns are the entries of a probability tensor. `rvs`

is a list of pairs `X => Q`

where `X`

is the name of a random variable and `Q`

is the list of states it takes. The polynomial ring being constructed will have one variable for each element in the cartesian product of the `Q`

s. It is a multivariate polynomial ring whose variables are named `p[...]`

and whose coefficient field `K`

is by default `QQ`

. These settings can be changed via the optional arguments.

If `cached`

is `true`

, the internally generated polynomial ring will be cached.

The name `tensor_ring`

is an alias for the constructor `markov_ring`

because that is really what a `MarkovRing`

is: the coordinate ring of tensors of a fixed format. The name `MarkovRing`

is kept for compatibility in terminology with the Macaulay2 package `GraphicalModels`

.

**Examples**

```
julia> R = markov_ring("A" => 1:2, "B" => 1:2, "X" => 1:2, "Y" => 1:2)
MarkovRing for random variables A -> {1, 2}, B -> {1, 2}, X -> {1, 2}, Y -> {1, 2} in 16 variables over Rational field
```

This function is part of the experimental code in Oscar. Please read here for more details.

This function is part of the experimental code in Oscar. Please read here for more details.

`ring`

— Method`ring(R::MarkovRing)`

Return the multivariate polynomial ring inside `R`

.

**Examples**

```
julia> R = markov_ring("A" => 1:2, "B" => 1:2, "X" => 1:2, "Y" => 1:2)
MarkovRing for random variables A -> {1, 2}, B -> {1, 2}, X -> {1, 2}, Y -> {1, 2} in 16 variables over Rational field
julia> ring(R)
Multivariate polynomial ring in 16 variables p[1, 1, 1, 1], p[2, 1, 1, 1], p[1, 2, 1, 1], p[2, 2, 1, 1], ..., p[2, 2, 2, 2]
over rational field
```

This function is part of the experimental code in Oscar. Please read here for more details.

`random_variables`

— Method`random_variables(R::MarkovRing)`

Return the list of random variables used to create the MarkovRing.

**Examples**

```
julia> R = markov_ring("A" => 1:2, "B" => 1:2, "X" => 1:2, "Y" => 1:2)
MarkovRing for random variables A -> {1, 2}, B -> {1, 2}, X -> {1, 2}, Y -> {1, 2} in 16 variables over Rational field
julia> random_variables(R)
4-element Vector{Union{Char, AbstractString, Symbol}}:
"A"
"B"
"X"
"Y"
```

This function is part of the experimental code in Oscar. Please read here for more details.

`ci_statements`

— Method`ci_statements(R::MarkovRing)`

Returns all the `CIStmt`

objects which can be formed on the `random_variables(R)`

.

```
julia> R = markov_ring("A" => 1:2, "B" => 1:2, "X" => 1:2, "Y" => 1:2)
MarkovRing for random variables A -> {1, 2}, B -> {1, 2}, X -> {1, 2}, Y -> {1, 2} in 16 variables over Rational field
julia> ci_statements(R)
24-element Vector{CIStmt}:
[A _||_ Y | {}]
[A _||_ Y | B]
[A _||_ Y | X]
[A _||_ Y | {B, X}]
[B _||_ Y | {}]
[B _||_ Y | A]
[B _||_ Y | X]
[B _||_ Y | {A, X}]
[X _||_ Y | {}]
[X _||_ Y | A]
⋮
[A _||_ X | {B, Y}]
[B _||_ X | {}]
[B _||_ X | A]
[B _||_ X | Y]
[B _||_ X | {A, Y}]
[A _||_ B | {}]
[A _||_ B | X]
[A _||_ B | Y]
[A _||_ B | {X, Y}]
```

This function is part of the experimental code in Oscar. Please read here for more details.

`unknowns`

— Method`unknowns(R::MarkovRing)`

Return the generators of the polynomial ring.

**Examples**

```
julia> R = markov_ring("A" => 1:2, "B" => 1:2, "X" => 1:2, "Y" => 1:2)
MarkovRing for random variables A -> {1, 2}, B -> {1, 2}, X -> {1, 2}, Y -> {1, 2} in 16 variables over Rational field
julia> unknowns(R)
Dict{NTuple{4, Int64}, QQMPolyRingElem} with 16 entries:
(2, 2, 2, 2) => p[2, 2, 2, 2]
(2, 2, 2, 1) => p[2, 2, 2, 1]
(1, 2, 1, 2) => p[1, 2, 1, 2]
(1, 2, 1, 1) => p[1, 2, 1, 1]
(2, 2, 1, 2) => p[2, 2, 1, 2]
(2, 2, 1, 1) => p[2, 2, 1, 1]
(1, 1, 2, 2) => p[1, 1, 2, 2]
(1, 1, 2, 1) => p[1, 1, 2, 1]
(2, 1, 2, 2) => p[2, 1, 2, 2]
(2, 1, 2, 1) => p[2, 1, 2, 1]
(1, 1, 1, 2) => p[1, 1, 1, 2]
(1, 1, 1, 1) => p[1, 1, 1, 1]
(1, 2, 2, 2) => p[1, 2, 2, 2]
(1, 2, 2, 1) => p[1, 2, 2, 1]
(2, 1, 1, 2) => p[2, 1, 1, 2]
(2, 1, 1, 1) => p[2, 1, 1, 1]
```

This function is part of the experimental code in Oscar. Please read here for more details.

`gens`

— Method`gens(R::MarkovRing)`

Alias for `unknowns`

. Return generators of the polynomial ring.

This function is part of the experimental code in Oscar. Please read here for more details.

`find_random_variables`

— Method`find_random_variables(R::MarkovRing, K)`

Given a subset `K`

of `random_variables(R)`

return its indices into the data structure `R.random_variables`

.

`find_state`

— Method`find_state(R::MarkovRing, K, x)`

Given a set of random variables `K`

and a joint event `x`

they can take, return the index vector `y`

of `x`

in the data structure `R.state_spaces`

such that `x[i] = R.state_spaces[J[i]][v[i]]`

where `J = find_random_variables(R, K)`

.

`state_space`

— Function`state_space(R::MarkovRing, K=random_variables(R))`

Return all states that the random subvector indexed by `K`

can attain in the ring `R`

. The result is an `Iterators.product`

iterator unless `K`

has only one element in which case it is a vector.

**Examples**

```
julia> R = markov_ring("A" => 1:2, "B" => 1:2, "X" => 1:2, "Y" => 1:2)
MarkovRing for random variables A -> {1, 2}, B -> {1, 2}, X -> {1, 2}, Y -> {1, 2} in 16 variables over Rational field
julia> collect(state_space(R, ["A", "B"]))
2×2 Matrix{Tuple{Int64, Int64}}:
(1, 1) (1, 2)
(2, 1) (2, 2)
```

This function is part of the experimental code in Oscar. Please read here for more details.

`marginal`

— Method`marginal(R::MarkovRing, K, x)`

Return a marginal as a sum of unknowns from `R`

. The argument `K`

lists random variables which are fixed to the event `x`

; all other random variables in `R`

are summed over their respective state spaces.

**Examples**

```
julia> R = markov_ring("A" => 1:2, "B" => 1:2, "X" => 1:2, "Y" => 1:2)
MarkovRing for random variables A -> {1, 2}, B -> {1, 2}, X -> {1, 2}, Y -> {1, 2} in 16 variables over Rational field
julia> marginal(R, ["A", "X"], [1,2])
p[1, 1, 2, 1] + p[1, 2, 2, 1] + p[1, 1, 2, 2] + p[1, 2, 2, 2]
```

This function is part of the experimental code in Oscar. Please read here for more details.

`ci_ideal`

— Method`ci_ideal(R::MarkovRing, stmts)::MPolyIdeal`

Return the ideal for the conditional independence statements given by `stmts`

.

**Examples**

```
julia> R = markov_ring("A" => 1:2, "B" => 1:2, "X" => 1:2)
MarkovRing for random variables A -> {1, 2}, B -> {1, 2}, X -> {1, 2} in 8 variables over Rational field
julia> ci_ideal(R, [CI"X,A|B", CI"X,B|A"])
Ideal generated by
p[1, 1, 1]*p[2, 1, 2] - p[2, 1, 1]*p[1, 1, 2]
p[1, 2, 1]*p[2, 2, 2] - p[2, 2, 1]*p[1, 2, 2]
p[1, 1, 1]*p[1, 2, 2] - p[1, 2, 1]*p[1, 1, 2]
p[2, 1, 1]*p[2, 2, 2] - p[2, 2, 1]*p[2, 1, 2]
```

This function is part of the experimental code in Oscar. Please read here for more details.