Different order of interpretation depending on the context? - prolog

I have the following rules to convert a structure.
cmap(predicate(_,Verb,named(N)),[S1,S2]) :-
next_uid(NewVar),
S1 =.. [named,N,NewVar],
S2 =.. [Verb,NewVar].
cmap(predicate(_,Verb,Subj),S) :-
S =.. [Verb,Subj].
the problem is that one rule needs clauses to be in one order and there is another rule that needs clauses to be in another order, as below :
cmap(predicate(_,Verb,Subj),S) :-
S =.. [Verb,Subj].
cmap(predicate(_,Verb,named(N)),[S1,S2]) :-
next_uid(NewVar),
S1 =.. [named,N,NewVar],
S2 =.. [Verb,NewVar].
how can I do that ?
The problem fields are : named(N) <=> Subj
The reason I need different order is that case1(fact) I have value already assigned, in case2(question) I need the variable to be unbound, so that it can bind it later.
PS> if it make any difference the rule-call is two steps removed i.e. via another two rules.
here the exact usage . the diff is one does skolemization the other dont.
The question variables have to stay un-unified/free, so they can be used as a query.
In addition named(X), have to extracted as its own separate fact when it is in the structure /thats DRS weirdnes i have no control over/.
% provides/unifies ID for every Reference variable
skolem([]).
skolem([H|T]) :- next_uid(H), skolem(T).
convert([],[]).
% use the map to convert any Item
convert(Item-_,R) :- cmap(Item,R).
%processing Questions
convert(drs([], [question(drs(_Refs,Conds))]), Res) :- convert(Conds, Res).
%DRS processing
convert(drs(Refs,Conds),Res) :- skolem(Refs), convert(Conds,Res).
% process list of items
convert([H|T],[RH|RT]) :- convert(H,RH), convert(T,RT).
may be something along the lines of :
cmap(predicate(_,Verb,named(N)),[named(N,NewVar),S2]) :- next_uid(NewVar), cmap(predicate(_,Verb,?X?),S2).

You want to distinguish the cases by explicitly verifying whether the 3rd argument of predicate/3 is bound ("is a variable", to perform the standard language abuse). This is all very outside of first-order positive logic:
cmap(predicate(_,Verb,NN),[S1,S2]) :-
nonvar(NN),
!,
cmap_nonvar(predicate(_,Verb,NN),[S1,S2]).
Symmetrically (one can actually get rid of the var(NN),! as the test and the subsequent committement to the clause have already happened, but I like symmetry if it is not expensive:
cmap(predicate(_,Verb,NN),[S1,S2]) :-
var(NN),
!,
cmap_var(predicate(_,Verb,NN),[S1,S2]).
Modifications: Here we can get rid of one use of "univ", =../2 (don't use "univ" if you don't need it). Also, it's strange and unbalanced that the second argument is a list in one case and a non-list in the other case. Why not use a list in both cases?
"nonvar" case
Possible problem: for cmap_nonvar the second clause executes if the 3rd argument of predicate/3 does not unify with named(N) as well as if it unifies with named(N). Is that really wanted?
% if the 3rd argument of predicate/3 unifies with named(N)
cmap_nonvar(predicate(_,Verb,named(N)),[named(N,NewVar),S]) :-
next_uid(NewVar),
S =.. [Verb,NewVar].
cmap_nonvar(predicate(_,Verb,Subj),[S]) :-
S =.. [Verb,Subj].
"var" case
Possible problem: I suppose you do not want the second clause here, which is always executed as a second case with Subj unbound as Subj can be unified with named(N).
cmap_var(predicate(_,Verb,Subj),S) :-
S =.. [Verb,Subj].
cmap_var(predicate(_,Verb,named(N)),[named(N,NewVar),S]) :-
next_uid(NewVar),
S =.. [Verb,NewVar].
Trick: tag the argument
"tagging" means enclosing a term into another term to be able to write Prolog code more idiomatically.
In this case, one can tag NN:
tag(X,var(X)) :- var(X),!.
tag(X,nonvar(X)) :- nonvar(X),!.
cmap(predicate(_,Verb,NN),[S1,S2]) :-
tag(NN,TaggedNN),
cmap_tag_aware(predicate(_,Verb,TaggedNN),[S1,S2]).
cmap can then match on the particular form of the passed term:
cmap_tag_aware(predicate(_,Verb,nonvar(named(N))),[named(N,NewVar),S]) :-
next_uid(NewVar),
S =.. [Verb,NewVar].
cmap_tag_aware(predicate(_,Verb,nonvar(Subj)),[S]) :-
S =.. [Verb,Subj].
cmap_tag_aware(predicate(_,Verb,var(Subj)),S) :-
S =.. [Verb,Subj].
cmap_tag_aware(predicate(_,Verb,var(named(N))),[named(N,NewVar),S]) :-
next_uid(NewVar),
S =.. [Verb,NewVar].

Related

How do I print dynamic/1 in Prolog

I want to print these all names under each dynamic/1. For example I want to print all names of male under one query for print all males in Prolog.
The easiest way to do this in swi-prolog (and also in gnu-prolog) is to use predicate listing/1:
?- listing(male/1).
:- dynamic male/1.
male(saad).
male(sohaib).
male(salman).
...
true.
If you want more control over display formatting, you can define your own predicate as:
list_facts(Name/Arity) :-
functor(Head, Name, Arity),
forall( clause(Head, true),
format('~w.\n', [Head]) ). % Adjust formatting here!
Example:
?- list_facts(female/1).
female(rida).
female(florida).
female(yasmeen).
...
true.
If you want to show just the names, try:
?- forall(female(Name), format('~w\n', [Name])).
rida
florida
yasmeen
...
true.
REMARK The swi-prolog built-in predicate forall/2is defined as:
forall(Cond, Action) :-
\+ (Cond, \+ Action).
The supplied code works with SWI-Prolog, don't know if this works with other Prolog systems but the basis of the code should be portable.
This is from actual code I use daily so it more production quality code than simple answer code but the basis is to use functor/3 to get a head and then use the head in forall/2 to get the rules (rule/2) and format/3 to output each rule. Normally a rule is a head and body but since this is outputting facts only the heads are output. To convert the rules to individual values =../2 is used. This uses library(options). This also uses current_predicate/1 to check if the predicate exists to avoid an exception if it does not. functor/3 could probably be used but somewhere I recall a corner case that it did now work. The rest should not need explaining.
I only entered 3 of the male facts. Would have used all of them if they were typed as text into the question as then they could have been easily copied.
If the facts are in a different module remember to change the name of the module when calling list_facts/N.
:- module(examples,
[
list_facts/1,
list_facts/2,
list_facts/3
]).
:- dynamic female/1.
:- dynamic male/1.
male(saad).
male(sohaib).
male(salman).
list_facts(Module:Name/Arity) :-
list_facts(user_output,Module:Name/Arity,[]).
list_facts(Output_stream,Module:Name/Arity) :-
list_facts(Output_stream,Module:Name/Arity,[]).
list_facts(Output_stream,Module:Name/Arity,Options) :-
(
current_predicate(Module:Name/Arity)
->
(
option(left_margin_size(Left_margin_size),Options)
->
atomic_list_concat(['~|~',Left_margin_size,'+~|~w'],Format)
;
Format = '~w'
),
(
option(title(Title),Options)
->
format(Output_stream,Format,[Title]),
format(Output_stream,'~n',[])
;
true
),
functor(Head,Name,Arity),
forall(
rule(Module:Head,Rule),
list_fact(Output_stream,Format,Rule)
)
;
format(Output_stream,'No facts found: ~w:~w/~w.~n',[Module,Name,Arity])
).
list_fact(Output_stream,Format,Fact) :-
Fact =.. Fact_values,
list_values(Output_stream,Format,false,Fact_values).
% Recursive case - functor name
list_values(Output_stream,Format,false,[_Value|Values]) :-
!,
list_values(Output_stream,Format,true,Values).
% Recursive case - fact arguments
list_values(Output_stream,Format,true,[Value|Values]) :-
!,
format(Output_stream,Format,[Value]),
list_values(Output_stream,Format,true,Values).
% Base case
list_values(Output_stream,_Format,_Functor_done,[]) :-
format(Output_stream,'~n',[]).
Example usage.
?- working_directory(_,'C:/Users/Groot').
true.
?- [examples].
true.
?- list_facts(examples:male/1).
saad
sohaib
salman
true.
?- list_facts(user_output,examples:male/1,[left_margin_size(3),title('male/1')]).
male/1
saad
sohaib
salman
true.

I have defined multiple predicates that seem to share a common form

All of these predicates are defined in pretty much the same way. The base case is defined for the empty list. For non-empty lists we unify in the head of the clause when a certain predicate holds, but do not unify if that predicate does not hold. These predicates look too similar for me to think it is a coincidence. Is there a name for this, or a defined abstraction?
intersect([],_,[]).
intersect(_,[],[]).
intersect([X|Xs],Ys,[X|Acc]) :-
member(X,Ys),
intersect(Xs,Ys,Acc).
intersect([X|Xs],Ys,Acc) :-
\+ member(X,Ys),
intersect(Xs,Ys,Acc).
without_duplicates([],[]).
without_duplicates([X|Xs],[X|Acc]) :-
\+ member(X,Acc),
without_duplicates(Xs,Acc).
without_duplicates([X|Xs],Acc) :-
member(X,Acc),
without_duplicates(Xs,Acc).
difference([],_,[]).
difference([X|Xs],Ys,[X|Acc]) :-
\+ member(X,Ys),
difference(Xs,Ys,Acc).
difference([X|Xs],Ys,Acc) :-
member(X,Ys),
difference(Xs,Ys,Acc).
delete(_,[],[]).
delete(E,[X|Xs],[X|Ans]) :-
E \= X,
delete(E,Xs,Ans).
delete(E,[X|Xs],Ans) :-
E = X,
delete(E,Xs,Ans).
There is an abstraction for "keep elements in list for which condition holds".
The names are inclide, exclude. There is a library for those in SWI-Prolog that you can use or copy. Your predicates intersect/3, difference/3, and delete/3 would look like this:
:- use_module(library(apply)).
intersect(L1, L2, L) :-
include(member_in(L1), L2, L).
difference(L1, L2, L) :-
exclude(member_in(L2), L1, L).
member_in(List, Member) :-
memberchk(Member, List).
delete(E, L1, L) :-
exclude(=(E), L1, L).
But please take a look at the implementation of include/3 and exclude/3, here:
https://www.swi-prolog.org/pldoc/doc/_SWI_/library/apply.pl?show=src#include/3
Also in SWI-Prolog, in another library, there are versions of those predicates called intersection/3, subtract/3, delete/3:
https://www.swi-prolog.org/pldoc/doc/_SWI_/library/lists.pl?show=src#intersection/3
https://www.swi-prolog.org/pldoc/doc/_SWI_/library/lists.pl?show=src#subtract/3
https://www.swi-prolog.org/pldoc/doc_for?object=delete/3
Those are similar in spirit to your solutions.
Your next predicate, without_duplicates, cannot be re-written like that with include/3 or exclude/3. Your implementation doesn't work, either. Try even something easy, like:
?- without_duplicates([a,b], L).
What happens?
But yeah, it is not the same as the others. To implement it correctly, depending on whether you need the original order or not.
If you don't need to keep the initial order, you can simply sort; this removes duplicates. Like this:
?- sort(List_with_duplicates, No_duplicates).
If you want to keep the original order, you need to pass the accumulated list to the recursive call.
without_duplicates([], []).
without_duplicates([H|T], [H|Result]) :-
without_duplicates_1(T, [H], Result).
without_duplicates_1([], _, []).
without_duplicates_1([H|T], Seen0, Result) :-
( memberchk(H, Seen0)
-> Seen = Seen0 , Result = Result0
; Seen = [H|Seen0], Result = [H|Result0]
),
without_duplicates_1(T, Seen, Result0).
You could get rid of one argument if you use a DCG:
without_duplicates([], []).
without_duplicates([H|T], [H|No_duplicates]) :-
phrase(no_dups(T, [H]), No_duplicates).
no_dups([], _) --> [].
no_dups([H|T], Seen) -->
{ memberchk(H, Seen) },
!,
no_dups(T, Seen).
no_dups([H|T], Seen) -->
[H],
no_dups(T, [H|Seen]).
Well, these are the "while loops" of Prolog on the one hand, and the inductive definitions of mathematical logic on the other hand (See also: Logic Programming, Functional Programming, and Inductive Definitions, Lawrence C. Paulson, Andrew W. Smith, 2001), so it's not surprising to find them multiple times in a program - syntactically similar, with slight deviations.
In this case, you just have a binary decision - whether something is the case or not - and you "branch" (or rather, decide to not fail the body and press on with the selected clause) on that. The "guard" (the test which supplements the head unification), in this case member(X,Ys) or \+ member(X,Ys) is a binary decision (it also is exhaustive, i.e. covers the whole space of possible X)
intersect([X|Xs],Ys,[X|Acc]) :- % if the head could unify with the goal
member(X,Ys), % then additionally check that ("guard")
(...action...). % and then do something
intersect([X|Xs],Ys,Acc) :- % if the head could unify with the goal
\+ member(X,Ys), % then additionally check that ("guard")
(...action...). % and then do something
Other applications may need the equivalent of a multiple-decision switch statement here, and so N>2 clauses may have to be written instead of 2.
foo(X) :-
member(X,Set1),
(...action...).
foo(X) :-
member(X,Set2),
(...action...).
foo(X) :-
member(X,Set3),
(...action...).
% inefficient pseudocode for the case where Set1, Set2, Set3
% do not cover the whole range of X. Such a predicate may or
% may not be necessary; the default behaviour would be "failure"
% of foo/1 if this clause does not exist:
foo(X) :-
\+ (member(X,Set1);member(X,Set2);member(X,Set3)),
(...action...).
Note:
Use memberchk/2 (which fails or succeeds-once) instead of member/2 (which fails or succeeds-and-then-tries-to-succeed-again-for-the-rest-of-the-set) to make the program deterministic in its decision whether member(X,L).
Similarly, "cut" after the clause guard to tell Prolog that if a guard of one clause succeeds, there is no point in trying the other clauses because they will all turn out false: member(X,Ys),!,...
Finally, use term comparison == and \== instead of unification = or unification failure \= for delete/3.

How to tell Prolog that two literals are equivalent

Anyone knows how to tell Prolog that n(n(p)) and n(p) represent the same thing?
Or how to reduce n(n(p)) to n(p)?
Anyone knows how to tell Prolog that n(n(p)) and n(p) represent the same thing?
Prolog's unification system has a clear meaning of when two things are the same. n(n(p)) and n(p) are not the same thing. You can construct a predicate that defines a more generic equivalence relation than (=)/2.
Normally in Prolog two constants are different if they have a different name. Two compound terms are the same only if the functor is the same (the name of the functor and the number of parameters), and the parameters are equal as well.
We thus can define a predicate like:
equiv_(n(n(p)), n(p)).
equivalence(L, R) :-
equiv_(L, R).
equivalence(L, R) :-
equiv_(R, L).
equivalence(L, L).
If you the match with equivalence(n(n(p)), n(p)), it will return true.
#false Can't I define a predicate n(n(p)) that returns n(p). What I want, in fact, is that all occurrences of the within a list to be replaced with the latter.
You can make a predicate that unifies a second parameter with n(p) if the first one is n(n(p)):
replace_nnp(X, n(p)) :-
X == n(n(p)).
replace_nnp(X, X) :-
X \== n(n(p)).
Then we can use maplist/3 [swi-doc] to map a list of items to another list of items:
replace_nnp_list(LA, LB) :-
maplist(replace_nnp, LA, LB).
For example:
?- replace_nnp_list([n(n(p)), p, n(p), n(n(p))], X).
X = [n(p), p, n(p), n(p)] ;
false.

Prolog: How to create a list of predicates?

d_edge(a, b, 5).
e_edge(a, c, 6).
f_edge(b, c, 8).
% I will have a list of rules for the graph point
% from source to destination with weight.
list2pair([T], [A,B], [(T,A,B)]).
list2pair([T1|Tt], [A1,A2|T], Result) :-
list2pair(Tt, [A1|T], R1),
append([(T1,A1,A2)], R1, Result).
I want to come up with the result like
[d_edge(a,b), f_edge(b,c)]
my 1st arg will be the list of names [d_edge,f_edge]
my 2nd arg will be the list of vertexes [a,b,c].
My current code generates [(d_edge,a,b),(f_edge,b,c)].
Whenever I try to update the predicate from (T1,A1,A2) to T1(,A1,A2)
I get an error saying that it is not valid predicate.
I understand why I am getting the error. But I couldn't find a way around it.
First things first: T1(,A1,A2) is syntactically incorrect.
Here's how you could proceed using the built-in predicate (=..)/2 (a.k.a. "univ"):
list2pair([T], [A1,A2], [X]) :-
X =.. [T,A1,A2].
list2pair([T1|Tt], [A1,A2|T], [X|Xs]) :-
X =.. [T1,A1,A2],
list2pair(Tt, [A2|T], Xs).
Sample query using SICStus Prolog 4.3.2:
| ?- list2pair([d_edge,f_edge], [a,b,c], Xs).
Xs = [d_edge(a,b),f_edge(b,c)] ? ; % expected result
no
Note that the above only "constructs" these compound terms—it does not ensure that suitable facts d_edge/3, f_edge/3 etc really do exist.

Prolog difference routine

I need some help with a routine that I am trying to create. I need to make a routine that will look something like this:
difference([(a,b),(a,c),(b,c),(d,e)],[(a,_)],X).
X = [(b,c),(d,e)].
I really need help on this one..
I have written a method so far that can remove the first occurrence that it finds.. however I need it to remove all occurrences. Here is what I have so far...
memberOf(A, [A|_]).
memberOf(A, [_|B]) :-
memberOf(A, B).
mapdiff([], _, []) :- !.
mapdiff([A|C], B, D) :-
memberOf(A, B), !,
mapdiff(C, B, D).
mapdiff([A|B], C, [A|D]) :-
mapdiff(B, C, D).
I have taken this code from listing(subtract).
I don't fully understand what it does, however I know it's almost what I want. I didn't use subtract because my final code has to be compatible with WIN-Prolog... I am testing it on SWI Prolog.
Tricky one! humble coffee has the right idea. Here's a fancy solution using double negation:
difference([], _, []).
difference([E|Es], DL, Res) :-
\+ \+ member(E, DL), !,
difference(Es, DL, Res).
difference([E|Es], DL, [E|Res]) :-
difference(Es, DL, Res).
Works on SWI-PROLOG. Explanation:
Clause 1: Base case. Nothing to diff against!
Clause 2: If E is in the difference list DL, the member/2 subgoal evaluates to true, but we don't want to accept the bindings that member/2 makes between variables present in terms in either list, as we'd like, for example, the variable in the term (a,_) to be reusable across other terms, and not bound to the first solution. So, the 1st \+ removes the variable bindings created by a successful evaluation of member/2, and the second \+ reverses the evaluation state to true, as required. The cut occurs after the check, excluding the 3rd clause, and throwing away the unifiable element.
Clause 3: Keep any element not unifiable across both lists.
I am not sure, but something like this could work. You can use findall to find all elements which can't be unified with the pattern:
?- findall(X, (member(X, [(a,b),(b,c),(a,c)]), X \= (a,_)), Res).
gets the reply
Res = [ (b, c) ]
So
removeAll(Pattern, List, Result) :-
findall(ZZ109, (member(ZZ109, List), ZZ109 \= Pattern), Result).
should work, assuming ZZ109 isn't a variable in Pattern (I don't know a way to get a fresh variable for this, unfortunately. There may be a non-portable one in WIN-Prolog). And then difference can be defined recursively:
difference(List, [], List).
difference(List, [Pattern|Patterns], Result) :-
removeAll(Pattern, List, Result1),
difference(Result1, Patterns, Result).
Your code can be easily modified to work by making it so that the memberOF predicate just checks to see that there is an element in the list that can be unified without actually unifying it. In SWI Prolog this can be done this way:
memberOf(A, [B|_]) :- unifiable(A,B,_).
But I'm not familiar with WIN-PRolog so don't know whether it has a predicate or operator which only tests whether arguments can be unified.

Resources