home *** CD-ROM | disk | FTP | other *** search
-
- Frame Unification
-
-
- /* frame_unify(Frame1, Frame2, Unification )
- unifies two frames. Slots that are present in one frame and not in
- another are added to the unification, as if the slot had appeared in
- the frame where it was absent with a variable value.
- */
-
- /* frame_unify */
- frame_unify(Frame1, Frame2, Unification ):-
- % use frame_merge to implement frame_unify
- frame_merge(Frame1, Frame2, Unification, slot_unify).
-
-
-
- % slot_unify([Tag : Slot_val1, Slot_list2, Result, Fail_Flag ])
- %
- % unifies a slot with Tag with a member of a Slot_list2 if possible.
-
- % This first rule applies when Slot_list2 contains a slot with Tag.
- % Result is the unification if it exists.
- % Fail_Flag is set to fail if unification fails, to signal
- % frame_merge to fail.
- slot_unify([Tag : Slot_val1, Slot_list2, Result, Fail_Flag ]):-
- % get value for Tag
- slot_list_val(Tag, Slot_list2, Slot_val2),
- % If slot list 2 contains a slot with Tag,
- % stay in this rule
- !,
- % if these slot values unify
- ( value_unify(Slot_val1, Slot_val2, Result),
- % then stay in this alternative
- !,
- % and tell frame_merge not to fail
- Fail_Flag = true
- % if the slot values do not unify
- % tell frame_merge to fail
- ; Fail_Flag = false).
-
- % When the slot in arg. 1 does not appear in the
- % arg. 2 slot list, the result of unify is the slot
- % value in arg. 1
- slot_unify([ _ : Slot_val1, _ , Slot_val1 , _]):- !.
-
-
- /*-------------------- value_unify -----------------------------------------*/
-
- % value_unify unifies slot values
- % Arg 3 is the unification
- % this rule unifies those things that are not frames
- value_unify(Slot_val1, Slot_val2, Slot_val1):-
- Slot_val1 = Slot_val2, !.
- è % this rule unifies frames
- value_unify(Slot_val1, Slot_val2, Result ):-
- frame_merge(Slot_val1, Slot_val2, Result, slot_unify),
- !.
-
- % set unify slot values that are sets
- value_unify(Slot_val1, Slot_val2, Slot_val1) :-
- set_unify( Slot_val1, Slot_val2 ) ,!.
-
-
- Intersecting Frames
-
-
- /* frame_intersect creates a new frame from 2 existing frames by
- * keeping in slots that appear in both frames with values that unify,
- and letting the value of such slots be the unification of the input
- slot values
- * deleting all other slots, including those where the same tag has
- values in the two frames that don't unify.
- */
-
- frame_intersect(Frame1, Frame2, Intersection ):-
- % do this with frame_merge
- frame_merge(Frame1, Frame2, Intersection, slot_intersect).
-
- slot_intersect([Tag : Slot_val1, Slot_list2, New_slot_val, true ]):-
- slot_list_val(Tag, Slot_list2, Slot_val2), !,
- % merge slot values
- slot_merge0(Slot_val1, Slot_val2, New_slot_val, _ ).
-
- % note that when a slot with Tag is not in Slot_list2,
- % slot_intersect fails. This causes frame_merge to
- % leave the Tag slot out of the computed Intersection
-
- % unify slots if possible
- slot_merge0(Slot_val1, Slot_val2, Slot_val1, _):-
- Slot_val1 = Slot_val2, !.
-
- % intersect slot values that are frames
- slot_merge0(Slot_val1, Slot_val2, New_slot_val, _):-
- frame_merge(Slot_val1, Slot_val2, New_slot_val, slot_intersect),
- !.
-
- % set unify slot values that are sets
- slot_merge0(Slot_val1, Slot_val2, Slot_val1 , _):-
- set_unify( Slot_val1, Slot_val2 ) ,!.
-
-
- A General Frame Merging Predicate
-
-
- /* frame_merge(Frame1,
- Frame2,
- New_frame,
- Slot_merge_pred,è Slot_append_pred),
-
- merges Frame1 and Frame2 into New_frame, where Slot_merge_pred
- is used to create the output slot.
-
-
- */
-
-
- frame_merge(Frame1, Frame2, New_frame, Slot_merge_pred):-
- /* 2 frames must have same name: */
- frame_info(Frame1, Class_name, Slot_list1),
- frame_info(Frame2, Class_name, Slot_list2),
- /* Merge the tag/slot lists: */
- slot_list_merge(Slot_list1, Slot_list2, New_slot_list, Slot_merge_pred),
- /* Construct the new frame: */
- New_frame =.. [Class_name, New_slot_list],
- !.
-
-
- /*-------------------- slot_list_merge -------------------------------------*/
-
- /* slot_list_merge( Slot_list1,
- Slot_list2,
- New_slot_list,
- Slot_merge_pred )
-
- merges a pair of slot lists, where Slot_merge_pred is used to
- merge the individual slots.
-
-
-
- */
-
- % Terminate the recursion when both input lists are empty
- slot_list_merge( [],
- [],
- [],
- _ ) :- !.
-
- % If both frames contain a slot with Tag, then use Slot_merge_pred
- % to unify them. Make slot_list_merge fail if Slot_merge_pred
- % sets FailFlag to fail. This lets us distinguish between
- % two slot values failing to merge but wanting to go on, and
- % wanting to quit when merge fails on the slot values.
- %
- % In particular, Slot_merge_pred's behavior is related to what
- % slot_list_merge should do in the following way:
- %
- % What slot_list_merge does What Slot_merge_pred does
- % when slot values fail to when slot values fail to
- % merge merge
- %
- % fail set FailFlag to fail and succeed
- %è % leave out the slot fail
- %
-
- slot_list_merge( [Tag : Slot_val1 | Slot_list1],
- Slot_list2,
- [Tag : New_slot_val | New_slot_list],
- Slot_merge_pred):-
- % create a term which will try to merge the
- % slot with Tag in the slot list in arg. 1, with
- % some frame in the slot list in arg. 2
- make_call_term(Slot_merge_pred,
- [Tag : Slot_val1, Slot_list2, New_slot_val, FailFlag],
- Term),
- call(Term), % call that term
- !,
- % cut, fail if FailFlag == fail
- FailFlag \== fail,
- % remove the slot that merges from the 2nd. slot list
- remove_if_slot(Tag, Slot_list2, New_slot_list2),
- % recurse
- slot_list_merge(Slot_list1,
- New_slot_list2,
- New_slot_list,
- Slot_merge_pred).
-
- % Skip Tag:Slot_val1 if Slot_merge_pred failed.
- slot_list_merge([_ | Slot_list1],
- Slot_list2,
- New_slot_list,
- Slot_merge_pred):-
- slot_list_merge(Slot_list1,
- Slot_list2,
- New_slot_list,
- Slot_merge_pred).
-
- % When the first slot list is exhausted, switch the slot list
- % arguments, and recurse.
- slot_list_merge([],
- [Slot | Slot_list],
- New_slot_list,
- Slot_merge_pred):-
- slot_list_merge([Slot | Slot_list],
- [],
- New_slot_list,
- Slot_merge_pred).
-
-
- Using Frame Unify
-
-
-
- f(part(X)):- part(X). /* Include part frames in test */
-
- test_merge:-
- New_pin_frame = part([part_number : lm309,è class : ic,
- /* Append info. to 'type' slot */
- /* for pins 3 and 4: */
- pin(3): pin([type : set([high_gain])]),
- pin(4): pin([type : set([high_gain])]),
- /* Add new pin descr. for pin 8: */
- pin(8): pin([device_number : 2,
- type : set([output]),
- milliamps : [0, 100],
- volts : [-7, 7]
- ])
- ]),
- !,
- f(Frame),
- frame_unify( Frame,
- New_pin_frame,
- New_frame),
- frame_display(New_frame).
-