home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / aijournl / ai_may89.arc / FRAMES.CDE < prev    next >
Encoding:
Text File  |  1988-05-04  |  8.4 KB  |  236 lines

  1.  
  2.                Frame Unification
  3.  
  4.  
  5. /* frame_unify(Frame1, Frame2, Unification )
  6.    unifies two frames.  Slots that are present in one frame and not in
  7.    another are added to the unification, as if the slot had appeared in
  8.    the frame where it was absent with a variable value.
  9. */
  10.  
  11.                     /*  frame_unify                    */
  12. frame_unify(Frame1, Frame2, Unification ):-
  13.              % use frame_merge to implement frame_unify
  14.     frame_merge(Frame1, Frame2, Unification, slot_unify).
  15.  
  16.  
  17.  
  18.    %  slot_unify([Tag : Slot_val1, Slot_list2, Result, Fail_Flag ])
  19.    %
  20.    % unifies a slot with Tag with a member of a Slot_list2 if possible.
  21.  
  22.       % This first rule applies when Slot_list2 contains a slot with Tag.
  23.       % Result is the unification if it exists.
  24.       % Fail_Flag is set to fail if unification fails, to signal
  25.       % frame_merge to fail.
  26. slot_unify([Tag : Slot_val1, Slot_list2, Result, Fail_Flag ]):-
  27.               % get value for Tag
  28.     slot_list_val(Tag, Slot_list2, Slot_val2),
  29.               % If slot list 2 contains a slot with Tag,
  30.               % stay in this rule
  31.     !,
  32.               % if these slot values unify
  33.     (    value_unify(Slot_val1, Slot_val2, Result),
  34.               % then stay in this alternative
  35.          !,
  36.               % and tell frame_merge not to fail
  37.          Fail_Flag = true
  38.               % if the slot values do not unify
  39.               % tell frame_merge to fail
  40.       ;  Fail_Flag = false).
  41.  
  42.        % When the slot in arg. 1 does not appear in the
  43.        % arg. 2 slot list, the result of unify is the slot
  44.        % value in arg. 1
  45. slot_unify([ _  : Slot_val1, _ , Slot_val1 , _]):-  !.
  46.  
  47.  
  48. /*-------------------- value_unify -----------------------------------------*/
  49.  
  50.       % value_unify unifies slot values
  51.       % Arg 3 is the unification
  52.             % this rule unifies those things that are not frames
  53. value_unify(Slot_val1, Slot_val2,  Slot_val1):-
  54.              Slot_val1 = Slot_val2, !.
  55.  
  56. è            % this rule unifies  frames
  57. value_unify(Slot_val1, Slot_val2, Result ):-
  58.     frame_merge(Slot_val1, Slot_val2, Result, slot_unify),
  59.     !.
  60.  
  61.            % set unify slot values that are sets
  62. value_unify(Slot_val1, Slot_val2, Slot_val1) :-
  63.     set_unify(  Slot_val1, Slot_val2  ) ,!.
  64.  
  65.  
  66. Intersecting Frames
  67.  
  68.  
  69. /* frame_intersect creates a new frame from 2 existing frames by
  70.     * keeping in slots that appear in both frames with values that unify,
  71.       and letting the value of such slots be the unification of the input
  72.       slot values
  73.     * deleting all other slots, including those where the same tag has
  74.       values in the two frames that don't unify.
  75. */
  76.  
  77. frame_intersect(Frame1, Frame2, Intersection ):-
  78.            % do this with frame_merge
  79.     frame_merge(Frame1, Frame2, Intersection, slot_intersect).
  80.  
  81. slot_intersect([Tag : Slot_val1, Slot_list2, New_slot_val, true    ]):-
  82.     slot_list_val(Tag, Slot_list2, Slot_val2), !,
  83.            % merge slot values
  84.     slot_merge0(Slot_val1, Slot_val2, New_slot_val, _  ).
  85.  
  86.            % note that when a slot with Tag is not in Slot_list2,
  87.            % slot_intersect fails.  This causes frame_merge to
  88.            % leave the Tag slot out of the computed Intersection
  89.  
  90.            % unify slots if possible
  91. slot_merge0(Slot_val1, Slot_val2, Slot_val1, _):-
  92.              Slot_val1 = Slot_val2, !.
  93.  
  94.            % intersect slot values that are frames
  95. slot_merge0(Slot_val1, Slot_val2, New_slot_val, _):-
  96.     frame_merge(Slot_val1, Slot_val2, New_slot_val, slot_intersect),
  97.     !.
  98.  
  99.            % set unify slot values that are sets
  100. slot_merge0(Slot_val1, Slot_val2, Slot_val1   , _):-
  101.     set_unify(  Slot_val1, Slot_val2  ) ,!.
  102.  
  103.  
  104. A General Frame Merging Predicate
  105.  
  106.  
  107. /*  frame_merge(Frame1,
  108.                 Frame2,
  109.                 New_frame,
  110.                 Slot_merge_pred,
  111. è                Slot_append_pred),
  112.  
  113.      merges Frame1 and Frame2 into New_frame, where Slot_merge_pred
  114.      is used to create the output slot.
  115.  
  116.  
  117. */
  118.  
  119.  
  120. frame_merge(Frame1, Frame2, New_frame, Slot_merge_pred):-
  121.                                          /*  2 frames must have same name:  */
  122.     frame_info(Frame1, Class_name, Slot_list1),
  123.     frame_info(Frame2, Class_name, Slot_list2),
  124.                                          /*  Merge the tag/slot lists:      */
  125.     slot_list_merge(Slot_list1, Slot_list2, New_slot_list, Slot_merge_pred),
  126.                                          /*  Construct the new frame:       */
  127.     New_frame =.. [Class_name, New_slot_list],
  128.     !.
  129.  
  130.  
  131. /*-------------------- slot_list_merge -------------------------------------*/
  132.  
  133. /* slot_list_merge( Slot_list1,
  134.                     Slot_list2,
  135.                     New_slot_list,
  136.                     Slot_merge_pred  )
  137.  
  138.    merges a pair of slot lists, where Slot_merge_pred is used to
  139.    merge the individual slots.
  140.  
  141.  
  142.  
  143. */
  144.  
  145.      %  Terminate the recursion when both input lists are empty
  146. slot_list_merge( [],
  147.                  [],
  148.                  [],
  149.                  _  )  :- !.
  150.  
  151.      % If both frames contain a slot with Tag, then use Slot_merge_pred
  152.      % to unify them.  Make slot_list_merge fail if Slot_merge_pred
  153.      % sets FailFlag to fail.  This lets us distinguish between
  154.      % two slot values failing to merge but wanting to go on, and
  155.      % wanting to quit when merge fails on the slot values.
  156.      %
  157.      % In particular, Slot_merge_pred's behavior is related to what
  158.      % slot_list_merge should do in the following way:
  159.      %
  160.      %  What slot_list_merge does    What Slot_merge_pred does
  161.      %  when slot values fail to     when slot values fail to
  162.      %  merge                        merge
  163.      %
  164.      %  fail                         set  FailFlag to fail and succeed
  165.      %
  166. è     %  leave out the slot           fail
  167.      %
  168.  
  169. slot_list_merge( [Tag : Slot_val1 | Slot_list1],
  170.                  Slot_list2,
  171.                  [Tag : New_slot_val | New_slot_list],
  172.                  Slot_merge_pred):-
  173.                     % create a term which will try to merge the
  174.                     % slot with Tag in the slot list in arg. 1, with
  175.                     % some frame in the slot list in arg. 2
  176.     make_call_term(Slot_merge_pred,
  177.                    [Tag : Slot_val1, Slot_list2, New_slot_val, FailFlag],
  178.                    Term),
  179.     call(Term),     % call that term
  180.     !,
  181.                     % cut, fail if FailFlag == fail
  182.     FailFlag \== fail,
  183.                     % remove the slot that merges from the 2nd. slot list
  184.     remove_if_slot(Tag, Slot_list2, New_slot_list2),
  185.                     % recurse
  186.     slot_list_merge(Slot_list1,
  187.                     New_slot_list2,
  188.                     New_slot_list,
  189.                     Slot_merge_pred).
  190.  
  191.      % Skip Tag:Slot_val1 if Slot_merge_pred failed.
  192. slot_list_merge([_ | Slot_list1],
  193.                Slot_list2,
  194.                New_slot_list,
  195.                Slot_merge_pred):-
  196.     slot_list_merge(Slot_list1,
  197.                     Slot_list2,
  198.                     New_slot_list,
  199.                     Slot_merge_pred).
  200.  
  201.      % When the first slot list is exhausted, switch the slot list
  202.      % arguments, and recurse.
  203. slot_list_merge([],
  204.                 [Slot | Slot_list],
  205.                 New_slot_list,
  206.                 Slot_merge_pred):-
  207.     slot_list_merge([Slot | Slot_list],
  208.                     [],
  209.                     New_slot_list,
  210.                     Slot_merge_pred).
  211.  
  212.  
  213. Using Frame Unify
  214.  
  215.  
  216.  
  217. f(part(X)):- part(X).        /*  Include part frames in test    */
  218.  
  219. test_merge:-
  220.       New_pin_frame = part([part_number : lm309,
  221. è                          class : ic,
  222.                              /*  Append info. to 'type' slot    */
  223.                              /*  for pins 3 and 4:              */
  224.                           pin(3): pin([type : set([high_gain])]),
  225.                           pin(4): pin([type : set([high_gain])]),
  226.                              /*  Add new pin descr. for pin 8:  */
  227.                           pin(8): pin([device_number : 2,
  228.                                        type : set([output]),
  229.                                        milliamps : [0, 100],
  230.                                        volts : [-7, 7]
  231.                                       ])
  232.                          ]),
  233.       !,
  234.       f(Frame),
  235.       frame_unify( Frame,
  236.                    New_pin_frame,
  237.                    New_frame),
  238.       frame_display(New_frame).
  239.  
  240.