
Sb99055
.pdfМИНОБРНАУКИ РОССИИ
–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Санкт-Петербургский государственный электротехнический университет «ЛЭТИ» им. В.И. Ульянова (Ленина)
––––––––––––––––––––––––––––––––––––––––––
С. А. БЕЛЯЕВ С. В. РОДИОНОВ
ПРОГРАММИРОВАНИЕ НАБОРОВ ОТВЕТОВ
Учебно-методическое пособие
Санкт-Петербург Издательство СПбГЭТУ «ЛЭТИ»
2020
УДК 004.432(07) + 510.755(07) ББК З 973.2–018я7 + В 12я7
Б44
Беляев С. А., Родионов С. В.
Б44 Программирование наборов ответов: учеб.-метод. пособие. СПб.: Изд-во СПбГЭТУ «ЛЭТИ», 2020. 32 с.
ISBN 978-5-7629-2660-7
Представлены материалы по дисциплине «Логическое программирование» по программированию наборов ответов (answer set programming – ASP). Рассматриваются особенности языка программирования и вопросы разработки текста программ и формирования на их основе стабильных моделей из правил и фактов, решающих поставленную задачу. Рассматриваются варианты решения нескольких NP-полных задач. Приводятся основы программирования наборов ответов с использованием ограничений. Описываются механизмы вывода и доказательства, используемые в ASP.
Предназначено для студентов, обучающихся по направлениям «Программная инженерия» и «Прикладная математика и информатика».
УДК 004.432(07) + 510.755(07) ББК З 973.2–018я7 + В 12я7
Рецензент – д-р техн. наук, ведущий специалист Ю. В. Миронов (АО«НИЦСПбЭТУ»).
Утверждено редакционно-издательским советом университета
в качестве учебно-методического пособия
ISBN 978-5-7629-2660-7 |
© СПбГЭТУ «ЛЭТИ», 2020 |
ВВЕДЕНИЕ
Программирование наборов ответов (англ. answer set programming, ASP) – парадигма декларативного программирования, ориентированная на сложные (в основном NP-сложные) задачи поиска. Используется для разработки автономных программных агентов, программирования роботов, формирования расписаний и пр. ASP поддерживает интеграцию с Python, C++, Prolog и др.
Программа на языке ASP основана на семантике логического программирования, анализирует проблему как набор фактов, описывает её с использованием правил и формирует решение в виде стабильной модели (набора ответов). Среда ASP компилирует проблему в виде логической программы и в процессе формирования стабильной модели многократно изменяет получившуюся логическую программу.
В данной работе рассматривается «Potsdam Answer Set Solving Collection» (Potassco) [1] – реализация инструментов ASP в виде программы clingo, включающей в себя граундер gringo [2] и решатель clasp. Программа clingcon будет использоваться для программирования наборов ответов с использованием целочисленных ограничений.
Загрузка и установка
Программы gringo, clasp и clingo производства Potassco разработаны на C++, опубликованы с лицензией MIT и доступны для скачивания на сайте https://potassco.org. Нами использована программа clingo, версия 5.3.0, опубликованная по адресу https://github.com/potassco/clingo/releases.
Доступны реализации для операционных систем Windows, Linux и MacOS. Реализации представлены в виде архивов, после скачивания архивы следует распаковать. Для пробного знакомства и решения небольших задач может использоваться web-версия программы по адресу:
http://potassco.sourceforge.net/clingo.html.
Проверка версии может быть выполнена командой: clingo –version Получение справки по использованию: clingo --help
Также использована программа clingcon, версия 3.3.0, опубликованная по адресу:
https://github.com/potassco/clingcon/releases.
3
1. Язык программирования ASP 1.1. Термы
Логические программы используют термы. В качестве простых термов выступают числа, константы, строки и переменные (в том числе символ «_»). Константы состоят из латинских букв, цифр и символа «_» и могут начинаться только с маленькой латинской буквы или символа «_», за которым обязательно следует маленькая латинская буква (например, const, cOn_St, - c24). Строки записываются в двойных кавычках ("string"). Переменные состоят из латинских букв, цифр и символа «_» и могут начинаться только с большой латинской буквы или символа «_», за которым обязательно следует большая латинская буква (например, V, Variable, _Variable, VaR24). Отдельный символ «_» называется неименованной переменной и обладает дополнительными свойствами.
В качестве составных термов выступают функции и кортежи. Функции имеют имя-константу, за которым в круглых скобках через запятую перечисляются один или более термов (например, time(12, 24, am), d(3), line(point(0,0), point(2, 4)). Кортежи, в отличие от функций, не имеют имени – только скобки, в которых через запятую перечислены один или более термов (например, (abc, 12)).
1.2. Построение простой программы
Программа на языке ASP включает в себя факты, правила и исключения
(ограничения целостности). |
|
|
Факт: |
A. |
|
Правило: |
A :- L1, …, Ln. |
|
Ограничения целостности: |
:- |
L1, …, Ln. |
В качестве «головы» А могут выступать атомы в виде константы или функции. В качестве «тела» правила или ограничения целостности выступают литералы Lj (1 ≤ j ≤ n) вида A или not A, где A – атом, а not обозначает отрицание. Будем называть литерал L позитивным, если он атом A, и негативным, если он атом с отрицанием not A.
Голова факта А должна быть всегда истинна. Если все позитивные литералы в теле правила истинны, а все негативные литералы удовлетворены, то-
4
гда голова А правила истинна. Ограничения целостности при этом выступают в роли фильтра, не должна сложиться ситуация, при которой тело ограничения целостности истинно.
Набор атомов фактов и «голов» каждого правила называется моделью логической программы, если удовлетворены все правила, факты и ограничения целостности с использованием ациклического вывода. Атомы считаются истинными тогда и только тогда, когда они входят в модель. В ASP такой набор атомов называется набором ответов (англ. answer set).
Рассмотрим программу.
a:- b.
b:- a.
Если a и b ложны, то ложны тела обоих правил и ложны их головы. Соответственно, программа истинна при пустом наборе ответов. Если a и b истинны, то тела обоих правил истинны, и истинны головы, но в данном случае нет ациклического вывода результата. Ситуации, когда истинно a, а b ложно или истинно b, а a ложно приводят к противоречию. Вывод: у представленной программы ровно один набор ответов – пустой. Ответ clingo:
Answer: 1
SATISFIABLE
Другая ситуация возникает в следующей программе.
a:- not b.
b:- not a.
В данном случае в набор ответов входит либо a, либо b, пустой набор ответов некорректен, набор ответов, включающий a и b, – некорректен. От-
вет clingo (пример запуска: clingo.exe 0 ab_program.lp):
Answer: 1 b
Answer: 2 a
SATISFIABLE
В дальнейших примерах надпись «SATISFIABLE» приводиться не будет. Рассмотрим программу с фактом, правилами и ограничением целостности.
a:- not b.
b:- not a.
:- c, not b.
5
В данном примере есть только один ответ, включающий b и c. Рассмотрим пример, в котором транспортное средство может быть с мо-
тором, а может быть без мотора. При этом рассматриваем как факт, что велосипед не использует мотор.
motor(X) :- vehicle(X), not neg_motor(X). neg_motor(X) :- vehicle(X), not motor(X).
neg_motor(X) :- bike(X).
При этом заранее известна американская фирма sram, производящая велосипеды, и как новую продукцию – некое транспортное средство mulsane, производимое bentley.
vehicle(sram). bike(sram).
vehicle(mulsane). bentley(mulsane).
В результате работы граундера gringo переменным присваиваются все возможные значения, в нашем случае X присваиваются значения sram и mulsane. Получаются следующие правила.
motor(sram) :- vehicle(sram), not neg_motor(sram). motor(mulsane) :- vehicle(mulsane), not
neg_motor(mulsane).
neg_motor(sram) :- vehicle(sram), not motor(sram). neg_motor(mulsane) :- vehicle(mulsane), not
motor(mulsane).
neg_motor(sram) :- bike(sram).
neg_motor(mulsane) :- bike(mulsane).
Учитывая факты программы получаем.
motor(mulsane) :- not neg_motor(mulsane). neg_motor(mulsane) :- not motor(mulsane).
neg_motor(sram) :- bike(sram).
Таким образом, mulsane может быть как моторным, так и не моторным транспортным средством. Поэтому есть два набора ответов.
Answer: 1 vehicle(mulsane) vehicle(sram) neg_motor(sram) bike(sram) bentley(mulsane)
neg_motor(mulsane)
Answer: 2 vehicle(mulsane) vehicle(sram) neg_motor(sram) bike(sram) bentley(mulsane)
motor(mulsane)
6
В дальнейших примерах очевидные ответы будем заменять многоточи-
ем.
1.3. Использование дизъюнкции и задание альтернатив
Дизъюнкция в ASP обозначается с использованием символа «;» в голове правил и фактов.
Факт: A1; …; Am.
Правило: A1; …; Am :- L1, …, Ln.
Дизъюнкция обеспечивает, чтобы хотя бы один из атомов Ai (1 ≤ i ≤ m) был истинен. Рассмотрим программу.
a; b.
В ней будет два набора ответов: a или b. При этом решатель clasp ищет минимальную комбинацию, поэтому третий набор ответов, включающий a и b, появится только при наличии дополнительных условий.
a:- b.
b:- a.
a; b.
В указанной программе будет один набор ответов: a b.
Символ «;» может использоваться для задания альтернатив. Например, для задачи с транспортными средствами альтернативы могут быть заданы следующим образом.
vehicle((sram; mulsane)).
В данном примере дополнительные внутренние скобки могут быть опу-
щены. И результатом будет: vehicle(sram) vehicle(mulsane).
Другой пример альтернатив, в котором дополнительные скобки убирать нельзя.
values(X) :- X = (1;2;3).
Результат: values(3) values(2) values(1)
Целочисленные интервалы могут задаваться через символы «..».
values(X) :- X = 1..4.
Результат: values(1) values(2) values(3) values(4)
7
1.4. Логические константы и арифметика
Логические константы #true и #false принимают значения «истина» и «ложь». Пример их использования в программе:
#true.
not #false. not not #true. :- #false.
:- not #true.
:- not not #false.
Результат данной программы SATISFIABLE, значит все факты и ограничения целостности удовлетворены.
ASP поддерживает следующие арифметические операции: сложение «+», вычитание и унарный минус «–», умножение «*», деление «/», остаток от деления «\», модуль «|», возведение в степень «**», побитовое И «&», побитовое ИЛИ «?», побитовое исключающее ИЛИ «^», побитовое отрицание «~». Пример их использования в программе:
l(5).
r(3).
plus(L + R) :- l(L), r(R). min(L - R) :- l(L), r(R). mod(L \ R) :- l(L), r(R). abs(|-R|) :- r(R).
pow(L ** R) :- l(L), r(R).
Результат выполнения данной программы.
r(3) l(5) plus(8) min(2) mod(2) abs(3) pow(125)
ASP поддерживает операции сравнения: равно «=», неравно «!=», меньше «<», меньше либо равно «<=», больше «>», больше либо равно «>=».
1.5. Условия и условные литералы
Формат условного литерала: L0 : L1, …, Ln.
Здесь каждый Lj (0 ≤ j ≤ n) – литерал, при этом L1, …, Ln называются условием. Если n = 0 получается обычный литерал. Литерал L0 истинный, если истинны все литералы L1, …, Ln:
a :- b : c.
8
В данном примере a истинно только если либо оба b и c ложны, либо оба истинны:
r(a). r(b). r(c).
p :- q(X) : r(X).
В данном случае будет доказываться p :- q(a), q(b), q(c). Обычно условные литералы используются для объединения значений
нескольких переменных:
c(1). d(2). b(1, 2).
a :- b(X, Y) : c(X), d(Y).
В результате будет получено: c(1) d(2) b(1,2) a.
При этом условные операторы могут встречаться как в теле правила, так и в голове правила:
person(jane). person(john).
day(mon). day(tue). day(wed). day(thu). day(fri). available(jane) :- not on(fri).
available(john) :- not on(mon), not on(wed). meet :- available(X) : person(X).
on(X) : day(X) :- meet.
В данной программе два человека jane и john пытаются назначить встречу на рабочей неделе: mon, tue, wed, thu, fri. При этом jane не может встретиться в fri, а john не может в mon и wed. Встреча возможна (available), если оба в этот день могут встретиться (meet). Граундер преобразует последние два правила следующим образом:
meet:-available(jane),available(john).
on(mon);on(tue);on(wed);on(thu);on(fri):-meet.
В результате получаем два ответа (многоточием заменены очевидные факты, такие как person(jane), person(john), day(mon)…):
Answer: 1 ... on(thu)
Answer: 2 ... on(tue)
Рассмотрим программу:
person(tom; bob; alex; liza).
parent(tom, bob). parent(tom, alex). parent(bob, liza).
havechild(X) :- person(X), parent(X, _). havenotchild(X) :- person(X), #false : havechild(X).
9
Первая строка – все участники генеалогического дерева. Вторая строка – указание на родственные связи. Третья строка – правило вычисления тех, у кого есть ребенок. Четвертая строка – правило вычисления тех, у кого нет ребёнка. Условный оператор ложен (#false), если выполнилось условие havechild(X). В результате – один набор ответов.
Answer: 1 ... havechild(tom) havechild(bob)
havenotchild(alex) havenotchild(liza)
В данном случае четвертая строка может быть записана без использования условного литерала.
havenotchild(X) :- person(X), not havechild(X).
Если после условного литера следуют безусловные, то в качестве разделителя используется символ «;»:
d(1..5).
next(X,Z) :- d(X), #false : X < Y, d(Y), Y < Z;
d(Z), X < Z.
В данном примере условный литерал ложен, если между X и Z существует Y. Результат:
Answer: 1 d(1) d(2) d(3) d(4) d(5) next(1,2)
next(2,3) next(3,4) next(4,5)
Ограничения условного литерала:
1)ни одна переменная, унифицированная внутри условного литерала, не может быть использована за его пределами;
2)в первую очередь выполняется унификация переменных за пределами условного литерала, после чего унифицируются переменные условного литерала;
3)в условных литералах могут использоваться только встроенные в ASP
идоменные предикаты. К доменным предикатам относят не содержащие от-
рицаний (не содержат not) и не являющиеся агрегаторами (раздел 1.6).
1.6. Агрегаторы
Общий вид агрегатора
Агрегаторы – конструкции, которые позволяют формировать ответы из групп атомов. При этом за счёт добавления сравнений агрегаторы могут ограничивать количество полученных атомов.
Агрегатор: s1 <1 Func{ t1: L1; ...; tn: Ln } <2 s2.
10