Reputation: 12928
I am converting a method for creating a Halton sequence into a generator in Python. I am running into the same problem in Python 2.7 and Python 3.3.
When I create a generator object using my generator and call my_object.next()
repeatedly, I get the results that I expect. When, however, I call list(my_object)
or tuple(my_object)
, I get the appropriately-sized list/tuple, but each element is just a copy of the final value that the generator outputs. My Python 3.3 code is below:
def halton_gen(dim, num_pts):
sequence = np.empty(dim)
sequence.fill(np.nan)
primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31) # first 11 prime #s
log_pts = log(num_pts + 1)
k = 1
# Generate the sequence
while k <= num_pts:
print("k = {}".format(k))
for i in range(dim):
print("i = {}".format(i))
prime = primes[i]
num_helper = int(ceil(log_pts / log(prime)))
kk = k
sum_ = 0
for j in range(num_helper):
sum_ += fmod(kk, prime) * pow(prime, -(j + 1))
kk = floor(kk / prime)
sequence[i] = sum_
print("sequence {}".format(sequence))
yield sequence
k += 1
Note that the print statements in the code above give me what I am expecting, but the list/tuple created with list(my_object)
or tuple(my_object)
is incorrect:
my_object = halton_gen(2, 5)
tuple(my_object)
k = 1
i = 0
i = 1
sequence [ 0.5 0.33333333]
k = 2
i = 0
i = 1
sequence [ 0.25 0.66666667]
k = 3
i = 0
i = 1
sequence [ 0.75 0.11111111]
k = 4
i = 0
i = 1
sequence [ 0.125 0.44444444]
k = 5
i = 0
i = 1
sequence [ 0.625 0.77777778]
Out[86]:
(array([ 0.625 , 0.77777778]),
array([ 0.625 , 0.77777778]),
array([ 0.625 , 0.77777778]),
array([ 0.625 , 0.77777778]),
array([ 0.625 , 0.77777778]))
I am expecting (dropping the array()
specifiers for readability):
([0.5 0.333],
[0.25 0.667],
[0.75 0.111],
[0.125 0.444],
[0.625 0.778])
How can I get my generator to properly populate my list? Or my list to properly unpack my generator? Whatever the proper way of stating that is.
Upvotes: 0
Views: 63
Reputation: 75575
Your sequence
object is being recycled. One fix is to re-create it every time you yield.
def halton_gen(dim, num_pts):
primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31) # first 11 prime #s
log_pts = log(num_pts + 1)
k = 1
# Generate the sequence
while k <= num_pts:
sequence = np.empty(dim)
sequence.fill(np.nan)
print("k = {}".format(k))
for i in range(dim):
print("i = {}".format(i))
prime = primes[i]
num_helper = int(ceil(log_pts / log(prime)))
kk = k
sum_ = 0
for j in range(num_helper):
sum_ += fmod(kk, prime) * pow(prime, -(j + 1))
kk = floor(kk / prime)
sequence[i] = sum_
print("sequence {}".format(sequence))
yield sequence
k += 1
Another fix would be as the comment mentions, to use sequence.copy()
.
yield sequence.copy()
Upvotes: 2