Skip to content

Commit b4b341e

Browse files
committed
Init code
1 parent cc4accb commit b4b341e

34 files changed

+1718
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"
2+
I am a baseline to define the structure and dependencies of the MathRandomNumbers project.
3+
"
4+
Class {
5+
#name : #BaselineOfMathRandomNumbers,
6+
#superclass : #BaselineOf,
7+
#category : #BaselineOfMathRandomNumbers
8+
}
9+
10+
{ #category : #baseline }
11+
BaselineOfMathRandomNumbers >> baseline: spec [
12+
<baseline>
13+
spec
14+
for: #common
15+
do: [
16+
17+
"Packages"
18+
spec
19+
package: 'Math-RandomNumbers';
20+
package: 'Math-Tests-RandomNumbers' with: [ spec requires: #('Math-RandomNumbers') ].
21+
22+
"Groups"
23+
spec
24+
group: 'Core' with: #('Math-RandomNumbers');
25+
group: 'Tests' with: #('Math-Tests-RandomNumbers') ]
26+
]
27+
28+
{ #category : #accessing }
29+
BaselineOfMathRandomNumbers >> projectClass [
30+
^ MetacelloCypressBaselineProject
31+
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Package { #name : #BaselineOfMathRandomNumbers }
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"
2+
A PMBernoulliGenerator is simulates a Bernoulli Process. This is a discrete process, with probability of p for success, and 1-p for failure.
3+
4+
next
5+
answer 1 if success event, 0 otherwise
6+
7+
generator:
8+
provide a uniform [0,1] random number generator
9+
10+
p:
11+
set the probability of success events
12+
13+
class methods
14+
15+
withProbability:
16+
create a generator with probability set to p
17+
18+
defaultGeneratorClass
19+
class used for generator in new instances
20+
"
21+
Class {
22+
#name : #PMBernoulliGenerator,
23+
#superclass : #PMNumberGenerator,
24+
#instVars : [
25+
'probability'
26+
],
27+
#category : #'Math-RandomNumbers'
28+
}
29+
30+
{ #category : #'instance creation' }
31+
PMBernoulliGenerator class >> fair [
32+
^ self withProbability: 0.5
33+
]
34+
35+
{ #category : #private }
36+
PMBernoulliGenerator class >> validProbability: aProbability [
37+
"reject probabilities outside of [0,1]"
38+
39+
self assert: [ (aProbability < 0) not and: (aProbability > 1) not ]
40+
]
41+
42+
{ #category : #'instance creation' }
43+
PMBernoulliGenerator class >> withProbability: p [
44+
self validProbability: p.
45+
^ self new probability: p
46+
]
47+
48+
{ #category : #initialization }
49+
PMBernoulliGenerator >> initialize [
50+
super initialize.
51+
self generator: self class defaultGeneratorClass new.
52+
self probability: 0.5
53+
]
54+
55+
{ #category : #'stream accessing' }
56+
PMBernoulliGenerator >> next [
57+
^ randomNumberGenerator next < probability
58+
ifTrue: [ 1 ]
59+
ifFalse: [ 0 ]
60+
]
61+
62+
{ #category : #accessing }
63+
PMBernoulliGenerator >> probability [
64+
^ probability
65+
]
66+
67+
{ #category : #accessing }
68+
PMBernoulliGenerator >> probability: aProbability [
69+
self class validProbability: aProbability.
70+
probability := aProbability
71+
]
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"
2+
A PMBinomialGenerator yields results from a binomial distribution with probability p and n trials. The generator is the underlying random source.
3+
4+
If each independent event has probability 0<p<1, and n trials are performed, next returns number of successes.
5+
"
6+
Class {
7+
#name : #PMBinomialGenerator,
8+
#superclass : #PMNumberGenerator,
9+
#instVars : [
10+
'numberOfTrials',
11+
'probability'
12+
],
13+
#category : #'Math-RandomNumbers'
14+
}
15+
16+
{ #category : #'instance-creation' }
17+
PMBinomialGenerator class >> numberOfTrials: numberOfTrials probabilityOfSuccess: probabilityOfSuccess [
18+
^ self new
19+
numberOfTrials: numberOfTrials;
20+
probability: probabilityOfSuccess;
21+
yourself
22+
]
23+
24+
{ #category : #accessing }
25+
PMBinomialGenerator >> expectedValue [
26+
^ numberOfTrials * probability
27+
]
28+
29+
{ #category : #initialization }
30+
PMBinomialGenerator >> initialize [
31+
self generator: PMParkMillerMinimumRandomGenerator new.
32+
self numberOfTrials: 10; probability: 0.5
33+
]
34+
35+
{ #category : #'stream access' }
36+
PMBinomialGenerator >> next [
37+
| x |
38+
x := 0.
39+
numberOfTrials timesRepeat: [ randomNumberGenerator next <= probability ifTrue: [ x := x + 1 ] ].
40+
^ x
41+
]
42+
43+
{ #category : #accessing }
44+
PMBinomialGenerator >> numberOfTrials: anInteger [
45+
numberOfTrials := anInteger
46+
]
47+
48+
{ #category : #accessing }
49+
PMBinomialGenerator >> probability: aProbability [
50+
probability := aProbability
51+
]
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"
2+
This Combined Random Number Generator is based on the algorithm described by PIERRE L'ECUYER in ""Efficient and Portable Combined Random Number Generators"" [Communications of the ACM, June 19, Volume 31, Number 6, pp. 742-749, references p.774]. Taking into account its two-dimensional behaviour (from abovementioned article), this generator is suitable to produce the pairs of consecutive numbers.
3+
For the first linear congruential generator (generator A):
4+
m = 2147483563; a = 40014; q = 53668; r = 12211.
5+
For the second linear congruential generator (generator B):
6+
m = 2147483399; a = 40692; q = 52774; r = 3791.
7+
8+
To produce initial seedA (for the first generator) the method #nextInt: 2147483562 of Random is used; to produce seedB (for the second) - the method #nextInt: 2147483398. Corresponding seeds are represented as Floats. The result of work of two generators (the next seedA and seedB) are combined.
9+
10+
Developed by Konstantin Nizheradze <[email protected]>
11+
12+
Instance Variables:
13+
random <Random>
14+
seedA <Number>
15+
seedB <Number>
16+
"
17+
Class {
18+
#name : #PMCombinedRandomGenerator,
19+
#superclass : #Random,
20+
#instVars : [
21+
'random',
22+
'seedA',
23+
'seedB'
24+
],
25+
#category : #'Math-RandomNumbers'
26+
}
27+
28+
{ #category : #initialize }
29+
PMCombinedRandomGenerator >> initialize [
30+
31+
super initialize.
32+
random := Random new.
33+
seedA := (random nextInt: 2147483562) asFloat.
34+
seedB := (random nextInt: 2147483398) asFloat
35+
]
36+
37+
{ #category : #accessing }
38+
PMCombinedRandomGenerator >> next [
39+
"Combine seedA and seedB to produce new seed. Seed is in the interval [0, 1]. "
40+
41+
seed := (self nextValueA) - (self nextValueB).
42+
seed < 1 ifTrue: [seed := seed + 2.147483562e9].
43+
seed := seed * 4.656613057391769e-10.
44+
^ seed
45+
46+
47+
]
48+
49+
{ #category : #private }
50+
PMCombinedRandomGenerator >> nextValueA [
51+
"Evaluate next value of seedA using m and a of generatorA"
52+
53+
| lo hi aLoRHi |
54+
hi := (seedA quo: 53668.0) asFloat.
55+
lo := seedA - (hi * 53668.0). " = seed rem: q"
56+
aLoRHi := ( 40014.0 * lo) - ( 12211.0 * hi).
57+
seedA := (aLoRHi > 0.0)
58+
ifTrue: [aLoRHi]
59+
ifFalse: [aLoRHi + 2.147483563e9].
60+
^ seedA
61+
]
62+
63+
{ #category : #private }
64+
PMCombinedRandomGenerator >> nextValueB [
65+
"Evaluate next value of seedB using m, a, q and r of generatorB"
66+
67+
| lo hi aLoRHi |
68+
hi := (seedB quo: 52774.0) asFloat.
69+
lo := seedB - (hi * 52774.0). " = seed rem: q"
70+
aLoRHi := (40692.0 * lo) - (3791.0 * hi).
71+
seedB := (aLoRHi > 0.0)
72+
ifTrue: [aLoRHi]
73+
ifFalse: [aLoRHi + 2.147483399e9].
74+
^ seedB
75+
]
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"
2+
A PMConstantGenerator is still a number generator but a simple one :)
3+
"
4+
Class {
5+
#name : #PMConstantGenerator,
6+
#superclass : #PMNumberGenerator,
7+
#instVars : [
8+
'constant'
9+
],
10+
#category : #'Math-RandomNumbers'
11+
}
12+
13+
{ #category : #'instance-creation' }
14+
PMConstantGenerator class >> constant: aNumber [
15+
^ self new constant: aNumber ; yourself
16+
]
17+
18+
{ #category : #accessing }
19+
PMConstantGenerator >> constant: aConstant [
20+
constant := aConstant
21+
]
22+
23+
{ #category : #accessing }
24+
PMConstantGenerator >> generator: aRandomGenerator [
25+
"Do nothing."
26+
^ self
27+
]
28+
29+
{ #category : #'stream access' }
30+
PMConstantGenerator >> next [
31+
^ constant
32+
]
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
"
2+
A PMExplicitInverseCongruentialGenerator is an explicit inversive congruential generator, constructed according to ""Good random number generators are (not so) easy to find"" by P. Hellekalek (1998) and extended euclidean algorithm.
3+
Developed by Konstantin Nizheradze <[email protected]>
4+
5+
Instance Variables
6+
nextN: <Object>
7+
nextValue: <Object>
8+
p: <Object>
9+
10+
nextN
11+
- next number of the sequence of random numbers. It is also the parameter at extended euclidean algorythm
12+
13+
nextValue
14+
- next modulo inverse value, calculated by extended euclidean algorithm
15+
16+
p
17+
- parameter at extended euclidean algorithm
18+
19+
"
20+
Class {
21+
#name : #PMExplicitInverseCongruentialRandomGenerator,
22+
#superclass : #Random,
23+
#instVars : [
24+
'p',
25+
'nextN',
26+
'nextValue',
27+
'nextModInv'
28+
],
29+
#category : #'Math-RandomNumbers'
30+
}
31+
32+
{ #category : #initialization }
33+
PMExplicitInverseCongruentialRandomGenerator >> initialize [
34+
"Initialize using Random and define the modulo (p)"
35+
36+
| random |
37+
super initialize.
38+
p := 16r7FFFFFFF asFloat.
39+
random := Random new.
40+
nextN := random nextValue.
41+
42+
]
43+
44+
{ #category : #accessing }
45+
PMExplicitInverseCongruentialRandomGenerator >> next [
46+
"This method is used by nextInt:, answer a random Float in the interval [0 to 1]"
47+
48+
nextModInv := self nextRandomValue / p.
49+
^ nextModInv
50+
51+
52+
53+
]
54+
55+
{ #category : #private }
56+
PMExplicitInverseCongruentialRandomGenerator >> nextRandomValue [
57+
"Calculate the next modulo inverse value for n+1"
58+
59+
| rem newrem inv newinv transrem transinv quotient |
60+
inv := 0.
61+
newinv := 1.
62+
rem := p.
63+
newrem := nextN.
64+
[newrem ~= 0] whileTrue: [quotient := rem // newrem.
65+
transrem := newrem.
66+
newrem := rem \\ newrem.
67+
rem := transrem.
68+
transinv := newinv.
69+
newinv := inv - (quotient * newinv).
70+
inv := transinv].
71+
(inv < 0) ifTrue: [inv := inv + p].
72+
nextValue := inv.
73+
nextN := nextN + 1.
74+
^nextValue
75+
76+
]
77+
78+
{ #category : #tests }
79+
PMExplicitInverseCongruentialRandomGenerator >> testNextValue: anInteger [
80+
"This is to test the principle of modulo inverse"
81+
82+
| rem newrem inv newinv transrem transinv quotient |
83+
inv := 0.
84+
newinv := 1.
85+
rem := 240.
86+
newrem := anInteger.
87+
[newrem ~= 0] whileTrue: [quotient := rem // newrem.
88+
transrem := newrem.
89+
newrem := rem \\ newrem.
90+
rem := transrem.
91+
transinv := newinv.
92+
newinv := inv - (quotient * newinv).
93+
inv := transinv].
94+
^ inv
95+
96+
]

0 commit comments

Comments
 (0)