# Usage

A semiring over a set $S$ is an algebraic structure $(S, \oplus, \otimes, \bar{0}, \bar{1})$ where $\oplus$ and $\otimes$ are two binary operators called "addition" and "multiplication" and $\bar{0}$ and $\bar{1}$ are their respective neutral element.

## Simple example

Load the module

`using Semirings`

The usual workflow when is to first declare a semiring type and then perform a computation

```
S = LogSemiring{Float64,1}
(S(-2.3) + one(S)) * S(-1)
# output
LogSemiring{Float64, 1}(-0.904454535402037)
```

The neutral elements $\bar{0}$ and $\bar{1}$ can be instantiated with the `zero`

and `one`

functions respectively:

```
S = BoolSemiring
isone(one(S) + one(S)), iszero(zero(S) * one(S))
# output
(true, true)
```

## Input / Output

Semirings can written and read from binary stream

```
S = TropicalSemiring{Float32}
io = IOBuffer()
write(io, S(2.4))
read(seekstart(io), S)
# output
TropicalSemiring{Float32}(2.4f0, 1)
```

It is also possible to create semiring `S<:Semiring{T}`

from a textual representation with `parse`

:

```
S = TropicalSemiring{Float32}
parse(S, "0.123")
# output
TropicalSemiring{Float32}(0.123f0, 1)
```

This will work only if the type `T`

wrapped by semiring type `S`

can be created from `parse`

.

## Automatic Differentiation

Computation over sermiings should be differentiable (for semiring over numeric values) with reverse-mode differentiation backend relying upon ChainRulesCore.jl. Here is an example with Zygote.

```
using Semirings
using Zygote
S = LogSemiring{Float32,2}
gradient(S(1), S(2), S(3)) do x, y , z
val(z * (x + y))
end
# output
(SemiringTangent{Float64}(0.11920294090533493), SemiringTangent{Float64}(0.8807972175070349), SemiringTangent{Float32}(1.0f0))
```

Importantly, the function that needs to be differentiated should return the value of the semiring (not the semiring itself). Hence, your function should end with a call to `val(...)`

.