/
random.jl
127 lines (111 loc) · 2.92 KB
/
random.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
using Random, Parameters
"""Generate random decision diagram with `n_C` chance nodes, `n_D` decision nodes, and `n_V` value nodes.
Parameter `n_I` is the upper bound on the size of the information set.
# Examples
```julia
rng = MersenneTwister(3)
random_diagram(rng, 5, 2, 3, 2)
```
"""
function random_diagram(rng::AbstractRNG, n_C::Int, n_D::Int, n_V::Int, n_I::Int)
C = Vector{ChanceNode}()
D = Vector{DecisionNode}()
V = Vector{ValueNode}()
# Create nodes
n = n_C + n_D
u = shuffle(rng, 1:n)
C_j = sort(u[1:n_C])
D_j = sort(u[n_C+1:end])
V_j = collect((n+1):(n+n_V))
for j in C_j
if j == 1
I_j = Vector{Node}()
else
m = rand(rng, 0:n_I)
I_j = unique(rand(rng, 1:(j-1), m))
end
push!(C, ChanceNode(j, I_j))
end
for j in D_j
if j == 1
I_j = Vector{Node}()
else
m = rand(rng, 0:n_I)
I_j = unique(rand(rng, 1:(j-1), m))
end
push!(D, DecisionNode(j, I_j))
end
# TODO: require node n to be in one of the I_j
for j in V_j
I_j = unique(rand(rng, 1:n, n_I))
push!(V, ValueNode(j, I_j))
end
return C, D, V
end
"""Generate `n` random states from `states`.
# Examples
```julia
rng = MersenneTwister(3)
S = States(rng, [2, 3], 10)
```
"""
function States(rng::AbstractRNG, states::Vector{State}, n::Int)
States(rand(rng, states, n))
end
"""Generate random probabilities for chance node `c` with `S` states.
# Examples
```julia
rng = MersenneTwister(3)
c = ChanceNode(2, [1])
S = States([2, 2])
Probabilities(rng, c, S)
```
"""
function Probabilities(rng::AbstractRNG, c::ChanceNode, S::States)
states = S[c.I_j]
state = S[c.j]
X = zeros(states..., state)
for s in paths(states)
x = rand(rng, state)
x = x / sum(x)
for s_j in 1:state
X[s..., s_j] = x[s_j]
end
end
Probabilities(X)
end
scale(x::Float64, low::Float64, high::Float64) = x * (high - low) + low
"""Generate random consequences between `low` and `high` for value node `v` with `S` states.
# Examples
```julia
rng = MersenneTwister(3)
v = ValueNode(3, [1])
S = States([2, 2])
Consequences(rng, v, S; low=-1.0, high=1.0)
```
"""
function Consequences(rng::AbstractRNG, v::ValueNode, S::States; low::Float64=-1.0, high::Float64=1.0)
high > low || error("")
Y = rand(rng, S[v.I_j]...)
Y = scale.(Y, low, high)
Consequences(Y)
end
"""Generate random decision strategy for decision node `d` with `S` states.
# Examples
```julia
rng = MersenneTwister(3)
d = DecisionNode(2, [1])
S = States([2, 2])
DecisionStrategy(rng, d, S)
```
"""
function LocalDecisionStrategy(rng::AbstractRNG, d::DecisionNode, S::States)
states = S[d.I_j]
state = S[d.j]
Z = zeros(Int, [states; state]...)
for s in paths(states)
s_j = rand(rng, 1:state)
Z[s..., s_j] = 1
end
LocalDecisionStrategy(Z)
end