Clingo/ASP: лучший способ генерировать персонажей в генераторе историй

Я пытаюсь написать генератор историй в Clingo.

Я пытаюсь сказать: «Новые персонажи могут родиться, если их породят существующие персонажи». Я определяю новые символы как entity(<int\>), и это лучший способ представления сущностей, который я мог придумать. Я не могу жестко закодировать это, так как в истории может быть создано различное количество сущностей.

My code is :

% Create instances of time, only 3 for testing
time(0..2).

% Arrow of time flows forward
next_t(T, T+1) :- time(T), time(T+1).

% Entity 1 exists at time 0.
entity(1, 0).

% If an entity ever existed, that ID is taken and cannot be assigned to
% other entities
entity_id(ID) :- entity(ID, _).

% If an entity exists, he can give birth to a new entity
% The ID of the new entity will be 1 more than ID of all current entities.
birth(X, Y, T) :- entity(Y, T), X = #max{X1+1:entity_id(X1)}, time(T).

% At each time instant, only 1 entity can be born, as only 1 event can happen per time instant.
% This also should prevent infinite entities to be created.
:- birth(X1, _, T), birth(Y1, _, T), X1!=Y1.

% In case of a birth, create a new entiti the next time instant.
entity(X, T1) :- birth(X, _, T), next(T, T1).

#show entity_id/1.
#show entity/2.
#show birth/3 .

Однако вывод:

entity_id(1) entity(1,0) birth(2,1,0)

entity(2, 1) никогда не создается, равно как и entity(3, 2) или entity(4, 3).

Что я делаю не так? Есть лучший способ сделать это?


person Sid Datta    schedule 10.07.2018    source источник
comment
Вы действительно запускали код? clingo очень полезно информирует вас о том, что ваш предикат next отличается от next_t. Исправив это, вы получите ошибку, для которой вам нужно отметить, что вы пытаетесь взять #max набора, сгенерировать что-то, что увеличивает максимальный идентификатор этого набора, что затем делает предыдущий оператор недействительным как максимум, который мы найденное уже не является максимальным. Чтобы получить желаемый результат, вы можете сделать, например. birth(Y+1, Y, T) :- entity(Y, T), time(T)., но этого может быть недостаточно для вашей более крупной цели.   -  person vukk    schedule 11.07.2018
comment
Спасибо. Ошибка, которую я получаю после исправления, operation undefined: (1*X1+1), а затем зависание, что очень тупо. Я использую clingo 5.2, более поздние версии clingo лучше отображают сообщения об ошибках? Кажется, что генерация сложна в моделях clingo/stable. Мне придется изменить модель извне и создать стабильную модель на основе этого для каждого временного шага.   -  person Sid Datta    schedule 11.07.2018


Ответы (1)


Вы, кажется, думаете, что операторы ASP выполняются по порядку от первого к последнему или что-то в этом роде. Но на самом деле это всего лишь правила о наборе атомов. Правила всегда действуют. В частности правило:

entity_id(ID) :- entity(ID, _).

ничего не говорит о дубликатах. Он просто говорит, что для каждой сущности с идентификатором ID ID является entity_id. Если вы хотите закодировать правило, что каждый ID используется один раз, вы должны написать его как:

:- {entity(ID,_)} > 1; entity_id(ID).

Также вы пытаетесь создать «ID», которые «на один больше, чем все текущие объекты», но не существует такой вещи, как «текущие» объекты. Все, что нам нужно, — это временные шаги.

Давайте попробуем написать это таким образом, чтобы наши временные шаги были явными.


% Create instances of time, only 3 for testing
time(0..2).

% Entity eve exists at time 0.
entity(1, 0).

nextID(2, 0).

% If an entity existed at the previous time-step, they continue to exist
% at the next time-step (as I understand, no entity dies).
entity(ID, T) :- entity(ID, T-1); time(T).

% Any entity who was alive on the previous time-step can give birth to
% a child at time T. This child's ID is the current `nextID`
% Note this is a _choice_ rule. The entity _can_ give birth, they don't
% have to. Also we only allow at most one of these births to happen at
% each time-step.
{birth(ChildID, ParentID, T) : entity(ParentID,T-1)} <= 1 :- nextID(ChildID,T).

% Once born, an ID becomes an entity.
entity(ID,T) :- birth(ID,_,T).

% If an entity was born at the previous time-step, the nextID increases by one
% for this time-step.
nextID(ID+1,T) :- nextID(ID,T-1); time(T); entity(ID,T-1).
% Otherwise it stays the same.
nextID(ID,T) :- nextID(ID,T-1); time(T); not entity(ID,T-1).

#show birth/3.

Запустив это, я обнаружил, что есть 5 моделей.

$ clingo entities.asp 0
clingo version 5.3.1
Reading from entities.asp
Solving...
Answer: 1

% ^ Nobody is ever born
Answer: 2
birth(2,1,2)
% ^ Nobody born at time 1. 1 births a child at time 2
Answer: 3
birth(2,1,1) birth(3,2,2)
% ^ 1 births a child at time 1 and that child gives birth at time 2.
Answer: 4
birth(2,1,1)
% ^ 1 births a child at time 1. Nobody is born at time 2.
Answer: 5
birth(2,1,1) birth(3,1,2)
% ^ 1 births two children; one at time 1 and another at time 2.
SATISFIABLE

Models       : 5
Calls        : 1
Time         : 0.011s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time     : 0.004s
person dspyz    schedule 20.09.2018