пролог - создать список из фактов по критериям - PullRequest
1 голос
/ 16 февраля 2020

Я пытаюсь создать список из фактов в SWI-Prolog. Есть множество примеров, но я не понимаю, как создать список по критериям . Вы можете увидеть мой код ниже. Предикат извлечение не работает, как я ожидал.

Мне нужно:

L = [depos(sbr, 3000, 3), depos(psb, 4000, 4), depos(hkb, 5000, 5)]

Но я получаю:

?- deposit(X), extract(X, 3, 5, Ls).

X = depos(sbr, 3000, 3),
Ls = [depos(sbr, 3000, 3)] ;
X = depos(psb, 4000, 4),
Ls = [depos(psb, 4000, 4)] ;
X = depos(hkb, 5000, 5),
Ls = [depos(hkb, 5000, 5)] ;
false.

Что мне делать не так?

% vim: ft=prolog

depos(rsb, 1000, 1).
depos(vtb, 2000, 2).
depos(sbr, 3000, 3).
depos(psb, 4000, 4).
depos(hkb, 5000, 5).
depos(mkb, 6000, 6).

deposit(depos(Bank, Body, Rate)) :- depos(Bank, Body, Rate).

bank(depos(Bank,_,_), Bank).
body(depos(_,Body,_), Body).
rate(depos(_,_,Rate), Rate).

% Usage:
% deposit(X), bank(X, Ba), body(X, Bo), rate(X, Ra).

% Usage: create List from Body
% ?- findall(Bo, depos(Ba, Bo, Ra), L).
% L = [1000, 2000, 3000, 4000, 5000, 6000].

% Usage: create List from Rate
% ?- findall(Ra, depos(Ba, Bo, Ra), L).
% L = [1, 2, 3, 4, 5, 6].

profit(X, Prof) :-
  body(X, Body),
  rate(X, Rate),
  Prof is Body * Rate.

% Usage:
% ?- deposit(X), profit(X, Pro).
% X = depos(rsb, 1000, 1),
% Pro = 1000 ;
% X = depos(vtb, 2000, 2),
% Pro = 4000 ;

critRate(X, From, Before) :-
  rate(X, Rate),
  Rate >= From,
  Rate =< Before.

% Usage:
% ?- deposit(X), critRate(X, 3, 5).
% X = depos(sbr, 3000, 3) ;
% X = depos(psb, 4000, 4) ;
% X = depos(hkb, 5000, 5) ;

critProf(X, From, Before, Prof) :-
  profit(X, Prof),
  Prof >= From,
  Prof =< Before.

% Usage:
% ?- deposit(X), critProf(X, 9000, 25000).
% X = depos(sbr, 3000, 3) ;
% X = depos(psb, 4000, 4) ;
% X = depos(hkb, 5000, 5) ;

% How to create List Ls from deposit with Rate From to Before ???
extract(X, From, Before, Ls) :-
  bagof(X, critRate(X, From, Before), Ls).

% Expected:
% L = [depos(sbr, 3000, 3), depos(psb, 4000, 4), depos(hkb, 5000, 5)]

1 Ответ

1 голос
/ 16 февраля 2020

Я думаю, что ваша проблема связана с структурированием вашего кода с помощью «аксессоров», таких как эти 3

bank(depos(Bank,_,_), Bank).
body(depos(_,Body,_), Body).
rate(depos(_,_,Rate), Rate).

и их функциональным использованием.

edit by OP

Не могли бы вы объяснить этот аспект более подробно? Я новичок в Прологе. Я прочитал о аксессорах в Bratko и пользуюсь им без полного понимания. Когда я могу использовать, а когда нет.

В Прологе есть реляционная модель данных, поэтому вам следует пересмотреть свой рабочий процесс. Например, упростите извлечение / 4 для извлечения / 3 следующим образом

extract(From, Before, Ls) :-
  bagof(X, (deposit(X),critRate(X, From, Before)), Ls).

, и вы получите то, что вам нужно:

?- extract(3, 5, Ls).
Ls = [depos(sbr, 3000, 3), depos(psb, 4000, 4), depos(hkb, 5000, 5)].

Это работает! Спасибо.

редактировать с помощью OP

Я добавил новый предикат для critProf

extract_prof4(From, Before, Prof, Ls) :-
  bagof(X, (deposit(X), critProf(X, From, Before, Prof)), Ls).

и это больше не работает.

?- extract_prof4(3000,25000,P,L).
P = 4000,
L = [depos(vtb, 2000, 2)] ;
P = 9000,
L = [depos(sbr, 3000, 3)] ;

НО, если я добавлю еще один предикат (без аргумента в качестве аргумента), например:

critProf3(X, From, Before) :-
  profit(X, Prof),
  Prof >= From,
  Prof =< Before.

extract_prof(From, Before, Ls) :-
  bagof(X, (deposit(X), critProf3(X, From, Before)), Ls).

они работают правильно:

?- extract_prof(3000,25000,L).
L = [depos(vtb, 2000, 2), depos(sbr, 3000, 3), depos(psb, 4000, 4), depos(hkb, 5000, 5)].

Почему?

...