Как связать список монадическую функцию в ширину - первый поиск? -- haskell поле с участием monads поле с участием breadth-first-search поле с участием non-deterministic пол Связанный проблема

How do I convert a list monadic function to a breadth-first search?


6
vote

проблема

русский

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

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

 <код> solve :: Game -> [Game] solve game = do         let ruleBasedSolverResult = applyRuleBasedSolversUntilSteady game         guard $ consistant ruleBasedSolverResult         if solved ruleBasedSolverResult                 then return ruleBasedSolverResult                 else speculate ruleBasedSolverResult  speculate :: Game -> [Game] speculate game = do         coord <- coords game         guard $ lightableUnlit game coord         let solutions = solve $ light game coord         if null solutions                 then solve $ exclude game coord                 else solutions   

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

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

Я поглотил такие вещи, как «широта первого недетерманизма Монада», и я получаю несколько результатов, которые мне трудно понять, например:

    .
  • control.Monad.omega это похоже на излишки За то, что мне нужно, потому что, похоже, охраняется против бесконечно расходящихся детерминизма, что не так для меня, и я не полностью понимаю это.

  • control.monad.weightedsearch документы Для Control.Monad.omega предлагает использовать это вместо этого при использовании его в качестве монады, но я думаю, что взвешивание также немного переплетет для моих нужд. Я бы, вероятно, просто имел 2 веса, один для вещей с решениями и одним для вещей, которые не имеют решения.

  • control.monad.level Я не верю, что это будет работать За то, что я хочу, поскольку только листья дерева имеют значения.

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

Мой следующий вопрос будет о том, как параллелизировать его :)

Английский оригинал

I just got over the hump of figuring out how to use the List monad to do nondeterministic computations. However I believe my algorithm would benefit from a breadth-first search instead of a depth-first one which you get from the List monad.

Here is an excerpt showing the interesting part of my algorithm. It is a solver for the logic puzzle Akari.

solve :: Game -> [Game] solve game = do         let ruleBasedSolverResult = applyRuleBasedSolversUntilSteady game         guard $ consistant ruleBasedSolverResult         if solved ruleBasedSolverResult                 then return ruleBasedSolverResult                 else speculate ruleBasedSolverResult  speculate :: Game -> [Game] speculate game = do         coord <- coords game         guard $ lightableUnlit game coord         let solutions = solve $ light game coord         if null solutions                 then solve $ exclude game coord                 else solutions 

Basically it applies some basic deterministic rules to see if that solves it. If not it tries putting lights in various places. If a light makes a puzzle inconsistent after recursing to solve it places an exclusion mark where the light was and proceeds. If it finds solutions while placing lights then it adds those to the list of solutions.

This works fine, but is slow because often there is an obvious choice for which coord to speculate on that will quickly result in an inconsistent puzzle and let you place an x with just one (or two) levels of search, but if it doesn't choose that coord until halfway through the search then it winds up chewing a bunch of uninteresting stuff first. Thus the breadth-first search idea.

I have googled things like "breadth first nondetermanism monad" and I get a few results that are difficult for me to understand, like:

  • Control.Monad.Omega This seems like overkill for what I need because it seems to guard against infinitely diverging determinism which is not the case for me, and I don't completely understand it.

  • Control.Monad.WeightedSearch the docs for Control.Monad.Omega suggest using this instead when using it as a Monad, but I think weighting is also a bit overkill for my needs. I would likely just have 2 weights, one for things with solutions and one for things that don't have solutions.

  • Control.Monad.Level I don't believe this will work for what I want since only the leaves of the tree have values.

  • Data.Tree I think this might be what I want to use, but I'm not sure how to convert my List monadic code to use it, though I feel like there's a beautiful way.

My next question will be about how to parallelize it :)

</div
           

Список ответов

6
 
vote

Я верю, что "backtracking, чередование и прекращение монадных трансформаторов "(Функциональная жемчужина) по Киселеве, Шан и Фридману изложены решение.

Отказ от ответственности: Я не эксперт в этой работе!

в основном, вы должны использовать другой монад. Поскольку <код> ListT Monad Transformer - во-первых, они придумали новый монадовый трансформатор <код> LogicT , который делает ширину. (Если вы не заинтересованы в монаде-трансформаторах, вы можете просто применить трансформатор в <код> Id , чтобы вернуться регулярным монадом).

Во-первых, они распознают недостатки в других подходах:

Просторная глубина - первый поиск, выполненный большинством реализаций монапплеса, не является справедливым: недетерский выбор между двумя альтернативами пытается каждый раствор от первой альтернативы перед любым решением со второй альтернативы. Когда первая альтернатива предлагает бесконечное количество решений, вторая альтернатива никогда не пробовала, делая поиск неполным. Действительно, в качестве наших примеров в разделе 3 шоу, честный обратный отходчик помогает более логическим программам.

[...]

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

[...]

Третий практический дефицит - это часто забытый интерфейс верхнего уровня: как запустить и взаимодействовать с вычислением, который может вернуть бесконечное количество ответов? Наиболее распространенным решением является обеспечение потока, который может потребляться или обрабатываться на верхнем уровне по желанию. Но в случае монадских трансформаторов этого решения работает только в том случае, если базовый монад не является строгим (например, ленивый список Haskell Monad и Lanyst). В случае, когда база монады строго, оценка может расходиться, заставляя оценку всего потока, даже если мы только желаем одного ответа.

Затем они представляют решение на основе LogicT Monad Transformer и <код> msplit функции. Хотя ссылка на код сломана, я искал Hoogle для <код> LogicT и нашел это .

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

Если вы найдете эту бумагу полезную, не забудьте проверить свои ссылки и другие документы, которые ссылаются!

 

I believe that "Backtracking, Interleaving, and Terminating Monad Transformers" (Functional Pearl) by Kiselyov, Shan and Friedman outlines a solution.

Disclaimer: I am not an expert in this work!

Basically, you have to use a different monad. Since the ListT monad transformer does depth-first, they came up with a new monad transformer LogicT which does breadth-first. (If you're not interested in monad transformers, you can just apply a transformer to Id to get back a regular monad).

First, they recognize deficiencies in other approaches:

the straightforward depth-first search performed by most implementations of MonadPlus is not fair: a non-deterministic choice between two alternatives tries every solution from the first alternative before any solution from the second alternative. When the first alternative offers an infinite number of solutions, the second alternative is never tried, making the search incomplete. Indeed, as our examples in Section 3 show, fair backtracking helps more logic programs terminate.

[...]

The second deficiency in many existing backtracking monads is the adoption of Prolog’s cut, which confounds negation with pruning. Theoretically speaking, each of negation and pruning independently makes logic programming languages more expressive

[...]

The third practical deficiency is the often-forgotten top-level interface: how to run and interact with a computation that may return an infinite number of answers? The most common solution is to provide a stream that can be consumed or processed at the top- level as desired. But in the case of monad transformers, this solution only works if the base monad is non-strict (such as Haskell’s lazy list monad and LazyST). In the case where the base monad is strict, the evaluation may diverge by forcing the evaluation of the entire stream, even if we only desire one answer.

They then present a solution based on the LogicT monad transformer and the msplit function. Although the link to the code is broken, I searched Hoogle for LogicT and found this.

I hope that reading this paper will give you a good background in this topic and help you to understand how to use the projects that you already found.

If you find this paper useful, don't forget to check out its references and the other papers that cite it!

</div
 
 
       
       

Связанный проблема

1  Как написать генератор Haskell QuickCheck для Data.meldableheap Очередь приоритета  ( How to write a haskell quickcheck generator for a data meldableheap priority que ) 
Как учебное упражнение, которое я хочу написать генератор <код> Data.MeldableHeap . Я счеркнул его после: https://gitorious.org/aocapq/aoCapq/ Source / 7F2...

35  Функция Haskell Состав  ( Haskell function composition ) 
Я читаю Это Учебник на Haskell. Они определяют функцию функции как следующее: <код> (.) :: (b->c) -> (a->b) -> (a->c) f . g ...

3  Haskell - заставить строгую оценку со странным, рекурсивный тип  ( Haskell forcing strict evaluation with a weird recursive type ) 
i Ранее задали вопрос о том, как заставить строгая оценка для создания тайм-аута. Используя <код> seq / <код> $! достаточно большую часть времени, а <код>...

3  Функциональные учебные проблемы  ( Functional learning woes ) 
Я начинающий к функциональным языкам, и я пытаюсь зацепить все это в Haskell. Вот быстроразъемная функция, которая находит все факторы номера: <код> factors...

2  Выпуск производительности на цепочке Коллац  ( Performance issue on collatz chain ) 
У меня есть рабочая программа для вычисления самой длинной цепочки Collatz в данном диапазоне (проект EULER N ° 14). Я думаю, что это работает правильно, но о...

0  Аргумент функции, который трансформируется в монаде  ( Function argument which transforms in st monad ) 
Как я могу написать следующую функцию <код> tt , который имеет в данный момент ошибки: <код> t :: Int t = runST $ do ref <- newSTRef 10 readSTRef ref t...

2  Рассуждение о функциях, осматривая их тип подписи [закрыто]  ( Reasoning about functions by examining their type signatures ) 
<в сторону CLASS = "S-NEWACTS S-WELTIVE__info JS-Post-New Imide MB16« Роль = «Статус»> закрыт . Этот вопрос должен быть больше Фокусированный . В настоя...

1  Могу ли я сформировать сопоставление на имя типа?  ( Can i pattern match on type name ) 
Можно ли узозить совпадение на самом названии типа, а не на одном из конструкторов типа? Вот надуманный пример с кодом, который не скомпилируется, который, ...

15  Как вы используете типопливники в Haskell?  ( How do you use typeapplications in haskell ) 
с -XTypeApplications в GHC 8.0, вы явно указываете типы с <код> @ предшествующих аргументах функций. Какие типы это точно уточняют, особенно когда введен н...

1  Как пользоваться арбитрами аргументами объектива Makefields с различными типами в той же функции?  ( How to use an arbitrary makefields lens argument with different types in the sam ) 
Я использую makeFields от объектива для генерации полей, перегруженных для различных структур. Я хотел бы использовать эти поля в одном с несколькими струк...

8  Emacs: переопределение команды в Haskell-Mode (Haskell-Mode-Took)  ( Emacs redefining command in haskell mode haskell mode hook ) 
В Emacs в Haskell-режиме я хотел изменить команду . "C-X C-S" к . «C-X C-S», а затем «C-C C-L». Принимая кий от: haskell.org: emacs / keybindings и...

20  Как поднимается (в функциональном контексте программирования) относится к теории категории?  ( How does lifting in a functional programming context relate to category theory ) 
Смотреть на haskell Документация, подъем, кажется, в основном обобщение <код> filter%5Blogic%5D=and&filter%5Bfilters%5D%5B0%5D%5Bvalue%5D=CAR&filter%5Bfilte...

4  Haskell Aeson Разрушение общих разбросов  ( Haskell aeson destructuring generic parse ) 
У меня есть запрос JSON в стиле <код> {"command":"get","params":{"something":"something else"}} и этот код фрагмента из yesod book <код> {-# LANGUAG...

2  Обобщение функции объединить набор производителей труб Haskell  ( Generalizing a function to merge a set of haskell pipes producers ) 
Я работаю с Пакет Haskell Трубы . Я пытаюсь использовать Трубы-параллелизм для объединения списка производителей вместе. Что я хочу прибыть на: <код>...

1  Aeson: анализ вложенного объекта AS (карта String MyshinyType)  ( Aeson parse nested object as map string myshinytype ) 
У меня есть файл JSON-схемы с помощью поля «Свойства». <код> { ... "properties": { "id": { "description": "ID", "type": "int...

Связанный проблема

1  Как написать генератор Haskell QuickCheck для Data.meldableheap Очередь приоритета 
35  Функция Haskell Состав 
3  Haskell - заставить строгую оценку со странным, рекурсивный тип 
3  Функциональные учебные проблемы 
2  Выпуск производительности на цепочке Коллац 
0  Аргумент функции, который трансформируется в монаде 
2  Рассуждение о функциях, осматривая их тип подписи [закрыто] 
1  Могу ли я сформировать сопоставление на имя типа? 
15  Как вы используете типопливники в Haskell? 
1  Как пользоваться арбитрами аргументами объектива Makefields с различными типами в той же функции? 
8  Emacs: переопределение команды в Haskell-Mode (Haskell-Mode-Took) 
20  Как поднимается (в функциональном контексте программирования) относится к теории категории? 
4  Haskell Aeson Разрушение общих разбросов 
2  Обобщение функции объединить набор производителей труб Haskell 
1  Aeson: анализ вложенного объекта AS (карта String MyshinyType)