Мое понимание проблемы, как первоначально заявлено, а затем дополнено комментариями в ответе Маке, включает следующее: 1) оба типа ребер (зависимости и конфликты) направлены; 2) если два узла соединены одним ребром, они не должны быть соединены другим, даже если он другого типа или наоборот; 3) если путь между двумя узлами можно построить путем смешивания ребер разных типов, то это скорее ошибка, чем игнорируемое обстоятельство; 4) Если существует путь между двумя узлами, использующими ребра одного типа, тогда между ними не может быть другого пути, использующего ребра другого типа; 5) циклы одного типа ребер или смешанных типов ребер недопустимы (из предположения приложения я не уверен, что циклы только конфликта являются ошибкой, но это условие может быть удалено, если нет).
Кроме того, я предполагаю, что используемая структура данных не предотвращает нарушения этих требований (например, условие 2 нарушения графа не может быть выражено в карте от пары узлов до (тип, направление), если пара узлов всегда сначала имеет наименее пронумерованный узел.) Если определенные ошибки не могут быть выражены, это уменьшает количество рассматриваемых случаев.
Здесь на самом деле можно рассмотреть три графика: два исключительно одного типа ребер и смешанный граф, образованный объединением одного из каждого из двух типов. Вы можете использовать это, чтобы систематически генерировать все графики вплоть до некоторого количества узлов. Сначала сгенерируйте все возможные графы из N узлов, имеющих не более одного ребра между любыми двумя упорядоченными парами узлов (упорядоченные пары, потому что это ориентированные графы.) Теперь возьмем все возможные пары этих графов, один из которых представляет зависимости, а другой представляет конфликты, и сформировать объединение каждой пары.
Если ваша структура данных не может выразить нарушения условия 2, вы можете значительно сократить число рассматриваемых случаев, только построив все возможные графы конфликтов, которые помещаются в пространства графов зависимостей, или наоборот. В противном случае вы можете обнаружить нарушения условия 2 при формировании объединения.
При обходе объединенного графа в ширину от первого узла вы можете создать набор всех путей к каждому достижимому узлу, и при этом вы можете проверить наличие всех условий (для обнаружения цикла вы можете использовать алгоритм Тарьяна .)
Вам нужно только рассмотреть пути от первого узла, даже если граф отключен, потому что пути от любого другого узла будут отображаться как пути от первого узла в другом случае.
Если пути смешанных ребер можно просто игнорировать, а не ошибки (условие 3), достаточно рассмотреть графы зависимостей и конфликтов независимо и проверить, что если узел доступен в одном, то нет в другом.
Если вы помните пути, найденные при проверке графов N-1 узлов, вы можете использовать их в качестве отправной точки для генерации и оценки графов из N узлов.
Это не создает несколько ребер одного типа между узлами, но это может быть расширено для этого. Однако это значительно увеличило бы число случаев, поэтому было бы лучше, если бы тестируемый код делал невозможным представление или невозможность этого отфильтровать все такие случаи заранее.
Ключ к написанию оракула, как это, состоит в том, чтобы сделать его как можно более простым, даже если это означает, что он неэффективен, так что вы можете установить доверие к нему (в идеале с помощью аргументов в пользу его правильности, подкрепленных тестированием).
Если у вас есть средства для генерации тестовых случаев, и вы доверяете созданному оракулу для точного отделения хорошего от плохого, вы можете использовать его для автоматического тестирования целевого кода. Если это невозможно, ваш следующий лучший вариант - прочесать результаты для конкретных случаев. Оракул может классифицировать найденные ошибки и предоставить вам некоторую информацию о принятых случаях, таких как количество и длина путей каждого типа, а также наличие каких-либо узлов, которые находятся в начале обоих типов путей, и это может помочь вам найти случаи, которые вы не видели раньше.