Skip to content

Commit

Permalink
use a Julia iterator in MinimalDegreeHard
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasBreuer committed Feb 21, 2019
1 parent 61841c5 commit 545c866
Showing 1 changed file with 79 additions and 47 deletions.
126 changes: 79 additions & 47 deletions JuliaExperimental/julia/loewy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -350,48 +350,75 @@ function DivisorsInt( n::Int )
return sort( divs( 1, 1 ) )
end;


raw"""
> V( m, n, s )
> Enumerate the set `V(m,n,s)` of all vectors of length `n`
"""
> VectorIterator( m, n, s )
> Iterate over all vectors of length `n`
> with entries in the set { 0, 1, 2, ... `m` }
> and coefficient sum `s`,
> such that a largest entry is in the first position.
>
> \[
> V(m,n,s) = \bigcup_{0 \leq a \leq \min\{ m, s \}}
> \{ [a,v]; v \in V(m,n-1,s-a) \}
> \]
"""
# replace this by an iterator, we just want to run over the elements!
function Vinner( m::Int, n::Int, s::Int )
local result, a

if s == 0
return [ zeros( Int, n ) ]
elseif n == 0 || m*n < s
return []
end

result = []
for a in 0:min( m, s )
append!( result, map( v -> append!( [ a ], v ),
Vinner( m, n-1, s-a ) ) )
end
return result
end;
> and coefficient sum `s`.
> The vectors are enumerated in lexicographical order.
> (The functions change the vectors in place,
> just collecting the results makes no sense.)
"""
mutable struct VectorIterator
m::Int
n::Int
s::Int
end

function V( m::Int, n::Int, s::Int )
local result, a
# Auxiliary function for the iterator:
# Distribute `s` to the first `n` positions in the array `v`
# such that as many initial entries are `m`.
function VectorIterator_ResetPrefix( v::Array{Int,1}, m::Int, n::Int, s::Int )
local rest::Int, i::Int, j::Int

result = []
for a in 1:m
append!( result, map( v -> append!( [ a ], v ),
Vinner( a, n-1, s-a ) ) )
rest = s
i = 1
while m < rest
v[i] = m
rest = rest - m
i = i + 1
end
return result
end;
v[i] = rest
for j in (i+1):n
v[j] = 0
end

return v
end

# Initialize the iterator.
function Base.iterate( vi::VectorIterator )
local next::Array{Int,1}

if vi.s > vi.m * vi.n
# The iterator is empty.
return
end
next = VectorIterator_ResetPrefix( zeros( Int, vi.n ), vi.m, vi.n, vi.s )
return ( next, next )
end

# Define the iteration step.
# Note that `state` is changed in place.
function Base.iterate( vi::VectorIterator, state::Array{Int,1} )
local sum::Int, i::Int

# Find the first position with a nonzero value
# such that the value on the right is smaller than m.
sum = -1
for i in 1:(vi.n-1)
sum = sum + state[i]
if state[i] != 0 && state[ i+1 ] < vi.m
state[i] = state[i] - 1
state[i+1] = state[i+1] + 1
VectorIterator_ResetPrefix( state, vi.m, i, sum )
return ( state, state )
end
end

# There is no such position, we are done.
return
end

"""
MinimalDegreeCheap( q::Int, n::Int, e )
Expand Down Expand Up @@ -471,19 +498,21 @@ end;
function MinimalDegreeHard( q::Int, n::Int, e::T ) where {T<:Integer}
local powers, m, v

powers = map( i -> powermod( q, i, e ), 0:(n-1) )
powers = map( i -> powermod( q, i, e ), 1:(n-1) )
m = 3

while true
for v in V( m, n, m )
if mod( sum( v .* powers ), e ) == 0
for a in 1:m
for v in VectorIterator( a, n-1, m-a )
if mod( a + sum( v .* powers ), e ) == 0
# is there no dot( v, powers ) anymore in Julia 1.0??
# ('.*' needs same length of its operands)
if ! haskey( MinimalDegreeCache, e )
MinimalDegreeCache[e] = Dict()
if ! haskey( MinimalDegreeCache, e )
MinimalDegreeCache[e] = Dict()
end
MinimalDegreeCache[e][q] = m
return m
end
MinimalDegreeCache[e][q] = m
return m
end
end
m = m + 1
Expand Down Expand Up @@ -718,9 +747,12 @@ function test_this_module()
ok = false
end

# V( m, n, s )
if LoewyStructure.V( 3, 3, 4 ) !=
[ [ 2, 0, 2 ], [ 2, 1, 1 ], [ 2, 2, 0 ], [ 3, 0, 1 ], [ 3, 1, 0 ] ]
# VectorIterator( m, n, s )
n = 0
for i in VectorIterator( 2, 5, 7 )
n = n + 1
end
if n != 30
ok = false
end

Expand Down

0 comments on commit 545c866

Please sign in to comment.