Related
edge is a :- dynamic edge/2
the edge indicates only if the vertex are joined, example:
edge(a, b).
edge(c, d).
edge(r, c).
edge(c, t).
edge(a, t).
And I want to know if a vertex have 3 or more edges but only one of them, if there are more than one with 3 or more should return no.
Thanks
In SWI Prolog:
test() :-
findall([A,B], edge(A,B), VRaw), % find every vertex.
flatten(VRaw, VFlat), % make a flat list of them.
msort(VFlat, VSorted), % sort them.
clumped(VSorted, VClumped), % count how many of each.
include([_-C]>>(C>=3), VClumped, V3), % filter the ones with count>=3.
length(V3, 1). % was there exactly one?
Another possible solution:
unique_vertex_with_three_or_more_edges(V) :-
setof(V, vertex_with_three_or_more_edges(V), [V]).
vertex_with_three_or_more_edges(V) :-
setof(W, (edge(V,W) ; edge(W,V)), [_,_,_|_]).
Example:
?- time(unique_vertex_with_three_or_more_edges(X)).
% 78 inferences, 0.000 CPU in 0.000 seconds (?% CPU, Infinite Lips)
X = c.
?- time(unique_vertex_with_three_or_more_edges(c)).
% 35 inferences, 0.000 CPU in 0.000 seconds (?% CPU, Infinite Lips)
true.
?- time(unique_vertex_with_three_or_more_edges(a)).
% 33 inferences, 0.000 CPU in 0.000 seconds (?% CPU, Infinite Lips)
false.
I am new to this language and am having trouble coming up with a solution to this problem. The program must implement the following cases.
Both variables are instantiated:
pivot( [1,2,3,4,5,6,7], [5,6,7,4,1,2,3] ).`
yields a true/yes result.
Only Before is instantiated:
pivot( [1,2,3,4,5,6], R ).
unifies R = [4,5,6,1,2,3] as its one result.
Only After is instantiated:
pivot(L, [1,2]).
unifies L = [2,1] as its one result.
Neither variable is instantiated:
pivot(L, R).
is undefined (since results are generated arbitrarily).
If by pivot, you mean to split the list in 2 and swap the halves, then something like this would work.
First, consider the normal case: If you have an instantiated list, pivoting it is trivial. You just need to
figure out half the length of the list
break it up into
a prefix, consisting of that many items, and
a suffix, consisting of whatever is left over
concatenate those two lists in reverse order
Once you have that, everything else is just a matter of deciding which variable is bound and using that as the source list.
It is a common Prolog idiom to have a single "public" predicate that invokes a "private" worker predicate that does the actual work.
Given that the problem statement requires that at least one of the two variable in your pivot/2 must be instantiated, we can define our public predicate along these lines:
pivot( Ls , Rs ) :- nonvar(Ls), !, pivot0(Ls,Rs) .
pivot( Ls , Rs ) :- nonvar(Rs), !, pivot0(Rs,Ls) .
If Ls is bound, we invoke the worker, pivot0/2 with the arguments as-is. But if Ls is unbound, and Rs is bound, we invoke it with the arguments reversed. The cuts (!) are there to prevent the predicate from succeeding twice if invoked with both arguments bound (pivot([a,b,c],[a,b,c]).).
Our private helper, pivot0/2 is simple, because it knows that the 1st argument will always be bound:
pivot0( Ls , Rs ) :- % to divide a list in half and exchange the halves...
length(Ls,N0) , % get the length of the source list
N is N0 // 2 , % divide it by 2 using integer division
length(Pfx,N) , % construct a unbound list of the desired length
append(Pfx,Sfx,Ls) , % break the source list up into its two halves
append(Sfx,Pfx,Rs) % put the two halves back together in the desired order
. % Easy!
In swi-prolog:
:- use_module(library(dcg/basics)).
pivot_using_dcg3(Lst, LstPivot) :-
list_first(Lst, LstPivot, L1, L2, IsList),
phrase(piv3_up(L1), L1, L2),
% Improve determinism
(IsList = true -> ! ; true).
piv3_up(L), string(Ri), string(M), string(Le) --> piv3(L, Le, M, Ri).
piv3([], [], [], Ri) --> [], remainder(Ri).
piv3([_], [], [H], Ri) --> [H], remainder(Ri).
piv3([_, _|Lst], [H|T], M, Ri) --> [H], piv3(Lst, T, M, Ri).
% From 2 potential lists, rearrange them in order of usefulness
list_first(V1, V2, L1, L2, IsList) :-
( is_list(V1) ->
L1 = V1, L2 = V2,
IsList = true
; L1 = V2, L2 = V1,
(is_list(L1) -> IsList = true ; IsList = false)
).
Is general and deterministic, with good performance:
?- time(pivot_using_dcg3(L, P)).
% 18 inferences, 0.000 CPU in 0.000 seconds (88% CPU, 402441 Lips)
L = P, P = [] ;
% 8 inferences, 0.000 CPU in 0.000 seconds (86% CPU, 238251 Lips)
L = P, P = [_] ;
% 10 inferences, 0.000 CPU in 0.000 seconds (87% CPU, 275073 Lips)
L = [_A,_B],
P = [_B,_A] ;
% 10 inferences, 0.000 CPU in 0.000 seconds (94% CPU, 313391 Lips)
L = [_A,_B,_C],
P = [_C,_B,_A] ;
% 12 inferences, 0.000 CPU in 0.000 seconds (87% CPU, 321940 Lips)
L = [_A,_B,_C,_D],
P = [_C,_D,_A,_B] ;
% 12 inferences, 0.000 CPU in 0.000 seconds (86% CPU, 345752 Lips)
L = [_A,_B,_C,_D,_E],
P = [_D,_E,_C,_A,_B] ;
% 14 inferences, 0.000 CPU in 0.000 seconds (88% CPU, 371589 Lips)
L = [_A,_B,_C,_D,_E,_F],
P = [_D,_E,_F,_A,_B,_C] ;
?- numlist(1, 5000000, P), time(pivot_using_dcg3(L, P)).
% 7,500,018 inferences, 1.109 CPU in 1.098 seconds (101% CPU, 6759831 Lips)
The performance could be improved further, using difference lists for the final left-middle-right append, and cuts (sacrificing generality).
I have several dynamic facts in Prolog and I want to shuffle them (reorder in random order). Is there any way in Prolog how to do this?
:- dynamic max/3.
max(1,2,3).
max(1,5,6).
max(3,4,5).
max(2,2,5).
Possible random order:
max(2,2,5).
max(1,2,3).
max(3,4,5).
max(1,5,6).
As you mention that you're using SWI-Prolog, a possible solution is to use its nth_clause/3 and clause/3 built-in predicates. The idea is to access the predicate using a proxy predicate, ramdom_max/3 in this case. I'm also assuming that you only have facts.
:- use_module(library(lists)).
:- use_module(library(random)).
ramdom_max(A, B, C) :-
predicate_property(max(_,_,_), number_of_clauses(N)),
numlist(1, N, List),
random_permutation(List, Permutation),
member(Index, Permutation),
nth_clause(max(_,_,_), Index, Ref),
clause(max(A,B,C), _, Ref).
Sample call:
?- ramdom_max(A, B, C).
A = 1,
B = 2,
C = 3 ;
A = 3,
B = 4,
C = 5 ;
A = 1,
B = 5,
C = 6 ;
A = B, B = 2,
C = 5.
Each call to the ramdom_max/3 predicate will give you a different clause random order but still enumerating all the clauses on backtracking.
This, however, is a relatively computationally costly solution. But as max/3 is a dynamic predicate the first goals in the body of the ramdom_max /3 clause cannot be optimized to run only once. Let's check the number of inferences:
% autoload the time/1 library predicate:
?- time(true).
% 3 inferences, 0.000 CPU in 0.000 seconds (60% CPU, 333333 Lips)
true.
?- time(ramdom_max(A, B, C)).
% 42 inferences, 0.000 CPU in 0.000 seconds (85% CPU, 913043 Lips)
A = 3,
B = 4,
C = 5 ;
% 6 inferences, 0.000 CPU in 0.000 seconds (69% CPU, 272727 Lips)
A = 1,
B = 2,
C = 3 ;
% 4 inferences, 0.000 CPU in 0.000 seconds (69% CPU, 222222 Lips)
A = 1,
B = 5,
C = 6 ;
% 6 inferences, 0.000 CPU in 0.000 seconds (70% CPU, 250000 Lips)
A = B, B = 2,
C = 5.
It's worth to compare with luker's suggestion in the comments regrading using findall/3. A possible implementation is:
ramdom_max(A, B, C) :-
findall(max(A,B,C), max(A,B,C), Clauses),
random_permutation(Clauses, Permutation),
member(max(A,B,C), Permutation).
Timed call:
?- time(ramdom_max(A, B, C)).
% 40 inferences, 0.000 CPU in 0.000 seconds (78% CPU, 930233 Lips)
A = 1,
B = 5,
C = 6 ;
% 2 inferences, 0.000 CPU in 0.000 seconds (50% CPU, 200000 Lips)
A = 1,
B = 2,
C = 3 ;
% 2 inferences, 0.000 CPU in 0.000 seconds (45% CPU, 250000 Lips)
A = B, B = 2,
C = 5 ;
% 4 inferences, 0.000 CPU in 0.000 seconds (62% CPU, 250000 Lips)
A = 3,
B = 4,
C = 5.
Performance is about the same in this very limited testing. But it's also a simpler and more portable solution. Knowing a bit more about the problem you want to solve would likely allow better solutions, however.
I'm struggling with the following problem, partition a set into n subsets using prolog.
So for example, I give as input to program: X = [1,2,3,4], N=3 and I get
Res = [[1,2], [3], [4]]
Res = [[1,3], [2], [4]]
Res = [[1,4], [2], [3]]
Res = [[2,3], [1], [4]]
Res = [[2,4], [1], [3]]
Res = [[3,4], [1], [2]]
or I give as input: X = [1,2,3,4], N=2 and I get
Res = [[1,2], [3,4]]
Res = [[1,3], [2,4]]
Res = [[1,4], [2,3]]
Res = [[1,2,3], [4]]
Res = [[1,2,4], [3]]
Res = [[1,3,4], [2]]
Res = [[2,3,4], [1]]
This answer extends
#lurker's previous answer with additional (redundant) constraints.
Using dcg we define the following auxiliary non-terminals:
same_length([]) --> []. % DCG-style same_length/2
same_length([_|Es]) --> [_], same_length(Es).
same_length1([_|Es]) --> [_], same_length(Es).
same_lengths1([]) --> [].
same_lengths1([Es|Ess]) --> same_length1(Es), same_lengths1(Ess).
We utilize these DCGs by adding a phrase/2 goal upfront:
list_partitionedNU(Es, Xss) :-
phrase(same_lengths1(Xss), Es),
list_partitioned(Es, Xss).
Do we still get reasonable answers for some vanilla test case?
?- list_partitionedNU([a,b,c], Xss).
Xss = [[a],[b],[c]]
; Xss = [[a],[b,c]]
; Xss = [[a,b],[c]]
; Xss = [[a,c],[b]]
; Xss = [[a,b,c]]
; false.
Sure looks okay to me.
Next, let's talk about universal termination. Goals like list_partitioned(Es, [[a,b,c]]) do not terminate universally—even though they are trivial. list_partitionedNU/2 fixes this:
?- list_partitioned(Es, [[a,b,c]]).
Es = [a,b,c]
; NONTERMINATION
?- list_partitionedNU(Es, [[a,b,c]]).
Es = [a,b,c]
; false. % terminates universally
These additional constraints can speedup some queries considerably.
Using SICStus Prolog 4.4.0:
| ?- use_module(library(between), [numlist/3]).
yes
| ?- numlist(1, 14, _Es),
length(_Xss, 10),
member(P_2, [list_partitioned,list_partitionedNU]),
call_time((call(P_2,_Es,_Xss), false ; true), T_msec).
P_2 = list_partitioned , T_msec = 29632 ? ;
P_2 = list_partitionedNU, T_msec = 600 ? ; % 40x faster
no
Alright! Of course, the speedup depends on the actual lengths of the lists used... YMMV:)
The problem is already mostly solved in this question: All Partitions of a List In Prolog. This was easy to find just doing a Google search on "Prolog partition set".
Then you can just constrain it with length/2:
partitions_of_length(List, N, Partition) :-
length(Partition, N), list_partitioned(List, Partition).
| ?- partitions_of_length([a,b,c,d], 2, L).
L = [[a,b,c],[d]] ? ;
L = [[a,b,d],[c]] ? ;
L = [[a,b],[c,d]] ? ;
L = [[a,c,d],[b]] ? ;
L = [[a,c],[b,d]] ? ;
L = [[a,d],[b,c]] ? ;
L = [[a],[b,c,d]] ? ;
no
| ?-
We optimize performance in this case by constraining the length first. Below illustrates, in SWI Prolog, the difference between constraining the length after versus before:
:- use_module(library(statistics)).
6 ?- time((list_partitioned([a,b,c,d], P), length(P, 2))).
% 18 inferences, 0.000 CPU in 0.000 seconds (85% CPU, 1580195 Lips)
P = [[a, b, c], [d]] ;
% 12 inferences, 0.000 CPU in 0.000 seconds (88% CPU, 1059696 Lips)
P = [[a, b, d], [c]] ;
% 10 inferences, 0.000 CPU in 0.000 seconds (86% CPU, 900414 Lips)
P = [[a, b], [c, d]] ;
% 19 inferences, 0.000 CPU in 0.000 seconds (88% CPU, 1624070 Lips)
P = [[a, c, d], [b]] ;
% 10 inferences, 0.000 CPU in 0.000 seconds (86% CPU, 1021555 Lips)
P = [[a, c], [b, d]] ;
% 19 inferences, 0.000 CPU in 0.000 seconds (87% CPU, 1665060 Lips)
P = [[a, d], [b, c]] ;
% 19 inferences, 0.000 CPU in 0.000 seconds (87% CPU, 1661420 Lips)
P = [[a], [b, c, d]] ;
% 37 inferences, 0.000 CPU in 0.000 seconds (90% CPU, 2382639 Lips)
false.
7 ?- time((length(P, 2), list_partitioned([a,b,c,d], P))).
% 13 inferences, 0.000 CPU in 0.000 seconds (89% CPU, 1175832 Lips)
P = [[a, b, c], [d]] ;
% 6 inferences, 0.000 CPU in 0.000 seconds (83% CPU, 742023 Lips)
P = [[a, b, d], [c]] ;
% 6 inferences, 0.000 CPU in 0.000 seconds (85% CPU, 848896 Lips)
P = [[a, b], [c, d]] ;
% 9 inferences, 0.000 CPU in 0.000 seconds (84% CPU, 1210328 Lips)
P = [[a, c, d], [b]] ;
% 6 inferences, 0.000 CPU in 0.000 seconds (82% CPU, 828386 Lips)
P = [[a, c], [b, d]] ;
% 9 inferences, 0.000 CPU in 0.000 seconds (84% CPU, 1215723 Lips)
P = [[a, d], [b, c]] ;
% 9 inferences, 0.000 CPU in 0.000 seconds (90% CPU, 697999 Lips)
P = [[a], [b, c, d]] ;
% 10 inferences, 0.000 CPU in 0.000 seconds (86% CPU, 991277 Lips)
false.
If you were to modify the code in the link above to constrain the length of the list, the best way is probably to put the length/2 call inside the predicate before doing anything else, but the behavior is identical then to the above.
TL;DR: This question is about one particular aspect of evaluating candidate failure-slices.
The following code of ancestor_of/2 expresses the transitive-closure of child_of/2:
ancestor_of(X, Y) :-
child_of(Y, X).
ancestor_of(X, Z) :-
child_of(Z, Y),
ancestor_of(X, Y).
If we define child_of/2 and include several cycles ...
child_of(xx, xy).
child_of(xy, xx).
child_of(x, x).
... ancestor_of(X, Y) does not terminate universally:
?- ancestor_of(X, Y), false.
**LOOPS**
With SWI-Prolog, we can limit the amount of work invested in the execution of the query:
?- time(call_with_inference_limit((ancestor_of(_,_),false), 10000, R)).
% 10,008 inferences, 0.002 CPU in 0.002 seconds (100% CPU, 4579243 Lips)
R = inference_limit_exceeded ;
% 5 inferences, 0.000 CPU in 0.000 seconds (85% CPU, 235172 Lips)
false.
Alright, but it could be better!
First, we might be able to prove definitely that the goal loops.
Second, we might be able to do so with less effort.
Let's add an additional argument to ancestor_of/2 for transferring call stack information!
ancestor_of_open(X, Y, Open) :-
G = ancestor_of(X,Y),
( member(G, Open)
-> throw(loop(G,Open))
; ancestor_of_aux(X, Y, [G|Open])
).
ancestor_of_aux(X, Y, _Open) :-
child_of(Y, X).
ancestor_of_aux(X, Z, Open) :-
child_of(Z, Y),
ancestor_of_open(X, Y, Open).
Sample query:
?- time(ancestor_of_open(X,Y,[])).
% 4 inferences, 0.000 CPU in 0.000 seconds (92% CPU, 219696 Lips)
X = xy,
Y = xx ;
% 1 inferences, 0.000 CPU in 0.000 seconds (79% CPU, 61839 Lips)
X = xx,
Y = xy ;
% 1 inferences, 0.000 CPU in 0.000 seconds (79% CPU, 61084 Lips)
X = Y, Y = x ;
% 8 inferences, 0.000 CPU in 0.000 seconds (87% CPU, 317473 Lips)
X = Y, Y = xx ;
% 11 inferences, 0.000 CPU in 0.000 seconds (90% CPU, 262530 Lips)
ERROR: Unhandled exception: loop(ancestor_of(_G282,xx),[ancestor_of(_G282,xy),ancestor_of(_G282,xx)])
Is this it?! That was too easy. Does this cover the general case?
I feel like I'm missing something important, but I can't quite point my finger at it. Please help!