home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / huprolog_1 / Help! / s < prev   
Encoding:
Text File  |  1995-09-15  |  27.6 KB  |  777 lines

  1.  
  2.  
  3. /* 
  4. ----------------------------------------------------------------------
  5. (The dashes are cosmetic.) 
  6.                                "start" file.
  7.                                =============
  8.  
  9. These comments, marked by the slash*, will be ignored by Prolog. 
  10.  
  11. There is a user option to interpret a particular scenario and make up 
  12. a personal file of clues. These can be entered instead of one of the
  13. collected clues files "a", "h", "l", "m".  Facts, present in this 
  14. Udunit tend to show that identity X is, or is not, compatible to 
  15. identity Y. 
  16.  
  17. It will be seen that a pair of facts which fit each other  
  18. c(williamtell,crossbow) is a compatibility. Otherwise the fact 
  19. i(williamtell,sherwoodforest), for instance, is an incompatibility.
  20.  
  21. To reduce the number of files which need to be loaded a gleaned 
  22. clues listing may be inserted into a "group" file. These group files 
  23. "marinatale", "loungetale" etc apart from "remarks" otherwise contain 
  24. only lists of the principals seen in a particular episode. Thus, 
  25. together with your inserted clues would replace the standard "clus" 
  26. file. 
  27.  
  28. This ability to introduce your own material underlines the importance 
  29. of making a backup of the disc first.  
  30. As a rule the user's clues collection will be effectively the same as 
  31. the resident "clus" version, provided that all the transparent clues 
  32. have been entered and without aberrations. Loading "monitor" may 
  33. provide guidance if you suspect that all is not well with your 
  34. entries.
  35.      
  36. With the clue processor inside this file Prolog will progress towards 
  37. a solution to an episode through a process of data correlation. On the 
  38. first pass correlation between various i(X,Y) will produce one or more
  39. c(X,Y) by virtue of Prolog's scrutiny and elimination of n-1 
  40. impossibilities in a field of n candidates. The c(X,Y) produced will 
  41. on subsequent passes be cross-correlated with the earlier data.
  42.  
  43. Although not actually mandatory, in this type of problem there are the 
  44. same number of individuals in each group. Of these, n-1 members 
  45. (in a group) can be eliminated from any particular activity. 
  46.  
  47. Actual names of the utilities used will be as long as need be to 
  48. reflect their purpose to the user.
  49.  
  50. All this commentary will be ignored by Prolog.
  51.  
  52. (Note. The slash ends the comments.)
  53. ------------------------------------     
  54. */                 
  55.  
  56. %  This is a one-line comment.
  57.  
  58. /*
  59. A discussion of the utilities will be accompanied by reference to the 
  60. relevant Prolog conventions. This will become less necessary as we go 
  61. along. 
  62. */
  63.                                 %   " :- "  means " IF  ". 
  64. s :-  nl,nl,                    %   " nl,"  means new line. 
  65.       write(' Start.'),nl,      %   " ,  "  means " AND ".                              
  66.       write(' ------'),nl,nl,   
  67.       start.                    
  68.                   %  For readability a space is usually maintained 
  69.                   %  between the name and the semicolon.                          
  70.                    
  71. start :-                    
  72.       episode,            %  Title, if any, given in the readout. 
  73.       fail.               %  A pseudo "fail". The next "start" clause
  74.                           %  will now be addressed. 
  75.              
  76. start :-                 
  77.       i(_,_),             %  Has data been entered ?.                          
  78.       remove_duplicates.  %  Readouts will look better without
  79.                           %  repetitive data.  
  80. start :-      
  81.       c(_,_),         %  Data is in the form "i(X,Y)" and/or "c(X,Y)".
  82.       remove_duplicates.
  83.                                                                 
  84. start :-        % If Prolog arrives here the data has not been loaded.  
  85.       nl,nl,         
  86.       write('           DATA HAS NOT YET BEEN ENTERED.'),nl,
  87.       write('           ------------------------------'),nl,nl,           
  88.       write(' Prolog halts here.').
  89.         
  90. /*
  91. Composers of logic problems ensure that only the minimum number of 
  92. facts necessary to obtain a solution are available. This rule has 
  93. been relaxed in this Udunit. However, a very few of the clues in 
  94. each episode express similar data in slightly different ways. This 
  95. gives rise to duplicated entry of these clues. Redundancy of entries 
  96. need not trouble us here as they will be suppressed at run time thus 
  97. avoiding repetition of Prolog output. This is achieved by the 
  98. procedure below. Clauses found to have been duplicated of course 
  99. could, instead, have been cached under a new name and made inactive. 
  100. */
  101.  
  102. remove_duplicates :- 
  103.       write('  Duplicates removed and Inversions introduced .'),nl,
  104.       write('  ----------------------------------------------'),nl,                                    fail.             
  105.                             
  106. /*
  107. The negation "bar" is used in the following utility where it is a 
  108. safeguard against duplicated data being processed. The resident Prolog 
  109. predicate "not" would usually be employed for this purpose. However an 
  110. alias, "bar", will be used in its stead for the reasons stated below.   
  111. */
  112.  
  113. %  A slave j(X,Y) in place of the particular i(X,Y) being dealt with, 
  114. %  without duplicates, will now be raised.  Although KeyLink kprolog 
  115. %  could enable a simpler utility to be used which can retract and 
  116. %  save a copy of a clause to a cache, this utility is more general 
  117. %  purpose.
  118.  
  119. remove_duplicates :-                           
  120.       i(X,Y),          %  These may have had duplicates. 
  121.       bar(j(X,Y)),     %  If done already Prolog now backtracks 
  122.       assert(j(X,Y)),  %  to find the next i(X,Y) candidate, if any. 
  123.       fail.            %  Both "bar" and "fail" are construed below.
  124.  
  125. /*
  126. Prolog will backtrack on seeing "fail" and try to find other i(X,Y) 
  127. clauses before addressing the next "remove_duplicates" clause.
  128. */
  129.  
  130. /* 
  131. Note, the definition of the ad hoc utility "bar", is not given whilst 
  132. in the middle of this "remove_duplicates" procedure. Otherwise, Prolog 
  133. will draw our attention to what it would construe as possibly 
  134. dislocated clauses.
  135. */
  136.      
  137. remove_duplicates :- 
  138.      abolish(i,2),
  139.      fail.     
  140.                       % Any duplications in i(X,Y) in database are, 
  141.                       % thus, also abolished. 
  142.                          
  143. /*
  144. We have cleared the database of any duplicates by the expediency of
  145. raising j(X,Y) and abolishing the i(X,Y) data.   
  146.  Going full circle, the functor name "i" can be resurrected. Also, to 
  147. promote a solution, the inversions i(Y,X) generated from pristine 
  148. i(X,Y).
  149.      
  150. The readout will look rather like this, 
  151.        
  152.         i(alpha,beta)             
  153.                            i(beta,alpha)
  154.         i(mu,phi)
  155.                            i(phi,mu)
  156.         i(epsilon,gamma)  
  157.                            i(gamma,epsilon)  
  158.    
  159. More simply,
  160.  
  161.         i(alpha,beta)      i(beta,alpha)
  162.         i(mu,phi)      i(phi,mu)
  163.         i(epsilon,gamma)      i(gamma,epsilon) 
  164. */
  165.  
  166. remove_duplicates :-   
  167.       j(X,Y),             %  The interim form.
  168.       bar(i(X,Y)),       
  169.       assert(i(X,Y)),    
  170.       assert(i(Y,X)),    
  171.       write(i(X,Y)),nl,   %  More simply, remove "nl," and reduce to,  
  172.       tab(30),            %  say, tab(15).
  173.       write(i(Y,X)),nl,   
  174.       fail. 
  175.  
  176. remove_duplicates :-          
  177.       abolish(j,2),   %  No further need for these.
  178.       c_data.         %  "c_data" will check for c(X,Y) data. If none 
  179.                       %  then a jump will made.
  180.          
  181. /*
  182. Now "not" and "bar".                                                      
  183. PrologX will raise an objection for some uses of "not". Briefly, the 
  184. negation of a fact which has not yet made its entry into the 
  185. circumscribed world of the database can be a bit tricky. This, 
  186. perhaps, partly stems from the fact that both " not X " and " not(X) " 
  187. can be used. Hence to avoid initial confusion the "bar" alias, which 
  188. has been given the same definition as "not", is used. The user later 
  189. can engage the usual form.  
  190. */
  191.                    
  192. bar(Goal) :-          % The term "bar" has been substituted for "not". 
  193.       call(Goal),!,   % "!", A cut. If the goal is found, and this 
  194.       fail.           % could be an unwanted duplicate, then the 
  195.                       % second clause, bar(_),will not be addressed.  
  196. bar(_).               % Also, perforce, the goal is made to fail.   
  197.  
  198. /*  
  199. If (Goal) was not found then the cut ! would not be encountered as   
  200. backtracking would occur. The next clause, bar(Anything) then enables 
  201. the procedure to continue. 
  202. */
  203.  
  204. /*
  205. ----------------------------------------------------------------------
  206. The "member" utility, below, will now be used fairly frequently.
  207.  
  208. Let us consider a list, that is any number of constants contained 
  209. within square brackets. For instance, [a,b,c,d,e], or indeed the empty 
  210. list [] which has a significant part to play in Prolog. The "member" 
  211. utility operates by first looking at the element currently at the head 
  212. of the list.  Thus something is a member of a list if it is at its 
  213. head. This leaves the tail of the list remaining for scrutiny. The 
  214. definition below shows the Prolog use of the vertical separator  "|".  
  215.           
  216. The member utility:   Let  [Head|Tail]  be  [a,b,c,d,e]. 
  217. -------------------
  218.  
  219.      member(X,[X|_]).     % X is obviously a member of [X|_].
  220.                           % Example: member(a,[a|_]).
  221.  
  222.      member(X,[_|Tail]) :- member(X,Tail). 
  223.                           % Example: member(d,[_|[b,c,d,e]]).
  224.  
  225. As the tail is also a list "member" will simply shed the head of the 
  226. list progressively until it either finds a match or fails.    
  227. ----------------------------------------------------------
  228. */ 
  229.  
  230. % In order to avoid conflict with HUprolog, and others, "member" is
  231. % renamed "member2". (Any particular prolog facility regards its
  232. % built-in predicates as sacrosanct.) 
  233.  
  234.                     member2(X,[X|_]).  
  235.  
  236.                     member2(X,[_|Tail]) :- member2(X,Tail).
  237.                        
  238. c_data :- 
  239.       nl, 
  240.       c(_,_),     %  Are there any c(X,Y) ?.
  241.       c_inverse.  %  Various forms of correlation will take place 
  242.                   %  between all elements that have been introduced by
  243.                   %  the data file. 
  244.                     
  245.                       
  246. c_data :-         % No c(X,Y) in the initial data if Prolog gets here. 
  247.       make_subgroups.   %  (See NOTE).
  248.  
  249. /*  
  250. NOTE.  If a c(X,Y) had not been entered then the next few utilities 
  251.        which are designed to operate on c(X,Y) will be avoided on a 
  252.        first pass. Subsequent recursions however will call up these 
  253.        facilities. Thus an absence of c(X,Y) at the outset will cause 
  254.        Prolog to go to "make_subgroups" early.
  255.        This being in the main loop. 
  256.        "make_subgroups" will then collect something like:
  257.       
  258.        Example:  i(X,a1), i(X,a2), i(X,a4), i(X,a5), and thus c(X,a3) 
  259.                  would be generated. 
  260.                  The variable X could have been replaced with an 
  261.                  arbitrary constant.
  262.  
  263. One of the episodes gives up no transparent c(X,Y), however read
  264. "c_inverse" since it is functionally similar to the inversion of 
  265. i(X,Y). Follow this with Introduction to "findall", just below. 
  266. */
  267.                               
  268. c_inverse :- nl,nl,    %  If c(X,Y) then c(Y,X) also is needed.
  269.       write(' inverse'),nl,
  270.       write(' -------'),nl,nl,
  271.       c(X,Y),          %  Both will be used.                  
  272.       bar(c(Y,X)),     %  If already in database base don't bother.
  273.       assert(c(Y,X)), 
  274.       write(c(X,Y)),nl,
  275.       tab(30),
  276.       write(c(Y,X)),nl, 
  277.       fail. 
  278.  
  279. c_inverse :- 
  280.       cross_correlate,   % These are defined later.
  281.       auto_correlate,    % "c_inverse" would not have been called up 
  282.                          % if no c(X,Y) had been entered as in the 
  283.                          % harem episode "h".
  284.       make_subgroups.        
  285.  
  286. /*
  287. ----------------------------------------------------------------------
  288. Introduction to "findall".
  289. --------------------------
  290. The procedure "make_subgroups" will use "findall" to make up subgroups 
  291. of elements from Y in i(X,Y). We could, instead, have chosen to find 
  292. all X in i(X,Y).
  293. A description of "findall" is usually given as findall(X,Goal,List) 
  294. which can be interpreted here as, either;
  295.    
  296.                              findall(X,i(X,Y),List) or 
  297.                              findall(Y,i(X,Y),List). 
  298.  
  299. We will use the latter and declare X as being the identity which is 
  300. incompatible to the contents of List. 
  301.  
  302. Example: If, say,
  303.                     group([snail,rat,mosquito,tsetse_fly,sand_fly]),
  304.  
  305. was sitting in the database and user entered from the keyboard:         
  306.  
  307.                       ?- assert(i(lassa_fever,snail)).
  308.                          assert(i(lassa_fever,mosquito)).
  309.                          assert(i(lassa_fever,tsetse_fly)).
  310.                          assert(i(lassa_fever,sand_fly)).
  311.  
  312.                          findall(Y,i(X,Y),List).   
  313.  
  314. (Then Prolog would return:)
  315.    
  316.                          List =  [snail,mosquito,tsetse_fly,sand_fly]
  317.  
  318. As Lassa fever is not attributable to any of these agents an extension 
  319. of the inquiry would give up the compatible pair:
  320.  
  321.                         c(lassa_fever,rat). 
  322.                    
  323. The range of any list is limited in length only by the Prolog facility 
  324. storage allocation. 
  325. -------------------
  326. */
  327.  
  328. /*
  329. The implementation of the findall relation shown here is seen in 
  330. Bratko's "Prolog, Programming for Artificial intelligence." 
  331. Other versions may cache the "find" using "asserta" instead of 
  332. "assertz", where the suffix "z" means go to the bottom of the pile.
  333. Originated by D.H.D.Warren it was refined by R,A.O'Keefe et al. 
  334. An ad hoc version which performed well with this clue processor was 
  335. regretfully set aside as it flies in the face of the fully evolved 
  336. "findall" predicate. It does however point up the fact that it is not 
  337. particularly difficult to produce workable utilities for a knowledge 
  338. database.          
  339. */
  340.  
  341. % In order to avoid conflict with "findall" in both HUprolog and 
  342. % PrologX the utility will be renamed "findall3". The new name is 
  343. % suggested by the fact that there are three parameters or arguments
  344. % in "findall".  
  345. % An understanding of "findall" is not particularly germane to the
  346. % user's progress through this clue processor at the outset.
  347.             
  348. findall3(X,Goal,Xlist):-            % The structure for "findall".                             
  349.       call(Goal),                   % Find items and
  350.       assertz(queue(X)),            % assert each to end of a queue.  
  351.       fail;                         % ";" means OR.
  352.       assertz(queue(bottom)),       % Mark the end of the queue.
  353.       collect(Xlist).               % Collect items to list. 
  354.  
  355.       collect(L) :-                 % L becomes Xlist.
  356.       retract(queue(X)),!,          % Retract next item.
  357.       (X == bottom,!,L = [];        % No more items ?
  358.       L = [X|Rest], collect(Rest)). % Otherwise collect the rest. 
  359.                               
  360. % The [] of course means "empty". 
  361.                        
  362. make_subgroups :-    %  Subgroups of the form ii(a1,[b1,b2,b3,b5]) 
  363.       abolish(ii,2), %  will be fashioned. A simple way to avoid the  
  364.       fail.          %  clutter of small subgroups of the previous  
  365.                      %  recursion is to abolish them.                               
  366.                                                 
  367. make_subgroups :-  % This leads to the use of the "findall3" utility. 
  368.       nl,                 
  369.       write(' make_subgroups'),nl,
  370.       write(' --------------'),nl,nl,
  371.       fail.
  372. /*
  373. To prevent Prolog from looping indefinitely should insufficient data
  374. have been entered the next clause will assert a flag to the top of 
  375. the functor c(_,_) pile. This will be "c([],[])", it could have been 
  376. "c(insufficient,data)", say. Thus, when during the course of this new 
  377. recursion a fresh c(X,Y) is found it will displace c([],[]) from the 
  378. top of the pile. At the end of a recursion involving each element in 
  379. turn as a reference, if all is well the marker c([],[]) will have been 
  380. relegated to the bottom of the current pile. It remains then to 
  381. restore it to the top of the pile before the start of the next 
  382. recursion. Conversely if a new c(X,Y) had not been encountered then a 
  383. call to "c(X,Y)" would produce c([],[]) immediately. This, still the 
  384. topmost clause, would then cause Prolog to signal "Insufficient data." 
  385. and await further information.  
  386. */
  387.  
  388. make_subgroups :-  
  389.       write('             The flag c([],[]), below, will be hidden 
  390.               when a c(X,Y) is disclosed. Failing this, the 
  391.               program will stop due to insufficient data.'),
  392.       nl,nl,
  393.       write('Small wait.'),nl,nl,
  394.       fail.
  395.    
  396. make_subgroups :-  
  397.       asserta(c([],[])),   % If this is still top of the pile after 
  398.       c(X,Y),              % "data_check" below then "Insufficient 
  399.       tab(40),             %  data.".      
  400.       write(c(X,Y)),write('  asserted.'),!,  
  401.       nl,nl,
  402.       subgroups.          
  403.                           
  404. subgroups :-   
  405.       group(XX),          %  Get a group.
  406.       member2(X,XX),      %  Select the head of the list.
  407.       group(YY),          %  This group will supply the Y in i(X,Y).                             
  408.       YY \== XX,          %  Prevents Prolog from assigning the same 
  409.                           %  group to different variables.
  410.       makej(X,YY),        %  "makej/2" will produce one subset at a 
  411.       fail.               %  time of i(X,Y)  clauses using a unique
  412.                           %  X and a selected group(YY).
  413.  
  414. subgroups :-                
  415.       oddoneout.          % Here a search for n-1 instances of Y in
  416.                           % a possible n i(X,Y) clauses.       
  417.                           % "findall3" will be called up.
  418.          
  419. makej(X,YY) :-
  420.       member2(Y,YY),
  421.       i(X,Y),
  422.       assert(j(X,Y)),   
  423.       fail.             
  424.  
  425. makej(X,YY) :-     
  426.       findjy.
  427.           
  428. findjy :-  
  429.      j(X,_),                 
  430.      findall3(Y,j(X,Y),Subgroup),
  431.      bar(ii(X,Subgroup)),
  432.      assert(ii(X,Subgroup)),
  433.      fail. 
  434.  
  435. findjy :-
  436.      abolish(j,2).   %  Returns to "subgroups". Another recursion. 
  437.   
  438.  
  439. /*
  440. The next utility, "oddoneout", compares complete groups with the 
  441. current Subgroups. Employing the "difference" predicate it marks
  442. the presence of all n-1 subgroups so enabling compatible pairs to 
  443. be raised. This is done by noting when the difference "Diff" is equal 
  444. to the singleton [Head|[]]. 
  445.  
  446. Example:      group([a1,a2,a3,a4,a5]) 
  447.               ii(X,([a1,a2,a4,a5])).    This leads to c(X,a3). 
  448.  
  449. Numeric example:    difference([1,2,3,4,5], [2,3,5,6], Diff).
  450.                     Diff = [1,4]
  451.  
  452. "difference" is a predicate favoured by more than one text book.
  453.  
  454. The "Utilities" directory shows the utility "length" which could be 
  455. used to compare a "group" with a subgroup. The odd one out can then 
  456. be ascertained when the difference in length is a singleton.
  457.  From a group list [a1,a2,a3,a4,a5] and its subgroup list 
  458. [a1,a2,a4,a5] the element a3 would emerge thus pointing to c(X,a3).
  459. */  
  460.  
  461. difference([],_,[]).   
  462.  
  463. difference([X|Set1],Set2,Diff) :-
  464.      member2(X,Set2), !,              
  465.      difference(Set1,Set2,Diff).
  466.  
  467. difference([X|Set1],Set2,[X|Diff]) :-
  468.      difference(Set1,Set2,Diff).
  469.  
  470. oddoneout :- 
  471.       write(
  472.    ' Permutations of n-1 subsets will be encountered. These also will 
  473.      be shown but only one the first one seen will be operated on.'),
  474.       nl,nl,nl,
  475.       fail.
  476.  
  477. oddoneout :-  
  478.       ii(X,List),         %  ii(X,[a1,a2,a4,a5]).  
  479.       write(ii(X,List)),nl,                           
  480.       member1(M,List),    %  Confirming that List is a subgroup of G. 
  481.       group(G),           %  e.g.   group([a1,a2,a3,a4,a5]).
  482.       member2(M,G),       %  Say, member2(a1,[a1,a2,a3,a4,a5]).     
  483.                           %  difference(G,List,Difference) 
  484.                       % Difference is a list, [Head|Tail].
  485.                       % So let us use:
  486.       
  487.       difference(G,List,[Head|[]]),
  488.  
  489.                       % That is a Head followed by an empty tail.
  490.                       % Which is exactly what we are looking for.                         
  491.       bar(c(X,Head)),     
  492.       asserta(c(X,Head)),
  493.       nl,
  494.       write(ii(X,List)),nl,
  495.       tab(1),
  496.       write(c(X,Head)), 
  497.       bar(c(Head,X)),  
  498.       asserta(c(Head,X)),                                                                 
  499.       tab(5),
  500.       write(c(Head,X)),      
  501.       write('   shown.'),nl,nl,
  502.       fail.
  503.  
  504. oddoneout :- nl,
  505.       c(X,Y),
  506.       write(c(X,Y)),
  507.       nl,
  508.       fail.
  509.  
  510. oddoneout :-      
  511.       progress,
  512.       cross_correlate,
  513.       auto_correlate,
  514.       fail.
  515.  
  516. oddoneout :-
  517.       do,   % This utility will inspect the data file for
  518.             % additional instructions.
  519.       fail.
  520.  
  521. oddoneout :-
  522.       monitor,  % Operative if the monitor file has been loaded.
  523.       fail.      
  524.  
  525. oddoneout :-  
  526.       sort_c,                         
  527.       delete_unwanted_i.
  528.      
  529. progress :-  
  530.       c(X,Y),!,  %  Only the first instance found will be used.
  531.       check(X).  %  One of the parameters is passed on for vetting. 
  532.       
  533. check(X) :-            
  534.       [] == X,
  535.       nl,nl,
  536.       write('..... End; c([],[]) still at the top of the pile.'),
  537.       nl,nl,                     
  538.       write('c([],[]) not displaced.'),nl,nl,  
  539.       nl,nl,                     
  540.       write('     WE HAVE INSUFFICIENT DATA.'), nl,
  541.       write('     --------------------------'),
  542.       nl,nl,
  543.       abort.
  544.  
  545. check(X) :-  % Prolog has seen fresh data.
  546.       nl,  
  547.       retract(c([],[])),
  548.       nl,
  549.       tab(10),
  550.       write('c([],[])  retracted.'),nl,nl.
  551.           
  552. cross_correlate :- nl,
  553.       write('   c(Y,Z) generated from c(X,Y) and c(X,Z).'),
  554.       nl,           
  555.       fail. 
  556.  
  557. % This utility has been awaiting the production of further c(X,Y).
  558. % It was unlikely that both c(X,Y) and c(X,Z) were available from 
  559. % file. 
  560.  
  561. cross_correlate :-
  562.       c(X,Y),
  563.       c(X,Z),
  564.       Z \== Y,
  565.       bar(c(Y,Z)),
  566.       assert(c(Y,Z)),
  567.       write(c(Y,Z)),nl,
  568.       fail.   
  569.  
  570. cross_correlate :- nl,
  571.       write('    If c(X,Y) and i(X,Z) then i(Y,Z).'),nl,
  572.       fail.      
  573.                    
  574. cross_correlate :-  %         
  575.       nl,                                                   
  576.       c(X,Y),             % c(a1,b1), 
  577.       i(X,Z),             % i(a1,c1), 
  578.       group(YY),          % group([b1,b2,b3,b4,b5]),   
  579.       member2(Y,YY),       % member2(b1,[b1,b2,b3,b4,b5]), 
  580.       bar(member2(Z,YY)),  % bar(member2(c1,[b1,b2,b3,b4,b5]).
  581.       bar(i(Y,Z)),        % If done already don't bother.            
  582.       assert(i(Y,Z)),     % assert(i(b1,c1)),
  583.       bar(i(Z,Y)),
  584.       assert(i(Z,Y)),     % assert(i(c1,b1)),
  585.       write(i(Y,Z)),nl,   % There will be a fair number of these.
  586.       fail.               % Prefix "write" with a "%" to  
  587.                           % avoid a readout.
  588.  
  589. cross_correlate. 
  590.                 
  591. /*
  592. Suppose c(a1,Y) and group([a1,a2,a3,a4,a5]) then i(a2,Y), i(a3,Y) etc. 
  593. must be asserted.
  594. */
  595.  
  596. auto_correlate :- nl,nl,
  597.       write('   c(a1,Y) will evoke i(a2,Y), i(a3,Y) etc.'),nl,nl,
  598.       write(
  599.        '   They are comprised of the following, with their inverts.'),
  600.       nl,nl,
  601.       fail.
  602.                                                   
  603. auto_correlate :-                                                           
  604.       group(XX),       
  605.       member2(X,XX),    
  606.       c(X,Y),                   
  607.       member2(X2,XX),                                       
  608.       X2 \== X,              
  609.       bar(i(X2,Y)),   
  610.       assert(i(X2,Y)),
  611.       write(i(X2,Y)),nl,  
  612.       bar(i(Y,X2)),                              
  613.       assert(i(Y,X2)),              
  614.       fail.  
  615.  
  616. auto_correlate. 
  617.            
  618. sort_c :-
  619.        group(XX),
  620.        member2(X,XX),
  621.        c(X,Y),
  622.        asserta(slave(X,Y)),
  623.        fail.
  624.  
  625. sort_c :-       
  626.        abolish(c,2),
  627.        fail. 
  628.  
  629. sort_c :-
  630.        slave(X,Y),
  631.        asserta(c(X,Y)),
  632.        fail.
  633.  
  634. sort_c :- 
  635.        abolish(slave,2). 
  636.  
  637. delete_unwanted_i :-   %  i(X,Y) are still in evidence.
  638.       nl,nl,               
  639.       write('We are looking for subgroups of n-1 elements.'),nl, 
  640.       write('---------------------------------------------'),    
  641.       nl,nl,
  642.       fail.                                       
  643.  
  644. % To avoid clutter, as c(x,y) are present, certain i(X,Y) will be
  645. % deleted.
  646.       
  647. delete_unwanted_i :- 
  648.       write(' delete_unwanted_i'),nl,
  649.       write(' -----------------'), 
  650.       group(YY),           %  group([a1,a2,a3,a4,a5]).
  651.       member2(Y,YY),       %  member2(a5,[a1,a2,a3,a4,a5]), say.
  652.       c(X,Y),              %  c(X,a5), say.
  653.       member2(Y2,YY),      %  member2(M,[a1,a2,a3,a4,a5]).
  654.       Y2 \== Y,            %  M \== a5.
  655.       i(X,Y2),             %  These would be i(X,a1)..i(X,a4).    
  656.       retract(i(X,Y2)),    %  When, eventually, the global i(X,Y) have 
  657.       fail.                %  been retracted then the logic problem is 
  658.                            %  solved. 
  659.                                                                                              
  660. delete_unwanted_i :- 
  661.       i(_,_),          %  Any i(X,Y) left ?.
  662.       make_subgroups.      
  663.                       %  Another recursion.
  664.  
  665. delete_unwanted_i :-  % If Prolog gets here then
  666.       collect_sets.        % no i(X,Y) left.  (See NOTE.)
  667.  
  668. /* NOTE.
  669. Only compatible elements remain in the database. Inverts c(Y,X) can 
  670. be suppressed. A general clean-up will now take place in 
  671. "collect_sets". 
  672. */
  673.                                                                                                
  674. collect_sets :- nl,
  675.       write('   collect_sets '),nl,
  676.       write('   ------------ '),nl,nl,
  677.       write(
  678. 'All c(X,Y) including inverts have been found. Interacting components
  679. will be retained but their inverts will be suppressed. This will
  680. facilitate the subsequent attraction of complete sets of compatible
  681. elements.'),
  682.       nl,nl, 
  683.       make_one_list.  % Use only c(X,Y) with X of one list.
  684.  
  685. make_one_list :- nl,
  686.     write('consolidated lists.'),nl,
  687.     fail.
  688.  
  689. make_one_list :-
  690.      write(
  691.      '  One group only will be used to attract its compatibles,
  692.       namely.'),
  693.      nl,nl,
  694.      group(XX),     
  695.      klists(XX).   
  696.  
  697. klists(XX) :-  
  698.      write(XX),nl,nl, 
  699.      group(XX),    
  700.      member2(X,XX), 
  701.      c(X,Y),   
  702.      assert(k(X,Y)),      
  703.      write(k(X,Y)),nl,  
  704.      fail.
  705.  
  706. klists(XX) :- 
  707.      ccsets. 
  708.       
  709. ccsets :- nl,
  710.      k(X,_),
  711.      findall3(Y,k(X,Y),Subset),
  712.      precede(X,Subset,Set),
  713.      bar(cc(Set)),
  714.      assert(cc(Set)),
  715.      write(cc(Set)),nl,
  716.      fail.  
  717.  
  718. ccsets :-  nl,
  719.       write(' * all_done *'),nl,
  720.       write(' ------------'),nl,nl,
  721.       write('          PROBLEM SOLVED.'),nl,nl,                          
  722.       write('          The cc sets show connected elements.'),nl,                
  723.       write( '  To do a re-run do < ss.>.'),nl,nl,
  724.       write('  
  725.            ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤'),nl.
  726.              
  727. delete(X,List1,List2) :-
  728.       conc(L1,[X|L2],List1),
  729.       conc(L1,L2,List2).                  
  730.                                                                                                                              % Used above.    
  731. precede(X,List,[X|List]).   % Appends a single element X to a list. 
  732.                             % Example  precede(a,[b,c,d],List]).
  733.                             % List = [a,b,c,d]
  734.  
  735. member1(X,[X|_]) :- !.      % This will find one member only.
  736. member1(X,[_|T]) :-
  737.       member1(X,T).    
  738.  
  739. conc([],L,L).
  740. conc([X|L1],L2,[X|L3]) :- 
  741.       conc(L1,L2,L3).
  742.            
  743. ss :-
  744.      write('* ss *'),nl,
  745.      write('------'),nl,nl,                                               
  746.      nl,nl,       
  747.      group(YY),         %  group([y1,y2,y3,y4,y5]).
  748.      member2(Y,YY),     %  member2(y1,[y1,y2,y3,y4,y5]).
  749.      c(X,Y),            %  c(x1,y1).
  750.      member2(Y1,YY),    %  member2(y2,[y1,y2,y3,y4,y5]).
  751.      Y1 \== Y,          %  y2 \== y1.
  752.      bar(i(X,Y1)),      %  bar(i(x1,y2)),
  753.      assert(i(X,Y1)),   %  assert(i(x1,y2)),   
  754.      fail.
  755.  
  756. ss :-    
  757.      abolish(k,2),    
  758.      abolish(c,2),    
  759.      abolish(cc,1),
  760.      nl,  
  761.      make_subgroups. 
  762.                % This is a convenient entry into the programme.
  763.                
  764.  
  765.  
  766.    
  767.                               
  768.     
  769.    
  770.  
  771.                       
  772.  
  773.    
  774.                               
  775.     
  776.    
  777.