Advertisement
Guest User

Untitled

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