Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Re: Randomly biased, random numbers.

by GrandFather (Saint)
on Dec 08, 2013 at 10:04 UTC ( [id://1066201]=note: print w/replies, xml ) Need Help??


in reply to Randomly biased, random numbers.

A little late to the party, but maybe interesting. The following code generates a random set of "attractors" which tend to suck near by randomly generated points closer to the attractor. Attractors have a radius which limits their effect. Nearby attractors fight with each other which results in oddly shaped clumping, which is most likely a desirable outcome.

use strict; use warnings; use Tk; use Tk::Canvas; use List::Util qw(min max); my $kMaxRadius = 400; my $kMinRadius = 50; my $kNumPoints = 1000; run(); sub run { my $halfSteps = 20; my $halfWidth = 350; my ($spanAdj, @attractors) = calcAttractors(1 + rand 3, $halfWidth +); my @points = genPoints($halfWidth, $kNumPoints); #my @points = genGrid($halfSteps, $halfWidth / $halfSteps); my @biasedPoints = biasPoints(\@attractors, $spanAdj, @points); my $margin = 10; my $max = 2 * $margin + $halfWidth * 2 - 1; my $mw = MainWindow->new(-title => "Biased random"); my $canvas = $mw->Canvas(-height => $max, -width => $max)->pac +k(); my $offset = $margin + $halfWidth; plot($canvas, $offset, 'blue', @points); plot($canvas, $offset, 'red', @biasedPoints); #plotAttractors($canvas, $offset, $max, @attractors); $mw->MainLoop(); } sub calcAttractors { my ($num, $w2) = @_; my $width = 2 * $w2; my @attractors; my $adj = 1; for (1 .. $num) { my $x = rand ($width) - $w2; my $y = rand ($width) - $w2; my @edges = ([$w2, $y], [-$w2, $y], [$x, $w2], [$x, -$w2]); my $radius = $kMinRadius + rand ($kMaxRadius - $kMinRadius); my @biases; push @biases, calcBias($_->[0], $_->[1], [$x, $y, $radius]) fo +r @edges; my $maxBias = max(map {abs} @biases); $adj = max($adj, ($w2 + $maxBias) / $w2); push @attractors, [$x, $y, $radius]; } return $adj, @attractors; } sub genPoints { my ($halfWidth, $numPoints) = @_; my $width = $halfWidth * 2; my @points; for (1 .. $numPoints) { push @points, [rand ($width) - $halfWidth, rand ($width) - $ha +lfWidth]; } return @points; } sub biasPoints { my ($attractors, $spanAdj, @inPoints) = @_; my @outPoints; return @inPoints if !$attractors || !@$attractors; for my $point (@inPoints) { my ($x, $y) = @$point; my $xOff; my $yOff; for my $atPt (@$attractors) { my ($xBias, $yBias) = calcBias($x, $y, $atPt); $xOff += $xBias; $yOff += $yBias; } push @outPoints, [$spanAdj * $point->[0] + $xOff, $spanAdj * $point->[1] + +$yOff]; } return @outPoints; } sub calcBias { my ($x, $y, $point, $spanAdj) = @_; my ($pX, $pY, $pRadius) = @$point; my $dX = $pX - $x; my $dY = $pY - $y; my $dist = sqrt ($dX**2 + $dY**2); my $scale = cos (1.5708 * min(1, $dist / $pRadius)); return $dX * $scale, $dY * $scale; } sub genGrid { my ($halfSteps, $inc) = @_; my @points; for my $x (-$halfSteps .. $halfSteps) { for my $y (-$halfSteps .. $halfSteps) { push @points, [$x * $inc, $y * $inc]; } } return @points; } sub plot { my ($canvas, $offset, $colour, @points) = @_; for my $point (@points) { my ($x, $y) = @$point; $x += $offset; $y += $offset; $canvas->createLine($x - 1, $y, $x + 2, $y, -fill => $ +colour); $canvas->createLine($x, $y - 1, $x, $y + 2, -fill => $ +colour); } } sub plotAttractors { my ($canvas, $offset, $max, @attractors) = @_; for my $point (@attractors) { my ($x, $y, $radius) = @$point; $radius /= 4; $radius ||= 1; $x += $offset; $y += $offset; $canvas->createLine( max($x - $radius, 1), $y, min($x + $radius + 1, $max), $y, -fill => 'green' ); $canvas->createLine( $x, max($y - $radius, 1), $x, min($y + $radius + 1, $max), -fill => 'green' ); } }

The script above plots results using Tk and includes a little commented out code that was used while tuning the code. At present both the original points and the biased points are plotted.

True laziness is hard work

Replies are listed 'Best First'.
Re^2: Randomly biased, random numbers.
by BrowserUk (Patriarch) on Dec 09, 2013 at 16:41 UTC
    A little late to the party, but maybe interesting

    Thanks for the reply and code.

    I played with this a little and it definitely produces clumps. The problem with it (for my purposes) is that it always leaves a background of relatively uniformly distributed points, and I couldn't see any way of preventing that.

    For my purpose, I really want clear space around and between the clumps, which the weight map method both achieves and gives fine control over.

    However, your "attractors" idea sparked another idea in me -- completely unrelated to OP purpose -- but intriguing enough to sidetrack me for a day or so.

    What happens if you treat a set of clumpy random points as equally sized particles of some finite mass, and have them all exert "gravity" upon each other according to the inverse square of their distance.

    Tada. The red dots are the starting position, the cyan their position after a single round of attraction, and the blue, after the second.

    Ignore the ones that 'sling-shot' off into outer space; the effect of the inverse square law is that in order to get detectable influence over any distance, you have to set the mass of the points quite high, with the consequence that once they get very close to each other, they exert huge forces that results in sling shots because there are no collisions.

    Over many generations, the gravity will cause all the points to come together (and then be scattered in all directions), but the first few generations have the effect of concentrating whatever clusters already exist. I wonder if this wouldn't be a fruitful technique for tackling the NP-hard clustering problem without resorting making assumptions per the K-means type of algorithm?


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1066201]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (4)
As of 2024-04-24 20:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found