Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Sb99055

.pdf
Скачиваний:
6
Добавлен:
13.02.2021
Размер:
411.94 Кб
Скачать

Здесь tj и Lj описывают элементы агрегатора: tj – терм, Lj – литерал. Если литерал пустой, а терм не пустой, то двоеточие не используется. Func – имя функции, которая будет применена к термам. Функция может отсутствовать. Ограничения «s1 <1» и «<2 s2» могут отсутствовать. При этом «<1» и «<2» по умолчанию означают «<=». Значения «s1» и «s2» определяют нижнюю и верхнюю границы.

Поддерживаемые функции: #count (количество атомов в группе), #sum (сумма значений всех термов), #sum+ (сумма всех положительных значений термов-весов), #min (минимальное значение термов-весов), #max (максимальное значение термов-весов).

В результате использования агрегатора формируется набор ответов, соответствующий заданным условиям:

10 #sum{8: course(db); 4: course(web); 6:

course(ai)}.

Результаты:

Answer: 1 course(db) course(web)

Answer: 2 course(ai) course(web) course(db) Answer: 3 course(ai) course(db)

Answer: 4 course(ai) course(web)

Вычисление сумм при этом происходит при использовании следующих значений: 10 <= #sum{8; 4; 6}. Во всех случаях сумма весов получалась больше либо равна 10. Исключим равенство суммы термов-весов 10.

10 < #sum{8: course(db); 4: course(web); 6:

course(ai)}.

При этом в наборе ответов встретятся только первые три ответа. Рассмотрим пример для #count:

2 #count{1: course(db); 2: course(web); 3:

course(ai)} 2.

Результаты:

Answer: 1 course(web) course(db)

Answer: 2 course(ai) course(web)

Answer: 3 course(ai) course(db)

Вприведённом примере количество атомов в ответе должно быть равно

2.То же самое можно записать следующим образом:

#count{1: course(db); 2: course(web); 3: course(ai)}

= 2.

11

Вычисление при этом представляет собой определение количества

#count{1; 2; 3} = 2.

Рассмотренные варианты агрегаторов могут использоваться как в голове, так и в теле правил:

a.

cnt(X) :- X = #count{ -2 : a; 3 : a }. sum(X) :- X = #sum { -2 : a; 3 : a }. pos(X) :- X = #sum+{ -2 : a; 3 : a }. min(X) :- X = #min { -2 : a; 3 : a }.

max(X) :- X = #max { -2 : a; 3 : a }.

Результат наглядно демонстрирует применение функций:

Answer: 1 a cnt(2) sum(1) pos(3) min(-2) max(3)

Рассмотрим программу с суммированием:

#sum{ 3 : cost(1,2,3); 3 : cost(2,3,3) } = 3.

Её результаты:

Answer: 1 cost(1,2,3)

Answer: 2 cost(2,3,3)

Answer: 3 cost(2,3,3) cost(1,2,3)

Следует отметить, что использованы одинаковые термы-веса, в то же время ASP ожидает, что они будут уникальны, именно поэтому в результате появился ответ № 3. Эту программу можно изменить следующим образом.

#sum{ 3,a : cost(1,2,3); 3,b : cost(2,3,3) } = 3.

Тогда результат будет следующий:

Answer: 1 cost(1,2,3)

Answer: 2 cost(2,3,3)

В данном случае получились уникальные термы 3,a и 3,b, а суммирование выполняется только по первым числам.

Использование сокращений

Если необходимо задать ограничение на количество результирующих атомов, допустима запись, в которой опущено указание на функцию #count и не приводятся термы-веса:

{course(db); course(web); course(ai)} = 2.

Результат:

Answer: 1 course(web) course(db)

Answer: 2 course(ai) course(web)

12

Answer: 3 course(ai) course(db)

Атомы, сгенерированные агрегаторами, могут отфильтровываться с помощью ограничений целостности:

{course(db); course(web); course(ai)} = 2.

:- course(web).

Результат:

Answer: 1 course(db) course(ai)

Рассмотрим программу «сваха»:

male(tom;alex). female(mary;liza). {couple(X, Y)} :- male(X), female(Y). :- couple(X, Y), couple(X, Z), Y != Z.

:- couple(X, Y), couple(Z, Y), X != Z.

В предложенной программе первая строка задаёт перечень представителей мужского и женского пола. Вторая строка с использованием агрегатора описывает все возможные супружеские пары. Ограничения целостности в третьей и четвёртой строке – запрещают многоженство и многомужество. Результаты:

Answer: 1 ...

Answer: 2 ... couple(alex,mary)

Answer: 3 ... couple(tom,liza)

Answer: 4 ... couple(alex,mary) couple(tom,liza) Answer: 5 ... couple(alex,liza)

Answer: 6 ... couple(tom,mary)

Answer: 7 ... couple(tom,mary) couple(alex,liza)

Приведённый пример демонстрирует следующие особенности использования механизма агрегаторов в ASP.

1.Использование агрегаторов в голове правила. При этом генерируются значения, но нет возможности задать нижнюю и верхнюю границы или использовать функции.

2.Создание с использованием агрегатора новых фактов в программе.

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

1.7. Оптимизация

Использование оптимизации позволяет не просто найти набор ответов, а найти оптимальный набор ответов. Предусмотрена линейная оптимизация с

13

получением минимальных (#minimize) и максимальных (#maximize) значений оптимизируемого параметра:

#minimize{w1@p1,t1 : L1, ... , wn@pn,tn : Ln}

В данном описании @pj – приоритет (необязательное значение), wj – вес, который будет минимизироваться среди истинных литералов Lj

(1 j n).

Оптимизацию называют мягким ограничением. Для решения задачи минимизации существует альтернативная запись.

: ~noisy. [ 1@3 ]

#minimize { 1@3 : noisy }.

Приведённые две записи с точки зрения ASP полностью идентичны. Рассмотрим следующую программу.

{ hotel(1..5) } = 1. star(1,5). cost(1,170). star(2,4). cost(2,140). star(3,3). cost(3,90).

star(4,3). cost(4,75). main_street(4). star(5,2). cost(5,60).

noisy :- hotel(X), main_street(X). #maximize{Y@1,X : hotel(X), star(X,Y)}.

#minimize{Y/Z@2,X : hotel(X), cost(X,Y), star(X,Z)}.

#minimize{1@3 : noisy}.

Дано пять отелей, определена их «звёздность», стоимость и шумность. Последнее ограничение говорит, что не нужен шумный отель. В первую очередь требуется максимизировать звёздность, во вторую – минимизировать отношение стоимости на звездность. Из программы видно, что под требование минимизации подходят два отеля № 3 и № 5, но у отеля № 3 выше «звёздность». Результат:

Answer: 1 ... hotel(1)

Optimization: 0 34 12

Answer: 2 ... hotel(3)

Optimization: 0 30 14

OPTIMUM FOUND

14

1.8. Дополнительные возможности ASP

Комментарии начинаются с символа «%», для многострочных комментариев используется символ открытия «%*» и символ закрытия «*%» комментариев.

Директива #show ограничивает результаты вывода. Для примера с отелями (раздел 1.7):

#show hotel/1.

При использовании данной директивы в качестве результата будут вы-

ведены только hotel(1) и hotel(3).

Директива #const позволяет задавать константы, которые могут изменяться в командной строке:

#const x = 42.

#const y = f(x,z).

p(x,y).

Результат:

p(42,f(42,z))

Замена константы:

clingo.exe --text -c x="2+2*2" -c z=7 1.lp

Результат:

p(6,f(6,7)).

Рассмотрим вычисление чисел Фибоначчи: x(n) = x(n-1) + x(n-2).

#const n=4. num(1..n).

fib(0, 1). fib(1, 1).

fib(N, X1 + X2) :- num(N), N > 1, fib(N - 1, X1), fib(N - 2, X2).

#show fib/2.

Результат:

fib(0,1) fib(1,1) fib(2,2) fib(3,3) fib(4,5)

1.9.Упражнения

1.Задан набор фактов, описывающих числа:

#const n = 5.

4{num(1..n)}.

15

Дополните программу таким образом, чтобы был только один набор ответов, в котором игнорируется число 2. Единственный набор ответов для n=5:

num(1) num(3) num(4) num(5)

2. Задан набор фактов, описывающих генеалогическое дерево:

person(tom; bob; alex; liza; sam; mary; lucy).

parent(tom,(bob;alex)). parent(bob,(liza;sam)).

parent(sam,(mary;lucy)).

male(tom;bob;alex;sam).

female(liza;mary;lucy).

Напишите программу «есть сестра», которая отобразит только тех, у кого есть сестра. Правильный ответ для приведённой программы:

havesister(sam) havesister(lucy) havesister(mary)

3. Для набора фактов, описывающих генеалогическое дерево из упражнения (2):

Напишите программу «есть тетя», которая отобразит только тех, у кого есть тетя. Правильный ответ для программы из упражнения (2):

haveaunt(mary) haveaunt(lucy)

4. Дан набор фактов для вычисления факториала: x(n) = x(n-1) * n.

#const n=5.

num(1..n). fact(1, 1).

#show fact/2.

Необходимо дополнить программу, чтобы она вычисляла факториал. Единственный набор ответов для n=5:

fact(1,1) fact(2,2) fact(3,6) fact(4,24) fact(5,120)

5. Дан набор фактов, описывающих числа:

#const n = 12.

num(2..n).

#show prime/1.

Необходимо дополнить программу, чтобы в наборе ответов были только простые числа, меньшие n. Единственный набор ответов для n=12:

prime(2) prime(3) prime(5) prime(7) prime(11)

6. Дан набор фактов, описывающих числа:

#const n = 30.

num(2..n).

16

#show prime6/2.

Необходимо дополнить программу, чтобы в наборе ответов были только пары простых чисел X и Y, меньшие n, отличающиеся на 6. Единственный набор ответов для n=30:

prime6(5,11) prime6(7,13) prime6(11,17)

prime6(13,19) prime6(17,23) prime6(23,29)

7. Задан набор фактов, описывающих решетку 5 на 5:

#const n = 5.

1 { grid(1..n, 1..n) } n*n.

Напишите программу, которая сформирует маршрут из позиции grid(1,1) в grid(5,5). Пример правильного ответа:

move(1,1) move(2,1) move(3,1) move(4,1) move(4,2)

move(4,3) move(4,4) move(4,5) move(5,5)

Для упрощения решения можете исключить из ответа move(1,1) и/или move(5,5).

2.Подходы к решению задач

2.1.Задача о расстановке ферзей

Шахматная фигура ферзь бьёт по горизонтали, по вертикали и по обеим диагоналям. В классической постановке задачи о расстановке ферзей необходимо на доске 8×8 расставить 8 ферзей так, чтобы они не били друг друга. Эта задача может решаться для доски размера n×n.

#const n = 8.

{ queen(1..n,1..n) }. :- { queen(I,J) } != n.

:- queen(I,J), queen(I,X), J != X. :- queen(I,J), queen(X,J), I != X.

:- queen(I,J), queen(X,Y), (I,J) != (X,Y), I-J == X-

Y.

:- queen(I,J), queen(X,Y), (I,J) != (X,Y), I+J == X+Y.

В программе строка 1 – размер доски 8×8. Строка 2 – все возможные варианты расстановки ферзей. Строка 3 – количество ответов равно 8. Строки 4

и5 – запрет нахождения ферзей на одной вертикали и горизонтали. Строки 6

и7 – запрет нахождения на одной диагонали.

17

В результате получается 92 набора ответов следующего вида:

queen(5,1) queen(2,2) queen(4,3) queen(6,4) queen(8,5) queen(3,6) queen(1,7) queen(7,8)

queen(5,1) queen(7,2) queen(4,3) queen(1,4)

queen(3,5) queen(8,6) queen(6,7) queen(2,8)

Возможен другой вариант решения задачи о расстановке ферзей:

#const n = 8. number(1..n).

1 { queen(X,Y) : number(Y) } 1 :- number(X). { queen(1..n,Y) } = 1 :- Y = 1..n.

:- queen(I,J), queen(X,Y), I < X, J+I == Y+X. :- queen(I,J), queen(X,Y), I < X, J-I == Y-X. #show queen/2.

Впрограмме строка 1 – размер доски 8×8. Строка 2 – определение набора чисел от 1 до n. Строки 3 и 4 идентичны друг другу и задают все варианты размещения ферзей на шахматной доске. Строки 5 и 6 обеспечивают запрет нахождения ферзей на одной диагонали, вертикали или горизонтали.

Врезультате получаем 92 ответа следующего вида:

queen(1,4) queen(2,6) queen(3,8) queen(4,2)

queen(5,7) queen(6,1) queen(7,3) queen(8,5)

Программа может быть сокращена. Альтернативный вариант решения:

#const n = 8.

{queen(I,1..n) } = 1 :- I = 1..n.

{queen(1..n,J) } = 1 :- J = 1..n.

:- { queen(D-X,X) } > 1, D = 2..2*n.

:- { queen(D+Y,Y) } > 1, D = 1-n..n-1.

В результате получаем 92 ответа следующего вида:

queen(2,2) queen(5,1) queen(4,3) queen(1,7)

queen(3,6) queen(6,4) queen(8,5) queen(7,8)

2.2.Задача коммивояжера

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

%* Дан взвешенный граф (cost). Первый параметр – начальная вершина дуги, второй параметр – конечная вершина дуги, третий параметр – вес. *%

18

cost(1,2,2). cost(1,3,3). cost(1,4,1).

cost(2,4,2). cost(2,5,2). cost(2,6,4).

cost(3,1,3). cost(3,4,2). cost(3,5,2).

cost(4,1,1). cost(4,2,2).

cost(5,3,2). cost(5,4,2). cost(5,6,1).

cost(6,2,4). cost(6,3,3). cost(6,5,1).

% Дуга описывается edge (см. параметры cost)

edge(X,Y) :- cost(X,Y,_).

% Узел node – первый либо второй параметр cost

node(X) :- cost(X,_,_). node(Y) :- cost(_,Y,_). % Поиск циклов

{cycle(X,Y) : edge(X,Y) } = 1 :- node(X).

{cycle(X,Y) : edge(X,Y) } = 1 :- node(Y).

%* Должен быть ровно один цикл по всем вершинам. Без ограничения целостности может получиться не-

сколько циклов. *%

reached(Y) :- cycle(1,Y).

reached(Y) :- cycle(X,Y), reached(X).

:- node(Y), not reached(Y). % Поиск минимального решения

#minimize { C,X,Y : cycle(X,Y), cost(X,Y,C) }.

#show cycle/2.

В результате находится один набор ответов, обеспечивающий вес пути, равный 11.

Answer: 1 cycle(1,4) cycle(4,2) cycle(3,1) cycle(2,6) cycle(6,5) cycle(5,3)

Optimization: 13

Answer: 2 cycle(1,4) cycle(4,2) cycle(3,1) cycle(2,5) cycle(6,3) cycle(5,6)

Optimization: 12

Answer: 3 cycle(1,2) cycle(4,1) cycle(3,4) cycle(2,5) cycle(6,3) cycle(5,6)

Optimization: 11

OPTIMUM FOUND

19

2.3.Задача о раскрашивании графа

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

% Узлы

node(1..6).

%* Направленные дуги edge. Первый параметр – начальный узел, второй параметр – конечный узел *%

edge(1,(2;3;4)). edge(2,(4;5;6)). edge(3,(1;4;5)).

edge(4,(1;2)). edge(5,(3;4;6)). edge(6,(2;3;5)). % Количество цветов, в которые раскрашивается граф

#const n = 3.

%Возможные варианты цветов для каждого узла графа

{color(X,1..n) } = 1 :- node(X).

%Проверка: соседние вершины имеют разные цвета

:- edge(X,Y), color(X,C), color(Y,C).

#show color/2.

В результате получается один набор ответов:

color(2,2) color(1,3) color(3,2) color(4,1)

color(5,3) color(6,1)

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

% Страны на карте (узлы графа)

countries(belgium;denmark;france;germany;netherlands). % Предполагается использовать 3 цвета

colors(red;green;blue). % Дуги графа

edge(france,(belgium;germany)).

edge(netherlands,belgium).

edge(germany,(belgium;netherlands;denmark)). % Дуги графа должны быть ненаправленные

neighbour(X,Y) :- edge(X,Y).

neighbour(Y,X) :- edge(X,Y).

20

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]