I'm trying to write a predicate is_multi(M), defined as:
every element of M has the form X / N, where X is an atom, and N is an integer greater than 0;
M does not contain two elements with the same atom, for what
is_multi([]).
is_multi([a / 2, b / 2]).
are satisfied, but
is_multi([a, b/2]).
is_multi([a/0, b/2]).
is_multi([a/2, 2/4])
is_multi([a/2, b/3, a/2])
is_multi([a/3, b/-4, c/1])
are not.
Here's what I have written so far:
is_multi(M) :- M = [].
is_multi(M) :-
M = [Head|Tail],
Head = X/N,
integer(N),
N > 0,
is_multi(Tail).
But it does not compare two elements if with the same atom. For example, is_multi([a/2, a/3]) is not satisfied. I got stuck for one day with this; could somebody give me some hints?
First, you can simplify your code considerably by moving some of your unifications from the body to the head.
is_multi([]).
is_multi([X/N|Tail]) :-
integer(N), N > 0,
is_multi(Tail).
Cleaning it up reveals one thing you're not doing here which is in your spec is checking that X is an atom. Fix by adding atom(X) to the body.
OK, so this takes care of the basic form, but doesn't ensure that the atoms do not repeat. The simplest thing to do would be to split this into two checks, one that checks that each item is well-formed, and one that checks that the list is well-formed. In fact, I would be inclined to use maplist/2 with a predicate that checks a single element. But all you really have to do is something like this:
is_valid([]).
is_valid([X/_|T]) :- is_valid(T), \+ memberchk(X/_, T).
This just says that the empty list is valid, and if the tail is valid, a list is valid if X over something doesn't occur in the tail.
If that's all you wanted, stop reading there. If you want to refactor, this is how I would approach it:
well_formed(X/N) :- atom(X), integer(N), N > 0.
no_repeating_numerators([]).
no_repeating_numerators([X/_|T]) :- no_repeating_numerators(T), \+ memberchk(X/_, T).
is_multi(L) :- maplist(well_formed, L), no_repeating_numerators(L).
Just to complete Daniel's instructive answer (+1 by me), I want to showcase how your task could be solved by means of some library predicates:
is_multi(L) :-
forall(select(E, L, R),
(E = A/N, atom(A), integer(N), N > 0, \+memberchk(A/_, R))).
Related
course(cmput325).
course(cmput175).
course(cmput201).
course(cmput204).
prerequisite(cmput204, cmput325).
prerequisite(cmput175, cmput201).
prerequisite(cmput175, cmput204).
I need to write a new predicate, which is
can_take(+L,?C).
Definition:
L is a given list of courses that a student has already taken. If C is also given,then the predicate should check whether the student has all the required courses for C. If C is a variable, then with backtracking, the predicate should produce one course at a time that the student can take now. Courses can be in any order, but each course should be generated only once, and you should not return any courses that the student has already taken.
Example:
?- findall(C, can_take([cmput175], C), L).
should return
L = [cmput201, cmput204].
Here is my predicate:
can_take(L,C) :- prerequisite(L,C).
can_take([L|List],C) :- prerequisite(L,C),can_take(List,C).
This predicate didn't return the correct result, and it just returned false. I think it is because I didn't determine the condition when L is empty, however, if I tried to add L \== [] in either of them. It still gave me error...what should I do so that this predicate will stop and give me result?
-------update-------
pre(X,C) :- prerequisite(X,C).
pre(X,C) :- prerequisite(X,Y), pre(Y,C).
pre2(C,L) :- findall(L1,pre(L1,C),L).
required(C,L) :- pre2(C,L1),sort(L1,L).
can_take([],_).
can_take(L,C) :- required(C,L).
can_take([L|List],C) :- prerequisite(L,C),can_take(List,C).
Here is my code test:
?- required(cmput325,L).
L = [cmput175, cmput204].
?- required(cmput204,L).
L = [cmput175].
?- can_take([cmput175],X).
X = cmput201 ;
X = cmput204 ;
?- findall(C, can_take([cmput175], C), L).
L = [cmput201, cmput204].
?- can_take([cmput204],cmput325).
false. (this one is OK)
?- can_take([cmput175,cmput204],cmput325).
true ;
false. (this one is OK)
?- can_take([cmput175],cmput204).
true ;
true ;
false.
the last one is not ok because I don't want it to return two true statements...so what I want is just let it stop when either second or last line returns true. For my assignment, I am not allowed to use cut operator !, is there any other way to do it?
(I will assume that you can take a course a second time, even if you have taken it already. That at least are the rules I know of.)
You can take a course, provided you have taken all required courses already.
There is no direct "all" in Prolog. But you can formulate this differently
You can take a course, provided there is no required course that you have not taken already.
can_take(Takens, Next) :-
course(Next),
iwhen( ground(Takens),
\+ ( prerequisite(Required, Next), \+ member(Required, Takens) ) ).
This uses iwhen/2 to guard against cases where Takens is not fully instantiated.
Note that there is a slight difference to your examples:
?- findall(C, can_take([cmput175], C), L).
L = [cmput175, cmput201, cmput204].
% ^^^^^^^^
Disclaimer
Your problem is inherently non-monotonic: By adding further facts for requirements you are reducing the number of possible courses you may take. As a beginner, rather stick to problems that are monotonic in nature. It is on this side where Prolog really excels.
I've written a small Prolog program that's supposed to check a list and see whether the head Ha is greater than K, if it is, it is supposed to append it to a list R and after checking the whole list give back R which then would consist of bigger than K integers.
This code returns R = [].
teilliste_grK([],_,_).
teilliste_grK([Ha|Ta], K, R) :-
Ha =< K,
teilliste_grK(Ta,K,R).
teilliste_grK([Ha|Ta], K, R) :-
Ha > K,
append(R, [Ha], C),
teilliste_grK(Ta, K, C).
Any help?
you should write out how do you want to call this predicate with some sample data, and what you're expecting to get back from it. this is important. :)
okay, I'll do it: teilliste_grK([1,4,2,5,3,6],3,X) should succeed, instantiating X to [4,5,6], correct? Now try to see which of the clauses does it match with.
So it matches with the second, 1 is indeed =< 3, and the last line says, continue without the head element (that was smaller than the given K), and whatever R we get from there, is our R as well – R is R after all.
Good. So when we come to 4 next, what happens? The 2nd clause matches but is then rejected with 4 =< 2. Good. On to the third clause.
Again it matches, and the inequality holds, but then you do something strange. You first say that C is one element longer than R, and that C you get from the shorter list - the tail Ta of your input. Whatever you set your R in the final clause (the first one), this just can't be.
You want your C to be shorter than R, which is to start with the same head Ha which has just passed the test, so the arguments just need to be put in a different order:
append([Ha], C, R),
(you can write this shorter and simpler though, without any call to append – what is it?).
Now what about that final (3rd, i.e. []) clause? If you call teilliste_grK([],3,X), what should X be?
I have two predicates in Prolog, the first one does return a correct dot product of two lists(vectors w/e) ... the second is when you take a list times a list of lists(matrix) which will return a list. The second one fails when I try to pass anything such as ([1,2],[[3,4],[5,6],[7,8]], X). Anyone well versed in Prolog see my mistake? I am kinda stuck since tracing and prolog itself just returns a fail all the time.
getDotProd([],[],0.0).
getDotProd([H1|T1],[H2|T2], N):-
getDotProd(T1,T2,N1),
N is N1 + (H1 * H2).
vecTimesMatrix(_,[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
N is getDotProd(List, MH, _),
vecTimesMatrix(List, Mtail, N).
Updated Code thus far now:
getDotProd([],[],0.0).
getDotProd([H1|T1],[H2|T2], N):-
getDotProd(T1,T2,N1),
N is N1 + (H1 * H2).
vecTimesMatrix([],[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
getDotProd(List, MH, N),
vecTimesMatrix(List, Mtail, N).
Your remaining problem is in your vecTimesMatrix predicate:
vecTimesMatrix([],[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
getDotProd(List, MH, N),
vecTimesMatrix(List, Mtail, N).
Issues:
In the second clause, the first argument is given as [List] which would imply a list of a single element (List). Subsequent calls to getDotProd and vecTimesMatrix in the clause indicate that this should simply be List.
In the second clause, the third argument is shown simply as a list of one argument: [N]. So the third argument never "builds" a list. Additionally, the recursive call to vecTimesMatrix has N as its third argument, and that argument had already been instantiated by the prior query to getDotProd as the dot product of the vector List and the vectory MH. Logically, the recursive call should be saying that the vector product of List with Mtail is the tail of the final product.
The base case assumes that the first argument reduces to [], but this is not so. List always remains as-is throughout the recursive process. So instead of [] you should have _ (it will keep its value, but you don't care about it in the base case).
The base case has as a second argument [[]], but that's not the correct form for an empty list. That's actually a list consisting of one element, that element being the empty list. In reality, even though the second argument is a "list of lists", the empty list is still [].
Putting it all together (and renaming predicates per de facto conventions using underscores rather than camel case):
get_dot_prod([], [], 0.0). % Dot product of empty vectors is 0.0
% (Dot prod of vectors of unequal length
% is not defined and will fail)
get_dot_prod([H1|T1], [H2|T2], N) :- % N is dot product of [H1|T1] [H2|T2] if...
get_dot_prod(T1, T2, N1), % N1 is dot product of T1 T2, and
N is N1 + (H1 * H2). % N is N1 + (H1*H2) [evaluated]
vec_times_matrix(_, [], []). % Product of any vector with
% empty matrix is empty
vec_times_matrix(List, [MH|Mtail], [N|Ntail]):-
% [N|Ntail] is List x [MH|Mtail] if...
get_dot_prod(List, MH, N), % N is dot product of List and MH, and
vec_times_matrix(List, Mtail, Ntail). % Ntail is List x Mtail
This will yield:
| ?- vec_times_matrix([1,2],[[1,0],[0,1]], M).
M = [1.0,2.0] ? a
no
| ?- vec_times_matrix([1,2],[[1,0],[0,1],[1,1]], M).
M = [1.0,2.0,3.0] ? a
(1 ms) no
I added the comments in the code above to illustrate, in a simple way, how to think of the prolog predicate logic, which aids in defining them. As was pointed out already, the prolog "predicate" doesn't act as a "function". It describes a logical relation between entities which will either succeed or fail.
Once you learn to think how prolog thinks (relationally), you'll find it more enjoyable. :)
There are several problems in your code. First, you define both getDotProd/4 and getDotProd/3 predicates. The first one is a typo. I.e. you base case for the getDotProd/3 predicate have a duplicated argument and it should be:
getDotProd([], [], 0).
Second, in the second predicate, vecTimesMatrix/3, you have a goal, a call to the built-in predicate is/2, that will cause an exception:
N is getDotProd(List, MH, _)
You cannot define your own functions on standard Prolog. You need to replace that goal with:
getDotProd(List, MH, N)
There are other problems but this should help you progress.
Ho do I square numbers in a list in prolog?
The list can contain numbers, atoms and lists.
for example: [a,b,2,3,4,[3],[c,d,9]] and the answer should be [a,b,4,9,16,[3],[c,d,9]].
As we see in the answer it should be a shallow squaring of the values in the list.
2->4
3->9
4->16
What I have tried so far,
square([],X).
square([A|B],X):-number(A), A is A*A, square(B,X).
X will contain squared values. Base case is when empty list is received. I check if head (A) is a number then I go ahead square the number and change A to A * A. Then go ahead and call the square function for remaining part B.
Please suggest where I am doing wrong.
EDIT: Correct answer as follows. By aBathologist. Please read his comment for detailed explanation.
squared_members([], []).
squared_members([L|Ls], [SqrdL|SqrdLs]) :-
number(L),
SqrdL is L * L,
squared_members(Ls, SqrdLs).
squared_members([L|Ls], [L|SqrdLs]) :-
\+number(L),
squared_members(Ls, SqrdLs).
And
squared_members([], []).
squared_members([L|Ls], [M|Ms]) :-
( number(L)
-> M is L * L, squared_members(Ls, Ms)
; M = L, squared_members(Ls, Ms)
).
We're defining a predicate which describes the relationship between one list, A, and another list, B: B should have all the same elements as A, except that any number in A should be squared in B.
Where you've gone wrong:
Your ground condition, square([],X), says that when A is empty, then B is anything (so, for instance, even something like square([], 15) is true). But this doesn't capture the meaning we're after, since the second argument should be a list with the same number of members as the first. That is, when the first list is empty then the second list should be empty.
The same problem occurs with your recursive rule, since, at each iteration, an undetermined variable is passed along, and there is never anything said about the relationship between the first list and the second.
This rule will only succeed if the first element of alist is a number. In the case where the first element is, e.g., a (like in your example), number(a) will be false. Since there are no additional rules for the predicate, it will simply be false unless every member of the first list is a number.
Variables in Prolog must always have the same, consistent value throughout the context in which they appear. They function like variables in arithmetic formula. The formula a + b - b = a is true for any values of a and b but *only if a and b are each assigned one, consistent value throughout the equation. The same is true in Prolog statements of the form <variable> is <expression>. What you've written says a = a * a which cannot be the case.
*What you're definition says is, roughly, this: The list B is a squared version of the list A if A is an empty list and B is anything OR if the first element of A is a number, and that number is equal to itself squared, and B is a squared version of the rest of A.
Here's one possible solution:
squared_members([], []).
squared_members([L|Ls], [SqrdL|SqrdLs]) :-
number(L),
SqrdL is L * L,
squared_members(Ls, SqrdLs).
squared_members([L|Ls], [L|SqrdLs]) :-
\+number(L),
squared_members(Ls, SqrdLs).
Notice that this definition is able to establish a meaningful relationship between the two lists by having them either share variables, or contain elements related by a chain of relations between variables (i.e., SqrdL is related to L by virtue of being L * L). This definition has one more clause then yours, which enables it to take account of the members of a list which are not numbers: those are added to the second list unaltered.
An alternative definition, using If-Then-Else notation for cleaner expression, would be the following:
squared_members([], []).
squared_members([L|Ls], [M|Ms]) :-
( number(L)
-> M is L * L, squared_members(Ls, Ms)
; M = L, squared_members(Ls, Ms)
).
question is:
when we key in mem([1,2,3,4,5]).
we will get the output as bellow:
odd=3
even=2
my coding is like that but cannot run. can help me check where is my mistake??
mem(X,[X|L]).
mem(X,[element|L]):-
mem([X,L]).
count([],L,L).
count([X|H],L1,L2):-
write(even),
X%2=0,nl,
write(odd),
X%2>=1,nl,
count([H],[X|L1],L2).
thanks for your helping.
The procedures you have written do two different things and don't actually belong together. mem/2 is equivalent to the usually builtin member/2 except that your definition contains an error: in the second clause element is an atom instead of a variable so it will not match other elements of the list. The usual definition is
member(X, [X|_]).
member(X, [_|L]) :- member(X, L).
Note that this definition will not only test if a term is an element of a list but can even be use to generate a list.
What exactly are you trying to do in count/3: split the list into two lists, one containing odd and the other containing even; or count the number of odd and even elements? The splitting could be done with something like:
count([], [], []).
count([X|L], O, E) :- X rem 2 =/= 0, count(L, [X|O], E).
count([X|L], O, E) :- X rem 2 =:= 0, count(L, O, [X|E]).
Note that =/= /2 and =:= / 2 force evaluation of arguments as arithmetic expressions while = /2 attempts to unify its arguments.
Counting the number of odds and evens can be done in a similar fashion, and is left as an exercise for the reader. :-)