? ?
Notes from a Medium-Sized Island [entries|archive|friends|userinfo]

[ website | My Website ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

[Oct. 15th, 2011|10:06 am]
[Tags|, ]

Here is a tiny javascript thing that reacts a little if you mouseover. I just threw it together in an hour after waking up wondering what sort of shapes you'd get if you randomly assigned directions to lattice points and followed them. It's regrettably slow in firefox although speedy enough in chrome. Dunno why.

The javascript toy has a built-in bias towards paths going down and to the right, just because I wanted more visual interest than the short paths that came out of the uniform distribution over the four directions. I kind of wonder what happens in higher dimensions. My thoughts tend toward think along the paths 'upstream': suppose I've got some vertex in my hand and I want to extend the path by finding some one of my neighbors that's pointing at me. What are the odds there's at least one? (This line of thinking is just an approximation, ignoring the possibility that it turns out to actually be a node that's already in my 'downstream')

Well, in an n-dimensional square lattice, I've got 2n neighbors, and each one of them picks one of 2n directions at random. Each one has a 1 in 2n chance of pointing towards me. The chance of none of them pointing towards me is (1 - 1/2n)^(2n) which is 1/e in the limit. So my gut says that things don't actually spiral out of control in higher dimensions. I guess I could do an experiment with hash functions or something...


Huh! It empirically seems like the average time until you hit a cycle in n dimensions is exactly 2n.
2 4.8731
3 6.459
4 8.3785
5 10.2061
6 12.1667
7 14.2784
8 15.7819
9 17.8955
10 20.4033
11 22.0062
12 24.0271
13 26.1572
14 27.9639
15 30.0764
16 31.7978
17 34.1895
18 35.5108


use Digest::MD5 qw(md5);

$LIMIT = 1000;

sub iter {
my ($x, $salt) = @_;
my $new = [@$x];
my $str = join (" ", @$x);
my ($p, $n) = unpack("LL", md5($salt, $str));
$new->[$p % @$x] += 2 * ($n % 2) - 1;
($str, $new);

sub period {
my ($dim, $salt) = @_;
my $x = [(0) x $dim];
my %seen = ();
my $t = 0;
while ($t < $LIMIT) {
my $str2 = join (" ", map {sprintf("% 3d",$_)} @$x);
# print "> $str2\n";
($str, $x) = iter($x, $salt);
if ($seen{$str}) { return ($t, $t - $seen{$str}); }
$seen{$str} = $t;
warn "exceeded limit";
return ($LIMIT, $LIMIT);

sub avg {
my ($dim, $sample) = @_;
my $sum = 0;
for my $i (1..$sample) {
my ($t, $per) = period($dim, $i);
$sum += $t;
return $sum / $sample;

for my $j (2 .. 18) {
my $a = avg($j, 10000);
print "$j $a\n";

[User Picture]From: bubblingbeebles
2011-10-15 02:10 pm (UTC)
it isn't instantaneous but it's fast enough in firefox for me...
(Reply) (Thread)
[User Picture]From: platypuslord
2011-10-16 05:37 pm (UTC)
2n sounds like the average number of steps you need to specifically get a cycle of length 2.
(ie, with every step you have a 1/2n chance of being sent back to your previous vertex.)

I would guess that larger cycles are so vanishingly rare that they don't affect the result much.
(Reply) (Thread)
[User Picture]From: jcreed
2011-10-18 01:13 am (UTC)
Um wow you're totally spot on. I don't know how I missed that. Looking at the cycle size, cycles larger than 2 are indeed vanishingly rare, especially in higher dimensions.
(Reply) (Parent) (Thread)