Pseudo Random Bit Pattern generation ideas
Beau Schwabe
Posts: 6,568
Suppose I have 9-Bits, and within the 9-Bits I want a specific number of random bits that would range from 0 to 9.
Anyone have a cleaver code idea for this?
·
Example1:
I want 5 random bits "ON" within the 9-Bits...
·
A few possible results:
%101010101
%110010101
%101100101
%011100110
·
Example2:
I want 3 random bits "ON" within the 9-Bits...
·
A few possible results:
%000010101
%110000001
%001000101
%010000110
·
·
I could·do this with brute force, but I was looking for a small compact elegant solution, I don't care if it's in Spin or Assembly and pseudo random is ok.
·
Thanks
·
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Anyone have a cleaver code idea for this?
·
Example1:
I want 5 random bits "ON" within the 9-Bits...
·
A few possible results:
%101010101
%110010101
%101100101
%011100110
·
Example2:
I want 3 random bits "ON" within the 9-Bits...
·
A few possible results:
%000010101
%110000001
%001000101
%010000110
·
·
I could·do this with brute force, but I was looking for a small compact elegant solution, I don't care if it's in Spin or Assembly and pseudo random is ok.
·
Thanks
·
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Comments
in the case of 5 one bits, start with %0 0001 1111
start at the first bit, swap with a random bit location (0 to 8) including itself.
start at the second bit, swap with a random bit.
etc.
not elegant but it would do the job.
Are you trying to do something related to dithering? Where error could be accumulated over more than one 9-bit chunk?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
Interesting... I hadn't thought of it from that end.. starting from the number of bits I wanted "ON' ... I might try that and see which one is faster... I imagine your method would be, because there is no chance of turning on a bit that is already lit up.
Here is my brute force method...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Result = %000000000
Bitcounter = 0
Repeat
..N := (<random number> // 9)
..If Nth bit of Result not yet set
....Set Nth bit
....Bitcounter := Bitcounter + 1
....If Bitcounter == <desired number>
......quit
Rats, it threw away·my indents.· Putting them back with periods.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
Post Edited (Carl Hayes) : 2/21/2009 9:59:27 PM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
you might as well go %1 1111 1110 and then just shuffle that single zero.
so for zero and nine bits set, the answer is known already.
for 1 to 4 bits set, at most 4 shuffles of 1's are needed.
for 5 to 8 bits set, at most 4 shuffles of 0's are needed.
%000000001
%000000011
%000000111
%000001111
%111110000
%111111000
%111111100
%111111110
The reason I suggest it this way is that the time of completion is known. If you wanted consistent time completion, then 9 swaps would take place regardless of the distribution of 1's to 0's.
Here's a program that uses the Fisher-Yates shuffle to randomly permute the n least-significant bits of any long. It will do what you want.
-Phil
Thanks, I will try tried that out
Edit
Perfect!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 2/21/2009 11:26:38 PM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
I don't know if this helps but the center row of bits on Stephen Wolfram's 1-dimensional binary cellular automaton when computing rule 30 is random and ideally fully non-deterministic. The Wolfram CA is based on John von Neumann 29 state and E.F. Codd's 8 state CA's. You would be limited by the size of the array required for simulation and/or if it was toroidal.
Computing the next state of the cell is like moving a 74HC151/251 8-1 line multiplexer across the bit array where - 3 cells at a time form the address on a lookup of the transition rule (30 = 0000:1110)
see
http://mathworld.wolfram.com/Rule30.html
thank you
/michael
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
After subtracting the loop overhead, I got the following results per call for the permute routines:
····spermute: 811 µs
····apermute: 92 µs
By reducing the number of bits in the modulo operation to 16 from 32:
····apermute: 67 µs
-Phil
What about generating a pseudo random number and table lookup?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Airspace V - international hangar flying!
www.airspace-v.com/ggadgets for tools & toys
For numbers in this size range (9, 4), that's certainly a solid approach. Now, since you brought it up, can you:
1. write a program that will generate the table?
2. do it without sifting through all 512 binaries and picking just the ones with four bits set?
-Phil
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Airspace V - international hangar flying!
www.airspace-v.com/ggadgets for tools & toys
You can replace the dynamic table init by a table constant generated by an external program like this one:
As usual, optimality depends on application. Calculating the table on the prop at start up needs some time. I haven't looked at the size. Cannot tell which version consumes more memory.
And a warning at the end: I have only statically tested the SPIN code. Be prepared for bugs.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Airspace V - international hangar flying!
www.airspace-v.com/ggadgets for tools & toys
Nicely done!
-Phil
Thanks for posting your code.... I think though since I don't really need the speed at all for my application, and since I already have it implemented in code I will use Phils' permutation method.· With the few Checks I have added in place for a 0 or 9 it only uses 20 longs of program space.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Not very deterministic, but the code isn't very long.
What it does is set less than half the bits. If your number of bits to be set is more than half the size, it sets the number of bits that should be zero and then inverts the result. This way you always have a >=50/50 chance of the random bit not having already been set.
For execution speed, the worst case scenario will be when the number of bits to be set is equal to half the total number of bits.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
·"I have always wished that my computer would be as easy to use as my telephone.· My wish has come true.· I no longer know how to use my telephone."
- Bjarne Stroustrup
Post Edited (Ken Peterson) : 2/24/2009 2:09:23 AM GMT
We could also replace the operations 'x // c' by 'x ** (2^32 ) / c' to accelerate. Well, 'x // 8' can even be done be 'x & 0x3'...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Airspace V - international hangar flying!
www.airspace-v.com/ggadgets for tools & toys
Post Edited (virtuPIC) : 2/25/2009 9:43:12 AM GMT
Maybe I think a little about the program with mixed probs and fix them. Yeah, I know. Nobody will use it anyway. But it's demanding. And it's fun.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Airspace V - international hangar flying!
www.airspace-v.com/ggadgets for tools & toys
But that brings me to my math question. The Spin operator ? is, according to the manual, an LFSR that can be used forward ?X or in reverse X? Neat! Retrace steps. But how does an LFSR do that? The manual states.
The Propeller chip’s Random output is reversible; in fact, specifically it is a 32-bit
maximum-length, four-tap LFSR (Linear Feedback Shift Register) with taps in both the LSB
(Least Significant Bit, rightmost bit) and the MSB (Most Significant Bit, leftmost bit)
allowing for bi-directional operation.
However, it is not as simple as shifting right with the same set of taps. For example, taps=$802000003 is a four tap mask with taps in both the lsb and msb, however, it does not take long to come up with a counterexample, where the left shift is not reversible with a right shift using the same taps. Short of iterating the forward map 2^32-2 times, is there a trick to make it reversible? Looking shallowly on line, it looks like there exists a complementary set of taps, that mathematically can generate the reverse sequence. But the circuit to do it is not trivial, example here. Hmmm...to echo the Joker, how does he do that?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
The key element is that the bit that gets shifted out is involved in the XOR process. That way, the XOR product that gets shifted into the other end can be used to reconstruct this bit from the other taps. In this case, the taps for the reverse case are just the same taps as for the forward case, rotated by one position in the direction of the original shift. (You don't really have to have both the MSB and LSB set in the original mask — just the one corresponding to the bit that gets shifted out.) For example, if your original mask is %11010000_00000001, and you're shifting right, the new mask for shifting left will be %11101000_00000000. This is enough to reconstruct the bit that got shifted out in the forward direction and to shift it back into the other end.
-Phil
It occurs to me now that you could just keep a set of constants, one for each bit. Just add (or not) them to build your new instance.
binary:
0_0000_0001
0_0000_0010
...
1_0000_0000
Arrange these randomly, maybe following the 4 bit lfsr's order which has nice properties.
then you need a set of eight starting instances of one set bit through 8 set bits.
To get an new instance of any of these, run a nine step loop that shifts off a bit from the old instance, and if it's set, add the nth binary to your new instance. If you keep track of the number of adds, you can even drop out of the loop when you have set the appropriate number of bits.
My guess is that it's random enough. You could reshuffle the binary array every now and then if you're worried about that.
Post Edited (Fred Hawkins) : 2/25/2009 3:09:29 AM GMT
Say for these taps for the 32 bit lfsr
$8020_0003 for shift left
with the new lsb from
x0 := x31 ^ x21 ^ x1 ^ x0
with x31 being lost after the shift, but it can be recomputed from the new x0 along with the now shifted x1, x2 and x22.
The taps for shift right would be
$0040_0007
with new msb from
x31 := x22 ^ x2 ^ x1 ^ x0
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
If you look at en.wikipedia.org/wiki/LFSR you will find two possible implementations in hardware (Fibonacci and Galois) giving different sequences. Maybe we should try to rewire them that each clock to the SR gives backward change? Or simply look it up in the code of the SPIN interpreter?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Airspace V - international hangar flying!
www.airspace-v.com/ggadgets for tools & toys
Again, the Propeller Tools swallows it, but I haven't run it so far.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Airspace V - international hangar flying!
www.airspace-v.com/ggadgets for tools & toys