Re: Experimental approach to reference-type random number generators
See also this idea (and API problem): http://d.puremagic.com/issues/show_bug.cgi?id=5849 Bye, bearophile
Re: Experimental approach to reference-type random number generators
On 01/09/13 14:21, bearophile wrote: See also this idea (and API problem): http://d.puremagic.com/issues/show_bug.cgi?id=5849 On dice(): I think this is one case of what is in practice a random number _distribution_, akin to uniform(). My own instinct is that as much as possible, random number distributions should come in two forms -- functions, and ranges. So, it should be possible to go, foreach(_; 0 .. 10) { writeln(uniform(0.0, 1.0)); writeln(dice(10, 5, 7)); } but equally well to go, auto uniDist = uniformDistribution(0.0, 1.0); auto biasedDice = diceDistribution(10, 5, 7); foreach(u, d; lockstep(uniDist, biasedDice).take(10)) { writeln(u); writeln(d); } (I'm sure you can find something to improve in how I've written the second example, but you get the idea of how the distributions could behave:-)
Re: Experimental approach to reference-type random number generators
Joseph Rushton Wakeling: auto uniDist = uniformDistribution(0.0, 1.0); auto biasedDice = diceDistribution(10, 5, 7); foreach(u, d; lockstep(uniDist, biasedDice).take(10)) { writeln(u); writeln(d); } (I'm sure you can find something to improve in how I've written the second example, but you get the idea of how the distributions could behave:-) Perhaps it's better for it to only accept a range (despite this causes a memory allocation): diceDistribution([10, 5, 7]) It's usable like this: [0.3, 0.5, 0.1, 0.1].diceDistribution.map!(i = ACGT[i]).take(10).writeln; diceDistribution() is much more efficient than calling dice() many times in map. In the enhancement request I have also suggested to support an optional list of items, so the code becomes: [0.3, 0.5, 0.1, 0.1].diceDistribution(ACGT).take(10).writeln; The name diceDistribution is rather long, but at the moment I don't know of better names. diceDist is shorter, but less clear. I usually don't have a continuous distribution to sample (beside the most common ones, like the gaussian), so for me a diceDistribution is enough for now. Bye, bearophile
Re: Experimental approach to reference-type random number generators
On 02/09/13 00:54, bearophile wrote: diceDistribution() is much more efficient than calling dice() many times in map. Surely, but you should have both available in any case. I think there's a good argument that for all random number distributions, there should be a function _and_ a range implementation, so depending on your needs do either: auto dist = someDistribution(/* ... parameters ... */, rng); foreach (x; dist.take(10)) { writeln(x); } ... or: foreach(_; 0 .. 10) { auto x = some(/* ... parameters ... */, rng); writeln(x); } Of course in practice sometimes the range might just wrap the function, or the function might contain within a static instance of the range.
Re: Experimental approach to reference-type random number generators
24-Aug-2013 22:48, Joseph Rushton Wakeling пишет: On 24/08/13 20:35, Joseph Rushton Wakeling wrote: I do have one specific query Actually, two. Lines 448-457 of the second codepad paste have this unittest, with the last line commented out: // Check .save works foreach (Type; TypeTuple!(MinstdRand0, MinstdRand)) { auto rnd1 = Type(unpredictableSeed); auto rnd2 = rnd1.save; //assert(rnd1 == rnd2); // Enable next test when RNGs are reference types version(none) { assert(rnd1 !is rnd2); } //assert(rnd1.take(100).array() == rnd2.take(100).array()); } If the last assert is uncommented, assert(rnd1.take(100).array() == rnd2.take(100).array()); ... then running the unittests results in the following error: /opt/dmd/include/d2/std/array.d(37): Error: variable std.array.array!(Take!(RandomGenerator!(LinearCongruentialEngine!(uint, 16807, 0, 2147483647.array.r has scoped destruction, cannot build closure Now I'm in the same boat in the midst of wrok of applying new std.uni facilities to std.regex. As soon as std.array.array started using trusted lambda internally it doesn't accept any range with destructor. This is simply not acceptable, I'll put a minimized test-case in Bugzilla if nobody beats me to it. This is rather worrying and I'm concerned that this could be a fundamental flaw in the whole design. Can anyone advise on how to fix it? It seems a fundamental bug in closures. They have to work somehow with these structs esp as in this case there need not to allocate GC closure (no references escapes scope of std.array.array). -- Dmitry Olshansky
Re: Experimental approach to reference-type random number generators
On 30/08/13 15:32, Dmitry Olshansky wrote: This is simply not acceptable, I'll put a minimized test-case in Bugzilla if nobody beats me to it. Please do, I think you will state the case better than me :-) It seems a fundamental bug in closures. They have to work somehow with these structs esp as in this case there need not to allocate GC closure (no references escapes scope of std.array.array). Oddly enough that's a relief, because it means that the approach I've outlined to RNGs probably isn't fundamentally flawed.
Re: Experimental approach to reference-type random number generators
On Friday, 30 August 2013 at 13:32:31 UTC, Dmitry Olshansky wrote: Now I'm in the same boat in the midst of wrok of applying new std.uni facilities to std.regex. As soon as std.array.array started using trusted lambda internally it doesn't accept any range with destructor. Is the bug specific to trusted lambdas? I mean, would simply using a named function work around the problem? If so, then we should simply patch array immediately, while waiting for a lambda improvement. Having a broken std.array.array is problematic for everyone...
Re: Experimental approach to reference-type random number generators
30-Aug-2013 17:38, Joseph Rushton Wakeling пишет: On 30/08/13 15:32, Dmitry Olshansky wrote: This is simply not acceptable, I'll put a minimized test-case in Bugzilla if nobody beats me to it. Please do, I think you will state the case better than me :-) Not very colorful but with minimal test-case ... http://d.puremagic.com/issues/show_bug.cgi?id=10928 -- Dmitry Olshansky
Re: Experimental approach to reference-type random number generators
On Friday, 30 August 2013 at 15:18:09 UTC, Dmitry Olshansky wrote: 30-Aug-2013 17:38, Joseph Rushton Wakeling пишет: On 30/08/13 15:32, Dmitry Olshansky wrote: This is simply not acceptable, I'll put a minimized test-case in Bugzilla if nobody beats me to it. Please do, I think you will state the case better than me :-) Not very colorful but with minimal test-case ... http://d.puremagic.com/issues/show_bug.cgi?id=10928 I took a look at your bug report. This works: // struct D { int x; ~this() { } } void foo(D bar) { void do_it(){ bar.x++; } do_it(); } void main() { foo(D.init); } // So while lambdas remain broken we can easily work around the problem in std.array.array. If you'd care to file a pull request, I can review it double quick.
Re: Experimental approach to reference-type random number generators
30-Aug-2013 19:31, monarch_dodra пишет: On Friday, 30 August 2013 at 15:18:09 UTC, Dmitry Olshansky wrote: 30-Aug-2013 17:38, Joseph Rushton Wakeling пишет: On 30/08/13 15:32, Dmitry Olshansky wrote: This is simply not acceptable, I'll put a minimized test-case in Bugzilla if nobody beats me to it. Please do, I think you will state the case better than me :-) Not very colorful but with minimal test-case ... http://d.puremagic.com/issues/show_bug.cgi?id=10928 I took a look at your bug report. This works: // struct D { int x; ~this() { } } void foo(D bar) { void do_it(){ bar.x++; } do_it(); } void main() { foo(D.init); } // So while lambdas remain broken we can easily work around the problem in std.array.array. If you'd care to file a pull request, I can review it double quick. Got it: https://github.com/D-Programming-Language/phobos/pull/1535 -- Dmitry Olshansky
Re: Experimental approach to reference-type random number generators
On 24/08/13 20:35, Joseph Rushton Wakeling wrote: Apart from that, {enj, destr}oy. Does this look like a valid route to a next-gen std.random? :-) I should offer a vote of thanks to monarch_dodra, who referred me to ByLine as an example of a reference range (from where I got the idea to use RefCounted), and to John Colvin and Artur Skawina who pointed me at some useful info on wrapping arbitrary structs.
Re: Experimental approach to reference-type random number generators
On 24/08/13 20:35, Joseph Rushton Wakeling wrote: I do have one specific query Actually, two. Lines 448-457 of the second codepad paste have this unittest, with the last line commented out: // Check .save works foreach (Type; TypeTuple!(MinstdRand0, MinstdRand)) { auto rnd1 = Type(unpredictableSeed); auto rnd2 = rnd1.save; //assert(rnd1 == rnd2); // Enable next test when RNGs are reference types version(none) { assert(rnd1 !is rnd2); } //assert(rnd1.take(100).array() == rnd2.take(100).array()); } If the last assert is uncommented, assert(rnd1.take(100).array() == rnd2.take(100).array()); ... then running the unittests results in the following error: /opt/dmd/include/d2/std/array.d(37): Error: variable std.array.array!(Take!(RandomGenerator!(LinearCongruentialEngine!(uint, 16807, 0, 2147483647.array.r has scoped destruction, cannot build closure This is rather worrying and I'm concerned that this could be a fundamental flaw in the whole design. Can anyone advise on how to fix it?
Re: Experimental approach to reference-type random number generators
Joseph Rushton Wakeling: Today I spent some time playing around with an attempt at a wrapper for random number generation. The idea is that random number generators should exist as reference types, but without needing to be implemented as classes. I think I'd like std.random2.Random to be a final class. Bye, bearophile
Re: Experimental approach to reference-type random number generators
On Saturday, 24 August 2013 at 19:42:18 UTC, bearophile wrote: I think I'd like std.random2.Random to be a final class. That was also an approach I considered. It's easy -- even trivial -- to do. But since Phobos has such a strong struct-oriented approach, I thought I'd try something that could make that work. One of the benefits of that approach is that it should be possible to drop std.random2 into 99% of code and have it Just Work, without downstreams having to change a line of their own code.