База данных цепей Prolog

У меня есть вопрос по теме этого вопроса (Создать словарь Prolog), но в нем используется немного разная лексика.

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

Основное различие между используемыми словарями заключается в том, что мой использует

signal(in(inPortNumber, portName), signalValue)

В связи с этим у меня есть несколько вопросов:

РЕШЕНО 1 - Как написать "Если C - цепь, пусть ее арность будет I, J (I = numInPorts, J = numOutPorts). Для всех возможных значений N (0 ‹ N ‹ I ), порт номер N C - это терминал"?

Это то, что у меня есть, но оно не работает (бесконечный цикл):

% Check arity of IN wires
% If more in wires than gate can support, it's an error
terminal(in(N, C)) :- circuit(C), arity(C, I, _J), N < I, N > 0.

РЕДАКТИРОВАТЬ 2. Как мне написать «Если клеммы T1 и T2 подключены, и T2 был назначен сигнал, T1 также назначается это значение сигнала»?

Вот что у меня есть:

% FACTS
circuit('c1').
arity('c1', 3, 2).
gate('x1').
type('x1', xorGate).
are_connected(in(1, 'c1'), in(1, 'x1')).
are_connected(in(2, 'c1'), in(2, 'x1')).
signal(in(1, 'c1'), 1).
signal(in(2, 'c1'), 1).
signal(in(3, 'c1'), 1).

% RULES
% All gates are circuits
circuit(G) :- gate(G).

% Check arity of IN wires
terminal(in(N, G)) :- circuit(G), arity(G, I, _J), N =< I, N > 0.
% Check arity of OUT wires
terminal(out(N, G)) :- circuit(G), arity(G, _I, J), N =< J, N > 0.

% Signals do only exist in terminals
terminal(T) :- signal(T, _V).

% Arity
arity(G, 1, 1) :- gate(G), type(G, notGate). % NOT gate
arity(G, 2, 1) :- gate(G), type(G, V), not(V = notGate). % Other gates

% Commutativity
connected(T1, T2) :- are_connected(T1, T2), !.
connected(T2, T1) :- are_connected(T1, T2), !.

% Connectivity
same_signal(T1, T2) :- terminal(T1), terminal(T2), not(T1 = T2), connected(T1, T2).
signal(T1, V) :- same_signal(T1, T2), signal(T2, V), !.
signal(T2, V) :- same_signal(T1, T2), signal(T1, V), !.

Проблема в том, что при запросе:

signal(in(1, x1), V).

Это выдает ошибку, так как вещи недостаточно созданы. Я знаю, где и в чем проблема, но не знаю, как ее решить.

Жду ответов/предложений. Я новичок в Прологе, поэтому буду рад любым советам (но да, я знаю, что должен соединять предложения одного и того же предиката).


person Daniel Carvalho    schedule 29.01.2014    source источник
comment
Как определяется circuit/1? Одной из проблемных точек круговой логики может быть то, что у вас есть terminal(T) :- signal(T, V)., но также и signal(T1, V) :- terminal(T1), .... Они ссылаются друг на друга без какого-либо сведения к терминальному случаю.   -  person lurker    schedule 30.01.2014
comment
Одна вещь: я думаю, вам следует избавиться от второго пункта signal/2 (signal(T2,V) :-...). Поскольку same_signal уже имеет дело с коммутативностью аргументов, это второе предложение является избыточным и позже может стать еще одной причиной зацикливания.   -  person lurker    schedule 01.02.2014


Ответы (1)


В случае 1 Если C — канал, пусть его арность будет равна I, J (I = numInPorts, J = numOutPorts). Для всех возможных значений N (0 ‹ N ‹ I) номер входящего порта N для C является терминалом

terminal(in(N, C)) :-   % in(N, C) is a terminal if...
    circuit(C),         % C is a circuit and...
    arity(C, I, _J),    % Arity of C is I, _ and...
    N < I, N > 0.       % 0 < N < I

Кажется, это соответствует вашему описанию на естественном языке. Вы упомянули, что это вызывает бесконечный цикл, но в этом коде нет ничего, что могло бы вызвать такой цикл. Вам нужно будет показать определение circuit/1, чтобы разбить его дальше.

В случае 2, если клеммы T1 и T2 подключены, а T2 был назначен сигнал, T1 также назначается это значение сигнала

terminal(T) :- signal(T, V).  % T is a terminal if it is assigned a signal

signal(T1, V) :-       % T1 is assigned signal V if...
    terminal(T1),      % T1 is a terminal and...
    terminal(T2),      % T2 is another terminal and...
    connected(T1, T2), % T1 and T2 are connected and...
    signal(T2, V).     % T2 is assigned signal V

Второй пункт здесь уже выражает ваше полное описание.


[Редактировать на основе комментариев OP] Первое предложение, terminal(T) :- signal(T, V), кажется источником для вашего бесконечного цикла, поскольку оно создает циклический вывод между signal и terminal в этих двух предложениях. Потенциальным решением было бы переименовать предложение signal/2 в same_signal/2, чтобы избежать конфликта с именем факта, signal/2.
[Редактировать на основе обновленного описания проблемы OP] При указании ошибки лучше указать точное сообщение об ошибке, в данном случае это ERROR: =</2: Arguments are not sufficiently instantiated. В прологе предикаты неравенства, такие как =</2, требуют, чтобы обе части неравенства были полностью конкретизированы.

Причина, по которой вы находитесь в этом состоянии, заключается в том, что terminal(T1) или terminal(T2) в same_signal/2 в конечном итоге вызовет предикат signal/2:

terminal(T) :- signal(T, _V).

Для некоторых итераций signal/2 удовлетворяются полностью конкретизированными фактами, и поиск по этим работам. Но затем он, наконец, вернется к предикату signal/2 (у вас есть два предложения для предиката) и выдаст неконкретизированный терминал. Это приводит к сбою предложений предиката terminal/1, поскольку N не конкретизировано.

Помимо этого, все еще существует потенциальная опасность бесконечной рекурсии между terminal/1 и signal/2 из-за связи между их предикатами. Есть на что посмотреть.


[EDIT на основе дальнейшего комментария OP] Основная причина существующей проблемы с «неустановленной переменной» заключается в том, что предикат terminal/1, который проверяет арность, также запрашивается для создания терминала. Однако логика проверки арности предназначена не для создания нового терминала, а для проверки существующего (или, по крайней мере, для проверки терминала, для которого уже задана арность).

Если единственной целью пунктов проверки арности является только проверка арности, тогда для этого может потребоваться другое имя и соответствующий вызов.

person lurker    schedule 30.01.2014
comment
Первый был почти правильным, я просто забыл добавить N › 0 в свой код, и это должно быть не N ‹ I, а N = ‹ I. Circuit/1 — это просто факт. Во втором случае терминал :- сигнал(T, V) необходим, потому что можно объявлять только сигналы как факты, а не терминалы, поэтому для того, чтобы второе правило работало, должно существовать первое правило. Вот как я обошел эту проблему: тот же сигнал (T1, T2): - терминал (T1), терминал (T2), не (T1 = T2), подключен (T1, T2). сигнал(T1, V):- тот же сигнал(T1, T2), сигнал(T2, V), !. сигнал(T2, V):- тот же сигнал(T1, T2), сигнал(T1, V), !. - person Daniel Carvalho; 31.01.2014
comment
@DanielCarvalho Понятно. Да, в этом случае подходящим решением будет переименование вашего предиката signal/2 в same_signal/2 (обратите внимание на типичные соглашения об именах Prolog - обычно используется under_scores вместо camelCase). Вне контекста мне было трудно отличить фундаментальные факты от производных терминов. - person lurker; 31.01.2014
comment
Спасибо за совет по именованию, @mbrach. Да, я должен был упомянуть, что является фактом, а что нет. Я, наверное, скоро отредактирую пост, чтобы было понятнее. Я почти закончил его, но несколько раз он все еще находится в бесконечных циклах, когда я пытаюсь выяснить окончательный вывод схемы. - person Daniel Carvalho; 31.01.2014
comment
Я ценю ваш ответ, но, как я уже сказал, я знаю, в чем и где проблема. Основная проблема здесь в том, что я понятия не имею, как переписать свои правила, чтобы этого не произошло. - person Daniel Carvalho; 31.01.2014
comment
@DanielCarvalho, это зависит от цели вашей логики, которая не совсем ясна. Например, предназначены ли предложения для terminal/1, которые проверяют арность, также для определения terminal? Если нет, то у него должно быть другое имя, например terminal_arity/1, и оно должно называться соответствующим образом, где это необходимо, чтобы избежать путаницы в логике между двумя определениями. Аналогично для signal/2: определяется ли signal как фактами, так и предикатами? Или они служат двум разным целям? - person lurker; 31.01.2014
comment
Да, и сигнал определяется как фактами, так и предикатами. Это потому, что если существуют входные или выходные ворота, то это терминал. В этом и заключается цель проверки арности - если число входных ворот выше арности, то у нас ошибка. Что касается сигнала, факты говорят о входных сигналах схемы, а мы хотим запросить выходные сигналы. Таким образом, чтобы вычислить сигнал(выход(1, цепь)), мы должны вычислить входные сигналы после прохождения через логические вентили. - person Daniel Carvalho; 01.02.2014
comment
Я прекрасно понимаю, в чем проблема, но не знаю, как написать решение на Прологе. У меня есть неуниверсальное решение, которое может обрабатывать текущую базу данных, поэтому я просто продолжаю это из любопытства и чтобы иметь возможность выяснить в будущем, буду ли я когда-нибудь снова использовать Prolog. Не могли бы вы написать решение, даже если оно для другой проблемы, созданной вами? - person Daniel Carvalho; 03.02.2014
comment
Вот точная выдержка из проблемы: у нас есть предикат (max_num/2), чтобы сказать, что максимальное значение числа в функции (func/2), которая связывает элемент с числом elem, равно maxNum. Мы хотим объявить как факты как можно больше действительных чисел. Как я вижу проблему в Прологе (правда, написано неправильно): valid_num(func(num, elem)) :- max_num(elem, maxNum), num ‹ maxNum. max_num(элемент, maxNum). Но это не сработает по причине, изложенной во всей этой дискуссии. - person Daniel Carvalho; 03.02.2014