From 7dc8fb625238f1d91d10ee1c4e4826241878824f Mon Sep 17 00:00:00 2001 From: Stefan Rigger Date: Thu, 5 Jan 2017 17:00:02 +0100 Subject: [PATCH 1/5] Add files via upload This is a julia port of the sage VectorPartitions function originally written by Amritanshu Prasad (2013). A vector partition of "vec" is a list of vectors with non-negative integer entries whose sum is "vec". The method vector_partitions creates all vector partitions of "vector" with all parts greater than or equal to "min" in lexicographic order recursively. INPUT: - "vec" -- a list of non-negative integers. EXAMPLES: If "min" is not specified, then the class of all vector partitions of "vec" is created:: julia> vector_partitions([2, 2]) 9-element Array{Any,1}: Array{Int64,1}[[1,0],[1,0],[0,1],[0,1]] Array{Int64,1}[[2,0],[0,1],[0,1]] Array{Int64,1}[[1,1],[1,0],[0,1]] Array{Int64,1}[[2,1],[0,1]] Array{Int64,1}[[1,0],[1,0],[0,2]] Array{Int64,1}[[2,0],[0,2]] Array{Int64,1}[[1,2],[1,0]] Array{Int64,1}[[1,1],[1,1]] Array{Int64,1}[[2,2]] --- src/vector_partitions.jl | 136 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/vector_partitions.jl diff --git a/src/vector_partitions.jl b/src/vector_partitions.jl new file mode 100644 index 0000000..ebd053a --- /dev/null +++ b/src/vector_partitions.jl @@ -0,0 +1,136 @@ +# This is a julia version of the VectorPartitions function for sage by Amritanshu Prasad (2013) +# AUTHORS: Stefan Rigger, Gudmund Pammer (2017) + +export vector_partitions + +function find_min(vector::Array{Int64}) + # Return a string of 0's with one 1 at the location where the list + # "vector" has its last entry which is not equal to 0. + # INPUT: + # -"vector" -- An Int64-Array + # OUTPUT: + # A list of the same length with 0's everywhere, except for a 1 + # at the last position where "vector" has an entry not equal to 0. + # EXAMPLES:: + # julia> find_min([2, 1]) + # [0, 1] + # julia> find_min([2, 1, 0]) + # [0, 1, 0] + + min = zeros(Int64,length(vector)) + if vector != min + min[maximum(find(vector))] = 1 + end + + return min + +end + +function componentwise_minors(vector::Array{Int64},min=zeros(Int64,length(vector))) + + # Return array of integer vectors which are componentwise + # less than or equal to "vector" and lexicographically greater than or equal + # to "min". + # INPUT: + # - "vector" -- A list of non-negative integers + # - "min" -- A list of non-negative integers dominated lexicographically by "vector" + # OUTPUT: + # An array in lexicographic order of all integer arrays which are + # dominated elementwise by "vector" and are greater than or equal to "min" in + # lexicographic order. + # EXAMPLES:: + # julia> componentwise_minors([1, 1])) + # 4-element Array{Any,1}: + # [0,0] + # [0,1] + # [1,0] + # [1,1] + # julia> componentwise_minors([3,2],[2,4]) + # 3-element Array{Any,1}: + # [3,0] + # [3,1] + # [3,2] + + minors = [] + difference = vector - min + + if difference == zeros(Int64,length(difference)) + minors = [vector] + elseif length(vector) == 1 + minors =[[k] for k in min[1]:vector[1]] + else + # test if min is lexicographically less than vector + if (difference[minimum(find(difference))] < 0) + minors = [] + else + for vec in componentwise_minors(vector[2:end],min[2:end]) + unshift!(vec,min[1]) + push!(minors,vec) + end + for j in (min[1]+1):vector[1] + for vec in componentwise_minors(vector[2:end]) + unshift!(vec,j) + push!(minors,vec) + end + end + end + end + + return minors +end + +function vector_partitions(vector::Array{Int64},min=zeros(Int64,length(vector))) + + # Creates all vector partitions of "vector" with all parts greater than + # or equal to "min" in lexicographic order recursively. + # A vector partition of "vec" is a list of vectors with non-negative + # integer entries whose sum is "vec". + # INPUT: + # - "vec" -- a list of non-negative integers. + # EXAMPLES: + # If "min" is not specified, then the class of all vector partitions of + # "vec" is created:: + # julia> vector_partitions([2, 2]) + # 9-element Array{Any,1}: + # Array{Int64,1}[[1,0],[1,0],[0,1],[0,1]] + # Array{Int64,1}[[2,0],[0,1],[0,1]] + # Array{Int64,1}[[1,1],[1,0],[0,1]] + # Array{Int64,1}[[2,1],[0,1]] + # Array{Int64,1}[[1,0],[1,0],[0,2]] + # Array{Int64,1}[[2,0],[0,2]] + # Array{Int64,1}[[1,2],[1,0]] + # Array{Int64,1}[[1,1],[1,1]] + # Array{Int64,1}[[2,2]] + # + # If "min" is specified, then the array lists those vector + # partitions whose parts are all greater than or equal to "min" in + # lexicographic order:: + # julia> vector_partitions([2,2],[1,0]) + # 3-element Array{Any,1}: + # Array{Int64,1}[[1,2],[1,0]] + # Array{Int64,1}[[1,1],[1,1]] + # Array{Int64,1}[[2,2]] + + vpartitions=[] + + if min == zeros(Int64,length(vector)) + min = find_min(vector) + end + + if vector == zeros(Int64,length(vector)) + vpartitions = [] + else + for vec in componentwise_minors(vector,min) + if vec == vector + push!(vpartitions,[vector]) + else + for part in vector_partitions(vector-vec,vec) + push!(part,vec) + push!(vpartitions,part) + end + end + end + end + + return vpartitions +end From 2f981fca7155d7d36edcdb0b8ab9edab1d147514 Mon Sep 17 00:00:00 2001 From: Stefan Rigger Date: Mon, 26 Dec 2022 00:28:57 +0100 Subject: [PATCH 2/5] added tests and cleaned up code --- src/Combinatorics.jl | 1 + src/vector_partitions.jl | 136 --------------------------------------- src/vectorpartitions.jl | 124 +++++++++++++++++++++++++++++++++++ test/runtests.jl | 1 + test/vectorpartitions.jl | 12 ++++ 5 files changed, 138 insertions(+), 136 deletions(-) delete mode 100644 src/vector_partitions.jl create mode 100644 src/vectorpartitions.jl create mode 100644 test/vectorpartitions.jl diff --git a/src/Combinatorics.jl b/src/Combinatorics.jl index 442fd04..ae7e796 100644 --- a/src/Combinatorics.jl +++ b/src/Combinatorics.jl @@ -7,6 +7,7 @@ include("combinations.jl") include("permutations.jl") include("partitions.jl") include("multinomials.jl") +include("vectorpartitions.jl") include("youngdiagrams.jl") end #module diff --git a/src/vector_partitions.jl b/src/vector_partitions.jl deleted file mode 100644 index ebd053a..0000000 --- a/src/vector_partitions.jl +++ /dev/null @@ -1,136 +0,0 @@ -# This is a julia version of the VectorPartitions function for sage by Amritanshu Prasad (2013) -# AUTHORS: Stefan Rigger, Gudmund Pammer (2017) - -export vector_partitions - -function find_min(vector::Array{Int64}) - # Return a string of 0's with one 1 at the location where the list - # "vector" has its last entry which is not equal to 0. - # INPUT: - # -"vector" -- An Int64-Array - # OUTPUT: - # A list of the same length with 0's everywhere, except for a 1 - # at the last position where "vector" has an entry not equal to 0. - # EXAMPLES:: - # julia> find_min([2, 1]) - # [0, 1] - # julia> find_min([2, 1, 0]) - # [0, 1, 0] - - min = zeros(Int64,length(vector)) - if vector != min - min[maximum(find(vector))] = 1 - end - - return min - -end - -function componentwise_minors(vector::Array{Int64},min=zeros(Int64,length(vector))) - - # Return array of integer vectors which are componentwise - # less than or equal to "vector" and lexicographically greater than or equal - # to "min". - # INPUT: - # - "vector" -- A list of non-negative integers - # - "min" -- A list of non-negative integers dominated lexicographically by "vector" - # OUTPUT: - # An array in lexicographic order of all integer arrays which are - # dominated elementwise by "vector" and are greater than or equal to "min" in - # lexicographic order. - # EXAMPLES:: - # julia> componentwise_minors([1, 1])) - # 4-element Array{Any,1}: - # [0,0] - # [0,1] - # [1,0] - # [1,1] - # julia> componentwise_minors([3,2],[2,4]) - # 3-element Array{Any,1}: - # [3,0] - # [3,1] - # [3,2] - - minors = [] - difference = vector - min - - if difference == zeros(Int64,length(difference)) - minors = [vector] - elseif length(vector) == 1 - minors =[[k] for k in min[1]:vector[1]] - else - # test if min is lexicographically less than vector - if (difference[minimum(find(difference))] < 0) - minors = [] - else - for vec in componentwise_minors(vector[2:end],min[2:end]) - unshift!(vec,min[1]) - push!(minors,vec) - end - for j in (min[1]+1):vector[1] - for vec in componentwise_minors(vector[2:end]) - unshift!(vec,j) - push!(minors,vec) - end - end - end - end - - return minors -end - -function vector_partitions(vector::Array{Int64},min=zeros(Int64,length(vector))) - - # Creates all vector partitions of "vector" with all parts greater than - # or equal to "min" in lexicographic order recursively. - # A vector partition of "vec" is a list of vectors with non-negative - # integer entries whose sum is "vec". - # INPUT: - # - "vec" -- a list of non-negative integers. - # EXAMPLES: - # If "min" is not specified, then the class of all vector partitions of - # "vec" is created:: - # julia> vector_partitions([2, 2]) - # 9-element Array{Any,1}: - # Array{Int64,1}[[1,0],[1,0],[0,1],[0,1]] - # Array{Int64,1}[[2,0],[0,1],[0,1]] - # Array{Int64,1}[[1,1],[1,0],[0,1]] - # Array{Int64,1}[[2,1],[0,1]] - # Array{Int64,1}[[1,0],[1,0],[0,2]] - # Array{Int64,1}[[2,0],[0,2]] - # Array{Int64,1}[[1,2],[1,0]] - # Array{Int64,1}[[1,1],[1,1]] - # Array{Int64,1}[[2,2]] - # - # If "min" is specified, then the array lists those vector - # partitions whose parts are all greater than or equal to "min" in - # lexicographic order:: - # julia> vector_partitions([2,2],[1,0]) - # 3-element Array{Any,1}: - # Array{Int64,1}[[1,2],[1,0]] - # Array{Int64,1}[[1,1],[1,1]] - # Array{Int64,1}[[2,2]] - - vpartitions=[] - - if min == zeros(Int64,length(vector)) - min = find_min(vector) - end - - if vector == zeros(Int64,length(vector)) - vpartitions = [] - else - for vec in componentwise_minors(vector,min) - if vec == vector - push!(vpartitions,[vector]) - else - for part in vector_partitions(vector-vec,vec) - push!(part,vec) - push!(vpartitions,part) - end - end - end - end - - return vpartitions -end diff --git a/src/vectorpartitions.jl b/src/vectorpartitions.jl new file mode 100644 index 0000000..9e662f4 --- /dev/null +++ b/src/vectorpartitions.jl @@ -0,0 +1,124 @@ + +export vector_partitions + +function vector_partitions(vector::Vector{Int64},min=zeros(Integer,length(vector))) + + # Creates all vector partitions of "vector" with all parts greater than + # or equal to "min" in lexicographic order recursively. + # A vector partition of "vector" is a list of vectors with non-negative + # integer entries whose sum is "vector". + # EXAMPLES: + # julia> vector_partitions([2, 2]) + # 9-element Vector{Any}: + # [[1, 0], [1, 0], [0, 1], [0, 1]] + # [[2, 0], [0, 1], [0, 1]] + # [[1, 1], [1, 0], [0, 1]] + # [[2, 1], [0, 1]] + # [[1, 0], [1, 0], [0, 2]] + # [[2, 0], [0, 2]] + # [[1, 2], [1, 0]] + # [[1, 1], [1, 1]] + # [[2, 2]] + # + # julia> vector_partitions([2,2],[1,0]) + # 3-element Vector{Any}: + # [[1, 2], [1, 0]] + # [[1, 1], [1, 1]] + # [[2, 2]] + + if minimum(min) < 0 + throw(DomainError(min, "vector must have nonnegative entries")) + end + + if minimum(vector) < 0 + throw(DomainError(max, "vector must have nonnegative entries")) + end + + vpartitions=Vector{Vector{Vector{Int64}}}[] + + if min == zeros(Integer,length(vector)) + min = lexicographic_nonzero_minimum(vector) + end + + if vector == zeros(Integer,length(vector)) + vpartitions = [] + else + for vec in lexicographic_summand_range(vector,min) + if vec == vector + push!(vpartitions,[vector]) + else + for part in vector_partitions(vector-vec,vec) + push!(part,vec) + push!(vpartitions,part) + end + end + end + end + + return vpartitions + + end + +function lexicographic_summand_range(max::Vector{Int64},min=zeros(Integer,length(max))) + + # Return array of nonegative integer vectors which are componentwise dominated by + # "max" and greater than or equal to "min" in lexicographic order. + # + # EXAMPLES:: + # julia> lexicographic_summand_range([1,1,0],[0,2,0])) + # 2-element Vector{Any}: + # [1, 0, 0] + # [1, 1, 0] + # julia> lexicographic_summand_range([1,2]) + # 6-element Vector{Any}: + # [0, 0] + # [0, 1] + # [0, 2] + # [1, 0] + # [1, 1] + # [1, 2] + + range = [] + difference = max - min + + if difference == zeros(Integer,length(difference)) + range = [max] + elseif length(max) == 1 + range =[[k] for k in min[1]:max[1]] + else + if (difference[findfirst(x->x!=0, difference)] < 0) + range = [] + else + for vector in lexicographic_summand_range(max[2:end],min[2:end]) + pushfirst!(vector,min[1]) + push!(range,vector) + end + for j in (min[1]+1):max[1] + for vector in lexicographic_summand_range(max[2:end]) + pushfirst!(vector,j) + push!(range,vector) + end + end + end + end + + return range +end + +function lexicographic_nonzero_minimum(vector::Array{Int64}) + # Returns the lexicographically smallest nonzero vector of the same length as + # "vector" that is componentwise dominated by "vector". + # EXAMPLES:: + # julia> lexicographic_nonzero_minimum([2, 1]) + # [0, 1] + # julia> lexicographic_nonzero_minimum([2, 1, 0]) + # [0, 1, 0] + + min = zeros(Integer,length(vector)) + if vector != min + min[findlast(x->x>0,vector)] = 1 + end + + return min + +end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index d790670..b9e4870 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -7,4 +7,5 @@ include("combinations.jl") include("permutations.jl") include("partitions.jl") include("multinomials.jl") +include("vectorpartitions.jl") include("youngdiagrams.jl") diff --git a/test/vectorpartitions.jl b/test/vectorpartitions.jl new file mode 100644 index 0000000..fd660a4 --- /dev/null +++ b/test/vectorpartitions.jl @@ -0,0 +1,12 @@ +#vector_partitions +@test collect(vector_partitions([1,1])) == Any[[[1,0],[0,1]],[[1,1]]] +@test collect(vector_partitions([2,1])) == Any[[[1, 0], [1, 0], [0, 1]], + [[2, 0], [0, 1]], + [[1, 1], [1, 0]], + [[2, 1]]] +@test collect(vector_partitions([2,1],[0,2])) == Any[[[1,1],[1,0]],[[2,1]]] +@test collect(vector_partitions([2,1],[3,2])) == [] + +@test_throws DomainError vector_partitions([-3,2]) + +@test length(vector_partitions([1,1],[2,3])) == 0 From 8deb3f78904d1ea1ea06f3f7190128cd4712f530 Mon Sep 17 00:00:00 2001 From: Stefan Rigger Date: Mon, 26 Dec 2022 00:59:29 +0100 Subject: [PATCH 3/5] removed incorrect initialization --- src/vectorpartitions.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vectorpartitions.jl b/src/vectorpartitions.jl index 9e662f4..9e07d94 100644 --- a/src/vectorpartitions.jl +++ b/src/vectorpartitions.jl @@ -34,14 +34,14 @@ function vector_partitions(vector::Vector{Int64},min=zeros(Integer,length(vector throw(DomainError(max, "vector must have nonnegative entries")) end - vpartitions=Vector{Vector{Vector{Int64}}}[] + vpartitions=[] if min == zeros(Integer,length(vector)) min = lexicographic_nonzero_minimum(vector) end if vector == zeros(Integer,length(vector)) - vpartitions = [] + vpartitions=[] else for vec in lexicographic_summand_range(vector,min) if vec == vector From 380ff941cb7aded7e26752de848f68ed27ada35f Mon Sep 17 00:00:00 2001 From: Stefan Rigger Date: Mon, 26 Dec 2022 01:21:26 +0100 Subject: [PATCH 4/5] add test throwing DomainError if min has a negative entry --- test/vectorpartitions.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/vectorpartitions.jl b/test/vectorpartitions.jl index fd660a4..0987fc6 100644 --- a/test/vectorpartitions.jl +++ b/test/vectorpartitions.jl @@ -8,5 +8,6 @@ @test collect(vector_partitions([2,1],[3,2])) == [] @test_throws DomainError vector_partitions([-3,2]) +@test_throws DomainError vector_partitions([3,2],[-2,-3]) @test length(vector_partitions([1,1],[2,3])) == 0 From 6245f53c1b9a6ba0308b04024941f72e23b3daf0 Mon Sep 17 00:00:00 2001 From: Stefan Rigger Date: Mon, 26 Dec 2022 01:23:32 +0100 Subject: [PATCH 5/5] add test for zero vector input --- test/vectorpartitions.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/vectorpartitions.jl b/test/vectorpartitions.jl index 0987fc6..9c8e364 100644 --- a/test/vectorpartitions.jl +++ b/test/vectorpartitions.jl @@ -11,3 +11,5 @@ @test_throws DomainError vector_partitions([3,2],[-2,-3]) @test length(vector_partitions([1,1],[2,3])) == 0 +@test length(vector_partitions([0,0,0])) == 0 +