room.okb
来自「prolog开发工具」· OKB 代码 · 共 313 行
OKB
313 行
% ROOM is an expert system for placing furniture in a living room.
% It is written using the OOPS production system rules language.
% It is only designed to illustrate the use of a forward chaining
% rules based language for solving configuration problems. As such
% it makes many simplifying assumptions (such as furniture has no
% width). It just decides which wall each item goes on, and does
% not decide the relative placement on the wall.
% Furniture to be placed in the room is stored in terms of the form
% "furniture(item,length)". The rules look for unplaced furniture,
% and if found attempt to place it according to the rules of thumb.
% Once placed, the available space on a wall is updated, the furniture
% is ed on a wall with a term of the form "position(item,wall)",
% and the original "furniture" term is removed.
% 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(place_furniture),
not_end_yet,
legal_furniture([couch, chair, table_lamp, end_table,
coffee_table, tv, standing_lamp, end]),
opposite(north,south),
opposite(south,north),
opposite(east,west),
opposite(west,east),
right(north,west),
right(west,south),
right(south,east),
right(east,north),
left(north,east),
left(east,south),
left(south,west),
left(west,north)]).
% Rules 1-8 are an example of how to generate procedural behavior
% from a non-procedural rule language. These rules force a series
% of prompts and gather data from the user on the room and furniture
% to be configured. They are included to illustrate the kludgy
% nature of production systems in a conventional setting.
% This is in contrast to rules f1-f14 which elegantly configure the room.
rule 1:
[1: goal(place_furniture), % The initial goal causes a rule to
2: legal_furniture(LF)] % to fire with introductory information.
==> % It will set a new goal.
[retract(1),
nl,
write('Enter a single item of furniture at each prompt.'),nl,
write('Include the width (in feet) of each item.'),nl,
write('The format is Item:Length.'),nl,nl,
write('The legal values are:'),nl,
write(LF),nl,nl,
write('When there is no more furniture, enter "end:end."'),nl,
assert(goal(read_furniture))].
rule 2:
[1: furniture(end,end), % When the furniture is read
2: goal(read_furniture)] % set the new goal of reading
==> % reading wall sizes
[retract(all),
assert(goal(read_walls))].
rule 3:
[1: goal(read_furniture), % Loop to read furniture.
2: legal_furniture(LF)]
==>
[prompt('furniture> ', F:L),
member(F,LF),
assert(furniture(F,L))].
rule 4: % If rule 3 matched and failed
[1: goal(read_furniture), % the action, then member must
2: legal_furniture(LF)] % have failed.
==>
[write('Unknown piece of furniture, must be one of:'),nl,
write(LF),nl].
rule 5:
[1: goal(read_walls)]
==>
[retract(1),
prompt('What is the length of the north and south sides? ', LengthNS),
prompt('What is the length of the east and west sides? ', LengthEW),
assert(wall(north,LengthNS)),
assert(wall(south,LengthNS)),
assert(wall(east,LengthEW)),
assert(wall(west,LengthEW)),
assert(goal(find_door))].
rule 6:
[1: goal(find_door)]
==>
[retract(1),
prompt('Which wall has the door? ', DoorWall),
prompt('What is the width of the door? ', DoorWidth),
retract(wall(DoorWall,X)),
NewWidth = X - DoorWidth,
assert(wall(DoorWall, NewWidth)),
assert(position(door,DoorWall)),
assert(goal(find_plugs)),
write('Which walls have plugs? "end." when no more plugs:'),nl].
rule 7:
[1: goal(find_plugs),
2: position(plug,end)]
==>
[retract(all)].
rule 8:
[1: goal(find_plugs)]
==>
[prompt('Side: ', Wall),
assert(position(plug,Wall))].
% 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 is longer.
rule f1:
[1: furniture(couch,LenC), % an unplaced couch
position(door, DoorWall), % find the wall with the door
opposite(DoorWall, OW), % the wall opposite the door
right(DoorWall, RW), % the wall to the right of the door
2: wall(OW, LenOW), % available space opposite
wall(RW, LenRW), % available space to the right
LenOW >= LenRW, % if opposite wall bigger than right
LenC =< LenOW] % length of couch less than wall space
==>
[retract(1), % remove the furniture term
assert(position(couch, OW)), % assert the new position
retract(2), % remove the old wall,length
NewSpace = LenOW - LenC, % calculate the space now available
assert(wall(OW, NewSpace))]. % assert the wall with new space left
rule f2:
[1: furniture(couch,LenC),
2: position(door, DoorWall),
3: opposite(DoorWall, OW),
4: right(DoorWall, RW),
5: wall(OW, LenOW),
6: wall(RW, LenRW),
LenOW =< LenRW,
LenC =< LenRW]
==>
[retract(1),
assert(position(couch, RW)),
retract(6),
NewSpace = LenRW - LenC,
assert(wall(RW, NewSpace))].
% f3 - the tv should be opposite the couch
rule f3:
[1: furniture(tv,LenTV),
2: position(couch, CW),
3: opposite(CW, W),
4: wall(W, LenW),
LenW >= LenTV]
==>
[retract(1),
assert(position(tv, W)),
retract(4),
NewSpace = LenW - LenTV,
assert(wall(W, NewSpace))].
% f4, f5 - the coffee table should be in front of the couch or if there
% is no couch, in front of a chair.
rule f4:
[1: furniture(coffee_table,_),
2: position(couch, CW)]
==>
[retract(1),
assert(position(coffee_table, front_of_couch:CW))].
rule f5:
[1: furniture(coffee_table,_),
2: position(chair, CW)]
==>
[retract(1),
assert(position(coffee_table, front_of_chair:CW))].
% f6, f7 - chairs should be on adjacent walls from the couch
rule f6:
[1: furniture(chair,LC),
position(couch, CW),
right(CW, ChWa),
left(CW, ChWb),
4: wall(ChWa, La),
wall(ChWb, Lb),
La >= Lb,
La >= LC]
==>
[retract(1),
assert(position(chair, ChWa)),
NewSpace = La - LC,
retract(4),
assert(wall(ChWa, NewSpace))].
rule f7:
[1: furniture(chair,LC),
position(couch, CW),
right(CW, ChWa),
left(CW, ChWb),
wall(ChWa, La),
4: wall(ChWb, Lb),
La =< Lb,
Lb >= LC]
==>
[retract(1),
assert(position(chair, ChWb)),
NewSpace = Lb - LC,
retract(4),
assert(wall(ChWb, NewSpace))].
rule f8:
[1: furniture(chair,LC),
2: position(couch, CW),
3: left(CW, ChW),
4: wall(ChW, L),
L >= LC]
==>
[retract(1),
assert(position(chair, ChW)),
NewSpace = L - LC,
retract(4),
assert(wall(ChW, NewSpace))].
% put end_tables next to the couch first, then on the walls with
% the chairs
rule f9:
[1: furniture(end_table,TL),
2: position(couch, W),
3: not(position(end_table, W)),
4: wall(W, L),
L >= TL]
==>
[retract(1),
assert(position(end_table, W, nolamp)),
NewSpace = L - TL,
retract(4),
assert(wall(W, NewSpace))].
rule f10:
[1: furniture(end_table,TL),
2: position(chair, W),
3: not(position(end_table, W)),
4: wall(W, L),
L >= TL]
==>
[retract(1),
assert(position(end_table, W, nolamp)),
NewSpace = L - TL,
retract(4),
assert(wall(W, NewSpace))].
% put the table lamps on the end tables
rule f11:
[1: furniture(table_lamp,_),
2: position(end_table, W, nolamp)]
==>
[retract(all),
assert(position(table_lamp, W)),
assert(position(end_table, W, lamp))].
% get extension cords if needed
rule f12:
[1: position(tv, W),
2: not(position(plug, W))]
==>
[assert(buy(extension_cord, W)),
assert(position(plug, W))].
rule f13:
[1: position(table_lamp, W),
2: not(position(plug, W))]
==>
[assert(buy(extension_cord, W)),
assert(position(plug, W))].
% When no other rules fire, here is the summary
rule f14:
[1: not_end_yet]
==>
[retract(1),
write('Recommendations:'),nl,nl,
write('furniture positions:'),nl,nl,
list(position(_,_)),
list(position(_,_,_)),nl,
write('purchase recommendations:'),nl,nl,
list(buy(_,_)),nl,
write('furniture which wouldn''t fit:'),nl,nl,
list(furniture(_,_)),nl,nl].
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?