room.fkb
来自「prolog开发工具」· FKB 代码 · 共 385 行
FKB
385 行
% ROOM - a version of the room knowledge base for FOOPS. Much of the
% knowledge about furniture is stored in frames, thus simplifying
% the rule portion of the knowledge base.
frame(furniture, [
legal_types - [val [couch,chair,coffee_table,end_table,standing_lamp,
table_lamp,tv,knickknack]],
position - [def none, add pos_add],
length - [def 3],
place_on - [def floor],
can_hold - [def 0]]).
frame(couch, [
ako - [val furniture],
length - [def 6]]).
frame(chair, [
ako - [val furniture],
length - [def 3]]).
% A table is different from most furniture in that it can hold things
% on it.
frame(table, [
ako - [val furniture],
space - [def 4],
length - [def 4],
can_support - [def yes],
holding - [def []]]).
frame(end_table, [
ako - [val table],
length - [def 2]]).
frame(coffee_table, [
ako - [val table],
length - [def 4]]).
% electric is used as a super class for anything electrical. It contains
% the defaults for those attributes unique to electrical things.
frame(electric, [
needs_outlet - [def yes]]).
frame(lamp, [
ako - [val [furniture, electric]]]).
frame(standing_lamp, [
ako - [val lamp]]).
frame(table_lamp, [
ako - [val lamp],
place_on - [def table]]).
frame(tv, [
ako - [val [furniture, electric]],
place_on - [calc tv_support]]).
frame(knickknack, [
ako - [val furniture],
length - [def 1],
place_on - [def table]]).
frame(wall, [
length - [def 10],
outlets - [def 0],
space - [calc space_calc],
holding - [def []]]).
frame(door, [
ako - [val furniture],
length - [def 4]]).
frame(goal, []).
frame(recommend, []).
% calculate the available space if needed. The available space is
% computed from the length of the item minus the sum of the lengths of
% the items it is holding. The held items are in the holding list.
% The items in the list are identified only by their unique names.
% This is used by walls and tables.
space_calc(C,N,space-S) :-
getf(C,N,[length-L,holding-HList]),
sum_lengths(HList,0,HLen),
S is L - HLen.
sum_lengths([],L,L).
sum_lengths([C/N|T],X,L) :-
getf(C,N,[length-HL]),
XX is X + HL,
sum_lengths(T,XX,L).
% When placing the tv, check with the user to see if it goes on the
% floor or a table.
tv_support(tv,N,place_on-table) :-
nl,
write('Should the TV go on a table? '),
read(yes),
uptf(tv,N,[place_on-table]).
tv_support(tv,N,place_on-floor) :-
uptf(tv,N,[place_on-floor]).
% Whenever a piece is placed in position, update the holding list of the
% item which holds it (table or wall) and the available space. If something
% is placed in front of something else, then do nothing.
pos_add(_,_,position-frontof(X)) :-
uptf(C,N,[holding-[X]]).
pos_add(C,N,position-CP/P) :-
getf(CP,P,[space-OldS]),
getf(C,N,[length-L]),
NewS is OldS - L,
NewS >= 0,
uptf(CP,P,[holding-[C/N],space-NewS]).
pos_add(C,N,position-CP/P) :-
nl,write_line(['Not enough room on',CP,P,for,C,N]),
!,fail.
% The forward chaining rules of the system. They make use of call
% to activate some pure Prolog predicates at the end of the knowledge
% base. In particular, data gathering, and wall space calculations
% are done in Prolog.
% These are the terms which are initially stored in working storage.
% They set a goal used to force firing of certain preliminary rules,
% and various facts about the problem domain used by the actual
% configuration rules.
initial_data([goal - gather_data,
wall - north with [opposite-south,right-west,left-east],
wall - south with [opposite-north,right-east,left-west],
wall - east with [opposite-west,right-north,left-south],
wall - west with [opposite-east,right-south,left-north] ]).
% first gather data, then try the couch first.
rule 1:
[goal - gather_data]
==>
[call(gather_data),
assert( goal - couch_first )].
% Rules f1-f13 illustrate the strength of rule based programming.
% Each rule captures a rule of thumb used in configuring furniture
% in a living room. The rules are all independent, transparent,
% and can be easily maintained. Complexity can be added without
% concern for the flow of control.
% f1, f2 - place the couch first, it should be either opposite the
% door, or to its right, depending on which wall has more space.
rule f1:
[goal - couch_first,
couch - C with [position-none,length-LenC],
door - D with [position-wall/W],
wall - W with [opposite-OW,right-RW],
wall - OW with [space-SpOW],
wall - RW with [space-SpRW],
SpOW >= SpRW,
LenC =< SpOW]
==>
[update(couch - C with [position-wall/OW])].
rule f2:
[goal - couch_first,
couch - C with [position-none,length-LenC],
door - D with [position-wall/W],
wall - W with [opposite-OW,right-RW],
wall - OW with [space-SpOW],
wall - RW with [space-SpRW],
SpRW >= SpOW,
LenC =< SpRW]
==>
[update(couch - C with [position-wall/RW])].
% f3 - f3a the tv should be opposite the couch. if it needs a table, an
% end table should be placed under it, if no table is available put
% it on the floor anyway and recommend the purchase of a table. The rules
% first check to see if the couch has been placed.
rule f3:
[couch - C with [position-wall/W],
wall - W with [opposite-OW],
tv - TV with [position-none,place_on-floor]]
==>
[update(tv - TV with [position-wall/OW])].
rule f4:
[couch - C with [position-wall/W],
wall - W with [opposite-OW],
tv - TV with [position-none,place_on-table],
end_table - T with [position-none]]
==>
[update(end_table - T with [position-wall/OW]),
update(tv - TV with [position-end_table/T])].
rule f4a:
[tv - TV with [position-none,place_on-table]]
==>
[assert(recommend - R with [buy-['table for tv']])].
% f5 - the coffee table should be in front of the couch.
rule f5:
[coffee_table - CT with [position-none],
couch - C]
==>
[update(coffee_table - CT with [position-frontof(couch/C)])].
% f6, f7 - chairs should be on adjacent walls from the couch, which ever
% has the most space
rule f6:
[chair - Ch with [position-none],
couch - C with [position-wall/W],
wall - W with [right-RW,left-LW],
wall - RW with [space-SpR],
wall - LW with [space-SpL],
SpR >= SpL]
==>
[update(chair - Ch with [position-wall/RW])].
rule f7:
[chair - Ch with [position-none],
couch - C with [position-wall/W],
wall - W with [right-RW,left-LW],
wall - RW with [space-SpR],
wall - LW with [space-SpL],
SpL > SpR]
==>
[update(chair - Ch with [position-wall/LW])].
% put end_tables next to the couch first, then on the walls with
% the chairs
rule f9:
[end_table - ET with [position-none],
not tv - TV with [position-none,place_on-table],
couch - C with [position-wall/W],
not end_table - ET2 with [position-wall/W]]
==>
[update(end_table - ET with [position-wall/W])].
rule f10:
[end_table - ET with [position-none],
not tv - TV with [position-none,place_on-table],
chair - C with [position-wall/W],
not end_table - ET2 with [position-wall/W]]
==>
[update(end_table - ET with [position-wall/W])].
% put the table lamps on the end tables
rule f11:
[table_lamp - TL with [position-none],
end_table - ET with [position-wall/W]]
==>
[update( table_lamp - TL with [position-end_table/ET] )].
% put the knickknacks on anything which will hold them.
rule f11a:
[knickknack - KK with [position-none],
Table - T with [can_support-yes, position-wall/W]]
==>
[update( knickknack - KK with [position-Table/T] )].
% get extension cords if needed
rule f12:
[Thing - X with [needs_outlet-yes, position-wall/W],
wall - W with [outlets-0]]
==>
[assert(recommend - R with [buy-['extension cord'-W]])].
rule f13:
[Thing - X with [needs_outlet-yes, position-C/N],
C - N with [position-wall/W],
wall - W with [outlets-0]]
==>
[assert(recommend - R with [buy-['extension cord'-Thing/W]])].
% When no other rules fire, here is the summary
rule f14:
[]
==>
[call(output_data)].
% Prolog predicates called by various rules to perform functions better
% handled by Prolog.
% Gather the input data from the user.
gather_data :-
read_furniture,
read_walls.
read_furniture :-
get_frame(furniture,[legal_types-LT]),
write('Enter name of furniture at the prompt. It must be one of:'),nl,
write(LT),nl,
write('Enter ''end.'' to stop input.'),nl,
write('At the length prompt enter ''y.'' or a new number.'),nl,
repeat,
write('>'),read(X),
process_furn(X), !.
process_furn(end).
process_furn(X) :-
get_frame(X,[length-DL]),
write(length-DL),write('>'),
read(NL),
get_length(NL,DL,L),
addf(X,_,[length-L]),fail.
get_length(y,L,L) :- !.
get_length(L,_,L).
read_walls :-
nl,write('Enter data for the walls.'),nl,
write('What is the length of the north & south walls? '),
read(NSL),
uptf(wall,north,[length-NSL]),
uptf(wall,south,[length-NSL]),
write('What is the length of the east & west walls? '),
read(EWL),
uptf(wall,east,[length-EWL]),
uptf(wall,west,[length-EWL]),
write('Which wall has the door? '),
read(DoorWall),
write('What is its length? '),
read(DoorLength),
addf(door,D,[length-DoorLength]),
uptf(door,D,[position-wall/DoorWall]),
write('Which walls have outlets? (a list)'),
read(PlugWalls),
process_plugs(PlugWalls).
process_plugs([]) :- !.
process_plugs([H|T]) :-
uptf(wall,H,[outlets-1]),
!, process_plugs(T).
process_plugs(X) :-
uptf(wall,X,[outlets-1]).
output_data :-
write('The final results are:'),nl,
% print_frames,
output_walls,
output_tables,
output_recommends,
output_unplaced.
output_walls :-
getf(wall,W,[holding-HL]),
write_line([W,wall,holding|HL]),
fail.
output_walls.
output_tables :-
getf(C,N,[holding-HL]),
not C = wall,
write_line([C,N,holding|HL]),
fail.
output_tables.
output_recommends :-
getf(recommend,_,[buy-BL]),
write_line([purchase|BL]),
fail.
output_recommends.
output_unplaced :-
write('Unplaced furniture:'),nl,
getf(T,N,[position-none]),
write(T-N),nl,
fail.
output_unplaced.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?