Только вычислить/решить конкретное правило в clingo

Предупреждение: новичок в ASP.

Предположим, у нас есть эта простая программа:

      % crime scene

% Facts
present(harry). % was present on the crime scene
present(sally).
present(mary).
motive(harry). % has a motive
motive(sally). 
guilty(harry). 

% encoding / rules
innocent(Suspect) :- motive(Suspect), not guilty(Suspect).
witness(Suspect) :- present(Suspect), not motive(Suspect), not guilty(Suspect).

Вывод, как и ожидалось, таков:

      present(harry) present(sally) present(mary)
motive(harry) motive(sally) guilty(harry)
innocent(sally) witness(mary)

Есть ли способ вычислить только конкретное правило из всех определенных? Я не говорю о том, чтобы спрятать атом за#showзаявление, но на самом деле говорит решателю только вычислитьwitness(Suspect)правило например.

Я предполагаю, что написание двух разных программ - это ответ, но есть ли что-нибудь еще?

Для контекста я использую Clingo Python API для выполнения ASP-программы, содержащей десятки правил. Эти (независимые) правила соответствуют вопросам, на которые пользователь может захотеть получить ответ. На данный момент все они вычисляются при выполнении программы, и я фильтрую вывод, чтобы обрабатывать интересующие атомы только после того, как будет найден ответ.

1 ответ

Я нашел ответ в статье «Учебное пособие по решению гибридных наборов ответов с помощью clingo» Камински и др. (2017) [Архив здесь] .

Короткий ответ

Используйте директиву для разделения программы на подпрограммы (блоки правил). Затем используйте сценарии для выполнения только той подпрограммы, которую вы хотите.

Конкретно:

      % crime scene

% Facts
#program base. % NEW
present(harry). 
present(sally).
present(mary).
motive(harry). 
motive(sally). 
guilty(harry). 

% encoding / rules
#program groundInnocent. % NEW
innocent(Suspect) :- motive(Suspect), not guilty(Suspect).
#program groundWitness. % NEW
witness(Suspect) :- present(Suspect), not motive(Suspect), not guilty(Suspect).

Затем вы можете либо включить скрипт в код ASP:

      #script(python) 
def main(prg):
    prg.ground([("base", []), ("groundWitness", [])])
    prg.solve() 
#end

Или используйте Clingo Python API:

      from clingo.control import Control
def on_model(model):
    print ("result = ", model)

if __name__ == '__main__':
    ctl = Control()
    ctl.configuration.solve.models = 1
    ctl.load("path_to_asp_file")
    ctl.ground([("base", []), ("groundWitness", [])])
    ctl.solve(on_model=on_model)

Важный:

  1. Обратите внимание, что факты помещаются в подпрограмму. И базовая программа явно вызывается перед любой другой подпрограммой, чтобы гарантировать, что факты, используемые вwitnessзаземлены.
  2. Это означает, что подпрограммы должны быть независимыми. Здесь оба наших правила независимы. Если бы у нас былоwitness(Suspect) :- present(Suspect), not innocent(Suspect)., правило не будет обоснованным, посколькуinnocentвыходит за рамкиgroundWitnessподпрограммы и не является частью ни той, ни другой.

См. длинный ответ ниже, чтобы понять, почему.

Длинный ответ

Прямая цитата из раздела 3.1 («Нежное введение») упомянутой выше статьи:

[...] программу можно разделить на несколько подпрограмм с помощью директивы ; он поставляется с именем и необязательным списком параметров. [...] В качестве примера две подпрограммы base и acid(k) могут быть указаны следующим образом:

       a(1).
#program acid(k). 
b(k).
c(X,k) :- a(X).
#program base.
a(2).

Обратите внимание, чтоbaseявляется специальной подпрограммой (с пустым списком параметров): в дополнение к правилам в ее области действия она собирает все правила, которым не предшествует какой-либо#programдиректива. Следовательно, в приведенном выше примере базовая подпрограмма включает фактыa(1)иa(2), хотя только последний находится в фактической сфере действия директивы [...].

Без дополнительных управляющих инструкций (см. ниже) clingo обосновывает и решает только базовую подпрограмму [...]. Обработка других подпрограмм, например, подлежит управлению сценариями.

Для индивидуального управления заземлением и решением может быть предоставлена ​​основная процедура (принимающая объект управления, представляющий состояние clingo в качестве аргумента).

       #script(python) 
def main(prg):
prg.ground([("base",[])])
prg.solve() 
#end.

В то время как приведенная выше управляющая программа соответствует поведению clingo по умолчанию, приведенная ниже программа игнорирует все правила базовой программы, а вместо этого содержит наземную инструкцию для acid(k)[...], где параметрkдолжен быть конкретизирован термином 42.

       #script(python) 
def main(prg):
prg.ground([("acid",[42])])
prg.solve()
#end.

Соответственно, схематический фактb(k)превращается в , из него не получается никакого основного правила c(X,k) :- a(X)из-за отсутствия экземпляров a(X), а команда решения [...] дает устойчивую модель, состоящую изb(42)только.

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

Другие вопросы по тегам