Advertisement
Guest User

Untitled

a guest
Mar 8th, 2015
1,172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 5.38 KB | None | 0 0
  1. module trainsearch;
  2.  
  3. void main() {
  4.     int[][] paths;
  5.     // There are only six paths through the
  6.     // intersection that a train can take.
  7.     // side paths
  8.     paths ~= [349, 350];
  9.     paths ~= [354, 353];
  10.     paths ~= [352, 351];
  11.     // center paths
  12.     paths ~= [349, 344, 353];
  13.     paths ~= [354, 344, 351];
  14.     paths ~= [352, 344, 350];
  15.     /*
  16.     paths ~= [2];
  17.     paths ~= [3];
  18.     paths ~= [4];
  19.     paths ~= [2, 1, 4];
  20.     paths ~= [4, 1, 3];
  21.     paths ~= [3, 1, 2];
  22.     */
  23.     /*
  24.     paths ~= [327, 338];
  25.     paths ~= [327, 344, 334];
  26.     paths ~= [345, 334];
  27.     paths ~= [345, 344, 330];
  28.     paths ~= [331, 330];
  29.     paths ~= [331, 344, 338];
  30.     */
  31.     // What is a deadlock?
  32.     // A deadlock is a state, created when multiple
  33.     // trains enter the intersection at once, where no
  34.     // train can claim the next area of its path.
  35.     int[] entry_blocks;
  36.     for auto path <- paths {
  37.         int block = path[0];
  38.         for int i <- entry_blocks if (i == block) break;
  39.         then entry_blocks ~= block;
  40.     }
  41.     as_type x (int block, int train, bool enter, string delegate(x) info, x next)* block_actions;
  42.     // continuation passing style
  43.     void record_action(int block, int train, bool enter, void delegate() cont) {
  44.         bool is_free = true;
  45.         for (auto ptr = block_actions; ptr; ptr = ptr.next) {
  46.             if (ptr.block == block) {
  47.                 if (ptr.enter) {
  48.                     is_free = false;
  49.                 } else {
  50.                     is_free = true;
  51.                 }
  52.                 break;
  53.             }
  54.         }
  55.         alias leave = !enter;
  56.         assert(!(leave && is_free), "tried to leave a block that was not in use");
  57.         if (enter && !is_free) return;
  58.         auto info = λ(type-of block_actions record) {
  59.             return "Train $(record.train+1) enters block $(record.block).";
  60.         };
  61.         using scoped block_actions =
  62.             &auto record = (block, train, enter, info, block_actions)
  63.         {
  64.             cont();
  65.         }
  66.     }
  67.     alias TrainAction = void delegate(int train, void delegate());
  68.     TrainAction make_action(int block, bool enter) {
  69.         return new λ(int train, void delegate() cont) {
  70.             record_action(block, train, enter, cont);
  71.         }
  72.     }
  73.     // How does a train pass through the intersection?
  74.     TrainAction[][] train_paths;
  75.     for auto path <- paths {
  76.         TrainAction[] actions;
  77.         // First, it tries to claim all its blocks.
  78.         for int block <- path {
  79.             actions ~= make_action(block, true);
  80.         }
  81.         // Then, it releases them in the same order it entered.
  82.         for int block <- path {
  83.             actions ~= make_action(block, false);
  84.         }
  85.         train_paths ~= actions;
  86.     }
  87.     // How do we discover deadlocks?
  88.     // We simply consider all possible combinations of
  89.     // "trains wanting to take a path through the intersection"
  90.     // - since there's only three entry blocks, there's only 8 possible
  91.     // combinations - and for each of them, any possible
  92.     // sequence of train movements.
  93.     for int variant <- 0 .. (1 << entry_blocks.length) {
  94.         struct Option {
  95.             int[] blocks;
  96.             TrainAction[] list;
  97.         }
  98.         Option[][] train_options;
  99.         int[] used_blocks;
  100.         for int idx <- ints && int block <- entry_blocks {
  101.             if (variant & (1 << idx)) {
  102.                 Option[] alternatives;
  103.                 used_blocks ~= block;
  104.                 for auto action <- train_paths && auto path <- paths {
  105.                     if (path[0] == block) {
  106.                         alternatives ~= Option:(path, action);
  107.                     }
  108.                 }
  109.                 train_options ~= alternatives;
  110.             }
  111.         }
  112.         int num_success_states = 0;
  113.         void for_any_combination() {
  114.             bool there_were_trains = false;
  115.             bool one_could_move = false;
  116.             for int train <- ints && ref options <- train_options {
  117.                 if (options.length > 1) {
  118.                     for int i <- 0..options.length {
  119.                         using scoped options = options[i..i+1] {
  120.                             auto info = new λ(type-of block_actions record) {
  121.                                 return "Train $(record.train+1) chooses path $(options[0].blocks).";
  122.                             }
  123.                             using scoped block_actions =
  124.                                 &auto record = (-1, train, false, info, block_actions)
  125.                             {
  126.                                 for_any_combination();
  127.                             }
  128.                         }
  129.                     }
  130.                     return;
  131.                 }
  132.                 ref list = options[0].list;
  133.                 if (!list.length) continue;
  134.                 there_were_trains = true;
  135.                 auto dg = list[0];
  136.                 dg(train, λ{
  137.                     one_could_move = true;
  138.                     using scoped list = list[1..$] {
  139.                         for_any_combination();
  140.                     }
  141.                 });
  142.             }
  143.             if (!there_were_trains) {
  144.                 num_success_states ++;
  145.                 return;
  146.             }
  147.             if (one_could_move) {
  148.                 return;
  149.             }
  150.             writeln "Variant $variant: $(train_options.length) simultaneous trains, from $used_blocks.";
  151.             writeln "There were trains, but none of them could move. Failure state.";
  152.             writeln "The events leading up to this were:";
  153.             void print_forwards(type-of block_actions action) {
  154.                 if (action.next) print_forwards(action.next);
  155.                 writeln "  $(action.info(action))";
  156.             }
  157.             print_forwards block_actions;
  158.             for int train <- ints && auto options <- train_options {
  159.                 if (!options[0].list.length) continue;
  160.                 auto block = options[0].(blocks[$*2-list.length]);
  161.                 // Which train is using block?
  162.                 int responsible = -1;
  163.                 for (auto ptr = block_actions; ptr; ptr = ptr.next) {
  164.                     if (ptr.block == block) {
  165.                         assert(ptr.enter, "block is free, what happened here?!");
  166.                         responsible = ptr.train;
  167.                         break;
  168.                     }
  169.                 }
  170.                 assert(responsible != -1);
  171.                 writeln $ "Train $(train+1) wants to enter block "
  172.                     ~"$block but it's blocked by train $(responsible+1).";
  173.             }
  174.             exit(1);
  175.         }
  176.         for_any_combination();
  177.         writeln $ "Variant $variant: "
  178.             ~"$(train_options.length) simultaneous trains, from $used_blocks. "
  179.             ~"$num_success_states successful orderings.";
  180.     }
  181.     writeln "No possible deadlocks.";
  182. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement