Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/TagBot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ on:
types:
- created
workflow_dispatch:
inputs:
lookback:
default: 3
permissions:
actions: read
checks: read
contents: write
deployments: read
issues: read
discussions: read
packages: read
pages: read
pull-requests: read
repository-projects: read
security-events: read
statuses: read
jobs:
TagBot:
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'
Expand Down
38 changes: 22 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
name: CI
on:
- push
- pull_request
push:
branches:
- master
tags: ['*']
pull_request:
workflow_dispatch:
concurrency:
# Skip intermediate builds: always.
# Cancel intermediate builds: only if it is a pull request build.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
jobs:
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
runs-on: ${{ matrix.os }}
timeout-minutes: 60
permissions: # needed to allow julia-actions/cache to proactively delete old caches that it has created
actions: write
contents: read
strategy:
fail-fast: false
matrix:
Expand All @@ -17,24 +30,17 @@ jobs:
arch:
- x64
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: actions/cache@v1
env:
cache-name: cache-artifacts
with:
path: ~/.julia/artifacts
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
restore-keys: |
${{ runner.os }}-test-${{ env.cache-name }}-
${{ runner.os }}-test-
${{ runner.os }}-
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v1
- uses: codecov/codecov-action@v5
with:
file: lcov.info
files: lcov.info
token: ${{ secrets.CODECOV_TOKEN }}
slug: TensorBFS/TropicalNumbers.jl
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ pkg> add TropicalNumbers

A Topical algebra can be described as a tuple $(R, \oplus, \otimes, \mathbb{0}, \mathbb{1})$, where $R$ is the set, $\oplus$ and $\otimes$ are the opeartions and $\mathbb{0}$, $\mathbb{1}$ are their identity element, respectively. In this package, the following tropical algebras are implemented:
* `TropicalAndOr`: $([T, F], \lor, \land, F, T)$;
* `TropicalBitwise`: $(\mathbb{T}, |, \&, 0, \sim 0)$
* `Tropical` (`TropicalMaxPlus`): $(\mathbb{R}, \max, +, -\infty, 0)$;
* `TropicalMinPlus`: $(\mathbb{R}, \min, +, \infty, 0)$;
* `TropicalMaxMul`: $(\mathbb{R}^+, \max, \times, 0, 1)$.
* `TropicalMaxMin`: $(\mathbb{R}^+, \max, \min, -\infty, \infty)$.

```julia
julia> using TropicalNumbers
Expand Down
30 changes: 27 additions & 3 deletions src/TropicalNumbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ export TropicalTypes, AbstractSemiring

export TropicalAndOr
export Tropical, TropicalF64, TropicalF32, TropicalF16, TropicalI64, TropicalI32, TropicalI16
export TropicalMaxMul, TropicalMaxMulF64, TropicalMaxMulF32, TropicalMaxMulF16, TropicalMaxMulI64, TropicalMaxMulI32, TropicalMaxMulI16
export TropicalMaxPlus, TropicalMaxPlusF64, TropicalMaxPlusF32, TropicalMaxPlusF16, TropicalMaxPlusI64, TropicalMaxPlusI32, TropicalMaxPlusI16
export TropicalMinPlus, TropicalMinPlusF64, TropicalMinPlusF32, TropicalMinPlusF16, TropicalMinPlusI64, TropicalMinPlusI32, TropicalMinPlusI16
export TropicalMaxMul, TropicalMaxMulF64, TropicalMaxMulF32, TropicalMaxMulF16, TropicalMaxMulI64, TropicalMaxMulI32, TropicalMaxMulI16
export TropicalMaxMin, TropicalMaxMinF64, TropicalMaxMinF32, TropicalMaxMinF16, TropicalMaxMinI64, TropicalMaxMinI32, TropicalMaxMinI16
export TropicalBitwise, TropicalBitwiseI64, TropicalBitwiseI32, TropicalBitwiseI16
export CountingTropical, CountingTropicalF16, CountingTropicalF32, CountingTropicalF64, CountingTropicalI16, CountingTropicalI32, CountingTropicalI64


Expand Down Expand Up @@ -41,6 +43,8 @@ include("tropical_maxplus.jl")
include("tropical_andor.jl")
include("tropical_minplus.jl")
include("tropical_maxmul.jl")
include("tropical_maxmin.jl")
include("tropical_bitwise.jl")
include("counting_tropical.jl")

const TropicalTypes{T} = Union{CountingTropical{T}, Tropical{T}}
Expand All @@ -53,17 +57,20 @@ for NBIT in [16, 32, 64]
@eval const $(Symbol(:TropicalMaxPlus, :F, NBIT)) = TropicalMaxPlus{$(Symbol(:Float, NBIT))}
@eval const $(Symbol(:TropicalMinPlus, :F, NBIT)) = TropicalMinPlus{$(Symbol(:Float, NBIT))}
@eval const $(Symbol(:TropicalMaxMul, :F, NBIT)) = TropicalMaxMul{$(Symbol(:Float, NBIT))}
@eval const $(Symbol(:TropicalMaxMin, :F, NBIT)) = TropicalMaxMin{$(Symbol(:Float, NBIT))}
@eval const $(Symbol(:CountingTropical, :F, NBIT)) = CountingTropical{$(Symbol(:Float, NBIT)),$(Symbol(:Float, NBIT))}

@eval const $(Symbol(:Tropical, :I, NBIT)) = Tropical{$(Symbol(:Int, NBIT))}
@eval const $(Symbol(:TropicalMaxPlus, :I, NBIT)) = TropicalMaxPlus{$(Symbol(:Int, NBIT))}
@eval const $(Symbol(:TropicalMinPlus, :I, NBIT)) = TropicalMinPlus{$(Symbol(:Int, NBIT))}
@eval const $(Symbol(:TropicalMaxMul, :I, NBIT)) = TropicalMaxMul{$(Symbol(:Int, NBIT))}
@eval const $(Symbol(:TropicalMaxMin, :I, NBIT)) = TropicalMaxMin{$(Symbol(:Int, NBIT))}
@eval const $(Symbol(:TropicalBitwise, :I, NBIT)) = TropicalBitwise{$(Symbol(:Int, NBIT))}
@eval const $(Symbol(:CountingTropical, :I, NBIT)) = CountingTropical{$(Symbol(:Int, NBIT)),$(Symbol(:Float, NBIT))}
end

# alias
for T in [:Tropical, :TropicalMaxMul, :TropicalMinPlus, :CountingTropical]
for T in [:Tropical, :TropicalMaxMul, :TropicalMaxMin, :CountingTropical]
for OP in [:>, :<, :(==), :>=, :<=, :isless]
@eval Base.$OP(a::$T, b::$T) = $OP(a.n, b.n)
end
Expand All @@ -76,6 +83,16 @@ for T in [:Tropical, :TropicalMaxMul, :TropicalMinPlus, :CountingTropical]
end
end

for T in [:TropicalMinPlus, :TropicalBitwise]
@eval begin
content(x::$T) = x.n
content(x::Type{$T{X}}) where X = X
Base.isapprox(x::AbstractArray{<:$T}, y::AbstractArray{<:$T}; kwargs...) = all(isapprox.(x, y; kwargs...))
Base.show(io::IO, ::MIME"text/plain", t::$T) = Base.show(io, t)
Base.isnan(x::$T) = isnan(content(x))
end
end

for T in [:TropicalAndOr]
for OP in [:>, :<, :(==), :>=, :<=, :isless]
@eval Base.$OP(a::$T, b::$T) = $OP(a.n, b.n)
Expand All @@ -88,7 +105,7 @@ for T in [:TropicalAndOr]
end
end

for T in [:Tropical, :TropicalMaxMul, :TropicalMinPlus, :CountingTropical]
for T in [:Tropical, :TropicalMinPlus, :TropicalMaxMul, :CountingTropical]
@eval begin
# this is for CUDA matmul
Base.:(*)(a::$T, b::Bool) = b ? a : zero(a)
Expand All @@ -100,4 +117,11 @@ for T in [:Tropical, :TropicalMaxMul, :TropicalMinPlus, :CountingTropical]
end
end

for T in [:TropicalMaxMin, :TropicalBitwise]
@eval begin
Base.:(*)(a::$T, b::Bool) = b ? a : zero(a)
Base.:(*)(b::Bool, a::$T) = b ? a : zero(a)
end
end

end # module
2 changes: 2 additions & 0 deletions src/tropical_andor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ It maps
* `1` to `true` in regular algebra,
* `0` to `false` in regular algebra.

For the parallel bit-wise version, see [`TropicalBitwise`](@ref).

Example
-------------------------
```jldoctest; setup=:(using TropicalNumbers)
Expand Down
110 changes: 110 additions & 0 deletions src/tropical_bitwise.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
"""
TropicalBitwise{T} <: AbstractSemiring

`TropicalBitwise` is a semiring algebra that parallelizes the [`TropicalAndOr`](@ref) algebra,
It can be described by
* TropicalBitwise, (ℝ, |, &, 0, ~0).

It maps
* `+` to `|`
* `*` to `&`
* `0` to `0`
* `1` to `~0`

Example
-------------------------
```jldoctest; setup=:(using TropicalNumbers)
julia> TropicalBitwise(1) + TropicalBitwise(3)
3ₛ

julia> TropicalBitwise(1) * TropicalBitwise(3)
1ₛ

julia> zero(TropicalBitwiseI64)
0ₛ

julia> one(TropicalBitwiseI64)
-1ₛ
```
"""
struct TropicalBitwise{T} <: AbstractSemiring
n::T
end

function TropicalBitwise(a::TropicalBitwise)
return TropicalBitwise(a.n)
end

function TropicalBitwise{T}(a::TropicalBitwise) where {T}
return TropicalBitwise{T}(a.n)
end

function Base.show(io::IO, a::TropicalBitwise)
print(io, "$(a.n)ₛ")
return
end

function Base.isapprox(a::TropicalBitwise, b::TropicalBitwise; kw...)
return isapprox(a.n, b.n; kw...)
end

function Base.promote_rule(::Type{TropicalBitwise{U}}, ::Type{TropicalBitwise{V}}) where {U, V}
W = promote_type(U, V)
return TropicalBitwise{W}
end

function Base.:+(a::TropicalBitwise, b::TropicalBitwise)
n = a.n | b.n
return TropicalBitwise(n)
end

function Base.:*(a::TropicalBitwise, b::TropicalBitwise)
n = a.n & b.n
return TropicalBitwise(n)
end

function Base.zero(::Type{T}) where {T <: TropicalBitwise}
return typemin(T)
end

function Base.zero(::T) where {T <: TropicalBitwise}
return zero(T)
end

function Base.one(::Type{T}) where {T <: TropicalBitwise}
return typemax(T)
end

function Base.one(::T) where {T <: TropicalBitwise}
return one(T)
end

function Base.typemin(::Type{TropicalBitwise{T}}) where {T}
n = zero(T)
return TropicalBitwise(n)
end

function Base.typemax(::Type{TropicalBitwise{T}}) where {T}
n = ~zero(T)
return TropicalBitwise(n)
end

function Base.:(==)(a::TropicalBitwise, b::TropicalBitwise)
return a.n == b.n
end

function Base.:>=(a::TropicalBitwise, b::TropicalBitwise)
return b.n <= a.n
end

function Base.:<=(a::TropicalBitwise, b::TropicalBitwise)
return a.n | b.n == b.n
end

function Base.:<(a::TropicalBitwise, b::TropicalBitwise)
return a != b && a <= b
end

function Base.:>(a::TropicalBitwise, b::TropicalBitwise)
return b < a
end
89 changes: 89 additions & 0 deletions src/tropical_maxmin.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"""
TropicalMaxMin{T} <: AbstractSemiring

TropicalMaxMin is a semiring algebra, can be described by
* TropicalMaxMin, (ℝ, max, min, -Inf, Inf).

It maps
* `+` to `max` in regular algebra,
* `*` to `min` in regular algebra,
* `0` to `-Inf` in regular algebra (for integer content types, this is a small integer).
* `1` to `Inf` in regular algebra, (for integer content types, this is a large integer)

Example
-------------------------
```jldoctest; setup=:(using TropicalNumbers)
julia> TropicalMaxMin(1.0) + TropicalMaxMin(3.0)
3.0ₛ

julia> TropicalMaxMin(1.0) * TropicalMaxMin(3.0)
1.0ₛ

julia> zero(TropicalMaxMinF64)
-Infₛ

julia> one(TropicalMaxMinF64)
Infₛ
```
"""
struct TropicalMaxMin{T} <: AbstractSemiring
n::T
end

function TropicalMaxMin(a::TropicalMaxMin)
return TropicalMaxMin(a.n)
end

function TropicalMaxMin{T}(a::TropicalMaxMin) where {T}
return TropicalMaxMin{T}(a.n)
end

function Base.show(io::IO, a::TropicalMaxMin)
print(io, "$(a.n)ₛ")
return
end

function Base.isapprox(a::TropicalMaxMin, b::TropicalMaxMin; kw...)
return isapprox(a.n, b.n; kw...)
end

function Base.promote_rule(::Type{TropicalMaxMin{U}}, ::Type{TropicalMaxMin{V}}) where {U, V}
W = promote_type(U, V)
return TropicalMaxMin{W}
end

function Base.:+(a::TropicalMaxMin, b::TropicalMaxMin)
n = max(a.n, b.n)
return TropicalMaxMin(n)
end

function Base.:*(a::TropicalMaxMin, b::TropicalMaxMin)
n = min(a.n, b.n)
return TropicalMaxMin(n)
end

function Base.zero(::Type{T}) where {T <: TropicalMaxMin}
return typemin(T)
end

function Base.zero(::T) where {T <: TropicalMaxMin}
return zero(T)
end

function Base.one(::Type{T}) where {T <: TropicalMaxMin}
return typemax(T)
end

function Base.one(::T) where {T <: TropicalMaxMin}
return one(T)
end

function Base.typemin(::Type{TropicalMaxMin{T}}) where {T}
n = neginf(T)
return TropicalMaxMin(n)
end

function Base.typemax(::Type{TropicalMaxMin{T}}) where {T}
n = posinf(T)
return TropicalMaxMin(n)
end
Loading