I am working with implementing a unification algorithm for a term rewriting system in Prolog. To fully implement this, I need a predicate substituting out a given subterm for another term. Unfortunately, the way that Prolog instantiates fresh variables prevents the system from successfully be able to achieve this. I have some built in operators, star and divi (really just representing the * and / symbols, but in prefix form). My substitute predicate is made up of the following predicates:
replace(A,B, [], []).
replace(A,B, [H|T], [B|T2]) :- (H==A)->replace(A, B, T, T2).
replace(A,B, [H|T], [H|T2]) :- (H\==A)->replace(A, B, T, T2).
replace_lst([], [H|T], [H2|T2]).
replace_lst([H1|T1], [H|T], [H2|T2]) :-
arg(1,H1,X),
arg(2,H1,Y),
replace(X,Y,[H|T],[H2|T2]),
replace_lst(T1,[H|T],[H2|T2]).
substitute([H|T],A,X):-
A=..List,
replace_lst([H|T],List,C),
X=..C.
Where this runs into trouble is that, for instance, the terms star(X,X) and star(Y,Y), are, by the logic of my rewrite system, structurally equivalent and require no such substitution. However, comparing these two terms using the unifiable predicate will lead Prolog to attempting unification for the two, and the resulting term is no longer equivalent in structure to the original star(X,X) structure. Therefore, I attempted to check for term equality through their structure, but this leads to another can of worms in which, for instance, my rewrite system contains the rewrite rule:
star(X,X)==>X.
However,attempting to substitute based on the variant equality =#= operator leads to the issue of Prolog seeing two differently instantiated terms with the same structure as the same term. Therefore, defining a variant-based subtitution predicate like so:
variant_replace(A,B, [], []).
variant_replace(A,B, [H|T], [B|T2]) :- (H=#=A)->variant_replace(A, B, T, T2).
variant_replace(A,B, [H|T], [H|T2]) :- (H\=#=A)->variant_replace(A, B, T, T2).
variant_replace_lst([], [H|T], [H2|T2]).
variant_replace_lst([H1|T1], [H|T], [H2|T2]) :-
arg(1,H1,X),
arg(2,H1,Y),
variant_replace(X,Y,[H|T],[H2|T2]),
variant_replace_lst(T1,[H|T],[H2|T2]).
variant_substitute([H|T],A,X):-
A=..List,
variant_replace_lst([H|T],List,C),
X=..C.
Leads to an issue where if I have some term:
star((star(X,Y),star(A,B))
and I want to substitute the star(X,Y) subterm with the following predicate:
?- variant_substitute([star(X,Y)=hole],star(star(X,Y),star(A,B)),D).
D = star(hole, hole) .
We can see Prolog, by the logic of the variant substitution predicate, will simply check for terms of a given structure, disregarding the actual variable instantiation. Therefore, I need a way to declare variables. What I desire is to have a system that is able to use metavariables declared in such a way each given term has up to N unique variables, ranging in value from V(0) to V(N-1). Ideally, such a system of metavariables would look like so:
substitute([star(v(0),v(1))=hole],star(star(v(0),v(1)),star(v(2),v(3))),D).
D = star(hole, star(v(2), v(3)))
I need Prolog to see terms denoted with v(#) as variables since I will need to use the unifiable predicate down the road to compare them to the original declaration of my rewrite rules, which is declared like so :
star(X,X) ==> X.
divi(X,X) ==> X.
divi(star(X,Y),Y) ==> X.
star(divi(X,Y),Y) ==> X.
star(X, star(Y,Z)) ==> star(star(divi(X,Z),Y),Z).
divi(X, star(Y,Z)) ==> star(divi(divi(X,Z),Y),Z).
star(X, divi(Y,Z)) ==> divi(star(star(X,Z),Y),Z).
divi(X, divi(Y,Z)) ==> divi(divi(star(X,Z),Y),Z).
What would be the best way to implement this format of metavariable in Prolog?
Related
Given a number of facts is there a way to count them without using a built in function I have tried doing so with the below code but could no get it work. I hope someone can help me out.
For example the following facts:
stops(jubilee,bondstreet,1).
stops(jubilee,waterloo,2).
stops(jubilee,bakerstreet,3).
The code have got so far is:
findStops(X) :- stops(X,_, N), N1 is N+1, stopsX,_,N1).
I would like to make it so that N1 is the counter of how stops the jubilee line has.
A simple solution would be to count the number of stops/3 facts that have the atom jubilee in the first argument. Assuming all clauses for the stops/3 predicate have a bound first argument, you could write:
?- findall(1, stops(jubilee,_,_), List), length(List, Count).
In this query, findall/3 is a standard Prolog predicate and length/2 is a de facto standard predicate, usually available as a built-in predicate or as a library predicate.
Can you convert this query into a predicate that takes the station as an argument (instead of a hardcoded station as jubilee) and returns the count for that station?
The question isn't totally clear since it hasn't been defined what is allowed in terms of "built in" predicates. Such a problem cannot be solved without using some kind of predefined predicate.
Here are a couple of other ideas.
Using assertz and retract:
count_stops(Count) :-
assertz(num_stops(0)),
count_stops_aux(Count).
count_stops_aux(_) :-
stops(_, _, _),
retract(num_stops(C)),
C1 is C + 1,
assertz(num_stops(C1)),
fail.
count_stops_aux(Count) :-
retract(num_stops(Count)).
You could also probably do something similar with SWI Prolog's b_setval/2 and b_getval/2.
Here's a recursive solution that uses a list to check whether we've counted a particular fact already:
count_stops(Count) :-
count_stops_aux([], 0, Count).
count_stops_aux(L, Count, Total) :-
stops(A, B, C),
\+ member(stops(A,B,C), L),
C is Count + 1,
count_stops_aux([stops(A,B,C)|L], C, Total), !.
count_stops_aux(_, Total, Total).
Or similarly, but using length/2 as well:
count_stops(Count) :-
count_stops_aux([], Facts),
length(Facts, Count).
count_stops_aux(L, Facts) :-
stops(A, B, C),
\+ member(stops(A,B,C), L),
count_stops_aux([stops(A,B,C)|L], Facts), !.
count_stops_aux(Facts, Facts).
The first solution will count redundant facts (if an identical fact exists more than once), and assertz and retract are slow operations. The second and third solutions won't count redundant facts, but are really just clunky, verbose versions of Paulo's solution to avoid using findall. This is all why Prolog has predicates such as findall/3 and bagof/3.
I'm trying to further my understanding of Prolog, and how it handles unification. In this case, how it handles unification with lists.
This is my knowledgebase;
member(X, [X|_]).
member(X, [_|T]):- member(X, T).
If I'm understanding the process correctly. If member(X, [X|_]) is not true, then it moves into the recursive rule, and if X is in list T, then [_|T] is unified with T.
So what happens to the anonymous variable in my recursive predicate? Does it get discarded? I'm having difficulty understanding the exact unification process with lists, as [_|T] is two variables, rather than one. I'm just trying to figure out how the unification process works precisely with lists.
Assume that _ is Y
member(X, [Y|T]):- member(X, T).
Then this is True regardless Y. Now you are "returning" member(X, T). In other words, you are discarding Y and "returning" member(X, T).
_ means, whatever it is, ignore that variable.
The _ is just like any other variable, except that each one you see is
treated as a different variable and Prolog won't show you what it
unifies with. There's no special behavior there; if it confuses you
about the behavior, just invent a completely new variable and put it
in there to see what it does.
In your case, your function check if a given element exists on a list, so, you take first element of the list, check if is equal, if not, you discard that element and moves on.
I think your primary question of how lists are represented as variables has been adequately answered, but I sense there are some other aspects to Prolog that need clarification.
To understand Prolog predicates and clauses, it's a good idea not to think of them as "functions" that "return" things, even metaphorically. It can lead you down the dark path of imperative thinking in Prolog. :)
In considering the predicate:
(1) member(X, [X|_]).
(2) member(X, [_|T]) :- member(X, T).
Think of member/2 as a relation which describes when element X is a member of the list L, and the clauses are the rules for determining when it is true.
I'll assume that you already know about how lists are represented in Prolog based upon other answers (e.g., Will Ness' detailed answer).
The first clause says:
(1) X is a member of [X|_] regardless of what the tail of the list [X|_] is
In that notation, the variable _ represents the tail of list [X|_] and X represents the first element of that list. It's trivially true that X is a member of this list, so member(X, [X|_]). is a fact. It's true regardless of what the tail of the list is, so we just use _ (an anonymous variable) since this rule doesn't need the information. Prolog doesn't technically "throw the value away" but the programmer throws it away because the programmer isn't using it. If we had, instead, said, member(X, [X|T]). that would work fine, but we're not using T. Prolog might instantiate it, but it wouldn't be used. It's like assigning x = 3 in C but not using it's value. In this case, Prolog will indicate a warning about a "singleton" variable. Watch for those, because it often means you misspelled something or forgot something. :)
The next rule is recursive. It says:
(2) X is a member of list [_|T] if X is a member of the tail (T) of that list, regardless of what the first element of the list is
Here we're considering the less trivial case where the first element in the list may not be a match to X, so the truth value of member(X, L) depends, in this rule, upon the truth value of member(X, T) where T is the tail (everything but the first element) of L. The rule does not unify member(X, [_|T]) with member(X, T), so it does not unify T with [_|T] as you might suppose. The :- operator defines a rule or implication (note the if in the rule description). [N.B., If you were to unify these terms, it would be done with with the unification operator, =/2: member(X, [_|T]) = member(X, T)].
On the recursive query member(X, T), Prolog goes back to the top, the first rule, and attempts to unify the first argument X with the head of the second argument (which is the original list minus its first element, or head) and, if it doesn't match, goes to rule #2 again, continually checking the tail as well, until it can unify. If it gets to the point where the tail is empty ([]) and hasn't been able to unify X with any elements, the predicate fails because there are no facts or rules that match member(X, []). However, if it does unify X with an element, it succeeds (it does not "return a value* in the sense that a function would in other languages) and reveals the values of any variables it instantiated in the arguments in the process, or simply will succeed if all the arguments passed are already instantiated. If there are more rules to check after succeeding (there was what's called a choice point), it will (if you tell it to) go back and check for more solutions and, if it finds them, display them as well. Or display no or false if there are no more.
Looking at an example query, is b a member of [a,b,c]?
member(b, [a,b,c]).
Prolog will first try to unify the query with a fact or the head of a predicate. The first one it finds is:
member(X, [X|_]).
In attempting to unify, X = b, but [a,b,c] (or, [a|[b,c]] in the head-tail notation) doesn't unify with [b|_](note the head elementsaandb` mismatch). Prolog then moves on to the next clause:
member(X, [_|T]) :- member(X, T).
In unifying member(b, [a,b,c]) with the head, it comes up with:
member(b, [_|[b,c]]) :- member(b, [b,c]).
It now has the recursive query to chase down: member(b, [b,c]). Since it's a new query, it starts at the top again and attempts to unify this with member(X, [X|_]). Now, it's successful, because member(b, [b,c]) (or, member(b, [b|[c]])) matches this pattern: member(b, [b|_]).
Therefore, the member(b, [a,b,c]). succeeds and Prolog will return "true". However, it's not done yet because it left what's called a choice point. Even though it matched member(b, [b,c]) with the first clause, it will still want to go back and find more cases that make it succeed, and there's still another clause to pursue. So, Prolog will go back and try member(b, [b,c]) against the second clause, matching member(b, [b|[c]]) to member(b, [_|[c]]) and doing another recursive query, member(b, [c]) and so on until it ultimately fails to find another solution. This is why the query looks something like this:
| ?- member(b, [a,b,c]).
true ? ;
no
| ?-
It first succeeds, but then we ask for more (with ;) and it then fails (no). This confuses some Prolog beginners, but it's because we've asked Prolog to get another solution, and it said there are none.
Because Prolog continues to try to find solutions (upon request), you can also use a variable in the query:
member(E, [a,b,c]).
This query runs the same way as the prior example, but now I have a variable as the first argument. Prolog will successfully match this to the first clause: member(E, [a,b,c]) unifies with member(X, [X|_]) via E = a. So you'll see something like:
| ?- member(E, [a,b,c]).
E = a ?
If we now ask for more solutions with ;, Prolog goes back and attempts the second clause, unifying member(E, [a|[b,c]]) with member(X, [_|T]) yielding _ = a (which is ignored in the predicate) and T = [b,c]. It then recursively queries, member(E, [b,c]) and, since it's a new query, goes back to the top and matches member(X, [X|_]) again, this time with E = b. So we see:
| ?- member(E, [a,b,c]).
E = a ? ;
E = b ?
And so on. member(E, [a,b,c]) will find all the values of E which make member(E, [a,b,c]) true and then finally fail after exhausting all the elements of [a,b,c]).
[A|B] represents a list where A is the Head element and B is the whole rest list.
So to explain you the algorithm shortly:
Clause: If X is the first element of the list the predicate succeeds.
Clause: If that's not the case, we try to find X in the tail of the list. Therefore, we call member recursively but instead of passing the whole list we now pass the list EXCEPT the head element. In other words, we walk through the list step by step always looking at the head element first. If that is not our element, we dig further.
Think of the anonymous variable _ just as a variable you do not need later. The algorithm would also work, if you replaced _ by a capital letter, however it would give you a warning that you named a variable that you never use.
A list is just a compound term with the '.' functor:
1 ?- [_|T] = .(_,T).
true.
2 ?- [_|T] =.. X.
X = ['.', _G2393, T].
The usual process of structural unification of compound terms apply:
3 ?- [A|T] = .(B,R).
A = B,
T = R.
[A|T] is really .(A,T) so the functors (.) and the arities (both terms are binary, of arity 2) match, so the respective constituents are matched as well.
Yes, the anonymous variable _ is ignored for the purposes of reporting the unification results. Otherwise it is just a fresh uniquely named variable.
it moves into the recursive rule, and if X is in list T, then [_|T] is unified with T.
Not quite. The unification happens before the "moving on", as part of the clause selection. To unify a list L with [_|T] is to select its "tail" and have T referring to it. E.g.
4 ?- L = [1,2,3], L = [_|T].
L = [1, 2, 3],
T = [2, 3].
(_ is 1 but is not reported).
In my Prolog program I have a predicate reg/1 which says if something is a regular expression. I'd like to make the program recognize sequences of regular expressions as a regular expression. So, if reg(a_1), reg(a_2), ..., reg(a_n) are all regular expressions, Prolog should answer yes/true to the query reg(a_1, a_2, ..., a_n).
But I don't know how to do it.
What I have done is the following:
reg([H|T]) :- reg(H), reg(T).
reg([X]) :- reg(X).
If, for example, reg(a), reg(b), reg(c) are all in the knowledge base, then Prolog answers yes/true to the query reg([a, b]) or reg([b, a, c]), but I can't ask it something like reg(a, b) or reg(b, a, c), i.e., I can't get rid of the square brackets.
It is very uncommon in Prolog to use the same structure with varying arities. To show you one such place where they could have been used but are not, consider directives as they are used to declare a predicate dynamic, multifile, or discontiguous. Say, I want to declare a/2 and b/5 dynamic. The following options are possible in ISO-Prolog:
:- dynamic(a/2).
:- dynamic(b/5).
:- dynamic([a/2,b/5]). % using a list
:- dynamic((a/2,b/5)). % using an and-sequence
Additionally, many Prolog systems have declared dynamic/1 a prefix operator (as an implementation specific extension) such that you can write:
:- dynamic a/2.
:- dynamic b/5.
:- dynamic [a/2,b/5].
:- dynamic a/2, b/5.
However, there is no
:- dynamic(a/2,b/5). % does not work
which would correspond to your idea.
If you really want to use that representation, you will need (=..)/2 for that. I'd say this is a source of many potential bugs.
The only case that comes to mind where a structure with "variable" arity is commonly used are compact representations of sets of variables, as they are used in the implementation of setof/3. Instead of using a list of variables Vs the structure V is used.
term_varvect(T, V) :-
term_variables(T, Vs),
V =.. ['.'|Vs]. % some use v instead of '.'
In systems with a limited max_arity you have to handle the overflow case:
term_varvect(T, V) :-
term_variables(T, Vs),
catch( V =.. ['.'|Vs],
error(representation_error(max_arity), _),
Vs = V).
So I just started Prolog and I was wondering two things:
1) Is there built in functions (or are they all called predicates?) for simple things like max of 2 numbers, or sine of a number, etc... If so, how do I access them?
2) How can I call a predicate from another one? I wrote two predicates called car and cdr. car returns the head of a list and cdr returns the list without the head. But now I want to call car on the cdr. Here are some examples for clarification:
car([3,4,5,5], H). would return H = 3
cdr([3,4,5,5],L). would return L = [4,5,5]
and what I am asking is how can I do this:
car(cdr[3,4,5,5]))
??
As others have pointed out, the predicates in Prolog are called that for a reason: they really aren't functions. Many newcomers to Prolog start out by trying to map the functionality they know in other languages over to Prolog and it generally fails. Prolog is a very different programming tool than most other languages. So it's a bit like using a variety of hammers for a long time, then having someone hand you a wrench, and you wonder why it doesn't make a good hammer.
In Prolog, predicates are a means of declaring relations between entities. If you say foo(a, b) it means there's a relationship between a and b called foo. You've probably seen the examples: knows(joe, jim). and knows(jim, sally). And you can define a relation, like:
remotely_acquainted(X, Y) :- knows(X, Z), knows(Z, Y), \+ knows(X, Y).
Or something like that.
A predicate does not return a value. It either succeeds or it fails. If you have a sequence of predicates separated by commas (an "and" relationship) and Prolog encounters a predicate that fails, it backs up (backtracks) to the nearest prior predicate which it can make succeed again with different instantiation of its arguments and moves forward again.
Just to add a little to the confusion, there are some predicates in Prolog designed specifically for the evaluation of arithmetic expressions. These act like functions, but they are special case. For example:
X is Y / gcd(Z, 4).
Here, gcd of Z and 4 is computed an its value returned, and then Y is divided by that value and the result is instantiated into X. There are a variety of other functions as well, such as max/2, sin/1, etc. You can look them up in the documentation.
Arithmetic comparative operators function this way as well (using =:=/2, >/2, </2, etc with numeric expressions). So if you say:
X < Y + Z
The Prolog will consider numerical evaluation of these arguments and then compare them.
So having said all that, Prolog does allow embedding of term structures. You could have something like:
car(cdr([1,2,3]))
as a term. Prolog will not interpret it. Interpretation is left up to the programmer. I could then create a predicate which defines an evaluation of such terms:
car([H|_], H).
cdr([_|T], T).
proc_list(car(X), Result) :-
proc_list(X, R1),
car(R1, Result), !.
proc_list(cdr(X), Result) :-
proc_list(X, R1),
cdr(R1, Result), !.
proc_list(X, X).
The cut in the above clauses prevents backtracking to proc_list(X, X) when I don't want it.
Then:
| ?- proc_list(car(cdr([1,2,3])), R).
R = 2
yes
| ?- proc_list(car(cdr(cdr([1,2,3]))), R).
R = 3
yes
| ?-
Note this is a simple case and I may not have captured all of the subtleties of doing a proper sequence of car and cdr. It can also be made more general using =.. and call, etc, instead of discrete terms car and cdr in the parameters. For example, a slightly more general proc_list might be:
proc_list(Term, Result) :-
Term =.. [Proc, X], % Assumes terms have just one argument
member(Proc, [car, cdr]), % True only on recognized terms
proc_list(X, R1), % Recursively process embedded term
ProcCall =.. [Proc, R1, Result], % Construct a calling term with Result
call(ProcCall), !.
proc_list(X, X).
This technique of processing a term does step away from relational behavior which Prolog is best at, and leans into functional behavior, but with an understand of how Prolog works.
Prolog has a really different attitude to computing...
You don't define functions, but relations among arguments. The most similar and well known language I'm aware of is SQL. Think of predicates as tables (or stored procedures, when some computation not predefined by database engine is required).
car([H|_],H).
cdr([_|T],T).
car_of_cdr(L, Car) :- cdr(L, Cdr), car(Cdr, Car).
but since lists' syntax is a core part of the language, a better definition could be
car_of_cdr([_,X|_], X).
Anyway, I think you should spend some time on some Prolog tutorial. SO info page has much more information...
:- use_module(support).
This means the module will use predicates written in other modules.
<module_name>:<predicate_name>(<atoms / Variables>).
This way you can call a predicate in another module.
How do I define a binary operation on a list in prolog and then check its properties such as closure , associative, transitive , identity etc. ? I am new to prolog.. I don't know whether it is the place to ask but I tried and I didn't come across anything somewhere.
In Prolog you define predicates, i.e. relations among a symbol (called functor) and its arguments.
A predicate doesn't have a 'return value', just a 'truth value', depending of whether it can be evaluated WRT its arguments. Then your question it's not easy to answer.
Associativity, transitivity, identity, are of little help when it come down to speaking about predicates. The first and most common property we wish to evaluate is termination, because Prolog control flow it's a bit unusual and can easily lead to infinite recursion.
Anyway, the simpler binary relation on a list is member/2, that holds when its first argument it's an element of the second argument (the list).
member(X, [X|_]).
member(X, [_|T]) :- member(X,T).
I can't see any benefit in assessing that it's not associative, neither transitive (its arguments are of different types !).
Common operations like intersection, union, etc typically needs 3 arguments, where the last is the result of the operation performed between 2 lists.
Identity in Prolog (that is an implementation of first order logic) deserves a special role. Indeed, the usual programming symbol = used to assess identity, really performs a (potentially) complex operation, called unification. You can see from the (succint) documentation page that it's 'just' a matching between arbitrary terms.
You could do something like this:
% Define sets I want to try
set7([0,1,2,3,4,5,6]).
% Define operations
% Sum modulo 7
sum7(X, Y, R) :-
R is (X+Y) mod 7.
% Normal sum
nsum(X, Y, R) :-
R is X + Y.
% A given set is closed if there is not a single case which
% indicates that it is not closed
closed(S, Operator) :-
\+ n_closed(S, Operator, _), !.
% This predicate will succeed if it finds one pair of elements
% from S which, when operated upon, will give a result R which
% is outside of the set
n_closed(S, Operator, R) :-
member(X, S),
member(Y, S),
Operation =.. [Operator, X, Y, R],
Operation,
\+ member(R, S).
When you execute it, you get these results:
| ?- set7(S), closed(S, sum7).
(1 ms) yes
| ?- set7(S), closed(S, nsum).
no
I'm not convinced my closure check is optimal, but it gives some ideas for how to play with it.