1

I'm trying to create list from the facts in SWI-Prolog. There are amount of exapmles but I don't understand how to create list by criteria. You can see my code below. Predicate extract doesn't work as I expected.

I need:

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

But I get:

?- 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.

What do I wrong?

% 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)]
false
  • 10,264
  • 13
  • 101
  • 209
gorshkov
  • 67
  • 6
  • Since your `From` and `Before` are free variables, they will "bind". – Willem Van Onsem Feb 16 '20 at 08:34
  • 1
    This is not a discussion site. Your editing of the answer by CapelliC to ask new questions is very wrong. As you are a new user I won't down vote this question at this time, but if you don't follow the guidelines [tour](https://stackoverflow.com/tour) here I will reconsider. I am not a fan of all of the rules here either, but if we all did what we wanted it would be much harder to find answers when we need them. – Guy Coder Feb 17 '20 at 10:45

1 Answers1

1

I think your problem is related in structuring your code with 'accessors', like these 3

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

and using them in a functional fashion.

edit by OP

Can you, please, explain that aspect in more detail? I'm a new in Prolog. I've read about accessors in Bratko and use it without full understanding. When I can use and when I don't.

Prolog has a relational data model, so you should rethink your workflow. For instance, simplify extract/4 to extract/3 in this way

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

and you'll get what you need:

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

That works! Thank you.

edit by OP

I added new predicate for critProf

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

and it doesn't work again.

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

BUT if I added another predicates (without Prof as an argument), like this:

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).

they work correctly:

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

Why?

CapelliC
  • 59,646
  • 5
  • 47
  • 90