Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linear combinations of set partitions #3944

Merged
merged 31 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d487544
Linear Combinations for Partitions (from december 23)
sebvz777 Jun 13, 2024
ebe1b41
Doctest partially fixed, tests added, renaming
sebvz777 Jun 14, 2024
a307173
deepcopy, fixed test, hash
sebvz777 Jun 18, 2024
e6d82e9
minor comments
sebvz777 Jul 2, 2024
ac62a5a
comments, renaming, test, scale fix, using linear_partition ...
sebvz777 Jul 8, 2024
4127075
return stmt
sebvz777 Jul 8, 2024
b21bb58
cite and get_coefficients
sebvz777 Jul 16, 2024
ac1682f
Merge branch 'oscar-system:master' into sv/LinearComb
sebvz777 Jul 16, 2024
ba5188a
comments
sebvz777 Jul 16, 2024
0636ae8
readme
sebvz777 Jul 16, 2024
3571eaa
import coefficients
sebvz777 Jul 16, 2024
9842ff4
test fix
sebvz777 Jul 16, 2024
a6d8169
iszerro
sebvz777 Jul 16, 2024
d963179
doctest fixes
sebvz777 Jul 16, 2024
e4fe5a5
trying to fix doctest
sebvz777 Jul 17, 2024
b08bef8
doctest fix 2.0
sebvz777 Jul 17, 2024
de2835c
S(X) -> X for doctest
sebvz777 Jul 23, 2024
9fb5313
removed add and substract
sebvz777 Jul 23, 2024
3028f5a
doctest without line breaks
sebvz777 Jul 24, 2024
97a9b63
feedback implementation part 1
sebvz777 Jul 25, 2024
9e08dcd
Update experimental/SetPartitions/src/LinearSetPartition.jl
pinguly Jul 25, 2024
80ad141
rename to LinearPartition, implement base_ring, fix some docstrings
pinguly Jul 26, 2024
91fb265
minor doctest fix for simplify operation and linear_partition
sebvz777 Jul 26, 2024
78e8574
Update experimental/SetPartitions/src/LinearPartition.jl
sebvz777 Jul 30, 2024
25a827f
Update experimental/SetPartitions/src/LinearPartition.jl
sebvz777 Jul 30, 2024
b72f932
Update experimental/SetPartitions/src/LinearPartition.jl
sebvz777 Jul 30, 2024
4069c34
Update experimental/SetPartitions/src/Util.jl
sebvz777 Jul 30, 2024
1721c84
fixing SetPartition reference in doctest and RingElem
sebvz777 Jul 31, 2024
6e8db15
fix base_ring_type import
pinguly Jul 31, 2024
d6de93e
docstring improvements, renaming LinearComb-test to LinearPartition-t…
sebvz777 Aug 26, 2024
5c3e20a
Update experimental/SetPartitions/src/Util.jl
lgoettgens Aug 26, 2024
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
3 changes: 0 additions & 3 deletions experimental/SetPartitions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ This includes:
* basic set-partitions and operations on them (e.g. composition, tensor product, involution)
* variations like colored partitions [TW18](@cite) and spatial partitions [CW16](@cite)
* enumeration of partitions which can be constructed from a set of generators

In the future, we plan to implement:
* linear combinations of partitions
* examples of tensor categories in the framework of [TensorCategories.jl](https://github.com/FabianMaeurer/TensorCategories.jl)

## Contact

Expand Down
241 changes: 241 additions & 0 deletions experimental/SetPartitions/src/LinearSetPartition.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
"""
LinearSetPartition

LinearSetPartition represents a linear combination of set-partitions. See Chapter 5 in [Gro20](@cite).
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
"""
struct LinearSetPartition{S <: AbstractPartition, T <: RingElement}
coefficients :: Dict{S, T}
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved

function LinearSetPartition{S, T}(coeffs::Dict{S, T}) where {S <: AbstractPartition, T <: RingElement}
return new(simplify_operation_zero(coeffs))
end
end

"""
linear_partition(coeffs::Dict{S, T}) where {S <: AbstractPartition, T <: RingElement}

Initialize LinearSetPartition object, while simplifying the term.

# Examples
```jldoctest
julia> S, d = polynomial_ring(QQ, "d")
(Univariate polynomial ring in x over QQ, d)
julia> linear_partition(Dict(set_partition([1, 2], [1, 1]) => S(4), set_partition([1, 1], [1, 1]) => 4*d))
LinearSetPartition(Dict(set_partition([1, 2], [1, 1]) => S(4), set_partition([1, 1], [1, 1]) => 4*d))
"""
function linear_partition(coeffs::Dict{S, T}) where {S <: AbstractPartition, T <: RingElement}
return LinearSetPartition{S, T}(coeffs)
end

"""
coefficients(p::LinearSetPartition{S, T}) where { S <: AbstractPartition, T <: RingElement }

Get the constructor field `coefficients`, the partition term, in form of a `Dict` from
`SetPartition` to coefficient.
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
"""
function coefficients(p::LinearSetPartition{S, T}) where { S <: AbstractPartition, T <: RingElement }
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
return p.coefficients
end

function hash(p::LinearSetPartition, h::UInt)
return hash(coefficients(p), h)
end

function ==(p::LinearSetPartition{S, T}, q::LinearSetPartition{S, T}) where
{ S <: AbstractPartition, T <: RingElement }
return coefficients(p) == coefficients(q)
end

function deepcopy_internal(p::LinearSetPartition, stackdict::IdDict)
if haskey(stackdict, p)
return stackdict[p]
end
q = linear_partition(deepcopy_internal(coefficients(p), stackdict))
stackdict[p] = q
return q
end

"""
linear_partition(term::Vector{Tuple{S, T}}) where { S <: AbstractPartition, T <: RingElement }

Return a `LinearSetPartition` generated from the Vector `term` of 2-tuples,
where the first element in the tuple is a `RingElement` and the second
a `SetPartition`. Furthermore simplify the term before initializing
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
the `LinearSetPartition` object with the corresponding dict.

# Examples
```jldoctest
julia> S, d = polynomial_ring(QQ, "d")
(Univariate polynomial ring in x over QQ, d)
julia> linear_partition([(set_partition([1, 1], [1, 1]), S(4)), (set_partition([1, 1], [1, 1]), 4*d)])
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
LinearSetPartition(Dict(set_partition([1, 1], [1, 1]) => 4 + 4*d))
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
```
"""
function linear_partition(term::Vector{Tuple{S, T}}) where { S <: AbstractPartition, T <: RingElement }
return linear_partition(Dict{S, T}(x[1] => x[2] for x in simplify_operation(term)))
end

"""
add(p::LinearSetPartition{S, T}, q::LinearSetPartition{S, T}) where
{ S <: AbstractPartition, T <: RingElement }

Return the addition between `p` and `q`.

# Examples
```jldoctest
julia> S, d = polynomial_ring(QQ, "d")
(Univariate polynomial ring in x over QQ, d)
julia> a = linear_partition([(set_partition([1, 2], [1, 1]), S(4)),
(set_partition([1, 1], [1, 1]), 4*d)])
julia> add(a, a)
LinearSetPartition(Dict(set_partition([1, 2], [1, 1]) => S(8),
SetPartition([1, 1], [1, 1]) => 8*d))
```
"""
function add(p::LinearSetPartition{S, T}, q::LinearSetPartition{S, T}) where
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
{ S <: AbstractPartition, T <: RingElement }

result = deepcopy(p)
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved

for i in pairs(coefficients(q))
coefficients(result)[i[1]] = get(coefficients(result), i[1], 0) + i[2]
end

return linear_partition(coefficients(result))
end

function +(p::LinearSetPartition{S, T}, q::LinearSetPartition{S, T}) where
{ S <: AbstractPartition, T <: RingElement }
return add(p, q)
end

"""
scale(a::RingElement, p::LinearSetPartition{S, T}) where
{ S <: AbstractPartition, T <: RingElement }

Multiply each coefficient in `p` with `a` and return
the result.

# Examples
```jldoctest
julia> S, d = polynomial_ring(QQ, "d")
(Univariate polynomial ring in x over QQ, d)
julia> scale(S(1) / S(2), linear_partition(Dict(set_partition([1, 2], [1, 1]) => S(8),
set_partition([1, 1], [1, 1]) => 8*d)))
LinearSetPartition(Dict(SetPartition([1, 2], [1, 1]) => S(4),
SetPartition([1, 1], [1, 1]) => 4*d))
```
"""
function scale(a::RingElement, p::LinearSetPartition{S, T}) where
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
{ S <: AbstractPartition, T <: RingElement }
result = Dict{S, T}()

for (i, n) in pairs(coefficients(p))
result[i] = a * n
end
return linear_partition(result)
end

function *(a::RingElement, p::LinearSetPartition{S, T}) where
{ S <: AbstractPartition, T <: RingElement }
return scale(a, p)
end

"""
compose(p::LinearSetPartition{S, T}, q::LinearSetPartition{S, T}, d::T) where
{ S <: AbstractPartition, T <: RingElement }

Multiply each coefficient from `p` with each coefficient from `q`
as well as perform a composition between each SetPartition part
in `p` and `q` and return the result.

# Examples
```jldoctest
julia> S, d = polynomial_ring(QQ, "d")
(Univariate polynomial ring in x over QQ, d)
julia> a = linear_partition([(set_partition([1, 2], [1, 1]), S(4)),
(SetPartition([1, 1], [1, 1]), 4*d)])
julia> compose(a, a, d)
LinearSetPartition(Dict(SetPartition([1, 2], [1, 1]) => 16*d + 16,
SetPartition([1, 1], [1, 1]) => 16*d^2 + 16*d))
```
"""
function compose(p::LinearSetPartition{S, T}, q::LinearSetPartition{S, T}, d::T) where
{ S <: AbstractPartition, T <: RingElement }
result = Dict{S, T}()
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved

for i in pairs(coefficients(p))
for ii in pairs(coefficients(q))
(composition, loop) = compose_count_loops(i[1], ii[1])
new_coefficient = i[2] * ii[2] * (d^loop)
result[composition] = get(result, composition, 0) + new_coefficient
end
end
return linear_partition(result)
end

"""
tensor_product(p::LinearSetPartition{P, R}, q::LinearSetPartition{P, R}) where
{ P <: AbstractPartition, R <: RingElement }

Return the tensor product of `p` and `q`.

# Examples
```jldoctest
julia> S, d = polynomial_ring(QQ, "d")
(Univariate polynomial ring in x over QQ, d)
julia> a = linear_partition([(set_partition([1, 2], [1, 1]), S(4)),
(set_partition([1, 1], [1, 1]), 4*d)])
julia> tensor_product(a, a)
LinearSetPartition(Dict(SetPartition([1, 1, 2, 2], [1, 1, 2, 2]) => 16*d^2,
SetPartition([1, 2, 3, 3], [1, 1, 3, 3]) => 16*d,
SetPartition([1, 2, 3, 4], [1, 1, 3, 3]) => S(16),
SetPartition([1, 1, 2, 3], [1, 1, 2, 2]) => 16*d)))
```
"""
function tensor_product(p::LinearSetPartition{S, T}, q::LinearSetPartition{S, T}) where
{ S <: AbstractPartition, T <: RingElement }

result = Dict{S, T}()

for i in pairs(coefficients(p))
for ii in pairs(coefficients(q))
composition = tensor_product(i[1], ii[1])
new_coefficient = i[2] * ii[2]
result[composition] = get(result, composition, 0) + new_coefficient
end
end

return linear_partition(result)
end

function ⊗(p::LinearSetPartition{S, T}, q::LinearSetPartition{S, T}) where
{ S <: AbstractPartition, T <: RingElement }
return tensor_product(p, q)
end

"""
subtract(p::LinearSetPartition{S, T}, q::LinearSetPartition{S, T}) where
{ S <: AbstractPartition, T <: RingElement }

Perform a subtraction between `p` and `q` and return the result.

# Examples
```jldoctest
julia> S, d = polynomial_ring(QQ, "d")
(Univariate polynomial ring in x over QQ, d)
julia> a = linear_partition([(set_partition([1, 2], [1, 1]), S(4)),
(SetPartition([1, 1], [1, 1]), 4*d)])
julia> subtract(a, a)
LinearSetPartition(Dict(SetPartition([1, 1], [1, 1]) => S(0)))
```
"""
function subtract(p::LinearSetPartition{S, T}, q::LinearSetPartition{S, T}) where
{ S <: AbstractPartition, T <: RingElement }
return add(p, scale(-1, q))
end

function -(p::LinearSetPartition{S, T}, q::LinearSetPartition{S, T}) where
{ S <: AbstractPartition, T <: RingElement }
return subtract(p, q)
end
26 changes: 24 additions & 2 deletions experimental/SetPartitions/src/SetPartitions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import Base:
deepcopy,
deepcopy_internal,
hash,
size
size,
-,
+

import Oscar:
⊗,
Expand All @@ -19,11 +21,16 @@ import Oscar:
parent,
degree,
tensor_product,
@req
@req,
RingElement,
scale,
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
coefficients,
iszero

export ColoredPartition
export SetPartition
export SpatialPartition
export LinearSetPartition

export colored_partition
export compose_count_loops
Expand Down Expand Up @@ -51,6 +58,13 @@ export set_partition
export spatial_partition
export upper_colors
export upper_points
export simplify_operation_zero
export simplify_operation
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
export linear_partition
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
export add
export scale
export subtract



include("AbstractPartition.jl")
Expand All @@ -60,13 +74,15 @@ include("ColoredPartition.jl")
include("SpatialPartition.jl")
include("PartitionProperties.jl")
include("GenerateCategory.jl")
include("LinearSetPartition.jl")
end

using .SetPartitions

export ColoredPartition
export SetPartition
export SpatialPartition
export LinearSetPartition

export colored_partition
export compose_count_loops
Expand Down Expand Up @@ -94,3 +110,9 @@ export set_partition
export spatial_partition
export upper_colors
export upper_points
export simplify_operation_zero
export simplify_operation
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
export linear_partition
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
export add
export scale
export subtract
43 changes: 43 additions & 0 deletions experimental/SetPartitions/src/Util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,46 @@ function _add_partition_top_bottom(vector::Vector{Dict{Int, Set{T}}}, p::T) wher

return vector
end

"""
simplify_operation(partition_sum::Vector{Tuple{S, T}}) where { S <: AbstractPartition, T <: RingElement }

Simplify the vector representation of a `LinearSetPartition` in terms of associativity.
"""
function simplify_operation(partition_sum::Vector{Tuple{S, T}}) where { S <: AbstractPartition, T <: RingElement }

partitions = Dict{S, T}()

for (i1, i2) in partition_sum

if iszero(i2)
deleteat!(partition_sum, findall(x -> x == (i1, i2), partition_sum))
continue
end

if !(i1 in keys(partitions))
partitions[i1] = i2
else
deleteat!(partition_sum, findall(x -> x == (i1, i2), partition_sum))
deleteat!(partition_sum, findall(x -> x == (i1, get(partitions, i1, -1)), partition_sum))
push!(partition_sum, (i1, get(partitions, i1, -1) + i2))
partitions[i1] = get(partitions, i1, -1) + i2
end
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
end
return partition_sum
end

"""
simplify_operation_zero(p::Dict{S, T}) where { S <: AbstractPartition, T <: RingElement }

Simplify the dict representation of a `LinearSetPartition` in terms of zero coefficients.
"""
function simplify_operation_zero(p::Dict{S, T}) where { S <: AbstractPartition, T <: RingElement }
result = Dict{S, T}()
for (i1, i2) in pairs(p)
if !iszero(i2)
result[i1] = i2
end
end
return result
end
25 changes: 25 additions & 0 deletions experimental/SetPartitions/test/LinearComb-test.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@testset "LinearCombinations of SetPartitions" begin
sebvz777 marked this conversation as resolved.
Show resolved Hide resolved
@testset "LinearSetPartition Constructor" begin
S, d = polynomial_ring(QQ, "d")
@test coefficients(linear_partition(Dict(set_partition([1, 2], [1, 1]) => S(4), set_partition([1, 1], [1, 1]) => 8*d))) == Dict(set_partition([1, 2], [1, 1]) => S(4), set_partition([1, 1], [1, 1]) => 8*d)
@test coefficients(linear_partition(Dict(set_partition([1, 2], [1, 1]) => S(0), set_partition([1, 1], [1, 1]) => 8*d))) == Dict(set_partition([1, 1], [1, 1]) => 8*d)
@test coefficients(linear_partition([(set_partition([1, 1], [1, 1]), S(5)), (set_partition([1, 1], [1, 1]), 4*d)])) == Dict(set_partition([1, 1], [1, 1]) => 5 + 4*d)
end

@testset "LinearPartition Operations" begin
S, d = polynomial_ring(QQ, "d")
a = linear_partition([(set_partition([1, 2], [1, 1]), S(5)), (set_partition([1, 1], [1, 1]), 5*d)])
@test add(a, a) == a + a == linear_partition(Dict(set_partition([1, 2], [1, 1]) => S(10), set_partition([1, 1], [1, 1]) => 10*d))
@test add(a, linear_partition([(set_partition([1, 1], [1, 1]), S(1)), (set_partition([1, 1], [1, 1]), 2*d)])) == linear_partition([(set_partition([1, 2], [1, 1]), S(5)), (set_partition([1, 1], [1, 1]), 7*d + 1)])

@test scale(S(2), linear_partition(Dict(set_partition([1, 2], [1, 1]) => S(10), set_partition([1, 1], [1, 1]) => 8*d))) == S(2) * linear_partition(Dict(set_partition([1, 2], [1, 1]) => S(10), set_partition([1, 1], [1, 1]) => 8*d)) == linear_partition(Dict(set_partition([1, 2], [1, 1]) => S(20), set_partition([1, 1], [1, 1]) => 16*d))
@test scale(S(1) / S(2), linear_partition(Dict(set_partition([1, 2], [1, 1]) => S(8), set_partition([1, 1], [1, 1]) => 8*d))) == linear_partition(Dict(SetPartition([1, 2], [1, 1]) => S(4), SetPartition([1, 1], [1, 1]) => 4*d))

a = linear_partition([(set_partition([1, 2], [1, 1]), S(4)), (set_partition([1, 1], [1, 1]), 4*d)])
@test compose(a, a, d) == linear_partition(Dict(set_partition([1, 2], [1, 1]) => 16*d + 16, set_partition([1, 1], [1, 1]) => 16*d^2 + 16*d))

@test tensor_product(a, a) == linear_partition(Dict(set_partition([1, 1, 2, 2], [1, 1, 2, 2]) => 16*d^2, set_partition([1, 2, 3, 3], [1, 1, 3, 3]) => 16*d, set_partition([1, 2, 3, 4], [1, 1, 3, 3]) => S(16), set_partition([1, 1, 2, 3], [1, 1, 2, 2]) => 16*d))

@test subtract(a, a) == a - a == linear_partition(Dict(set_partition([1, 1], [1, 1]) => S(0)))
end
end
Loading