home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / CLIPPER / MISC / AIE8901.ZIP / AIAPRENT.CDE next >
Encoding:
Text File  |  1988-05-04  |  12.1 KB  |  457 lines

  1.  
  2. The complete listing for the Nuclear reactor simulator code to 
  3. accompany AI Apprentice for January 1989.
  4. Copyright 1989 Mark Minassi and AI EXPERT
  5.  
  6.  
  7. {$R-}    {Range checking off}
  8. {$B+}    {Boolean complete evaluation on}
  9. {$S+}    {Stack checking on}
  10. {$I+}    {I/O checking on}
  11. {$N-}    {No numeric coprocessor}
  12. {$M 65500,16384,655360} {Turbo 3 default stack and heap}
  13.  
  14. Program MoveRods;
  15.  
  16.  
  17. {AKT Version of rod moving problem converted to Turbo 4.0}
  18.  
  19. Uses
  20.   Dos;
  21.  
  22. Const
  23.  maxnode=3000;
  24.  {$I treecons.ins}
  25.  Nrules = 16;             {Problem Specific}
  26.  Goal = 1;
  27.  DeadEnd = 2;
  28.  UnFinished = 3;
  29.  Finished = 4;
  30.  EmptyCType=0;
  31.  
  32. {Goal State here can be any of four goals:  2534,2543,5234,5243}
  33.  
  34. Type CType = Integer;
  35.  
  36. Var
  37.  {$I treevars.ins}
  38.  
  39.  Hval:                               array[1..maxnode] of integer;
  40.  FoundGoal, Impossible, RuleApplied, FoundEarlier:    Boolean;
  41.  NN, Rule, TestState, GoalNode:                       Integer;
  42.  I, Cost,BestGoalSoFar:                                 Integer;
  43.  OK:                                                  Boolean;
  44.  T1,T2:                                               Real;
  45.  
  46.  {$I treeproc.ins}
  47.  
  48. function time:real;
  49. var  h,m,s,t:word;
  50. begin
  51.   gettime(h,m,s,t);
  52.   time := h*3600.0 + m*60.0 + s + t/100.0;
  53. end;
  54.  
  55. {Routines to allow new node attributes, the G and H functions}
  56.  
  57.  
  58. Function HValue(N:integer):integer;
  59. Begin
  60.   HValue:=HVal[Nodelist[N]];
  61. End;
  62.  
  63. Procedure SetHValue(N,V:integer);
  64. Begin
  65.   HVal[NodeList[N]] := V;
  66. End;
  67.  
  68. Procedure CheckForGoal(N:integer;Var FoundGoal:boolean);
  69. {This routine is problem specific }
  70. var X:integer;
  71. Begin
  72.   X := Characteristic(N);
  73.   If (X = 2534) or (X = 2543) or (X= 5243) or (X = 5234) then FoundGoal:=True
  74.   else FoundGoal := False;
  75. end;
  76.  
  77. **********************
  78. Kay: Here starts the function containing the six heuristics
  79. **********************
  80. Function FindH(TestState:Integer):integer;
  81. {This routine is problem specific}
  82. {Computes guess of distance from TestState to the goal}
  83. Var
  84.   X,B1,B2,U1,U2,Uouts,Bouts:integer;
  85.   BB1,UU1,BB2,UU2,B,U:integer;
  86. Begin
  87.   X := Characteristic(NN);
  88.   B1 := X div 1000; X:=X - B1*1000;
  89.   B2 := X div 100; X:= X - B2*100;
  90.   U1 := X div 10;  X:= X - U1*10;
  91.   U2 := X;
  92.  
  93.   {Count the number of borons and uraniums out of place}
  94.   if (B1<>2) and (B2<>2) then Bouts:=1 else Bouts:=0;
  95.   if (B1<>5) and (B2<>5) then Bouts := Bouts + 1;
  96.   if (U1<>3) and (U2<>3) then Uouts :=1 else Uouts:=0;
  97.   if (U1<>4) and (U2<>4) then Uouts := Uouts+1;
  98.  
  99.   {First formula in text:  no heuristic}
  100.   {FindH := 0;}
  101.  
  102.   {Second formula in text:  borons out of place + uraniums out of place}
  103.   {FindH := Bouts + Uouts;}
  104.  
  105.   {Third formula:  weight the borons and uranium by minimum cost}
  106.   {FindH := Bouts + 4*Uouts;}
  107.  
  108.   {Fourth:  sum minimum uranium move}
  109.   {FindH := abs(U1 - 3) + abs(U2 - 3) - 1;}
  110.  
  111.   {Fifth:  Weight the previous}
  112.   {FindH := (abs(U1 - 3) + abs(U2 - 3) - 1)*4;}
  113.  
  114.   {Sixth:  see text}
  115.   {BB1 := abs(B1-2) + abs(B2-5);
  116.   BB2 := abs(B1-5) + abs(B2-2);
  117.   UU1 := abs(U1-3) + abs(U2-4);
  118.   UU2 := abs(U2-3) + abs(U1-4);
  119.   if BB1<BB2 then B:=BB1 else B:=BB2;
  120.   if UU1<UU2 then U:=UU1*4 else U:=UU2*4;
  121.   FindH:=U+B;}
  122.  
  123.   Uncomment one of the above before using!
  124. End;
  125. **********************
  126. Kay: That's all.  No more of those.  The rest is cream.
  127. **********************
  128.  
  129.  
  130. Procedure CheckAncestry(Test,TestCost:integer;var OK:boolean);
  131. { Check to see that no node that is an ancestor of N has the same character-
  132.   istics of N}
  133. Var
  134.   M,X:integer;
  135. Begin
  136.   M:=Root;
  137.   OK:=true;
  138.   {Do branch & bound: if we've already found a goal node that is easier to
  139.    get to than this node, there's no point in considering this node}
  140.   If TestCost >= BestGoalSoFar Then OK:=False Else
  141.   Begin
  142.     While (M<>Null) and OK do
  143.       If (Characteristic(M)=Test) and (TestCost>=GValue(M)) then OK:=false
  144.       else M := NextNode(M);
  145.   End;
  146. End;
  147.  
  148.  
  149. Function BestUnfinished:integer;
  150. var n,bestf,BestNode,F:integer;
  151.     FoundOne,ExhaustedTree:boolean;
  152. Begin
  153.   { Find unfinished node with minimum value of g(node)}
  154.   if debug[5] then writeln(outfile,'  Started Search for best unfinished');
  155.   N := Root;
  156.   BestF := 1000;
  157.   While N<>Null Do
  158.   Begin
  159.     F := GValue(N) + HValue(N);
  160.     If (F < BestF) and (NodeValue(N)=Unfinished) Then
  161.     Begin
  162.       BestNode:=N;
  163.       BestF:=F;
  164.     End;
  165.     N:=NextNode(N);
  166.   End;
  167.   If BestF = 1000 then BestUnfinished:=Null else BestUnfinished:=BestNode;
  168.   if debug[5] then writeln(outfile,'  Ended search for best unfinished.');
  169. End;
  170.  
  171. Procedure ApplyRule(Rule,NN:integer;var RuleApplied:boolean;var TestState:
  172.                     integer; var Cost:Integer);
  173.  
  174. {This entire procedure is problem specific}
  175.  
  176. { Applies input rule Rule to node NN, if possible.  If it was possible,
  177.   reports in RuleApplied.  New state is in TestState}
  178.  
  179.  
  180. Var
  181.  
  182.     X,G3,G4,T:                  Integer; (* current state of jugs *)
  183.     Reactor:                    array[0..7] of integer;
  184.     N,B1,B2,U1,U2: Integer;
  185.  
  186. Function NextHole(Strt,Direction:integer):integer;
  187. Var
  188.   NH, J: integer;
  189.   NotFound:boolean;
  190.  
  191. Begin
  192.   If ((direction = 1) and (Strt = 6)) or ((direction = -1) and (Strt = 1))
  193.   Then NH:=0 Else
  194.   if reactor[Strt+direction]=0 then NH:=0 else
  195.   Begin
  196.     NotFound:=true;
  197.     J:=Strt + direction;
  198.     While (j>0) and (J<7) and NotFound do
  199.        If Reactor[J] = 0 then
  200.        begin
  201.          NH := J;
  202.          NotFound:=False;
  203.        end else J:=J+direction;
  204.     If NotFound then NH:=0;
  205.   End;
  206.   NextHole:=NH;
  207. End;
  208.  
  209. Begin
  210.  
  211.   RuleApplied:=False;
  212.   {Decode state}
  213.   X := Characteristic(NN);
  214.   If Debug[4] then writeln(outfile,'  Applying rule ',rule,' to ',X);
  215.   For I:=1 to 6 do Reactor[i]:=0;reactor[0]:=1;reactor[7]:=1;
  216.   B1 := X div 1000; X:=X - B1*1000;
  217.   B2 := X div 100; X:= X - B2*100;
  218.   U1 := X div 10;  X:= X - U1*10;
  219.   U2 := X;
  220.   reactor[B1]:=1;
  221.   reactor[B2]:=1;
  222.   reactor[U1]:=1;
  223.   reactor[U2]:=1;
  224.   If debug[4] then writeln(outfile,'  States: B1/2, U1/2=',B1,' ',B2,' ',U1
  225.                            ,' ',U2);
  226.  
  227.   Case Rule of
  228.       1: If (B1>1) and (Reactor[B1-1]=0) then
  229.          begin
  230.            B1:=B1-1;
  231.            Cost:=1;
  232.            RuleApplied:=True;
  233.          end;
  234.       2: If (B1<6) and (Reactor[B1+1]=0) then
  235.          begin
  236.            B1:=B1+1;
  237.            Cost:=1;
  238.            RuleApplied:=True;
  239.          end;
  240.       3: If (B2>1) and (Reactor[B2-1]=0) then
  241.          begin
  242.            B2:=B2-1;
  243.            Cost:=1;
  244.            RuleApplied:=True;
  245.          end;
  246.       4: If (B2<6) and (Reactor[B2+1]=0) then
  247.          begin
  248.            B2:=B2+1;
  249.            Cost:=1;
  250.            RuleApplied:=True;
  251.          end;
  252.       5: If (U1>1) and (Reactor[U1-1]=0) then
  253.          begin
  254.            U1:=U1-1;
  255.            Cost:=4;
  256.            RuleApplied:=True;
  257.          end;
  258.       6: If (U1<6) and (Reactor[U1+1]=0) then
  259.          begin
  260.            U1:=U1+1;
  261.            Cost:=4;
  262.            RuleApplied:=True;
  263.          end;
  264.       7: If (U2>1) and (Reactor[U2-1]=0) then
  265.          begin
  266.            U2:=U2-1;
  267.            Cost:=4;
  268.            RuleApplied:=True;
  269.          end;
  270.       8: If (U2<6) and (Reactor[U2+1]=0) then
  271.          begin
  272.            U2:=U2+1;
  273.            Cost:=4;
  274.            RuleApplied:=True;
  275.          end;
  276.  
  277.       {Nonadjacency Rules}
  278.  
  279.       9: Begin
  280.            N := NextHole(B1,1);
  281.            If N <> 0 Then
  282.            Begin
  283.              RuleApplied:=True;
  284.              Cost := 2 * Abs(N - B1);
  285.              B1 := N;
  286.            End;
  287.          End;
  288.      10: Begin
  289.            N := NextHole(B1,-1);
  290.            If N <> 0 Then
  291.            Begin
  292.              RuleApplied:=True;
  293.              Cost := 2 * Abs(N - B1);
  294.              B1 := N;
  295.            End;
  296.          End;
  297.      11: Begin
  298.            N := NextHole(B2,1);
  299.            If N <> 0 Then
  300.            Begin
  301.              RuleApplied:=True;
  302.              Cost := 2 * Abs(N - B2);
  303.              B2 := N;
  304.            End;
  305.          End;
  306.      12: Begin
  307.            N := NextHole(B2,-1);
  308.            If N <> 0 Then
  309.            Begin
  310.              RuleApplied:=True;
  311.              Cost := 2 * Abs(N - B2);
  312.              B2 := N;
  313.            End;
  314.          End;
  315.      13: Begin
  316.            N := NextHole(U1,1);
  317.            If N <> 0 Then
  318.            Begin
  319.              RuleApplied:=True;
  320.              Cost := 8 * Abs(N - U1);
  321.              U1 := N;
  322.            End;
  323.          End;
  324.      14: Begin
  325.            N := NextHole(U1,-1);
  326.            If N <> 0 Then
  327.            Begin
  328.              RuleApplied:=True;
  329.              Cost := 8 * Abs(N - U1);
  330.              U1 := N;
  331.            End;
  332.          End;
  333.      15: Begin
  334.            N := NextHole(U2,1);
  335.            If N <> 0 Then
  336.            Begin
  337.              RuleApplied:=True;
  338.              Cost := 8 * Abs(N - U2);
  339.              U2 := N;
  340.            End;
  341.          End;
  342.      16: Begin
  343.            N := NextHole(U2,-1);
  344.            If N <> 0 Then
  345.            Begin
  346.              RuleApplied:=True;
  347.              Cost := 8 * Abs(N - U2);
  348.              U2 := N;
  349.            End;
  350.          End;
  351.  
  352.  
  353.   End; { Case statement}
  354.   If RuleApplied then TestState:=1000*B1 + 100*B2 + 10*U1 + U2;
  355.   If Debug[4] and RuleApplied then writeln(outfile,'    New state:',TestState);
  356. End;
  357.  
  358. Procedure AddNode(NN,TestState,Cost:integer);
  359. Var NewNd,NewG: Integer;
  360.     Temp:boolean;
  361. Begin
  362.   NewG := GValue(NN) + Cost;
  363.   CreateNode(NN, TestState, NewNd);
  364.   SetValue(NewNd,UnFinished);
  365.   SetGValue(NewNd,NewG); {Set G value = parent g + cost of
  366.                                      getting from parent}
  367.   SetHValue(NewNd,FindH(TestState)); {Compute H value}
  368.   {Maintain BestGoalSoFar}
  369.   CheckForGoal(NewNd,Temp);
  370.   If Temp and (NewG < BestGoalSoFar) then BestGoalSoFar:=NewG;
  371. End;
  372.  
  373. Procedure TraceBack(GoalNode:integer);
  374. Var trace: array[1..40] of integer;
  375.     T,N,I  : integer;
  376.  
  377. {Starting from the Goal Node, work backwards to the root node, then
  378.  report the entire path. }
  379.  
  380. Begin
  381.   T:=GoalNode;
  382.   N:=0;
  383.   While T <> Root do
  384.   Begin
  385.     N:=N+1;
  386.     Trace[N]:=T;
  387.     T:=Parent(T);
  388.   End;
  389.   N:=N+1;
  390.   Trace[N]:=Root;
  391.   For I:=N downto 1 do writeln(Characteristic(Trace[i]));
  392. End;
  393.  
  394. { M A I N    P R O G R A M}
  395.  
  396. Begin
  397.   For I:=1 to 5 do debug[i]:=false;debug[2]:=true;
  398.   assign(outfile,'debug.msgs');
  399.   rewrite(outfile);
  400.   {Set things up}
  401.   InitTree;
  402.   SetCharacteristic(Root,3546);    {Problem Specific}
  403.   SetValue(Root,Unfinished);
  404.   SetGValue(Root,0);
  405.   FoundGoal:=False;
  406.   Impossible:=False;
  407.   BestGoalSoFar:=1000;
  408.   T1 := Time;
  409.  
  410.   While (not FoundGoal) and (not Impossible) Do
  411.   Begin
  412.     {Are there any unfinished nodes left?}
  413.     NN:=BestUnfinished;
  414.     {Check to see if it is the goal node}
  415.     CheckForGoal(NN,FoundGoal);
  416.     If Not FoundGoal then
  417.     Begin
  418.       if debug[5] then writeln(outfile,'Considering ',Characteristic(NN),
  419.                                ' Cost=',GValue(NN));
  420.       If NN=Null then Impossible:=true else
  421.       Begin {Generate offspring nodes}
  422.         For Rule:=1 to NRules Do
  423.         Begin
  424.           ApplyRule(Rule,NN,RuleApplied,TestState,Cost);
  425.           If RuleApplied then
  426.           Begin {Ensure no parents are identical.  Also, ensure that an equal
  427.         or lower cost path doesn't exist already.  Finally, do branch & bound
  428.         Notice that you do this only on the G value.  Don't use H value.}
  429.  
  430.             CheckAncestry(TestState,Cost+GValue(NN),OK);
  431.             If OK then
  432.             Begin
  433.               AddNode(NN,TestState,Cost);
  434.               if debug[5] then writeln(outfile,' Created ',TestState,
  435.                                 ' Cost=',Cost+GValue(NN));
  436.             End;
  437.           End;
  438.         End; {Trying all rules}
  439.         {Set node NN finished}
  440.         SetValue(NN,Finished);
  441.       End; { expanding space }
  442.     End;  { search clause if goal not found yet}
  443.   End; { While clause }
  444.  
  445.   If Impossible then writeln('No possible solution to the problem.')
  446.                 else begin
  447.                        writeln('Solution found.');
  448.                        traceback(NN);
  449.                        writeln('Cost: ',Gvalue(NN));
  450.                      end;
  451. T2 := Time;
  452. Writeln('Took ',(T2-T1):7:2,' seconds.');
  453. Writeln(nnodes,' nodes generated.');
  454. End.
  455.                      end;
  456. T2 := Time;
  457. Writeln('Took ',(T2-