How to call a predicate inside a loop in prolog? - prolog

I am trying to the find the sum of a list of predicates, I have defined function that would find the sum for a list of numbers, however I am struggling to make calls to the predicate to return the number value.
For example the following predicates have been defined
money(jack,600).
money(amanda,1200).
list_sum([],0).
list_sum([Head|Tail], TotalSum):-
list_sum(Tail, Sum1),
TotalSum is temp+Sum1.
The list_sum function currently only finds the sum of a list of integers.
How can I make it find the sum of a list of predicates was given list_sum([jack, amanda], TotalSum)

Query for the amount of money the person has, and add that to the running total:
money(jack,600).
money(amanda,1200).
list_sum([], 0).
list_sum([Person|Tail], TotalSum):-
money(Person, Amount), % <-- head of list is a person
list_sum(Tail, TailSum),
TotalSum is Amount+TailSum. % <-- add their money Amount

Related

Prolog CLP(FD) Number of items in result

I'm now solving a scheduling problem and I'm a bit stuck on the way how to describe number or count of certain items in result.
For example, the result is a list of numbers between 1..7 and I want to at least see or better to define constraints on the count of 1s in the result, 2s, 3s and so on.
I tried some solutions like this:
schedule(D1_D1,D1_D2,D1_N1,D1_N2,D1_A0,D2_D1,D2_D2,D2_N1,D2_N2,D2_A0,D3_D1,D3_D2,D3_N1,D3_N2,D3_A0,D4_D1,D4_D2,D4_N1,D4_N2,D4_A0,D5_D1,D5_D2,D5_N1,D5_N2,D5_A0,D6_D1,D6_D2,D6_N1,D6_N2,D6_A0,D7_D1,D7_D2,D7_N1,D7_N2,D7_A0,SUM_1, SUM_2, SUM_3, SUM_4, SUM_5, SUM_6) :-
Vars = [D1_D1,D1_D2,D1_N1,D1_N2,D1_A0,D2_D1,D2_D2,D2_N1,D2_N2,D2_A0,D3_D1,D3_D2,D3_N1,D3_N2,D3_A0,D4_D1,D4_D2,D4_N1,D4_N2,D4_A0,D5_D1,D5_D2,D5_N1,D5_N2,D5_A0,D6_D1,D6_D2,D6_N1,D6_N2,D6_A0,D7_D1,D7_D2,D7_N1,D7_N2,D7_A0],
Vars ins 1..6,
Sums = [SUM_1, SUM_2, SUM_3, SUM_4, SUM_5, SUM_6],
Sums ins 1..7,
all_distinct([D1_D1,D1_D2,D1_N1,D1_N2,D1_A0]),
all_distinct([D2_D1,D2_D2,D2_N1,D2_N2,D2_A0]),
all_distinct([D3_D1,D3_D2,D3_N1,D3_N2,D3_A0]),
all_distinct([D4_D1,D4_D2,D4_N1,D4_N2,D4_A0]),
all_distinct([D5_D1,D5_D2,D5_N1,D5_N2,D5_A0]),
all_distinct([D6_D1,D6_D2,D6_N1,D6_N2,D6_A0]),
all_distinct([D7_D1,D7_D2,D7_N1,D7_N2,D7_A0]),
include(=(1),Vars,I1),length(I1, SUM_1),
include(=(2),Vars,I2),length(I2, SUM_2),
include(=(3),Vars,I3),length(I3, SUM_3),
include(=(4),Vars,I4),length(I4, SUM_4),
include(=(5),Vars,I5),length(I5, SUM_5),
include(=(6),Vars,I6),length(I6, SUM_6),
append(Vars,Sums,Res),
label(Res).
I define some permutations of the numbers using all_distinct and later I want to see (get the value to the SUM_N) count of a certain number in the result (VARS) list.
But in SWI Prolog I get:
?- schedule(D1_D1,D1_D2,D1_N1,D1_N2,D1_A0,D2_D1,D2_D2,D2_N1,D2_N2,D2_A0,D3_D1,D3_D2,D3_N1,D3_N2,D3_A0,D4_D1,D4_D2,D4_N1,D4_N2,D4_A0,D5_D1,D5_D2,D5_N1,D5_N2,D5_A0,D6_D1,D6_D2,D6_N1,D6_N2,D6_A0,D7_D1,D7_D2,D7_N1,D7_N2,D7_A0,SUM_1, SUM_2, SUM_3, SUM_4, SUM_5, SUM_6).
false.
But there are obviously some solutions matching the criteria. If I remove the "constraints" counting the ocurences of numbers I will get all the suitable permutations. Therefore I think the include(..),length(..) somehow constraints the result but I don't understand why since the result is pointed to a free variable.

Evaluating(interpreting) a list in Prolog

If I have a list in Prolog, made up of operators and operands, how do you interpret the list to achieve the appropriate operators on the appropriate operands?
So lets say we have a list of
[100, 25, sum, 2, multiply, 800, 50, subtract, sum]
should result in [1000] by the following steps
// 100 and 25 are summed together, making it
[125, 2, multiply, 800, 50, subtract, sum]
// 125 and 2 are multiplied, making it 250
[250, 800, 50, subtract, sum]
// 50 is subtracted from 800, making it 750
[250, 750, sum]
// 250 is added to 750, making it 1000
[1000]
I am trying to understand the structure of how to make this happen (in particular, how to iterate through the list and make appropriate actions, not so much on the helper predicates that do the actual work[sum, multiple, etc]). Which scenario is best, and what other considerations should I consider?
Scenario 1 'Along the way' (main predicate, which has list1(before evaluation), and list2 (the final list) ):
Look for the first instance of a non integer in list1
Check to see if that 'word' is in a dictionary or list (probably using member), and if it is, see if there are enough preceding values in the list to accomplish it, if so, return the completed operation with the tail, if not, return false.
Continue until no more words are found
Scenario 2 'Look ahead' (main predicate, which has list1(before evaluation), and list2 (the final list) ):
Look at each element in the list, keeping track of the maximum number of numbers required for the longest operator (lets say and operation called duplicatePairs needed two sets of pairs, therefore 4 numbers)
If I come across an operator, perform the operation, and return the unused head (if any) with the completed result and the tail.
Continue until no more words are found
Scenario 3 'Fold Left' (main predicate, which has list1(before evaluation), and list2 (the final list) ):
Using some map function (maplist/3 maybe), somehow recursively left fold through the list1 until the final list is achieved (borrowing this idea from functional programming[Haskell])
the simpler code I can think of:
eval([A1,A2,sum|Rest], Result) :- Sum is A1+A2, !, eval([Sum|Rest], Result).
eval(Result, Result).
and so on... testing:
?- eval([1,2,sum,4,sum],R).
R = [7].
of course, the 'catchall' eval(Result, Result). must be the last rule...

Retain variable while backtracking prolog

I am trying to find the minimum cost of a path while retaining the variable Min over backtracking. The code below does not work, however it gives a slight idea over what I want.
The Min is variable which holds the current minimum value, when compared with the new Total if the Total is smaller then the NewMin should be Total. This is possible I send the NewMin as Min foreward. However, because I am relying on backtracking, the clause before forcefully fails, and hence all the values stored are lost.
calculate_cost(Start, [], CostList, Min, NewMin):-
sum_list(CostList, Total),
Total < Min,
NewMin is Total.
calculate_cost(Start, Rest, CostList, Min, NewMin):-
flatten(Rest, Places),
[Next|Left] = Places,
route(Start, Next, Cost),
calculate_cost(Next, Left, [Cost|CostList], Min, NewMin),
fail.
Now I want to essentially retain the Min variable till the programs ends, while making several comparisons.
Note: The predicate calculate_cost is called several times (a lot more than 1 million), so lists is not feasible as i've tried and I leads to Out of global stack exception.
Assert option has also been tried, but it leads to the same problem.
The only option is to search through and keep the minimum.
keep updated Path & MinCost when calculate_cost complete:
:- dynamic current_min/2. % Path, Cost
calculate_cost(Start, [], CostList, Min, NewMin):-
sum_list(CostList, Total),
Total < Min,
NewMin is Total,
( current_min(CPath, CMin), CMin =< NewMin
-> true
; retract(current_min(_,_)), assert(current_min(NewPath, NewMin))).
I know NewPath isn't available now: see if you can change your program flow to make NewPath available to calculate_cost
BTW there is Dijkstra algorithm available: why don't you use it ?

PROLOG: How to know if a number is a perfect number?

A perfect number is one that is equal to the sum of all its divisors excluding itself.
e.g. 6 = 1+2+3, then 6 is a perfect number.
I am wondering how to implement this in PROLOG.
Can you give me some ideas?
-Hello Steven,as you may be aware by now PROLOG is a declarative language where we express the program logic using relations.
Your task is to express the relation between a given number and the sum of its divisors. In order to find the sum, you will have to iterate through all possible integers starting from 1 to Number-1(since Number wont be included in the sum) and test whether a given integer is a divisor of the input number.
If the integer is a divisor then add it to the current sum,increment the integer and repeat the task until you reach an integer that has the same value as the input number. Once you get there all you have to do is check the sum( if the sum is equal to our input number, we have a perfect number,otherwise we don't). Below are given the predicates we need :
perfectNumber(Number) :- perfectNumber(Number,1,0).
perfectNumber(Number,Number,Sum):- Number = Sum.
perfectNumber(Number,CurrDivisor,CurrSum) :- not(CurrDivisor = Number),
NewDivisor is CurrDivisor+1,
0 is mod(Number,CurrDivisor),
NewSum is CurrSum+CurrDivisor,
perfectNumber(Number,NewDivisor,NewSum).
perfectNumber(Number,CurrDivisor,CurrSum) :- not(CurrDivisor = Number),
NewDivisor is CurrDivisor+1,perfectNumber(Number,NewDivisor,CurrSum).
Let me know what you think.

Prolog; try to make fibonacci more effective?

This logic programming is really making a lap dance on my imperative programming skills. This is homework, so please just don't drop me the answer. This is what I have:
fibo(N,1) :-
N < 2,
!.
fibo(N,R) :-
N1 is N-1,
N2 is N-2,
fibo(N1,R1),
fibo(N2,R2),
R is R1+R2.
I'm suppose to make another function that looks like this; fib(N,Value,LastValue).
N is the n'th number, and value is the return value. I don't understand how I can rewrite this using accumulation. And since it counts backwards I don't see how it can "know" a last value before it calculates anything. :s Any input is appreciated.
I could post here the solution, but since that this is homework, it would be counter-productive. Instead, here's a lead:
The problem with the version of Fibonacci that you listed is that it is inefficient. Each call to fibo/2 causes another two calls, but some of these calls calculate the values of the same Fibonacci numbers. For example, in pseudo-code:
(a) fibo(4) -> fibo(3), fibo(2)
(b) fibo(3) -> fibo(2), fibo(1)
(c) fibo(2) -> fibo(1), fibo(0) % called from (a)
(d) fibo(2) -> fibo(1), fibo(0) % called from (b), redundant
To overcome this deficiency, you were asked to rephrase Fibonacci in terms of returning not just the last value, but the last two values, so that each call to fib/3 will cause only a single recursive call (hence calculate the Fibonacci series in linear time). You'll need to change the base cases to:
fib(1,1,0).
fib(2,1,1).
I'll leave the recursive case to you.
For the impatient
Here is the recursive case as well:
fib(N, Val, Last) :-
N > 2,
N1 is N - 1,
fib(N1, Last, Last1), % single call with two output arguments,
% instead of two calls with one output argument
Val is Last + Last1.
See the related discussion:
Generalizing Fibonacci sequence with SICStus Prolog
and consider ony's very good solution using finite domain constraints from there.
Perhaps using tail recursion is a good option
edit:
Instead of breaking fib(6) into fib(5)+fib(4) you might try something like fib(6) = fib(6,0,0) the first parameter is the count of steps, when it reaches 0 you stop, the second parameter the last value you calculated, and the third parameter is the value to calculate which is equal to the sum of current second and third parameters (with the exception of the first step, in which 0 + 0 will be 1)
So to calculate you set the second parameter at each call and acumulate in the third so fib(6,0,0) => fib(5,0,1) => fib(4,1,1) => fib(3,1,2) => fib(2,2,3) => fib(1,3,5) => fib(0,5,8) then you return 8
In that method you dont actually have to save in the stack the adress return, avoiding stack overflow
Remember that there is another way to calculate the Fibonacci sequence: starting from the base case and moving up.
Right now, to calculate fib(n), you add fib(n-1) and fib(n-2). Instead, flip that around and calculate fib(0) and fib(1) based on the definition of the Fibonacci sequence, and build up from that.
You almost already have it. Just rewrite:
fibo(N, Value) :-
N1 is N-1, N2 is N-2,
fibo(N1, LastValue),fibo(N2, SecondToLastValue),
Value is LastValue + SecondToLastValue.
in terms of
fibo2(N, Value, LastValue):- ...
I don't understand how I can rewrite
this using accumulation
Just don't, this is not needed (although it's possible to do so).

Resources