| << Prev | - Up - | Next >> |
Continuation.
Now finally we come to the THEN-part in scan_state/2. It consists in calling scan_states/2 (plural!) on the Ds produced by the preceding setof/3-call. The scan_states/2-predicate recursively calls scan_state/2 (singular!) on every state on Ds:
scan_states(A,[S|Ss]):-
scan_state(A,S), % scan state from state list
scan_states(A,Ss). % go to next state from state list
scan_states(_,[]). % state list already emptied?
In our example, this means that the transition trans(a1,2,3,a) is copied to trans(a2,2,3,a). Then the next level of the recursion is entered by calling scan_states/2 again, this time on Ds=[3]. Now there are two transitions. This means that Ds will have two members: [2,4]. State 2 has already been processed, and state 4 for has no outgoing transitions. This indicates that a1 has been fully traversed and the next call to scan_states/2 should end the recursion.
How is this done? For state 2, the one that has already been processed, the first clause of scan_state/2 will succeed, because the database contains the entry state(cp(a1,b1),2) that was asserted when state 2 was processed for the first time. This means that no further recursive level will be entered. For state 4, recursion will end simply because setof/3 in scan_state/2 won't find any transitions and so Ds will be empty.
Finally notice that state 4 is the final state of a1. For this reason, the call to check check_final/2 in the second clause of scan_state/2 will not just trivially succeed. Rather it will really do something before it succeeds. Let's have a look at the code:
check_final(A,S):-
final(A,S),!. % final states receive special treatment
check_final(_,_). % non-final states: no processing necessary - just return trueThe first clause contains a call to final/2. This predicate is again implemented differently for cp, intersection and union. Here's the clause for cp:
final(cp(A1,A2),S):-
final(A1,S),
assert(final(A2,S)).If S is a final state in the original A1, an according final state is asserted for the copy A2. In our example, the entry final(b1,2) will be asserted. For all non-final states, the above clause of final/2 will fail and the second clause of check_final/2 will succeed without any further actions.
Summing up, after running scan(cp(a1,b1)), the following will have happened:
Due to the call to start/2 in scan/1, the database will contain the entry:
start(b1,1)The calls to trans/2 in the second clause of scan_state/2 will have added:
trans(b1,1,2,h).
trans(b1,2,3,a).
trans(b1,3,4,!).
trans(b1,3,2,h).The call to final/2 in check_final/2 will have added:
final(b1,4).That's a full copy of a1. Additionally, the database will contain the entries:
state(cp(a1,b1),1).
state(cp(a1,b1),2).
state(cp(a1,b1),3).
state(cp(a1,b1),4).These were asserted in scan_state/2 as control information and can be retracted.
| << Prev | - Up - | Next >> |