I have been thinking of a solution for finding all the useless states defined in a particular automaton and I know that one approach is to start moving from the start state and then ask for the following state all of these stored in the Prolog predicate database. I have had no luck in writing the code very well because I am learning Prolog. I wish someone could help me out with this. Here I leave what I have.
The finite state machine structure. fa_start -> the initial state, fa_move -> the valid move from one state to another, fa_final -> the final state.
% Start State
:- assert(fa_start(fa_1, s_0)).
% Final States
:- assert(fa_final(fa_1, s_5)).
:- assert(fa_move(fa_1, s_0, s_1, a)).
:- assert(fa_move(fa_1, s_1, s_4, b)).
:- assert(fa_move(fa_1, s_0, s_2, c)).
:- assert(fa_move(fa_1, s_2, s_4, d)).
:- assert(fa_move(fa_1, s_2, s_5, e)).
:- assert(fa_move(fa_1, s_0, s_3, f)).
:- assert(fa_move(fa_1, s_3, s_5, g)).
:- assert(fa_move(fa_1, s_6, s_3, h)).
:- assert(fa_move(fa_1, s_6, s_7, i)).
:- assert(fa_move(fa_1, s_7, s_8, j)).
Now, here is the code I have been writing. The idea is to start with fa_start and then keep moving using valid fa_move until it cannot reach fa_final.
adjacent(fa, N, M):-
fa_move(fa, N, M, _).
adjacent_recursive(fa, N, L):-
fa_start(fa, N),
findall(l,adjacent(fa,N,_),L).
find_paths(fa):-
adjacent_recursive(fa,s_0,_).
Thank you in advance for all the help.
I know it's difficult to find accurate information related to my specific question. I have been working on it and finally found a solution, may it not be the best, but makes the deal. I owe the idea to this site. If you find bugs, it'd be welcome.
Now, the following code prints the useless states given a finite state automata implemented as above.
find_useless_states(FA):- retractall(utiles(_)),retractall(visited(_)),
forall(fa_final(FA,S),assert(utiles(S))),
find_useless_states2(FA).
find_useless_states2(FA):- retract(utiles(S)),
not(visited(S)), assert(visited(S)),
forall((fa_move(FA,Y,S,_), not(visited(Y))),(asserta(utiles(Y)))),
find_useless_states2(FA).
find_useless_states2(_).
difference(L1, L2, R) :- intersection(L1, L2, I),
append(L1, L2, All),
subtract(All, I, R).
find_all_states_as_list(FA,L):- findall(X,fa_move(FA,X,_,_),M),findall(Y,fa_move(FA,_,Y,_),N),merge(M,N,LL),sort(LL,L).
find_useful_states_as_list(L):- findall(X,visited(X),L).
print_useless_states(FA):- find_all_states_as_list(FA,L),find_useful_states_as_list(M), difference(L,M,R), length(R,D),write(R),nl,write(D).
Hope it helps other people. Some code ideas have been used from questions posted here in stackoverflow. I thank the people who answered those.
It is possible to use the dynamic database for all such things, but it easily gets very difficult to maintain. I'd rather compile the file with your definitions, thus avoid to perform assertz/1 manually.
uselessstate(Aut, Usl) :-
setof(S0, S^( closure0(adjacent(Aut), S0,S), fa_final(Aut,S) ), S0s),
setof(t, A^B^( adjacent(Aut, A,B), (Usl=A;Usl=B) ), _),
non_member(Usl, S0s).
unreachable(Aut, Usl) :-
setof(S, S0^( fa_start(Aut, S0), closure0(adjacent(Aut), S0,S) ), Ss),
setof(t, A^B^( adjacent(Aut, A,B), (Usl=A;Usl=B) ), _),
non_member(Usl, Ss).
The definition of closure0/3 and non_member/2 is found in another answer.
Related
The Cousin Explainer
Write a program that when given a person of reference and a degree the program can tell me all of the nth degree cousins that person has. I've started by writing my facts: male/1 female/1 and child/2 these are populated with the names of my family members. I then began writing rules for cousins I figured id write a different rule for every degree so only up to the third cousins. The problems I'm having are as follows.
firstCousin_of(X,Y):-child(X,Z1),child(Y,Z2),child(Z1,Z),child(Z2,Z). I have this to find a first cousin but the 2nd cousin is more complicated which makes me think there has gotta be a way to do this recursively.
I need the rule, all_cousins(Person, Degree, ListOfCousins), which after figuring out all of the nth degree cousins edits a list of all cousins to only include those specific nth degree cousins. I'm used to imperative languages and all i can think about with this is how do I even convey to the rule which people to remove from the list from one rule to another.
lastly I have a rule, all_cousinsRemoved(Person, Degree, removed(Number, Direction), ListOfCousins) that I don't even know where to start with but ill need the all_cousins rule for this one because it does the same thing but also only includes cousins in the edited lists w=that were removed nth times either up or down.
The best solutions is make a several rules that call other rules, here an example
male(dicky).
male(randy).
male(mike).
male(don).
male(elmer).
female(anne).
female(rosie).
female(esther).
female(mildred).
female(greatgramma).
male(blair).
male(god).
female(god).
parent(don,randy).
parent(don,mike).
parent(don,anne).
parent(rosie,randy).
parent(rosie,mike).
parent(rosie,anne).
parent(elmer,don).
parent(mildred,don).
parent(esther,rosie).
parent(esther,dicky).
parent(greatgramma,esther).
parent(randy,blair).
male(mel).
male(teo).
parent(melsr,mel).
parent(melsr,teo).
american(anne).
american(X) :- ancestor(X,anne).
american(X) :- ancestor(anne,X).
relation(X,Y) :- ancestor(A,X), ancestor(A,Y).
father(X,Y) :- male(X),parent(X,Y).
father(god, _) :- male(god).
mother(X,Y) :- female(X),parent(X,Y).
son(X,Y) :- male(X),parent(Y,X).
daughter(X,Y) :- female(X),parent(Y,X).
grandfather(X,Y) :- male(X),parent(X,Somebody),parent(Somebody,Y).
aunt(X,Y) :- female(X),sister(X,Mom),mother(Mom,Y).
aunt(X,Y) :- female(X),sister(X,Dad),father(Dad,Y).
sister(X,Y) :- female(X),parent(Par,X),parent(Par,Y), X \= Y.
uncle(X,Y) :- brother(X,Par),parent(Par,Y).
cousin(X,Y) :- uncle(Unc , X),father(Unc,Y).
ancestor(X,Y) :- parent(X,Y).
ancestor(X,Y) :- parent(X,Somebody),ancestor(Somebody,Y).
brother(X,Y) :- male(X),parent(Somebody,X),parent(Somebody,Y), X \= Y.
Retrived from this repository
Given a number of facts is there a way to count them without using a built in function I have tried doing so with the below code but could no get it work. I hope someone can help me out.
For example the following facts:
stops(jubilee,bondstreet,1).
stops(jubilee,waterloo,2).
stops(jubilee,bakerstreet,3).
The code have got so far is:
findStops(X) :- stops(X,_, N), N1 is N+1, stopsX,_,N1).
I would like to make it so that N1 is the counter of how stops the jubilee line has.
A simple solution would be to count the number of stops/3 facts that have the atom jubilee in the first argument. Assuming all clauses for the stops/3 predicate have a bound first argument, you could write:
?- findall(1, stops(jubilee,_,_), List), length(List, Count).
In this query, findall/3 is a standard Prolog predicate and length/2 is a de facto standard predicate, usually available as a built-in predicate or as a library predicate.
Can you convert this query into a predicate that takes the station as an argument (instead of a hardcoded station as jubilee) and returns the count for that station?
The question isn't totally clear since it hasn't been defined what is allowed in terms of "built in" predicates. Such a problem cannot be solved without using some kind of predefined predicate.
Here are a couple of other ideas.
Using assertz and retract:
count_stops(Count) :-
assertz(num_stops(0)),
count_stops_aux(Count).
count_stops_aux(_) :-
stops(_, _, _),
retract(num_stops(C)),
C1 is C + 1,
assertz(num_stops(C1)),
fail.
count_stops_aux(Count) :-
retract(num_stops(Count)).
You could also probably do something similar with SWI Prolog's b_setval/2 and b_getval/2.
Here's a recursive solution that uses a list to check whether we've counted a particular fact already:
count_stops(Count) :-
count_stops_aux([], 0, Count).
count_stops_aux(L, Count, Total) :-
stops(A, B, C),
\+ member(stops(A,B,C), L),
C is Count + 1,
count_stops_aux([stops(A,B,C)|L], C, Total), !.
count_stops_aux(_, Total, Total).
Or similarly, but using length/2 as well:
count_stops(Count) :-
count_stops_aux([], Facts),
length(Facts, Count).
count_stops_aux(L, Facts) :-
stops(A, B, C),
\+ member(stops(A,B,C), L),
count_stops_aux([stops(A,B,C)|L], Facts), !.
count_stops_aux(Facts, Facts).
The first solution will count redundant facts (if an identical fact exists more than once), and assertz and retract are slow operations. The second and third solutions won't count redundant facts, but are really just clunky, verbose versions of Paulo's solution to avoid using findall. This is all why Prolog has predicates such as findall/3 and bagof/3.
Is there a way one can show all solutions and/or find how many there are in SICSTus prolog? For instance, the code below maybe used to solve the map colouring problem.
:- use_module(library(clpfd)).
solve_AUSTRALIA(WA,NT,Q,SA,NSW,V):-
domain([WA,NT,Q,SA,NSW,V], 1, 4),%colours represented by integers from 1 to 4
WA #\= NT,
WA #\= SA,
NT #\= SA,
NT #\= Q,
SA #\= Q,
SA #\= NSW,
SA #\= V,
Q #\= NSW,
NSW #\= V,
labeling([],[WA,NT,Q,SA,NSW,V]).
At the moment,I am typing ; every time to see further solutions till Prolog says no. Is there a way I can tell prolog to show all solutions at once, or better, a way I can find how many there. Like prolog tells me there are five solutions to the problem.
The following is for counting the number of answers. When you ask a query or execute a predicate, what you get back from Prolog are answers. Sometimes these answers are solutions, may contain more than one solution, infinitely many solutions, and sometimes even no solution at all.
The simplest way to go is to say findall(t, Goal_0, Ts), length(Ts, N). The only disadvantage is that this requires space proportional to the number of answers counted.
If you want to go one step further you need some kind of counter. Currently in SICStus 4.3.3 you can do this like so:
:- meta_predicate count_answers(0, ?).
:- meta_predicate count_answers1(0, +, ?). % internal
:- use_module(library(types),[must_be/4]).
:- use_module(library(structs),
[new/2,
dispose/1,
get_contents/3,
put_contents/3]).
count_answers(G_0, N) :-
( nonvar(N)
-> must_be(N, integer, count_answers(G_0, N), 2)
; true
),
new(unsigned_64, Ref),
call_cleanup(count_answers1(G_0, Ref, N), dispose(Ref) ).
count_answers1(G_0, Ref, N) :-
( call(G_0),
get_contents(Ref, contents, N0),
N1 is N0+1,
put_contents(Ref, contents, N1),
fail
; get_contents(Ref, contents, N)
).
See this answer how counters can be implemented in other systems. Example use:
| ?- count_answers(member(_,"abcde"),Ans).
Ans = 5 ? ;
no
Is there a way I can tell Prolog to show all solutions at once
This part of your question is related to the prolog-toplevel. In Prolog IV all answers (not necessarily solutions) were shown by default. The top level loop of a couple of Prolog systems permits to enter a to see all answers at once:
GNU-Prolog (originator)
Trealla-Prolog
Scryer-Prolog
I'm trying to solve a CSP where I need to distribute cocktails over bartenders so that each bartender has at most one cocktail and all cocktails are given a bartender. I solved it by creating a list of clpfd variables,first giving them the full domain of all bartenders and then removing all bartenders that don't know how to make that cocktail.
My code works, but there is one problem: it's too slow. If I look in the profiler, remove_domain gets called 2000 times(for the input I'm giving my program), while it's Redo statistic is >100 000.
What do I need to change in one of these functions(or both) so that prolog doesn't need to backtrack?
produce_domains(_,_,[],[]) :- !.
produce_domains(Bartenders,NBartenders,[Cocktail|Cocktails],[Var|Vars]) :-
Var in 1..NBartenders,
remove_domain(Bartenders,NBartenders,Cocktail,Var),!,
produce_domains(Bartenders,NBartenders,Cocktails,Vars),!.
remove_domain([],0,_,_) :- !.
remove_domain([Bartender|Bartenders],NBartenders,Cocktail,Var) :-
(\+ member(Cocktail,Bartender) -> Var #\= NBartenders;!),!,
NNBartenders is NBartenders - 1,
remove_domain(Bartenders,NNBartenders,Cocktail,Var),!.
I have already read this related question, but I am using the latest Windows build of SWI-Prolog(5.10.5), so that shouldn't be the problem here.
You do not need so many !/0: Prolog can often tell that your predicates are deterministic.
Let me first offer the following version of your code. It uses names that are more relational, contains no !/0 and uses higher-order predicates to make the code shorter.
:- use_module(library(clpfd)).
bartenders_cocktails_variables(Bs, Cs, Vs) :-
length(Bs, LBs),
maplist(bartenders_cocktail_variable(Bs, LBs), Cs, Vs).
bartenders_cocktail_variable(Bs, N, C, V) :-
V in 1..N,
foldl(compatible_bartender(C,V), Bs, 1, _).
compatible_bartender(C, V, Cs, N0, N1) :-
( member(C, Cs) -> true
; V #\= N0
),
N1 #= N0 + 1.
Notice that I am counting upwards instead of downwards to enumerate the bartenders (which are just lists of cocktails they are able to mix), since this seems more natural. I was also able to omit a (\+)/1 by simply switching the branches of the if-then-else.
Example query, showing that the predicate is deterministic in this use case:
?- bartenders_cocktails_variables([[a,b],[a,b],[x,y]], [x,a,b], Vars).
Vars = [3, _G1098, _G1101],
_G1098 in 1..2,
_G1101 in 1..2.
We see: Cocktail x must be mixed by the third bartender etc.
I think this part of your program may not be responsible for the slow performance you are describing. Maybe other parts of your program are (unintentionally) not deterministic? Maybe try different labeling strategies or other constraints? We may be able to help you more if you post more context.
Say I have the following piece of code:
edge(a, b).
edge(a, c).
edge(a, d).
Now when I do
neighbors(V, N) :- edge(V, N), writeln(N), fail.
I can get a list of the neighbors printed out to the console. But how can I get it as a result list? Something like
neighbors(V, Vs) :-
edge(V, N),
not(member(N, Vs)),
neighbors(V, [N|Vs]).
(the above piece doesn't really work due to the way member is handled. Any suggestion please?
Read about findall, bagof and setof in your favorite Prolog implementation's manual, or e.g. the section "11.2 Collecting solutions" in Learn Prolog Now!
(Unfortunately it is difficult to directly link to these resources.)
You can use bagof/3 to create a list of your verticies that satisfy the goal, "Vs is all N that is an edge of V."
neighbors(V, Vs) :- bagof(N, edge(V, N), Vs).
neighbors(a, Vs). % Vs = [b, c, d].