In [97]:
import numpy as np
import functools

In [98]:
def evaluateOrderOne(vector):
    '''
    Input: vector
    '''
    return np.sum(vector)

def __evaluate3Dvector(v):
    #print(v)
    tmp = np.sum(v)
    if tmp == 3:
        return 30
    elif tmp == 2:
        return 0
    elif tmp == 0:
        return 28
    else:
        if v[0]==1 :
            return 14
        elif v[1] == 1:
            return 22
        elif v[2] == 1:
            return 26

def evaluateOrderThree(vector):
    '''
    Input: 3d vector
    '''
    try:
        if vector.shape[0]>3:
            s = 0
            # print(int(vector.shape[0]/3),3)
            newv = np.reshape(vector,(int(vector.shape[0]/3),3))
            # print(newv)
            for v in newv:
                # print(v)
                s += __evaluate3Dvector(v)
            return s
        else:
            return  __evaluate3Dvector(vector)
    except Exception:
        print("vector length invalid",Exception)

In [99]:
evaluateOrderThree(np.array([1,0,0,1,1,0,1,1,0]))
evaluateOrderOne(np.array([1,0,0,1,1,0,1,1,0]))


Out[99]:
5

In [100]:
def bitflip_mutation(bit, probability):
    if np.random.rand() < probability:
        if bit == 1:
            return 0.
        else:
            return 1.
    else:
        return bit


def uniform_crossover(i1,i2):
    D = i1.shape[0]
    u = np.empty((D,))
    for i in range(D):
        # print(P[i1][i],P[i2][i])
        u[i] = np.random.choice(np.array([i1[i],i2[i]]))
    return u

In [101]:
def random_init(number,P,D, evaluate_func):
    '''
    initialize and evaluate the population
    number: number of the individuals
    P: the list for the population and value
    D: dimension
    '''
    for i in range(number):
        vector = np.random.choice(np.array([0,1]),(D,))
        P.append((vector,evaluate_func(vector)))
    return P

In [114]:
def GEAlgorithm():
    '''
    the main algorithm
    '''
    n = 0
    t = 1
    D = 24
    mu = 20
    pm = 1/D # mutation rate
    lambda_ = 30
    evaluate_func = evaluateOrderOne
    # Algorithm 2: The initialization procedure of the population
    P = list()
    P = random_init(mu,P,D,evaluate_func)
    # print(P)
    terminate = False
    x_bsf = (None,-1)
    for x,y in P:
        if y == evaluate_func(np.ones(D)):
            terminate = True
            x_bsf = (x,y)
    print(terminate,x_bsf)
    
    while(not terminate):
        Q = list()
        for i in range(lambda_):
            # Step1: Mating selection: generate two distinct random number
            r = np.arange(len(P))
            np.random.shuffle(r)
            selected = r[:2]
            #print(selected)
            # Step2: Variation operator : Crossover
            u = uniform_crossover(P[selected[0]][0],P[selected[1]][0])
            # print(u)
            # Step3: Variation operator2: Mutation
            vfunc = np.vectorize(functools.partial(bitflip_mutation, probability=pm))
            u = vfunc(u)
            # print(u)
            # Step4: Evaluate
            new_value = evaluate_func(u)
            # print("New value:" + str(newvalue))
            n += 1
            Q.append((u,new_value))
            
            # Step5: Update bsf solution
            
            if(new_value >x_bsf[1]):
                x_bsf=(u,new_value)
            
        # Step6: Environment Selection
        R = P + Q
        sort_result = sorted(R,key=lambda x:x[1],reverse=True)
        P = sort_result[:int(len(R)/2)]
        t += 1
        if(new_value == evaluate_func(np.ones(D))):
            terminate = True

    print("# of generation:", t)
    print("optimal value: %d"%x_bsf[1] )
    return (t,n)


if __name__ == "__main__":
    count = list()
    totaltimes = 1
    for i in range(totaltimes):
        count.append(GEAlgorithm())
        print(count)
    # print("Average # of generations %f" % (sum(count)/float(totaltimes)))


False (None, -1)
# of generation: 26
optimal value: 24
[(26, 750)]