Facts VIEW, like a SQL VIEW? - view

I have facts stored in different formats f.e.:
fact(a,b,c)
fact(d,e,f(g,h))
fact(j(k,l),m,n(o,p,q))
...
.. always triple.
I want to create a VIEW of the facts by only seeing the functor i.e.
fact(a,b,c)
fact(d,e,f)
fact(j,m,n)
...
how do you do that .. ?
.. of course i want to be able to query them as normal facts ... omitting the hidden structure of-course (it will be interesting to take the hidden structure into account, but lets not complicate things for now)
PS>
In general the most important thing is that the fact is a triple .. in the future I may change the possible structure of the items, but I want to be able to have simplified views where it is a triple. Any ideas along these lines are welcome.

factview(fact(A, B, C)) :-
fact(Af, Bf, Cf),
functor(Af, A, _),
functor(Bf, B, _),
functor(Cf, C, _).
Gives
?- factview(X).
X = fact(a, b, c) ;
X = fact(d, e, f) ;
X = fact(j, m, n).

A more generic approach for SWI-Prolog:
fact(a,b,c).
fact(d,e,f(g,h)).
fact(j(k,l),m,n(o,p,q)).
view(Predicate/Arity) :-
functor(Head, Predicate, Arity),
forall( clause(Head, true),
( compound_name_arguments(Head, Predicate, Arguments),
maplist([A,F]>>functor(A,F,_), Arguments, Functors),
compound_name_arguments(Fact, Predicate, Functors),
writeln(Fact) ) ).
Query:
?- view(fact/3).
fact(a,b,c)
fact(d,e,f)
fact(j,m,n)
true.

Related

How can I unify this list instead of just adding more variables to it?

I'm doing a project in college and I'm trying to use Prolog, in this case I have to run trough the elements of the list three by three, but I've not been successful at unifying the list with the correct variables (X, Y, Z) and my program keeps adding more and more variables to the list.
aplica_R1_fila_aux(Fila, N_Fila) :-
copia(Fila, N_Fila).
aplica_R1_fila_aux(Fila, [X,Y,Z|T]) :-
aplica_R1_Triplo([X,Y,Z], F),
aplica_R1_fila_aux(Fila, T).
This code it should copy the list Fila to N_Fila then unify [X,Y,Z|T] with N_Fila and change the list but instead it just keeps adding variables to N_Fila.
The main trick you need to make this work is that you can use call/N with varying numbers of arguments. So once you have peeled off X, Y and Z, you can obtain the result of your Goal against them with call(Goal, X, Y, Z, Result).
There are several ways to do this, but I would prefer to just make three sublists and recur on all three of them. When the rightmost one is exhausted, you are done recurring. This gives you fewer base cases to worry about (lists with no, one or two elements do not need to be handled separately) and there are no cuts so your code will wind up looking like this:
map3(Goal, [X,Y,Z|L], Solutions) :-
map3(Goal, [X,Y,Z|L], [Y,Z|L], [Z|L], Solutions).
map3(_, _, _, [], []).
map3(Goal, [X|XR], [Y|YR], [Z|ZR], [R|Rest]) :-
call(Goal, X, Y, Z, R),
map3(Goal, XR, YR, ZR, Rest).
This could also be solved without the helper predicate, but there was something that offended me about it and this really shouldn't be much worse in terms of expense, so this is the way I went.
With a dummy goal of foo(X,Y,Z, foo(X,Y,Z)), I got this example query and result:
?- map3(foo, [a,b,c,d,e,f], Result).
Result = [foo(a, b, c), foo(b, c, d), foo(c, d, e), foo(d, e, f)] ;
false.
I think this is basically what you are trying to get, let me know if I can clarify anything.

How to compare elements in dynamic

I have two dynamics of /2.
One of the lists, lets call it D2 has set values inside of it. For example: 2 and 3, 4 and 5.
How can I check if my dynamic 1 aka. D1 has all the values inside of it that D2 has and then return true if it does?
I tried to use
member(E, D1(_,_)), member(E, D2(_, _)). So far but without much luck.
This is pretty icky as far as data models go and whatever it is you're trying to do with this is going to at least be inefficient, if it can even be made to work. You'd be far better off defining an arity 3 fact with the first arg being an atom that identifies the type.
That said, you can probably do enough introspection to handle it.
dif(Q, P),
predicate_property(QR, dynamic),
predicate_property(PR, dynamic),
QR =.. [Q, _, _],
PR =.. [P, _, _].
This says, find me two predicates with arity 2, whose heads are different. Ideally, you want just the user-defined predicates. SWI-Prolog cannot do this, but GNU Prolog can, you could add some extra constraints:
predicate_property(QR, user),
predicate_property(PR, user),
This is my solution:
matching(Q, P) :-
dif(Q, P), % different predicates, please
predicate_property(QR, dynamic), % both dynamic
predicate_property(PR, dynamic),
QR =.. [Q, Q1, Q2], % arity-2 predicates, please
PR =.. [P, P1, P2],
findall([Q1, Q2], clause(QR, true), Qs), % find all facts (:- true)
findall([P1, P2], clause(PR, true), Ps),
forall(member(PV, Ps), member(PV, Qs)), % ensure the fact sets are equal
forall(member(QV, Qs), member(QV, Ps)).
Please, please, please DO NOT DO THIS!

accessing program listing in prolog

I'm having some strange (or not so strange) problems defining variables in SWI-Prolog. Example:
I'd like to do something like below:
:- initialization(main).
main :-
X = listing(main),
write(X).
but it's simply printing "listing(main)"
maybe, using another casual predicate instead of main/0...
?- with_output_to(atom(X), listing(pattern)), write(X).
gram:pattern(A, B, C) :-
dig(A, B, C).
gram:pattern(A+C, B, E) :-
ten(A, B, D),
dig(C, D, E).
...
What you are doing with X = listing(...) is creating a term, which later you are printing with write.
It seems you want to access the code of main. The thing you are looking for is clause/2:
clause(:Head, ?Body)
True if Head can be unified with a clause head and Body with the corresponding clause body. Gives alternative clauses on backtracking. For facts, Body is unified with the atom true.
Example:
main :- clause(main, X), write(X).
?- main.
clause(main,_G2381),write(_G2381)
true.

Prolog : eliminating cycles from indirect relation

I have a list of user facts defined as:
user(#michael).
user(#ana).
user(#bob).
user(#george).
user(#john).
and so on. Furthermore, I have a set of facts as:
follows(#michael,#ana).
follows(#ana,#bob).
follows(#bob,#michael).
I am trying to write a relation indirect(user1,user1) which will tell me if user1 indirectly follows user2.
However, I am not able to do away with cyclic relations.
Like in the given example, michael -> ana -> bob -> michael will cause a cycle.
What is the best way to eliminate these cycles from the result of indirect(user1,user2)?
You can make a rule that passes an extra list of users that you have "seen" so far, and ignore follows originating from these users: follows(A, B, Seen).
To do that, define a "follow transitive" rule that wraps the actual rule, like this:
follows_tx(A, B) :- follows(A, B, []).
Now you can define follows/3 rule this way:
follows(A, B, Seen) :-
not_member(B, Seen),
follows(A, B).
follows(A, B, Seen) :-
follows(A, X),
not_member(X, Seen),
follows(X, B, [A|Seen]).
The base clause says that if there is a fact about A following B, we consider the predicate proven as long as we have not seen B before.
Otherwise, we find someone who follows A, check that we have not seen that user yet by checking not_member/2, and finally see if that user follows B, directly or indirectly.
Finally, here is how you can define not_member:
not_member(_, []).
not_member(X, [H|T]) :- dif(X, H), not_member(X, T).
Demo.
indirect( A0,A) :-
closure(follows, A0,A).
See for a definition of closure/3.

Split list on given element

I have a list C and I want to split the list using the element c in the list.
The expected results are as example:
?- split([a,c,a,a,c,a,a,a],X).
X = [[a],[a,a],[a,a,a]].
Can anybody help? Thanks in advance.
I can remove the c in the list now and here is my codes.
split([],[]).
split([H|T],[H|S]) :- H=a,split(T,S).
split([H|T],S) :- H=c,split(T,S).
Your "remove c" predicate would look better like this:
remove_c([c|T], S) :-
remove_c(T, S).
remove_c([a|T], [a|S]) :-
remove_c(T, S).
This still only works for lists that have only c and a in them.
If you want to "split", this means you at least need another argument, to collect the a's between the c's. For example:
split_on_c(List, Split) :-
split_on_c_1(List, Split, []).
split_on_c_1([], [Acc], Acc).
split_on_c_1([c|Rest], [Acc|Split], Acc) :-
split_on_c_1(Rest, Split, []).
split_on_c_1([a|Rest], Split, Acc) :-
split_on_c_1(Rest, Split, [a|Acc]).
Again, this expects lists of a and c only. It could also be done in different ways, but this is a start.
While learning a language you need to get accomplished to common abstractions already established (in simpler terms, use libraries). What about
split(In, Sep, [Left|Rest]) :-
append(Left, [Sep|Right], In), !, split(Right, Sep, Rest).
split(In, _Sep, [In]).
to be used like
?- split([a,c,a,a,c,a,a,a],c,R).
R = [[a], [a, a], [a, a, a]].
Use the meta-predicate splitlistIf/3 together with reified term equality
(=)/3, like this:
Here is the query the OP gave in the question:
?- splitlistIf(=(c),[a,c,a,a,c,a,a,a],Xs).
Xs = [[a],[a,a],[a,a,a]].
Note that above code is monotone, so the following query gives reasonable results:
?- splitlistIf(=(X),[Y,X,Y,Y,X,Y,Y,Y],Xs), Y = a, X = c.
X = c,
Y = a,
Xs = [[a],[a, a],[a, a, a]].

Resources