So I have been playing around with linear congruential generators but I am stuck on the idea that once a script has been run, it always generates the same way. If I run a script such as this;
import random
print(random.randrange(0,9))
It will generate a new random number each time the script is run. I'm wondering how it does this.
So this is what I have gotten so far;
from collections import Counter
class linearCongruentialGenerator(object):
def __init__(self, lowBound, highBound, length):
self.lowBound, self.highBound, self.length = lowBound, highBound, length
self.modulus = 20226231145#modulus
self.multiplier = 104743412357321567#multiplier
self.increment = 1049592131123467#increment
self.seed = 43123211114#seed
def __iter__(self):
while self.length > 0:
self.length -= 1
self.seed = (self.multiplier*self.seed + self.increment) % self.modulus
yield (self.seed % self.highBound)
def linearCongruentialGenerator(self, first, last):
self.seed = (self.multiplier*self.seed + self.increment) % self.modulus
return self.seed
def binary(self):
self.seed = (self.multiplier*self.seed + self.increment) % self.modulus
self.seedLength = len(str(seed))
return (self.seed // 10**1 % 10) % 2
if __name__ == "__main__":
random = linearCongruentialGenerator(0, 9, 100)
random1 = linearCongruentialGenerator(0, 9, 100)
list1 = []
list2 = []
for i in random:
list1.append(i)
for j in random1:
list2.append(j)
print(Counter(list1))
print(len(set(list1)))
print(Counter(list2))
print(len(set(list2)))
This script counts the numbers generated by the linearCongruentialGenerator class then prints the distribution: number:count.
I want the script to generate new values every time I run the script. Without using the random class that comes with python. Because that is cheating :D
Not sure how to approach this, any tips?
Just do what we do to ensure this problem doesn't occur in random, set the seed as time.time() in init so it always seeds with the current time seed=time.time()
Related
I am currently creating my genetic algorithm and want to print the number of generations at the very end of the program when it finishes. However I am unsure how to access the counter variable that is the number of generations when it is outside of the class and method. So for example, at the end it would be like
Generation 100, average fit 18966, best fit 18947
Your best chromosone at generation 100
'\x06pzÂ\x8cYÆr¯n0q\x07l¿M8\x93Þ\x19\x87"\x01\x85\x1er\x89[F_VyER\x9b\x0bm=)\x9a\x9a¿¥\x10F\x12A\x84\x0fZ^\x14\x99\x8a4®\x9f¿*\\\xa0yi\x19E\x8aÇ+6(_<¾£cO~\x9c\x99\x932\x06\x0f\x82\x7f¤\x808xǸñA\x13\x0e<%\x06ÿ#í\x91Pô\x98 ®\r\x1b}\x89y¦\x0cqAK\tp\x95\x99ÔNj=Wn\x16\x94\x0cu!¯ñ\x13Qü[e8_ÂóU\x10\x1av_+%Q_¡ù\x87=\x08~ciÎ_Ï[\x8f#AëT\x14©qG\x89#Z«L\x9b¢\x94WL\x1dV¶R03\x84æ^ßr\x1fÃÈ\x1d\x8e Læª&®x\x94?TAÒD\x14£i\x82J\x15=w~\x03\x0c\xa0¾5\x02f5T\x91ol¢bIÞfk¬¡27W16(}6\x92\x87\n®xm0\x1a\n<8(à}ñ\x88̾\x17g\x9bj6\x8fI&\x12\x9aÂ\x9a_F\x1a\r[\x1dK\x15<.±DjcIy`98d>\x197Z\x91£%tIJ\x820\x93|\x07\x8dnÚ QÂ!Pf\x1d\nåòf\x91\x1d#S¾|\x9ff[d>O=T$ݶI\x9e»QÛÂ\x1d"¿U=û´F÷\x83C}wA\xa0É\x8aD\x93x»\x85\x7f\x14^\x0eL'
done:
100 generations
How do I exactly access the 100 from the method in the class?
import random
class GeneticAlgorithm(object):
def __init__(self, genetics):
self.genetics = genetics
pass
def run(self):
population = self.genetics.initial()
while True:
fits_pops = [(self.genetics.fitness(ch), ch) for ch in population]
if self.genetics.check_stop(fits_pops): break
population = self.next(fits_pops)
pass
return population
def next(self, fits):
parents_generator = self.genetics.parents(fits)
size = len(fits)
nexts = []
while len(nexts) < size:
parents = next(parents_generator)
cross = random.random() < self.genetics.probability_crossover()
children = self.genetics.crossover(parents) if cross else parents
for ch in children:
mutate = random.random() < self.genetics.probability_mutation()
nexts.append(self.genetics.mutation(ch) if mutate else ch)
pass
pass
return nexts[0:size]
pass
class GeneticFunctions(object):
def probability_crossover(self):
r"""returns rate of occur crossover(0.0-1.0)"""
return 1.0
def probability_mutation(self):
r"""returns rate of occur mutation(0.0-1.0)"""
return 0.0
def initial(self):
r"""returns list of initial population
"""
return []
def fitness(self, chromosome):
r"""returns domain fitness value of chromosome
"""
return len(chromosome)
def check_stop(self, fits_populations):
r"""stop run if returns True
- fits_populations: list of (fitness_value, chromosome)
"""
return False
def parents(self, fits_populations):
r"""generator of selected parents
"""
gen = iter(sorted(fits_populations))
while True:
f1, ch1 = next(gen)
f2, ch2 = next(gen)
yield (ch1, ch2)
pass
return
def crossover(self, parents):
r"""breed children
"""
return parents
def mutation(self, chromosome):
r"""mutate chromosome
"""
return chromosome
pass
if __name__ == "__main__":
"""
example: Mapped guess prepared Text
"""
class GuessText(GeneticFunctions):
def __init__(self, target_text,
limit=100, size=100,
prob_crossover=0.9, prob_mutation=0.2):
self.target = self.text2chromo(target_text)
self.counter = 0
self.limit = limit
self.size = size
self.prob_crossover = prob_crossover
self.prob_mutation = prob_mutation
pass
# GeneticFunctions interface impls
def probability_crossover(self):
return self.prob_crossover
def probability_mutation(self):
return self.prob_mutation
def initial(self):
return [self.random_chromo() for j in range(self.size)]
def fitness(self, chromo):
# larger is better, matched == 0
return -sum(abs(c - t) for c, t in zip(chromo, self.target))
def check_stop(self, fits_populations):
self.counter += 1
if self.counter % 100 == 0:
best_match = list(sorted(fits_populations))[-1][1]
fits = [f for f, ch in fits_populations]
best = -(max(fits))
ave = -(sum(fits) / len(fits))
print(
"Generation %3d, average fit %4d, best fit %4d" %
(self.counter, ave, best,
))
print("Your best chromosone at generation %3d" % self.counter)
print("%r" % self.chromo2text(best_match))
pass
return self.counter >= self.limit
def parents(self, fits_populations):
while True:
father = self.tournament(fits_populations)
mother = self.tournament(fits_populations)
yield (father, mother)
pass
pass
def crossover(self, parents):
father, mother = parents
index1 = random.randint(1, len(self.target) - 2)
index2 = random.randint(1, len(self.target) - 2)
if index1 > index2: index1, index2 = index2, index1
child1 = father[:index1] + mother[index1:index2] + father[index2:]
child2 = mother[:index1] + father[index1:index2] + mother[index2:]
return (child1, child2)
def mutation(self, chromosome):
index = random.randint(0, len(self.target) - 1)
vary = random.randint(-5, 5)
mutated = list(chromosome)
mutated[index] += vary
return mutated
# internals
def tournament(self, fits_populations):
alicef, alice = self.select_random(fits_populations)
bobf, bob = self.select_random(fits_populations)
return alice if alicef > bobf else bob
def select_random(self, fits_populations):
return fits_populations[random.randint(0, len(fits_populations)-1)]
def text2chromo(self, text):
return [ord(ch) for ch in text]
def chromo2text(self, chromo):
return "".join(chr(max(1, min(ch, 255))) for ch in chromo)
def random_chromo(self):
return [random.randint(1, 255) for i in range(len(self.target))]
pass
GeneticAlgorithm(GuessText("""The smartest and fastest Pixel yet.
Google Tensor: Our first custom-built processor.
The first processor designed by Google and made for Pixel, Tensor makes the new Pixel phones our most powerful yet.
The most advanced Pixel Camera ever.
Capture brilliant color and vivid detail with Pixels best-in-class computational photography and new pro-level lenses.""")).run()
print('done:')
print("%3d " 'generations' % counter)
pass
Define the GuessText first. Then access the counter.
gt = GuessText("""The smartest and fastest Pixel yet.
Google Tensor: Our first custom-built processor.
The first processor designed by Google and made for Pixel, Tensor makes the new Pixel phones our most powerful yet.
The most advanced Pixel Camera ever.
Capture brilliant color and vivid detail with Pixels best-in-class computational photography and new pro-level lenses.""")
GeneticAlgorithm(gt).run()
print('done:')
print("%3d " 'generations' % gt.counter)
Edit: Added Minimal Reproducible Problem Example
I'm trying to create a wrapper class to emulate an ArrayList that is thread-safe. All methods seem to work fine, but the resizeBackingArray method isn't working. I've gathered that this is because I'm reassigning the value that belongs to the object, not the class, so the resized backing array won't be visible to all threads.
What would be the best way to fix this? I know the multiprocessing.manager has functionality to use a list, but I was hoping to use the faster ctype array.
You'll notice in the output that the array has to be resized since 15 elements are added to an array with an initial capacity of 10. However, after resizing, the copy of the list available to the main.py has a length of 10, while the size has been incremented to 15.
Output:
Resizing
Size of Array: 15
Length of Array: 10
Done!
From main.py
def addToList(aList):
for x in range(0, 15):
aList.add(x)
if __name__ == "__main__":
import sys
safeArray = ThreadSafeArray.SafeArrayList()
p3 = multiprocessing.Process(target=addToList, args=(safeArray,))
p3.start()
p3.join()
print("Size of Array: " + str(safeArray.getSize()))
print("Length of Array: " + str(safeArray.lengthOfBackingArray()))
print("Done!")
From ThreadSafeArray.py
import multiprocessing
import sys, traceback
class SafeArrayList:
def __init__(self, initSize = 10):
self.arr = multiprocessing.Array('i', initSize)
self.size = multiprocessing.Value('i', 0)
self.lock = multiprocessing.RLock()
#Doubles the size of the array
def resizeBackingArray(self):
#print("resizing")
with self.lock:
newArr = multiprocessing.Array('i', self.size.value * 2)
for num in range(0,self.size.value):
newArr[num] = self.arr[num]
self.arr = newArr
def add(self, num):
with self.lock:
try:
if self.size.value == len(self.arr):
print("Resizing")
self.resizeBackingArray()
if self.size.value == len(self.arr):
print("ERROR")
self.arr[self.size.value] = num
self.size.value = self.size.value + 1
except:
print ('-'*60)
print("Error")
print(sys.exc_info())
traceback.print_exc(file=sys.stdout)
print ('-'*60)
print("Printing " + str(num))
print("Size = " + str(self.size.value) + "\nLength = " + str(len(self.arr)))
self.printArray()
def get(self, index):
with self.lock:
if index < 0 or index >= self.size.value:
return None
else:
return self.arr[index]
def getSize(self):
return self.size.value
def lengthOfBackingArray(self):
return len(self.arr)
def printArray(self):
print("Printing Array")
for x in range(0, self.size.value):
print(str(self.arr[x]))
This question already has an answer here:
python function called but not returning value. Should be simple
(1 answer)
Closed 6 years ago.
I'm quite new to Python and this is for programming project in my CS course. The code seems to work perfectly EXCEPT on the last line of code:
return finalWord
does not return anything. I have tried replacing this with:
print(finalWord)
and it does print everything correctly.
Essentially in the program, I must create a Random class that pseudo-randomly generates numbers and then in the class Nonce, add several different words to the dictionary, and using the dictionary, create new, random words.
class Random:
def __init__(self, seed):
self.seed = seed
def next(self, range):
self.seed = (7 ** 5 * self.seed) % (2 ** 31 - 1)
return self.seed % range
def choose(self, objects):
return objects[self.next(len(objects))]
class Nonce:
def __init__(self, seed):
self.first = []
self.follow = {}
self.random = Random(seed)
def add(self, word):
self.first += [word[0]]
for x in range(0, len(word) - 1):
self.follow.setdefault(word[x], []).append(word[x + 1])
return None
def make(self, size):
nextLetter = self.random.choose(self.first)
finalWord = nextLetter
for x in range(1, size):
if nextLetter in self.follow:
followList = self.follow[nextLetter]
nextLetter = self.random.choose(followList)
finalWord += nextLetter
else:
finalWord += self.random.choose(self.first)
return finalWord
potato = Nonce(101)
potato.add('python')
potato.add('java')
potato.add('html')
potato.make(5)
Thanks in advance.
If you are calling the function directly, then you must either do something with the returned value (like printing it) or store it in a variable for later use. The code is "not working" because you are never calling the function, at least not in the excerpt that you provided.
Printing the response:
print(instance_name.make())
Storing it in a variable:
variable_name = instance_name.make())
The code is where the instance of the class is called instance_name
In your code, you wrote potato.make(5). The function runs, but does not print anything or store it in a variable. To print the response, you would need to do the following:
print(potato.make(5))
I've been told to write a simple program that generates coupon codes, which should offer more than two algorithms (any two) and that the algorithm and the number of codes generated should be read from a config file. Also I've been told that the solution would involve using a known design pattern and that I should look for what pattern is.
I've come up with two solutions for this, but I don't think I've found a proper OOP design pattern that fits for the problem, since objects are data with methods that operate over that data, and in this problem there is little data to operate over, it's more a function (functional?) problem to my naive eyes. Here are the two, one is basically executing the proper static method for the algorithm in the config file and the other returns a reference to a function. Both generate the numbers and print them to the screen.
First method:
class CouponGenerator:
SEQUENTIAL_NUMBERS = "sequentialNumbers"
FIBONACCI_NUMBERS = "fibonacciNumbers"
ALPHANUMERIC_SEQUENCE = "alphanumericSequence"
quantity = 0
algorithm = ""
def __init__(self, quantity, algorithm):
self.quantity = quantity
self.algorithm = algorithm
def generateCouponList(self):
numbers = list()
if self.algorithm == self.SEQUENTIAL_NUMBERS:
numbers = CouponGenerator.generateSequentialNumbers(self.quantity)
elif self.algorithm == self.FIBONACCI_NUMBERS:
numbers = CouponGenerator.generateFibonacciSequence(self.quantity)
for number in numbers:
print number
#staticmethod
def getCouponGenerator(configFile):
cfile = open(configFile)
config = cfile.read()
jsonconfig = json.loads(config)
cg = CouponGenerator(jsonconfig['quantity'], jsonconfig['algorithm'])
return cg
#staticmethod
def generateSequentialNumbers(quantity):
numbers = list()
for n in range(1, quantity+1):
zeroes = 6-len(str(n))
numbers.append(zeroes*"0"+str(n))
return numbers
#staticmethod
def generateFibonacciSequence(quantity):
def fib(n):
a, b = 0, 1
for _ in xrange(n):
a, b = b, a + b
return a
numbers = list()
for n in range(1, quantity+1):
number = fib(n)
zeros = 6-len(str(number))
numbers.append(zeros*"0"+str(number))
return numbers
if __name__ == "__main__":
generator = CouponGenerator.getCouponGenerator("config")
generator.generateCouponList()
Second solution:
class CouponGenerator:
#staticmethod
def getCouponGenerator(algorithm):
def generateSequentialNumbers(quantity):
numbers = list()
for n in range(1, quantity+1):
zeroes = 6-len(str(n))
numbers.append(zeroes*"0"+str(n))
return numbers
def generateFibonacciSequence(quantity):
def fib(n):
a, b = 0, 1
for _ in xrange(n):
a, b = b, a + b
return a
numbers = list()
for n in range(1, quantity+1):
number = fib(n)
zeros = 6-len(str(number))
numbers.append(zeros*"0"+str(number))
return numbers
generators = {"sequentialNumbers": generateSequentialNumbers,
"fibonacciNumbers": generateFibonacciSequence}
return generators[algorithm]
class CouponGeneratorApp:
configFile = "config"
def __init__(self):
cfile = open(self.configFile)
config = cfile.read()
self.jsonconfig = json.loads(config)
self.generateCouponCodes()
def generateCouponCodes(self):
generator = CouponGenerator.getCouponGenerator(self.jsonconfig["algorithm"])
numbers = generator(self.jsonconfig["quantity"])
for n in numbers:
print n
if __name__ == "__main__":
app = CouponGeneratorApp()
If you want to make it a little more object oriented I suggest you use some kind of strategy pattern, that means, use a class per generation algorithm (which should have a common interface) and specify that CouponGenrator use an object which implements this interface to do whatever it has to do. This is theory and making interface and everything in your case might be a little to much.
http://en.wikipedia.org/wiki/Strategy_pattern
you could try something like :
class SequentialGenerator(Object):
def implementation():
...
class FibonacciGenerator(Object):
def implementation():
...
class CouponGenerator(Object):
def set_generator(generator):
# set self.generator to either an instance
# of FibonacciGenerator or SequentialGenerator
def generate_coupon_code():
# at some point calls self.generator.implementation()
I have implemented the following class to generate either 'p' or 'q' based on a input frequency of 'p'. However, this implementation breaks if the frequency gets smaller than the size of the list used to store the options. Is there a way in which I can implement this to work for any value of p?
from random import random
class AlleleGenerator(object):
"""
allele generator - will break if p < 0.001
"""
def __init__(self, p):
"""construct class and creates list to select from"""
self.values = list()
for i in xrange(int(1000*p)):
self.values.append('p')
while len(self.values) <= 1000:
self.values.append('q')
def next(self):
"""Returns p or q based on allele frequency"""
rnd = int(random() * 1000)
return self.values[rnd]
def __call__(self):
return self.next()
Don't use self.values. In next, just generate a random number between 0 and 1, and return 'p' if the random number is less than p:
from random import random
class AlleleGenerator(object):
def __init__(self, p):
"""construct class and creates list to select from"""
self.p = p
def next(self):
"""Returns p or q based on allele frequency"""
return 'p' if random() < self.p else 'q'
def __call__(self):
return self.next()
Also, be careful not to use classes when a function suffices.
For example, you might consider using a generator function:
from random import random
def allele_generator(p):
while True:
yield 'p' if random() < p else 'q'
agen = allele_generator(0.001)
for i in range(3):
print(next(agen))