generating random tuples in python

P

per

hi all,

i am generating a list of random tuples of numbers between 0 and 1
using the rand() function, as follows:

for i in range(0, n):
rand_tuple = (rand(), rand(), rand())
mylist.append(rand_tuple)

when i generate this list, some of the random tuples might be
very close to each other, numerically. for example, i might get:

(0.553, 0.542, 0.654)

and

(0.581, 0.491, 0.634)

so the two tuples are close to each other in that all of their numbers
have similar magnitudes.

how can i maximize the amount of "numeric distance" between the
elements of
this list, but still make sure that all the tuples have numbers
strictly
between 0 and 1 (inclusive)?

in other words i want the list of random numbers to be arbitrarily
different (which is why i am using rand()) but as different from other
tuples in the list as possible.

thank you for your help
 
B

bearophileHUGS

per:
in other words i want the list of random numbers to be arbitrarily
different (which is why i am using rand()) but as different from other
tuples in the list as possible.

This is more or less the problem of packing n equal spheres in a cube.
There is a lot of literature on this. You can use a simulated
annealing to find good enough solutions. You just need 15 lines of
code or less. But it's going to be slow if n is not very small. A fast
language (or Psyco) is better for that.

Bye,
bearophile
 
A

Arnaud Delobelle

per said:
hi all,

i am generating a list of random tuples of numbers between 0 and 1
using the rand() function, as follows:

for i in range(0, n):
rand_tuple = (rand(), rand(), rand())
mylist.append(rand_tuple)

when i generate this list, some of the random tuples might be
very close to each other, numerically. for example, i might get:

(0.553, 0.542, 0.654)

and

(0.581, 0.491, 0.634)

so the two tuples are close to each other in that all of their numbers
have similar magnitudes.

how can i maximize the amount of "numeric distance" between the
elements of this list, but still make sure that all the tuples have
numbers strictly between 0 and 1 (inclusive)?

To solve your problem, you need to define quantitatively what your
"numeric distance" is.
 
S

Steven D'Aprano

hi all,

i am generating a list of random tuples of numbers between 0 and 1 using
the rand() function, as follows:

for i in range(0, n):
rand_tuple = (rand(), rand(), rand()) mylist.append(rand_tuple)

when i generate this list, some of the random tuples might be very close
to each other, numerically. for example, i might get: [...]
how can i maximize the amount of "numeric distance" between the elements
of
this list, but still make sure that all the tuples have numbers strictly
between 0 and 1 (inclusive)?

Well, the only way to *maximise* the distance between the elements is to
set them to (0.0, 0.5, 1.0).

in other words i want the list of random numbers to be arbitrarily
different (which is why i am using rand()) but as different from other
tuples in the list as possible.

That means that the numbers you are generating will no longer be
uniformly distributed, they will be biased. That's okay, but you need to
describe *how* you want them biased. What precisely do you mean by
"maximizing the distance"?

For example, here's one strategy: you need three random numbers, so
divide the complete range 0-1 into three: generate three random numbers
between 0 and 1/3.0, called x, y, z, and return [x, 1/3.0 + y, 2/3.0 + z].

You might even decide to shuffle the list before returning them.

But note that you might still happen to get (say) [0.332, 0.334, 0.668]
or similar. That's the thing with randomness.
 
P

per

i am generating a list of random tuples of numbers between 0 and 1 using
the rand() function, as follows:
for i in range(0, n):
  rand_tuple = (rand(), rand(), rand()) mylist.append(rand_tuple)
when i generate this list, some of the random tuples might be very close
to each other, numerically. for example, i might get: [...]
how can i maximize the amount of "numeric distance" between the elements
of
this list, but still make sure that all the tuples have numbers strictly
between 0 and 1 (inclusive)?

Well, the only way to *maximise* the distance between the elements is to
set them to (0.0, 0.5, 1.0).
in other words i want the list of random numbers to be arbitrarily
different (which is why i am using rand()) but as different from other
tuples in the list as possible.

That means that the numbers you are generating will no longer be
uniformly distributed, they will be biased. That's okay, but you need to
describe *how* you want them biased. What precisely do you mean by
"maximizing the distance"?

For example, here's one strategy: you need three random numbers, so
divide the complete range 0-1 into three: generate three random numbers
between 0 and 1/3.0, called x, y, z, and return [x, 1/3.0 + y, 2/3.0 + z]..

You might even decide to shuffle the list before returning them.

But note that you might still happen to get (say) [0.332, 0.334, 0.668]
or similar. That's the thing with randomness.

i realize my example in the original post was misleading. i dont want
to maximize the difference between individual members of a single
tuple -- i want to maximize the difference between distinct tuples. in
other words, it's ok to have (.332, .334, .38), as long as the other
tuple is, say, (.52, .6, .9) which is very difference from (.332, .
334, .38). i want the member of a given tuple to be arbitrary, e.g.
something like (rand(), rand(), rand()) but that the tuples be very
different from each other.

to be more formal by very different, i would be happy if they were
maximally distant in ordinary euclidean space... so if you just plot
the 3-tuples on x, y, z i want them to all be very different from each
other. i realize this is obviously biased and that the tuples are not
uniformly distributed -- that's exactly what i want...

any ideas on how to go about this?

thank you.
 
P

Paul Rubin

per said:
to be more formal by very different, i would be happy if they were
maximally distant in ordinary euclidean space...

In that case you want them placed very carefully, not even slightly
random. So you are making conflicting requests.
 
A

Aaron Brady

hi all,
i am generating a list of random tuples of numbers between 0 and 1 using
the rand() function, as follows:
for i in range(0, n):
  rand_tuple = (rand(), rand(), rand()) mylist.append(rand_tuple)
when i generate this list, some of the random tuples might be very close
to each other, numerically. for example, i might get: [...]
how can i maximize the amount of "numeric distance" between the elements
of
this list, but still make sure that all the tuples have numbers strictly
between 0 and 1 (inclusive)?
Well, the only way to *maximise* the distance between the elements is to
set them to (0.0, 0.5, 1.0).
That means that the numbers you are generating will no longer be
uniformly distributed, they will be biased. That's okay, but you need to
describe *how* you want them biased. What precisely do you mean by
"maximizing the distance"?
For example, here's one strategy: you need three random numbers, so
divide the complete range 0-1 into three: generate three random numbers
between 0 and 1/3.0, called x, y, z, and return [x, 1/3.0 + y, 2/3.0 + z].
You might even decide to shuffle the list before returning them.
But note that you might still happen to get (say) [0.332, 0.334, 0.668]
or similar. That's the thing with randomness.

i realize my example in the original post was misleading. i dont want
to maximize the difference between individual members of a single
tuple -- i want to maximize the difference between distinct tuples. in
other words, it's ok to have (.332, .334, .38), as long as the other
tuple is, say, (.52, .6, .9) which is very difference from (.332, .
334, .38).  i want the member of a given tuple to be arbitrary, e.g.
something like (rand(), rand(), rand()) but that the tuples be very
different from each other.

to be more formal by very different, i would be happy if they were
maximally distant in ordinary euclidean space... so if you just plot
the 3-tuples on x, y, z i want them to all be very different from each
other.  i realize this is obviously biased and that the tuples are not
uniformly distributed -- that's exactly what i want...

any ideas on how to go about this?

thank you.

Two ideas. One, start with a square grid and jitter the individual
points by a small random amount. Two, start with one point, and move
from it by a random large distance: a2= a1+ .5+ rand( ), then %1.
 
S

Steven D'Aprano

i realize my example in the original post was misleading. i dont want to
maximize the difference between individual members of a single tuple --
i want to maximize the difference between distinct tuples. in other
words, it's ok to have (.332, .334, .38), as long as the other tuple is,
say, (.52, .6, .9) which is very difference from (.332, . 334, .38). i
want the member of a given tuple to be arbitrary, e.g. something like
(rand(), rand(), rand()) but that the tuples be very different from each
other.

to be more formal by very different, i would be happy if they were
maximally distant in ordinary euclidean space... so if you just plot the
3-tuples on x, y, z i want them to all be very different from each
other. i realize this is obviously biased and that the tuples are not
uniformly distributed -- that's exactly what i want...


If you *really* mean "maximally distant", the maximal distance in a 1x1x1
cube is sqrt(3). Clearly you can't move sqrt(3) away in an arbitrary
direction from an arbitrary point and remain inside the cube, but you
could probably do something like this:

* generate a random point (a, b, c);
* work out what's the furthest you can go from there and still remain
inside the cube;
* return that point as the second point.

Problem is that one out of every two points will be on the edge of the
cube. This will be *seriously* biase, and obviously so.


Here's another strategy: given the first point, generated randomly,
reflect it around the centre point (0.5, 0.5, 0.5) in some plane to give
the second point. You'll need to do some geometry to determine what plane
to use. Disadvantage: the points will have a very strong symmetry.


Third strategy: divide the cube into eight half-cubes. Label then A
through H:

A: 0.0 <= x <= 0.5, 0.0 <= y <= 0.5, 0.0 <= z <= 0.5
B: 0.5 < x <= 1.0, 0.0 <= y <= 0.5, 0.0 <= z <= 0.5
C: 0.0 <= x <= 0.5, 0.5 < y <= 1.0, 0.0 <= z <= 0.5
D: 0.5 < x <= 1.0, 0.5 < y <= 1.0, 0.0 <= z <= 0.5

(E, F, G, H are the same but with 0.5 < z <= 1.0)

Generate a point in one half of the cube, A-D. If the point is in A, then
the second point needs to be in H; if the first point is in B, the second
should be in G; if the first point is in C, then generate your second
point in F, and if in D, generate a point in E.

This will give you points which are still random-ish, but on average they
should be sqrt(3)/2 apart, which is probably about as far as you can
reasonably expect. There will be some symmetry, *on average*, but
individual points shouldn't have a mirror image (except by some fluke).
 
S

Steven D'Aprano

Third strategy: divide the cube into eight half-cubes. Label then A
through H:

Sheesh. Obviously they're not *half* cubes if there are eight of them.
What I meant was that their edges are half as long as the edge of the
1x1x1 cube.
 
R

Robert Kern

to be more formal by very different, i would be happy if they were
maximally distant in ordinary euclidean space... so if you just plot
the 3-tuples on x, y, z i want them to all be very different from each
other. i realize this is obviously biased and that the tuples are not
uniformly distributed -- that's exactly what i want...

any ideas on how to go about this?

Perhaps it would help if you told us what application you are going to use them
for? You can straightforwardly make a regular tetrahedral grid of points that
fit in your box at whatever density you like. Which is more important: maximal
(average) distance between neighbors or avoiding regularity? If you need to
strike a balance between them, then you may want to look into low-discrepancy
sequences:

http://en.wikipedia.org/wiki/Low-discrepancy_sequence

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 
R

Raymond Hettinger

[per]
i realize my example in the original post was misleading. i dont want
to maximize the difference between individual members of a single
tuple -- i want to maximize the difference between distinct tuples. in
other words, it's ok to have (.332, .334, .38), as long as the other
tuple is, say, (.52, .6, .9) which is very difference from (.332, .
334, .38).  i want the member of a given tuple to be arbitrary, e.g.
something like (rand(), rand(), rand()) but that the tuples be very
different from each other.

No problem, just define a predicate that formalizes what you mean by
"very different from each other".

def generate_very_different_random_tuples(n):
selected = set()
for i in range(n):
t = rand(), rand(), rand()
while any(not very_different(t, s) for s in selected):
t = rand(), rand(), rand()
selected.add(t)
return list(selected)


Raymond
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top