Advertisement
Marrin

Random Walk

Jan 20th, 2013
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Vala 5.84 KB | None | 0 0
  1. using GLib;
  2. using Gee;
  3.  
  4.  
  5. static inline int python_modulo(int a, int b) {
  6.     int r = a % b;
  7.     r += ((int) (r != 0) & ((r ^ b) < 0)) * b;
  8.     return r;
  9. }
  10.  
  11.  
  12. class CoordinateSystem : Object {
  13.     internal uint[] shape;
  14.    
  15.     public CoordinateSystem (uint[] shape)
  16.         requires (this.is_valid_shape (shape))
  17.     {
  18.         this.shape = shape;
  19.     }
  20.    
  21.     static inline bool is_valid_shape (uint[] shape) {
  22.         foreach (var n in shape) {
  23.             if (n < 0) return false;
  24.         }
  25.         return shape.length != 0;
  26.     }
  27.    
  28.     public inline uint dimensions {
  29.         get { return this.shape.length; }
  30.     }
  31.    
  32.     public uint size {
  33.         get {
  34.             uint result = 1;
  35.             foreach (var v in this.shape) {
  36.                 result *= v;
  37.             }
  38.             return result;
  39.         }
  40.     }
  41.    
  42.     public bool is_valid_coordinates(uint[] values) {
  43.         if (values.length == this.dimensions) {
  44.             for (var i = 0; i < values.length; ++i) {
  45.                 if (values[i] < 0 || values[i] >= this.shape[i]) return false;
  46.             }
  47.             return true;
  48.         } else {
  49.             return false;
  50.         }
  51.     }
  52.    
  53.     public new Coordinate get (uint index)
  54.         requires (index >= 0)
  55.     {
  56.         var result = new uint[this.shape.length];
  57.         for (int i = 0; i < this.shape.length; ++i) {
  58.             result[i] = index % this.shape[i];
  59.             index /= this.shape[i];
  60.         }
  61.         assert (index == 0);
  62.         return new Coordinate (this, result);
  63.     }
  64.    
  65.     public Coordinate[] get_sample (uint count)
  66.         requires (count <= this.size)
  67.     {
  68.         var result = new Coordinate[count];
  69.         var selected = new HashSet<uint> ();
  70.         uint j = 0;
  71.        
  72.         for (var i = 0; i < count; ++i) {
  73.             do {
  74.                 j = Random.int_range (0, (int32) this.size);
  75.             } while (j in selected);
  76.             selected.add (j);
  77.             result[i] = this[j];
  78.         }
  79.         return result;
  80.     }
  81. }
  82.  
  83. class Coordinate : Object {
  84.     CoordinateSystem coordinate_system;
  85.     uint[] coordinates;
  86.    
  87.     public Coordinate (CoordinateSystem coordinate_system, uint[] coordinates)
  88.         requires (coordinate_system.is_valid_coordinates (coordinates))
  89.     {
  90.         this.coordinate_system = coordinate_system;
  91.         this.coordinates = coordinates;
  92.     }
  93.    
  94.     public inline int dimensions {
  95.         get { return this.coordinates.length; }
  96.     }
  97.    
  98.     public bool equals(Coordinate other) {
  99.         if (this.coordinates.length == other.coordinates.length) {
  100.             for (var i = 0; i < this.coordinates.length; ++i) {
  101.                 if (this.coordinates[i] != other.coordinates[i]) return false;
  102.             }
  103.             return true;
  104.         } else {
  105.             return false;
  106.         }
  107.     }
  108.    
  109.     public uint hash () {
  110.         uint x = 0x345678, mult = 100003;
  111.         for (var i = 0; i < this.coordinates.length; ++i) {
  112.             x = (x ^ this.coordinates[i]) * mult;
  113.             mult += 82520 + 2 * i;
  114.         }
  115.         return x + 97531;
  116.     }
  117.    
  118.     public void move(int[] delta)
  119.         requires (delta.length == this.dimensions)
  120.     {
  121.         for (var i = 0; i < delta.length; ++i) {
  122.             this.coordinates[i] =
  123.                 python_modulo (((int) this.coordinates[i] + delta[i]),
  124.                     (int) this.coordinate_system.shape[i]);
  125.         }
  126.     }
  127. }
  128.  
  129. class Walker : Object {
  130.     public Coordinate coordinate;
  131.     public uint id;
  132.    
  133.     public Walker (Coordinate coordinate, uint id) {
  134.         this.coordinate = coordinate;
  135.         this.id = id;
  136.     }
  137.    
  138.     public void random_move() {
  139.         var delta = new int[this.coordinate.dimensions];
  140.         delta[Random.int_range (0, this.coordinate.dimensions)] =
  141.             Random.boolean () ? -1 : 1;
  142.         this.coordinate.move(delta);
  143.     }
  144. }
  145.  
  146.  
  147. class WalkerCounter : Object {
  148.     public Walker walker;
  149.     public uint count = 0;
  150.    
  151.     public WalkerCounter(Walker walker) {
  152.         this.walker = walker;
  153.     }
  154. }
  155.  
  156.  
  157. class Simulation : Object {
  158.     Walker[] walkers;
  159.    
  160.     public Simulation (Walker[] walkers) {
  161.         this.walkers = walkers;
  162.     }
  163.    
  164.     public Simulation.with_randomly_placed_walkers (
  165.         CoordinateSystem coordinate_system, uint count
  166.     ) {
  167.         var walkers = new Walker[count];
  168.         var coordinates = coordinate_system.get_sample (count);
  169.         for (var i = 0; i < count; ++i) {
  170.             walkers[i] = new Walker(coordinates[i], i);
  171.         }
  172.         this (walkers);
  173.     }
  174.    
  175.     public uint size {
  176.         get { return this.walkers.length; }
  177.     }
  178.    
  179.     public void step () {
  180.         var coordinate2walkers = new HashMap<Coordinate, WalkerCounter> (
  181.             Coordinate.hash, (EqualFunc) Coordinate.equals);
  182.         foreach (var walker in this.walkers) {
  183.             walker.random_move();
  184.            
  185.             var walker_counter = coordinate2walkers[walker.coordinate];
  186.             if (walker_counter == null) {
  187.                 walker_counter = new WalkerCounter (walker);
  188.                 coordinate2walkers[walker.coordinate] = walker_counter;
  189.             }
  190.             walker_counter.count += 1;
  191.         }
  192.         var i = 0;
  193.         foreach (var walker_counter in coordinate2walkers.values) {
  194.             if (walker_counter.count == 1) {
  195.                 this.walkers[i++] = walker_counter.walker;
  196.             }
  197.         }
  198.         this.walkers.resize (i);
  199.     }
  200. }
  201.  
  202. static int main (string[] args) {
  203.     var simulation = new Simulation.with_randomly_placed_walkers (
  204.         new CoordinateSystem ({100, 100}), 500);
  205.     for (var i = 0; i < 100; ++i) {
  206.         simulation.step ();
  207.         stdout.printf ("%u walkers left in step %d\n", simulation.size, i);
  208.         if (simulation.size <= 1) break;
  209.     }
  210.     return 0;
  211. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement