chiark / gitweb /
main resolution algorithm
authorian <ian>
Fri, 28 Mar 2008 22:34:31 +0000 (22:34 +0000)
committerian <ian>
Fri, 28 Mar 2008 22:34:31 +0000 (22:34 +0000)
hostside/TODO
hostside/realtime.h
hostside/resolve.c
hostside/safety.h
hostside/startup.c

index 7438dfd5fc8958569d47cfb8e135287b2db3749c..a828be0fe9657b2f62926d674b4747a3559db761 100644 (file)
@@ -4,6 +4,9 @@ before can test
        write trivial initial settlement to get data array right
        write out layout data on crash
        check that everything in Train and Segment is init'd
+       set polarity on resolution startup before we poweron
+       do lay_train in resolution, or moral equivalent
+       set points under existing trains according to existing movposcomb
 
 dunno but maybe before can test
        train speed curve measurements
@@ -12,6 +15,7 @@ dunno but maybe before can test
 things not yet considered at all in safety code
        coming up against points the wrong way
        min. curve specifications
+       crossovers
 
 initialise safety_state with appropriate stuff
 
index fecb36bf4eaad411c215ac3e2c94d941c44c7cd4..ec9019155b28fadba2b72defe8984cda886872a6 100644 (file)
@@ -90,7 +90,8 @@ void serial_moredata(PicInsn *buf);
 extern StartupState sta_state;
 extern const char *const stastatelist[];
 
-int resolve_failed(void); /* from resolve.c */
+void resolve_begin(void); /* from resolve.c */
+int resolve_complete(void);
 
 /*---------- from/for record.c and persist.c ----------*/
 
index 4c27aaa85d9d02f0b04dc65e7b6438834df23bef..d3aaed133511645f658d3f7c26ed293ed37cf105 100644 (file)
 
 #include "realtime.h"
 
-typedef enum {
-  RR_N, RR_E, RR_H
-} ResolutionResult;
+/* values for Train->resolution: */
+#define RR_N 0u
+#define RR_E 1u
+#define RR_H 2u
 
-typedef struct {
-  SegmentNum d; /* proof element d from 3a, 3b, 3c */ /* sentinel has NOTA */
-  TrainNum t; /* proof element t from 3b(ii) and 3b(iii) */
-} ProofElement;
-
-typedef struct {
-  SegmentNum d1; /* proof element d' from 3b(iii) */ /* sentinel has NOTA */
-  TrainNum t2; /* proof element t'' from 3b(iii) */
-} Clash;
-
-typedef struct {
-  ResolutionResult r; /* R(t) */
-  ProofElement why_eh[NUM_SEGMENTS]; /* entry for 3a's t, proof of R(t)=E
-                                     * entry for 3b's t', proof of R(t')=H */
-  Clash whynot_e[NUM_SEGMENTS]; /* in the entry for train t' from 3b(iii),
-                                * clashes d' and corresponding t'' */
-} TrainResolution;
-
-static TrainResolution *rx; /* [0,n_trains> */
-/* We record U in segi->tr_updated and D in segi->res_detect */
+/* We record R in tra->resolution,
+ * U in segi->tr_updated and D in segi->res_detect */
 
 void resolve_begin(void) {
   SEG_IV;
   FOR_SEG {
     seg->res_detect= 0;
+    seg->tr_updated= 0;
   }
 }
 
 #define NOOP (void)0
 
-#define TRAIN(t,tra)                           \
-  Train *t= (tra);                             \
-  TrainNum t##n= (tra) - trains;               \
-  TrainResolution *t##r= rx + t##n;
-
-#define BLANKREASONS(array, sentinelmember)    \
-    ((*(SegmentNum*)(array))= NOTA(Segment))
-
-#define ADDREASON(array, newvalue) do{                 \
-    typeof(*(array)) addreason_i;                      \
-    for (addreason_i=(array);                          \
-         ;                                             \
-         addreason_i++) {                              \
-      assert(addreason_i < ARRAY_END(array));          \
-      if (!SOMEP(*(SegmentNum*)(addreason_i))) {       \
-       *addreason_i++= newvalue;                       \
-        *(SegmentNum*)addreason_i= NOTA(Segment);      \
-        assert(addreason_i < ARRAY_END(array));                \
-       break;                                          \
-      }                                                        \
-      if (*addreason_i == newvalue)                    \
-       break;                                          \
-    }                                                  \
-  }while(0)
+int resolve_complete(void) {
+  int problems, phase, nextphase;
+  TRAIN_ITERVARS(t);
+  TRAIN_ITERVARS(t2);
+  TRAIN_ITERVARS(tplus);
+  SEGMENT_ITERVARS(d);
+  SEGMENT_ITERVARS(d1);
+  SEGMENT_ITERVARS(dplus);
 
-#define FOR_TRAIN_R(t)  FOR_TRAIN(t, t##r=rx, t##r++)
+  problems= 0;
+  FOR_TRAIN(t,NOOP,NOOP) t->resolution= RR_N;
 
-int resolve_complete(void) {
-  int problems;
-  SEG_IV;
+  for (phase=0; phase<3; phase=nextphase) {
+    nextphase= phase+1;
+    oprintf(UPO, "resolving iteration %c\n", "EHX"[phase]);
 
-  rx= mmalloc(sizeof(*rx) * n_trains);
-  FOR_TRAIN_R(t) {
-    tr->r= RR_N;
-    BLANKREASONS(tr->why_eh);
-    BLANKREASONS(tr->whynot_e);
-  }
+    oprintf(UPO, "resolving  calculate-u\n");
 
-  while 1 {
     FOR_SEGMENT(d, NOOP, NOOP) { /* calculate U */
       unsigned updated= 0;
-      if (d->home) { TRAIN(t, d->home); if (tr->r == HH_H) updated++; }
-      if (d->owner) { TRAIN(t, d->owner); if (tr->r == HH_E) updated++; }
+
+#define ADDTO_U_EH(homeowner,HH_HE,string)                     \
+      if (d->homeowner && d->homeowner->resolution == HH_HE) { \
+       oprintf(UPO, "resolving   covered @%s " string " %s\n", \
+               di->pname, d->homeowner->pname);                \
+       updated++;                                              \
+      }
+      ADDTO_U_EH(home,  RR_H, "at-home");
+      ADDTO_U_EH(owner, RR_E, "as-expected");
+
       assert(updated<=1);
       d->tr_updated= updated;
     }
 
+    oprintf(UPO, "resolving  searching\n");
     FOR_SEGMENT(d, NOOP, NOOP) {
       if (!(d->res_detect && !d->tr_updated))
        continue;
       /* 3. we have a violation of D \subset U, namely d */
 
-      ProofElement why_h;
-      why_h.d= d;
-      why_h.t= NOTA(Train);
-      
+      oprintf(UPO, "resolving   violation @%s\n", di->pname);
+      nextphase= 0;
+
       if (d->owner) { /* 3a perhaps */
-       TRAIN(t, d->owner);  /* t st d \elem E(t) */
-       why_h.t= tn;
-       if (tr->r == RR_H)
+       oprintf(UPO, "resolving    expected %s\n", t->pname);
+
+       if (t->resolution == RR_H) {
+         oprintf(UPO, "resolving     expected-is-at-home\n");
          goto not_3a;
+       }
 
-       if (tr->r == RR_E)
+       if (t->resolution == RR_E)
          /* we added it in this sweep and have found another d */
          goto already_3a;
-       assert(tr->r == RR_N);
+       assert(t->resolution == RR_N);
 
        /* check E(t) \disjoint U */
+       int clashes= 0;
        FOR_SEGMENT(d1, NOOP, NOOP) {
          if (d1->owner == t && d1->tr_updated) {
            FOR_TRAIN(t2, NOOP, NOOP) {
-             if (t2r->r == HH_H && d1->owner == t2) {
-               Clash clash;
-               clash.d1= d1;
-               clash.t2= t2;
-               ADDREASON(tr->whynot_e, clash);
+             if (t2->resolution == RR_H && d1->owner == t2) {
+               oprintf(UPO, "resolving     clash @%s %s\n",
+                       d1i->pname, t2->pname);
+               clashes++;
              }
            }
          }
        }
-       if (SOMEP(tr->whynot_e[0]))
+       if (clashes) {
+         oprintf(UPO, "resolving    expected-has-clashes\n");
          goto not_3a;
+       }
 
        /* Yay! 3a. */
-       tr->r= RR_E;
+       t->resolution= RR_E;
       already_3a:
-       ProofElement why_e;
-       why_e.d= d;
-       why_e.t= NOTA(Train);
-       ADDREASON(tr->why_eh, why_e);
+       oprintf(UPO, "resolving    supposing %s as-expected\n", t->pname);
        continue;
       }
-
     not_3a:
+
       if (d->home) { /* 3b then */
-       TRAIN(t1, d->home); /* t' st d \elem H(t') */
-       
-       if (tr->r == RR_H)
-         /* added in this sweep, have found another d */
-         goto already_3b;
+       if (phase<1)
+         continue;
 
-       FOR_SEGMENT(dplus, NOOP, NOOP) {
-         if (!dplus->owner) continue;
-         TRAIN(tplus, dplus->owner);
-         if (tplusr->r != HH_E) continue;
-         dplus->tr_updated= 0;
-       }
-       FOR_TRAIN_R(tplus) {
-         BLANKREASONS(tplusr->whynot_e);
-         if (tplusr->r == HH_E) {
-           tplusr->r= HH_N;
-           BLANKREASONS(tplusr->why_eh);
+       Train *t1= d->home; /* t' st d \elem H(t') */
+       oprintf(UPO, "resolving    home %s\n", t1->pname);
+       
+       oprintf(UPO, "resolving    reset-expecteds\n");
+       FOR_TRAIN(tplus, NOOP,NOOP) {
+         if (tplus->resolution == RR_E) {
+           oprintf(UPO, "resolving    supposing %s absent\n", tplus->pname);
+           tplus->resolution= RR_N;
          }
        }
+       /* Now must trim U to correspond to our setting of R(t+)=N
+        * so that any other implied Hs are spotted. */
+       FOR_SEGMENT(dplus, NOOP,NOOP) {
+         Train *tplus= dplus->owner;
+         if (!(tplus && tplus->resolution == RR_E)) continue;
+         dplus->tr_updated= 0;
+       }
 
-       tr->r= RR_H;
-       BLANKREASONS(tr->why_eh);
-
-      already_3b:
-       ADDREASON(tr->why_eh, why_h);
-       fixme /* need to make us scan for case 3a first, so that
-                when we report a problem we report as reasons
-                for some H only those ds which would not have
-                been satisfied by E.  perhaps scan for Es
-                and then only for Hs, each time ? */
-       
-         /* tr->whynot_e is already filled in */
-         goto not_3a;
-       assert(tr->r == RR_N);
-
-
-       if (tr->whynot_e
-       
-       
-         goto not_e;
-       
-         
-
-      FOR_TRAIN(t_, NOOP, NOOP) {
-       if (
-       
+       t1->resolution= RR_H;
 
-       goto found;
+       oprintf(UPO, "resolving    supposing %s at-home\n", t1->pname);
+       continue;
       }
-    /* no (more) unexpected trains */
-    break;
 
-  found:
-    
-    
-    if (problems) oprintf(UPO,"resolve problems %d\n",problems);
-    return !problems;
+      /* Oh dear, 3c. */
+      if (phase<2)
+       continue;
 
-  found:
-    if (!seg->home) {
-      /* completely unexpected presence of train */
-      oprintf(UPO,"resolve inexplicable %s\n",segi->pname);
-      seg->res_detect= 0;
+      oprintf(UPO, "resolving    inexplicable @%s\n", di->pname);
+      d->res_detect= 0;
       problems++;
-      continue;
     }
-    /* train put back in its home (we assume!) */
-    resolve_send_home(seg->home,seg,"spotted");
-    
-
+  }
     
-  SEGMENT_ITERVARS(inner);
+  if (problems) oprintf(UPO,"resolve problems %d\n",problems);
 
-      if (inner->home == seg->home) oprintf(UPO," +%s",inneri->pname);
-      
+  FOR_SEGMENT(d,NOOP,NOOP)
+    d->tr_updated= d->res_detect= 0;
 
-      if (inner->train
-      
-       } else {
-         
-         
+  if (problems)
+    return -1;
 
-  FOR_SEG
   return 0;
 }
-
-
-
-fixme deal with  until_detect etc.
-    seg->tr_updated= 0;
-
-static void send_home(Train *tra, const char *why, Segment *why_seg) {
-  const char *trap;
-
-  trap= tra->i->pname;
-  oprintf(UPO,"resolve home %s %s %s\n",trap, why, why_seg->i->pname);
-  
-  FOR_SEG {
-    if (seg->home==tra && seg->owner && seg->owner!=tra)
-      send_home(seg->owner,"displaced",seg);
-
-    if (seg->owner==tra && seg->home!=tra) {
-      oprintf(UPO,"resolve home %s nolonger %s\n",trap, seg->i->pname);
-      seg->owner= 0;
-    }
-
-    }
-    
-      
-  
index def129d90b46a159281fb160e7b3d7c4257ec7db..9d96fb0d393381797fdcb0e69be30cef92982ee0 100644 (file)
@@ -49,7 +49,10 @@ struct Train {
     backwards:1, /* train is moving backwards wrt its own front and back */
 
   /* Speed: */
-    estopping:1; /* set and cleared by speed.c */
+    estopping:1, /* set and cleared by speed.c */
+
+  /* Startup resolution (resolve.c): */
+    resolution:2;
   Speed speed; /* when accelerating/decelerating, is maximum at this moment */
 
   struct {
index 155ce12726668dd939e7359dc7645dfc2014331a..b30c766a59d103276fc9a0e34a2cccd9f093c12f 100644 (file)
@@ -49,8 +49,6 @@ static void initial_ping(void) {
 void sta_startup(void) { sta_goto(Sta_Flush); }
 
 static void sta_goto(StartupState new_state) {
-  SEG_IV;
-  
   toev_stop(&sta_toev);
   sta_toev.callback= timedout_onward;
   sta_toev.duration= -1;
@@ -81,11 +79,11 @@ static void sta_goto(StartupState new_state) {
   case Sta_Fault:                                                  break;
   case Sta_Settling:                        enco_pic_off(&piob);   break;
   case Sta_Resolving:
-    FOR_SEG seg->res_detect= 0;
+    resolve_begin();
     enco_pic_on(&piob);
     break;
   case Sta_Run:
-    if (resolve_failed)
+    if (resolve_complete() <0)
       /* in this case, we get stuck - user has to power cycle the layout */
       return;
     persist_install();