Automatic results showing?
Asked Answered
F

4

6

How can I make SWI-Prolog interpreter to automatically do a semicolon? I have a lot of results (about 300) due to backtracking and I don't want to push semicolon for all of them.

I do NOT want a list of all solutions, I only want not to push semicolon or space so I can leave the program printing backtracked solutions on background.

Flexuous answered 23/1, 2014 at 16:3 Comment(3)
possible duplicate of How do I find all solutions to a goal in Prolog?Predicable
I believe the prolog manual for your prolog interpreter describes various options you have at the "solution prompt".Shattuck
It is NOT duplicated. I don't want to make a list of solutions. I only want an automatic semicolon.Flexuous
H
3

You can manually emit solutions (using for example write/1 or format/2), and force backtracking with false to see all solutions. For example:

?- solution(S), writeln(S), false.

In addition, for example in SWI-Prolog, you can simply press SPACE instead of ; for further solutions.

Hydrosol answered 23/1, 2014 at 16:7 Comment(6)
Using the ISO Prolog built-in control construct fail/0 will be a bit more clear in this context (although false/0 was also recently standardized by ISO).Mclellan
I'm not sure how to implement this. This is what I got agrupacion_compatible_de_asignaturas(C,P) :- findall(A, lista_de_clase(C,A,_), J), setof(T, (subseq0(J,T), not(T=[]), not(grupo_incompatible(T))), Y), subseq0(Y,P), flatten(P,U), is_set(U), permutation(U,J).Flexuous
I got it now. This is not the ideal solution but it solves the issue pretty well.Flexuous
@Javier: As a matter of habit: Do use writeq/1 to write out general Prolog terms. Do not use write or writeln. They garble up some terms.Shin
Great to know that. Do you know any particular case when that might happen?Flexuous
@Javier: Always if something has to be quoted. Think of T = 'a b'Shin
F
3

@repeat Not sure if this would fit your criteria but could you not develop a meta interpreter ? I am not sure if there is a way to load a mi so that all top level queries go through it?

So something like:

mi1(true).
mi1((A,B)) :-
 mi1(A),
 mi1(B).
mi1(Goal) :-
 Goal \= true,
 Goal \= (_,_),
 Goal =..List,
 maplist(newvar,List,NewList),
 Goal2 =..NewList,
 clause(Goal2, Body),
 List=[_,T],!,
 findnsols(5,I,(Goal =..[_,I],Goal),T),
 mi1(Body).

newvar(V,V2):-
 var(V).
newvar(V,V):-
 nonvar(V).

%test predicates.
natnum1(0).
natnum1(s(X)) :-
 natnum1(X).

 w(w1).
 w(w2).
 w(w3).
 w(w4).
 w(w5).
 w(w6).
 w(w7).
 w(w8).

Queries:

?- mi1(w(X)).
X = [w1, w2, w3, w4, w5] ;
X = [w6, w7, w8] ;
false.

?- mi1(natnum1(X)).
X = [0, s(0), s(s(0)), s(s(s(0))), s(s(s(s(0))))] ;
X = [s(s(s(s(s(0))))), s(s(s(s(s(s(0)))))), s(s(s(s(s(s(s(...))))))), s(s(s(s(s(s(...)))))), s(s(s(s(s(...)))))] ;
X = [s(s(s(s(s(s(s(s(s(...))))))))), s(s(s(s(s(s(s(s(...)))))))), s(s(s(s(s(s(s(...))))))), s(s(s(s(s(s(...)))))), s(s(s(s(s(...)))))] ;
X = [s(s(s(s(s(s(s(s(s(...))))))))), s(s(s(s(s(s(s(s(...)))))))), s(s(s(s(s(s(s(...))))))), s(s(s(s(s(s(...)))))), s(s(s(s(s(...)))))] 
...

Just showing the basic idea.. this only works for 1 arg predicates..

Fiche answered 20/10, 2015 at 8:33 Comment(7)
There must be a setting in swi prolog as in swish you can do next 10 solutions etc swish.swi-prolog.org/p/so1.swinbFiche
What I have there is a bit of a strange idea because all variables would need to be lists, so all your predicates would then have to work with them which would be quite weird and different!Fiche
Crafty! I was hoping that some prolog-toplevel already has everything needed in place, so I would just have to set the right flag. swish has something like it (but I would need to change the default behavior to "whenever a query is run, at least 5-10 answers are searched for and presented"). Of course, GUPU has done the right thing for at least 20 years...Bayer
if for ?-natnum(X). X gets bound to [0, s(0), s(s(0)), s(s(s(0))), s(s(s(s(0))))], so what would you want to happen to the query like natnum(X),natnum(Y), something(X,Y,Z).Fiche
How do I obtain a copy of GUPU? I have not heard of it before.Fiche
For nat(0). nat(s(X)) :- nat(X). nat_nat_sum(0,X,X). nat_nat_sum(s(X),Y,s(Z)) :- nat_nat_sum(X,Y,Z). I want: ?- nat(X),nat(Y),nat_nat_sum(X,Y,Z). X = Y, Y = Z, Z = 0 ; X = 0, Y = Z, Z = s(0) ; X = 0, Y = Z, Z = s(s(0)) ; X = 0, Y = Z, Z = s(s(s(0))) ; X = 0, Y = Z, Z = s(s(s(s(0)))) ; X = 0, Y = Z, Z = s(s(s(s(s(0))))) ...Bayer
In most Prolog systems, the standard clause/2 predicate can only be used with dynamic predicates...Mclellan
F
3

This is another way which I think is quite nice:

:- op(1200, xfx, all).
:- op(1200, xfx, s5).
:- op(1200, xfx, s10).

all(F,X):-
 F =.. [_|T],
 findall(T, F,X).

s5(F,X):-
 F =.. [_|T],
 findnsols(5,T,F,X).

s10(F,X):-
 F =.. [_|T],
 findnsols(10,T,F,X).

p(1).
p(2).
p(3).
p(4).
p(5).
p(6).
p(7).

nat(0).
nat(s(X)) :- nat(X).
nat_nat_sum(0,X,X).
nat_nat_sum(s(X),Y,s(Z)) :- nat_nat_sum(X,Y,Z).

Q:

 ?- nat(X),nat(Y),nat_nat_sum(X,Y,Z) s5 Sols.
 Sols = [[nat(0),  (nat(0), nat_nat_sum(0, 0, 0))], [nat(0),  (nat(s(0)), nat_nat_sum(0, s(0), s(0)))], [nat(0),  (nat(s(s(0))), nat_nat_sum(0, s(s(0)), s(s(0))))], [nat(0),  (nat(s(s(...))), nat_nat_sum(0, s(s(...)), s(s(...))))], [nat(0),  (nat(s(...)), nat_nat_sum(0, s(...), s(...)))]] ;
 Sols = [[nat(0),  (nat(s(s(s(s(s(...)))))), nat_nat_sum(0, s(s(s(s(s(...))))), s(s(s(s(s(...)))))))], [nat(0),  (nat(s(s(s(s(...))))), nat_nat_sum(0, s(s(s(s(...)))), s(s(s(s(...))))))], [nat(0),  (nat(s(s(s(...)))), nat_nat_sum(0, s(s(s(...))), s(s(s(...)))))], [nat(0),  (nat(s(s(...))), nat_nat_sum(0, s(s(...)), s(s(...))))], [nat(0),  (nat(s(...)), nat_nat_sum(0, s(...), s(...)))]] ;
Sols = [[nat(0),  (nat(s(s(s(s(s(...)))))), nat_nat_sum(0, s(s(s(s(s(...))))), s(s(s(s(s(...)))))))], [nat(0),  (nat(s(s(s(s(...))))), nat_nat_sum(0, s(s(s(s(...)))), s(s(s(s(...))))))], [nat(0),  (nat(s(s(s(...)))), nat_nat_sum(0, s(s(s(...))), s(s(s(...)))))], [nat(0),  (nat(s(s(...))), nat_nat_sum(0, s(s(...)), s(s(...))))], [nat(0),  (nat(s(...)), nat_nat_sum(0, s(...), s(...)))]] .

 ?- p(X) s5 Sols.
 Sols = [[1], [2], [3], [4], [5]] ;
 Sols = [[6], [7]].

The advantage is that you can just add how many answers you want at the end of a query. You then gets lists of that length as answers, so they are not just written to console but can be used for further queries.

Fiche answered 21/10, 2015 at 9:32 Comment(0)
M
2

A possible solution, using the nasty globals predicates found on some Prolog systems with varying names, illustrated here for SWI-Prolog.

chunks_of_size(Size, Goal) :-
    Size1 is Size + 1,
    nb_setval('$chunk_size', Size1),
    nb_setval('$chunk_count', Size),
    call((Goal,chunks)).

chunks :-
    nb_getval('$chunk_count', N),
    N > 0,
    M is N - 1,
    nb_setval('$chunk_count', M),
    nl,
    fail.
chunks :-
    nb_getval('$chunk_count', 0),
    nb_getval('$chunk_size', Size),
    nb_setval('$chunk_count', Size),
    write('-----'),
    chunks.

Usage example:

?- chunks_of_size(3, (between(1, 12, N), write(N))).
1
2
3
-----
4
5
6
-----
7
8
9
-----
10
11
12
-----
false.

If you want to stop for user interaction after each group of solutions, replace the second clause of the chunks/0 predicate by:

chunks :-
    nb_getval('$chunk_count', 0),
    nb_getval('$chunk_size', Size),
    nb_setval('$chunk_count', Size),
    (   write('-----')
    ;   chunks
    ).

With this change you will now get:

?- chunks_of_size(3, (between(1, 12, N), write(N))).
1
2
3
-----
N = 3 ;

4
5
6
-----
N = 6 ;

7
8
9
-----
N = 9 ;

10
11
12
-----
N = 12 ;

false.
Mclellan answered 20/10, 2015 at 14:34 Comment(3)
s(X). Turning the nasties into a force for good is most definitely a "Good Thing™"!Bayer
Could using nb_setarg be an option for getting rid of the "global variable" smell?Bayer
@Bayer Maybe. But it would still stink :-)Mclellan

© 2022 - 2024 — McMap. All rights reserved.