How to use the predicate "assert" in a predicate - prolog

I have a problem I want a code Prolog for that I will generate new predicate with the predicate "assert" but I want to use the result of my predicate .
i have a predicate that counts the number of element of a list here is it
and I have to make a new predicate that will add me a new predicate using the predicate "assert" in my knowledge base calling to the predicate "creat_nbStation" who will use the 2 "assert" and "compte" for exemple i have creat_nbStation(L) and L is a Liste it will add me in my knowledge base a new predicate it's nb_Station(L,25) using assert predicate .
thank you for the help.
this is my predicate for counting the number of elements of a list and it worka perfectly
compte([],0).
compte([_|R],N) :- compte(R,N1), N is N1+1, N>0.

It is quite difficult to figure out what exactly you are looking for, but I must say it does look very much like homework assignment. Is this what you are looking for?
create_nbStation(L) :- compte(L, N), assert(nbStation(L, N)).

Related

How to find the last item in the third list, which is collected from the first and second list?

intersection([],L1,L2,L3).
intersection([H|T],L2,L3,[H|L4]):-member(H,L2),intersection(T,L3,L3,L4).
member(H,[H|T]).
member(X,[H|T]):-member(X,T).
This code makes the third list from the first and second list.
last([U],U).
last([_|L3],U) :- last(L3,U).
This piece of code looks for the last item in the list.
My problem is that I can’t figure out how to make these two pieces of code fit into one. That is, the program should find duplicate elements in the first and second list and display them in the third, and from the third list, display the last element multiplied by 3.
The main problem is intersection/4. I assume you wanted to write a deterministic predicate intersection/3 the first two arguments of which are fully instantiated at call time and the last argument of which is an output argument. By deterministic, I mean that intersection/3 should succeed exactly once without leftover choice points. The SWI-Prolog documentation contains a useful overview of determinism and mode declarations (although it does not enforce them).
It is useful to begin by writing a declarative specification of the predicate following the inductive definition of lists:
The intersection of [] and Ys is [].
The intersection of [A|Xs] and Ys is A prepended to the intersection of Xs and Ys if A is a member of Ys.
The intersection of [A|Xs] and Ys is the intersection of Xs and Ys if A is not a member of Ys.
The simplest translation of this specification into standard Prolog is:
intersection([],_,[]).
intersection([A|Xs],Ys,[A|Zs]) :-
member(A,Ys),
intersection(Xs,Ys,Zs).
intersection([A|Xs],Ys,Zs) :-
\+ member(A,Ys),
intersection(Xs,Zs).
If the first call to member/2 succeeds the second should fail. In order to avoid backtracking, unifying the current goal with the head of the second clause, and performing a redundant call to member/2, we place a cut after the occurrence of member/2 in the second clause.
intersection([],_,[]).
intersection([A|Xs],Ys,[A|Zs]) :-
member(A,Ys),
!,
intersection(Xs,Ys,Zs).
intersection([_|Xs],Ys,Zs) :-
intersection(Xs,Ys).
If the current goal unifies with the head of the first clause, it will not unify with the heads of later clauses. In order to prevent spurious backtracking, we place a cut in the (empty) body of the first clause. Whether this cut is necessary depends on your choice of Prolog implementation.
intersection([],_,[]) :-
!.
intersection([A|Xs],Ys,[A|Zs]) :-
member(A,Ys),
!,
intersection(Xs,Ys,Zs).
intersection([_|Xs],Ys,Zs) :-
intersection(Xs,Ys).
We are only interested in checking membership in the second list. Thus, we can replace the occurrence of member/2 with the semideterministic predicate memberchk/2. Here, semideterministic means that memberchk/2 succeeds or fails exactly once without leftover choice points.
intersection([],_,[]).
!.
intersection([A|Xs],Ys,[A|Zs]) :-
memberchk(A,Ys),
!,
intersection(Xs,Ys,Zs).
intersection([_|Xs],Ys,Zs) :-
intersection(Xs,Ys).
This implementation of intersection/3 is nearly identical to the implementation found in the SWI-Prolog library lists.pl. You can combine this predicate with an implementation of last/2 in order to complete your program. For example:
last_duplicate_tripled(Xs,Ys,N) :-
intersection(Xs,Ys,Zs),
last(Zs,M),
N is M * 3.
From here, I recommend doing the following:
Implement intersection/3 using metalogical predicates like findall/3.
Read #false's answer to this question.
Read #repeat's answer to this question.
They are doing something much more interesting and sophisticated than I attempted in this answer.

Joining predicates in prolog

I'm doing an exercise in Prolog using SWI-Prolog, to take a nested list and convert it into a list of elements and then make the sum of the elements, I made two separate predicates which make me both functionalities:
my_flatten(X,[X])->Transform a list, possibly holding lists as elements into a 'flat' list by replacing each list with its elements (recursively).
my_flatten(X,[X]) :- \+ is_list(X).
my_flatten([],[]).
my_flatten([X|Xs],Zs) :-
my_flatten(X,Y), my_flatten(Xs,Ys), append(Y,Ys,Zs).
addList-> Adds all the elements of a list and returns their sum
addList([],0).
addList([X|Xs],N):-
addList(Xs,N0),N is X+N0.
The problem itself is that I'm new programming in Prolog and I don't know how join both predicates in the same predicate, so that the list returned by my_flattern be used by the predicate addList. Maybe it's a bit foolish question, but I've been stuck on it for days. I need some help to clarify this question for other problems
To construct a new predicate which does both, simply call both my_flatten and addList, with a shared variable:
addListFlattened(L, Sum) :-
my_flatten(L, L2),
addList(L2, Sum).
addListFlattened is a new predicate (you can change the name), which reuses addList.

binary predicate to square list and sublists in Prolog

I am new to prolog and was trying to create a binary predicate which will give
a list in which all numbers are squared, including those in sublists.
e.g.
?-dcountSublists([a,[[3]],b,4,c(5),4],C).
C=[a,[[9]],b,c(5),16]
Can anyone guide me how i can do this.
Thank You. Answer with a snippet is appreciated
This is easily achieved using recursion in Prolog. Remember that everything in Prolog is either a variable, or a term (atoms are just 0-arity terms), so a term like the following:
[a,[[3]],b,4,c(5),4]
...is easily deconstructed (also note that the list syntax [..] is sugar for the binary predicate ./2). Prolog offers a range of predicates to test for particular types of terms as well, such as numbers, strings, or compound terms (such as compound/1).
To build the predicate you're after, I recommend writing it using several predicates like this:
dcountSublists(In, Out) :-
% analyze type of In
% based on type, either:
% 1. split term into subterms for recursive processing
% 2. term cannot be split; either replace it, or pass it through
Here's an example to get you started which does the hard bit. The following recognizes compound terms and breaks them apart with the term de/constructor =../2:
dcountSublists(In, Out) :-
% test if In has type compound term
compound(In),
% cut to exclude backtracking to other cases below this predicate
!,
% deconstruct In into functor and an argument list
In =.. [Func|Args],
% apply dcountSublists/2 to every argument, building new args
maplist(dcountSublists, Args, NewArgs),
% re-construct In using the new arguments
Out =.. [Func|NewArgs].
dcountSublists(In, Out) :-
% test if In has type atom
atom(In), !,
% pass it through
Out = In.
Testing:
?- dcountSublists([a,[[e]],b,a,c(s),a], L).
L = [a, [[e]], b, a, c(s), a].
Note that this fails if the input term has numbers, because it doesn't have a predicate to recognize and deal with them. I'll leave this up to you.
Good luck!
SWI-Prolog has the predicate maplist/[2-5] which allows you to map a predicate over some lists.
Using that, you only have to make a predicate that will square a number or the numbers in a list and leave everything else the same. The predicates number/1, is_list/1 are true if their argument is a number or a list.
Therefore:
square(N,NN):-
integer(N),
NN is N*N.
square(L,LL):-
is_list(L),
dcountSublists(square,L,LL).
square(Other,Other):-
\+ number(Other),
\+ is_list(Other).
dcountSublists(L,LSquared):-
maplist(square,L,LSquared).
with the negation in the final predicate we avoid multiple (wrong) solutions:
for example dcountSublists([2],X) would return X=[4] and X=[2] otherwise.
This could be avoided if we used an if-then-else structure for square or once/1 to call square/2.
If this is homework maybe you should not use maplist since (probably) the aim of the exercise is to learn how to build a recursive function; in any case, I would suggest to try and write an equivalent predicate without maplist.

Problem with accumulators in prolog

While learning Prolog, I'm trying to solve the following problem, using accumulators:
Write a predicate addone2/ whose first argument is a list of integers, and whose second argument is the list of integers obtained by adding 1 to each integer in the first list. For example, the query
addone([1,2,7,2],X).
should give
X = [2,3,8,3].
I created the following code:
addone([], _).
addone([E|Tail], [R|Rs]) :-
NewE is E+1,
append([R|Rs], [NewE], NewRs),
addone(Tail, NewRs).
But it's not working. Can someone tell me why? So, how do I use accumulators in Prolog?
Thanks!
anthares is correct in that you have to refine your base case. However, you are also making things very inefficiently with your append calls. In Prolog, it takes some time to get used to the power of unification, but for example, in this case it helps you to immediately set up your result list. Try the following:
addone([E|Tail], [E1|Rs]) :-
E1 is E+1,
addone(Tail, Rs).
That's really all there is to it. By immediately placing E1 in your second argument's pattern, you have already created the first element of your result list. The remaining elements Rs will be created during the recursion. A very typical Prolog pattern.
The bottom of your recursion should be addone([],[]). in order NewRs to be connected with the []

Pairing Two Lists

Hey guys, a few simple prolog questions that I'm hoping you can help me on. Basically, I am trying to write a function that takes input as two lists, and an integer. From there, the function will try to find an x in the first list and a y in the second list such that x + y is equal to the input integer.
So far I am thinking to just recurse down by doing something such as follows:
sum([H1|T1], [H2|T2], Value) :-
NewVal is H1+H2
% Check for equality?
sum(List1, T2, Value)
sum(T1, List2, Value).
So, a few questions regarding this method.
1) How do I refer the the "whole" list after I've passed it in as H1|T1? In the example I just named them List1 and List2 for reading ease.
2) I can check for equality, but how do I "stop" searching and force output?
You need a disjunction, not a conjunction: EITHER h1+h2 is ok, OR there is a solution without h1, OR there is a solution without h2.
There are two syntaxes in prolog for disjunction. You can use a semicolon:
sum([H1|T1], [H2|T2], Value) :- Value is H1+H2 ; sum([H1|T1], T2, Value) ; sum(T1, [H2|T2], Value).
Or you can use separate clauses:
sum([H1|_], [H2|_], Value) :- Value is H1+H2.
sum([H1|T1], [_|T2], Value) :- sum([H1|T1], T2, Value).
sum([_|T1], [H2|T2], Value) :- sum(T1, [H2|T2], Value).
IIRC, I think you should be able to pass the whole list as a parameter using [H1|T1].
Most likely you would want to use the Prolog cut, which stops searching for solutions.
1) Kaleb is right, to do this, just reconstruct the list as the head cons with the tail.
2) Jerome is right, but here's another way of putting it...
Your question "How do I make it stop?" actually hints at a missing part of your predicate. You currently have a recursive predicate with no base case - the recursion has no way of being able to stop. Well I guess in this case it will get to the end of one of the lists, but since this will then be the empty list it will then fail when being unified with the term [H|T] as there is no head item.
When writing a recursive predicate that is looking for a particular element of a list it is common to make the base contain the constraints which define the solution. You can see this in Jerome's solution. This results in a predicate that succeeds once it has found a solution and doesn't continue to process the list afterwards. It will however continue on after this point if you tell it to backtrack and look for more solutions. If you don't care about these further solutions, then you can use the cut to discard them.

Resources