def formate_teams(k, agents):
    alpha = 0.58/3
    beta = 3 * alpha
    gamma = 0.1

    alpha_vector = np.array([0, alpha, alpha, alpha, 0])
    beta_vector = np.array([0, 0, (-1) * beta, 0, 0])
    #gamma_vector = np.array([0, 0, 0, 0, gamma])


    team_distribution = list(calculate_number_of_teams(agents.shape[0],k))
    print "team distribution", team_distribution

    agentsAssigned =[]
    teamDistribution = []
    time1 = time.time()
    while (team_distribution[0][0] > 0 or team_distribution[1][0] > 0):

            if (team_distribution[0][0] > 0):

                combinations = list(itertools.combinations(enumerate(agents), team_distribution[0][1]))
                #generate all possible combinations of number_of_teams calculated above
                elements = list(itertools.combinations(agents, team_distribution[0][1]))

                Result = calculate_g_foreach_combination(elements, alpha_vector, beta_vector, gamma)
                teams_generated, team_dist,agentsUsed = generate_teams(team_distribution[0], Result, combinations,agentsAssigned)
                team_distribution[0] = team_dist

            elif (team_distribution[1][0] > 0):
                combinations = list(itertools.combinations(enumerate(agents), team_distribution[1][1]))
                #print "combinations", combinations
                #generate all possible combinations of number_of_teams calculated above
                elements = list(itertools.combinations(agents, team_distribution[1][1]))

                Result = calculate_g_foreach_combination(elements, alpha_vector, beta_vector, gamma)
                teams_generated, team_dist, agentsUsed = generate_teams(team_distribution[1], Result, combinations,agentsAssigned)
                team_distribution[1] = team_dist
            else:
                print "no teams left"
                break

            time2 = time.time()
            print "time of generating all combinations: ", time2-time1

            for m in teams_generated:
                teamDistribution.append(m)
            for i in agentsUsed:
                if i not in agentsAssigned:
                    agentsAssigned.append(i)



    #print "first distribution: "
    #for i in teamDistribution:
    #    print i
    print  "teamDistribution: ", teamDistribution

    old_F_value=calculate_f(teamDistribution)
    print "first value for all teams: ", old_F_value
    new_F_value =0.0
    t_start= time.time()
    t_end = t_start + 0.5
    count_runs = 0
    end_constraint = 50

    time_table=[]
    f_results=[]
    while (time.time() < t_end and count_runs < end_constraint):
        randomList = random.sample(xrange(len(teamDistribution)),2)
        #print "these are random 2 elements: ", randomList

        agentsValues = []
        newAgentList=[]
        agentsIds = []
        old_g_value = 1
        for z in randomList:
            old_g_value = old_g_value * teamDistribution[z][1]

            for l in teamDistribution[z][0]:
                    agentsValues.append(l[1])
                    agentsIds.append(l[0])
            newAgentList.append(teamDistribution[z])

        print "current g value for selected teams: ", old_g_value

        agentsValues = np.array(agentsValues)

        a = calculate_number_of_teams(len(agentsValues),k)

        length = int(len(agentsValues))
        number_of_teams = int(a[0][0] + a[1][0])

        number1 = a[0][0]
        number2 = a[1][0]
        teamSizes = []
        for i in range(0,number_of_teams):
            if number1 >0:
                teamSizes.append(a[0][1])
                number1 -=1
            else:
                teamSizes.append(a[1][1])
                number2 -=1
        #print teamSizes
        team = []
        Result = {}
        numberOfTeams = len(teamSizes)
        teamSizes.sort()

        if numberOfTeams > 1:
            (partition,maximums) = initPartition(length,number_of_teams)
            #print partition
            while True:
               (partition,maximums) = nextPartition(partition,maximums,number_of_teams,length)
               if partition == None:
                   break
               if filterPartition(partition,teamSizes):
                   #print "Filtered partition = ", partition
                   for i in range(0,number_of_teams):
                       for p in range(0,len(partition)):
                           if (partition[p] == i):
                               team.append(agentsValues[p])
                       x= []
                       y= []
                       z =[]
                       for a in team:
                                 x.append(a[0])
                                 y.append(a[1])
                                 z.append(a[4])
                       max1, max2 = calculate_max(alpha_vector, beta_vector, team)
                       gender = calculate_gender_balance(z)
                       combination = str(partition).replace(', ',"")
                       if combination in Result:
                            Result[combination] = Result[combination] * calculate_g(x, y, gamma, max1, max2, gender)
                       else:
                            Result[combination] = calculate_g(x, y, gamma, max1, max2, gender)
                       team =[]
        elif numberOfTeams == 1:
                print length * [0]
        #print Result
        maxim = max(Result.iteritems(), key=operator.itemgetter(1))[0]
        #sorted_x = sorted(Result.items(), key=operator.itemgetter(1), reverse=True)
        #print "new value for selected teams:", maxim, Result.get(maxim)
        #print "sorted ", sorted_x

        first_team = []
        second_team=[]
        first_team_g = []
        second_team_g=[]
        if old_g_value < Result.get(maxim):
            #print "I'm updating team distribution"
            #print "agentsIds: ", agentsIds
            for index, elem in enumerate(maxim):
                        #print index, elem
                        if (elem == "0"):
                            first_team.append((agentsIds[index-1], agentsValues[index-1]))
                            first_team_g.append(agentsValues[index-1])
                        elif (elem == "1"):
                            second_team.append((agentsIds[index-1], agentsValues[index-1]))
                            second_team_g.append(agentsValues[index-1])
            #print "first_team, second_team: ", first_team, second_team
            g_values = calculate_g_foreach_combination((first_team_g, second_team_g), alpha_vector, beta_vector, gamma)
            new_teams = ((tuple(first_team), g_values.get(0)), (tuple(second_team), g_values.get(1)))

            for index, value in enumerate(randomList):
                #print index, value
                #print teamDistribution[value]
                #print new_teams[index]
                teamDistribution[value] = new_teams[index]
            #print "updated teams: ",     teamDistribution
            new_F_value=calculate_f(teamDistribution)
            f_results.append(new_F_value)
            print "updated value for all teams: ", new_F_value
            count_runs = 0
            time_effect = time.time()
            time_table.append(time_effect-t_start)
        else:
            count_runs += 1

    #print "time_table: ", time_table
    #print "f_results: ", f_results



    optimum = 1.15793102184 #3 members 15 agents[010232021343414] 0.299874562273

    distance_to_optimum = []
    for i in f_results:
        distance_to_optimum.append(i/optimum)

    #all_runs_optimum_ratio.append(distance_to_optimum[-1])
    #all_runs_time.append(time_table[-1])

    # plt.plot(time_table, distance_to_optimum)
    # plt.xlabel('Time')
    # plt.ylabel('Distance to optimum')
    # plt.show()
    return distance_to_optimum[-1], time_table[-1]
def main():

    time_start= time.time()
    alpha = 0.58/3
    beta = 3 * alpha
    gamma = 0.1

    alpha_vector = np.array([0, alpha, alpha, alpha, 0])
    beta_vector = np.array([0, 0, (-1) * beta, 0, 0])

    ##         S   T	E   J
    ##         N   F	I   P
    agent0 = np.array([-0.2,  0.6,  0.6, -0.4,  1]) ##Maggy
    agent1 = np.array([-0.2,  0.6,  0.5,  0.6,  0]) ##Steve ETJ
    agent2 = np.array([-0.2, -0.2, -0.4,  0.6,  0]) ##Marsh I

    agent3 = np.array([ 0.6,  0.2,  0.2, -0.6,  0]) ##Chaz

    agent4 = np.array([-0.2, -0.6,  0.2, -0.2,  0]) ##Benny

    agent5 = np.array([ 0.0,  0.4, -0.8,  0.6,  1]) ##Olive I

    agent6 = np.array([ 0.6,  0.2,  0.6,  0.4,  0]) ##Sam ETJ
    agent7 = np.array([-0.2, -0.2,  0.4,  0.6,  1]) ##Micheline
    agent8 = np.array([ 0.4, -0.4,  0.6,  0.0,  0]) ##Robin
    agent9 = np.array([ 0.1,  0.2, -0.4,  0.2,  0]) ##John I
    agent10 = np.array([ 0.2,  0.8, -0.6, -0.4,  0]) ##Jimmy I
    agent11 = np.array([ 0.6,  0.2,  0.8,  0.6,  1]) ##Camille ETJ
    agent12 = np.array([ 0.4, -0.4,  0.4,  0.6,  1]) ##Annie
    agent13 = np.array([ 0.6, -0.4,  0.6, -0.6,  1]) ##Sandra
    agent14 = np.array([-0.6, -0.4,  0.2, -0.2,  0]) ##Lars
    agent15 = np.array([-0.2, -0.2,  0.4,  0.6,  1]) ##Selena
    agent16 = np.array([-0.6,  1.0,  0.6,  0.6,  0]) ##Brad ETJ
    agent17 = np.array([ 0.6,  0.2,  0.2, -0.2,  0]) ##Carl

    agent18 = np.array([ 0.0,  0.2,  0.4, -0.4,  0]) ##Danton

    agent19 = np.array([-0.2, -0.6,  0.0, -0.8,  1]) ##Lisa

    agents = np.array([agent0 , agent1, agent2, agent3, agent4, agent5, agent6, agent7, agent8, agent9, agent10, agent11, agent12, agent13])#, agent14, agent15, agent16, agent17, agent18, agent19])

    k = 2

    a = calculate_number_of_teams(agents.shape[0],k)
    #print a
    #print a[0]
    #print agents.shape[0]

    length = int(agents.shape[0])
    size = int(a[0][0] + a[1][0])

    number1 = a[0][0]
    number2 = a[1][0]
    teamSizes = []
    for i in range(0,size):
        if number1 >0:
            teamSizes.append(a[0][1])
            number1 -=1
        else:
            teamSizes.append(a[1][1])
            number2 -=1

    print length, size, teamSizes
    teamSizes.sort()

    team = []
    #initial=[1]*(comb(agents.shape[0],k))
    #Result = {n: initial[n] for n in range(comb(agents.shape[0],k))}

    Result = {}
    numberOfTeams = len(teamSizes)
    if numberOfTeams > 1:
        (partition,maximums) = initPartition(length,size)
        while True:
           (partition,maximums) = nextPartition(partition,maximums,size,length)
           if partition == None:
               break
           if filterPartition(partition,teamSizes):
               #print "Filtered partition = ", partition
               for i in range(0,size):
                   for p in range(0,len(partition)):
                       if (partition[p] == i):
                           team.append(agents[p])
                   x= []
                   y= []
                   z = []
                   for a in team:
                             x.append(a[0])
                             y.append(a[1])
                             z.append(a[4])
                   max1, max2 = calculate_max(alpha_vector, beta_vector, team)
                   #print max1, max2
                   count= str(partition).replace(', ',"")

                   gender = calculate_gender_balance(z)
                   if count in Result:
                        #print calculate_g(x, y, gamma, max1, max2, gender)
                        Result[count] = Result[count] * calculate_g(x, y, gamma, max1, max2, gender)
                   else:
                        #print calculate_g(x, y, gamma, max1, max2, gender)
                        Result[count] = calculate_g(x, y, gamma, max1, max2, gender)

                   #if count in Result:
                   #     Result[count] = Result[count] * calculate_g(x, y, max1, max2)
                   #else:
                   #     Result[count] = calculate_g(x, y, max1, max2)
                   #Result.update(count: Result[count] * calculate_g(x, y, max1, max2))
                   #print team
                   team =[]
    elif numberOfTeams == 1:
       print length * [0]

    #print Result
    maxim = max(Result.iteritems(), key=operator.itemgetter(1))[0]
    #sorted_x = sorted(Result.items(), key=operator.itemgetter(1), reverse=True)
    print k," members ", len(agents), " agents", maxim, Result.get(maxim)
    #print "sorted ", sorted_x
    print "time in sec: ", time.time() - time_start