Python Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me

The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.

Go Back   Dev Shed ForumsProgramming LanguagesPython Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old November 11th, 2012, 01:21 PM
russ123 russ123 is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Nov 2012
Posts: 19 russ123 User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 8 h 21 m 37 sec
Reputation Power: 0
Project | find_sequence_function() for python

Hi all

I wonder if this is allowed, but this isn't really a question. My apologies if it's not. I used to use www.python-forum.org and now their down for over a week as the site was bought by the members and were planning re-renovations, so hoping that's why. Anyways, there it was ok to post and update your projects in a new thread in the "General" or "Bar" sections.

This is my project. I was trying to solve a projecteuler problem related to the ulam spiral which involved the integers that lay on the diagonals of the spiral. After some videos to recap on how to find a sequence function (interesting memories of high school ) I managed to derive a function for one diagonal but the second one had a problem. Anyways long story short... I saw that Mathematica has a module or function or whatever for this called FindSequenceFunction() that attempts to find a simple mathematical function for a given sequence. I thought that would be cool but couldn't find it in Python.

So I've also been interested in Evolutionary Computation, specifically for now, Genetic Algorithms and Genetic Programming. I've used a GA once to optimize a small set of metric effectively and thought I would try and step it up a level. So I'm going to try and use a GA to implement the find_sequence_function().

I've been thinking about and working on this intermittently for a few days so this is my progress so far. These two blocks are from the same script but I separated them here.

Design
Code:

Goal:
-----

    find_sequence_function(seq, runtime)

        [0, 1, 4, 9, 16] --> 'x^2'

        Tries to find the sequence function for the given sequence



Concept:
--------

    Putting a mathematical expression in form suitable for the GA.


        infix notation:

            2 + 10x + x^2


        prefix notation: (arity of 2)

            + 2 + * 10 x ^ x 2


        like lisp: still with arity of 2

            (+ 2 (+ (* 10 x) (^ x 2)))



        In a python list form:

            ['+', 2, ['+', ['*', 10, x], ['^', x, 2]]]



    How expressions get evaluated

             operator                  func
               /  \          or        /  \
              /    \                  /    \
        operand    operand          arg    arg



    Eg. evaluate(['+', 2, ['+', ['*', 10, x], ['^', x, 2]]])


                add
               /   \
              /     \
             2      add
                   /   \
                  /     \
               mul       pow
              /  \       /  \
             /    \     /    \
            10     x   x      2




Prototype (unfinished)code

python Code:
Original - python Code
  1. from random import randint, choice, shuffle
  2. from time import clock
  3. from copy import deepcopy
  4. import pickle
  5.  
  6.  
  7.  
  8. # ----------------------------- Operators ------------------------------------|
  9.  
  10. add = lambda a, b: a + b
  11. sub = lambda a, b: a - b
  12. mul = lambda a, b: a * b
  13. div = lambda a, b: float(a) / b
  14. # pow --> builtin
  15.  
  16. symb_to_op = {'+':add,
  17.               '-':sub,
  18.               '*':mul,
  19.               '/':div,
  20.               '^':pow}
  21.  
  22. op_to_symb = dict([(symb_to_op[symb], symb)
  23.                    for symb in symb_to_op])
  24.  
  25.  
  26.  
  27. # ---------------------- Expression Functions --------------------------------|
  28.  
  29. def evaluate(expr, x):
  30.     '''
  31.     evaluate(['+', 1, 'x'], 2)  -->  3
  32.     '''
  33.     if type(expr) is int:
  34.         return expr
  35.     else:
  36.         try:
  37.             op, a, b = symb_to_op[expr[0]], expr[1], expr[2]
  38.             a = evaluate(a, x) if type(a) is list else (x if a is 'x' else a)
  39.             b = evaluate(b, x) if type(b) is list else (x if b is 'x' else b)
  40.             if a is 'er' or b is 'er':
  41.                 return 'er'
  42.             elif (a > 1000 or b > 1000) and expr[0] == '^':
  43.                 return 'er'
  44.             elif (a > 1000000 or b > 1000000) and expr[0] == '*':
  45.                 return 'er'
  46.             else:
  47.                 return op(a, b)
  48.         except (ZeroDivisionError, OverflowError, ValueError):
  49. ##            print 'error!'###debugline
  50.             return 'er'
  51.  
  52.  
  53. def infix(expr):
  54.     '''
  55.     ['+', 1, 'x']  -->  '(1 + x)'
  56.     '''
  57.     symb, a, b = expr[0], expr[1], expr[2]
  58.     a = infix(a) if type(a) is list else a
  59.     b = infix(b) if type(b) is list else b
  60.     return '(%s %s %s)' % (a, symb, b)
  61.  
  62.  
  63. ##def prefix(expr):
  64. ##    '''
  65. ##    '(1 + x) --> ['+', 1, 'x']
  66. ##    '''
  67. ##    # ?
  68. ##    return
  69.  
  70.  
  71. def random_expr(max_depth=6):
  72.     if max_depth == 0:
  73.         return [choice(['+', '-', '*', '/', '^']),
  74.                 randint(1, 5),
  75.                 randint(1, 5)]
  76.     else:
  77.         return [choice(['+', '-', '*', '/', '^']),
  78.                 choice([random_expr(max_depth-1), randint(1, 5), 'x']),
  79.                 choice([random_expr(max_depth-1), randint(1, 5), 'x'])]
  80.  
  81.  
  82. def test_expr(expr, max_time=1e-5):
  83.     '''
  84.     tests for viable expr; returns True if passed else False
  85.     '''
  86.     start = clock()
  87.     a = evaluate(expr, 1.1)
  88.     end = clock()
  89.  
  90.     if end - start > max_time:
  91.         # instances where max_time exceeded due to outside processes
  92.         # that have nothing to do with the expression will have to be
  93.         # considered collatoral or waste for the sake of efficiency.
  94.         return False
  95.     else:
  96.         pass
  97.     b = evaluate(expr, 1.23456)
  98.     if a == b:
  99.         # either 'x' is not in expression or operation on x nullified
  100.         # since 1.123456 and 1 for x should not produce the same result.
  101.         return False
  102.     else:
  103.         return True
  104.  
  105.  
  106. def max_depth(expr, cur_depth=0):
  107.     '''
  108.     ['+', 1, ['-', 2, 3]]   -->  1
  109.     ['+', 1, 2]             -->  0
  110.     returns depth of nesting in expression
  111.     '''
  112.     if type(expr[1]) is list:
  113.         a = max_depth(expr[1], cur_depth + 1)
  114.     else:
  115.         a = cur_depth
  116.     if type(expr[2]) is list:
  117.         b = max_depth(expr[2], cur_depth + 1)
  118.     else:
  119.         b = cur_depth
  120.     return a if a > b else b
  121.  
  122.  
  123. def get_any_list_at_depth(expr, depth):
  124.     '''
  125.     get_..._depth(['+', 1, ['-', 2, ['*', 3, 4]]], 0)  -->  ['-', 2, ['*', 3, 4]]
  126.     get_..._depth(['+', 1, ['-', 2, ['*', 3, 4]]], 1)  -->  ['*', 3, 4]
  127.     get_..._depth(['+', 1, ['-', 2, ['*', 3, 4]]], 2)  -->  False
  128.     '''
  129.     if type(expr[1]) is list:
  130.         if depth > 0:
  131.             a = get_any_list_at_depth(expr[1], depth - 1)
  132.         else:
  133.             a = expr[1]
  134.     else:
  135.         a = False
  136.  
  137.     if type(expr[2]) is list:
  138.         if depth > 0:
  139.             b = get_any_list_at_depth(expr[2], depth - 1)
  140.         else:
  141.             b = expr[2]
  142.     else:
  143.         b = False
  144.  
  145.     if not a and not b:
  146.         return False
  147.     elif not b:
  148.         return a
  149.     elif not a:
  150.         return b
  151.     else:
  152.         return a if randint(0, 1) else b
  153.  
  154.  
  155.  
  156. #-------------------- Genetic Algorithm Functions ----------------------------|
  157.  
  158. def select(popul, n):
  159.     '''
  160.     returns n individuals from population
  161.     uses roulette wheel selection method according to individual fitness
  162.     wheel contains integer corresponding to indexes of popul list.
  163.     '''
  164.     popul.sort()
  165.     wheel = []
  166.  
  167.     # find min score for elite group
  168.     m = popul[0][0]
  169.     for i in range(len(popul) / 2):
  170.         if popul[i][0] < m:
  171.             m = popul[i][0]
  172.  
  173.     # find minimized total of elite group
  174.     total = 0
  175.     for i in range(len(popul) / 2):
  176.         score = popul[i][0] - m
  177.         total += score
  178.  
  179.     # add elite group to wheel
  180.     for i in range(len(popul) / 2):
  181.         score = popul[i][0] - m
  182.         perc = int((score / total) * 100)
  183. ##        wheel += [i] * perc###debugline
  184.         wheel += [i] * (perc * (len(popul) / 100))
  185.  
  186.     print 'wheel:', len(wheel), 'popul:', len(popul)###debugline
  187.     # add buffer to wheel
  188.     wheel += range(len(popul))
  189.  
  190.     print 'wheel:', len(wheel), 'popul:', len(popul)###debugline
  191.     return###debugline
  192.    
  193.  
  194. ##    # 1. Create elite population
  195. ##    elite = deepcopy(popul[:len(popul) / 2])
  196. ##
  197. ##    # 2. Minimize fitness scores in elite.
  198. ##    m = min(elite)[0]
  199. ##    for ind in elite:
  200. ##        end[0] -= m
  201. ##
  202. ##    # 3. Index Wheel for elite group.
  203. ##    wheel = []
  204. ##    total_score = sum([n[0] for n in elite])
  205. ##    for ind in elite:
  206. ##        ind_perc =
  207.  
  208.  
  209. ##    total_score = 0.0
  210. ##    for ind in popul:
  211. ##        try:
  212. ##            total_score += ind[0]
  213. ##        except OverflowError:
  214. ##            ind[0] = 0
  215. ##    index_wheel = []
  216. ##    for i in range(len(popul)):
  217. ##        ind_perc = ind[0] / total_score
  218. ##        print '\tind_perc:', ind_perc
  219. ##        index_wheel += [i] * int(ind_perc * 100)
  220. ##    diff = 100 - len(index_wheel)
  221. ##    print 'wheel length:', len(index_wheel)
  222. ####    print diff###debugline
  223. ##    return###debugline
  224. ##    # Padding
  225. ##    index_wheel += range(len(popul))
  226. ##    return chosen
  227.  
  228.  
  229. def combine(pair, mutation_prob=2):
  230.     '''
  231.     combine([[score, expr], [score, expr]])  -->  [[None, expr], [None, expr]]
  232.     picks a random mutual depth and makes one random operand swap between parents
  233.     original parents not affected
  234.     mutation_prob  -->  1 out of n chances.
  235.     '''
  236.     expr1, expr2 = deepcopy(pair[0][1]), deepcopy(pair[1][1])
  237.  
  238.     # gage depth of both expressions to determin max mutual depth
  239.     depth = max_depth(expr1), max_depth(expr2)
  240.     depth = depth[0] if depth[0] < depth[1] else depth[1]
  241. ##    print 'max depth:', depth###debugline
  242.     depth -= 1
  243.  
  244.     # choose a random depth in range of max depth
  245.     swap_point = randint(-1, depth)
  246.  
  247. ##    print 'swap point:', swap_point###debugline
  248.  
  249.     # make one swap between two random operands at swap_point.
  250.     if swap_point > -1:
  251.         expr1_swap_point = get_any_list_at_depth(expr1, swap_point)
  252.         expr2_swap_point = get_any_list_at_depth(expr2, swap_point)
  253.     else:
  254. ##        print "!!"###debugline
  255.         expr1_swap_point = expr1
  256.         expr2_swap_point = expr2
  257.     operand1 = randint(1, 2)
  258.     operand2 = randint(1, 2)
  259.  
  260.     # mutation
  261.     if not randint(0, mutation_prob-1):
  262.         mut_expr = choice([expr1_swap_point, expr2_swap_point])
  263.         mut_operand = randint(1, 2)
  264.         if type(mut_expr[mut_operand]) is list:
  265.             pass
  266.         elif mut_expr[mut_operand] is 'x':
  267.             pass
  268.         elif type(mut_expr[mut_operand]) is str:
  269.             mut_expr[mut_operand] = choice(['+', '*', '-', '/', '^'])
  270.         else: # is int
  271.             mut_expr[mut_operand] += randint(0, 5)
  272.     else:
  273.         pass
  274.  
  275.     expr1_swap_point[operand1], expr2_swap_point[operand2] = deepcopy(expr2_swap_point[operand2]), deepcopy(expr1_swap_point[operand1])
  276.     return [[0, expr1], [0, expr2]]
  277.  
  278.  
  279. def fitness(ind, target):
  280.     '''
  281.     fitness([score, expr], target)  -->  [score, expr]
  282.     '''
  283.     # get a sequence from expr starting at x = 0
  284.     trash, expr =  ind
  285.     seq = [evaluate(expr, x) for x in range(len(target))]
  286.  
  287.     # check the difference in shape of the curve between target and seq
  288.     curve_dif = [seq[i] - target[i] if seq[i] != 'er' else 'er' for i in range(len(seq))]
  289.  
  290.     # replace 'er' with worst case i.e max difference
  291.     mx = max([n for n in curve_dif if type(n) is not str])
  292.     curve_dif = [mx if i == 'er' else i for i in curve_dif]
  293.  
  294.     # find average difference and subtract from all to normalize curve_dif
  295.     try:
  296.         av = float(sum(curve_dif)) / len(curve_dif)
  297.     except OverflowError:
  298.         av = sum(curve_dif) / len(curve_dif)
  299.     norm_curve_dif = [i - av for i in curve_dif]
  300.  
  301.     # CURVE/SHAPE DIFFERENCE
  302.     total_curv_dif = sum(norm_curve_dif)
  303.  
  304.     # ANGLE OF CURVE DIFFERENCE
  305.     total_angle_dif = sum(map(abs, norm_curve_dif))
  306.  
  307.     # RAW/MAGNITUDE DIFFERENCE
  308.     total_raw_dif = sum(map(abs, curve_dif))
  309.  
  310.     return [(total_curv_dif * metrics[0]) + (total_angle_dif * metrics[1]) + (total_raw_dif * metrics[2]),
  311.             expr]
  312.  
  313.  
  314. def genetic_algorithm_1(target, a, b, c, num_results=1, max_time=60):
  315.     '''
  316.     a: population size
  317.     b: offspring per family
  318.     c: ratio of parents to offspring for next pop selection
  319.     '''
  320.     a = a if a % 2 == 0 else a + 1
  321.     b = b if b >= 2 else 2
  322.     results = []
  323.  
  324.     # 1. Create initial population of a individuals.
  325.     # popul  ->  [[score, expr], ... ]
  326.     popul = []
  327.     while len(popul) < a:
  328.         expr = random_expr()
  329.         if expr and test_expr(expr):
  330.                 popul.append([0, expr])
  331.  
  332.     # 2. Test fitness of individuals.
  333.     popul = [fitness(ind, target) for ind in popul]
  334.     popul.sort()
  335.  
  336.     start = clock()
  337.     generations = 0###debugline
  338.     while len(results) < num_results and clock() - start < max_time:
  339.  
  340.         # 3. Put population into random pairs.
  341.         parents = deepcopy(popul)
  342.         shuffle(parents)
  343.         parents = zip(parents[:a/2], parents[a/2:])
  344.  
  345.         # 4. Combine each pair to produce b children.
  346.         offspring = []
  347.         for pair in parents:
  348.             for children in range(b):
  349.                 child1, child2 = combine(pair)
  350.                 offspring.append(child1)
  351.                 offspring.append(child2)
  352.  
  353. ##        return offspring###debugline
  354.  
  355.         # 5. Test fitness of offspring
  356.         offspring = [child for child in offspring if test_expr(child[1])]
  357.         offspring = [fitness(child, target) for child in offspring]
  358.         offspring.sort()
  359.  
  360.         # 6. Select (a * c) parents.
  361.         popul = popul[:int(a*c)]
  362.         select(popul, int(a*c))###debugline
  363. ##        popul = select(popul, int(a*c))
  364.  
  365.         # 7. Select (a - (a * c)) offspring.
  366.         popul += offspring[:a - int(a * c)]
  367. ##        popul += select(offspring, a - int(a * c))
  368.         select(offspring, (a - int(a*c)))
  369.         popul.sort()
  370.  
  371.         # check for suitable results
  372.  
  373.         generations += 1###debugline
  374.  
  375.     return popul, generations#results
  376.  
  377.  
  378.  
  379. # -------------------------------- Metrics -----------------------------------|
  380.  
  381. try:
  382.     with open('metrics.pkl', 'r') as f:
  383.         metrics = pickle.load(f)
  384. except IOError:
  385.     print "GA metrics not found! loading default."
  386.     metrics = [1, 1, 1]
  387.  
  388.  
  389. # --------------------------------- Main -------------------------------------|
  390.  
  391. def find_sequence_function(seq):
  392.     '''
  393.     [0, 1, 4, 9, 16] --> 'x^2'
  394.     '''
  395.     # ???
  396.     return
  397.  
  398.  
  399. def tune_metrics(runt_time=60):
  400.     '''
  401.     Runs a simple GA for stochastic optimization of metrics
  402.     '''
  403.     global metrics
  404.     # ?
  405.     return
  406.  
  407.  
  408. # ----------------------------- Workbench -----------------------------------|
  409.  
  410.  
  411. target = [(2 + (10*x) + (x**2)) for x in range(10)]
  412.  
  413. popul = [[0, random_expr()] for i in range(500)]
  414. popul = [fitness(i, target) for i in popul]
  415. save = deepcopy(popul)
  416. a = select(popul, 300)
  417.  
  418.  
  419. ##targets = [('x * 2', [x*2 for x in range(10)]),
  420. ##           ('(x * 2) - 1', [(x*2)-1 for x in range(10)]),
  421. ##           ('2 + (10*x) + (x**2)', [(2 + (10*x) + (x**2)) for x in range(10)])]
  422.  
  423. ##targets = [('2 + (10*x) + (x**2)', [(2 + (10*x) + (x**2)) for x in range(10)])]
  424. ##bucket = []
  425. ##
  426. ##for target in targets:
  427. ##    bucket.append(genetic_algorithm_1(target[1], 500, 5, 3/10.0, max_time=2))
  428. ##    result = bucket[-1][0][0][1]
  429. ##    print '-'*20
  430. ##    print 'expression:', target[0]
  431. ##    print 'GA result: ', infix(result)
  432. ##    print target[1]
  433. ##    print [evaluate(result, x) for x in range(10)]
  434.  
  435.  
  436. ##pair = [[0, ['+', 'a', ['+', 'a', ['+', 'a', 'a']]]],
  437. ##        [0, ['+', 'b', ['+', 'b', ['+', 'b', 'b']]]]]
  438. ##
  439. ##print 'parent1', pair[0][1]
  440. ##print 'parent2', pair[1][1]
  441. ##for i in range(10):
  442. ##    print '\n\n'
  443. ##    child = combine(pair)
  444. ##    print '\n'
  445. ##    print pair[0][1]
  446. ##    print child[0][1]
  447. ##    print '\n'
  448. ##    print pair[1][1]
  449. ##    print child[1][1]
  450.  
  451.  
  452. ##pair = [[0, ['+', 'a', ['+', 'a', 'a']]],
  453. ##        [0, ['+', 'b', ['+', 'b', ['+', 'b', 'b']]]]]
  454. ##
  455. ##print '-' * 50
  456. ##print 'parent1', pair[0][1]
  457. ##print 'parent2', pair[1][1]
  458. ##for i in range(10):
  459. ##    print '\n\n'
  460. ##    child = combine(pair)
  461. ##    print '\n'
  462. ##    print pair[0][1]
  463. ##    print child[0][1]
  464. ##    print '\n'
  465. ##    print pair[1][1]
  466. ##    print child[1][1]
  467.  
  468.  
  469. ##def timer(expr, runs):
  470. ##    'returns time to evaluate the expression'
  471. ##    start = clock()
  472. ##    for run in xrange(runs):
  473. ##        evaluate(expr, 7)
  474. ##    end = clock()
  475. ##    return (end - start) / runs
  476.  
  477.  
  478. ##samples = [random_expr() for expr in range(100)]
  479. ##samples = [expr for expr in samples if test_expr(expr)]
  480. ##samples = [expr for expr in samples if evaluate(expr, 2) != evaluate(expr, 7)]
  481.  
  482.  
  483. ##for i in range(100):
  484. ##    samples = [random_expr() for expr in range(100)]
  485. ##    samples = [expr for expr in samples if test_expr(expr)]
  486. ##    samples = [expr for expr in samples if evaluate(expr, 2) != evaluate(expr, 7)]
  487. ##    print '\t', len(samples)
  488.  


I think it's coming together quite well so far. There is one problem I've identified though. Every 5 or so times I run it it will either hang or it will produce one of the errors that are supposed to be handled in the try except block. The try except does seems to be doing it's job other than the one or two occasions where it just seems not to. Still trying to find out why that might be, if anyone knows please feel free to post, or with suggestions, feedback, criticism, etc.


log

I almost wrote clog for code log but ... you can see how that wouln't be very catchy

Mon | 12-11-2012
- added max_operand=200 argument to evaluate() as temporary fix to prevent overly large calculations hanging the machine.
- refactored test_expr() to also test if 'x' exists in exression and moved off workbench.
- started on code for genetic_algorithm.

Tues | 13-11-2012
- Got little more progress on genetic_algorithm(), almost complete.
- Started thinking about fitness() function.
- Made max_depth() function but wondering if there's a better way.
- Started on combine() function and a little stuck on a nice way to impliment it :s
* obviously didn't have allot of free time today or yesterday. Will use the time away from screen to try and refactor ideas rather than code.
* Wondering if this will help get me closer to future job as a developer... or not, still fun though

Wed | 14-11-2012
- Fixed max_depth() function.
- created get_any_list_at_depth() function (long name I know, it's temporary)
- Completed combine function. Shew that was tricky... and a bit messy.
managed to do it thanks to list pointers.
- removed max_operand=200 parameter from evaluate() and added some conditions in the function
instead that gaurd againsts excessive multiplication and power operations appropriately.
- Couldn't sleep so took a look at fitness function and actually put something together.
Now all I have to do is create the selection function which shouldn't be difficult at all, and finish up the GA
so I can do some tests and finally see some results... if any. Will use another GA (I know ga crazy in here) to
find the right settings for the three metrics used in the fitness function for:
curve shape difference
curve angle difference
raw sequence difference
* Note to self: Brute force approaches in the form of GA's can be more work than they seem

Thur | 15-11-2012
- Got GA to a point were it can at least return some results.
- Thought I had completed fitness() function last night, not really. Had much more free time today and it's only 1 in the afternoon, but most of the time went to debugging.
- Still haven't implemented any kind of mutation and metrics are still at [1, 1, 1]
but managed to get something working with just a random seed population and crossover operations and the fitness function I came up with last night.

Code:
GA metrics not found! loading default.
--------------------
expression: x * 2
GA result:  (1 * (x + x))
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
--------------------
expression: (x * 2) - 1
GA result:  ((x + x) - 1)
[-1, 1, 3, 5, 7, 9, 11, 13, 15, 17]
[-1, 1, 3, 5, 7, 9, 11, 13, 15, 17]
--------------------
expression: 2 + (10*x) + (x**2)
GA result:  ((4 + (x + 4)) * (x + 1))
[2, 13, 26, 41, 58, 77, 98, 121, 146, 173]
[8, 18, 30, 44, 60, 78, 98, 120, 144, 170]


Last one was getting there
Each of the three tests were run for 60 seconds and the population returned in sorted order of fitness. The first individual is taken to print the results above. Remember this is nothing but a random seed population, a simple fitness function that takes three different measurements and a crossover function. Quite pleased.
...later...
- Threw in some random mutation in the combine() function.
- Identified a problem with my algorithm. It's being affected by extreme elitism, causing the resulting population after a few generations to consist of clones of the same individual. In other words, it's been infected by Agent Smith. Will refacter GA1 to incorporate the rouletter wheel selection method while still being monogamous, if that still makes a difference.


Frid | 16-11-2012
Didn't do much today. Tried to impliment selection function which was supposed to be one of the easier tasks but failed twice. At this point due to the number of bugs I'm thinking of how the entire thing can be refactored. Not sure if classes would be suitable or what would be the best way to use them in this situation. Back to drawing board I suppose.

Teus | 20-11-2012
Haven't given up, but now that I'm re-factoring everything with classes I've decided to use the opportunity to finally learn some OOP with python. It's coming together.
You can find the work in progress here.

Reply With Quote
  #2  
Old November 11th, 2012, 02:44 PM
russ123 russ123 is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Nov 2012
Posts: 19 russ123 User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 8 h 21 m 37 sec
Reputation Power: 0
Genetic Algorithm

Wikipedia shows a Simple generational genetic algorithm procedure.

I came up with these two algorithms so far. I plan to implement both just to see if there's any difference. Assuming that either will work that is.

Code:
Genetic Algorithm 1: Monogamous


    parameters:

        A   population size
        B   Number of offspring per pair (must be >= 2)
        C   ratio of parents to offspring for new population.
            i.e parents / offspring
            eg. 2/8 = 0.25


    1. Create initial population of A randomly generated expressions.
    2. Put individuals into random pairs. (Population is reduced to half)
    3. Combine parents to produce (B) offspring per pair.
    4. Evaluate and select (A - (A * C)) best offspring for new population.
    5. Select (A * C) best parents for new population.
    6. Repeat from step 2.


    crossover and mutation occur at step 3.
    selection occurs at steps 4 and 5.
    Max pop size: step 3 = (A + (A * B))



Genetic Algorithm 2: Polygamous


    parameters:

        A   population size
        B   ratio of parents to offspring for new population.
            i.e parents / offspring
            eg. 2/8 = 0.25


    1. Create initial population of A randomly generated expressions.
    2. Evaluate all individuals.
    3. Using roulette wheel selection method, pick two parents.
    4. Combine parents to produce one offspring, append to new pop.
    5. Repeat from step 3 until new pop size == (A - (A * B)).
    6. Select (A * B) parents to append to new population.
    7. Repeat from step 3.


    crossover and mutation occur at step 3.
    selection occurs at step 3 and 6.
    Max pop size: at step 6 = (A + (A - (A * B)))


I was just thinking now, some kind of selection method can also take place at step 2 for GA1. Something like paring according to fitness or likeness or both, or perhaps unlikeness. I don't know. Going to call it a day for now.

Reply With Quote
  #3  
Old November 11th, 2012, 07:07 PM
b49P23TIvg's Avatar
b49P23TIvg b49P23TIvg is offline
Contributing User
Dev Shed Loyal (3000 - 3499 posts)
 
Join Date: Aug 2011
Posts: 3,359 b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level)b49P23TIvg User rank is Major (30000 - 40000 Reputation Level) 
Time spent in forums: 1 Month 2 Weeks 3 Days 9 h 43 m 46 sec
Reputation Power: 383
is this problem 28 or 58 or 167 (other?). I haven't yet solved 167. As I recall, quadratic equations fit the diagonals of the Ulam spiral. (Working from center center outward along a diagonal.)

Hey, if you're going to use GA try it for a worthy problem:
http://projecteuler.net/problem=314
That problem, to me, seems suited to GA.
__________________
[code]Code tags[/code] are essential for python code!

Reply With Quote
  #4  
Old November 11th, 2012, 08:34 PM
russ123 russ123 is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Nov 2012
Posts: 19 russ123 User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 8 h 21 m 37 sec
Reputation Power: 0
Quote:
Originally Posted by b49P23TIvg
is this problem 28 or 58 or 167 (other?). I haven't yet solved 167. As I recall, quadratic equations fit the diagonals of the Ulam spiral. (Working from center center outward along a diagonal.)

Hey, if you're going to use GA try it for a worthy problem:
http://projecteuler.net/problem=314
That problem, to me, seems suited to GA.


Woah! That's a hard one. I'm only level 2 and I've managed to do the problems consecutively so far, so don't want to tackle that one for now. Still very interesting though.

The problem this was related to was 58 but it's not to solve the problem. I already solved it using a method from prob 28. I can't remember exactly why but I found that even if I found both quadratics (thanks for mentioning that btw) it still wouldn't work.

The GA is only for the find_sequence_function() which I thought might come in handy, but also I just want to code something

Reply With Quote
  #5  
Old November 11th, 2012, 08:49 PM
russ123 russ123 is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Nov 2012
Posts: 19 russ123 User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 8 h 21 m 37 sec
Reputation Power: 0

Reply With Quote
  #6  
Old November 12th, 2012, 07:16 AM
russ123 russ123 is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Nov 2012
Posts: 19 russ123 User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 8 h 21 m 37 sec
Reputation Power: 0
Found that annoying bug that causes it to hang. I guess I didn't think too carefully about the mathematics of the whole thing, but it was running into expression made up mostly of power operations that were causing astronomical calculations that would freeze my computer.

I solved it temporarily by implementing a max_operand=200 default parameter in the evaluate() function. But that seems like it will limit the value for the x parameter. So thinking of another way to avoid dangerous calculations.

Started implementing GA1. Thinking of how to implement the combination process pro-grammatically. The idea is that an expression will be considered in levels like depicted in the tree form in the Design/concept. The combination function should randomly choose a level and split each parent at that level, combining opposite halves. There's a name for that technique, forgot what it's called.

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming LanguagesPython Programming > Project for find_function() | Find the mathematical expression for a given sequence

Developer Shed Advertisers and Affiliates



Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump

Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 


Powered by: vBulletin Version 3.0.5
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.

© 2003-2013 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap