Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
3
Task/Percolation-Mean-cluster-density/00-META.yaml
Normal file
3
Task/Percolation-Mean-cluster-density/00-META.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Percolation/Mean_cluster_density
|
||||
note: Percolation Simulations
|
||||
23
Task/Percolation-Mean-cluster-density/00-TASK.txt
Normal file
23
Task/Percolation-Mean-cluster-density/00-TASK.txt
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{{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.
|
||||
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
UInt32 seed = 0
|
||||
F nonrandom()
|
||||
:seed = 1664525 * :seed + 1013904223
|
||||
R (:seed >> 16) / Float(FF'FF)
|
||||
|
||||
V nn = 15
|
||||
V tt = 5
|
||||
V pp = 0.5
|
||||
V NotClustered = 1
|
||||
V Cell2Char = ‘ #abcdefghijklmnopqrstuvwxyz’
|
||||
V NRange = [4, 64, 256, 1024, 4096]
|
||||
|
||||
F newGrid(n, p)
|
||||
R (0 .< n).map(i -> (0 .< @n).map(i -> Int(nonrandom() < @@p)))
|
||||
|
||||
F walkMaze(&grid, m, n, idx) -> N
|
||||
grid[n][m] = idx
|
||||
I n < grid.len - 1 & grid[n + 1][m] == NotClustered
|
||||
walkMaze(&grid, m, n + 1, idx)
|
||||
I m < grid[0].len - 1 & grid[n][m + 1] == NotClustered
|
||||
walkMaze(&grid, m + 1, n, idx)
|
||||
I m > 0 & grid[n][m - 1] == NotClustered
|
||||
walkMaze(&grid, m - 1, n, idx)
|
||||
I n > 0 & grid[n - 1][m] == NotClustered
|
||||
walkMaze(&grid, m, n - 1, idx)
|
||||
|
||||
F clusterCount(&grid)
|
||||
V walkIndex = 1
|
||||
L(n) 0 .< grid.len
|
||||
L(m) 0 .< grid[0].len
|
||||
I grid[n][m] == NotClustered
|
||||
walkIndex++
|
||||
walkMaze(&grid, m, n, walkIndex)
|
||||
R walkIndex - 1
|
||||
|
||||
F clusterDensity(n, p)
|
||||
V grid = newGrid(n, p)
|
||||
R clusterCount(&grid) / Float(n * n)
|
||||
|
||||
F print_grid(grid)
|
||||
L(row) grid
|
||||
print(L.index % 10, end' ‘) ’)
|
||||
L(cell) row
|
||||
print(‘ ’Cell2Char[cell], end' ‘’)
|
||||
print()
|
||||
|
||||
V grid = newGrid(nn, 0.5)
|
||||
print(‘Found ’clusterCount(&grid)‘ clusters in this ’nn‘ by ’nn" grid\n")
|
||||
print_grid(grid)
|
||||
print()
|
||||
|
||||
L(n) NRange
|
||||
V sum = 0.0
|
||||
L 0 .< tt
|
||||
sum += clusterDensity(n, pp)
|
||||
V sim = sum / tt
|
||||
print(‘t = #. p = #.2 n = #4 sim = #.5’.format(tt, pp, n, sim))
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
#include <iostream>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
|
||||
std::random_device random;
|
||||
std::mt19937 generator(random());
|
||||
std::uniform_real_distribution<double> distribution(0.0F, 1.0F);
|
||||
|
||||
class Grid {
|
||||
public:
|
||||
Grid(const int32_t size, const double probability) {
|
||||
create_grid(size, probability);
|
||||
count_clusters();
|
||||
}
|
||||
|
||||
int32_t cluster_count() const {
|
||||
return clusters;
|
||||
}
|
||||
|
||||
double cluster_density() const {
|
||||
return (double) clusters / ( grid.size() * grid.size() );
|
||||
}
|
||||
|
||||
void display() const {
|
||||
for ( uint64_t row = 0; row < grid.size(); ++row ) {
|
||||
for ( uint64_t col = 0; col < grid.size(); ++col ) {
|
||||
uint64_t value = grid[row][col];
|
||||
char ch = ( value < GRID_CHARACTERS.length() ) ? GRID_CHARACTERS[value] : '?';
|
||||
std::cout << " " << ch;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
private:
|
||||
void count_clusters() {
|
||||
clusters = 0;
|
||||
for ( uint64_t row = 0; row < grid.size(); ++row ) {
|
||||
for ( uint64_t col = 0; col < grid.size(); ++col ) {
|
||||
if ( grid[row][col] == CLUSTERED ) {
|
||||
clusters += 1;
|
||||
identify_cluster(row, col, clusters);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void identify_cluster(const uint64_t row, const uint64_t col, const uint64_t count) {
|
||||
grid[row][col] = count;
|
||||
if ( row < grid.size() - 1 && grid[row + 1][col] == CLUSTERED ) {
|
||||
identify_cluster(row + 1, col, count);
|
||||
}
|
||||
if ( col < grid.size() - 1 && grid[row][col + 1] == CLUSTERED ) {
|
||||
identify_cluster(row, col + 1, count);
|
||||
}
|
||||
if ( col > 0 && grid[row][col - 1] == CLUSTERED ) {
|
||||
identify_cluster(row, col - 1, count);
|
||||
}
|
||||
if ( row > 0 && grid[row - 1][col] == CLUSTERED ) {
|
||||
identify_cluster(row - 1, col, count);
|
||||
}
|
||||
}
|
||||
|
||||
void create_grid(int32_t grid_size, double probability) {
|
||||
grid.assign(grid_size, std::vector<int32_t>(grid_size, 0));
|
||||
for ( int32_t row = 0; row < grid_size; ++row ) {
|
||||
for ( int32_t col = 0; col < grid_size; ++col ) {
|
||||
if ( distribution(generator) < probability ) {
|
||||
grid[row][col] = CLUSTERED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t clusters;
|
||||
std::vector<std::vector<int32_t>> grid;
|
||||
|
||||
inline static const int CLUSTERED = -1;
|
||||
inline static const std::string GRID_CHARACTERS = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
};
|
||||
|
||||
int main() {
|
||||
const int32_t size = 15;
|
||||
const double probability = 0.5;
|
||||
const int32_t test_count = 5;
|
||||
|
||||
Grid grid(size, probability);
|
||||
std::cout << "This " << size << " by " << size << " grid contains "
|
||||
<< grid.cluster_count() << " clusters:" << std::endl;
|
||||
grid.display();
|
||||
|
||||
std::cout << "\n p = 0.5, iterations = " << test_count << std::endl;
|
||||
std::vector<int32_t> grid_sizes = { 10, 100, 1'000, 10'000 };
|
||||
for ( int32_t grid_size : grid_sizes ) {
|
||||
double sumDensity = 0.0;
|
||||
for ( int32_t test = 0; test < test_count; test++ ) {
|
||||
Grid grid(grid_size, probability);
|
||||
sumDensity += grid.cluster_density();
|
||||
}
|
||||
double result = sumDensity / test_count;
|
||||
std::cout << " n = " << std::setw(5) << grid_size
|
||||
<< ", simulations K = " << std::fixed << result << std::endl;
|
||||
}
|
||||
}
|
||||
|
|
@ -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,37 @@
|
|||
(define-constant BLACK (rgb 0 0 0.6))
|
||||
(define-constant WHITE -1)
|
||||
;; sets pixels to clusterize to WHITE
|
||||
;; returns bit-map vector
|
||||
(define (init-C n p )
|
||||
(plot-size n n)
|
||||
(define C (pixels->int32-vector )) ;; get canvas bit-map
|
||||
(pixels-map (lambda (x y) (if (< (random) p) WHITE BLACK )) C)
|
||||
C )
|
||||
|
||||
;; random color for new cluster
|
||||
(define (new-color)
|
||||
(hsv->rgb (random) 0.9 0.9))
|
||||
|
||||
;; make-region predicate
|
||||
(define (in-cluster C x y)
|
||||
(= (pixel-ref C x y) WHITE))
|
||||
|
||||
;; paint all adjacents to (x0,y0) with new color
|
||||
(define (make-cluster C x0 y0)
|
||||
(pixel-set! C x0 y0 (new-color))
|
||||
(make-region in-cluster C x0 y0))
|
||||
|
||||
;; task
|
||||
(define (make-clusters (n 400) (p 0.5))
|
||||
(define Cn 0)
|
||||
(define C null)
|
||||
(for ((t 5)) ;; 5 iterations
|
||||
(plot-clear)
|
||||
(set! C (init-C n p))
|
||||
(for* ((x0 n) (y0 n))
|
||||
#:when (= (pixel-ref C x0 y0) WHITE)
|
||||
(set! Cn (1+ Cn))
|
||||
(make-cluster C x0 y0)))
|
||||
|
||||
(writeln 'n n 'Cn Cn 'density (// Cn (* n n) 5) )
|
||||
(vector->pixels C)) ;; to screen
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
USING: combinators formatting generalizations kernel math
|
||||
math.matrices random sequences ;
|
||||
IN: rosetta-code.mean-cluster-density
|
||||
|
||||
CONSTANT: p 0.5
|
||||
CONSTANT: iterations 5
|
||||
|
||||
: rand-bit-matrix ( n probability -- matrix )
|
||||
dupd [ random-unit > 1 0 ? ] curry make-matrix ;
|
||||
|
||||
: flood-fill ( x y matrix -- )
|
||||
3dup ?nth ?nth 1 = [
|
||||
[ [ -1 ] 3dip nth set-nth ] [
|
||||
{
|
||||
[ [ 1 + ] 2dip ]
|
||||
[ [ 1 - ] 2dip ]
|
||||
[ [ 1 + ] dip ]
|
||||
[ [ 1 - ] dip ]
|
||||
} [ flood-fill ] map-compose 3cleave
|
||||
] 3bi
|
||||
] [ 3drop ] if ;
|
||||
|
||||
: count-clusters ( matrix -- Cn )
|
||||
0 swap dup dim matrix-coordinates flip concat [
|
||||
first2 rot 3dup ?nth ?nth 1 = [ flood-fill 1 + ]
|
||||
[ 3drop ] if
|
||||
] with each ;
|
||||
|
||||
: mean-cluster-density ( matrix -- mcd )
|
||||
[ count-clusters ] [ dim first sq / ] bi ;
|
||||
|
||||
: simulate ( n -- avg-mcd )
|
||||
iterations swap [ p rand-bit-matrix mean-cluster-density ]
|
||||
curry replicate sum iterations / ;
|
||||
|
||||
: main ( -- )
|
||||
{ 4 64 256 1024 4096 } [
|
||||
[ iterations p ] dip dup simulate
|
||||
"iterations = %d p = %.1f n = %4d sim = %.5f\n" printf
|
||||
] each ;
|
||||
|
||||
MAIN: main
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
n_range = []int{4, 64, 256, 1024, 4096}
|
||||
M = 15
|
||||
N = 15
|
||||
)
|
||||
|
||||
const (
|
||||
p = .5
|
||||
t = 5
|
||||
NOT_CLUSTERED = 1
|
||||
cell2char = " #abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
)
|
||||
|
||||
func newgrid(n int, p float64) [][]int {
|
||||
g := make([][]int, n)
|
||||
for y := range g {
|
||||
gy := make([]int, n)
|
||||
for x := range gy {
|
||||
if rand.Float64() < p {
|
||||
gy[x] = 1
|
||||
}
|
||||
}
|
||||
g[y] = gy
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
||||
func pgrid(cell [][]int) {
|
||||
for n := 0; n < N; n++ {
|
||||
fmt.Print(n%10, ") ")
|
||||
for m := 0; m < M; m++ {
|
||||
fmt.Printf(" %c", cell2char[cell[n][m]])
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func cluster_density(n int, p float64) float64 {
|
||||
cc := clustercount(newgrid(n, p))
|
||||
return float64(cc) / float64(n) / float64(n)
|
||||
}
|
||||
|
||||
func clustercount(cell [][]int) int {
|
||||
walk_index := 1
|
||||
for n := 0; n < N; n++ {
|
||||
for m := 0; m < M; m++ {
|
||||
if cell[n][m] == NOT_CLUSTERED {
|
||||
walk_index++
|
||||
walk_maze(m, n, cell, walk_index)
|
||||
}
|
||||
}
|
||||
}
|
||||
return walk_index - 1
|
||||
}
|
||||
|
||||
func walk_maze(m, n int, cell [][]int, indx int) {
|
||||
cell[n][m] = indx
|
||||
if n < N-1 && cell[n+1][m] == NOT_CLUSTERED {
|
||||
walk_maze(m, n+1, cell, indx)
|
||||
}
|
||||
if m < M-1 && cell[n][m+1] == NOT_CLUSTERED {
|
||||
walk_maze(m+1, n, cell, indx)
|
||||
}
|
||||
if m > 0 && cell[n][m-1] == NOT_CLUSTERED {
|
||||
walk_maze(m-1, n, cell, indx)
|
||||
}
|
||||
if n > 0 && cell[n-1][m] == NOT_CLUSTERED {
|
||||
walk_maze(m, n-1, cell, indx)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
cell := newgrid(N, .5)
|
||||
fmt.Printf("Found %d clusters in this %d by %d grid\n\n",
|
||||
clustercount(cell), N, N)
|
||||
pgrid(cell)
|
||||
fmt.Println()
|
||||
|
||||
for _, n := range n_range {
|
||||
M = n
|
||||
N = n
|
||||
sum := 0.
|
||||
for i := 0; i < t; i++ {
|
||||
sum += cluster_density(n, p)
|
||||
}
|
||||
sim := sum / float64(t)
|
||||
fmt.Printf("t=%3d p=%4.2f n=%5d sim=%7.5f\n", t, p, n, sim)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
{-# language FlexibleContexts #-}
|
||||
import Data.List
|
||||
import Data.Maybe
|
||||
import System.Random
|
||||
import Control.Monad.State
|
||||
import Text.Printf
|
||||
import Data.Set (Set)
|
||||
import qualified Data.Set as S
|
||||
|
||||
type Matrix = [[Bool]]
|
||||
type Cell = (Int, Int)
|
||||
type Cluster = Set (Int, Int)
|
||||
|
||||
clusters :: Matrix -> [Cluster]
|
||||
clusters m = unfoldr findCuster cells
|
||||
where
|
||||
cells = S.fromList [ (i,j) | (r, i) <- zip m [0..]
|
||||
, (x, j) <- zip r [0..], x]
|
||||
|
||||
findCuster s = do
|
||||
(p, ps) <- S.minView s
|
||||
return $ runState (expand p) ps
|
||||
|
||||
expand p = do
|
||||
ns <- state $ extract (neigbours p)
|
||||
xs <- mapM expand $ S.elems ns
|
||||
return $ S.insert p $ mconcat xs
|
||||
|
||||
extract s1 s2 = (s2 `S.intersection` s1, s2 S.\\ s1)
|
||||
neigbours (i,j) = S.fromList [(i-1,j),(i+1,j),(i,j-1),(i,j+1)]
|
||||
n = length m
|
||||
|
||||
showClusters :: Matrix -> String
|
||||
showClusters m = unlines [ unwords [ mark (i,j)
|
||||
| j <- [0..n-1] ]
|
||||
| i <- [0..n-1] ]
|
||||
where
|
||||
cls = clusters m
|
||||
n = length m
|
||||
mark c = maybe "." snd $ find (S.member c . fst) $ zip cls syms
|
||||
syms = sequence [['a'..'z'] ++ ['A'..'Z']]
|
||||
------------------------------------------------------------
|
||||
|
||||
randomMatrices :: Int -> StdGen -> [Matrix]
|
||||
randomMatrices n = clipBy n . clipBy n . randoms
|
||||
where
|
||||
clipBy n = unfoldr (Just . splitAt n)
|
||||
|
||||
randomMatrix n = head . randomMatrices n
|
||||
|
||||
tests :: Int -> StdGen -> [Int]
|
||||
tests n = map (length . clusters) . randomMatrices n
|
||||
|
||||
task :: Int -> StdGen -> (Int, Double)
|
||||
task n g = (n, result)
|
||||
where
|
||||
result = mean $ take 10 $ map density $ tests n g
|
||||
density c = fromIntegral c / fromIntegral n**2
|
||||
mean lst = sum lst / genericLength lst
|
||||
|
||||
main = newStdGen >>= mapM_ (uncurry (printf "%d\t%.5f\n")) . res
|
||||
where
|
||||
res = mapM task [10,50,100,500]
|
||||
|
|
@ -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,49 @@
|
|||
M=: (* 1+i.@$)?15 15$2
|
||||
M
|
||||
0 2 3 4 0 6 0 8 0 10 11 12 0 0 15
|
||||
0 0 18 19 20 0 22 0 0 0 0 0 28 29 0
|
||||
31 32 0 34 35 36 37 38 0 0 0 42 0 0 45
|
||||
0 0 48 49 0 51 0 0 54 55 0 57 58 0 0
|
||||
61 62 63 64 0 0 67 0 69 0 71 72 0 74 0
|
||||
0 0 78 79 0 0 82 0 84 85 86 87 88 0 0
|
||||
0 92 0 94 0 0 0 0 99 100 101 0 103 0 105
|
||||
106 107 108 0 0 111 0 0 114 115 116 0 0 0 0
|
||||
0 0 0 124 125 126 127 0 0 0 0 0 133 134 135
|
||||
0 0 138 0 0 141 0 143 144 145 0 0 0 0 150
|
||||
0 152 153 154 0 0 0 158 0 160 0 162 163 164 165
|
||||
0 167 168 169 170 0 172 173 0 175 176 177 0 0 180
|
||||
181 182 183 0 0 186 0 188 189 190 191 192 0 194 195
|
||||
196 197 198 0 200 201 202 0 0 205 0 207 0 0 0
|
||||
211 212 213 0 0 0 217 218 0 220 221 0 0 224 0
|
||||
congeal M
|
||||
0 94 94 94 0 6 0 8 0 12 12 12 0 0 15
|
||||
0 0 94 94 94 0 94 0 0 0 0 0 29 29 0
|
||||
32 32 0 94 94 94 94 94 0 0 0 116 0 0 45
|
||||
0 0 94 94 0 94 0 0 116 116 0 116 116 0 0
|
||||
94 94 94 94 0 0 82 0 116 0 116 116 0 74 0
|
||||
0 0 94 94 0 0 82 0 116 116 116 116 116 0 0
|
||||
0 108 0 94 0 0 0 0 116 116 116 0 116 0 105
|
||||
108 108 108 0 0 141 0 0 116 116 116 0 0 0 0
|
||||
0 0 0 141 141 141 141 0 0 0 0 0 221 221 221
|
||||
0 0 213 0 0 141 0 221 221 221 0 0 0 0 221
|
||||
0 213 213 213 0 0 0 221 0 221 0 221 221 221 221
|
||||
0 213 213 213 213 0 221 221 0 221 221 221 0 0 221
|
||||
213 213 213 0 0 218 0 221 221 221 221 221 0 221 221
|
||||
213 213 213 0 218 218 218 0 0 221 0 221 0 0 0
|
||||
213 213 213 0 0 0 218 218 0 221 221 0 0 224 0
|
||||
(~.@, i. ])congeal M
|
||||
0 1 1 1 0 2 0 3 0 4 4 4 0 0 5
|
||||
0 0 1 1 1 0 1 0 0 0 0 0 6 6 0
|
||||
7 7 0 1 1 1 1 1 0 0 0 8 0 0 9
|
||||
0 0 1 1 0 1 0 0 8 8 0 8 8 0 0
|
||||
1 1 1 1 0 0 10 0 8 0 8 8 0 11 0
|
||||
0 0 1 1 0 0 10 0 8 8 8 8 8 0 0
|
||||
0 12 0 1 0 0 0 0 8 8 8 0 8 0 13
|
||||
12 12 12 0 0 14 0 0 8 8 8 0 0 0 0
|
||||
0 0 0 14 14 14 14 0 0 0 0 0 15 15 15
|
||||
0 0 16 0 0 14 0 15 15 15 0 0 0 0 15
|
||||
0 16 16 16 0 0 0 15 0 15 0 15 15 15 15
|
||||
0 16 16 16 16 0 15 15 0 15 15 15 0 0 15
|
||||
16 16 16 0 0 17 0 15 15 15 15 15 0 15 15
|
||||
16 16 16 0 17 17 17 0 0 15 0 15 0 0 0
|
||||
16 16 16 0 0 0 17 17 0 15 15 0 0 18 0
|
||||
|
|
@ -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,103 @@
|
|||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public final class PercolationMeanCluster {
|
||||
|
||||
public static void main(String[] aArgs) {
|
||||
final int size = 15;
|
||||
final double probability = 0.5;
|
||||
final int testCount = 5;
|
||||
|
||||
Grid grid = new Grid(size, probability);
|
||||
System.out.println("This " + size + " by " + size + " grid contains " + grid.clusterCount() + " clusters:");
|
||||
grid.display();
|
||||
|
||||
System.out.println(System.lineSeparator() + " p = 0.5, iterations = " + testCount);
|
||||
List<Integer> gridSizes = List.of( 10, 100, 1_000, 10_000 );
|
||||
for ( int gridSize : gridSizes ) {
|
||||
double sumDensity = 0.0;
|
||||
for ( int test = 0; test < testCount; test++ ) {
|
||||
grid = new Grid(gridSize, probability);
|
||||
sumDensity += grid.clusterDensity();
|
||||
}
|
||||
double result = sumDensity / testCount;
|
||||
System.out.println(String.format("%s%5d%s%.6f", " n = ", gridSize, ", simulation K = ", result));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final class Grid {
|
||||
|
||||
public Grid(int aSize, double aProbability) {
|
||||
createGrid(aSize, aProbability);
|
||||
countClusters();
|
||||
}
|
||||
|
||||
public int clusterCount() {
|
||||
return clusterCount;
|
||||
}
|
||||
|
||||
public double clusterDensity() {
|
||||
return (double) clusterCount / ( grid.length * grid.length );
|
||||
}
|
||||
|
||||
public void display() {
|
||||
for ( int row = 0; row < grid.length; row++ ) {
|
||||
for ( int col = 0; col < grid.length; col++ ) {
|
||||
int value = grid[row][col];
|
||||
char ch = ( value < GRID_CHARACTERS.length() ) ? GRID_CHARACTERS.charAt(value) : '?';
|
||||
System.out.print(" " + ch);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
private void countClusters() {
|
||||
clusterCount = 0;
|
||||
for ( int row = 0; row < grid.length; row++ ) {
|
||||
for ( int col = 0; col < grid.length; col++ ) {
|
||||
if ( grid[row][col] == CLUSTERED ) {
|
||||
clusterCount += 1;
|
||||
identifyCluster(row, col, clusterCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void identifyCluster(int aRow, int aCol, int aCount) {
|
||||
grid[aRow][aCol] = aCount;
|
||||
if ( aRow < grid.length - 1 && grid[aRow + 1][aCol] == CLUSTERED ) {
|
||||
identifyCluster(aRow + 1, aCol, aCount);
|
||||
}
|
||||
if ( aCol < grid[0].length - 1 && grid[aRow][aCol + 1] == CLUSTERED ) {
|
||||
identifyCluster(aRow, aCol + 1, aCount);
|
||||
}
|
||||
if ( aCol > 0 && grid[aRow][aCol - 1] == CLUSTERED ) {
|
||||
identifyCluster(aRow, aCol - 1, aCount);
|
||||
}
|
||||
if ( aRow > 0 && grid[aRow - 1][aCol] == CLUSTERED ) {
|
||||
identifyCluster(aRow - 1, aCol, aCount);
|
||||
}
|
||||
}
|
||||
|
||||
private void createGrid(int aGridSize, double aProbability) {
|
||||
grid = new int[aGridSize][aGridSize];
|
||||
for ( int row = 0; row < aGridSize; row++ ) {
|
||||
for ( int col = 0; col < aGridSize; col++ ) {
|
||||
if ( random.nextDouble(1.0) < aProbability ) {
|
||||
grid[row][col] = CLUSTERED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int[][] grid;
|
||||
private int clusterCount;
|
||||
|
||||
private static ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||
|
||||
private static final int CLUSTERED = -1;
|
||||
private static final String GRID_CHARACTERS = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
using Printf, Distributions
|
||||
|
||||
newgrid(p::Float64, r::Int, c::Int=r) = rand(Bernoulli(p), r, c)
|
||||
|
||||
function walkmaze!(grid::Matrix{Int}, r::Int, c::Int, indx::Int)
|
||||
NOT_CLUSTERED = 1 # const
|
||||
N, M = size(grid)
|
||||
dirs = [[1, 0], [-1, 0], [0, 1], [0, -1]]
|
||||
# fill cell
|
||||
grid[r, c] = indx
|
||||
# check for each direction
|
||||
for d in dirs
|
||||
rr, cc = (r, c) .+ d
|
||||
if checkbounds(Bool, grid, rr, cc) && grid[rr, cc] == NOT_CLUSTERED
|
||||
walkmaze!(grid, rr, cc, indx)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function clustercount!(grid::Matrix{Int})
|
||||
NOT_CLUSTERED = 1 # const
|
||||
walkind = 1
|
||||
for r in 1:size(grid, 1), c in 1:size(grid, 2)
|
||||
if grid[r, c] == NOT_CLUSTERED
|
||||
walkind += 1
|
||||
walkmaze!(grid, r, c, walkind)
|
||||
end
|
||||
end
|
||||
return walkind - 1
|
||||
end
|
||||
clusterdensity(p::Float64, n::Int) = clustercount!(newgrid(p, n)) / n ^ 2
|
||||
|
||||
function printgrid(G::Matrix{Int})
|
||||
LETTERS = vcat(' ', '#', 'A':'Z', 'a':'z')
|
||||
for r in 1:size(G, 1)
|
||||
println(r % 10, ") ", join(LETTERS[G[r, :] .+ 1], ' '))
|
||||
end
|
||||
end
|
||||
|
||||
G = newgrid(0.5, 15)
|
||||
@printf("Found %i clusters in this %i×%i grid\n\n", clustercount!(G), size(G, 1), size(G, 2))
|
||||
printgrid(G)
|
||||
println()
|
||||
|
||||
const nrange = 2 .^ (4:2:12)
|
||||
const p = 0.5
|
||||
const nrep = 5
|
||||
for n in nrange
|
||||
sim = mean(clusterdensity(p, n) for _ in 1:nrep)
|
||||
@printf("nrep = %2i p = %.2f dim = %-13s sim = %.5f\n", nrep, p, "$n × $n", sim)
|
||||
end
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// version 1.2.10
|
||||
|
||||
import java.util.Random
|
||||
|
||||
val rand = Random()
|
||||
const val RAND_MAX = 32767
|
||||
|
||||
lateinit var map: IntArray
|
||||
var w = 0
|
||||
var ww = 0
|
||||
|
||||
const val ALPHA = "+.ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
const val ALEN = ALPHA.length - 3
|
||||
|
||||
fun makeMap(p: Double) {
|
||||
val thresh = (p * RAND_MAX).toInt()
|
||||
ww = w * w
|
||||
var i = ww
|
||||
map = IntArray(i)
|
||||
while (i-- != 0) {
|
||||
val r = rand.nextInt(RAND_MAX + 1)
|
||||
if (r < thresh) map[i] = -1
|
||||
}
|
||||
}
|
||||
|
||||
fun showCluster() {
|
||||
var k = 0
|
||||
for (i in 0 until w) {
|
||||
for (j in 0 until w) {
|
||||
val s = map[k++]
|
||||
val c = if (s < ALEN) ALPHA[1 + s] else '?'
|
||||
print(" $c")
|
||||
}
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
fun recur(x: Int, v: Int) {
|
||||
if ((x in 0 until ww) && map[x] == -1) {
|
||||
map[x] = v
|
||||
recur(x - w, v)
|
||||
recur(x - 1, v)
|
||||
recur(x + 1, v)
|
||||
recur(x + w, v)
|
||||
}
|
||||
}
|
||||
|
||||
fun countClusters(): Int {
|
||||
var cls = 0
|
||||
for (i in 0 until ww) {
|
||||
if (map[i] != -1) continue
|
||||
recur(i, ++cls)
|
||||
}
|
||||
return cls
|
||||
}
|
||||
|
||||
fun tests(n: Int, p: Double): Double {
|
||||
var k = 0.0
|
||||
for (i in 0 until n) {
|
||||
makeMap(p)
|
||||
k += countClusters().toDouble() / ww
|
||||
}
|
||||
return k / n
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
w = 15
|
||||
makeMap(0.5)
|
||||
val cls = countClusters()
|
||||
println("width = 15, p = 0.5, $cls clusters:")
|
||||
showCluster()
|
||||
|
||||
println("\np = 0.5, iter = 5:")
|
||||
w = 1 shl 2
|
||||
while (w <= 1 shl 13) {
|
||||
val t = tests(5, 0.5)
|
||||
println("%5d %9.6f".format(w, t))
|
||||
w = w shl 1
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
(*Calculate C_n / n^2 for n=1000, 2000, ..., 10 000*)
|
||||
In[1]:= Table[N[Max@MorphologicalComponents[
|
||||
RandomVariate[BernoulliDistribution[.5], {n, n}],
|
||||
CornerNeighbors -> False]/n^2], {n, 10^3, 10^4, 10^3}]
|
||||
|
||||
(*Find the average*)
|
||||
In[2]:= % // MeanAround
|
||||
|
||||
(*Show a 15x15 matrix with each cluster given an incrementally higher number, Colorize instead of MatrixForm creates an image*)
|
||||
In[3]:= MorphologicalComponents[RandomChoice[{0, 1}, {15, 15}], CornerNeighbors -> False] // MatrixForm
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
import random, sequtils, strformat
|
||||
|
||||
const
|
||||
N = 15
|
||||
T = 5
|
||||
P = 0.5
|
||||
NotClustered = 1
|
||||
Cell2Char = " #abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
NRange = [4, 64, 256, 1024, 4096]
|
||||
|
||||
type Grid = seq[seq[int]]
|
||||
|
||||
|
||||
proc newGrid(n: Positive; p: float): Grid =
|
||||
result = newSeqWith(n, newSeq[int](n))
|
||||
for row in result.mitems:
|
||||
for cell in row.mitems:
|
||||
if rand(1.0) < p: cell = 1
|
||||
|
||||
|
||||
func walkMaze(grid: var Grid; m, n, idx: int) =
|
||||
grid[n][m] = idx
|
||||
if n < grid.high and grid[n + 1][m] == NotClustered:
|
||||
grid.walkMaze(m, n + 1, idx)
|
||||
if m < grid[0].high and grid[n][m + 1] == NotClustered:
|
||||
grid.walkMaze(m + 1, n, idx)
|
||||
if m > 0 and grid[n][m - 1] == NotClustered:
|
||||
grid.walkMaze(m - 1, n, idx)
|
||||
if n > 0 and grid[n - 1][m] == NotClustered:
|
||||
grid.walkMaze(m, n - 1, idx)
|
||||
|
||||
|
||||
func clusterCount(grid: var Grid): int =
|
||||
var walkIndex = 1
|
||||
for n in 0..grid.high:
|
||||
for m in 0..grid[0].high:
|
||||
if grid[n][m] == NotClustered:
|
||||
inc walkIndex
|
||||
grid.walkMaze(m, n, walkIndex)
|
||||
result = walkIndex - 1
|
||||
|
||||
|
||||
proc clusterDensity(n: int; p: float): float =
|
||||
var grid = newGrid(n, p)
|
||||
result = grid.clusterCount() / (n * n)
|
||||
|
||||
|
||||
proc print(grid: Grid) =
|
||||
for n, row in grid:
|
||||
stdout.write n mod 10, ") "
|
||||
for cell in row:
|
||||
stdout.write ' ', Cell2Char[cell]
|
||||
stdout.write '\n'
|
||||
|
||||
|
||||
when isMainModule:
|
||||
|
||||
randomize()
|
||||
|
||||
var grid = newGrid(N, 0.5)
|
||||
echo &"Found {grid.clusterCount()} clusters in this {N} by {N} grid\n"
|
||||
grid.print()
|
||||
echo ""
|
||||
|
||||
for n in NRange:
|
||||
var sum = 0.0
|
||||
for _ in 1..T:
|
||||
sum += clusterDensity(n, P)
|
||||
let sim = sum / T
|
||||
echo &"t = {T} p = {P:4.2f} n = {n:4} sim = {sim:7.5f}"
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
$fill = 'x';
|
||||
$D{$_} = $i++ for qw<DeadEnd Up Right Down Left>;
|
||||
|
||||
sub deq { defined $_[0] && $_[0] eq $_[1] }
|
||||
|
||||
sub perctest {
|
||||
my($grid) = @_;
|
||||
generate($grid);
|
||||
my $block = 1;
|
||||
for my $y (0..$grid-1) {
|
||||
for my $x (0..$grid-1) {
|
||||
fill($x, $y, $block++) if $perc[$y][$x] eq $fill
|
||||
}
|
||||
}
|
||||
($block - 1) / $grid**2;
|
||||
}
|
||||
|
||||
sub generate {
|
||||
my($grid) = @_;
|
||||
for my $y (0..$grid-1) {
|
||||
for my $x (0..$grid-1) {
|
||||
$perc[$y][$x] = rand() < .5 ? '.' : $fill;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub fill {
|
||||
my($x, $y, $block) = @_;
|
||||
$perc[$y][$x] = $block;
|
||||
my @stack;
|
||||
while (1) {
|
||||
if (my $dir = direction( $x, $y )) {
|
||||
push @stack, [$x, $y];
|
||||
($x,$y) = move($dir, $x, $y, $block)
|
||||
} else {
|
||||
return unless @stack;
|
||||
($x,$y) = @{pop @stack};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub direction {
|
||||
my($x, $y) = @_;
|
||||
return $D{Down} if deq($perc[$y+1][$x ], $fill);
|
||||
return $D{Left} if deq($perc[$y ][$x-1], $fill);
|
||||
return $D{Right} if deq($perc[$y ][$x+1], $fill);
|
||||
return $D{Up} if deq($perc[$y-1][$x ], $fill);
|
||||
return $D{DeadEnd};
|
||||
}
|
||||
|
||||
sub move {
|
||||
my($dir,$x,$y,$block) = @_;
|
||||
$perc[--$y][ $x] = $block if $dir == $D{Up};
|
||||
$perc[++$y][ $x] = $block if $dir == $D{Down};
|
||||
$perc[ $y][ --$x] = $block if $dir == $D{Left};
|
||||
$perc[ $y][ ++$x] = $block if $dir == $D{Right};
|
||||
($x, $y)
|
||||
}
|
||||
|
||||
my $K = perctest(15);
|
||||
for my $row (@perc) {
|
||||
printf "%3s", $_ for @$row;
|
||||
print "\n";
|
||||
}
|
||||
printf "𝘱 = 0.5, 𝘕 = 15, 𝘒 = %.4f\n\n", $K;
|
||||
|
||||
$trials = 5;
|
||||
for $N (10, 30, 100, 300, 1000) {
|
||||
my $total = 0;
|
||||
$total += perctest($N) for 1..$trials;
|
||||
printf "𝘱 = 0.5, trials = $trials, 𝘕 = %4d, 𝘒 = %.4f\n", $N, $total / $trials;
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">grid</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ww</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">make_grid</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">ww</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">*</span><span style="color: #000000;">w</span>
|
||||
<span style="color: #000000;">grid</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ww</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">ww</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-(</span><span style="color: #7060A8;">rnd</span><span style="color: #0000FF;">()<</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">alpha</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"+.ABCDEFGHIJKLMNOPQRSTUVWXYZ"</span><span style="color: #0000FF;">&</span>
|
||||
<span style="color: #008000;">"abcdefghijklmnopqrstuvwxyz"</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">show_cluster</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">ww</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">gi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">2</span>
|
||||
<span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">gi</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">alpha</span><span style="color: #0000FF;">)?</span><span style="color: #000000;">alpha</span><span style="color: #0000FF;">[</span><span style="color: #000000;">gi</span><span style="color: #0000FF;">]:</span><span style="color: #008000;">'?'</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join_by</span><span style="color: #0000FF;">(</span><span style="color: #000000;">grid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">w</span><span style="color: #0000FF;">,</span><span style="color: #000000;">w</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">recur</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">x</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">ww</span> <span style="color: #008080;">and</span> <span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]==-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">v</span>
|
||||
<span style="color: #000000;">recur</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">-</span><span style="color: #000000;">w</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">recur</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">recur</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">recur</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">+</span><span style="color: #000000;">w</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">count_clusters</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">cls</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">ww</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">cls</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #000000;">recur</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cls</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">cls</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">(</span><span style="color: #004080;">int</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">make_grid</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">k</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">count_clusters</span><span style="color: #0000FF;">()/</span><span style="color: #000000;">ww</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">n</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #000000;">w</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">15</span>
|
||||
<span style="color: #000000;">make_grid</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"width=15, p=0.5, %d clusters:\n"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">count_clusters</span><span style="color: #0000FF;">())</span>
|
||||
<span style="color: #000000;">show_cluster</span><span style="color: #0000FF;">()</span>
|
||||
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\np=0.5, iter=5:\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">w</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">4</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">w</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">4096</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%5d %9.6f\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">w</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">)})</span>
|
||||
<span style="color: #000000;">w</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">4</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
|
||||
<!--
|
||||
|
|
@ -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))
|
||||
|
|
@ -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,66 @@
|
|||
my @perc;
|
||||
my $fill = 'x';
|
||||
|
||||
enum Direction <DeadEnd Up Right Down Left>;
|
||||
|
||||
my $𝘒 = perctest(15);
|
||||
.fmt("%-2s").say for @perc;
|
||||
say "𝘱 = 0.5, 𝘕 = 15, 𝘒 = $𝘒\n";
|
||||
|
||||
my $trials = 5;
|
||||
for 10, 30, 100, 300, 1000 -> $𝘕 {
|
||||
my $𝘒 = ( [+] perctest($𝘕) xx $trials ) / $trials;
|
||||
say "𝘱 = 0.5, trials = $trials, 𝘕 = $𝘕, 𝘒 = $𝘒";
|
||||
}
|
||||
|
||||
sub infix:<deq> ( $a, $b ) { $a.defined && ($a eq $b) }
|
||||
|
||||
sub perctest ( $grid ) {
|
||||
generate $grid;
|
||||
my $block = 1;
|
||||
for ^$grid X ^$grid -> ($y, $x) {
|
||||
fill( [$x, $y], $block++ ) if @perc[$y; $x] eq $fill
|
||||
}
|
||||
($block - 1) / $grid²;
|
||||
}
|
||||
|
||||
sub generate ( $grid ) {
|
||||
@perc = ();
|
||||
@perc.push: [ ( rand < .5 ?? '.' !! $fill ) xx $grid ] for ^$grid;
|
||||
}
|
||||
|
||||
sub fill ( @cur, $block ) {
|
||||
@perc[@cur[1]; @cur[0]] = $block;
|
||||
my @stack;
|
||||
my $current = @cur;
|
||||
|
||||
loop {
|
||||
if my $dir = direction( $current ) {
|
||||
@stack.push: $current;
|
||||
$current = move $dir, $current, $block
|
||||
}
|
||||
else {
|
||||
return unless @stack;
|
||||
$current = @stack.pop
|
||||
}
|
||||
}
|
||||
|
||||
sub direction( [$x, $y] ) {
|
||||
( Down if @perc[$y + 1][$x] deq $fill ) ||
|
||||
( Left if @perc[$y][$x - 1] deq $fill ) ||
|
||||
( Right if @perc[$y][$x + 1] deq $fill ) ||
|
||||
( Up if @perc[$y - 1][$x] deq $fill ) ||
|
||||
DeadEnd
|
||||
}
|
||||
|
||||
sub move ( $dir, @cur, $block ) {
|
||||
my ( $x, $y ) = @cur;
|
||||
given $dir {
|
||||
when Up { @perc[--$y; $x] = $block }
|
||||
when Down { @perc[++$y; $x] = $block }
|
||||
when Left { @perc[$y; --$x] = $block }
|
||||
when Right { @perc[$y; ++$x] = $block }
|
||||
}
|
||||
[$x, $y]
|
||||
}
|
||||
}
|
||||
|
|
@ -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}]"
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
import "random" for Random
|
||||
import "/fmt" for Fmt
|
||||
|
||||
var rand = Random.new()
|
||||
var RAND_MAX = 32767
|
||||
|
||||
var list = []
|
||||
var w = 0
|
||||
var ww = 0
|
||||
|
||||
var ALPHA = "+.ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
var ALEN = ALPHA.count - 3
|
||||
|
||||
var makeList = Fn.new { |p|
|
||||
var thresh = (p * RAND_MAX).truncate
|
||||
ww = w * w
|
||||
var i = ww
|
||||
list = List.filled(i, 0)
|
||||
while (i != 0) {
|
||||
i = i - 1
|
||||
var r = rand.int(RAND_MAX+1)
|
||||
if (r < thresh) list[i] = -1
|
||||
}
|
||||
}
|
||||
|
||||
var showCluster = Fn.new {
|
||||
var k = 0
|
||||
for (i in 0...w) {
|
||||
for (j in 0...w) {
|
||||
var s = list[k]
|
||||
k = k + 1
|
||||
var c = (s < ALEN) ? ALPHA[1 + s] : "?"
|
||||
System.write(" %(c)")
|
||||
}
|
||||
System.print()
|
||||
}
|
||||
}
|
||||
|
||||
var recur // recursive
|
||||
recur = Fn.new { |x, v|
|
||||
if (x >= 0 && x < ww && list[x] == -1) {
|
||||
list[x] = v
|
||||
recur.call(x - w, v)
|
||||
recur.call(x - 1, v)
|
||||
recur.call(x + 1, v)
|
||||
recur.call(x + w, v)
|
||||
}
|
||||
}
|
||||
|
||||
var countClusters = Fn.new {
|
||||
var cls = 0
|
||||
for (i in 0...ww) {
|
||||
if (list[i] == -1) {
|
||||
cls = cls + 1
|
||||
recur.call(i, cls)
|
||||
}
|
||||
}
|
||||
return cls
|
||||
}
|
||||
|
||||
var tests = Fn.new { |n, p|
|
||||
var k = 0
|
||||
for (i in 0...n) {
|
||||
makeList.call(p)
|
||||
k = k + countClusters.call() / ww
|
||||
}
|
||||
return k / n
|
||||
}
|
||||
|
||||
w = 15
|
||||
makeList.call(0.5)
|
||||
var cls = countClusters.call()
|
||||
System.print("width = 15, p = 0.5, %(cls) clusters:")
|
||||
showCluster.call()
|
||||
|
||||
System.print("\np = 0.5, iter = 5:")
|
||||
w = 1 << 2
|
||||
while (w <= (1 << 13)) {
|
||||
var t = tests.call(5, 0.5)
|
||||
Fmt.print("$5d $9.6f", w, t)
|
||||
w = w << 1
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
const X=-1; // the sentinal that marks an untouched cell
|
||||
var C,N,NN,P;
|
||||
fcn createC(n,p){
|
||||
N,P=n,p; NN=N*N;
|
||||
C=NN.pump(List.createLong(NN),0); // vector of ints
|
||||
foreach n in (NN){ C[n]=X*(Float.random(1)<=P) } // X is the sentinal
|
||||
}
|
||||
fcn showCluster{
|
||||
alpha:="-ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz";
|
||||
foreach n in ([0..NN,N]){ C[n,N].pump(String,alpha.get).println() }
|
||||
}
|
||||
fcn countClusters{
|
||||
clusters:=0;
|
||||
foreach n in (NN){
|
||||
if(X!=C[n]) continue;
|
||||
fcn(n,v){
|
||||
if((0<=n<NN) and C[n]==X){
|
||||
C[n]=v;
|
||||
self.fcn(n-N,v); self.fcn(n-1,v); self.fcn(n+1,v); self.fcn(n+N,v);
|
||||
}
|
||||
}(n,clusters+=1);
|
||||
}
|
||||
clusters
|
||||
}
|
||||
fcn tests(N,n,p){
|
||||
k:=0.0;
|
||||
foreach z in (n){ createC(N,p); k+=countClusters().toFloat()/NN; }
|
||||
k/n
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
createC(15,0.5);
|
||||
println("width=%d, p=%.1f, %d clusters:".fmt(N,P,countClusters()));
|
||||
showCluster();
|
||||
|
||||
println("p=0.5, 5 iterations:");
|
||||
w:=4; do(6){ println("%5d %9.6f".fmt(w,tests(w, 5, 0.5))); w*=4; }
|
||||
Loading…
Add table
Add a link
Reference in a new issue