I understand that the two facts are expressed using complex terms which again have complex terms as arguments. There are three levels of terms nested inside terms.
vertical(line(point(X,Y), point(X,Z))).
horizontal(line(point(X,Y), point(Z,Y))).
Does this mean the overall complex term has an arity of one as the other complex terms are nested?
Notice that what you call "complex terms" are normally called coumpound terms in Prolog. You can easily check for the arity of Prolog terms yourself in the following way:
?- functor(vertical(line(point(X,Y), point(X,Z))), _, Arity).
Arity = 1.
As you can see, your intuition was correct in this particular case!
SWI7-specific
Since you have added the SWI-Prolog tag to your question, it may be useful to know that in SWI 7 there is also compound_name_arity/3, which works on compound terms of arity 0. (In other Prologs a compound term of arity zero would be an atom.) For example:
?- functor(f(), _, Arity).
ERROR: functor/3: Domain error: `compound_non_zero_arity' expected, found `f()'
?- compound_name_arity(f(), _, Arity).
Arity = 0.
Related
I have defined the following knowledge base:
leaf(_).
tree(X) :- leaf(X).
and was expecting the query:
leaf(X) = tree(X).
to return true ., because any leaf should per definition be a tree.
Unfortunately activating trace doesn't yield any useful results.
Here is a link to this minimal example if you'd like to play around with it.
Short answer: you here check if the term leaf(X) can be unified with tree(X). Since these are terms that consist out of different functors, this will fail.
The tree/1 and leaf/1 in your statement leaf(X) = tree(X) are not the predicates. What you basically here have written is:
=(leaf(X), tree(X))
So you call the (=)/2 predicate, with leaf(X) and tree(X) terms.
Now in Prolog two terms are unifiable if:
these are the same atom; or
it is a term with the same functor and arity, and the arguments are elementwise unifiable.
Since the functor leaf/1 is not equal to the functor tree/1, this means that leaf(X) and tree(X) can not be equal.
Even if we would define a predicate with the intent of checking if two predicates are semantically the same, this would fail. Here you basically aim to solve the Equivalence problem, which is undecidable. This means that one, in general, can not construct an algorithm that verifies if two Turing machines decide the same language. Prolog is a Turing complete language, we basically can translate any predicate in a Turing machine and vice versa. So that means that we can not calculate if two predicates accept the same input.
In Prolog, [H|T] is the list that begins with H and where the remaining elements are in the list T (internally represented with '.'(H, '.'(…))).
Is it possible to define new syntax in a similar fashion? For example, is it possible to define that [T~H] is the list that ends with H and where the remaining elements are in the list T, and then use it as freely as [H|T] in heads and bodies of predicates? Is it also possible to define e.g. <H|T> to be a different structure than lists?
One can interpret your question literally. A list-like data structure, where accessing the tail can be expressed without any auxiliary predicate. Well, these are the minus-lists which were already used in the very first Prolog system — the one which is sometimes called Prolog 0 and which was written in Algol-W. An example from the original report, p.32 transliterated into ISO Prolog:
t(X-a-l, X-a-u-x).
?- t(nil-m-e-t-a-l, Pluriel).
Pluriel = nil-m-e-t-a-u-x.
So essentially you take any left-associative operator.
But, I suspect, that's not what you wanted. You probably want an extension to lists.
There have been several attempts to do this, one more recent was Prolog III/Prolog IV. However, quite similar to constraints, you will have to face how to define equality over these operators. In other words, you need to go beyond syntactic unification into E-unification. The problem sounds easy in the beginning but it is frightening complex. A simple example in Prolog IV:
>> L = [a] o M, L = M o [z].
M ~ list,
L ~ list.
Clearly this is an inconsistency. That is, the system should respond false. There is simply no such M, but Prolog IV is not able to deduce this. You would have to solve at least such problems or get along with them somehow.
In case you really want to dig into this, consider the research which started with J. Makanin's pioneering work:
The Problem of Solvability of Equations in a Free Semi-Group, Akad. Nauk SSSR, vol.233, no.2, 1977.
That said, it might be the case that there is a simpler way to get what you want. Maybe a fully associative list operator is not needed.
Nevertheless, do not expect too much expressiveness from such an extension compared to what we have in Prolog, that is DCGs. In particular, general left-recursion would still be a problem for termination in grammars.
It is possible to extend or redefine syntax of Prolog with iso predicate
:- op(Precedence, Type, Name).
Where Precedence is a number between 0 and 1200, Type describe if the operatot is used postfix,prefix or infix:
infix: xfx, xfy, yfx
prefix: fx, fy
suffix: xf, yf
and finally name is the operator's name.
Operator definitions do not specify the meaning of an operator, but only describe how it can be used syntactically. It is only a definition extending the syntax of Prolog. It doesn't gives any information about when a predicate will succeed. So you need also to describe when your predicate succeeds. To answer your question and also give an example you could define :
:- op( 42, xfy, [ ~ ]).
where you declare an infix operator [ ~ ]. This doesn't means that is a representation of a list (yet). You could define clause:
[T ~ H]:-is_list([H|T]).
which matches [T~H] with the list that ends with H and where the remaining elements are in the list T.
Note also that it is not very safe to define predefined operators
like [ ] or ~ because you overwrite their existing functionality.
For example if you want to consult a file like [file]. this will
return false because you redefined operators.
Is there any difference between input and output parameters in Prolog predicate definitions? How does this this compare with other languages such as Scheme and C?
I hope I understand your question. You should look into how unification is implemented in Prolog, as it will make things clearer. Anyway:
Briefly, there is no built-in way to declare an argument to a Prolog predicate as input, output, or input/output.
In C, you could say:
void foo(int const *a, int *b)
{
*b += *a;
}
and you could argue that in the context of foo, a is an input argument, while b is an output argument. In Prolog, you can use this notation when describing predicates, but there is no way to declare in the head of the predicate definition that an argument must be bound or a free variable when the predicate is called. And anyway, most predicates in pure Prolog have arguments that can be input, output, or input/output, depending how the predicate is used. Look at the list library of SWI-Prolog for many examples.
You can of course demand that an argument is instantiated, or a free variable, but this is done in the body of the predicate definition:
add_2(A, B) :- integer(A), var(B), B is A+2.
Compare this to:
plus_2(A, B) :- integer(A), integer(B), B =:= A+2.
which checks whether B=A+2 holds true, instead of adding 2 to A and unifying the result with B. integer/1, var/1, and the other predicates that verify the type of a term cannot be implemented in pure Prolog.
In my very limited experience with Prolog, I have noticed that one will try to define predicates that work as long as enough arguments are instantiated to either:
Instantiate the other variables according to the logic of the predicate
Infer whether the relationship between the arguments described by the predicate holds true.
For example, length(List, Integer) can tell you how long a list is, make a list of uninstantiated variables of the given length, or check whether the list is that long.
What you can do, however, is have a ground term in the head of the predicate definition, for example foo(1). This sort of predicates are called facts. A clause with a ground term in the head is the usual way for defining the end-of-recursion for recursive predicates.
Is there any difference between the input/output parameters in Prolog definitions?
No, and in fact a parameter can be either one depending on how it is used. Boris's length example is a good one, because you can calculate length:
?- length([1,2,3], X).
X = 3.
Or test an answer:
?- length([1,2,3], 3).
true.
Or generate a list of specified length:
?- length(X, 3).
X = [_G273, _G276, _G279].
Or even generate lists and lengths:
?- length(X, Y).
X = [],
Y = 0 ;
X = [_G15],
Y = 1 ;
X = [_G15, _G18],
Y = 2 ;
...
So you see either argument of length/2 can be instantiated or not and you'll still get meaningful answers. Not every predicate in Prolog is this flexible, but many are.
How does this this compare with other languages such as scheme and C ?
This is the principal difference between Prolog and other languages. There is no other, better-known language which behaves analogously to help you grok it. It means that, among other differences, there is no implicit "return value," you must have a parameter to pass results back in, but you're not limited to just one result parameter. In the case where both arguments to length/2 were uninstantiated, they were both acting as return values.
By convention, you will want to write your predicates so that input parameters go before output parameters for the common cases (or at least, in a sensible way for the name you've chosen).
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.
anyone have idea how to solve this problem
counts the number of occurrences of an operator inside an expression. For instance, the query:
?- count(a+b*c-(2+3*4)/(5*(2+a)+(b+c)^f((d-e)*(x-y))), *, C).
would count the number of occurrences of operator * in the expression given as the first argument and output on C
I am using SWI-prolog
Is this homework?
Here's some hints:
Prolog operators are syntactic sugar around normal prolog terms. The expression 3 * 2 + 1 is parsed as the term '+'('*'(3,2),1).
The built-in predicate =.. decomposes a term into a list, the head of which is the functor and the tail of which comprises the [non-decomposed] terms that are the arguments to the original term.
The built-in predicate functor/3 unifies a term with its functor and arity.
You might also want to look at arg/3 which provide the means to examine the arguments of the specified term by ordinal position.
Now that you know that, a fairly simple recursive solution should present itself. If you need to factor in the arity of the desired operator, it's a little more convoluted (but not much).