Производная графа связана со списками смежности?

14

Некоторые из работ Конора МакБрайда, Diff , Dissect , связывают производную типов данных с их «типом контекстов с одной дырой». То есть, если вы берете производную от типа, который у вас остался, с типом данных, который показывает вам, как тип данных выглядит изнутри в любой заданной точке.

Так, например, если у вас есть список (в Haskell)

data List a = [] | a : List a

это соответствует

data List a = 1 + a * List a

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

data ListDeriv a = List a * List a

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

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

data Gr a b i = Gr [(i,a)] [(i,i,b)]

Если я правильно понимаю, производная этого типа данных по отношению к индексу графа iдолжна выглядеть примерно так.

data GrDeriv a b i = d/di (Gr a b i)
     = d\di ( [a*i] * [b*i^2] )
     = (d\di [a*i]) * [b*i^2] ) + [a*i]*(d/di [b*i^2])
     = (a* [a*i] * [a*i]) * [b*i^2] ) 
       + [a*i] * (2*b*i) *[b*i^2]*[b*i^2])
     = InNodes { nodesLeft :: [(a,i)]
               , nodeLbl :: a
               , nodesRight :: [(a,i)]
               , edges :: [(b,i,i)] }
     | InEdges { nodes :: [(a,i)]
               , adjNode :: Either (b,i) (b,i)
               , edgesLeft :: [(b,i,i)]
               , edgesRight :: [(b,i,i)] }

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

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

Node a b = ([(i,b)],a,[(i,b)])

Однако я действительно надеюсь, что у представления смежности есть некоторые общие термины с производной, одинокой табличкой a, в каждом месте отверстия представление соседства / расчленение каждого ребра.

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

Если есть, я надеюсь, что структуры типов отношений могут быть определены с помощью некоторого простого языка «набора вершин и ребер», и я могу получить эффективную библиотеку для работы с этой структурой. Такая реализация может быть использована для изучения структур "вне теории графов": гиперграфы, симплициальные комплексы ...

Так. Эта идея кажется осуществимой? Полезно? Было ли какое-нибудь исследование этого типа вещей, о котором я мог бы прочитать больше?

добавление

Как прокомментировал Кертис F , множество узлов и ребер не является точно графом. Тем не менее, все графики могут быть представлены такими, и я считаю это достаточно распространенным представлением. Я видел (очень грубую спецификацию) используемую в исследованиях, которые применяют теорию графов для оптимизации беспроводных сетей различными способами. Вот пример открытого доступа, DRAND *. Это поднимает вопрос, какова связь между презентацией и как какое-то программное обеспечение может быть реализовано на основе исследования.граммзнак равно(В,Е)

Тем не менее, я не совсем против изменения входной спецификации с на что-то другое. Например, с учетом типа индекса , узлы метки, и метки ребер, . Тогда график (приблизительно) является функцией от индексов до метки и списка ребер.граммзнак равно(В,Е)яВЕ

граммзнак равноя(В*яЕ)

Это, я уверен, может быть выражено (теория категорий?) Как

(1)граммзнак равно(В*Ея)я

или

граммзнак равноВя*Ея*я

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

грамм'знак равнопер(В*Ея)*(В*Ея)я*(пер(Е)*В*Ея)

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

* В случае разрыва связи, цитирование: Rhee, Injong, et al. «DRAND: распределенное рандомизированное планирование TDMA для беспроводных специальных сетей». Операции IEEE по мобильным вычислениям 8.10 (2009): 1384-1396.

Тревор Кук
источник
Ссылка, которую вы предоставляете для исследования, мертва. Можете ли вы дать более постоянную ссылку, например, DOI или журнал, в котором она была опубликована?
Кертис F

Ответы:

5

Ваш тип на Grсамом деле не соответствует графам, потому что он включает много экземпляров, которые явно не являются графами, потому что индексы ребер не обязательно должны быть фактическими индексами вершин.

Например,

Взнак равно{A,В}Езнак равно{(С,D,е)}

не является графиком, но допускается в вашем типе как

Gr [(1, A), (2, B)] [(3, 4, e)]

Скорее, ваш Grсоответствует буквально списку помеченных индексов и отдельному, не связанному, списку помеченных пар индексов. Вот почему вы получаете такую ​​«буквальную» производную Gr, которая не соответствует «дырам» в графах.

Существует также печальная проблема заботы о порядке вершин / ребер (видимых в nodesLeft/Rightи edgesLeft/Rightразличиях), но это можно исправить, используя Setвместо списка.


Вот тип, выраженный в Haskell, который, я думаю, более точно соответствует (непустым) графам:

data Graph v e = Lone v | Joined v (Graph (v, ([e], [e])) e)

Для простоты я вместо этого рассмотрю полные, простые, неориентированные графы:

data Graph v e = Lone v | Joined v (Graph (v, e) e)

(Для полноты расслабления e = Boolотметьте наличие краев)

Обратите внимание, что Graphэто рекурсивный (и фактически параметрически рекурсивный). Это то, что позволяет нам ограничивать тип только графами, а не просто списками смежности в сочетании со списками вершин.

Написано более алгебраически,

грамм(v,е)знак равноv+v*грамм(v*е,е)

еvграмм

грамм(v)знак равноv+v*грамм(v*е)

Повторно расширяясь, мы получаем фиксированную точку

грамм(v)знак равноv1е(12)+v2е(22)+v3е(32)+v4е(42)+...

Это имеет смысл, так как (полный) граф

  • Одна вершина и нет ребер
  • Две вершины и одно ребро
  • Три вершины и три ребра
  • Четыре вершины и четыре выбирают 2 = 6 ребер
  • ....

КграммК(v)знак равноvКе(К2)грамм(v)знак равнограмм1(v)+грамм2(v)+...

который имеет производную

ddvграмм(v)знак равноΣязнак равно1граммя'(v)

граммК'(v)знак равноddv[vКеК(К-1)2]знак равноКvК-1еК(К-1)2

граммК-1(v)знак равноvК-1е(К-1)(К-2)2граммК'(v)знак равнограммК-1(v)*К*еК-1

КК-1К-1К-1К

data SimpleGraph v e = Lone v | Joined v (SimpleGraph (v, e) e)

data SimpleGraphHole v e = Empty
                         | InsertLater v (SimpleGraphHole (v, e) e)
                         | InsertHere (SimpleGraph (v, e) e)

Исправление порядка в этом графике

Эта версия структуры данных Graph является в основном связанным списком, и поэтому она кодирует порядок вершин. Хотя это может быть исправлено в вашей версии списка смежности с помощью набора, это не так прямо здесь.

Я думаю, что вы можете изменить древовидную структуру данных, чтобы выполнить тот же тип параметрической рекурсии, когда корень играет роль, которую играет «голова» SimpleGraph. Благодаря интерфейсу результирующих наборов деревьев порядок / базовая структура становится невидимой (или даже канонической, если вас не интересуют быстрые обновления).

Ваше предлагаемое производное

Вы предложили производный тип; Я изменю это, чтобы сопоставить метки и индексы, как я сделал:([(v,e)], [(v,e)])

1(1-vе)2С+v1-vе(v, [(v, e)])

Кертис F
источник