Как определить лучшие комбинации из 2 списков - PullRequest
3 голосов
/ 16 августа 2011

Я ищу способ создать наилучшую комбинацию людей в группах. Позвольте мне набросать ситуацию.

Скажем, у нас есть люди A, B, C и D. Более того, у нас есть группы 1, 2, 3, 4 и 5. Оба примера и могут быть меньше или больше. Каждый человек дает оценку друг другу. Так, например, А ставки B a 3, C a 2 и так далее. Каждый человек также оценивает каждую группу. (Скажем, оценки 0-5). Теперь мне нужен какой-то алгоритм, чтобы распределить этих людей равномерно по группам, сохраняя их как можно более счастливыми (как в: Они должны быть в высокооплачиваемой группе с высокопоставленными людьми). Теперь я знаю, что люди не могут быть в лучшей группе (ту, которую они оценили в 5), но мне нужно, чтобы они находились в наилучшем из возможных решений для всей группы.

Я думаю, что это сложный вопрос, и я был бы рад, если бы кто-то мог направить меня к более подробной информации об этих типах проблем или помочь мне с алгоритмом, который я ищу.

Спасибо!

EDIT: Я вижу много хороших ответов, но эта проблема слишком велика, и я тоже могу ее решить правильно. Тем не менее, ответы, опубликованные до сих пор, дают мне отличную отправную точку для дальнейшего изучения предмета. Большое спасибо уже!

Ответы [ 3 ]

1 голос
/ 16 августа 2011

после установления этой проблемы NP-Hard я бы предложил в качестве эвристического решения: инструменты искусственного интеллекта.

Возможный подход - крутое восхождение на гору [SAHC] сначала мы определим нашу функцию полезности (пусть это будет u).Это может быть сумма общего счастья во всех группах.
далее мы определяем наш «мир»: S is the group of all possible partitions.
для каждого допустимого раздела s в S мы определяем:
next(s)={all possibilities moving one person to a different group}

Теперь все, что нам нужно сделать, это запустить SAHC со случайным перезапуском:

1. best<- -INFINITY 
2. while there is more time
3. choose a random partition as starting point, denote it as s.
4. NEXT <- next(s)
5. if max{ U(NEXT) } < u(s): //s is the top of the hill
   5.1. if u(s) > best: best <- u(s) //if s is better then the previous result - store it.
   5.2. go to 2. //restart the hill climbing from a different random point.
6. else:
   6.1. s <- max{ NEXT }
   6.2. goto 4.
7. return best //when out of time, return the best solution found so far.

Это алгоритм в любое время , означающий, что он получит лучший результат, если вы дадите ему больше времени для запуска, и в конечном итоге [на бесконечности времени] он найдет оптимальный результат.

1 голос
/ 16 августа 2011

Это пример проблемы оптимизация . Это очень хорошо изучил тип проблем с очень хорошими методами их решения. Читать Программирование Коллективного Разума , которое объясняет это намного лучше чем я.

В принципе, есть три части любой проблемы оптимизации.

  1. Вход в функцию решения проблем.
  2. Решение , выводимое функцией решения проблем.
  3. Функция оценки, которая оценивает, насколько оптимальным является решение забив.

Теперь проблема может быть сформулирована как поиск решения, которое производит самый высокий балл. Для этого сначала нужно придумать формат представить возможное решение, что функция оценки может затем Гол. Предполагая 6 человек (0-5) и 3 группы (0-2), эта структура данных Python будет работать и будет возможным решением:

output = [
    [0, 1],
    [2, 3],
    [4, 5]
    ]

Человек 0 и 1 помещен в группу 0, человек 2 и 3 в группу 1 и т. Д. на. Чтобы оценить это решение, нам нужно знать входные данные и правила для рассчитать выход. Входные данные могут быть представлены этими данными структура:

input = [
    [0, 4, 1, 3, 4, 1,  3, 1, 3],
    [5, 0, 1, 2, 1, 5,  5, 2, 4],
    [4, 1, 0, 1, 3, 2,  1, 1, 1],
    [2, 4, 1, 0, 5, 4,  2, 3, 4],
    [5, 5, 5, 5, 0, 5,  5, 5, 5],
    [1, 2, 1, 4, 3, 0,  4, 5, 1]
    ]

Каждый список в списке представляет рейтинг, который дал человек. За Например, в первом ряду человек 0 дал оценку 0 человеку 0 (вы не может оценить себя), 4 к человеку 1, 1 к человеку 2, 3 к 3, 4 к 4 и 1 человеку 5. Затем он или она оценили группы 0-2 3, 1 и 3 соответственно.

Итак, выше приведен пример правильного решения для данного ввода. Как мы забиваем это? Это не указано в вопросе, только то, что «Лучшая» комбинация желательна, поэтому я произвольно решу, что оценка для решения - сумма счастья каждого человека. каждый счастье человека определяется добавлением его или ее рейтинга группа со средним значением рейтинга для каждого человека в группе, исключая самого человека.

Вот функция подсчета очков:

N_GROUPS = 3
N_PERSONS = 6
def score_solution(input, output):
    tot_score = 0
    for person, ratings in enumerate(input):
        # Check what group the person is a member of.
        for group, members in enumerate(output):
            if person in members:
                # Check what rating person gave the group.
                group_rating = ratings[N_PERSONS + group]

                # Check what rating the person gave the others.
                others = list(members)
                others.remove(person)
                if not others:
                    # protect against zero division
                    person_rating = 0
                else:
                    person_ratings = [ratings[o] for o in others]
                    person_rating = sum(person_ratings) / float(len(person_ratings))
                tot_score += group_rating + person_rating
    return tot_score

Должно быть получено 37,0 баллов за данное решение. Что теперь мы сделаем, чтобы генерировать действительные результаты, отслеживая, какой из них лучше, пока мы не удовлетворены:

from random import choice
def gen_solution():
    groups = [[] for x in range(N_GROUPS)]
    for person in range(N_PERSONS):
        choice(groups).append(person)
    return groups

# Generate 10000 solutions
solutions = [gen_solution() for x in range(10000)]
# Score them
solutions = [(score_solution(input, sol), sol) for sol in solutions]
# Sort by score, take the best.
best_score, best_solution = sorted(solutions)[-1]
print 'The best solution is %s with score %.2f' % (best_solution, best_score)

Запуск этого на моем компьютере выдает:

The best solution is [[0, 1], [3, 5], [2, 4]] with score 47.00

Очевидно, вы можете подумать, что это действительно глупая идея - случайным образом генерировать решения, чтобы бросить на проблему, и это так. Есть много более сложные методы для создания решений, таких как имитация отжиг или генетическая оптимизация. Но все они основаны на том же рамки, как указано выше.

1 голос
/ 16 августа 2011

Проблема NP-сложна: вы можете уменьшить максимальную упаковку треугольников, то есть найти как минимум k треугольников, не пересекающихся по вершинам в графе, до версии, где есть k групп размера 3, никого не волнует, какиегруппа, в которой он находится, и любит всех за 0 или 1. Так что даже этот очень особый случай сложен.

Чтобы решить его, я бы попытался использовать ILP : иметь двоичные переменные g_ikуказание, что человек i находится в группе k, с ограничениями для обеспечения того, чтобы человек находился только в одной группе и группа имела соответствующий размер.Кроме того, двоичные переменные t_ijk, которые указывают, что люди i и j вместе в группе k (обеспечивается t_ijk <= 0,5 g_ik + 0,5 g_jk), и двоичные переменные t_ij, которые указывают, что i и j вместе в любой группе (обеспечивается t_ij <=sum_k t_ijk).Затем вы можете максимизировать функцию счастья при этих ограничениях. </p>

Этот ILP имеет очень много переменных, но современные решатели довольно хороши, и этот подход очень прост в реализации.

...