0

I want to use genetic algorithm to find five parameters of an equation with this code:

import random
import decimal
decimal.getcontext().prec = 100

def foo (a, b, c, x, coeff):                 
    return a * x ** coeff + b * x + c - 550

def fitness (a, b, c, x, coeff):
    ans = foo (a, b, c, x, coeff)
    if ans == 0:
        return 99999
    else:
        return abs (1/ans)


# generate solutions
solutions = []

for s in range(1000):
    solutions.append(
    (random. uniform (0, 10000),
    random.uniform(0, 10000),
    random.uniform(0, 10000),
    random.uniform(0, 10000),
    random.uniform(0,10000)))

for i in range (10000):
    rankedsolutions = []
    for s in solutions:
        rankedsolutions.append((fitness (s[0],s[1],s[2],s[3],s[4]),s))
        rankedsolutions.sort()
        rankedsolutions.reverse()
        print (f"=== Gen {i} best solutions")
        print (rankedsolutions [0])

        bestsolutions = rankedsolutions [:100]

        elements = []
        for s in bestsolutions:
            elements.append(s[1][0])
            elements.append(s[1][1])
            elements.append(s[1][2])
            elements.append(s[1][3])
            elements.append(s[1][4])
            
        newGen = []
        for _ in range(1000):
            e1 = random.choice (elements) * random.uniform(0.99,1.01)
            e2 = random.choice (elements) * random.uniform(0.99,1.01)
            e3 = random.choice (elements) * random.uniform(0.99,1.01)
            e4 = random.choice (elements) * random.uniform(0.99,1.01)
            e5 = random.choice (elements) * random.uniform(0.99,1.01)
            newGen.append((e1,e2,e3,e4,e5))

        solutions=newGen

If i run this code i got this error message:

"OverflowError: (34, 'Result too large')"

How can i handle this error?

Is there a general solution to change the float to decimal in an elegant way?

Any ideas?

  • This may be relevant: https://stackoverflow.com/questions/28081091/what-is-the-largest-number-the-decimal-class-can-handle. In your case though, you need to represent numbers up to at least 10000 ** 10000 (=1e40000), which is probably going to be a stretch. – slothrop Mar 28 '23 at 08:35

1 Answers1

0

I found a solution which handles the error:

import random
import decimal
decimal.getcontext().prec = 10

def foo(a, b, c, x, coeff):
    return a * x ** coeff + b * x + c - 550

def fitness(a, b, c, x, coeff):
    ans = foo(a, b, c, x, coeff)
    if ans == 0:
        return decimal.Decimal('99999')
    else:
        return abs(decimal.Decimal('1') / ans)

# generate solutions
solutions = []

for s in range(1000):
    solutions.append((
        decimal.Decimal(random.uniform(0, 10000)),
        decimal.Decimal(random.uniform(0, 10000)),
        decimal.Decimal(random.uniform(0, 10000)),
        decimal.Decimal(random.uniform(0, 10000)),
        decimal.Decimal(random.uniform(0, 10000))
    ))

for i in range(10000):
    rankedsolutions = []
    for s in solutions:
        rankedsolutions.append((fitness(s[0], s[1], s[2], s[3], s[4]), s))
    rankedsolutions.sort()
    rankedsolutions.reverse()
    print(f"=== Gen {i} best solutions")
    print(rankedsolutions[0])

    bestsolutions = rankedsolutions[:100]

    elements = []
    for s in bestsolutions:
        elements.append(s[1][0])
        elements.append(s[1][1])
        elements.append(s[1][2])
        elements.append(s[1][3])
        elements.append(s[1][4])

    newGen = []
    for _ in range(1000):
        e1 = random.choice(elements) * decimal.Decimal(random.uniform(0.99, 1.01))
        e2 = random.choice(elements) * decimal.Decimal(random.uniform(0.99, 1.01))
        e3 = random.choice(elements) * decimal.Decimal(random.uniform(0.99, 1.01))
        e4 = random.choice(elements) * decimal.Decimal(random.uniform(0.99, 1.01))
        e5 = random.choice(elements) * decimal.Decimal(random.uniform(0.99, 1.01))
        newGen.append((e1, e2, e3, e4, e5))

    solutions = newGen

By changing the decimal.getcontext().prec value to number of decimals can be set