Jump to page: 1 2
Thread overview
Range of random numbers
Apr 23, 2012
bearophile
Apr 23, 2012
Dmitry Olshansky
Apr 23, 2012
jerro
Apr 23, 2012
bearophile
Apr 23, 2012
Ali Çehreli
Apr 23, 2012
jerro
Apr 23, 2012
bearophile
Apr 23, 2012
bearophile
Apr 24, 2012
Christophe
Apr 24, 2012
bearophile
Apr 25, 2012
Christophe Travert
April 23, 2012
For some reason this got lost in the ether, so I'm resending.

Related to my earlier question on passing a function -- I was wondering if there's a trivial way of generating a lazily-evaluated range of random numbers according to a given distribution and parameters.

I wrote up the code below to generate a range of uniformly-distributed
numbers, but am not sure how to generalize it for arbitrary distribution and/or
parameters, and I'm also not sure that I'm overcomplicating what might be more
easily achieved with existing D functionality.

The larger goal here is that I want some way to pass an _arbitrary_ number source (may be deterministic, may be stochastic) to a function.  A range seemed a good way to do that (after all, in the deterministic case I can just pass an array, no?).

... but I couldn't work out how to generalize the stochastic case beyond what's shown here.

///////////////////////////////////////////////////////////////////////////////
import std.array, std.random, std.range, std.stdio;

struct UniformRange(T1, T2)
{
	T1 _lower;
	T2 _upper;
	
	@property enum bool empty = false;
	
	this(T1 a, T2 b)
	{
		_lower = a;
		_upper = b;
	}

	@property auto ref front()
	{
		assert(!empty);
		return uniform(_lower, _upper);
	}

	void popFront()
	{
	}
}

auto uniformRange(T1, T2)(T1 a, T2 b)
{
	return UniformRange!(T1, T2)(a, b);
}

auto uniformRange(T1, T2)(size_t n, T1 a, T2 b)
{
	return take(UniformRange!(T1, T2)(a, b), n);
}

void main()
{
	auto ur = uniformRange!(double, double)(5, 10.0, 20.0);
	double[] x = array( take(uniformRange(1.0, 2.0), 5) );
	double[] y = array(x);
	
	foreach(r; ur)
		writeln(r);
	writeln;

	foreach(r; ur)
		writeln(r);
	writeln;

	foreach(r; x)
		writeln(r);
	writeln;

	foreach(r; y)
		writeln(r);
	writeln;
}

April 23, 2012
Joseph Rushton Wakeling:

> struct UniformRange(T1, T2)
> {
> 	T1 _lower;
> 	T2 _upper;
> 	
> 	@property enum bool empty = false;
> 	
> 	this(T1 a, T2 b)
> 	{
> 		_lower = a;
> 		_upper = b;
> 	}
>
> 	@property auto ref front()
> 	{
> 		assert(!empty);
> 		return uniform(_lower, _upper);
> 	}
>
> 	void popFront()
> 	{
> 	}
> }

What about (untested):

auto uniformRange(T1 lower, T2 upper) {
    return count().map!(_ => uniform(lower, upper))();
}

Where count() is just:
http://d.puremagic.com/issues/show_bug.cgi?id=7839

In the meantime cycle([0]) is acceptable but slower (untested):

return cycle([0]).map!(_ => uniform(lower, upper))();

Bye,
bearophile
April 23, 2012
On 23.04.2012 17:52, bearophile wrote:
> Joseph Rushton Wakeling:
>
>> struct UniformRange(T1, T2)
>> {
>> T1 _lower;
>> T2 _upper;
>>
>> @property enum bool empty = false;
>>
>> this(T1 a, T2 b)
>> {
>> _lower = a;
>> _upper = b;
>> }
>>
>> @property auto ref front()
>> {
>> assert(!empty);
>> return uniform(_lower, _upper);
>> }
>>
>> void popFront()
>> {
>> }
>> }
>
> What about (untested):
>
> auto uniformRange(T1 lower, T2 upper) {
> return count().map!(_ => uniform(lower, upper))();
> }
>
> Where count() is just:
> http://d.puremagic.com/issues/show_bug.cgi?id=7839
>

What's wrong with:
http://dlang.org/phobos/std_algorithm.html#count

> In the meantime cycle([0]) is acceptable but slower (untested):
>
> return cycle([0]).map!(_ => uniform(lower, upper))();
>
> Bye,
> bearophile


-- 
Dmitry Olshansky
April 23, 2012
> What about (untested):
>
> auto uniformRange(T1 lower, T2 upper) {
>     return count().map!(_ => uniform(lower, upper))();
> }
>
> Where count() is just:
> http://d.puremagic.com/issues/show_bug.cgi?id=7839
>
> In the meantime cycle([0]) is acceptable but slower (untested):
>
> return cycle([0]).map!(_ => uniform(lower, upper))();

He could also use repeat in this case:

return repeat(0).map!(_ => uniform(lower, upper))();

repeat(0) returns the same sequence as cycle([0]) and is as fast
as it gets, since popFront does nothing and empty is an enum.
April 23, 2012
jerro:

> return repeat(0).map!(_ => uniform(lower, upper))();
> 
> repeat(0) returns the same sequence as cycle([0]) and is as fast
> as it gets, since popFront does nothing and empty is an enum.

Good idea.

-------------------

Dmitry Olshansky:

> What's wrong with: http://dlang.org/phobos/std_algorithm.html#count

It's for a different purpose. So the count() I was proposing will need a different name.

Bye,
bearophile
April 23, 2012
On 23/04/12 18:56, bearophile wrote:
> jerro:
>
>> return repeat(0).map!(_ =>  uniform(lower, upper))();
>>
>> repeat(0) returns the same sequence as cycle([0]) and is as fast
>> as it gets, since popFront does nothing and empty is an enum.
>
> Good idea.

Yes, this works nicely.  Thanks very much!
April 23, 2012
On 23/04/12 19:46, Joseph Rushton Wakeling wrote:
> On 23/04/12 18:56, bearophile wrote:
>> jerro:
>>
>>> return repeat(0).map!(_ => uniform(lower, upper))();
>>>
>
> Yes, this works nicely. Thanks very much!

Is this a new addition?  With GDC I get a compiler error:

  expression expected, not '>'

... suggesting => isn't supported.

April 23, 2012
On 04/23/2012 10:56 AM, Joseph Rushton Wakeling wrote:
> On 23/04/12 19:46, Joseph Rushton Wakeling wrote:
>> On 23/04/12 18:56, bearophile wrote:
>>> jerro:
>>>
>>>> return repeat(0).map!(_ => uniform(lower, upper))();
>>>>
>>
>> Yes, this works nicely. Thanks very much!
>
> Is this a new addition? With GDC I get a compiler error:
>
> expression expected, not '>'
>
> ... suggesting => isn't supported.
>

The lambda syntax was added in 2.058:

  http://dlang.org/changelog.html

Ali
April 23, 2012
> It's for a different purpose. So the count() I was proposing will need a different name.

Couldn't it just be iota with no parameters?
April 23, 2012
jerro:
> Couldn't it just be iota with no parameters?

The Count range has a helper count() function similar to this, that's meant to have an argument that defaults to zero:

Count!T count(T)(T start=0) if (isIntegral!T) { return Count!T(start); }

The argument allows it to start from another starting point, and it allows you to specify the type of the numbers it yields, while in iota() without arguments it's less easy to specify the type of the numbers it yields.

Count(5) is easy to replace with iota(5, int.max), but count(BigInt(0)) is less easy to replace with iota, because it doesn't give you a way to denote a right-open BigInt interval. And using iota(BigInt(0), BigInt(ulong.max)) is not that good. Currently using BigInt in iota seems to not even being supported...

Bye,
bearophile
« First   ‹ Prev
1 2