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 + -
显示快捷键?