How to add limit in prolog? - prolog

Previously I wrote the predicate, reach(Arrivals,Departure) to find a list of names of departure points from which I can get to a given point arrivals. Now, how can I make sure that the total cost from the calculated route does not exceed a given limit, for example now it`s work like this:
?-reach(krum, Departure).
Answer: Departure = [uzhorod].
in this example, the total cost of the route = 6000, how can it be implemented if 7000 is entered, it is false and if 6000 is true.
This is my facts:
trip(01, kuiv, odessa, 1500).
trip(02, kuiv, lviv, 700).
trip(08, lviv, zaporizhya, 700).
trip(03, uzhorod, krum, 6000).
trip(04, vunohradiv, odessa, 2540).
trip(05, ternopil, kuiv, 3800).
trip(06, zaporizhya, donetsk, 900).
trip(07, lytsk, mariupol, 7500).
trip(Id, Departure, Arrivals, Price)
This is my code:
reachable(D, D, _).
reachable(Departure, Arrival, Visited) :-
trip(_, Departure, Point, _),
\+ member(Point, Visited),
reachable(Point, Arrival, [Point|Visited]).
reachable(Departure, Arrival) :-
reachable(Departure, Arrival, [Departure]).
reach(Arrival, Departures) :-
setof(
Departure,
reachable(Departure, Arrival),
Departures
).

Related

How to make the predicate spent(Passengers, Year, Sum) in prolog?

I need to write a predicate "spent" that would find the total costs for tickets of passengers from
of the "Passengers" list in the given year "Year".
I have these facts:
trip(01, Tokio, Toronto, 1500). /trip (Id, From, To, Price)/
trip(02, California, London, 700).
ticket(01, Sara, 2021-12-26). /ticket (Id, Passenger, Date)/
ticket(02, Jane, 2021-05-21).
I wrote this code, but it is not enough to complete the task, please help.
sum_cash(Price) :- spent(sum(A), trip(_, _, _, A), Price).

shortest path in GNU PROLOG

need help with PROLOG, if anyone can give direction to any of the questions:
introduction:
I have a water supply network, two water sources (river and lake).
Three repositories.
Three automatic sampling stations.
I converted the raw data to PROLOG information.
Now I need to write down a code to find the following:
1.What is the water source of each point - river or lake (assuming the source is the closest).
The user enters a point number. The answer is the source of the water.
What are the shortest routes from each point to each of the sources.
The user enters a point number. The answer is two lists.
What is the total consumer from the water source to each point.
The user enters a point number. The answer is total consumption.
Assuming a water quality alert was received from a monitoring station, which nodes should be stopped at
Water supply.
j-junction ,r-river, l-lake ,p-pump, t-tank
/* Water junction's database */
flowcalc(source,l,0).
flowcalc(source,r,0).
flowcalc(l,p10,0).
flowcalc(p10,j10,0).
flowcalc(r,p335,1231).
flowcalc(p335,j61,0).
flowcalc(t3,j20,99).
flowcalc(t1,j40,99).
flowcalc(t2,j50,99).
flowcalc(r,j60,1231).
flowcalc(j10,j101,14200).
flowcalc(j101,j103,1350).
flowcalc(j101,j105,2540).
flowcalc(j105,j107,1470).
flowcalc(j103,j109,3940).
flowcalc(j109,j111,2000).
flowcalc(j111,j115,1160).
flowcalc(j111,j113,1680).
flowcalc(j113,j115,2000).
flowcalc(j107,j115,1950).
flowcalc(j113,j193,1660).
flowcalc(j105,j263,2725).
flowcalc(j115,j117,2180).
flowcalc(j120,j119,730).
flowcalc(j117,j120,1870).
flowcalc(j120,j121,2050).
flowcalc(j121,j119,2000).
flowcalc(j121,j123,1500).
flowcalc(j121,j125,930).
flowcalc(j125,j127,3240).
flowcalc(j127,j20,785).
flowcalc(j127,j129,900).
flowcalc(j129,j131,6480).
flowcalc(j129,j139,2750).
flowcalc(j139,j141,2050).
flowcalc(j141,j143,1400).
flowcalc(j15,j143,1650).
flowcalc(j141,j145,3510).
flowcalc(j145,j147,2200).
flowcalc(j147,j149,880).
flowcalc(j149,j151,1020).
flowcalc(j151,j153,1170).
flowcalc(j153,j125,4560).
flowcalc(j151,j119,3460).
flowcalc(j119,j157,2080).
flowcalc(j157,j159,2910).
flowcalc(j159,j161,2000).
flowcalc(j161,163,430).
flowcalc(j163,j164,150).
flowcalc(j164,j166,490).
flowcalc(j265,j169,590).
flowcalc(j169,j167,60).
flowcalc(j187,j204,99.9).
flowcalc(j169,j171,1270).
flowcalc(j171,j173,50).
flowcalc(j171,j271,760).
flowcalc(j181,j35,30).
flowcalc(j181,j177,30).
flowcalc(j177,j179,30).
flowcalc(j179,j183,210).
flowcalc(j179,j40,1190).
flowcalc(j185,j184,99.9).
flowcalc(j185,183,510).
flowcalc(j184,j205,4530).
flowcalc(j185,j204,1325).
flowcalc(j189,j183,1350).
flowcalc(j187,j189,500).
flowcalc(j169,j269,646).
flowcalc(j191,j187,2560).
flowcalc(j267,j189,1230).
flowcalc(j191,j193,520).
flowcalc(j193,j195,360).
flowcalc(j195,j161,2300).
flowcalc(j197,j191,1150).
flowcalc(j111,j197,2790).
flowcalc(j173,j199,4000).
flowcalc(j199,j201,630).
flowcalc(j201,j203,120).
flowcalc(j199,j273,725).
flowcalc(j205,j207,1200).
flowcalc(j207,j206,450).
flowcalc(j207,j275,1430).
flowcalc(j206,j208,510).
flowcalc(j208,j209,885).
flowcalc(j209,j211,1210).
flowcalc(j211,j213,990).
flowcalc(j213,j215,4285).
flowcalc(j215,j217,1660).
flowcalc(j217,j219,2050).
flowcalc(j217,j225,1560).
flowcalc(j213,j229,2200).
flowcalc(j229,j231,1960).
flowcalc(j211,j237,2080).
flowcalc(j237,j229,790).
flowcalc(j237,j239,510).
flowcalc(j239,j241,35 ).
flowcalc(j241,j243,2200).
flowcalc(j241,j247,445).
flowcalc(j239,j249,430).
flowcalc(j247,j249,10).
flowcalc(j247,j255,1390).
flowcalc(j255,j50,925).
flowcalc(j255,j253,1100).
flowcalc(j255,j251,1100).
flowcalc(j251,j249,1450).
flowcalc(j257,j120,645).
flowcalc(j259,j257,350).
flowcalc(j259,j263,1400).
flowcalc(j257,j261,1400).
flowcalc(j161,j117,645).
flowcalc(j261,j263,350).
flowcalc(j267,j265,1580).
flowcalc(j267,j163,1170).
flowcalc(j189,j269,646).
flowcalc(j181,j271,260).
flowcalc(j273,j275,2230).
flowcalc(j205,j273,645).
flowcalc(j265,j163,1200).
flowcalc(j201,j275,300).
flowcalc(j269,j271,1290).
flowcalc(j61,j123,45500).
flowcalc(j60,j601,1).
flowcalc(j601,j61,1).
/* best route Finding (use shortest distance) */
/* Stage one find all possible routes */
go:- write('Enter place to start from:'),read(Start),
write('Enter place to end at:'),read(End),
getroute(Start,[End],route,Dist),
assert(route(route,Dist)),nl,fail.
/* Chose the best one */
go:- findall(Dist,route(_,Dist),Distlist),
min(Distlist,Min),route(route,Min),
write('best rout is:'),nl,
writelist(route),retracall(route(_,_)).
/* find routes sections */
getroute(Start,[Start|rest],[Start|rest],0).
getroute(Start,[junction|rest],route,Dist):-flowcalc(Next,junction,D1),not_member(Next,rest),getroute(Start,[Next,junction|rest],route,D2),Dist is D1 + D2.
getroute(Start,[junction|rest],route,Dist):-flowcalc(junction,Next,D1),not_member(Next,rest),getroute(Start,[Next,junction|rest],route,D2),Dist is D1 + D2.
/* Check if not member */
not_member(_,[]):-!.
not_member(X,[Y|l]):-X\=Y,not_member(X,l).
/* find the minimum length route */
min(last,last).
min([l|lt],Min):-min(lt,SubMin),(l<SubMin,Min=l);Min=SubMin.
/* display the route */
writelist([]).
writelist([l|lt]):-write(l),nl,writelist(lt).
Friends I was able to answer the first 3 questions, but I have a very difficult performance problem, each time it takes the software to search for a route and a lot of time. I would love if you could direct, maybe change search method?
for sample check connection between two water sources
water_shortest_path(l, r, MinCost, Path).
takes hour to response.
path(X, Y, N, Path) :- path(X, Y, N, [], Path).
path(X, Y, N, Seen, [X]) :-
\+ check_member(X, Seen),
edge(X, Y, N).
path(X, Z, N, Seen, [X|T]) :-
\+ check_member(X, Seen),
edge(X, Y, N0),
path(Y, Z, N1, [X|Seen], T),
\+ check_member(X, T),
N is N0 + N1.
check_member(X, L) :- once(member(X, L)).
member(X, [X|_]).
member(X, [_|Xs]) :- member(X, Xs).
water_shortest_path(X, Y, MinCost, Path) :-
path(X, Y, MinCost, Path),
\+ (path(X, Y, LowerCost, OtherPath),
OtherPath \= Path,
LowerCost =< MinCost).
edge(l,l,0).
edge(r,r,0).
edge(l,p10,0).
edge(p10,j10,0).
edge(r,p335,1231).
edge(p335,j61,0).
edge(t3,j20,99).
edge(t1,j40,99).
edge(t2,j50,99).
edge(r,j60,1231).
edge(j10,j101,14200).
edge(j101,j103,1350).
edge(j101,j105,2540).
edge(j105,j107,1470).
edge(j103,j109,3940).
edge(j109,j111,2000).
edge(j111,j115,1160).
edge(j111,j113,1680).
edge(j113,j115,2000).
edge(j107,j115,1950).
edge(j113,j193,1660).
edge(j105,j263,2725).
edge(j115,j117,2180).
edge(j120,j119,730).
edge(j117,j120,1870).
edge(j120,j121,2050).
edge(j121,j119,2000).
edge(j121,j123,1500).
edge(j121,j125,930).
edge(j125,j127,3240).
edge(j127,j20,785).
edge(j127,j129,900).
edge(j129,j131,6480).
edge(j129,j139,2750).
edge(j139,j141,2050).
edge(j141,j143,1400).
edge(j15,j143,1650).
edge(j141,j145,3510).
edge(j145,j147,2200).
edge(j147,j149,880).
edge(j149,j151,1020).
edge(j151,j153,1170).
edge(j153,j125,4560).
edge(j151,j119,3460).
edge(j119,j157,2080).
edge(j157,j159,2910).
edge(j159,j161,2000).
edge(j161,j163,430).
edge(j163,j164,150).
edge(j164,j166,490).
edge(j265,j169,590).
edge(j169,j167,60).
edge(j187,j204,99.9).
edge(j169,j171,1270).
edge(j171,j173,50).
edge(j171,j271,760).
edge(j181,j35,30).
edge(j181,j177,30).
edge(j177,j179,30).
edge(j179,j183,210).
edge(j179,j40,1190).
edge(j185,j184,99.9).
edge(j185,j183,510).
edge(j184,j205,4530).
edge(j185,j204,1325).
edge(j189,j183,1350).
edge(j187,j189,500).
edge(j169,j269,646).
edge(j191,j187,2560).
edge(j267,j189,1230).
edge(j191,j193,520).
edge(j193,j195,360).
edge(j195,j161,2300).
edge(j197,j191,1150).
edge(j111,j197,2790).
edge(j173,j199,4000).
edge(j199,j201,630).
edge(j201,j203,120).
edge(j199,j273,725).
edge(j205,j207,1200).
edge(j207,j206,450).
edge(j207,j275,1430).
edge(j206,j208,510).
edge(j208,j209,885).
edge(j209,j211,1210).
edge(j211,j213,990).
edge(j213,j215,4285).
edge(j215,j217,1660).
edge(j217,j219,2050).
edge(j217,j225,1560).
edge(j213,j229,2200).
edge(j229,j231,1960).
edge(j211,j237,2080).
edge(j237,j229,790).
edge(j237,j239,510).
edge(j239,j241,35 ).
edge(j241,j243,2200).
edge(j241,j247,445).
edge(j239,j249,430).
edge(j247,j249,10).
edge(j247,j255,1390).
edge(j255,j50,925).
edge(j255,j253,1100).
edge(j255,j251,1100).
edge(j251,j249,1450).
edge(j257,j120,645).
edge(j259,j257,350).
edge(j259,j263,1400).
edge(j257,j261,1400).
edge(j161,j117,645).
edge(j261,j263,350).
edge(j267,j265,1580).
edge(j267,j163,1170).
edge(j189,j269,646).
edge(j181,j271,260).
edge(j273,j275,2230).
edge(j205,j273,645).
edge(j265,j163,1200).
edge(j201,j275,300).
edge(j269,j271,1290).
edge(j61,j123,45500).
edge(j60,j601,1).
edge(j601,j61,1).
edge(p10,l,0).
edge(j10,p10,0).
edge(p335,r,1231).
edge(j61,p335,0).
edge(j20,t3,99).
edge(j40,t1,99).
edge(j50,t2,99).
edge(j60,r,1231).
edge(j101,j10,14200).
edge(j103,j101,1350).
edge(j105,j101,2540).
edge(j107,j105,1470).
edge(j109,j103,3940).
edge(j111,j109,2000).
edge(j115,j111,1160).
edge(j113,j111,1680).
edge(j115,j113,2000).
edge(j115,j107,1950).
edge(j193,j113,1660).
edge(j263,j105,2725).
edge(j117,j115,2180).
edge(j119,j120,730).
edge(j120,j117,1870).
edge(j121,j120,2050).
edge(j119,j121,2000).
edge(j123,j121,1500).
edge(j125,j121,930).
edge(j127,j125,3240).
edge(j20,j127,785).
edge(j129,j127,900).
edge(j131,j129,6480).
edge(j139,j129,2750).
edge(j141,j139,2050).
edge(j143,j141,1400).
edge(j143,j15,1650).
edge(j145,j141,3510).
edge(j147,j145,2200).
edge(j149,j147,880).
edge(j151,j149,1020).
edge(j153,j151,1170).
edge(j125,j153,4560).
edge(j119,j151,3460).
edge(j157,j119,2080).
edge(j159,j157,2910).
edge(j161,j159,2000).
edge(j163,j161,430).
edge(j164,j163,150).
edge(j166,j164,490).
edge(j169,j265,590).
edge(j167,j169,60).
edge(j204,j187,99.9).
edge(j171,j169,1270).
edge(j173,j171,50).
edge(j271,j171,760).
edge(j35,j181,30).
edge(j177,j181,30).
edge(j179,j177,30).
edge(j183,j179,210).
edge(j40,j179,1190).
edge(j184,j185,99.9).
edge(j183,j185,510).
edge(j205,j184,4530).
edge(j204,j185,1325).
edge(j183,j189,1350).
edge(j189,j187,500).
edge(j269,j169,646).
edge(j187,j191,2560).
edge(j189,j267,1230).
edge(j193,j191,520).
edge(j195,j193,360).
edge(j161,j195,2300).
edge(j191,j197,1150).
edge(j197,j111,2790).
edge(j199,j173,4000).
edge(j201,j199,630).
edge(j203,j201,120).
edge(j273,j199,725).
edge(j207,j205,1200).
edge(j206,j207,450).
edge(j275,j207,1430).
edge(j208,j206,510).
edge(j209,j208,885).
edge(j211,j209,1210).
edge(j213,j211,990).
edge(j215,j213,4285).
edge(j217,j215,1660).
edge(j219,j217,2050).
edge(j225,j217,1560).
edge(j229,j213,2200).
edge(j231,j229,1960).
edge(j237,j211,2080).
edge(j229,j237,790).
edge(j239,j237,510).
edge(j241,j239,35 ).
edge(j243,j241,2200).
edge(j247,j241,445).
edge(j249,j239,430).
edge(j249,j247,10).
edge(j255,j247,1390).
edge(j50,j255,925).
edge(j253,j255,1100).
edge(j251,j255,1100).
edge(j249,j251,1450).
edge(j120,j257,645).
edge(j257,j259,350).
edge(j263,j259,1400).
edge(j261,j257,1400).
edge(j117,j161,645).
edge(j263,j261,350).
edge(j265,j267,1580).
edge(j163,j267,1170).
edge(j269,j189,646).
edge(j271,j181,260).
edge(j275,j273,2230).
edge(j273,j205,645).
edge(j163,j265,1200).
edge(j275,j201,300).
edge(j271,j269,1290).
edge(j123,j61,45500).
edge(j601,j60,1).
edge(j61,j601,1).

How do I write 'findall' in a Prolog code itself?

So, I am very new to Prolog and I have to write a short code about timetable.
How can I add the findall function to a code itself?
happening(monday,chemistry).
happening(monday,english).
happening(tuesday,chemistry).
happening(wednesday,maths).
happening(friday,chemistry).
happening(friday,maths).
And now I want to write a command that shows how many times do I have chemistry in a week.
find_lessons(X) :-
findall(X,happening(X,chemistry), Bag).
I assume you want the result, so the Bag, so you should rewrite find_lessons(X) to find_lessons(Bag):
find_lessons(Bag) :-
findall(X, happening(X,chemistry), Bag).
This will then give a list of days when there is a chemistry lesson, so:
?- find_lessons(Bag).
Bag = [monday, tuesday, friday].
to count the number of lessons, you can use length/2:
?- find_lessons(Bag), length(Bag, N).
Bag = [monday, tuesday, friday],
N = 3.
But one can do this more efficient. Right now there is overhead in constructing the list, and counting the elements. We can make use of the aggregate library [swi-doc] and use the aggregate/3 predicate [swi-doc]:
?- aggregate(count, X^happening(X, chemistry), Total).
Total = 3.
so we can count the number of chemistry lessons with:
:- use_module(library(aggregate))
num_chem_lessons(N) :-
aggregate(count, X^happening(X, chemistry), N).

Directed graphs in prolog

I have a graph that I am creating rules on. owes money graph
I have created rules that shows who owes money to who
owes(alice,5,charlie).
owes(alice,20,bob).
owes(bob,10,charlie).
I have created rules that display who owes someone under a certain amount or over
owesOver10(X,Y) :-owes(X,Y,Z),(Y>=10).
owesUnder10(X,Y) :-owes(X,Y,Z),(Y<10).
however know I need to write a rule that shows how much money a person owes in total so for instance it should display 25 for alice, and 10 for bob.
I propose the use of findall/3 to get a list of all owes and a simple sumList/2 to get the sum of the values.
By example
listSum([], 0).
listSum([H | T], S0) :-
listSum(T, S1),
S0 is S1 + H.
totOwes(X, S) :-
findall(Y, owes(X, Y, _), L),
listSum(L, S).
Calling totOwes(alice, S), I get that S is unified with 25; for bob with 10 and for charlie with 0.

Prolog find flights

I'm having some issues with the findall/3 in Prolog.
Facts:
%
country(dublin,ireland).
country(cork,ireland).
country(london,uk).
country(rome,italy).
country(moscow,russia).
country(hongkong,china).
country(amsterdam,holland).
country(berlin,germany).
country(paris,france).
country(newyork,usa).
country(chicago,usa).
country(sao_paulo,brazil).
country(rio,brazil).
I need to write predicate to show the connections from city X to city Y (one by one). X and Y are the two inputs (city) and T is the output. Each solution T is a list of all the cities connecting X to Y (X and Y included).
Example:
| ?- trip(rome,dublin,T).
T=[rome,london,dublin] ;
//first solution T=[rome,paris,dublin];
//second solution
my try is
path(X,Y,[X|Y]):- edge(X,Y).
path(X,Y,[]):- edge(X,Z),not(member(Z,V)),path(Z,Y,[Z|V]).
Any ideas would be greatly appreciated.
Cheers,
I think your question is: "how can I display all possible trip between two country ?". If so I advice you to do something like that:
trip(X,Y,T) :- X \= Y,
path(X, Y, [X], T).
path(Departure, Arrival, Visited, go(Departure, Arrival)) :- direct(Departure, Arrival) , !.
path(Departure, Arrival, Visited, go(Departure, Intermediate, GO)) :-
direct(Departure, Intermediate),
Intermediate \= Departure,
\+ member(Intermediate,Visited),
path(Intermediate, Arrival, [Intermediate|Visited], GO).
So I also advice you to modify the facts in your knowledge base like:
direct(rome, moskow).
direct(moskow, paris).
direct(paris, chicago).
direct(sau_paolo, rio).
direct(rio, honkong).
and so on.
What you did is logically uncorrect. How can you know if you can travel from a city to another only knowing where they are? There should be some facts that state that is possible travel from a city to another, e.g. direct(rome, milan) (or travel(rome, milan), you choose the functor).
I hope to have help you.
If you have some dubt, just ask ;)
by use prolog
Timetable of air routes
Each air route can be described by a structure:
country of departure, country of landing, date of departure, time of departure, duration, tariffs.
Tariff can described by a structure:
price for business class, price for economy class.
Implement the following rules:
• Find all routes from the given country
• Find all routes to the given country with duration less then than the given number
• Find all routes with the cheapest price for economy class
• Find all prices for flying from one given country to another given country

Resources