Prolog: Get all list elements recursively - list

Here I have a list of modules rule.
module(oop). % Object Oriented Programming
module(se1). % Software Engineering 1
module(se2). % Software Engineering 2
% etc.
Then I defined the prerequisites for each module.
require(oop, []). % oop is base module. It doesn't require any other modules.
require(se1, [oop]). % se1 requires oop
require(se2, [se1]). % se2 requires se1
As you can see, se2 requires se1 (directly) and oop (indirectly).
I would like to define a function which goes through the list recursively and return all the required modules as a list.
Query:
?- dependent(se2, L).
Expected Result:
L = [se1, oop]
How can I write the dependent predicate in Prolog using recursion?
Thank you very much for your help.

An easy-obvious way using mutual recursion:
dependent(X,L):- module(X), require(X,L1), find(L1,L).
find([],[]).
find([H|T],L):-dependent(H,L2),find(T,L3),append([H|L2],L3,L).
Examples:
?- dependent(se2,L).
L = [se1, oop].
?- dependent(se1,L).
L = [oop].
?- dependent(oop,L).
L = [].

Related

Prolog - Finding even elements in a list

I want to write a rule in Prolog that returns the even elements in a given list. For example:
even_elements([1,2,3,4], Result) would return Result: [2,4]
Here is what I have so far:
% This is my base case.
even_elements([H|T], Result) :- (0 is mod(H,2) -> Result = [H|T] ; Result = T).
% This is my recursion.
even_elements([H|T], [H|NT]) :- even_elements(T, NT).
The base case works properly and eliminates the first element if it is odd; but the recursion doesn't change anything. Any tips on how to complete the recursion is appreciated.
Often the base case in list processing deals with the empty list. Indeed, we can just write:
even_elements([], []).
For the recursive case, we can use quite a lot from your base case, the only thin that we still need to do is recurse on the tail of the list, so:
even_elements([H|T], Result) :-
( 0 is mod(H,2)
-> Result = [H|T2]
; Result = T2
),
even_elements(T, T2).
That being said, there is no need to implement the logic to filter a list. You can make use of the include/3 predicate [swi-doc], and thus define an even predicate:
even(N) :-
0 is N mod 2.
Then we can filter with:
even_elements(L, R) :-
include(even, L, R).
This then gives us:
?- even_elements([1,4,2,5], R).
R = [4, 2].
I also found this solution from this post although Willem's answer is way more readable:
even_elements(L1,L2):-findall(X,(member(X,L1), X mod 2=:=0),L2).

Prolog: compare list elements and sum

New to prolog and trying to implement the following function that takes 3 lists:
True if lists are the same length
True if elements of third list is sum of the two lists
Example: fn([1,2,3],[4,5,6],[5,7,9]) returns true. Note that the sum is element-wise addition.
This is what I have so far:
fn([],[],[]).
fn([_|T1], [_|T2], [_|T3]) :-
fn(T1,T2,T3), % check they are same length
fn(T1,T2,N1), % check that T3=T1+T2
N1 is T1+T2,
N1 = T3.
From what I understand, the error is due to the base case (it has empty lists which causes error with evaluation of addition?)
Thanks for any help and explanations!
In addition to #GuyCoder's answer, I would point out that it is worthwhile to consider using one of the maplist predicates from library(apply) when modifying all elements of lists. You can use a predicate to describe the relation between three numbers...
:- use_module(library(apply)). % for maplist/4
num_num_sum(X,Y,S) :-
S is X+Y.
... and subsequently use maplist/4 to apply it to entire lists:
fn(X,Y,Z) :-
maplist(num_num_sum,X,Y,Z).
This predicate yields the desired results if the first two lists are fully instantiated:
?- fn([1,2,3],[4,5,6],X).
X = [5,7,9]
However, due to the use of is/2 you get instantiation errors if the first two lists contain variables:
?- fn([1,A,3],[4,5,6],[5,7,9]).
ERROR at clause 1 of user:num_num_sum/3 !!
INSTANTIATION ERROR- X is _+B: expected bound value
?- fn([1,2,3],[4,5,A],[5,7,9]).
ERROR at clause 1 of user:num_num_sum/3 !!
INSTANTIATION ERROR- X is A+B: expected bound value
If you only want to use the predicate for lists of integers, you can use CLP(FD) to make it more versatile:
:- use_module(library(apply)).
:- use_module(library(clpfd)). % <- use CLP(FD)
int_int_sum(X,Y,S) :-
S #= X+Y. % use CLP(FD) constraint #=/2 instead of is/2
fnCLP(X,Y,Z) :-
maplist(int_int_sum,X,Y,Z).
With this definition the previously problematic queries work as well:
?- fnCLP([1,A,3],[4,5,6],[5,7,9]).
A = 2
?- fnCLP([1,2,3],[4,5,A],[5,7,9]).
A = 6
Even the most general query yields results with this version:
?- fnCLP(X,Y,Z).
X = Y = Z = [] ? ;
X = [_A],
Y = [_B],
Z = [_C],
_A+_B#=_C ? ;
X = [_A,_B],
Y = [_C,_D],
Z = [_E,_F],
_A+_C#=_E,
_B+_D#=_F ? ;
.
.
.
Since the numbers in the above answers are not uniquely determined, you get residual goals instead of actual numbers. In order to get actual numbers in the answers, you have to restrict the range of two of the lists and label them subsequently (see documentation for details), e.g. to generate lists containing the numbers 3,4,5 in the first list and 6,7,8 in the second list, you can query:
label the lists
restrict the domain | |
v v v v
?- fnCLP(X,Y,Z), X ins 3..5, Y ins 6..8, label(X), label(Y).
X = Y = Z = [] ? ;
X = [3],
Y = [6],
Z = [9] ? ;
X = [3],
Y = [7],
Z = [10] ? ;
.
.
.
X = [3,4],
Y = [6,7],
Z = [9,11] ? ;
X = [3,4],
Y = [6,8],
Z = [9,12] ? ;
.
.
.
On an additional note: there are also clp libraries for booleans (CLP(B)), rationals and reals (CLP(Q,R)) that you might find interesting.
From what I understand, the error is due to the base case.
I don't see it that way.
The first problem I see is that you are trying to process list which leads to thinking about using DCGs, but since you are new I will avoid that route.
When processing list you typically process the head of the list then pass the tail back to the predicate using recursion.
e.g. for length of list you would have
ln([],N,N).
ln([_|T],N0,N) :-
N1 is N0+1,
ln(T,N1,N).
ln(L,N) :-
ln(L,0,N).
The predicate ln/2 is used to set up the initial count of 0 and the predicate ln/3 does the work using recursion. Notice how the head of the list is taken off the front of the list and the tail of the list is passed recursively onto the predicate again. When the list is empty the predicate ln([],N,N). unifies, in this case think copies, the intermediate count from the second position into the third position, which it what is passed back with ln/2.
Now back to your problem.
The base case is fine
fn([],[],[]).
There are three list and for each one look at the list as [H|T]
fn([H1|T1],[H2|T2],[H3|T3])
and the call to do the recursion on the tail is
fn(T1,T2,T3)
all that is left is to process the heads which is
H3 is H1 + H2
putting it all together gives us
fn([],[],[]).
fn([H1|T1], [H2|T2], [H3|T3]) :-
H3 is H1 + H2,
fn(T1,T2,T3).
and a quick few checks.
?- fn([],[],[]).
true.
?- fn([1],[1],[2]).
true.
?- fn([1,2],[3,4],[4,6]).
true.
?- fn([1,2],[3,4,5],[4,6,5]).
false.
With regards to the two conditions. When I look at exercises problems for logic programming they sometimes give a condition like True if lists are the same length or some other condition that returns true. I tend to ignore those at first and concentrate on getting the other part done first, in this case elements of third list is sum of the two lists then I check to see if the other conditions are correct. For most simple classroom exercises they are. I sometimes think teacher try to give out these extra conditions to confuse the student, but in reality the are there just to clarify how the code should work.

Prolog: How do you iterate between two lists (nest for-loop)?

I just started learning Prolog this week so I am not sure if for-loops are possible in Prolog.
I have two lists in Prolog
stringList([hi,hello],[bye,later],X).
How do I create a new solution list with one element per list?
So the output should be:
X = [hi,bye]
X = [hi,later]
X = [hello,bye]
X = [hello,later]
A major advantage when using Prolog is that you can delegate such loops to the Prolog engine. You do not have to write them explicitly.
For example, in your case, think about the problem in this way: What holds (or should hold) about X?
We can say:
X is a list with two elements, say [A,B].
A is a member of the list that is denoted by the first argument.
B is a member of the list that is denoted by the second argument.
So, in Prolog:
one_from_each(As, Bs, [A,B]) :-
member(A, As),
member(B, Bs).
Sample query:
?- one_from_each([hi,hello],[bye,later], X).
X = [hi, bye] ;
X = [hi, later] ;
X = [hello, bye] ;
X = [hello, later].
And it works in other directions too:
?- one_from_each(As, Bs, [hi,bye]).
As = [hi|_4656],
Bs = [bye|_4662] ;
As = [hi|_4656],
Bs = [_4660, bye|_4668] ;
As = [hi|_4656],
Bs = [_4660, _4666, bye|_4674] .
Hence, the whole question is somewhat misguided. When coding in Prolog, always ask: How can I formulate what ought to hold? Once you have such a formulation, you can leave the search for solutions to the Prolog engine!
If you want, you can be more explicit. For example:
one_from_each([], _) --> [].
one_from_each([L|Ls], Rs) -->
one_from_each_(Rs, L),
one_from_each(Ls, Rs).
one_from_each_([], _) --> [].
one_from_each_([R|Rs], L) -->
[[L,R]],
one_from_each_(Rs, L).
Example:
?- phrase(one_from_each([hi,hello],[bye,later]), Ls).
Ls = [[hi, bye], [hi, later], [hello, bye], [hello, later]].
This is sometimes called a spatial representation, because the solutions are now no longer found on backtracking (temporal representation), but represented explicitly.
From this, you see that "loops" correspond to recursive definitions.

Prolog, permutation code understanding

I'm trying to understand how this program works.
Code from Daniel Lyons' solution(from the link above)
takeout(X,[X|R],R).
takeout(X,[F |R],[F|S]) :- takeout(X,R,S).
perm([X|Y],Z) :- perm(Y,W), takeout(X,Z,W).
perm([],[]).
I'm trying ti understand how it works with this list [1,2,3]
So, I have perm([1,2,3],X).
It's easy to understand at first, Y = [2,3] then Y = [3] and then Y = []
After that perm([],[]). is called and it gives us W = []
Now, takeout is called for the first time - takeout(3, Z, []).
It returns Z = [3]
Now, we are going back, where perm([],[]). gives us W = [3], (because Y was [3] at this point)
Same as above, takeout(2, Z, [3]) and Z = [2, 3].
Again perm([], []). and W = [2, 3].
And takeout(1, Z, [2, 3]), which gives us first answer Z = [1, 2, 3]
Here I don't know why program don't end , recursion is done, so why takeout and perm are working again ?
After that takeout is called takeout(1, [2,3]).
Which now works with takeout(X,[F |R],[F|S]) and not with takeout(X,[X|R],R). and that's my second question, why?
In Prolog, a predicate's behavior is quite unlike that of a function in procedural languages. A function is called to perform a task, it executes, and then comes back returning some values or having performed some side effects, or both.
A predicate defines a relation and/or set of facts that establish a logical connection between it's arguments. When a query is made to a predicate in Prolog, Prolog will attempt to find every instantiation of the argument variables that will make that predicate succeed (be true).
In a very simple case, I might have the following facts:
likes(tom, mary). % Tom likes Mary
likes(fred, mary). % Fred likes Mary
Here I have one predicate or fact, likes, which defines a relation between two people. We call the above facts because they each specify a precise, concrete relation with fully instantiated arguments. I can make a query to determine Who likes Mary? as follows:
| ?- likes(Person, mary).
Person = tom ? ;
Person = fred
yes
The query first comes back with Person = tom but indicates it has more options to check once it has found that Person = tom satisfies the query. Entering ; tells Prolog to continue with the next solution (if there is one), and it finds it: Person = fred.
Now let's consider takeout/3. This is a predicate which defines a relation between a set of variables.
takeout(X,[X|R],R).
takeout(X,[F|R],[F|S]) :- takeout(X,R,S).
The takeout/3 predicate has two predicate clauses or rules for the relation. It's helpful to try to read them:
R is what you get if you take X out of [X|R].
[F|S] is what you get if you take X out of [F|R] if S is what you get when you take X out of R.
Prolog looks at multiple clauses in a disjunctive way. That is, a query or call to the predicate will succeed if any one of the rules can hold true. When a query on takeout/3 is made, Prolog will look for instantiations of the given variables in the query which will make it true, and it will attempt to find every such instantiation that does so. In other words, if there's more than one way to satisfy the condition, it will backtrack and attempt to find those variables instantiations that do so.
Consider the query:
?- takeout(X, [1,2,3], R).
Prolog is able to match this to the first predicate clause: takeout(X, [X|R], R) as takeout(1, [1,2,3], [2,3]) by instantiating X = 1 and R = [2,3]. So this query will succeed with the following result:
R = [2,3]
X = 1 ?
But we see that Prolog is indicating there are more options to explore. That's because there's another clause: takeout(X,[F|R],[F|S]) which matches the query, takeout(X, [1,2,3], R). Prolog therefore backtracks and attempts the second clause, which matches:
takeout(X, [1|[2,3]], [1|S]) :- % F = 1, R = [2,3]
takeout(X, [2,3], S).
Prolog will then follow the recursive call takeout(X, [2,3], S) and start from the first clause again and attemp to match takeout(X, [2,3], S) with takeout(X, [X|R], R), which succeeds with X = 2 and S = [3] (takeout(2, [2|[3]], [3]).. The recursion unwinds or returns (as it would in any language), and the previous call head, takeout(X, [1|[2,3]], [1|S]) then ends up instantiating as: takeout(1, [1|[2,3]], [1|[3]]). So we get:
R = [2,3]
X = 1 ? ;
R = [1,3] % that is, [1|[3]]
X = 2 ?
And so on. Similar behavior applies to perm. In the context of the query perm, the calls to takeout backtrack to produce additional results, so perm produces additional results (since its calls to takeout backtrack, just like they do when you query takeout by hand).
As noted by #false, the predicate takeout/3 is implemented as a standard predicate in Prolog as select/3.

Store result as a list using prolog

I wanted the result to be stored in a list.
subject(english, 2).
subject(math,2).
subject(science,2).
get_subject(subject, level) :- subject(subject,level) .
when I have this query:
?-get_subject(X,2).
it gives me the output:
X = english;
X = math;
X = science.
but i wanted the output to be list like this:
[english, math, science]
is it possible to do that in prolog?
Yes, just use findall:
?- findall(X, get_subject(X,2), Subjects).
Also your get_subject definition should use capital-cased words for variables:
get_subject(Subject, Level) :- subject(Subject, Level).
What Prolog system do you use so your small-cased code works?
And of course your get_subject doesn't do anything useful, you can delete its definition and just use subject directly:
?- findall(X, subject(X,2), Subjects).
Subjects = [english, math, science].