persian language processing prolog - prolog

This is my prolog code, which gave me the following error:
ERROR: Out of global stack
hasA(S,A):- name(S,L1),
compar(L1,A).
compar([H1,H2|T1],T1):- H1 == 1575, H2 == 1740.
neda(H,A):- hasA(H,Z1),
append(A,[1575,1740],A),
state(Z1,Z2),
append(A,Z2,A).
state([H|T],T):- H == 32.
state(A,A).
What is wrong? Can you help me with it?

Assuming that you call neda(H,A) with A being a free variable you end up calling append(A,[1575,1740],A) with A being a free variable as well. However, traditionally, append is implemented as
append([],Ys,Ys).
append([X|Xs],Ys,[X|Zs]) :- append(Xs,Ys,Zs).
Unification of append(A,[1575,1740],A) with append([],Ys,Ys) fails since it requires A to be [], on the one hand, and [1575,1740], on the other hand. Hence, Prolog tries to unify append(A,[1575,1740],A) with append([X|Xs],Ys,[X|Zs]) and succeeds with {A/[X|Xs], Ys/[1575,1740], Xs/Zs} which leads to the call append(Xs,[1575,1740],Xs) and the process repeats, i.e., Prolog enters an infinite recursion and ultimately runs out of stack.
If I guess your intention correctly, you first would like to append [1575,1740] to A and then to append Z2. This would mean that you need to introduce two new variables, say A1 and A2, to record the state of A after each appending step:
neda(H,A):- hasA(H,Z1),
append(A,[1575,1740],A1),
state(Z1,Z2),
append(A1,Z2,A2).
Beware, however, that with A being a free variable on backtracking this code will generate lists of increasing length; is this what you want?

Related

Prolog list length comparison return true/false

I am trying to write a function longer(S1,S2) which should be true if S1 is longer than S2, otherwise false. What I have so far is the following:
longer(A,nil).
longer(nil,B) :- false.
longer([A,AS],[B,BS]) :- longer(AS,BS).
But for some reason I cannot seem to get it to parse correctly when I provide for instance the input: longer([1,2],[1]).
But when I run the above through swi-prolog it return false.
Another example is running the: longer([1],nil) which also return false, even though it should be true by matching with list(cons(A,As)) where As = nil, finally matching the end clause.
What am I missing? Can someone point me in the right direction here, as I cannot see how this is not evaluating to true.
Edit: it should be noted that I am still fairly new to prolog at this point.
Update I have had some misunderstanding in relation to what is common prolog semantic. Including trying to force the program to yield a false value (probably being steered by my understanding of non-declarative language semantics). I have updated my answer with the inputs from #tiffi.
That is a solution that is pretty close to the thinking behind what you have come up with:
longer([_|_],[]).
longer([_|As], [_|Bs]):- longer(As,Bs).
Your idea with regard to the first clause (before your edit) could be expressed like this:
longer(A,[]):- is_list(A). %is_list/1 is inbuilt
However, that doesn't give you the right result, since the empty list is also a list. Thus you need to make sure that the first argument is a non-empty list.

Local negation in prolog

I'm trying to write some rules that will tell about the number of blocks in a stack (not the data structure, just a location). The rule stack return true for every block in a stack.
Specifically, is zero/one/two the number of blocks in X?
num_blocks(X,zero) :- \+stack(X,_).
num_blocks(X,one) :- stack(X,A),\+stack(X,B),A\=B.
So, num_blocks(X,zero) works as intended, but the other one doesn't. My thought process is that if we can find one block(A) and we cannot find a second unique block(B), then there is only one block in X stack. However, I still keep getting false back.
What you intended (as per your description) is to check whether there is no other block in the stack. But you are just applying not to stack(X,B) which means there is no block in the stack X, and it \+stack(X,B) succeded it would leave B as is (uninstantiated).
I think what you want for the second clause is the negation of the conjunction of stack(X,B) and A\=B, that is:
num_blocks(X,one) :-
stack(X,A),
\+ ( stack(X,B), A\=B ).

Concatenate two atoms in prolog without using atom_concat

I want to write prolog that can essentially do what this is doing
atom_concat('3',' =',Answer).
Answer = '3 ='.
But I do not want to use the atom_concat function (or any built in predicates). I would also like the answer to have no quotation marks in it.
I have tried implementing a method that operates the same as the append method, which I have called merge.
merge([],Xs,Xs).
merge([X|Xs],Ys,[X|Zs]):-
merge(Xs,Ys,Zs).
But when I write this into my db.pl file I get false when running it.
?- [db].
true.
?- merge('3',' =',Answer).
false.
You can't mutate immutable values. You could use string_concat/3 to create a merger of two string atoms. By putting 'Variable' you are signalling Prolog that you want an ATOM called Variable. So numerical 3 and string atom '3' are not the same. What basically happens is you have two >immutables<, so a third has to be made that is an amalgamation of the other two.
atom_concat
string_concat
'merge' is also a deprecated method, just to clear up any confusion:
merge
The program you want:
The query
?- trace, (concat_strings(['Hello ','Hello ','Hello '],[world1,world2,world3],Output)).
The code
concat_strings([H1|T1],[H2|T2],[H3|T3]) :-
string_concat(H1, H2, H3),
concat_strings(T1,T2,T3).
concat_strings([],[],[]).
It takes the the first word of both lists, makes a new immutable atom from the 2 through string_concat and puts it in H3, which is then put onto the head of the list when the call ends. We have the end condition concat_strings([],[],[]) and the first 2 are the lists YOU pass, the third means T3 eventually unifies as T3 = [], which is also the atom to show Prolog the end of a list has been reached. Prolog then starts stepping back, adds [] as the tail and then adds the new atoms to the new list as it works its way back to your call.
OPINION:
My favorite resource for Prolog basics explained: http://www.learnprolognow.org/lpnpage.php?pageid=top
built_equality_structure(Id,Value,Id = Value).
If you call it with
?- built_equality_structure(a,3,X).
you will get the result
X = (a=3)
where the Prolog system only add parentheses for readability.

How do i count words in prolog?

I try to count words in a string in prolog. Like "No, I am definitely not a pie!"
To give me the number 7 and next example "w0w such t3xt... to give number 5.
I had thougt about subtract that are a library function and only get back white-characters. But the problem then is No way will give back 5 and not two words.
I thought about
filter([],L).
filter([X,Y|XS],[Y|XS]):- X = ' ',Y = ' ',L = [Y|XS], filter([Y|XS],L).
filter([X|XS],L):- filter(Xs,L).
That will remove white spaces and get back No way but it dosent work anbody have a tip.
Strings in Prolog are lists of character codes not of atoms, what explains why tests like X=' ' fail. See what is the result of executing
write("ab cd"), nl.
in your Prolog system.
You have errors in your 3 clauses:
What to do you expect the first clause to return in the last argument?
L is, as any other variable in a Prolog program, a variable that is local to the clause it appears in, never a global variable.
The second clause unifies L with a list and you use it as second argument of the recursive call: do you expect the recursive call to change the value of L? This will never be the case: in Prolog there is no assignment of variables, changes are made by building terms and unifying them with new variables.
What happens to X in your third clause???

Prolog Relational Tracking without Lists

I am trying to get a predicate to relate from 1 fact to another fact and to keep going until a specified stopping point.
For example,
let's say I am doing a logistics record where I want to know who got a package from who, and where did they get it from until the end.
Prolog Code
mailRoom(m).
gotFrom(annie,brock).
gotFrom(brock,cara).
gotFrom(cara,daniel).
gotFrom(daniel,m).
gotFrom(X,Y) :- gotFrom(Y,_).
So what I am trying to do with the predicate gotFrom is for it to recursively go down the list from what ever point you start (ex: gotFrom(brock,Who)) and get to the end which is specified by m, which is the mail room.
Unfortunately when I run this predicate, it reads out,
Who = annie.
Who = brock.
Who = cara.
etc.etc....
I tried stepping through the whole thing but Im not sure where it goes from brock to annie, to cara and all the way down till it cycles through trues for infinity. I have a feeling that it has something to do with the wildcard in the function (_), but Im not sure how else I could express that part of the function in order for the predicate to search for the next fact in the program instead of skipping to the end.
I tried using a backcut (!) in my program but it gives me the same error.
Any help is greatly appreciated. I don't want code I just want to know what I am doing wrong so I can learn how to do it right.
Thanks.
I'm afraid this rule is meaningless:
gotFrom(X,Y) :- gotFrom(Y,_).
There is nothing here to constrain X or Y to any particular values. Also, the presence of singleton variable X and the anonymous variable _ means that basically anything will work. Try it:
?- gotFrom([1,2,3], dogbert).
true ;
true ;
What I think you're trying to establish here is some kind of transitive property. In that case, what you want is probably more like this:
gotFrom(X,Z) :- gotFrom(X, Y), gotFrom(Y, Z).
This produces an interesting result:
?- gotFrom(brock, Who).
Who = cara ;
Who = daniel ;
Who = m ;
ERROR: Out of local stack
The reason for the problem may not be immediately obvious. It's that there is unchecked recursion happening twice in that rule. We recursively unify gotFrom/2 and then we recursively unify it again. It would be better to break this into two predicates so that one of them can be used non-recursively.
got_directly_from(annie,brock).
got_directly_from(brock,cara).
got_directly_from(cara,daniel).
got_directly_from(daniel,m).
gotFrom(X,Y) :- got_directly_from(X, Y).
gotFrom(X,Z) :- got_directly_from(X, Y), gotFrom(Y, Z).
This gives us the desired behavior:
?- gotFrom(brock, Who).
Who = cara ;
Who = daniel ;
Who = m ;
false.
Notice this one is resilient to my attack of meaningless data:
?- gotFrom([1,2,3], dogbert).
false.
Some general advice:
Never ignore singleton variable warnings. They are almost always a bug.
Never introduce a cut when you don't understand what's going on. The cut should be used only where you understand the behavior first and you understand how the cut will affect it. Ideally, you should try to restrict yourself to green cuts—cuts that only affect performance and have no observable effects. If you don't understand what Prolog is up to, adding a red cut is just going to make your problems more complex.

Resources