Artificial Intelligence and Prolog
Copyright © 2020 Jiri Kriz, www.nosco.ch

13    Frames, Inheritance, Demons

Solution of Exercise 13

13.1    Frames

:- dynamic frame/1.  /* For SWI Prolg */
:- dynamic slot/1.
 
frame( Frame, Slot, Facet, Value) :- /* Frame must be instantiated */
     F =.. [ Frame, Slot, Facet, Value], call( F). 

frame_up( Frame, Slot, Facet, Value, Frame) :- 
     frame( Frame, Slot, Facet, Value).

frame_up( Frame, Slot, Facet, Value, FoundFrame) :-
     frame( Frame, is_a, value, Parent_Frame),
     frame_up( Parent_Frame, Slot, Facet, Value, FoundFrame).

delete( Frame) :-
	retractall( frame( Frame)),
	functor( Term, Frame, 3), retractall( Term).

get_value1( Frame, Slot, Value) :- frame( Frame, Slot, value, Value), !.
 
get_value( Frame, Slot, Value) :- 
	frame_up( Frame, Slot, Facet, V, _), 
	(Facet = value
		->	Value = V
		;	Facet = if_needed,
			Demon =.. [ V, Frame, Slot, Value], call( Demon)
	), !. /* Facet = if_added ignored */

put_value1( Frame, Slot, Value) :-
     F =.. [Frame, Slot, value,  _], (retract( F) ; true), !,
     F1 =.. [Frame, Slot, value, Value], assertz( F1), !.

put_value( Frame, Slot, Value) :-
	frame_up( Frame, Slot, Facet, V, ParFrame), !, 
	/* first slot in hierarchy */
	put_value_x( Frame, Slot, Facet, Value).

put_value_x( Frame, Slot, if_needed, Value) :- !, fail.
put_value_x( Frame, Slot, _, Value) :- 
	put_value1( Frame, Slot, Value), 
	(frame_up( Frame, Slot, if_added, D, _)
		-> Demon =.. [ D, Frame, Slot, Value], call( Demon)
		; true
	), !.
	
create_instance( Frame, InstanceFrame) :-
	frame( Frame),
	retractall( slot( _)),
	assertz( frame( InstanceFrame)),
	put_value1( InstanceFrame, is_a, Frame), 
	frame_up( Frame, Slot, Facet, Value, _),
		\+ slot( Slot),
		assert( slot( Slot)), 
    	Slot \= is_a, Facet \= if_needed,
		modify_value( InstanceFrame, Slot), 
	fail.
create_instance( Frame, InstanceFrame) :- 
	nl, write( InstanceFrame), write( ': finished').

modify_value( Frame, Slot) :-
	get_value( Frame, Slot, Value),
	nl, write( Frame), write( ': '), 
	write( Slot), write( ': '), write( Value),
	nl, write( 'New value? [end with . / x. for none] : '),  
	read( NewValue),
	modify_value1( Frame, Slot, Value, NewValue), !.

modify_value1( Frame, Slot, Value, x) :- !,
	write( Value).
modify_value1( Frame, Slot, Value, NewValue) :- 
	put_value( Frame, Slot, NewValue), write( NewValue), !.
modify_value1( Frame, Slot, Value, NewValue) :- 
	nl, write( 'This value could not be asserted (if_added failed)'),
	modify_value( Frame, Slot).

Back to example 13.1

13.2    Application: Hierarchy of Graphical Objectse

:- dynamic frame/1.  /* For SWI Prolg */
:- dynamic slot/1.

frame( graphical_object).
graphical_object( name, value, 'graphical object').
graphical_object( position, value, (0, 0)).

frame( rectangle).
rectangle( is_a, value, graphical_object).
rectangle( name, value, 'rectangle').
rectangle( site_x, value, X).
rectangle( site_y, value, Y).
rectangle( area, if_needed, rectangle_area).

rectangle_area( Frame, Slot, Value) :-
	get_value( Frame, site_x, X),
	get_value( Frame, site_y, Y),
	Value is X * Y, !.

frame( square).
square( is_a, value, rectangle).
square( name, value, 'square').
square( site, value, X).
square( site_x, if_needed, square_site).
square( site_y, if_needed, square_site).

square_site( Frame, Slot, Value) :-
	get_value( Frame, site, Value), !.

frame( ellipse).
ellipse( is_a, value, graphical_object).
ellipse( name, value, 'Ellipse').
ellipse( axis_x, value, X).
ellipse( axis_y, value, Y).
ellipse( area, if_needed, ellipse_area).

ellipse_area( Frame, Slot, Value) :-
	get_value( Frame, axis_x, X), 
	get_value( Frame, axis_y, Y),
	Value is 3.14 * X * Y / 4, !.
	
frame( circle).
circle( is_a, value, ellipse).
circle( name, value, 'circle').
circle( radius, value, X).
circle( axis_x, if_needed, circle_axis).
circle( axis_y, if_needed, circle_axis).

circle_axis( Frame, Slot, Value) :-
	get_value1( Frame, radius, Radius), Value is Radius * 2, !.
	
/* Testing 
?- create_instance(rectangle, r1).  (enter 2 and 3 for sites)
?- get_value(r1, area, A).  => A = 6
?- create_instance(square, q1).   (enter 3 for the site)
?- get_value(q1, site_y, Y).  => Y = 3
?- get_value(q1, area, A).  => A = 9
?- create_instance(circle, c1).   (enter 2 for the radius)
?- get_value(c1, axis_y, Y).  => Y = 4
?- get_value(c1, area, A).  => A = 12.56 area inherited from ellipse
*/

Back to example 13.2