Update all new Tasks
This commit is contained in:
parent
00a190b0a6
commit
91df62d461
5697 changed files with 93386 additions and 804 deletions
22
Task/Percolation-Mean-cluster-density/00DESCRIPTION
Normal file
22
Task/Percolation-Mean-cluster-density/00DESCRIPTION
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{{Percolation Simulation}}
|
||||
Let <math>c</math> be a 2D boolean square matrix of <math>n \times n</math> values of either <tt>1</tt> or <tt>0</tt> where the
|
||||
probability of any value being <tt>1</tt> is <math>p</math>, (and of <tt>0</tt> is therefore <math>1-p</math>).
|
||||
We define a ''cluster'' of <tt>1</tt>'s as being a group of <tt>1</tt>'s connected vertically or
|
||||
horizontally (i.e., using the [[wp:Von Neumann neighborhood|Von Neumann neighborhood rule]]) and bounded by either <math>0</math> or by the limits of the matrix.
|
||||
Let the number of such clusters in such a randomly constructed matrix be <math>C_n</math>.
|
||||
|
||||
Percolation theory states that <math>K(p)</math> (the mean cluster density) will satisfy <math>K(p) = C_n / n^2</math> as <math>n</math> tends to infinity. For <math>p = 0.5</math>, <math>K(p)</math> is found numerically to approximate <math>0.065770</math>...
|
||||
|
||||
;Task
|
||||
|
||||
Show the effect of varying <math>n</math> on the accuracy of simulated <math>K(p)</math> for <math>p = 0.5</math> and
|
||||
for values of <math>n</math> up to at least <math>1000</math>.
|
||||
Any calculation of <math>C_n</math> for finite <math>n</math> is subject to randomness, so an approximation should be
|
||||
computed as the average of <math>t</math> runs, where <math>t</math> ≥ <math>5</math>.
|
||||
|
||||
For extra credit, graphically show clusters in a <math>15\times 15</math>, <math>p=0.5</math> grid.
|
||||
|
||||
Show your output here.
|
||||
|
||||
;See also
|
||||
* [http://mathworld.wolfram.com/s-Cluster.html s-Cluster] on Wolfram mathworld.
|
||||
2
Task/Percolation-Mean-cluster-density/00META.yaml
Normal file
2
Task/Percolation-Mean-cluster-density/00META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
note: Percolation Simulations
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int *map, w, ww;
|
||||
|
||||
void make_map(double p)
|
||||
{
|
||||
int i, thresh = RAND_MAX * p;
|
||||
i = ww = w * w;
|
||||
|
||||
map = realloc(map, i * sizeof(int));
|
||||
while (i--) map[i] = -(rand() < thresh);
|
||||
}
|
||||
|
||||
char alpha[] = "+.ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
#define ALEN ((int)(sizeof(alpha) - 3))
|
||||
|
||||
void show_cluster(void)
|
||||
{
|
||||
int i, j, *s = map;
|
||||
|
||||
for (i = 0; i < w; i++) {
|
||||
for (j = 0; j < w; j++, s++)
|
||||
printf(" %c", *s < ALEN ? alpha[1 + *s] : '?');
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
void recur(int x, int v) {
|
||||
if (x >= 0 && x < ww && map[x] == -1) {
|
||||
map[x] = v;
|
||||
recur(x - w, v);
|
||||
recur(x - 1, v);
|
||||
recur(x + 1, v);
|
||||
recur(x + w, v);
|
||||
}
|
||||
}
|
||||
|
||||
int count_clusters(void)
|
||||
{
|
||||
int i, cls;
|
||||
|
||||
for (cls = i = 0; i < ww; i++) {
|
||||
if (-1 != map[i]) continue;
|
||||
recur(i, ++cls);
|
||||
}
|
||||
|
||||
return cls;
|
||||
}
|
||||
|
||||
double tests(int n, double p)
|
||||
{
|
||||
int i;
|
||||
double k;
|
||||
|
||||
for (k = i = 0; i < n; i++) {
|
||||
make_map(p);
|
||||
k += (double)count_clusters() / ww;
|
||||
}
|
||||
return k / n;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
w = 15;
|
||||
make_map(.5);
|
||||
printf("width=15, p=0.5, %d clusters:\n", count_clusters());
|
||||
show_cluster();
|
||||
|
||||
printf("\np=0.5, iter=5:\n");
|
||||
for (w = 1<<2; w <= 1<<14; w<<=2)
|
||||
printf("%5d %9.6f\n", w, tests(5, .5));
|
||||
|
||||
free(map);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
import std.stdio, std.algorithm, std.random, std.math, std.array,
|
||||
std.range, std.ascii;
|
||||
|
||||
alias Cell = ubyte;
|
||||
alias Grid = Cell[][];
|
||||
enum Cell notClustered = 1; // Filled cell, but not in a cluster.
|
||||
|
||||
Grid initialize(Grid grid, in double prob, ref Xorshift rng) nothrow {
|
||||
foreach (row; grid)
|
||||
foreach (ref cell; row)
|
||||
cell = Cell(rng.uniform01 < prob);
|
||||
return grid;
|
||||
}
|
||||
|
||||
void show(in Grid grid) {
|
||||
immutable static cell2char = " #" ~ letters;
|
||||
writeln('+', "-".replicate(grid.length), '+');
|
||||
foreach (row; grid) {
|
||||
write('|');
|
||||
row.map!(c => c < cell2char.length ? cell2char[c] : '@').write;
|
||||
writeln('|');
|
||||
}
|
||||
writeln('+', "-".replicate(grid.length), '+');
|
||||
}
|
||||
|
||||
size_t countClusters(bool justCount=false)(Grid grid)
|
||||
pure nothrow @safe @nogc {
|
||||
immutable side = grid.length;
|
||||
static if (justCount)
|
||||
enum Cell clusterID = 2;
|
||||
else
|
||||
Cell clusterID = 1;
|
||||
|
||||
void walk(in size_t r, in size_t c) nothrow @safe @nogc {
|
||||
grid[r][c] = clusterID; // Fill grid.
|
||||
|
||||
if (r < side - 1 && grid[r + 1][c] == notClustered) // Down.
|
||||
walk(r + 1, c);
|
||||
if (c < side - 1 && grid[r][c + 1] == notClustered) // Right.
|
||||
walk(r, c + 1);
|
||||
if (c > 0 && grid[r][c - 1] == notClustered) // Left.
|
||||
walk(r, c - 1);
|
||||
if (r > 0 && grid[r - 1][c] == notClustered) // Up.
|
||||
walk(r - 1, c);
|
||||
}
|
||||
|
||||
size_t nClusters = 0;
|
||||
|
||||
foreach (immutable r; 0 .. side)
|
||||
foreach (immutable c; 0 .. side)
|
||||
if (grid[r][c] == notClustered) {
|
||||
static if (!justCount)
|
||||
clusterID++;
|
||||
nClusters++;
|
||||
walk(r, c);
|
||||
}
|
||||
return nClusters;
|
||||
}
|
||||
|
||||
double clusterDensity(Grid grid, in double prob, ref Xorshift rng) {
|
||||
return grid.initialize(prob, rng).countClusters!true /
|
||||
double(grid.length ^^ 2);
|
||||
}
|
||||
|
||||
void showDemo(in size_t side, in double prob, ref Xorshift rng) {
|
||||
auto grid = new Grid(side, side);
|
||||
grid.initialize(prob, rng);
|
||||
writefln("Found %d clusters in this %d by %d grid:\n",
|
||||
grid.countClusters, side, side);
|
||||
grid.show;
|
||||
}
|
||||
|
||||
void main() {
|
||||
immutable prob = 0.5;
|
||||
immutable nIters = 5;
|
||||
auto rng = Xorshift(unpredictableSeed);
|
||||
|
||||
showDemo(15, prob, rng);
|
||||
writeln;
|
||||
foreach (immutable i; iota(4, 14, 2)) {
|
||||
immutable side = 2 ^^ i;
|
||||
auto grid = new Grid(side, side);
|
||||
immutable density = nIters
|
||||
.iota
|
||||
.map!(_ => grid.clusterDensity(prob, rng))
|
||||
.sum / nIters;
|
||||
writefln("n_iters=%3d, p=%4.2f, n=%5d, sim=%7.8f",
|
||||
nIters, prob, side, density);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
congeal=: |.@|:@((*@[*>.)/\.)^:4^:_
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
6 trials 3
|
||||
0.1111111 0.1111111 0.2222222 0.1111111 0.1111111 0.3333333
|
||||
6 trials 10
|
||||
0.16 0.12 0.09 0.1 0.1 0.03
|
||||
6 trials 30
|
||||
0.05666667 0.1033333 0.08222222 0.07444444 0.08333333 0.07666667
|
||||
6 trials 100
|
||||
0.069 0.0678 0.0666 0.0677 0.0653 0.0739
|
||||
6 trials 300
|
||||
0.06563333 0.06663333 0.06713333 0.06727778 0.06658889 0.06664444
|
||||
6 trials 1000
|
||||
0.066079 0.066492 0.065847 0.065943 0.066318 0.065998
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
mean=: +/%#
|
||||
mean 8 trials 3
|
||||
0.1805556
|
||||
mean 8 trials 10
|
||||
0.0875
|
||||
mean 8 trials 30
|
||||
0.07486111
|
||||
mean 8 trials 100
|
||||
0.0690625
|
||||
mean 8 trials 300
|
||||
0.06749861
|
||||
mean 8 trials 1000
|
||||
0.06616738
|
||||
|
|
@ -0,0 +1 @@
|
|||
thru=: <./ + i.@(+*)@-~
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
(idclust 0.5 > 0 ?@$~ 15 15) {'.', 'A' thru&.(a.&i.) 'Z'
|
||||
A.......B..C...
|
||||
AAAA...D..E.F..
|
||||
A..A.G.D.D.FFF.
|
||||
AA..H..DDD.FF.I
|
||||
AAA...J...FFF..
|
||||
..AAAA.A.K...AA
|
||||
LL.A...A..A.AAA
|
||||
.L.A..AAA.AAAAA
|
||||
..AA.AAA.AAA.A.
|
||||
AA.AAAAAA....A.
|
||||
A.AAAA.AAAA.AA.
|
||||
AAA...AAA.AAAAA
|
||||
..AA..A.A...AAA
|
||||
.M.A.AA.AA..AA.
|
||||
.MM..A.N..O..A.
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
congeal=: |.@|:@((*@[*>.)/\.)^:4^:_
|
||||
idclust=: $ $ [: (~. i.])&.(0&,)@,@congeal ] * 1 + i.@$
|
||||
|
||||
K=: (%&#~ }.@~.)&,
|
||||
|
||||
experiment=: K@ idclust@: > 0 ?@$~ ,~
|
||||
trials=: 0.5&experiment"0@#
|
||||
|
||||
mean=:+/ % #
|
||||
|
||||
thru=: <./ + i.@(+*)@-~
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
M=:0.4>?6 6$0
|
||||
M
|
||||
1 0 0 0 0 0
|
||||
0 0 0 1 0 0
|
||||
0 0 0 1 0 0
|
||||
1 1 0 0 0 0
|
||||
0 0 0 1 0 1
|
||||
1 1 0 1 1 0
|
||||
M*p:i.$M
|
||||
2 0 0 0 0 0
|
||||
0 0 0 29 0 0
|
||||
0 0 0 53 0 0
|
||||
67 71 0 0 0 0
|
||||
0 0 0 107 0 113
|
||||
127 131 0 139 149 0
|
||||
congeal M*p:i.$M
|
||||
2 0 0 0 0 0
|
||||
0 0 0 53 0 0
|
||||
0 0 0 53 0 0
|
||||
71 71 0 0 0 0
|
||||
0 0 0 149 0 113
|
||||
131 131 0 149 149 0
|
||||
|
|
@ -0,0 +1 @@
|
|||
idclust=: $ $ [: (~. i.])&.(0&,)@,@congeal ] * 1 + i.@$
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
idclust M
|
||||
1 0 0 0 0 0
|
||||
0 0 0 2 0 0
|
||||
0 0 0 2 0 0
|
||||
3 3 0 0 0 0
|
||||
0 0 0 4 0 5
|
||||
6 6 0 4 4 0
|
||||
(idclust M) {'.ABCDEFG'
|
||||
A.....
|
||||
...B..
|
||||
...B..
|
||||
CC....
|
||||
...D.E
|
||||
FF.DD.
|
||||
|
|
@ -0,0 +1 @@
|
|||
K=: (%&#~ }.@~.)&,
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
K idclust M
|
||||
0.1666667
|
||||
|
|
@ -0,0 +1 @@
|
|||
experiment=: K@ idclust@: > 0 ?@$~ ,~
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
0.4 experiment 6
|
||||
0.1666667
|
||||
0.4 experiment 6
|
||||
0.1944444
|
||||
|
|
@ -0,0 +1 @@
|
|||
trials=: 0.5&experiment"0@#
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
from __future__ import division
|
||||
from random import random
|
||||
import string
|
||||
from math import fsum
|
||||
|
||||
n_range, p, t = (2**n2 for n2 in range(4, 14, 2)), 0.5, 5
|
||||
N = M = 15
|
||||
|
||||
NOT_CLUSTERED = 1 # filled but not clustered cell
|
||||
cell2char = ' #' + string.ascii_letters
|
||||
|
||||
def newgrid(n, p):
|
||||
return [[int(random() < p) for x in range(n)] for y in range(n)]
|
||||
|
||||
def pgrid(cell):
|
||||
for n in range(N):
|
||||
print( '%i) ' % (n % 10)
|
||||
+ ' '.join(cell2char[cell[n][m]] for m in range(M)))
|
||||
|
||||
|
||||
def cluster_density(n, p):
|
||||
cc = clustercount(newgrid(n, p))
|
||||
return cc / n / n
|
||||
|
||||
def clustercount(cell):
|
||||
walk_index = 1
|
||||
for n in range(N):
|
||||
for m in range(M):
|
||||
if cell[n][m] == NOT_CLUSTERED:
|
||||
walk_index += 1
|
||||
walk_maze(m, n, cell, walk_index)
|
||||
return walk_index - 1
|
||||
|
||||
|
||||
def walk_maze(m, n, cell, indx):
|
||||
# fill cell
|
||||
cell[n][m] = indx
|
||||
# down
|
||||
if n < N - 1 and cell[n+1][m] == NOT_CLUSTERED:
|
||||
walk_maze(m, n+1, cell, indx)
|
||||
# right
|
||||
if m < M - 1 and cell[n][m + 1] == NOT_CLUSTERED:
|
||||
walk_maze(m+1, n, cell, indx)
|
||||
# left
|
||||
if m and cell[n][m - 1] == NOT_CLUSTERED:
|
||||
walk_maze(m-1, n, cell, indx)
|
||||
# up
|
||||
if n and cell[n-1][m] == NOT_CLUSTERED:
|
||||
walk_maze(m, n-1, cell, indx)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
cell = newgrid(n=N, p=0.5)
|
||||
print('Found %i clusters in this %i by %i grid\n'
|
||||
% (clustercount(cell), N, N))
|
||||
pgrid(cell)
|
||||
print('')
|
||||
|
||||
for n in n_range:
|
||||
N = M = n
|
||||
sim = fsum(cluster_density(n, p) for i in range(t)) / t
|
||||
print('t=%3i p=%4.2f n=%5i sim=%7.5f'
|
||||
% (t, p, n, sim))
|
||||
1
Task/Percolation-Mean-cluster-density/README
Normal file
1
Task/Percolation-Mean-cluster-density/README
Normal file
|
|
@ -0,0 +1 @@
|
|||
Data source: http://rosettacode.org/wiki/Percolation/Mean_cluster_density
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
#lang racket
|
||||
(require srfi/14) ; character sets
|
||||
|
||||
; much faster than safe fixnum functions
|
||||
(require
|
||||
racket/require ; for fancy require clause below
|
||||
(filtered-in
|
||||
(lambda (name) (regexp-replace #rx"unsafe-" name ""))
|
||||
racket/unsafe/ops)
|
||||
; these aren't in racket/unsafe/ops
|
||||
(only-in racket/fixnum for/fxvector in-fxvector fxvector-copy))
|
||||
|
||||
; ...(but less safe). if in doubt use this rather than the one above
|
||||
; (require racket/fixnum)
|
||||
|
||||
(define t (make-parameter 5))
|
||||
|
||||
(define (build-random-grid p M N)
|
||||
(define p-num (numerator p))
|
||||
(define p-den (denominator p))
|
||||
(for/fxvector #:length (fx* M N) ((_ (in-range (* M N))))
|
||||
(if (< (random p-den) p-num) 1 0)))
|
||||
|
||||
(define letters
|
||||
(sort (char-set->list (char-set-intersection
|
||||
char-set:letter
|
||||
; char-set:ascii
|
||||
)) char<?))
|
||||
(define n-letters (length letters))
|
||||
(define cell->char
|
||||
(match-lambda
|
||||
(0 #\space) (1 #\.)
|
||||
(c (list-ref letters (modulo (- c 2) n-letters)))))
|
||||
|
||||
(define (draw-percol-grid M N . gs)
|
||||
(for ((r N))
|
||||
(for ((g gs))
|
||||
(define row-str
|
||||
(list->string
|
||||
(for/list ((idx (in-range (* r M) (* (+ r 1) M))))
|
||||
(cell->char (fxvector-ref g idx)))))
|
||||
(printf "|~a| " row-str))
|
||||
(newline)))
|
||||
|
||||
(define (count-clusters! M N g)
|
||||
(define (gather-cluster! k c)
|
||||
(when (fx= 1 (fxvector-ref g k))
|
||||
(define k-r (fxquotient k M))
|
||||
(define k-c (fxremainder k M))
|
||||
(fxvector-set! g k c)
|
||||
(define-syntax-rule (gather-surrounds range? k+)
|
||||
(let ((idx k+))
|
||||
(when (and range? (fx= 1 (fxvector-ref g idx)))
|
||||
(gather-cluster! idx c))))
|
||||
(gather-surrounds (fx> k-r 0) (fx- k M))
|
||||
(gather-surrounds (fx> k-c 0) (fx- k 1))
|
||||
(gather-surrounds (fx< k-c (fx- M 1)) (fx+ k 1))
|
||||
(gather-surrounds (fx< k-r (fx- N 1)) (fx+ k M))))
|
||||
|
||||
(define-values (rv _c)
|
||||
(for/fold ((rv 0) (c 2))
|
||||
((pos (in-range (fx* M N)))
|
||||
#:when (fx= 1 (fxvector-ref g pos)))
|
||||
(gather-cluster! pos c)
|
||||
(values (fx+ rv 1) (fx+ c 1))))
|
||||
rv)
|
||||
|
||||
(define (display-sample-clustering p)
|
||||
(printf "Percolation cluster sample: p=~a~%" p)
|
||||
(define g (build-random-grid p 15 15))
|
||||
(define g+ (fxvector-copy g))
|
||||
(define g-count (count-clusters! 15 15 g+))
|
||||
(draw-percol-grid 15 15 g g+)
|
||||
(printf "~a clusters~%" g-count))
|
||||
|
||||
(define (experiment p n t)
|
||||
(printf "Experiment: ~a ~a ~a\t" p n t) (flush-output)
|
||||
(define sum-Cn
|
||||
(for/sum ((run (in-range t)))
|
||||
(printf "[~a" run) (flush-output)
|
||||
(define g (build-random-grid p n n))
|
||||
(printf "*") (flush-output)
|
||||
(define Cn (count-clusters! n n g))
|
||||
(printf "]") (flush-output)
|
||||
Cn))
|
||||
(printf "\tmean K(p) = ~a~%" (real->decimal-string (/ sum-Cn t (sqr n)) 6)))
|
||||
|
||||
(module+ main
|
||||
(t 10)
|
||||
(for ((n (in-list '(4000 1000 750 500 400 300 200 100 15))))
|
||||
(experiment 1/2 n (t)))
|
||||
(display-sample-clustering 1/2))
|
||||
|
||||
(module+ test
|
||||
(define grd (build-random-grid 1/2 1000 1000))
|
||||
(/ (for/sum ((g (in-fxvector grd)) #:when (zero? g)) 1) (fxvector-length grd))
|
||||
(display-sample-clustering 1/2))
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package require Tcl 8.6
|
||||
|
||||
proc determineClusters {w h p} {
|
||||
# Construct the grid
|
||||
set grid [lrepeat $h [lrepeat $w 0]]
|
||||
for {set i 0} {$i < $h} {incr i} {
|
||||
for {set j 0} {$j < $w} {incr j} {
|
||||
lset grid $i $j [expr {rand() < $p ? -1 : 0}]
|
||||
}
|
||||
}
|
||||
# Find (and count) the clusters
|
||||
set cl 0
|
||||
for {set i 0} {$i < $h} {incr i} {
|
||||
for {set j 0} {$j < $w} {incr j} {
|
||||
if {[lindex $grid $i $j] == -1} {
|
||||
incr cl
|
||||
for {set q [list $i $j];set k 0} {$k<[llength $q]} {incr k} {
|
||||
set y [lindex $q $k]
|
||||
set x [lindex $q [incr k]]
|
||||
if {[lindex $grid $y $x] != -1} continue
|
||||
lset grid $y $x $cl
|
||||
foreach dx {1 0 -1 0} dy {0 1 0 -1} {
|
||||
set nx [expr {$x+$dx}]
|
||||
set ny [expr {$y+$dy}]
|
||||
if {
|
||||
$nx >= 0 && $ny >= 0 && $nx < $w && $ny < $h &&
|
||||
[lindex $grid $ny $nx] == -1
|
||||
} then {
|
||||
lappend q $ny $nx
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return [list $cl $grid]
|
||||
}
|
||||
|
||||
# Print a sample 15x15 grid
|
||||
lassign [determineClusters 15 15 0.5] n g
|
||||
puts "15x15 grid, p=0.5, with $n clusters"
|
||||
puts "+[string repeat - 15]+"
|
||||
foreach r $g {puts |[join [lmap x $r {format %c [expr {$x==0?32:64+$x}]}] ""]|}
|
||||
puts "+[string repeat - 15]+"
|
||||
|
||||
# Determine the densities as the grid size increases
|
||||
puts "p=0.5, iter=5"
|
||||
foreach n {5 30 180 1080 6480} {
|
||||
set tot 0
|
||||
for {set i 0} {$i < 5} {incr i} {
|
||||
lassign [determineClusters $n $n 0.5] nC
|
||||
incr tot $nC
|
||||
}
|
||||
puts "n=$n, K(p)=[expr {$tot/5.0/$n**2}]"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue