What do these predicates do in Prolog - prolog

I don't understand what exactly these following 4 predicates do:
predicate1([H1,H2|T1],X) :−
append([H1,H2|T1],[H2,H1|T1],X).
predicate2wrapper(In, Out) :-
predicate2([ ], In, Out).
predicate2(L, [ ], L).
predicate2(A,[H| T], Out) :-
predicate2([H,H|A],T, Out).
predicate3([X,X], [X,X|_]).
predicate3([X,X], [_,H|T]) :−
predicate3([X,X],[H|T]).
predicate4([ ], _) .
predicate4([H|T], L) :−
member(H,L),
predicate4(T,L).
I know that all these predicates take lists as their argument(s) and I also tried to run them but I always get a Syntax error: operator expected warning.
Could someone please help me understand what these predicates do and maybe also help me fix this error?

Did you copy this from a pdf or a word-document? The --signs in your :- are not minus signs - this is causing the error. Retype them to solve the issue and then you can analyze the predicates. How to know if chars looking the same are not the same? I would suggest using a diff tool (a program to compare files, as command line or with a gui (winmerge), even available online) or an ascii to hex converter like this.
Example queries which give you a hint what these predicates do:
?- predicate1([1,2,3],L).
?- append([1,2,3],[4,5],L).
?- predicate2wrapper([1,2,3],L).
?- predicate3([c,c],[a,a,b,b]).
?- predicate3([b,b],[a,a,b,b,c,c]).
?- predicate3([X,X],[a,a,c,b,b]).
?- predicate4([a,b],[a,c,b]).
?- predicate4([a,d],[a,c,b]).
?- member(a,[a,c,b]).
?- member(d,[a,c,b]).

Related

Prolog - How to set timestamp as an argument in a predicate?

Is there any way to use get_time(T) [which is built-in function] as an argument when I assert new facts to DB?
(I just want to compare between facts assertion time).
Code:
:- dynamic start/2.
start_interval(A) :- start(A, _), !, false.
start_interval(A) :- assert(start(A, get_time(T))).
Run Example:
Warning: c:/users/*****/desktop/prolog/4.pl:6:
Warning: Singleton variables: [T]
Welcome to SWI-Prolog (threaded, 64 bits, version 8.2.1)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. For legal details.
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- start_interval(1).
true.
?- start_interval(2).
true.
?- listing(start).
:- dynamic start/2.
start(1, get_time(_)).
start(2, get_time(_)).
true.
?- get_time(T).
T = 1598718310.038124.
Instead of "start(#, get_time(_))", I would like to get to timestamp, which was made when I called start_interval(Num) at first.
(You can see also the output of get_time(T) when I call it)
Is it possible?
Maybe there is another way to compare between facts assertion time?
You just have to actually call (whatever is behind) the get_time(T) expression (nominally a predicate, but not really, as its behaviour depends on the exact moment at which it is called. Very non-logical: we are in the real of I/O).
As you write it, it remains an un-called syntactic element, standing literally for itself.
(Also, use assertz/1 in preference to the oldish assert/1):
So:
:- dynamic start/2.
start_interval(A) :- start(A, _), !, false.
start_interval(A) :- get_time(T), assertz(start(A, T)).
Then:
?- start_interval(1).
true.
?- start(A,T).
A = 1,
T = 1598726506.9420764.

`multifile` in combination with semweb `rdf_meta` for prefix processing in a predicate

SWI-prolog version: threaded, 64 bits, version 7.6.4
OS: Ubuntu bionic 18.04
Still working on learning prolog and ran into an interesting situation. I would like to use a predicate that is 'asserted' over multiple files (just makes the code look a little cleaner in organization), but that predicate also needs to be able to process rdf prefixes as part of the semweb package and it does not seem to work.
Here is a code block that might show the problem:
:- module(multifile1,
[
test/2
]
).
:- use_module(library(semweb/rdf_db)).
:- use_module(library(semweb/rdfs)).
:- multifile
multifile1:bar/1,
multifile1:foo/1.
:- rdf_meta
test(-, r),
foo(r).
test(bar, X) :-
bar(X).
test(foo, X) :-
foo(X).
multifile1:bar(abc) :-
format('bar: abc~n', []).
foo(rdf:about) :-
format('foo: rdf:about~n', []).
And asserting the same foo in another file:
:- module(multifile2,
[
]
).
:- use_module(library(semweb/rdf_db)).
:- use_module(library(semweb/rdfs)).
:- multifile
multifile1:foo/1.
:- rdf_meta
multifile1:foo(r).
multifile1:foo(rdf:type) :-
format('rdf:type~n', []).
In this form calling test(foo, rdf:about) works, but asserting test(foo, rdf:type) does not work. Is rdf_meta and multifile not supposed to work together or there is a bug in this code?
PS: I had added the multifile bar to make sure that works over multiple files.
I think I figured out. multifile and rdf_meta do work together. The bug in the code was related to the fact that I had defined foo in rdf_meta as foo(r). I think that expansion was causing confusion at compile time with regards to pattern match. Changing the definition to foo(-) fixed the problem. Hope this helps someone in the future.

How do you get only one output from a swi-prolog query?

How do I get only one output from a SWI-Prolog query? I have tried using cut (!) but it does not seem to work.
For example:
I already filled my knowledge base up with statements and I wanted to find any one name who is both female and is the mother of someone.
I have already tried:
mother(X,Y), female(X).
...but that gives me all of the X-__ and Y-__
I have also tried:
mother(X,Y), female(X), !.
... but that still gives me both the X-__ and Y__
I only want to find the X. Does anyone have any tips for me to somehow only get one?
?- setof(t, Y^ ( mother(X, Y), female(Y) ), _).
which will remove duplicates (redundant answers/solutions), too. Or using library(lambda):
?- X+\ ( mother(X, Y), female(Y) ).
which does not remove redundant answers.

How to merge lists in PROLOG?

I need to merge two lists L1=[1,2,3] and L2=[a,b] like this: M=[1,a,2,b,3].
How can I do it in PROLOG please?
you can try
m2([A|As], [B|Bs], [A,B|Rs]) :-
!, m2(As, Bs, Rs).
m2([], Bs, Bs) :- !.
m2(As, [], As).
You may look at this link: Prolog program to merge two ordered lists
This will not give you the output you need, but it is a start.
After some tries, here is the correct answer, much simple than the original proposed by me (tested and working).
mergelist_alternate([],[],[]).
mergelist_alternate([X],[],[X]).
mergelist_alternate([],[Y],[Y]).
mergelist_alternate([X|List1],[Y|List2],[X,Y|List]) :- mergelist_alternate(List1,List2,List).
You can call it like this:
mergelist_alternate([1,2,3],[a,b],L),!.
merge_list([],L,L ).
merge_list([H|T],L,[H|M]):-
merge_list(T,L,M).
It will work. 100% tested!
Input: merge_list([1,2],[3,4],M).
Output: M=[1,2,3,4].

Compare two atoms in Prolog

I have been learning prolog.. I'm using a editor named prol1.1.1 I need to write rule to compare 2 strings, when i give something like
rel(a1,b1).
rel(a2,b2).
rel(b2,c2).
associatedWith(X,Y,Z) :- rel(X,Y),rel(Y,Z).
?- associatedWith(X,Y,Z).
it works
but when i give
?- associatedWith(X,Y,Z),X=\=Z.
i get parser exception
Parser exception [Should be evaluable ''a2''[7:31]] line 7:31
what i got from websites is =\= is for numeric values, i wasn't able to get answer for comparing string values.. can anyone help me..
and i wasn't able to get gui for swi-prolog can u please help me with that too?
i need to use the call prolog from java program and the output has to be again processed in java, can anyone please help me..
You are trying to compare atoms, not strings. Anyways, you need \=
?- aaa = aaa.
true.
?- aaa \= aaa.
false.
?- aaa \= aab.
true.

Resources