Prolog Sorting approach - prolog

Hı guys.I have a problem about prolog example.I have written following fact and rule to my database file but my database file doesn^t work while I compile it.Do you have any idea?
The error that I get is singleton variables
ordered([B]).
ordered(H|[H2|T]):-
H=<H2,
ordered([H2|T]).

The "singleton variable" warning is warning you that in the clause
ordered([B]).
the variable B only appears once, i.e., is not used to bind values between different calls, i.e., can serve no purpose. This is usually the result of a typo or from forgetting to make an intended change, so the top-level issues a warning. The usual way to use singleton variables for the easy of reading without triggering a warning is to prefix it with an underscore: _B.
But this is unrelated to the real problem with your code. A singleton variable will not cause any problems, it's just a matter of style or a way of warning of a typographical error. As #jol76 notes, the real problem with your code is that H|[H2|T] is not the correct notation for matching a list's first to elements and it's tail. The notation is [H,H2|T]. I think of the notation as [a,n,y,' ',n,u,m,b,e,r,' ',o,f,' ',e,l,e,m,e,n,t,s,' ',a,n,d|TheRest].

Most recursive rules have a couple of special/base cases and a general case.
You have two base cases:
ordered( [] ) . % the empty list is ordered
ordered( [_] ) . % a list consisting of a single item is ordered.
And the general case:
ordered( [A,B|C] ) :- % a list of two or more items is ordered, IF ...
A =< B , % - the first item is less than or equal to the second
ordered( [B|C] ). % - if the remainder of the list (less its head) is also ordered.
You might note that this won't actually sort the list for you: it will just indicate (via success or failure) whether or not the list is ordered.

Related

Where is the source of my time out error (swi-prolog)?

I am having difficulty finding the source of my time-out error, when I run the following code.
crossword(H1,H2,V3,V1,V2) :- word(H1), word(H2), word(V3), word(V1), word(V2), word(H2) \= word(V2), string_length(H1,3), string_length(H2,7), string_length(V3,6), string_length(V1,4), string_length(V2,5).
Preceding this section I have a series of words, such as word("coding"), word("is"), word("fun"), ...
I have a lot of words, could this be the problem? Or is it how I have defined my rules?
The chain of five independent unconstrained selections in a row word(H1), word(H2), word(V3), word(V1), word(V2) means there will be made n5 choices overall, if you have n words defined in your knowledge base.
Instead, move the constraining calls up in the predicate's body, for the wrong choices to fail as early as possible, preventing the futile nested selections from being performed at all:
crossword(H1,H2,V3,V1,V2) :-
word(H1), string_length(H1,3),
word(H2), string_length(H2,7),
word(V3), string_length(V3,6),
word(V1), ... .

Graph implementation (does graph include all vertices?)

Trying to implement following predicate, which takes on input
list of lists - one list = one tested graph T (as edges)
graph G itself (as edges)
and tests whether T includes all of the vertices of G. If it does(true) should return it. Basically it's list filtering.
What I have so far is:
covb([],G).
covb([H|R],G) :-
isItCov(G,H), covb(R,G).
isItCov([],H).
isItCov([V-W|R],H) :-
vertex(V,H),
vertex(W,H),
isItCov(R,H).
vertex(V,[V-_|G]).
vertex(V,[_-V|G]).
vertex(V,[_|G]):- vertex(V,G).
For covb([[a-c,c-b,c-d]],[a-b,a-c,a-d,c-d,b-c]) works fine(true). For covb([[a-c]],[a-b,a-c,a-d,c-d,b-c]) works fine too (false). I got an issue while I call it with multiple lists like covb([[a-c,c-b,c-d],[a-c]],[a-b,a-c,a-d,c-d,b-c]). which should work only for the first one.
I actually got two questions -
Why does it work for one list only?
I want to return items of lists of lists which passed the condition and returned true (that's the filtering part). How should I do that?
First of all, your program has a number of singleton variable warnings. Do not ignore singleton variable warnings. They can hide real bugs. Also, since more experienced Prolog users here know that programs with singleton variable warnings are not even worth running, they will (a) just see the warnings and decide that they are no longer interested in trying to help you, or (b) fix the warnings on their side, but then by definition they will be working on a program that is no longer the program you posted!
Now for your questions.
Why does it work for one list only?
It's really not clear what you are asking here, or just above with "covb([[a-c,c-b,c-d],[a-c]],[a-b,a-c,a-d,c-d,b-c]). which should work only for the first one."
This query does fail:
?- covb([[a-c,c-b,c-d],[a-c]],[a-b,a-c,a-d,c-d,b-c]).
false.
This comes down to testing each of the two lists:
?- isItCov([a-b,a-c,a-d,c-d,b-c], [a-c,c-b,c-d]).
true .
?- isItCov([a-b,a-c,a-d,c-d,b-c], [a-c]).
false.
The first list does cover the graph, while the second doesn't. Overall, your definition of covb/2 is written to succeed if all lists cover the graph. This is not the case, so your covb/2 query fails.
Was this what you wanted to know?
I want to return items of lists of lists which passed the condition and returned true (that's the filtering part). How should I do that?
You could see if your Prolog's documentation has something for the word "filter". On SWI-Prolog you can do this:
?- apropos(filter).
true.
This will point you to the include/3 predicate, which seems to do what you want:
?- include(isItCov([a-b,a-c,a-d,c-d,b-c]), [[a-c,c-b,c-d],[a-c]], Covers).
Covers = [[a-c, c-b, c-d]].
If you want to write a filter predicate for your concrete application, it might look something like this:
graph_covers(_Graph, [], []).
graph_covers(Graph, [Nodes|NodesRest], Covers) :-
( isItCov(Graph, Nodes)
-> Covers = [Nodes|CoversRest]
; Covers = CoversRest ),
graph_covers(Graph, NodesRest, CoversRest).
This is similar to your predicate, it just adds an extra argument to collect those node lists for which isItCov/2 succeeded. If it did not succeed, it continues with a list not containing that current node list.
?- graph_covers([a-b,a-c,a-d,c-d,b-c], [[a-c,c-b,c-d],[a-c]], Covers).
Covers = [[a-c, c-b, c-d]] ;
false.

Prolog replace element in a list with another list

*Hi, i am trying to replace an element from a list with another list and im stuck when turbo prolog gives me syntax error at the case where if C=A-> put in result list(L1) the list that replace the element.
domains
list=integer*
element=i(integer);l(list)
lista=element*
predicates
repl(list,integer,list,lista)
clauses
repl([],A,B,[]):-!.
repl([C|L],A,B,**[l(|L1])**:- C=A,repl(L,A,B,L1),!.
repl([C|L],A,B,[i(C)|L1]):- repl(L,A,B,L1),!.
Thanks for help, problem solved (using dasblinkenlight code)
Try this:
concat([],L,L).
concat([H|T],L,[H|Res]) :- concat(T,L,Res).
repl([],_,_,[]).
repl([Val|T],Val,Repl,Res) :- repl(T,Val,Repl,Temp), concat(Repl,Temp,Res).
repl([H|T],Val,Repl,[H|Res]) :- repl(T,Val,Repl,Res).
I do not know if it is going to work in Turbo Prolog, but it works fine in SWI, and it does not use any built-in predicates.
concat/3 pair of rules concatenates lists in positions 1 and 2 into a resultant list in position 3.
The first repl deals with the empty list coming in; it is identical to yours, except it replaces singleton variables with underscores (a highly recommended practice)
The second rule deals with the situation where the value Val being replaced is at the head of the list; it replaces the values in the tail, and concatenates the replacement list Repl with the result of the replacement Res.
The last rule deals with the situation when the head value does not match the Val. It recurses down one level, and prepends the head of the initial list to the head of the result of the replacement.
As a side note, the cut operator ! is rarely necessary. In case of this problem, you can definitely do without it.

Error in PROLOG code

I am new to prolog.
I want my code in PROLOG to produce the expected output given below. Can some one please tell me where I am going wrong.
The code is basically to remove duplicates and produce o/p in required format.
remove_dups([],_L2,_L2).
remove_dups([A|B],L2,L3) :-
functor(A,Pr,Ar),(member(level(Pr,Ar,1) ,L2) -> remove_dups(B,L2,L2); append([level(Pr,Ar,1)],L2,L3),remove_dups(B,L3,L3)).
expected output:
?- remove_dups([a,b,a],[],L).
L = [level(a,0,1),level(b,0,1)].
For starters I would have preferred to separate the two steps: removal of duplicates and presentation of the levels.
remove_dups([],[]).
remove_dups([X|Xs],Ys) :- member(X,Xs), !, remove_dups(Xs,Ys).
remove_dups([X|Xs],[X|Ys]) :- remove_dups(Xs,Ys).
levels([],[]).
levels([X|Xs],[level(N,A,1)|Ys]):- functor(X,N,A), levels(Xs,Ys).
go(L,R):- remove_dups(L,RL), levels(RL,R).
I have to admit that the constant 1 in the level tripples puzzles me. Are you sure that it should not be somehow more meaningful?
I have also assumed that the order of the list elements is of no importance: remove_dups removes all occurrences of a duplicated element except for the last one. If you would like to keep the first occurrence, remove_dups has to be modified.

Prolog: append a list to itself

suppose I have a list ListSum, and I want to append a new list to ListSum recursively, like
appList(ListSum):-
%%generate a list: ListTemp,
append(ListTemp,ListSum,ListSum),
appList(ListSum).
but append(ListTemp,ListSum,ListSum) didn't work in the way i wanted.
Can anyone help me out?
Cheers
You have to understand the concept of unification (or actually "matching" as implemented in Prolog). You can't bind two or more values to the same variable. Variables in Prolog once matched persisted its value until the final goal achieved, or fails somewhere. After that, if there're more possibilities then the variable is re-instantiated with another value and so on.
For example, if I query appList([]), then the append would be tested to match as:
append(ListTemp,[],[])
If ListTemp isn't empty list, this clause would fail because the semantic of append is "append the first argument with second, both are lists, resulting in the third". The recursive call to appList(ListSum) would be called as appList([]) since ListSum is matched with [] previously, resulting in infinite recursion (fortunately, if ListTemp isn't [], this won't be reached).
You must have two arguments in the clause, where one is the original list, and the other is the resulting list. The first two argument of append is then ListSum and ListTemp (depends on the append order you want), while the third is the resulting list. Done, no recursion required.
here's a non-recursive solution, not sure why you even need recursion:
appself(L,X) :- append(L,L,X).

Resources