Введение

Одновременное логическое программирование с ограничениями – это версия логического программирования с ограничениями, ориентированная главным образом на программирование параллельных процессов, а не (или в дополнение к) решению задач об удовлетворении ограничениям. Цели в логическом программировании с ограничениями вычисляются параллельно; следовательно, параллельный процесс программируется как вычисление цели интерпретатором. Синтаксически, программы одновременной логики ограничений похожи на последовательные программы, за исключением того, что клаузы включают охранные условия – это ограничения, которые могут блокировать применимость клаузы при определенных условиях. Семантически, одновременное логическое программирование с ограничениями отличается от своих последовательных версий тем, что вычисление цели предназначено для реализации параллельного процесса, а не для поиска решения задачи. Наиболее заметно, это различие влияет на поведение интерпретатора, когда применимо несколько клауз: последовательное логическое программирование с ограничениями рекурсивно перебирает все клаузы, а одновременное логическое программирование с ограничениями выбирает только одну. Это наиболее явный эффект заданной направленности интерпретатора, который никогда не пересматривает ранее принятое решение. Другие последствия этого – семантическая возможность наличия цели, которую нельзя доказать, при этом всё вычисление не завершается неудачей, и особый способ сопоставления цели и заголовка клаузы. Правила обработки ограничений можно рассматривать как форму одновременного логического программирования с ограничениями, но они используются для программирования упростителей или решателей ограничений, а не параллельных процессов.

Описание

В программировании с логикой ограничений цели текущей цели оцениваются последовательно, обычно в порядке LIFO, при котором новые цели оцениваются первыми. Параллельная версия логического программирования позволяет оценивать цели параллельно: каждая цель оценивается процессом, и процессы выполняются одновременно. Эти процессы взаимодействуют посредством хранилища ограничений: один процесс может добавить ограничение в хранилище, а другой проверить, следует ли это ограничение из хранилища. Добавление ограничения в хранилище выполняется как в обычном программировании с логикой ограничений. Проверка следования ограничения осуществляется с помощью охранных условий. Охранным условиям требуется синтаксическое расширение: пункт конкурентного логического программирования с ограничениями записывается как H : G | B, где G — это ограничение, называемое охранным условием пункта. Грубо говоря, новый вариант этого пункта может быть использован для замены литерала в цели только в том случае, если охранное условие следует из хранилища ограничений после добавления в него уравнения литерала и заголовка пункта. Точное определение этого правила более сложное и приведено ниже. Основное различие между неконкурентным и конкурентным программированием с ограничениями заключается в том, что первое ориентировано на поиск, а второе — на реализацию конкурентных процессов. Это различие влияет на возможность отмены выбора, допустимость незавершающихся процессов и способ уравнивания целей и заголовков пунктов. Первое семантическое различие между обычным и конкурентным логическим программированием с ограничениями касается условия, при котором для доказательства цели можно использовать более одного пункта. Неконкурентное логическое программирование пытается переписать цель, перебирая все возможные пункты: если цель не может быть доказана заменой ее телом нового варианта пункта, то проверяется другой пункт, если он существует. Это связано с тем, что цель состоит в доказательстве цели: перебираются все возможные способы ее доказательства. С другой стороны, конкурентное логическое программирование с ограничениями направлено на программирование параллельных процессов. В общем случае конкурентного программирования, если процесс делает выбор, этот выбор не может быть отменен. Конкурентная версия логического программирования с ограничениями реализует процессы, позволяя им делать выбор, но фиксируя его после принятия. Технически, если для переписывания литерала в цели можно использовать более одного пункта, неконкурентная версия последовательно перебирает все пункты, а конкурентная версия выбирает один произвольный пункт: в отличие от неконкурентной версии, другие пункты никогда не будут пробоваться. Эти два различных способа обработки множественного выбора часто называют «неопределенностью незнания» и «неопределенностью безразличия». При переписывании литерала в цели рассматриваются только те пункты, чье охранное условие следует из объединения хранилища ограничений и уравнения литерала с заголовком пункта. Охранные условия позволяют определить, какие пункты вообще не следует рассматривать. Это особенно важно, учитывая фиксацию выбора одного пункта в конкурентном логическом программировании с ограничениями: как только пункт выбран, этот выбор больше никогда не будет пересмотрен. Без охранных условий интерпретатор мог бы выбрать «неправильный» пункт для переписывания литерала, в то время как другие «правильные» пункты существуют. В неконкурентном программировании это менее важно, поскольку интерпретатор всегда перебирает все возможности. В конкурентном программировании интерпретатор фиксируется на одной возможности, не перебирая другие. Второй эффект различия между неконкурентной и конкурентной версиями заключается в том, что конкурентное логическое программирование с ограничениями специально разработано для того, чтобы процессы могли выполняться без завершения. Незавершающиеся процессы часто встречаются в конкурентной обработке; конкурентная версия логического программирования с ограничениями реализует их, не используя условие неудачи: если для переписывания цели не применимо ни одного пункта, процесс, оценивающий эту цель, останавливается, а не приводит к неудаче всей оценки, как в неконкурентном логическом программировании с ограничениями. В результате процесс, оценивающий цель, может быть остановлен из-за отсутствия доступных пунктов для продолжения, но при этом другие процессы продолжают выполняться. Синхронизация между процессами, решающими различные цели, достигается с помощью охранных условий. Если цель не может быть переписана, потому что все пункты, которые можно было бы использовать, имеют охранное условие, которое не следует из хранилища ограничений, процесс, решающий эту цель, блокируется до тех пор, пока другие процессы не добавят ограничения, необходимые для следования охранного условия хотя бы одного из применимых пунктов. Эта синхронизация подвержена взаимным блокировкам: если все цели заблокированы, новые ограничения не будут добавлены, и, следовательно, ни одна цель никогда не будет разблокирована. Третий эффект различия между конкурентным и неконкурентным логическим программированием заключается в способе уравнивания цели с заголовком нового варианта пункта. Операционно это делается путем проверки, можно ли уравнять переменные в заголовке с термами таким образом, чтобы заголовок был равен цели. Это правило отличается от соответствующего правила для логического программирования с ограничениями тем, что оно разрешает добавлять только ограничения вида переменная=терм, где переменная является одной из переменных заголовка. Это ограничение можно рассматривать как форму направленности, поскольку цель и заголовок пункта обрабатываются по-разному. Точнее, правило, определяющее, можно ли использовать новый вариант H : G | B пункта для переписывания цели A, следующее. Во-первых, проверяется, имеют ли A и H один и тот же предикат. Во-вторых, проверяется, существует ли способ уравнять A и H с учетом текущего хранилища ограничений; в отличие от обычного логического программирования, это делается с использованием односторонной унификации, которая разрешает только переменной заголовка быть равной терму. В-третьих, охранное условие проверяется на следование из хранилища ограничений и уравнений, сгенерированных на втором шаге; охранное условие может содержать переменные, которые не упоминаются в заголовке пункта: эти переменные интерпретируются экзистенциально. Этот метод определения применимости нового варианта пункта для замены цели можно компактно выразить следующим образом: текущее хранилище ограничений следует, что существует оценка переменных заголовка и охранного условия такая, что заголовок равен цели и охранное условие следует. На практике следование может проверяться неполным методом. Расширением синтаксиса и семантики конкурентного логического программирования является атомарное добавление ограничений. Когда интерпретатор использует пункт, его охранное условие добавляется в хранилище ограничений. Однако также добавляются ограничения тела. Из-за фиксации выбора этого пункта интерпретатор не откатывается, если ограничения тела несовместимы с хранилищем. Этого можно избежать с помощью атомарного добавления ограничений, которое является вариантом, в котором пункт содержит своего рода «второе охранное условие», которое проверяется только на согласованность. Такой пункт записывается как H : G : D | B. Этот пункт используется для переписывания литерала только в том случае, если G следует из хранилища ограничений и D согласовано с ним. В этом случае и G, и D добавляются в хранилище ограничений.

История

Изучение параллельного логического программирования с ограничениями началось в конце 1980-х годов, когда Майкл Дж. Махер интегрировал некоторые принципы параллельного логического программирования в логическое программирование с ограничениями. Теоретические свойства параллельного логического программирования с ограничениями позднее изучались различными авторами, включая Мартина Ринарда и Виджай А. Сарасват.