Алгоритм зависимости - найдите минимальный набор пакетов для установки

Я работаю над алгоритмом, цель которого - найти минимальный набор пакетов для установки пакета «X».

Я объясню лучше на примере:

X depends on A and (E or C)
A depends on E and (H or Y)
E depends on B and (Z or Y)
C depends on (A or K)
H depends on nothing
Y depends on nothing
Z depends on nothing
K depends on nothing

Решение - установить: A E B Y.

Вот изображение для описания примера:

Есть ли алгоритм решения проблемы без использования метода грубой силы?

Я уже много читал об алгоритмах, таких как DFS, BFS, Dijkstra и т. Д. Проблема в том, что эти алгоритмы не могут обработать условие «ИЛИ».

ОБНОВЛЕНИЕ

Я не хочу использовать внешние библиотеки.

Алгоритм не должен обрабатывать циклические зависимости.

ОБНОВЛЕНИЕ

Одно из возможных решений могло бы состоять в том, чтобы вычислить все возможные пути каждой вершины и сделать то же самое для каждой вершины возможного пути. Итак, возможный путь для X будет (A E), (A C). Теперь для каждого элемента в этих двух возможных путях мы можем сделать то же самое: A = (EH), (EY) / E = (BZ), (BY) и так далее ... В конце мы можем объединить возможные пути каждой вершины в НАБОРе и выберите тот, длина которого минимальна.

Что вы думаете?


person KLi    schedule 25.05.2015    source источник
comment
Требуется ли синяя зависимость и требуется одна из красных зависимостей?   -  person aioobe    schedule 28.05.2015
comment
Чтобы получить все незначительное количество зависимостей, необходимых для пакета, вам нужны все зависимости AND и столько зависимостей, сколько необходимо. Приведу другой пример. A = B, C, D | F | G, H | L Следовательно, чтобы получить наименьшее количество зависимостей для A u, нужны B, C, только 1 между [DFG] и одна между [HL] Способ выбора между найти кратчайший путь.   -  person KLi    schedule 28.05.2015
comment
Я предполагаю, что это формирует DAG?   -  person aioobe    schedule 28.05.2015
comment
Осторожно, вашего цветового кода недостаточно, он не говорит вам, где разместить круглые скобки.   -  person Yves Daoust    schedule 28.05.2015
comment
Ох, ладно. Я должен был исправить.   -  person KLi    schedule 28.05.2015
comment
@KLi, я предлагаю опубликовать свое решение в качестве ответа, а не помещать его в вопрос. Так что можно будет прокомментировать это напрямую. Также я думаю, картинка совершенно не помогает понять ваш пример; лучше удалить.   -  person dened    schedule 30.05.2015
comment
вы можете попробовать алгоритм аппроксимации с использованием жадного (локального) подхода с некоторым локальным поиском, если необходимо, взяв зависимость с минимальным количеством подзависимостей на каждом шаге   -  person Nikos M.    schedule 30.05.2015
comment
X зависит от A и (E или C) .... может это быть (D, E или C) ... что происходит, когда A- ›B и B-› A. Каков ваш план по предотвращению тупиковых ситуаций. Концепция контекстно-свободной грамматики также имеет набор правил. Терминальные символы. Вы можете проверить это на youtube.com/watch?v=9XKUcm8au4U.   -  person blueray    schedule 31.05.2015
comment
@ Ахмед Исмаил, как я уже писал, мне не нужно обрабатывать циклы.   -  person KLi    schedule 31.05.2015


Ответы (10)


К сожалению, мало надежды найти алгоритм, который намного лучше, чем перебор, учитывая, что проблема на самом деле NP-трудная (но даже не NP-complete).

Доказательством NP-сложности этой проблемы является то, что минимальная проблема вершинного покрытия (хорошо известная как NP-сложная, а не NP-полный) легко сводится к нему:

Дан граф. Создадим пакет P v для каждой вершины v графа. Также создайте пакет X what "and" -requires (P u или P v ) для каждого ребра (u, v) графа. Найдите минимальный набор пакетов для установки, чтобы удовлетворить требованиям X. Тогда v находится в минимальном покрытии вершин графа iff соответствующего пакета P v входит в установочный набор.

person dened    schedule 30.05.2015
comment
Это доказательство остается в силе, даже когда циклические зависимости не разрешены, и даже когда разрешено не более двух альтернатив в предложении OR. - person dened; 30.05.2015
comment
Сказать, что покрытие минимального набора (или вершины) является NP-трудным, но не NP-полным, правильно, но, вероятно, запутает людей излишне. Все такие дискретные задачи оптимизации (Найти минимум ...) можно тривиально превратить в эквивалентные задачи принятия решений (существует ли ... с размером ‹= k?), Которые являются NP-полными. - person j_random_hacker; 31.05.2015
comment
@j_random_hacker, проблема, которая не является NP-полной, не может быть заменена на эквивалентную NP-полную задачу, потому что если для некоторой проблемы существует эквивалентная NP-полная проблема, то сама эта проблема должна быть NP-полной .... И вероятно, явное указание на то, что проблема является одновременно NP-сложной и не NP-полной, оправдано, поскольку это говорит о том, что решение проблемы не только трудно найти, но и трудно проверить. - person dened; 01.06.2015
comment
Под эквивалентом я имел в виду в том смысле, что алгоритм для одного может преобразовываться в алгоритм для другого за разное время. Например, чтобы превратить задачу минимизации в полиномиально множество задач решения, просто решайте проблему принятия решения для k = 0, 1, 2, ... до тех пор, пока не будет получен ответ ДА. Затем, чтобы восстановить решение, несколько раз удалите 1 произвольный элемент (т. Е. 1 вершину для покрытия вершины) из набора возможностей и решите проблему решения для k '= k-1: включите вершину в решение, если ответ НЕТ . - person j_random_hacker; 01.06.2015
comment
@j_random_hacker, я знаю, что любую дискретную задачу оптимизации можно решить, решив серию задач решения. Это может быть полезно при анализе проблемы, но не может упростить расчет или проверку решения, т.е. по-прежнему невозможно изменить любую неполную NP-сложную задачу на NP-полную. Итак, ваш комментарий все еще не имеет для меня никакого смысла ... Есть еще одна причина указать, что проблема является одновременно NP-сложной и не NP-полной: любая NP-полная проблема может быть решена за полиномиальное время, если вдруг P = NP, но это не относится к NP-трудным задачам в целом. - person dened; 01.06.2015
comment
Единственная разница, которую я вижу между проблемой NPC и проблемой NPH, которая не является NPC, но может быть преобразована в полиномиальное количество экземпляров проблемы NPC, заключается в том, что решения последнего типа никогда не сопровождаются короткий сертификат (потому что они зависят от поиска хотя бы 1 NO-решения проблемы NPC). Но так ли уж важно отсутствие сертификатов? Когда случается, что у экземпляра проблемы NPC есть решение NO, для этого тоже нет сертификата - IOW, примерно половина ответов на проблемы NPC не имеет сертификата! - person j_random_hacker; 01.06.2015
comment
@j_random_hacker, это может быть большим делом. Например, может быть важно знать, что не существует эффективного алгоритма проверки того, действительно ли найденное вами вершинное покрытие является минимальным или нет. - person dened; 01.06.2015
comment
Справедливо. Есть различие, и ваш последний пункт дает следствие практической важности, поскольку было бы неплохо иметь способ быстро проверить эвристические решения на оптимальность. Если вы отредактируете, чтобы упомянуть свойство поли-временной эквивалентности, о котором я упоминал ранее, я обязательно добавлю +1. - person j_random_hacker; 01.06.2015
comment
@j_random_hacker, но можете ли вы сначала сказать, почему, по вашему мнению, это свойство все еще важно упоминать? - person dened; 01.06.2015
comment
Я думаю, что высококачественный ответ, заслуживающий одобрения, прояснил бы это, потому что в понимании большинства работающих программистов нет (или нет никакого важного) различия между этими двумя категориями (если они вообще их знают) . Даже во многих статьях по CS говорится о проблемах NP-полной оптимизации с пониманием того, что они могут быть взаимно преобразованы с проблемами принятия решений NPC. Вы, конечно, могли бы сказать, что об этом не нужно упоминать, потому что это не имеет прямого отношения к вопросу OP, но ИМХО, это означает только то, что не упоминание не заслуживает отрицательного голоса. - person j_random_hacker; 02.06.2015

«У меня нет проблемы с» или «(изображение не загружается для меня). Вот мои рассуждения. Скажем, мы берем стандартный алгоритм кратчайшего маршрута, такой как Дейкстра, а затем используем равный вес, чтобы найти лучший путь. лучший Xr снизу 2 варианта

Xr= X+Ar+Er
Xr= X+Ar+Cr

где Ar = - лучший вариант из дерева A = H (и последующие дочерние элементы) или A = Y (и последующие дочерние элементы)

Идея состоит в том, чтобы сначала назначить стандартный вес для каждого варианта or (поскольку и option не является проблемой). И позже для каждого параметра or мы повторяем процесс с его дочерними узлами, пока не дойдем до параметра or.

Однако нам нужно сначала определить, что означает лучший выбор, предположив, что критерием является наименьшее количество зависимостей, т.е. кратчайший путь. По вышеприведенной логике мы назначаем X вес 1.

X=1
X=A and E or C hence X=A1+E1 and X=A1+C1
A= H or Y, assuming H and Y are  leaf node hence A get final weight as 1
hence , X=1+E1 and X=1+C1

Now for E and C
E1=B1+Z1 and B1+Y1 . C1=A1 and C=K1.
Assuming B1,Z1,Y1,A1and K1 are leaf node 

E1=1+1 and 1+1 . C1=1 and C1=1
ie E=2 and C=1

Hence
X=1+2 and X=1+1 hence please choose X=>C as the best route

Надеюсь, это проясняет ситуацию. Также нам нужно позаботиться о циклических зависимостях X => Y => Z => X, здесь мы можем назначить такие узлы равными нулю на уровне родительского или конечного узла и позаботиться о зависимости ».

person mrsachindixit    schedule 28.05.2015
comment
Конечно, сообщите нам о своих выводах. Также необходимо рассмотреть небольшой случай, когда обнаружено 2 или более вариантов с одинаковым весом. Для выбора в таком случае могут применяться дополнительные критерии. - person mrsachindixit; 28.05.2015
comment
а что, если X зависит от A и (B или C), а B зависит от D и (F или G)? Как алгоритм может справиться с тем, что для того, чтобы принять B как зависимость от A, вы ДОЛЖНЫ иметь также D, поскольку это необходимо для B? - person KLi; 28.05.2015
comment
Вот почему я включил обозначение Ar. Ar = - лучший вариант из дерева A = H (и последующих дочерних элементов) или A = Y (и последующих дочерних элементов). Теперь, в соответствии с вашим новым случаем X = A и Br или Cr, наша идея состоит в том, чтобы назначить вес по умолчанию 1 корню до тех пор, пока его полное дочернее дерево не будет разрешено и вычислено. После этого корневой узел получает новый вес вместо исходного веса по умолчанию. См. Также в исходном вопросе E такое же поведение. X зависит от A и (E или C) A зависит от E и (H или Y) .. .. .. - person mrsachindixit; 30.05.2015
comment
Таким образом, наш алгоритм, по сути, предназначен для каждого необязательного узла, то есть опции, назначить вес по умолчанию, а затем пересмотреть его вес после того, как будет вычислен фактический вес дополнительного узла.Таким образом, в процессе цикл assign и revise (точнее, assign-flag и revise-de-falg). После того, как мы вычислим такой вес и узнаем наш сокращенный путь, мы можем использовать эту информацию о пути для любого использования в реальном мире (например, для установки пути сборки или последовательности загрузки jar-файлов). - person mrsachindixit; 30.05.2015

Я действительно думаю, что графики - подходящая структура для этой проблемы. Обратите внимание, что A и (E или C) ‹==> (A и E) или (A и C). Таким образом, мы можем представить X = A и (E или C) со следующим набором направленных ребер:

A <- K1
E <- K1
A <- K2
C <- K2
K1 <- X
K2 <- X

По сути, мы просто декомпозируем логику оператора и используем «фиктивные» узлы для представления операторов AND.

Предположим, мы раскладываем все логические операторы таким образом (фиктивные узлы Ki для ANDS и направленные ребра в противном случае). Затем мы можем представить входные данные как DAG и рекурсивно пройти через DAG. Я думаю, что следующий рекурсивный алгоритм может решить проблему:

Определения:
Узел u - Текущий узел.
S - Посещенный набор узлов.
children (x) - возвращает ближайших соседей x.

Алгоритм:

shortestPath u S = 
if (u has no children) {
    add u to S
    return 1
} else if (u is a dummy node) {
  (a,b) = children(u)
  if (a and b are in S) {
    return 0
  } else if (b is in S) { 
    x = shortestPath a S
    add a to S
    return x
  } else if (a in S) {
    y = shortestPath b S
    add b to S
    return y
  } else {
    x = shortestPath a S
    add a to S
    if (b in S) return x
    else {
        y = shortestPath b S
        add b to S
        return x + y
    }
  }
} else {
  min = Int.Max
  min_node = m
  for (x in children(u)){
    if (x is not in S) {
      S_1 = S
      k = shortestPath x S_1
      if (k < min) min = k, min_node = x
    } else {
      min = 1
      min_node = x
    }
  }
  return 1 + min
}

Анализ: это полностью последовательный алгоритм, который (я думаю) проходит каждое ребро не более одного раза.

person Xceptional    schedule 29.05.2015

Многие ответы здесь сосредоточены на том, что это теоретически сложная проблема из-за ее NP-трудного статуса. Хотя это означает, что вы столкнетесь с асимптотически низкой производительностью при точном решении проблемы (с учетом текущих методов решения), вы все равно сможете решить ее быстро (достаточно) для данных конкретной проблемы. Например, мы можем точно решить огромные примеры задач коммивояжера, несмотря на то, что задача теоретически сложна.

В вашем случае одним из способов решения проблемы было бы сформулировать ее как смешанную целочисленную линейную программу, в которой для каждого пакета i есть двоичная переменная x_i. Вы можете преобразовать требования A requires (B or C or D) and (E or F) and (G) в ограничения формы x_A <= x_B + x_C + x_D ; x_A <= x_E + x_F ; x_A <= x_G, и вы можете потребовать, чтобы пакет P был включен в окончательное решение с x_P = 1. Точное решение такой модели относительно несложно; например, вы можете использовать пакет pulp в python:

import pulp

deps = {"X": [("A"), ("E", "C")],
        "A": [("E"), ("H", "Y")],
        "E": [("B"), ("Z", "Y")],
        "C": [("A", "K")],
        "H": [],
        "B": [],
        "Y": [],
        "Z": [],
        "K": []}
required = ["X"]

# Variables
x = pulp.LpVariable.dicts("x", deps.keys(), lowBound=0, upBound=1, cat=pulp.LpInteger)

mod = pulp.LpProblem("Package Optimization", pulp.LpMinimize)

# Objective
mod += sum([x[k] for k in deps])

# Dependencies
for k in deps:
    for dep in deps[k]:
        mod += x[k] <= sum([x[d] for d in dep])

# Include required variables
for r in required:
    mod += x[r] == 1

# Solve
mod.solve()
for k in deps:
    print "Package", k, "used:", x[k].value()

Это выводит минимальный набор пакетов:

Package A used: 1.0
Package C used: 0.0
Package B used: 1.0
Package E used: 1.0
Package H used: 0.0
Package Y used: 1.0
Package X used: 1.0
Package K used: 0.0
Package Z used: 0.0

Для очень больших проблемных экземпляров это может занять слишком много времени. Вы можете либо принять потенциально неоптимальное решение, используя тайм-аут (см. здесь), либо переместить от решателей с открытым исходным кодом по умолчанию до коммерческих решателей, таких как gurobi или cplex, которые, вероятно, будут намного быстрее.

person josliber♦    schedule 10.06.2015

Чтобы добавить к ответу Мизандриста: ваша проблема NP-complete NP-hard (см. Ответ dened).

Изменить: Это прямая редукция экземпляра Set Cover (U , S) к вашему экземпляру "проблемы пакета": сделайте каждую точку z наземного множества U требованием И для X. Сделайте каждый набор в S, который покрывает точку z, требованием ИЛИ для z. Тогда решение проблемы с упаковкой дает минимальный набор крышек.

Точно так же вы можете спросить, какое удовлетворяющее назначение монотонной логической схемы имеет наименьшее количество истинных переменных, см. Эти примечания к лекциям < / а>.

person Valentas    schedule 28.05.2015

Поскольку граф состоит из двух разных типов ребер (отношения И и ИЛИ), мы можем разделить алгоритм на две части: искать все узлы, которые являются необходимыми преемниками узла, и искать все узлы, из которых мы должны выбрать один единственный узел. (ИЛИ).

Узлы содержат пакет, список узлов, которые должны быть наследниками этого узла (И), список списка узлов, которые могут быть наследниками этого узла (ИЛИ), и флаг, который отмечает, на каком шаге алгоритма узел был посетил.

define node: package p , list required , listlist optional , 
             int visited[default=MAX_VALUE]

Основная процедура переводит входные данные в граф и начинает обход в начальном узле.

define searchMinimumP:
    input: package start , string[] constraints
    output: list

    //generate a graph from the given constraint
    //and save the node holding start as starting point
    node r = getNode(generateGraph(constraints) , start)

    //list all required nodes
    return requiredNodes(r , 0)

requiredNodes ищет все узлы, которые являются необходимыми преемниками узла (которые связаны с n через И-отношение через 1 или несколько ребер).

define requiredNodes:
    input: node n , int step
    output: list

    //generate a list of all nodes that MUST be part of the solution
    list rNodes
    list todo

    add(todo , n)

    while NOT isEmpty(todo)
        node next = remove(0 , todo)
        if NOT contains(rNodes , next) AND next.visited > step
            add(rNodes , next)
            next.visited = step

    addAll(rNodes , optionalMin(rNodes , step + 1))

    for node r in rNodes
        r.visited = step

    return rNodes

optimalMin ищет кратчайшее решение среди всех возможных решений для необязательных соседей (ИЛИ). Этот алгоритм является полным перебором (будут проверены все возможные варианты выбора для соседей.

define optionalMin:
    input: list nodes , int step
    output: list

    //find all possible combinations for selectable packages
    listlist optSeq
    for node n in nodes
        if NOT n.visited < step
            for list opt in n.optional
                add(optSeq , opt)

    //iterate over all possible combinations of selectable packages
    //for the given list of nodes and find the shortest solution
    list shortest
    int curLen = MAX_VALUE

    //search through all possible solutions (combinations of nodes)
    for list seq in sequences(optSeq)
        list subseq

        for node n in distinct(seq)
            addAll(subseq , requiredNodes(n , step + 1))

        if length(subseq) < curLen
            //mark all nodes of the old solution as unvisited
            for node n in shortest
                n.visited = MAX_VALUE

            curLen = length(subseq)
            shortest = subseq
        else
            //mark all nodes in this possible solution as unvisited
            //since they aren't used in the final solution (not at this place)
            for node n in subseq
                n.visited = MAX_VALUE

     for node n in shorest
         n.visited = step

     return shortest

Основная идея была бы следующей: начать с начального узла и найти все узлы, которые должны быть частью решения (узлы, которые могут быть достигнуты из начального узла только путем обхода И-отношений). Теперь для всех этих узлов алгоритм ищет комбинацию дополнительных узлов (ИЛИ) с наименьшим количеством необходимых узлов.

ПРИМЕЧАНИЕ: пока что этот алгоритм ненамного лучше брутфорса. Я обновлюсь, как только найду лучший подход.

person Paul    schedule 28.05.2015
comment
Но что произойдет, если один узел используется в качестве зависимости двумя другими узлами? Возьмем мой пример: у A есть два или зависимости, Y и H. Кратчайший путь - это A E B Y, а не A E B H, потому что A и E имеют одну и ту же зависимость. Фактически, если вы выберете H вместо Y, ваш кратчайший путь будет A E B H Y. Как вы можете справиться с этим условием? Надеюсь вы понимаете меня. - person KLi; 28.05.2015
comment
Вы правы, мое решение работает только для деревьев. Я исправлю это - person Paul; 28.05.2015

Мой код находится здесь.

Сценарий:

Представьте ограничения.

X : A&(E|C)
A : E&(Y|N)
E : B&(Z|Y)
C : A|K

Подготовьте две переменные target и result. Добавьте узел X в цель.

target = X, result=[]

Добавьте к результату единственный узел X. Замените узел X зависимым в цели.

target = A&(E|C), result=[X]

Добавьте к результату единственный узел A. Замените узел A зависимым в цели.

target = E&(Y|N)&(E|C), result=[X, A]

Единственный узел E должен быть истинным. Итак, (E | C) всегда верно. Удалите его из мишени.

target = E&(Y|N), result=[X, A]

Добавьте к результату единственный узел E. Замените узел E зависимым в цели.

target = B&(Z|Y)&(Y|N), result=[X, A, E]

Добавьте к результату единственный узел B. Замените узел B зависимым в цели.

target = (Z|Y)&(Y|N), result=[X, A, E, B]

Отдельных узлов больше нет. Затем разверните целевое выражение.

target = Z&Y|Z&N|Y&Y|Y&N, result=[X, A, E, B]

Замените Y&Y на Y.

target = Z&Y|Z&N|Y|Y&N, result=[X, A, E, B]

Выберите термин с наименьшим количеством узлов. Добавьте все узлы в термине к цели.

target = , result=[X, A, E, B, Y]
person saka1029    schedule 01.06.2015
comment
Этот алгоритм кажется правильным, но крайне неэффективным. Узкое место - это этап расширения. Даже если ввод не такой большой (например, 100 разных (A|B)s), программа не только будет работать вечно (и это ожидается), но также потребляют yottabyte памяти для расширенного target. - person dened; 03.06.2015
comment
@dened Да, ты прав. Проблема состоит в том, чтобы найти термин, имеющий наименьшее количество узлов. Думаю, есть алгоритмы быстрого доступа. По крайней мере, есть алгоритмы, которые находят лучшее (а может и не лучшее) решение за полиномиальное время. Это всего лишь моя интуиция. - person saka1029; 03.06.2015

Я предлагаю вам сначала преобразовать граф в дерево И-ИЛИ . После этого вы можете выполнить поиск в дереве наилучшего (где вы можете выбрать, что означает «лучший»: самый короткий, наименьший объем памяти, занимаемый пакетами в узлах и т. Д.).

Я бы предложил, чтобы условие для установки X было чем-то вроде install(X) = install(A) and (install(E) or install(C)), состоит в том, чтобы сгруппировать узлы OR (в данном случае: E и C) в один узел, скажем EC, и преобразовать условие в install(X) = install(A) and install(EC).

В качестве альтернативы, на основе идеи дерева И-ИЛИ, вы можете создать собственный график И-ИЛИ, используя идею группировки. Таким образом, вы можете использовать адаптацию алгоритма обхода графа, который может быть более полезным в определенных сценарии.

Еще одним решением может быть использование прямой цепочки. Вам нужно будет выполнить следующие шаги:

  1. Преобразуйте (просто переписав здесь условия):

    A и (E или C) => X

    E и (H или Y) => A

    B и (Z или Y) => E

в

(A and E) or (A and C) => X
(E and H) or (E and Y) => A
(B and Z) or (B and Y) => E
  1. Установите X как цель.
  2. Вставьте B, H, K, Y, Z как факты.
  3. Запустите прямую цепочку и остановитесь при первом появлении X (цель). В данном случае это должен быть кратчайший путь к достижению цели (просто не забудьте отслеживать использованные факты).

Дайте мне знать, если что-то неясно.

person Gentian Kasa    schedule 03.06.2015

Это пример проблемы удовлетворения ограничений. Существуют решатели ограничений для многих языков, даже некоторые из них могут работать на общих механизмах 3SAT и, таким образом, работать на GPGPU.

person Community    schedule 25.05.2015

Другой (интересный) способ решить эту проблему - использовать генетический алгоритм.

Генетический алгоритм мощный, но вам нужно использовать множество параметров, чтобы найти лучший.

Genetic Step следующие:

а. Создание: число случайных людей, первое поколение (например, 100).

б. мутация: мутация небольшого процента из них (например: 0,5%).

c. Оценка: оценка (также называемая фитнесом) всем индивидуумам.

d. Воспроизведение: выберите (используя ставки) пару из них и создайте ребенка (например: 2 ребенка)

е. Выбор: выберите Родитель и Дочерний, чтобы создать новое поколение (например: оставить 100 человек за поколением)

f. Цикл: вернитесь к шагу а и повторите весь процесс несколько раз (например: 400 поколений).

грамм. Выбрать: выберите человека последнего поколения с максимальной скоростью. Индивидуальным будет ваше решение.

Вот что вам предстоит решить:

  1. Найдите генетический код для своего человека

Вы должны представить возможное решение (назвать индивидуальным) вашей проблемы в виде генетического кода.

В вашем случае это может быть группа букв, представляющая узел, который соблюдает ограничение ИЛИ и НЕ.

Например :

[ A E B Y ], [ A C K H ], [A E Z B Y] ...

  1. Найдите способ оценить человека

Чтобы узнать, является ли человек хорошим решением, вы должны оценить его, чтобы сравнить с другим человеком.

В вашем случае это может быть довольно просто: индивидуальная ставка = количество узлов - количество отдельных узлов

Например :

[ A E B Y ] = 8 - 4 = 4

[ A E Z B Y] = 8 - 5 = 3

[A E B Y] как лучшая оценка, чем [A E Z B Y]

  1. Выбор

Благодаря индивидуальному рейтингу мы можем выбрать пару из них для воспроизведения.

Например, используя генетический алгоритм выбора колеса рулетки

  1. Воспроизведение

Возьмите пару индивидуумов и создайте от них (например, 2) ребенка (другого человека).

Например :

Возьмите узел из первого и замените его узлом второго.

Сделайте некоторую корректировку, чтобы соответствовать или, и ограничению.

[A E BY], [AC K H] = ›[AC E HBY], [AEC K К]

Обратите внимание: это не лучший способ воспроизвести это, потому что ребенок стоит, чем родитель. Может быть, мы сможем поменять диапазон узлов.

  1. Мутация

Вам нужно просто изменить генетический код избранной особи.

Например :

  • Удалить узел

  • Сделайте некоторую корректировку, чтобы соответствовать или, и ограничению.

Как видите, это несложно реализовать, но необходимо сделать большой выбор, чтобы разработать его с учетом конкретной проблемы и контролировать различные параметры (процент мутаций, система оценок, система воспроизводства, количество особей, количество поколений). , ...)

person Mathieu Momal    schedule 03.06.2015